Module Name: src Committed By: tsarna Date: Mon Oct 26 00:46:19 UTC 2009
Modified Files: src/external/apache2/mDNSResponder/nss: nss_mdnsd.c Log Message: For the multicast_dns only mode, be very restrictive in what lookups we try. No point in making queries and waiting for timeouts on lookups that will never succeed. Now only does lookups for linklocal addresses (v4 or v6) and "name.local" names (and dotless names, iff "local" is specified in the resolv.conf search list). Also, lower the timeout in this mode, since multicast lookups should return pretty fast or not at all. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/external/apache2/mDNSResponder/nss/nss_mdnsd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/apache2/mDNSResponder/nss/nss_mdnsd.c diff -u src/external/apache2/mDNSResponder/nss/nss_mdnsd.c:1.1 src/external/apache2/mDNSResponder/nss/nss_mdnsd.c:1.2 --- src/external/apache2/mDNSResponder/nss/nss_mdnsd.c:1.1 Sun Oct 25 00:17:06 2009 +++ src/external/apache2/mDNSResponder/nss/nss_mdnsd.c Mon Oct 26 00:46:19 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: nss_mdnsd.c,v 1.1 2009/10/25 00:17:06 tsarna Exp $ */ +/* $NetBSD: nss_mdnsd.c,v 1.2 2009/10/26 00:46:19 tsarna Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -85,14 +85,9 @@ #define HCTX_BUFLEFT(c) (sizeof((c)->buf) - ((c)->next - (c)->buf)) -typedef struct search_domain { - const char *name; - bool enabled; -} search_domain; - typedef struct search_iter { const char *name; - search_domain *next_search; + char **next_search; size_t baselen; bool abs_first; bool abs_last; @@ -102,7 +97,7 @@ static hostent_ctx h_ctx; static DNSServiceFlags svc_flags = 0; static int ndots = 1, timeout = 1000; -static search_domain *search_domains, *no_search; +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); @@ -136,6 +131,7 @@ void search_init(search_iter *, const char *); const char *search_next(search_iter *); +bool searchable_domain(char *); @@ -153,8 +149,6 @@ { res_state res; - UNUSED(unreg); - *nelems = sizeof(mtab) / sizeof(mtab[0]); *unreg = NULL; @@ -179,16 +173,27 @@ int count = 0; char **sd; - ndots = res->ndots; - timeout = res->retrans * 1000; /* retrans in sec to timeout in msec */ + /* 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) { - count++; + if (searchable_domain(*sd)) { + count++; + } sd++; } - search_domains = malloc(sizeof(search_domain) * (count + 1)); + search_domains = calloc(sizeof(char *), count + 1); if (!search_domains) { return -1; } @@ -196,15 +201,24 @@ sd = res->dnsrch; no_search = search_domains; while (*sd) { - no_search->name = *sd; - no_search->enabled = - (svc_flags & kDNSServiceFlagsForceMulticast) ? true : true; - no_search++; + if (searchable_domain(*sd)) { + *no_search = strdup(*sd); + no_search++; + } sd++; } - /* terminate list */ - no_search->name = NULL; + /* 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; + } } @@ -243,6 +257,14 @@ 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)) { h_errno = NETDB_INTERNAL; @@ -250,9 +272,7 @@ } _mdns_addrinfo_init(&ctx, pai); - search_init(&iter, name); - sname = search_next(&iter); - + while (sname && (err != NS_SUCCESS)) { err = _mdns_getaddrinfo_abs(sname, proto, sdRef, &ctx); if (err != NS_SUCCESS) { @@ -279,7 +299,7 @@ err = DNSServiceGetAddrInfo( &sdRef, - svc_flags, + svc_flags | kDNSServiceFlagsReturnIntermediates, kDNSServiceInterfaceIndexAny, proto, name, @@ -291,7 +311,6 @@ h_errno = NETDB_INTERNAL; return NS_UNAVAIL; } - _mdns_eventloop(sdRef, (void *)ctx); DNSServiceRefDeallocate(sdRef); @@ -324,12 +343,28 @@ switch (af) { case AF_INET: + /* if mcast-only don't bother for non-LinkLocal addrs) */ + if (svc_flags & kDNSServiceFlagsForceMulticast) { + if ((addr[0] != 169) || (addr[1] != 254)) { + h_errno = HOST_NOT_FOUND; + return NS_NOTFOUND; + } + } + (void)snprintf(qbuf, sizeof(qbuf), "%u.%u.%u.%u.in-addr.arpa", (addr[3] & 0xff), (addr[2] & 0xff), (addr[1] & 0xff), (addr[0] & 0xff)); break; case AF_INET6: + /* if mcast-only don't bother for non-LinkLocal addrs) */ + if (svc_flags & kDNSServiceFlagsForceMulticast) { + if ((addr[0] != 0xfe) || ((addr[1] & 0xc0) != 0x80)) { + h_errno = HOST_NOT_FOUND; + return NS_NOTFOUND; + } + } + qp = qbuf; ep = qbuf + sizeof(qbuf) - 1; for (n = IN6ADDRSZ - 1; n >= 0; n--) { @@ -417,7 +452,15 @@ break; default: - h_errno = NETDB_INTERNAL; + h_errno = NO_RECOVERY; + return NS_UNAVAIL; + } + + search_init(&iter, name); + sname = search_next(&iter); + + if (!sname) { + h_errno = HOST_NOT_FOUND; return NS_NOTFOUND; } @@ -428,9 +471,7 @@ } _mdns_hostent_init(&h_ctx, af, addrlen); - search_init(&iter, name); - sname = search_next(&iter); - + while (sname && (err != NS_SUCCESS)) { err = _mdns_gethtbyname_abs(sname, rrtype, sdRef); if (err != NS_SUCCESS) { @@ -458,7 +499,7 @@ err = DNSServiceQueryRecord( &sdRef, - svc_flags, + svc_flags | kDNSServiceFlagsReturnIntermediates, kDNSServiceInterfaceIndexAny, name, rrtype, @@ -642,7 +683,6 @@ UNUSED(sdRef); UNUSED(interfaceIndex); - UNUSED(hostname); UNUSED(ttl); if (errorCode == kDNSServiceErr_NoError) { @@ -723,6 +763,8 @@ } break; } + } else if (errorCode == kDNSServiceErr_NoSuchRecord) { + ctx->cb_ctx.done = true; } } @@ -820,35 +862,52 @@ void search_init(search_iter *iter, const char *name) { - const char *c = name; - bool enddot = false; - int dots = 0; + const char *c = name, *cmp; + int dots = 0, enddot = 0; + size_t len, cl; iter->name = name; iter->baselen = 0; + iter->abs_first = iter->abs_last = false; + iter->next_search = search_domains; while (*c) { if (*c == '.') { dots++; - enddot = true; + enddot = 1; } else { - enddot = false; + enddot = 0; } c++; } - if (dots >= ndots) { - iter->abs_first = true; - iter->abs_last = false; + if (svc_flags & kDNSServiceFlagsForceMulticast) { + if (dots) { + iter->next_search = no_search; + if ((dots - enddot) == 1) { + len = strlen(iter->name); + cl = strlen(".local") + enddot; + if (len > cl) { + cmp = enddot ? ".local." : ".local"; + c = iter->name + len - cl; + + if (!strcasecmp(c, cmp)) { + iter->abs_first = true; + } + } + } + } } else { - iter->abs_first = false; - iter->abs_last = true; - } + if (dots >= ndots) { + iter->abs_first = true; + } else { + iter->abs_last = true; + } - if (enddot) { - iter->next_search = no_search; - } else { - iter->next_search = search_domains; + if (enddot) { + /* absolute; don't search */ + iter->next_search = no_search; + } } } @@ -866,34 +925,30 @@ return iter->name; } - while (iter->next_search->name) { - if (iter->next_search->enabled) { - if (!iter->baselen) { - iter->baselen = strlcpy(iter->buf, iter->name, sizeof(iter->buf)); - if (iter->baselen >= sizeof(iter->buf) - 1) { - /* original is too long, don't try any search domains */ - iter->next_search = no_search; - break; - } - - iter->buf[iter->baselen++] = '.'; - } - - len = strlcpy(&(iter->buf[iter->baselen]), - iter->next_search->name, - sizeof(iter->buf) - iter->baselen); - - iter->next_search++; - - if (len >= sizeof(iter->buf) - iter->baselen) { - /* result would be too long */ - continue; + while (*(iter->next_search)) { + if (!iter->baselen) { + iter->baselen = strlcpy(iter->buf, iter->name, sizeof(iter->buf)); + if (iter->baselen >= sizeof(iter->buf) - 1) { + /* original is too long, don't try any search domains */ + iter->next_search = no_search; + break; } - - return iter->buf; - } else { - iter->next_search++; + + iter->buf[iter->baselen++] = '.'; + } + + len = strlcpy(&(iter->buf[iter->baselen]), + *(iter->next_search), + sizeof(iter->buf) - iter->baselen); + + iter->next_search++; + + if (len >= sizeof(iter->buf) - iter->baselen) { + /* result was too long */ + continue; } + + return iter->buf; } if (iter->abs_last) { @@ -903,3 +958,24 @@ return NULL; } + + + +/* + * Is domain appropriate to be in the domain search list? + * For mdnsd, take everything. For multicast_dns, only "local" + * if present. + */ +bool +searchable_domain(char *d) +{ + if (!(svc_flags & kDNSServiceFlagsForceMulticast)) { + return true; + } + + if (!strcasecmp(d, "local") || !strcasecmp(d, "local.")) { + return true; + } + + return false; +}