Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/apache2/mDNSResponder/nss Two new features:



details:   https://anonhg.NetBSD.org/src/rev/df7d701e2284
branches:  trunk
changeset: 748768:df7d701e2284
user:      tsarna <tsarna%NetBSD.org@localhost>
date:      Wed Nov 04 23:34:59 2009 +0000

description:
Two new features:

- Detect and adapt to resolv.conf changes through the use of the new
  res_check() API, so that for example changing the search list doesn't
  require restarting clients.

- A persistent mdnsd connection pool, with slow start (so that
  programs like ping, ssh, etc don't keep connections open) and age-out.
  NOTE: Tuning parameter values are just SWAGs.

diffstat:

 external/apache2/mDNSResponder/nss/nss_mdnsd.c |  650 +++++++++++++++++++-----
 1 files changed, 496 insertions(+), 154 deletions(-)

diffs (truncated from 904 to 300 lines):

diff -r e0dedc74355b -r df7d701e2284 external/apache2/mDNSResponder/nss/nss_mdnsd.c
--- a/external/apache2/mDNSResponder/nss/nss_mdnsd.c    Wed Nov 04 22:25:56 2009 +0000
+++ b/external/apache2/mDNSResponder/nss/nss_mdnsd.c    Wed Nov 04 23:34:59 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nss_mdnsd.c,v 1.2 2009/10/26 00:46:19 tsarna Exp $     */
+/*     $NetBSD: nss_mdnsd.c,v 1.3 2009/11/04 23:34:59 tsarna Exp $     */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -45,6 +45,7 @@
 #include <stdlib.h>  
 #include <sys/socket.h>
 #include <sys/param.h>
+#include <sys/queue.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
@@ -54,6 +55,51 @@
 #include <string.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <time.h>
+
+
+/*
+ * Pool of mdnsd connections
+ */
+static SLIST_HEAD(, svc_ref) conn_list = LIST_HEAD_INITIALIZER(&conn_list);
+static unsigned int conn_count = 0;
+static pid_t my_pid;
+struct timespec last_config;
+
+typedef struct svc_ref {
+    SLIST_ENTRY(svc_ref)    entries;
+    DNSServiceRef           sdRef;
+    unsigned int            uses;
+} svc_ref;
+
+/*
+ * There is a large class of programs that do a few lookups at startup
+ * and then never again (ping, telnet, etc). Keeping a persistent connection
+ * for these would be a waste, so there is a kind of slow start mechanism.
+ * The first SLOWSTART_LOOKUPS times, dispose of the connection after use.
+ * After that we assume the program is a serious consumer of host lookup
+ * services and start keeping connections.
+ */
+#define SLOWSTART_LOOKUPS 5
+static unsigned int svc_puts = 0;
+
+/*
+ * Age out connections. Free connection instead of putting on the list
+ * if used more than REUSE_TIMES and there are others on the list.
+ */
+#define REUSE_TIMES          32
+ 
+/* protects above data */
+static pthread_mutex_t conn_list_lock = PTHREAD_MUTEX_INITIALIZER;
+
+extern int __isthreaded; /* libc private -- wish there was a better way */
+
+#define LOCK(x) do { if (__isthreaded) pthread_mutex_lock(x); } while (0)
+#define UNLOCK(x) do { if (__isthreaded) pthread_mutex_unlock(x); } while (0)
+
 
 #ifndef lint
 #define UNUSED(a)       (void)&a
@@ -85,9 +131,23 @@
 
 #define HCTX_BUFLEFT(c) (sizeof((c)->buf) - ((c)->next - (c)->buf))
 
+typedef struct res_conf {
+    unsigned int            refcount;
+    char                  **search_domains;
+    char                  **no_search;
+    short                   ndots;
+    short                   timeout;
+} res_conf;
+
+static res_conf *cur_res_conf;
+
+/* protects above data */
+static pthread_mutex_t res_conf_lock = PTHREAD_MUTEX_INITIALIZER;
+
 typedef struct search_iter {
+    res_conf       *conf;
     const char     *name;
-    char           **next_search;
+    char          **next_search;    
     size_t          baselen;
     bool            abs_first;
     bool            abs_last;
@@ -96,8 +156,6 @@
 
 static hostent_ctx h_ctx;
 static DNSServiceFlags svc_flags = 0;
-static int ndots = 1, timeout = 1000;
-static char **search_domains, **no_search;
 
 ns_mtab *nss_module_register(const char *, u_int *, nss_module_unregister_fn *);
 static int load_config(res_state);
@@ -107,12 +165,12 @@
 static int _mdns_gethtbyname(void *, void *, va_list);
 
 static int _mdns_getaddrinfo_abs(const char *, DNSServiceProtocol,
-    DNSServiceRef, addrinfo_ctx *);
+    svc_ref **, addrinfo_ctx *, short);
 static void _mdns_addrinfo_init(addrinfo_ctx *, const struct addrinfo *);
 static void _mdns_addrinfo_add_ai(addrinfo_ctx *, struct addrinfo *);
 static struct addrinfo *_mdns_addrinfo_done(addrinfo_ctx *);
 
-static int _mdns_gethtbyname_abs(const char *, int, DNSServiceRef);
+static int _mdns_gethtbyname_abs(const char *, int, svc_ref **, short);
 static void _mdns_hostent_init(hostent_ctx *, int, int);
 static void _mdns_hostent_add_host(hostent_ctx *, const char *);
 static void _mdns_hostent_add_addr(hostent_ctx *, const void *, uint16_t);
@@ -124,16 +182,26 @@
 static void _mdns_hostent_cb(DNSServiceRef, DNSServiceFlags,
     uint32_t, DNSServiceErrorType, const char *, uint16_t, uint16_t, uint16_t,
     const void *, uint32_t, void *);
-static void _mdns_eventloop(DNSServiceRef, callback_ctx *);
+static void _mdns_eventloop(svc_ref *, callback_ctx *, short);
 
 static char *_mdns_rdata2name(const unsigned char *, uint16_t,
     char *, size_t);
 
-void search_init(search_iter *, const char *);
-const char *search_next(search_iter *);
-bool searchable_domain(char *);
+static int search_init(search_iter *, const char *, const char **);
+static void search_done(search_iter *);
+static const char *search_next(search_iter *);
+static bool searchable_domain(char *);
 
+static void destroy_svc_ref(svc_ref *);
+static svc_ref *get_svc_ref(void);
+static void put_svc_ref(svc_ref *);
+static bool retry_query(svc_ref **, DNSServiceErrorType);
 
+static void decref_res_conf(res_conf *);
+static res_conf *get_res_conf(void);
+static void put_res_conf(res_conf *);
+static res_conf *new_res_conf(res_state);
+static short get_timeout(void);
 
 static ns_mtab mtab[] = {
     { NSDB_HOSTS, "getaddrinfo",    _mdns_getaddrinfo, NULL },
@@ -147,92 +215,32 @@
 nss_module_register(const char *source, u_int *nelems,
                     nss_module_unregister_fn *unreg)
 {
-    res_state res;
-
     *nelems = sizeof(mtab) / sizeof(mtab[0]);
     *unreg = NULL;
 
+    my_pid = getpid();
+
     if (!strcmp(source, "multicast_dns")) {
         svc_flags = kDNSServiceFlagsForceMulticast;
     }
 
-    res = __res_get_state();
-    if (res) {
-        load_config(res);
-        __res_put_state(res);
-    }
-
     return mtab;
 }
 
 
 
 static int
-load_config(res_state res)
-{
-    int count = 0;
-    char **sd;
-    
-    /* free old search list, if any */
-
-    if ((no_search = search_domains)) {
-        for (; *no_search; no_search++) {
-            free(*no_search);
-        }
-        
-        free(search_domains);
-    }
-
-    /* new search list */
-    
-    sd = res->dnsrch;
-    while (*sd) {
-        if (searchable_domain(*sd)) {
-            count++;
-        }
-        sd++;
-    }
-    
-    search_domains = calloc(sizeof(char *), count + 1);
-    if (!search_domains) {
-        return -1;
-    }
-    
-    sd = res->dnsrch;
-    no_search = search_domains;
-    while (*sd) {
-        if (searchable_domain(*sd)) {
-            *no_search = strdup(*sd);
-            no_search++;
-        }
-        sd++;
-    }
-
-    /* retrans in sec to timeout in msec */
-    timeout = res->retrans * 1000;
-
-    if (svc_flags & kDNSServiceFlagsForceMulticast) {
-        ndots = 1;
-        if (timeout > 2000) {
-            timeout = 2000;
-        }
-    } else {
-        ndots = res->ndots;
-    }
-}
-
-
-
-static int
 _mdns_getaddrinfo(void *cbrv, void *cbdata, va_list ap)
 {
     const struct addrinfo *pai;
     const char *name, *sname;
     DNSServiceProtocol proto;
-    int err = NS_UNAVAIL;
     DNSServiceRef sdRef;
     addrinfo_ctx ctx;
     search_iter iter;
+    res_conf *rc;
+    svc_ref *sr;
+    int err;
     
     UNUSED(cbdata);
     
@@ -257,30 +265,29 @@
         return NS_UNAVAIL;
     }
 
-    search_init(&iter, name);
-    sname = search_next(&iter);
-
-    if (!sname) {
-        h_errno = HOST_NOT_FOUND;
-        return NS_NOTFOUND;
-    }
-
-    /* use one connection for all searches */
-    if (DNSServiceCreateConnection(&sdRef)) {
+    sr = get_svc_ref();
+    if (!sr) {
         h_errno = NETDB_INTERNAL;
         return NS_UNAVAIL;
     }
     
+    if ((err = search_init(&iter, name, &sname)) != NS_SUCCESS) {
+        put_svc_ref(sr);
+        return err;
+    }
+    
     _mdns_addrinfo_init(&ctx, pai);
-
-    while (sname && (err != NS_SUCCESS)) {
-        err = _mdns_getaddrinfo_abs(sname, proto, sdRef, &ctx);
+    
+    err = NS_NOTFOUND;
+    while (sr && sname && (err != NS_SUCCESS)) {
+        err = _mdns_getaddrinfo_abs(sname, proto, &sr, &ctx, iter.conf->timeout);
         if (err != NS_SUCCESS) {
             sname = search_next(&iter);
         }
     };
 
-    DNSServiceRefDeallocate(sdRef);
+    search_done(&iter);
+    put_svc_ref(sr);
 
     if (err == NS_SUCCESS) {
         *(struct addrinfo **)cbrv = _mdns_addrinfo_done(&ctx);
@@ -293,25 +300,39 @@
 
 static int
 _mdns_getaddrinfo_abs(const char *name, DNSServiceProtocol proto,
-    DNSServiceRef sdRef, addrinfo_ctx *ctx)
+    svc_ref **sr, addrinfo_ctx *ctx, short timeout)
 {
-    DNSServiceErrorType err;
+    DNSServiceErrorType err = kDNSServiceErr_ServiceNotRunning;



Home | Main Index | Thread Index | Old Index