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