On Wed, Apr 23, 2014 at 12:02:44PM -0400, Simon Perreault wrote:
> Will send an updated diff later today.

It is now later today (ha!) and here's the promised updated diff.

Changes:

- Simplified and embettered address filtering based on Stuart Henderson's
  comments.

- Fixed manpage formatting.

ok?

Simon


Index: include/netdb.h
===================================================================
RCS file: /cvs/src/include/netdb.h,v
retrieving revision 1.31
diff -u -p -r1.31 netdb.h
--- include/netdb.h     15 Sep 2012 00:47:08 -0000      1.31
+++ include/netdb.h     27 Apr 2014 17:36:39 -0000
@@ -167,9 +167,11 @@ extern int h_errno;
 #define AI_EXT         8       /* enable non-portable extensions */
 #define AI_NUMERICSERV 16      /* don't ever try servname lookup */
 #define AI_FQDN                32      /* return the FQDN that was resolved */
+#define AI_ADDRCONFIG  64      /* return configured address families only */
 /* valid flags for addrinfo */
 #define AI_MASK \
-    (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_FQDN)
+    (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | AI_FQDN | \
+     AI_ADDRCONFIG)
 
 #define NI_NUMERICHOST 1       /* return the host address, not the name */
 #define NI_NUMERICSERV 2       /* return the service address, not the name */
Index: lib/libc/asr/getaddrinfo_async.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/getaddrinfo_async.c,v
retrieving revision 1.26
diff -u -p -r1.26 getaddrinfo_async.c
--- lib/libc/asr/getaddrinfo_async.c    26 Mar 2014 18:13:15 -0000      1.26
+++ lib/libc/asr/getaddrinfo_async.c    27 Apr 2014 17:36:39 -0000
@@ -21,6 +21,7 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/nameser.h>
+#include <net/if.h>
 #ifdef YP
 #include <rpc/rpc.h>
 #include <rpcsvc/yp.h>
@@ -32,6 +33,7 @@
 #include <asr.h>
 #include <err.h>
 #include <errno.h>
+#include <ifaddrs.h>
 #include <resolv.h> /* for res_hnok */
 #include <stdlib.h>
 #include <string.h>
@@ -104,6 +106,7 @@ getaddrinfo_async(const char *hostname, 
        else {
                memset(&as->as.ai.hints, 0, sizeof as->as.ai.hints);
                as->as.ai.hints.ai_family = PF_UNSPEC;
+               as->as.ai.hints.ai_flags = AI_ADDRCONFIG;
        }
 
        asr_ctx_unref(ac);
@@ -127,8 +130,9 @@ getaddrinfo_async_run(struct asr_query *
        char             fqdn[MAXDNAME];
        const char      *str;
        struct addrinfo *ai;
-       int              i, family, r;
+       int              i, family, r, v4, v6;
        FILE            *f;
+       struct ifaddrs  *ifa, *ifa0;
        union {
                struct sockaddr         sa;
                struct sockaddr_in      sain;
@@ -193,6 +197,39 @@ getaddrinfo_async_run(struct asr_query *
                        ar->ar_gai_errno = EAI_SERVICE;
                        async_set_state(as, ASR_STATE_HALT);
                        break;
+               }
+
+               /* Restrict result set to configured address families */
+               if (ai->ai_flags & AI_ADDRCONFIG) {
+                       if (getifaddrs(&ifa0) != 0) {
+                               ar->ar_gai_errno = EAI_FAIL;
+                               async_set_state(as, ASR_STATE_HALT);
+                               break;
+                       }
+                       v4 = 0;
+                       v6 = 0;
+                       for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
+                               if (ifa->ifa_flags & IFF_LOOPBACK)
+                                       continue;
+                               if (ifa->ifa_addr->sa_family == PF_INET)
+                                       v4 = 1;
+                               else if (ifa->ifa_addr->sa_family == PF_INET6 &&
+                                   !IN6_IS_ADDR_LINKLOCAL(&((struct
+                                   sockaddr_in6 *)ifa->ifa_addr)->sin6_addr))
+                                       v6 = 1;
+                       }
+                       freeifaddrs(ifa0);
+                       if (ai->ai_family == PF_UNSPEC && !v4 && !v6 ||
+                           ai->ai_family == PF_INET && !v4 ||
+                           ai->ai_family == PF_INET6 && !v6) {
+                               ar->ar_gai_errno = EAI_NONAME;
+                               async_set_state(as, ASR_STATE_HALT);
+                               break;
+                       }
+                       if (ai->ai_family == PF_UNSPEC && v4 && !v6)
+                               ai->ai_family = PF_INET;
+                       if (ai->ai_family == PF_UNSPEC && !v4 && v6)
+                               ai->ai_family = PF_INET6;
                }
 
                /* Make sure there is at least a valid combination */
Index: lib/libc/net/getaddrinfo.3
===================================================================
RCS file: /cvs/src/lib/libc/net/getaddrinfo.3,v
retrieving revision 1.54
diff -u -p -r1.54 getaddrinfo.3
--- lib/libc/net/getaddrinfo.3  21 Jan 2014 03:15:45 -0000      1.54
+++ lib/libc/net/getaddrinfo.3  27 Apr 2014 17:36:39 -0000
@@ -120,6 +120,13 @@ is formed by
 .Tn OR Ns 'ing
 the following values:
 .Bl -tag -width "AI_CANONNAMEXX"
+.It Dv AI_ADDRCONFIG
+If the
+.Dv AI_ADDRCONFIG
+bit is set, IPv4 addresses will be returned only if an IPv4 address is
+configured on an interface, and IPv6 addresses will be returned only if an IPv6
+address is configured on an interface.  The loopback address is not considered
+for this case as valid as a configured address.
 .It Dv AI_CANONNAME
 If the
 .Dv AI_CANONNAME
@@ -219,7 +226,10 @@ behaves as if the caller provided a
 with
 .Fa ai_family
 set to
-.Dv PF_UNSPEC
+.Dv PF_UNSPEC ,
+.Fa ai_flags
+set to
+.Dv AI_ADDRCONFIG ,
 and all other elements set to zero or
 .Dv NULL .
 .Pp

Reply via email to