Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/net Add AI_ADDRCONFIG, which makes getaddrinfo() re...



details:   https://anonhg.NetBSD.org/src/rev/6b86de6736e8
branches:  trunk
changeset: 778151:6b86de6736e8
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Mar 17 21:56:40 2012 +0000

description:
Add AI_ADDRCONFIG, which makes getaddrinfo() return only address with families
that are already configured in the system.

diffstat:

 lib/libc/net/getaddrinfo.c |  43 ++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 40 insertions(+), 3 deletions(-)

diffs (113 lines):

diff -r 876818a4e772 -r 6b86de6736e8 lib/libc/net/getaddrinfo.c
--- a/lib/libc/net/getaddrinfo.c        Sat Mar 17 21:54:12 2012 +0000
+++ b/lib/libc/net/getaddrinfo.c        Sat Mar 17 21:56:40 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: getaddrinfo.c,v 1.97 2012/03/13 21:13:40 christos Exp $        */
+/*     $NetBSD: getaddrinfo.c,v 1.98 2012/03/17 21:56:40 christos 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.97 2012/03/13 21:13:40 christos Exp $");
+__RCSID("$NetBSD: getaddrinfo.c,v 1.98 2012/03/17 21:56:40 christos Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include "namespace.h"
@@ -76,6 +76,7 @@
 #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_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 @@
        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 @@
                }
        }
 
+       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 @@
        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 @@
                        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,10 @@
        for (ex = explore; ex->e_af >= 0; ex++) {
                *pai = ai0;
 
+               /* ADDRCONFIG check */
+               if ((((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 +1019,30 @@
        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



Home | Main Index | Thread Index | Old Index