فهرست منبع

make getaddrinfo with AF_UNSPEC and null host return both IPv4 and v6

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.
Rich Felker 11 سال پیش
والد
کامیت
f5dfb45f78
1فایلهای تغییر یافته به همراه23 افزوده شده و 14 حذف شده
  1. 23 14
      src/network/getaddrinfo.c

+ 23 - 14
src/network/getaddrinfo.c

@@ -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;