Implement AI_ADDRCONFIG
authorsperreault <sperreault@openbsd.org>
Mon, 28 Apr 2014 21:38:59 +0000 (21:38 +0000)
committersperreault <sperreault@openbsd.org>
Mon, 28 Apr 2014 21:38:59 +0000 (21:38 +0000)
This is a getaddrinfo() flag that is defined thusly in RFC 3493:

   If the AI_ADDRCONFIG flag is specified, IPv4 addresses shall be
   returned only if an IPv4 address is configured on the local system,
   and IPv6 addresses shall be returned only if an IPv6 address is
   configured on the local system.  The loopback address is not
   considered for this case as valid as a configured address.

      For example, when using the DNS, a query for AAAA records should
      occur only if the node has at least one IPv6 address configured
      (other than IPv6 loopback) and a query for A records should occur
      only if the node has at least one IPv4 address configured (other
      than the IPv4 loopback).

The flag is set by default when hints is NULL.

ok Eric Faurot, Jason McIntyre

include/netdb.h
lib/libc/asr/getaddrinfo_async.c
lib/libc/net/getaddrinfo.3

index a5a1c6b..a176922 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: netdb.h,v 1.31 2012/09/15 00:47:08 guenther Exp $     */
+/*     $OpenBSD: netdb.h,v 1.32 2014/04/28 21:38:59 sperreault Exp $   */
 
 /*
  * ++Copyright++ 1980, 1983, 1988, 1993
@@ -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 1f1d19c..00ed6a1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: getaddrinfo_async.c,v 1.26 2014/03/26 18:13:15 eric Exp $     */
+/*     $OpenBSD: getaddrinfo_async.c,v 1.27 2014/04/28 21:38:59 sperreault Exp $       */
 /*
  * Copyright (c) 2012 Eric Faurot <eric@openbsd.org>
  *
@@ -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, const char *servname,
        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 *as, struct asr_result *ar)
        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;
@@ -195,6 +199,39 @@ getaddrinfo_async_run(struct asr_query *as, struct asr_result *ar)
                        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 */
                for (i = 0; matches[i].family != -1; i++)
                        if (MATCH_FAMILY(ai->ai_family, i) &&
index db4417a..33270db 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: getaddrinfo.3,v 1.54 2014/01/21 03:15:45 schwarze Exp $
+.\"    $OpenBSD: getaddrinfo.3,v 1.55 2014/04/28 21:38:59 sperreault Exp $
 .\"    $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $
 .\"
 .\" Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
@@ -16,7 +16,7 @@
 .\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 .\" PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: January 21 2014 $
+.Dd $Mdocdate: April 28 2014 $
 .Dt GETADDRINFO 3
 .Os
 .Sh NAME
@@ -120,6 +120,14 @@ 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.
+Addresses on a loopback interface and link-local IPv6 addresses are not
+considered valid as configured addresses.
 .It Dv AI_CANONNAME
 If the
 .Dv AI_CANONNAME
@@ -219,7 +227,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