Hi,

I don't like AI_ADDRCONFIG.  It's useless as specified, and making it
useful requires interpretations and deviations.

My understanding is that its goal is to solve a real world problem,
as in avoiding useless and potentially harmful DNS requests.  So why not
make it do that, and just that?  Because I don't think the end goal is
preventing IPv6 link-local communication, or communication with ::1 or
"localhost", etc.

What do you folks think?

The diff below seems to work well, as a bonus it avoids changing the
hints passed by the caller, and extends the use of local variable "ai"
("ai" could probably be renamed to "hints", btw).

Index: asr/getaddrinfo_async.c
===================================================================
RCS file: /cvs/src/lib/libc/asr/getaddrinfo_async.c,v
retrieving revision 1.27
diff -u -p -r1.27 getaddrinfo_async.c
--- asr/getaddrinfo_async.c     28 Apr 2014 21:38:59 -0000      1.27
+++ asr/getaddrinfo_async.c     2 May 2014 06:25:03 -0000
@@ -129,7 +129,7 @@ getaddrinfo_async_run(struct asr_query *
 #endif
        char             fqdn[MAXDNAME];
        const char      *str;
-       struct addrinfo *ai;
+       struct addrinfo *ai, *saved_ai, addrconfig_hints;
        int              i, family, r, v4, v6;
        FILE            *f;
        struct ifaddrs  *ifa, *ifa0;
@@ -157,7 +157,7 @@ getaddrinfo_async_run(struct asr_query *
                        break;
                }
 
-               ai = &as->as.ai.hints;
+               ai = saved_ai = &as->as.ai.hints;
 
                if (ai->ai_addrlen ||
                    ai->ai_canonname ||
@@ -219,17 +219,12 @@ getaddrinfo_async_run(struct asr_query *
                                        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;
-                       }
+
+                       memcpy(&addrconfig_hints, ai, sizeof(addrconfig_hints));
                        if (ai->ai_family == PF_UNSPEC && v4 && !v6)
-                               ai->ai_family = PF_INET;
+                               addrconfig_hints.ai_family = PF_INET;
                        if (ai->ai_family == PF_UNSPEC && !v4 && v6)
-                               ai->ai_family = PF_INET6;
+                               addrconfig_hints.ai_family = PF_INET6;
                }
 
                /* Make sure there is at least a valid combination */
@@ -246,10 +241,10 @@ getaddrinfo_async_run(struct asr_query *
 
                if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_UDP)
                        as->as.ai.port_udp = get_port(as->as.ai.servname, "udp",
-                           as->as.ai.hints.ai_flags & AI_NUMERICSERV);
+                           ai->ai_flags & AI_NUMERICSERV);
                if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_TCP)
                        as->as.ai.port_tcp = get_port(as->as.ai.servname, "tcp",
-                           as->as.ai.hints.ai_flags & AI_NUMERICSERV);
+                           ai->ai_flags & AI_NUMERICSERV);
                if (as->as.ai.port_tcp == -2 || as->as.ai.port_udp == -2 ||
                    (as->as.ai.port_tcp == -1 && as->as.ai.port_udp == -1) ||
                    (ai->ai_protocol && (as->as.ai.port_udp == -1 ||
@@ -322,13 +317,24 @@ getaddrinfo_async_run(struct asr_query *
                        async_set_state(as, ASR_STATE_NOT_FOUND);
                        break;
                }
+               ai = saved_ai;
+               /* AF filtering is only for dns */
+               if (ai->ai_flags & AI_ADDRCONFIG && AS_DB(as) == ASR_DB_DNS) {
+                       if (ai->ai_family == PF_UNSPEC && !v4 && !v6 ||
+                           ai->ai_family == PF_INET && !v4 ||
+                           ai->ai_family == PF_INET6 && !v6) {
+                               async_set_state(as, ASR_STATE_NEXT_DB);
+                               break;
+                       }
+                       ai = &addrconfig_hints;
+               }
                as->as_family_idx = 0;
                async_set_state(as, ASR_STATE_SAME_DB);
                break;
 
        case ASR_STATE_NEXT_FAMILY:
                as->as_family_idx += 1;
-               if (as->as.ai.hints.ai_family != AF_UNSPEC ||
+               if (ai->ai_family != AF_UNSPEC ||
                    AS_FAMILY(as) == -1) {
                        /* The family was specified, or we have tried all
                         * families with this DB.
@@ -384,8 +390,8 @@ getaddrinfo_async_run(struct asr_query *
                                break;
                        }
 
-                       family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
-                           AS_FAMILY(as) : as->as.ai.hints.ai_family;
+                       family = (ai->ai_family == AF_UNSPEC) ?
+                           AS_FAMILY(as) : ai->ai_family;
 
                        as->as.ai.subq = res_query_async_ctx(as->as.ai.fqdn,
                            C_IN, (family == AF_INET6) ? T_AAAA : T_A,
@@ -408,8 +414,8 @@ getaddrinfo_async_run(struct asr_query *
                                async_set_state(as, ASR_STATE_NEXT_DB);
                                break;
                        }
-                       family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
-                           AS_FAMILY(as) : as->as.ai.hints.ai_family;
+                       family = (ai->ai_family == AF_UNSPEC) ?
+                           AS_FAMILY(as) : ai->ai_family;
 
                        r = addrinfo_from_file(as, family, f);
                        if (r == -1) {
@@ -429,8 +435,8 @@ getaddrinfo_async_run(struct asr_query *
                                async_set_state(as, ASR_STATE_NEXT_DB);
                                break;
                        }
-                       family = (as->as.ai.hints.ai_family == AF_UNSPEC) ?
-                           AS_FAMILY(as) : as->as.ai.hints.ai_family;
+                       family = (ai->ai_family == AF_UNSPEC) ?
+                           AS_FAMILY(as) : ai->ai_family;
 
                        name = as->as.ai.hostname;
 
Index: net/getaddrinfo.3
===================================================================
RCS file: /cvs/src/lib/libc/net/getaddrinfo.3,v
retrieving revision 1.55
diff -u -p -r1.55 getaddrinfo.3
--- net/getaddrinfo.3   28 Apr 2014 21:38:59 -0000      1.55
+++ net/getaddrinfo.3   2 May 2014 06:50:01 -0000
@@ -123,9 +123,10 @@ the following values:
 .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.
+bit is set, DNS requests for IPv4 addresses will be performed only if an
+IPv4 address is configured on an interface, and DNS requetsts for IPv6
+addresses will be performed 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


-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to