Index: include/netdb.h =================================================================== --- include/netdb.h (revision 290743) +++ include/netdb.h (working copy) @@ -179,7 +179,7 @@ /* 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_ADDRCONFIG) + AI_ADDRCONFIG | AI_ALL | AI_V4MAPPED) #define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */ #define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */ Index: lib/libc/net/Makefile.inc =================================================================== --- lib/libc/net/Makefile.inc (revision 290743) +++ lib/libc/net/Makefile.inc (working copy) @@ -26,6 +26,10 @@ CFLAGS+=-DINET6 .endif +.if ${MK_GETADDRINFO_V4MAPPED} == "yes" +CFLAGS+=-DV4MAPPED +.endif + CFLAGS+=-I${.OBJDIR} # name6.c refers res_private.h Index: lib/libc/net/getaddrinfo.c =================================================================== --- lib/libc/net/getaddrinfo.c (revision 290743) +++ lib/libc/net/getaddrinfo.c (working copy) @@ -470,6 +470,25 @@ } /* + * RFC 3493: AI_ALL and AI_V4MAPPED are effective only against + * AF_INET6 query. They need to be ignored if specified in other + * occassions. + */ + switch (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) { + case AI_V4MAPPED: + case AI_ALL | AI_V4MAPPED: + if (pai->ai_family != AF_INET6) + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); +#ifndef V4MAPPED + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); +#endif + break; + case AI_ALL: + pai->ai_flags &= ~(AI_ALL | AI_V4MAPPED); + break; + } + + /* * check for special cases. (1) numeric servname is disallowed if * socktype/protocol are left unspecified. (2) servname is disallowed * for raw and other inet{,6} sockets. @@ -1199,7 +1218,7 @@ const char *servname, struct addrinfo **res, const char *canonname) { const struct afd *afd; - struct addrinfo *ai; + struct addrinfo *ai, ai0; int error; char pton[PTON_MAX], path[PATH_MAX], *p; @@ -1236,8 +1255,17 @@ p = pton; break; default: - if (inet_pton(afd->a_af, hostname, pton) != 1) - return 0; + if (inet_pton(afd->a_af, hostname, pton) != 1) { + if (pai->ai_family != AF_INET6 || + (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED) + return 0; + if (inet_aton(hostname, (struct in_addr *)pton) != 1) + return 0; + afd = &afdl[N_INET]; + ai0 = *pai; + ai0.ai_family = AF_INET; + pai = &ai0; + } p = pton; break; } @@ -1354,7 +1382,17 @@ { char *p; struct addrinfo *ai; + struct in6_addr mapaddr; + int map_translate = 0; + if (afd->a_af == AF_INET && (pai->ai_flags & AI_V4MAPPED) != 0) { + afd = &afdl[N_INET6]; + memset(&mapaddr.s6_addr[0], 0, 10); + memset(&mapaddr.s6_addr[10], 0xff, 2); + memcpy(&mapaddr.s6_addr[12], addr, sizeof(struct in_addr)); + map_translate = 1; + } + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); if (ai == NULL) @@ -1373,7 +1411,10 @@ } ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(void *)(ai->ai_addr); - memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + if (map_translate == 1) + memcpy(p + afd->a_off, &mapaddr, (size_t)afd->a_addrlen); + else + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); return ai; } @@ -2192,7 +2233,7 @@ static int _dns_getaddrinfo(void *rv, void *cb_data, va_list ap) { - struct addrinfo *ai; + struct addrinfo *ai, ai0; querybuf *buf, *buf2; const char *hostname; const struct addrinfo *pai; @@ -2220,6 +2261,13 @@ return NS_NOTFOUND; } + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) { + ai0 = *pai; + ai0.ai_family = AF_UNSPEC; + pai = &ai0; + } + switch (pai->ai_family) { case AF_UNSPEC: q.name = hostname; @@ -2276,9 +2324,12 @@ cur = cur->ai_next; } } - ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); - if (ai) - cur->ai_next = ai; + if (!ai || pai->ai_family != AF_UNSPEC || + (pai->ai_flags & (AI_ALL | AI_V4MAPPED)) != AI_V4MAPPED) { + ai = getanswer(buf, q.n, q.name, q.qtype, pai, res); + if (ai) + cur->ai_next = ai; + } free(buf); free(buf2); if (sentinel.ai_next == NULL) @@ -2361,8 +2412,19 @@ hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(addr, "0", &hints, &res0); - if (error) - goto again; + if (error) { + /* + * XXX: Both IPv6 address and IPv4-mapped IPv6 address + * are returned without specifying AI_ALL. + */ + if (pai->ai_family != AF_INET6 || + (pai->ai_flags & AI_V4MAPPED) != AI_V4MAPPED) + goto again; + hints.ai_flags |= AI_V4MAPPED; + error = getaddrinfo(addr, "0", &hints, &res0); + if (error) + goto again; + } #ifdef FILTER_V4MAPPED /* XXX should check all items in the chain */ if (res0->ai_family == AF_INET6 && @@ -2469,6 +2531,13 @@ hints = *pai; hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(addr, NULL, &hints, &res0); + if (error) { + if (pai->ai_family == AF_INET6 && + (pai->ai_flags & AI_V4MAPPED) == AI_V4MAPPED) { + hints.ai_flags |= AI_V4MAPPED; + error = getaddrinfo(addr, NULL, &hints, &res0); + } + } if (error == 0) { for (res = res0; res; res = res->ai_next) { /* cover it up */ Index: share/mk/bsd.opts.mk =================================================================== --- share/mk/bsd.opts.mk (revision 290743) +++ share/mk/bsd.opts.mk (working copy) @@ -70,6 +70,7 @@ FAST_DEPEND \ CTF \ DEBUG_FILES \ + GETADDRINFO_V4MAPPED \ INSTALL_AS_USER \ STALE_STAGED Index: tools/build/options/WITH_GETADDRINFO_V4MAPPED =================================================================== --- tools/build/options/WITH_GETADDRINFO_V4MAPPED (nonexistent) +++ tools/build/options/WITH_GETADDRINFO_V4MAPPED (working copy) @@ -0,0 +1,14 @@ +.\" $FreeBSD$ +Set to enable the +.Dv AI_V4MAPPED +support in +.Xr getaddrinfo 8 . +Without enabling this option, +.Xr getaddrinfo 8 +just ignores the +.Dv AI_V4MAPPED +bit in the +.Fa ai_flags +field of +.Fa hints +parameter. Property changes on: tools/build/options/WITH_GETADDRINFO_V4MAPPED ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property