aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHajimu UMEMOTO <ume@FreeBSD.org>2002-10-23 14:48:22 +0000
committerHajimu UMEMOTO <ume@FreeBSD.org>2002-10-23 14:48:22 +0000
commit57f9b3e30a651a88454928698fff35cb39836d9c (patch)
treecc326b70d1c7d04f032d65be8963ec859631ba6b
parent526df856a210f4b57b9918af50fe7977f025cf13 (diff)
downloadsrc-57f9b3e30a651a88454928698fff35cb39836d9c.tar.gz
src-57f9b3e30a651a88454928698fff35cb39836d9c.zip
MFS: Allocate 64K recieve buffer for DNS responses.
lib/libc/net/getaddrinfo.c: 1.9.2.10, 1.9.2.11 lib/libc/net/gethostbydns.c: 1.27.2.4 lib/libc/net/getnetbydns.c: 1.13.2.4 lib/libc/net/name6.c: 1.6.2.7 lib/libc/net/res_mkquery.c: 1.15.2.2 Approved by: security-officer
Notes
Notes: svn path=/releng/4.6/; revision=105800
-rw-r--r--lib/libc/net/getaddrinfo.c69
-rw-r--r--lib/libc/net/gethostbydns.c39
-rw-r--r--lib/libc/net/getnetbydns.c33
-rw-r--r--lib/libc/net/name6.c79
-rw-r--r--lib/libc/net/res_mkquery.c2
5 files changed, 152 insertions, 70 deletions
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index 7847cd31d6c3..ed46d3f4bf57 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -182,11 +182,7 @@ static const struct explore explore[] = {
#define PTON_MAX 4
#endif
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
+#define MAXPACKET (64*1024)
typedef union {
HEADER hdr;
@@ -1407,7 +1403,7 @@ _dns_getaddrinfo(pai, hostname, res)
struct addrinfo **res;
{
struct addrinfo *ai;
- querybuf buf, buf2;
+ querybuf *buf, *buf2;
const char *name;
struct addrinfo sentinel, *cur;
struct res_target q, q2;
@@ -1417,47 +1413,66 @@ _dns_getaddrinfo(pai, hostname, res)
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
+ buf = malloc(sizeof(*buf));
+ if (!buf) {
+ h_errno = NETDB_INTERNAL;
+ return EAI_MEMORY;
+ }
+ buf2 = malloc(sizeof(*buf2));
+ if (!buf2) {
+ free(buf);
+ h_errno = NETDB_INTERNAL;
+ return EAI_MEMORY;
+ }
+
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 EAI_FAIL;
}
- if (res_searchN(hostname, &q) < 0)
+ if (res_searchN(hostname, &q) < 0) {
+ free(buf);
+ free(buf2);
return EAI_NODATA;
- 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:
@@ -1662,7 +1677,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;
@@ -1677,6 +1692,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;
@@ -1696,14 +1717,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);
}
@@ -1714,12 +1736,15 @@ res_queryN(name, target)
if (_res.options & RES_DEBUG)
printf(";; res_query: send error\n");
#endif
+ free(buf);
h_errno = TRY_AGAIN;
return (n);
}
#endif
- if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+ if (n < 0 || n > anslen)
+ hp->rcode = FORMERR; /* XXX not very informative */
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
rcode = hp->rcode; /* record most recent error */
#ifdef DEBUG
if (_res.options & RES_DEBUG)
@@ -1734,6 +1759,8 @@ res_queryN(name, target)
t->n = n;
}
+ free(buf);
+
if (ancount == 0) {
switch (rcode) {
case NXDOMAIN:
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
index 52ac91a041be..5df45eb7e747 100644
--- a/lib/libc/net/gethostbydns.c
+++ b/lib/libc/net/gethostbydns.c
@@ -67,6 +67,7 @@ static char rcsid[] = "$FreeBSD$";
#include <arpa/nameser.h>
#include <stdio.h>
+#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
@@ -96,11 +97,7 @@ static u_char host_addr[16]; /* IPv4 or IPv6 */
static void addrsort __P((char **, int));
#endif
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
+#define MAXPACKET (64*1024)
typedef union {
HEADER hdr;
@@ -480,10 +477,11 @@ _gethostbydnsname(name, af)
const char *name;
int af;
{
- querybuf buf;
+ querybuf *buf;
register const char *cp;
char *bp;
int n, size, type, len;
+ struct hostent *hp;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
@@ -584,11 +582,19 @@ _gethostbydnsname(name, af)
break;
}
- if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ n = res_search(name, C_IN, type, buf->buf, sizeof(buf->buf));
+ if (n < 0) {
+ free(buf);
dprintf("res_search failed (%d)\n", n);
return (NULL);
}
- return (gethostanswer(&buf, n, name, type));
+ hp = gethostanswer(buf, n, name, type);
+ free(buf);
+ return (hp);
}
struct hostent *
@@ -600,7 +606,7 @@ _gethostbydnsaddr(addr, len, af)
static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
int n, size;
- querybuf buf;
+ querybuf *buf;
register struct hostent *hp;
char qbuf[MAXDNAME+1], *qp;
#ifdef SUNSECURITY
@@ -660,17 +666,26 @@ _gethostbydnsaddr(addr, len, af)
default:
abort();
}
- n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf->buf, sizeof buf->buf);
if (n < 0) {
+ free(buf);
dprintf("res_query failed (%d)\n", n);
return (NULL);
}
- if (n > sizeof buf.buf) {
+ if (n > sizeof buf->buf) {
+ free(buf);
dprintf("static buffer is too small (%d)\n", n);
return (NULL);
}
- if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
+ if (!(hp = gethostanswer(buf, n, qbuf, T_PTR))) {
+ free(buf);
return (NULL); /* h_errno was set by gethostanswer() */
+ }
+ free(buf);
#ifdef SUNSECURITY
if (af == AF_INET) {
/*
diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c
index e1a11d2e5d3a..5de46df9169f 100644
--- a/lib/libc/net/getnetbydns.c
+++ b/lib/libc/net/getnetbydns.c
@@ -70,6 +70,7 @@ static char rcsid[] = "$FreeBSD$";
#include <arpa/nameser.h>
#include <stdio.h>
+#include <stdlib.h>
#include <netdb.h>
#include <resolv.h>
#include <ctype.h>
@@ -85,11 +86,7 @@ extern int h_errno;
#define BYNAME 1
#define MAXALIASES 35
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
+#define MAXPACKET (64*1024)
typedef union {
HEADER hdr;
@@ -226,7 +223,7 @@ _getnetbydnsaddr(net, net_type)
{
unsigned int netbr[4];
int nn, anslen;
- querybuf buf;
+ querybuf *buf;
char qbuf[MAXDNAME];
unsigned long net2;
struct netent *net_entry;
@@ -252,15 +249,21 @@ _getnetbydnsaddr(net, net_type)
netbr[1], netbr[0]);
break;
}
- anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
+ anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)buf, sizeof(*buf));
if (anslen < 0) {
+ free(buf);
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_query failed\n");
#endif
return (NULL);
}
- net_entry = getnetanswer(&buf, anslen, BYADDR);
+ net_entry = getnetanswer(buf, anslen, BYADDR);
+ free(buf);
if (net_entry) {
unsigned u_net = net; /* maybe net should be unsigned ? */
@@ -278,24 +281,32 @@ _getnetbydnsname(net)
register const char *net;
{
int anslen;
- querybuf buf;
+ querybuf *buf;
char qbuf[MAXDNAME];
+ struct netent *net_entry;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
h_errno = NETDB_INTERNAL;
return (NULL);
}
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ h_errno = NETDB_INTERNAL;
+ return (NULL);
+ }
strncpy(qbuf, net, sizeof(qbuf) - 1);
qbuf[sizeof(qbuf) - 1] = '\0';
- anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
+ anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)buf, sizeof(*buf));
if (anslen < 0) {
+ free(buf);
#ifdef DEBUG
if (_res.options & RES_DEBUG)
printf("res_query failed\n");
#endif
return (NULL);
}
- return getnetanswer(&buf, anslen, BYNAME);
+ net_entry = getnetanswer(buf, anslen, BYNAME);
+ free(buf);
+ return net_entry;
}
void
diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c
index 401786811b50..070280a6c166 100644
--- a/lib/libc/net/name6.c
+++ b/lib/libc/net/name6.c
@@ -994,11 +994,7 @@ struct __res_type_list {
int rtl_type;
};
-#if PACKETSZ > 1024
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 1024
-#endif
+#define MAXPACKET (64*1024)
typedef union {
HEADER hdr;
@@ -1305,7 +1301,7 @@ _res_search_multi(name, rtl, errp)
int trailing_dot, ret, saved_herrno;
int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
struct __res_type_list *rtl0 = rtl;
- querybuf buf;
+ querybuf *buf;
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
*errp = NETDB_INTERNAL;
@@ -1318,17 +1314,23 @@ _res_search_multi(name, rtl, errp)
if (cp > name && *--cp == '.')
trailing_dot++;
+ buf = malloc(sizeof(*buf));
+ if (buf == NULL) {
+ *errp = NETDB_INTERNAL;
+ return NULL;
+ }
+
/* If there aren't any dots, it could be a user-level alias */
if (!dots && (cp = hostalias(name)) != NULL) {
for(rtl = rtl0; rtl != NULL;
rtl = SLIST_NEXT(rtl, rtl_entry)) {
- ret = res_query(cp, C_IN, rtl->rtl_type, buf.buf,
- sizeof(buf.buf));
- if (ret > 0) {
+ ret = res_query(cp, C_IN, rtl->rtl_type, buf->buf,
+ sizeof(buf->buf));
+ if (ret > 0 && ret < sizeof(buf->buf)) {
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
? AF_INET6 : AF_INET;
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
- hp = getanswer(&buf, ret, name, rtl->rtl_type,
+ hp = getanswer(buf, ret, name, rtl->rtl_type,
&hpbuf, errp);
if (!hp)
continue;
@@ -1336,6 +1338,7 @@ _res_search_multi(name, rtl, errp)
hp0 = _hpmerge(hp0, hp, errp);
}
}
+ free(buf);
return (hp0);
}
@@ -1348,12 +1351,12 @@ _res_search_multi(name, rtl, errp)
for(rtl = rtl0; rtl != NULL;
rtl = SLIST_NEXT(rtl, rtl_entry)) {
ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,
- buf.buf, sizeof(buf.buf));
- if (ret > 0) {
+ buf->buf, sizeof(buf->buf));
+ if (ret > 0 && ret < sizeof(buf->buf)) {
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
? AF_INET6 : AF_INET;
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
- hp = getanswer(&buf, ret, name, rtl->rtl_type,
+ hp = getanswer(buf, ret, name, rtl->rtl_type,
&hpbuf, errp);
if (!hp)
continue;
@@ -1361,8 +1364,10 @@ _res_search_multi(name, rtl, errp)
hp0 = _hpmerge(hp0, hp, errp);
}
}
- if (hp0 != NULL)
+ if (hp0 != NULL) {
+ free(buf);
return (hp0);
+ }
saved_herrno = *errp;
tried_as_is++;
}
@@ -1385,12 +1390,12 @@ _res_search_multi(name, rtl, errp)
rtl = SLIST_NEXT(rtl, rtl_entry)) {
ret = res_querydomain(name, *domain, C_IN,
rtl->rtl_type,
- buf.buf, sizeof(buf.buf));
- if (ret > 0) {
+ buf->buf, sizeof(buf->buf));
+ if (ret > 0 && ret < sizeof(buf->buf)) {
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
? AF_INET6 : AF_INET;
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
- hp = getanswer(&buf, ret, name,
+ hp = getanswer(buf, ret, name,
rtl->rtl_type, &hpbuf, errp);
if (!hp)
continue;
@@ -1398,8 +1403,10 @@ _res_search_multi(name, rtl, errp)
hp0 = _hpmerge(hp0, hp, errp);
}
}
- if (hp0 != NULL)
+ if (hp0 != NULL) {
+ free(buf);
return (hp0);
+ }
/*
* If no server present, give up.
@@ -1415,6 +1422,7 @@ _res_search_multi(name, rtl, errp)
* fully-qualified.
*/
if (errno == ECONNREFUSED) {
+ free(buf);
*errp = TRY_AGAIN;
return (NULL);
}
@@ -1427,7 +1435,7 @@ _res_search_multi(name, rtl, errp)
/* keep trying */
break;
case TRY_AGAIN:
- if (buf.hdr.rcode == SERVFAIL) {
+ if (buf->hdr.rcode == SERVFAIL) {
/* try next search element, if any */
got_servfail++;
break;
@@ -1455,12 +1463,12 @@ _res_search_multi(name, rtl, errp)
for(rtl = rtl0; rtl != NULL;
rtl = SLIST_NEXT(rtl, rtl_entry)) {
ret = res_querydomain(name, NULL, C_IN, rtl->rtl_type,
- buf.buf, sizeof(buf.buf));
- if (ret > 0) {
+ buf->buf, sizeof(buf->buf));
+ if (ret > 0 && ret < sizeof(buf->buf)) {
hpbuf.h_addrtype = (rtl->rtl_type == T_AAAA)
? AF_INET6 : AF_INET;
hpbuf.h_length = ADDRLEN(hpbuf.h_addrtype);
- hp = getanswer(&buf, ret, name, rtl->rtl_type,
+ hp = getanswer(buf, ret, name, rtl->rtl_type,
&hpbuf, errp);
if (!hp)
continue;
@@ -1468,10 +1476,14 @@ _res_search_multi(name, rtl, errp)
hp0 = _hpmerge(hp0, hp, errp);
}
}
- if (hp0 != NULL)
+ if (hp0 != NULL) {
+ free(buf);
return (hp0);
+ }
}
+ free(buf);
+
/* if we got here, we didn't satisfy the search.
* if we did an initial full query, return that query's h_errno
* (note that we wouldn't be here if that query had succeeded).
@@ -1531,7 +1543,7 @@ _dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
#ifdef INET6
static const char hex[] = "0123456789abcdef";
#endif
- querybuf buf;
+ querybuf *buf;
char qbuf[MAXDNAME+1];
char *hlist[2];
@@ -1584,12 +1596,27 @@ _dns_ghbyaddr(const void *addr, int addrlen, int af, int *errp)
break;
}
- n = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf);
+ buf = malloc(sizeof(*buf));
+ if (buf == NULL) {
+ *errp = NETDB_INTERNAL;
+ return NULL;
+ }
+
+ n = res_query(qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf);
if (n < 0) {
+ free(buf);
*errp = h_errno;
return NULL;
+ } else if (n > sizeof(buf->buf)) {
+ free(buf);
+ *errp = NETDB_INTERNAL;
+#if 0
+ errno = ERANGE; /* XXX is it OK to set errno here? */
+#endif
+ return NULL;
}
- hp = getanswer(&buf, n, qbuf, T_PTR, &hbuf, errp);
+ hp = getanswer(buf, n, qbuf, T_PTR, &hbuf, errp);
+ free(buf);
if (!hp)
return NULL;
hbuf.h_addrtype = af;
diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c
index 6cbd37394b92..bacc4d58fe6b 100644
--- a/lib/libc/net/res_mkquery.c
+++ b/lib/libc/net/res_mkquery.c
@@ -228,6 +228,8 @@ res_opt(n0, buf, buflen, anslen)
__putshort(T_OPT, cp); /* TYPE */
cp += INT16SZ;
+ if (anslen > 0xffff)
+ anslen = 0xffff; /* limit to 16bit value */
__putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
cp += INT16SZ;
*cp++ = NOERROR; /* extended RCODE */