Module Name: src Committed By: jdc Date: Sun Jun 3 21:41:35 UTC 2012
Modified Files: src/include [netbsd-6]: netdb.h src/lib/libc/net [netbsd-6]: getaddrinfo.c Log Message: Pull up revisions: src/lib/libc/net/getaddrinfo.c revision 1.98 - 1.100 src/include/netdb.h revision 1.65 (requested by khorben in ticket #278). Add AI_ADDRCONFIG, which makes getaddrinfo() return only address with families that are already configured in the system. PR 46206: fix programmed SIGSEGV more work is needed as tests seem to indicate that name resolution now does no seem to work (firefox reports Server not found) thanks to Ryo ONODERA for testing. PR pkg/46206 re-establish fqdn lookup when AI_ADDRCONFIG is used in hints AI_ADDRCONFIG led to fqdn lookup being skipped as the systems didn't configure any PF_UNSPEC addresses - check was too strict here. Thnaks to Ryo ONODERA for testing. To generate a diff of this commit: cvs rdiff -u -r1.64 -r1.64.8.1 src/include/netdb.h cvs rdiff -u -r1.96 -r1.96.4.1 src/lib/libc/net/getaddrinfo.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/include/netdb.h diff -u src/include/netdb.h:1.64 src/include/netdb.h:1.64.8.1 --- src/include/netdb.h:1.64 Wed May 5 17:12:29 2010 +++ src/include/netdb.h Sun Jun 3 21:41:34 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: netdb.h,v 1.64 2010/05/05 17:12:29 christos Exp $ */ +/* $NetBSD: netdb.h,v 1.64.8.1 2012/06/03 21:41:34 jdc Exp $ */ /* * ++Copyright++ 1980, 1983, 1988, 1993 @@ -269,7 +269,9 @@ struct addrinfo { #define AI_NUMERICSERV 0x00000008 /* prevent service name resolution */ /* valid flags for addrinfo (not a standard def, apps should not use it) */ #define AI_MASK \ - (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV) + (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \ + AI_ADDRCONFIG) +#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */ #endif #if (_POSIX_C_SOURCE - 0) >= 200112L || (_XOPEN_SOURCE - 0) >= 520 || \ Index: src/lib/libc/net/getaddrinfo.c diff -u src/lib/libc/net/getaddrinfo.c:1.96 src/lib/libc/net/getaddrinfo.c:1.96.4.1 --- src/lib/libc/net/getaddrinfo.c:1.96 Sat Oct 15 23:00:02 2011 +++ src/lib/libc/net/getaddrinfo.c Sun Jun 3 21:41:34 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: getaddrinfo.c,v 1.96 2011/10/15 23:00:02 christos Exp $ */ +/* $NetBSD: getaddrinfo.c,v 1.96.4.1 2012/06/03 21:41:34 jdc Exp $ */ /* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ /* @@ -55,7 +55,7 @@ #include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: getaddrinfo.c,v 1.96 2011/10/15 23:00:02 christos Exp $"); +__RCSID("$NetBSD: getaddrinfo.c,v 1.96.4.1 2012/06/03 21:41:34 jdc Exp $"); #endif /* LIBC_SCCS and not lint */ #include "namespace.h" @@ -76,6 +76,7 @@ __RCSID("$NetBSD: getaddrinfo.c,v 1.96 2 #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <ifaddrs.h> #include <syslog.h> #include <stdarg.h> @@ -208,6 +209,7 @@ static int get_portmatch(const struct ad static int get_port(const struct addrinfo *, const char *, int, struct servent_data *); static const struct afd *find_afd(int); +static int addrconfig(uint64_t *); #ifdef INET6 static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); #endif @@ -348,6 +350,7 @@ getaddrinfo(const char *hostname, const struct addrinfo *pai; const struct explore *ex; struct servent_data svd; + uint64_t mask = (uint64_t)~0ULL; /* hostname is allowed to be NULL */ /* servname is allowed to be NULL */ @@ -409,6 +412,9 @@ getaddrinfo(const char *hostname, const } } + if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && addrconfig(&mask) == -1) + ERR(EAI_FAIL); + /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed @@ -441,6 +447,10 @@ getaddrinfo(const char *hostname, const for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; + /* ADDRCONFIG check */ + if ((((uint64_t)1 << ex->e_af) & mask) == 0) + continue; + /* PF_UNSPEC entries are prepared for DNS queries only */ if (ex->e_af == PF_UNSPEC) continue; @@ -451,7 +461,6 @@ getaddrinfo(const char *hostname, const continue; if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) continue; - if (pai->ai_family == PF_UNSPEC) pai->ai_family = ex->e_af; if (pai->ai_socktype == ANY && ex->e_socktype != ANY) @@ -494,6 +503,13 @@ getaddrinfo(const char *hostname, const for (ex = explore; ex->e_af >= 0; ex++) { *pai = ai0; + + /* ADDRCONFIG check */ + /* PF_UNSPEC entries are prepared for DNS queries only */ + if (ex->e_af != PF_UNSPEC && + (((uint64_t)1 << ex->e_af) & mask) == 0) + continue; + /* require exact match for family field */ if (pai->ai_family != ex->e_af) continue; @@ -1006,6 +1022,30 @@ find_afd(int af) return NULL; } +/* + * AI_ADDRCONFIG check: Build a mask containing a bit set for each address + * family configured in the system. + * + */ +static int +addrconfig(uint64_t *mask) +{ + struct ifaddrs *ifaddrs, *ifa; + + if (getifaddrs(&ifaddrs) == -1) + return -1; + + *mask = 0; + for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) + if (ifa->ifa_addr && (ifa->ifa_flags & IFF_UP)) { + _DIAGASSERT(ifa->ifa_addr->sa_family < 64); + *mask |= (uint64_t)1 << ifa->ifa_addr->sa_family; + } + + freeifaddrs(ifaddrs); + return 0; +} + #ifdef INET6 /* convert a string to a scope identifier. XXX: IPv6 specific */ static int