make getaddrinfo with AF_UNSPEC and null host return both IPv4 and v6
authorRich Felker <dalias@aerifal.cx>
Wed, 24 Jul 2013 20:49:17 +0000 (16:49 -0400)
committerRich Felker <dalias@aerifal.cx>
Wed, 24 Jul 2013 20:49:17 +0000 (16:49 -0400)
based on a patch by orc, with indexing and flow control cleaned up a
little bit. this code is all going to be replaced at some point in the
near future.

src/network/getaddrinfo.c

index 3d7b9ecd4e4b32775b38c4f84618ae12e2f20718..4c1fe27717329d0d591130762b25a803fa384464 100644 (file)
@@ -100,21 +100,30 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
        }
 
        if (!host) {
-               if (family == AF_UNSPEC) family = AF_INET;
-               buf = calloc(sizeof *buf, 1+EXTRA);
+               if (family == AF_UNSPEC) {
+                       cnt = 2; family = AF_INET;
+               } else {
+                       cnt = 1;
+               }
+               buf = calloc(sizeof *buf, cnt);
                if (!buf) return EAI_MEMORY;
-               buf->ai.ai_protocol = proto;
-               buf->ai.ai_socktype = type;
-               buf->ai.ai_addr = (void *)&buf->sa;
-               buf->ai.ai_addrlen = family==AF_INET6 ? sizeof sa.sin6 : sizeof sa.sin;
-               buf->ai.ai_family = family;
-               buf->sa.sin.sin_family = family;
-               buf->sa.sin.sin_port = port;
-               if (!(flags & AI_PASSIVE)) {
-                       if (family == AF_INET) {
-                               0[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=127;
-                               3[(uint8_t*)&buf->sa.sin.sin_addr.s_addr]=1;
-                       } else buf[0].sa.sin6.sin6_addr.s6_addr[15] = 1;
+               for (i=0; i<cnt; i++) {
+                       if (i) family = AF_INET6;
+                       buf[i].ai.ai_protocol = proto;
+                       buf[i].ai.ai_socktype = type;
+                       buf[i].ai.ai_addr = (void *)&buf[i].sa;
+                       buf[i].ai.ai_addrlen = family==AF_INET6
+                               ? sizeof sa.sin6 : sizeof sa.sin;
+                       buf[i].ai.ai_family = family;
+                       buf[i].sa.sin.sin_family = family;
+                       buf[i].sa.sin.sin_port = port;
+                       if (i+1<cnt) buf[i].ai.ai_next = &buf[i+1].ai;
+                       if (!(flags & AI_PASSIVE)) {
+                               if (family == AF_INET) {
+                                       0[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=127;
+                                       3[(uint8_t*)&buf[i].sa.sin.sin_addr.s_addr]=1;
+                               } else buf[i].sa.sin6.sin6_addr.s6_addr[15] = 1;
+                       }
                }
                *res = &buf->ai;
                return 0;