diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index ccd5d6e18109..847f1629b96e 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -201,11 +201,7 @@ static const ns_src default_dns_files[] = { { 0 } }; -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif +#define MAXPACKET (64*1024) typedef union { HEADER hdr; @@ -1415,7 +1411,7 @@ _dns_getaddrinfo(rv, cb_data, ap) va_list ap; { struct addrinfo *ai; - querybuf buf, buf2; + querybuf *buf, *buf2; const char *name; const struct addrinfo *pai; struct addrinfo sentinel, *cur; @@ -1429,47 +1425,66 @@ _dns_getaddrinfo(rv, cb_data, ap) memset(&sentinel, 0, sizeof(sentinel)); cur = &sentinel; + buf = malloc(sizeof(*buf)); + if (!buf) { + h_errno = NETDB_INTERNAL; + return NS_NOTFOUND; + } + buf2 = malloc(sizeof(*buf2)); + if (!buf2) { + free(buf); + h_errno = NETDB_INTERNAL; + return NS_NOTFOUND; + } + switch (pai->ai_family) { case AF_UNSPEC: /* prefer IPv6 */ q.qclass = C_IN; q.qtype = T_AAAA; - q.answer = buf.buf; - q.anslen = sizeof(buf); + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); q.next = &q2; q2.qclass = C_IN; q2.qtype = T_A; - q2.answer = buf2.buf; - q2.anslen = sizeof(buf2); + q2.answer = buf2->buf; + q2.anslen = sizeof(buf2->buf); break; case AF_INET: q.qclass = C_IN; q.qtype = T_A; - q.answer = buf.buf; - q.anslen = sizeof(buf); + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); break; case AF_INET6: q.qclass = C_IN; q.qtype = T_AAAA; - q.answer = buf.buf; - q.anslen = sizeof(buf); + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); break; default: + free(buf); + free(buf2); return NS_UNAVAIL; } - if (res_searchN(name, &q) < 0) + if (res_searchN(name, &q) < 0) { + free(buf); + free(buf2); return NS_NOTFOUND; - ai = getanswer(&buf, q.n, q.name, q.qtype, pai); + } + ai = getanswer(buf, q.n, q.name, q.qtype, pai); if (ai) { cur->ai_next = ai; while (cur && cur->ai_next) cur = cur->ai_next; } if (q.next) { - ai = getanswer(&buf2, q2.n, q2.name, q2.qtype, pai); + ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); if (ai) cur->ai_next = ai; } + free(buf); + free(buf2); if (sentinel.ai_next == NULL) switch (h_errno) { case HOST_NOT_FOUND: @@ -1772,7 +1787,7 @@ res_queryN(name, target) const char *name; /* domain name */ struct res_target *target; { - u_char buf[MAXPACKET]; + u_char *buf; HEADER *hp; int n; struct res_target *t; @@ -1787,6 +1802,12 @@ res_queryN(name, target) return (-1); } + buf = malloc(MAXPACKET); + if (!buf) { + h_errno = NETDB_INTERNAL; + return -1; + } + for (t = target; t; t = t->next) { int class, type; u_char *answer; @@ -1806,14 +1827,15 @@ res_queryN(name, target) #endif n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, - buf, sizeof(buf)); + buf, MAXPACKET); if (n > 0 && (_res.options & RES_USE_EDNS0) != 0) - n = res_opt(n, buf, sizeof(buf), anslen); + n = res_opt(n, buf, MAXPACKET, anslen); if (n <= 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); #endif + free(buf); h_errno = NO_RECOVERY; return (n); } @@ -1824,6 +1846,7 @@ res_queryN(name, target) if (_res.options & RES_DEBUG) printf(";; res_query: send error\n"); #endif + free(buf); h_errno = TRY_AGAIN; return (n); } @@ -1846,6 +1869,8 @@ res_queryN(name, target) t->n = n; } + free(buf); + if (ancount == 0) { switch (rcode) { case NXDOMAIN: