aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--resolv/gethnamaddr.c24
-rw-r--r--resolv/getnetbyaddr.c2
-rw-r--r--resolv/getnetent.c21
-rw-r--r--resolv/getnetnamadr.c6
-rw-r--r--resolv/netdb.h2
-rw-r--r--resolv/res_comp.c85
-rw-r--r--resolv/res_debug.c37
-rw-r--r--resolv/res_send.c27
-rw-r--r--resolv/resolv.h6
10 files changed, 169 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index f72444a..c4233e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
Thu May 9 09:17:46 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
+ * resolv: Code updated from BIND-4.9.3P2C3.
+
* Rules (static-only-routines rule): Use dummy.o, not dummy.so.
Wed May 8 20:04:29 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 41be4fc..6872be0 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -158,10 +158,21 @@ getanswer(answer, anslen, qname, qclass, qtype)
int toobig = 0;
char tbuf[MAXDNAME+1];
const char *tname;
+ int (*name_ok) __P((const char *));
tname = qname;
host.h_name = NULL;
eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = dn_isvalid;
+ break;
+ default:
+ abort();
+ }
/*
* find first satisfactory answer
*/
@@ -175,7 +186,8 @@ getanswer(answer, anslen, qname, qclass, qtype)
h_errno = NO_RECOVERY;
return (NULL);
}
- if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if ((n < 0) || !(*name_ok)(bp)) {
h_errno = NO_RECOVERY;
return (NULL);
}
@@ -204,7 +216,7 @@ getanswer(answer, anslen, qname, qclass, qtype)
had_error = 0;
while (ancount-- > 0 && cp < eom && !had_error) {
n = dn_expand(answer->buf, eom, cp, bp, buflen);
- if (n < 0) {
+ if ((n < 0) || !(*name_ok)(bp)) {
had_error++;
continue;
}
@@ -224,7 +236,7 @@ getanswer(answer, anslen, qname, qclass, qtype)
if (ap >= &host_aliases[MAXALIASES-1])
continue;
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
- if (n < 0) {
+ if ((n < 0) || !(*name_ok)(tbuf)) {
had_error++;
continue;
}
@@ -254,7 +266,7 @@ getanswer(answer, anslen, qname, qclass, qtype)
}
if (qtype == T_PTR && type == T_CNAME) {
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
- if (n < 0) {
+ if ((n < 0) || !res_hnok(tbuf)) {
had_error++;
continue;
}
@@ -288,7 +300,7 @@ getanswer(answer, anslen, qname, qclass, qtype)
continue; /* XXX - had_error++ ? */
}
n = dn_expand(answer->buf, eom, cp, bp, buflen);
- if (n < 0) {
+ if ((n < 0) || !res_hnok(bp)) {
had_error++;
break;
}
@@ -517,7 +529,7 @@ gethostbyaddr(addr, len, type)
h_errno = NETDB_INTERNAL;
return (NULL);
}
- if (type != AF_INET) {
+ if (type != AF_INET || len != INADDRSZ) {
errno = EAFNOSUPPORT;
h_errno = NETDB_INTERNAL;
return (NULL);
diff --git a/resolv/getnetbyaddr.c b/resolv/getnetbyaddr.c
index 3bc01ad..32513cc 100644
--- a/resolv/getnetbyaddr.c
+++ b/resolv/getnetbyaddr.c
@@ -42,7 +42,7 @@ extern int _net_stayopen;
struct netent *
_getnetbyaddr(net, type)
- register long net;
+ register unsigned long net;
register int type;
{
register struct netent *p;
diff --git a/resolv/getnetent.c b/resolv/getnetent.c
index fb47c30..7ec5607 100644
--- a/resolv/getnetent.c
+++ b/resolv/getnetent.c
@@ -143,18 +143,19 @@ again:
net.n_net = inet_network(cp);
net.n_addrtype = AF_INET;
q = net.n_aliases = net_aliases;
- if (p != NULL)
+ if (p != NULL) {
cp = p;
- while (cp && *cp) {
- if (*cp == ' ' || *cp == '\t') {
- cp++;
- continue;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &net_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
}
- if (q < &net_aliases[MAXALIASES - 1])
- *q++ = cp;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
- *cp++ = '\0';
}
*q = NULL;
return (&net);
diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c
index b2c9118..fad2b8c 100644
--- a/resolv/getnetnamadr.c
+++ b/resolv/getnetnamadr.c
@@ -139,7 +139,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
haveanswer = 0;
while (--ancount >= 0 && cp < eom) {
n = dn_expand(answer->buf, eom, cp, bp, buflen);
- if (n < 0)
+ if ((n < 0) || !dn_isvalid(bp))
break;
cp += n;
ans[0] = '\0';
@@ -150,7 +150,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
GETSHORT(n, cp);
if (class == C_IN && type == T_PTR) {
n = dn_expand(answer->buf, eom, cp, bp, buflen);
- if (n < 0) {
+ if ((n < 0) || !res_hnok(bp)) {
cp += n;
return (NULL);
}
@@ -202,7 +202,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
struct netent *
getnetbyaddr(net, net_type)
- register long net;
+ register u_long net;
register int net_type;
{
unsigned int netbr[4];
diff --git a/resolv/netdb.h b/resolv/netdb.h
index 822b621..fd06e17 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -135,7 +135,7 @@ struct hostent *gethostbyaddr __P((const char *, int, int));
struct hostent *gethostbyname __P((const char *));
struct hostent *gethostbyname2 __P((const char *, int));
struct hostent *gethostent __P((void));
-struct netent *getnetbyaddr __P((long, int)); /* u_long? */
+struct netent *getnetbyaddr __P((unsigned long, int));
struct netent *getnetbyname __P((const char *));
struct netent *getnetent __P((void));
struct protoent *getprotobyname __P((const char *));
diff --git a/resolv/res_comp.c b/resolv/res_comp.c
index 1342205..f234772 100644
--- a/resolv/res_comp.c
+++ b/resolv/res_comp.c
@@ -148,9 +148,6 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)
}
}
*dn = '\0';
- for (dn = exp_dn; (c = *dn) != '\0'; dn++)
- if (isascii(c) && isspace(c))
- return (-1);
if (len < 0)
len = cp - comp_dn;
return (len);
@@ -340,6 +337,88 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)
}
/*
+ * Verify that a domain name uses an acceptable character set.
+ */
+
+/****
+To: "Lawrence R. Rogers" <lrr@cert.org>
+cc: cert@cert.org, pvm@home.net
+Subject: Re: VU#14542
+In-reply-to: Your message of "Mon, 19 Feb 1996 17:16:27 PST."
+Date: Tue, 20 Feb 1996 22:37:21 -0800
+From: Paul A Vixie <vixie@wisdom.home.vix.com>
+
+in retrospect,
+
+ hostname = firstlabel ( "." otherlabel )+
+ firstchar = [a-zA-Z0-9_]
+ otherchar = [a-zA-Z0-9_-/]
+ firstlabel = firstchar otherchar*
+ otherlabel = otherchar+
+
+should have been
+
+ hostname = label ( "." label )+
+ firstchar = [a-zA-Z0-9_]
+ otherchar = [a-zA-Z0-9_-]
+ label = firstchar otherchar*
+
+i know of no example of a real host name that needs the looser rule i sent
+earlier. since i'm only trying to bend the spec to fit actual known uses,
+i should not have widened the rules as far as i did earlier.
+****/
+
+#define firstchar(c) ((isascii(c) && isalnum(c)) || (c) == '_')
+#define otherchar(c) (firstchar(c) || (c) == '-')
+#define wildlabel(firstlabel, ch, nch) \
+ ((firstlabel) && (ch) == '*' && ((nch) == '.' || (nch) == '\0'))
+
+int
+res_hnok(dn)
+ const char *dn;
+{
+ int ppch = '\0', pch = '.', ch = *dn++, firstlabel = 1;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (ch == '.' || (ch == '\\' && nch == '.')) {
+ NULL;
+ } else if (pch == '.' && ppch != '\\') {
+ if (!firstchar(ch) && !wildlabel(firstlabel, ch, nch))
+ return (0);
+ } else {
+ if (!otherchar(ch))
+ return (0);
+ }
+ ppch = pch, pch = ch, ch = nch;
+ firstlabel = 0;
+ }
+ return (1);
+}
+
+/*
+ * This function is quite liberal, since RFC 1034's character sets are only
+ * recommendations.
+ *
+ * Note that some char's are signed, so we have to cast to unsigned.
+ */
+int
+dn_isvalid(dn)
+ const char *dn;
+{
+ unsigned char *t = (unsigned char *)dn;
+ int ch;
+
+ while ((ch = *t++) != '\0')
+ if (ch <= 0x1f || ch >= 0x7f) {
+ /* Unprintable in ASCII. */
+ return (0);
+ }
+ return (1);
+}
+
+/*
* Routines to insert/extract short/long's.
*/
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index b3dfcdf..85ec628 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -502,16 +502,28 @@ __p_rr(cp, msg, file)
case T_HINFO:
case T_ISDN:
+ (void) fputs("\t\"", file);
cp2 = cp + dlen;
- if (n = *cp++) {
- fprintf(file, "\t%.*s", n, cp);
- cp += n;
+ if ((n = (unsigned char) *cp++) != 0) {
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ putc('"', file);
}
- if ((cp < cp2) && (n = *cp++)) {
- fprintf(file, "\t%.*s", n, cp);
- cp += n;
- } else if (type == T_HINFO)
+ if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
+ (void) fputs ("\t\"", file);
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
+ putc('"', file);
+ } else if (type == T_HINFO) {
+ (void) fputs("\"?\"", file);
fprintf(file, "\n;; *** Warning *** OS-type missing");
+ }
break;
case T_SOA:
@@ -563,12 +575,11 @@ __p_rr(cp, msg, file)
cp2 = cp1 + dlen;
while (cp < cp2) {
if (n = (unsigned char) *cp++) {
- for (c = n; c > 0 && cp < cp2; c--)
- if ((*cp == '\n') || (*cp == '"')) {
- (void) putc('\\', file);
- (void) putc(*cp++, file);
- } else
- (void) putc(*cp++, file);
+ for (c = n; c > 0 && cp < cp2; c--) {
+ if (strchr("\n\"\\", *cp))
+ (void) putc('\\', file);
+ (void) putc(*cp++, file);
+ }
}
}
putc('"', file);
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 5a10faa..d2c97d0 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -409,6 +409,7 @@ res_send(buf, buflen, ans, anssiz)
/*
* Receive length & response
*/
+read_len:
cp = ans;
len = INT16SZ;
while ((n = read(s, (char *)cp, (int)len)) > 0) {
@@ -477,6 +478,20 @@ res_send(buf, buflen, ans, anssiz)
break;
}
}
+ /*
+ * The calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused. Anyway drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((_res.options & RES_DEBUG) ||
+ (_res.pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen>anssiz)?anssiz:resplen);
+ goto read_len;
+ }
} else {
/*
* Use datagrams.
@@ -593,6 +608,8 @@ res_send(buf, buflen, ans, anssiz)
n = select(s+1, &dsmask, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
Perror(stderr, "select", errno);
_res_close();
goto next_ns;
@@ -626,7 +643,7 @@ res_send(buf, buflen, ans, anssiz)
DprintQ((_res.options & RES_DEBUG) ||
(_res.pfcode & RES_PRF_REPLY),
(stdout, ";; old answer:\n"),
- ans, resplen);
+ ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
}
#if CHECK_SRVR_ADDR
@@ -640,7 +657,7 @@ res_send(buf, buflen, ans, anssiz)
DprintQ((_res.options & RES_DEBUG) ||
(_res.pfcode & RES_PRF_REPLY),
(stdout, ";; not our server:\n"),
- ans, resplen);
+ ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
}
#endif
@@ -655,7 +672,7 @@ res_send(buf, buflen, ans, anssiz)
DprintQ((_res.options & RES_DEBUG) ||
(_res.pfcode & RES_PRF_REPLY),
(stdout, ";; wrong query name:\n"),
- ans, resplen);
+ ans, (resplen>anssiz)?anssiz:resplen);
goto wait;
}
if (anhp->rcode == SERVFAIL ||
@@ -663,7 +680,7 @@ res_send(buf, buflen, ans, anssiz)
anhp->rcode == REFUSED) {
DprintQ(_res.options & RES_DEBUG,
(stdout, "server rejected query:\n"),
- ans, resplen);
+ ans, (resplen>anssiz)?anssiz:resplen);
badns |= (1 << ns);
_res_close();
/* don't retry if called from dig */
@@ -689,7 +706,7 @@ res_send(buf, buflen, ans, anssiz)
DprintQ((_res.options & RES_DEBUG) ||
(_res.pfcode & RES_PRF_REPLY),
(stdout, ""),
- ans, resplen);
+ ans, (resplen>anssiz)?anssiz:resplen);
/*
* If using virtual circuits, we assume that the first server
* is preferred over the rest (i.e. it is on the local
diff --git a/resolv/resolv.h b/resolv/resolv.h
index fb3de28..1a4a0de 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -78,7 +78,7 @@
* is new enough to contain a certain feature.
*/
-#define __RES 19951031
+#define __RES 19960229
/*
* Resolver configuration file.
@@ -184,6 +184,8 @@ typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns,
extern struct __res_state _res;
/* Private routines shared between libc/net, named, nslookup and others. */
+#define res_hnok __res_hnok
+#define dn_isvalid __dn_isvalid
#define dn_skipname __dn_skipname
#define fp_query __fp_query
#define fp_nquery __fp_nquery
@@ -203,6 +205,8 @@ extern struct __res_state _res;
#define res_nameinquery __res_nameinquery
#define res_queriesmatch __res_queriesmatch
__BEGIN_DECLS
+int __res_hnok __P((const char *));
+int __dn_isvalid __P((const char *));
int __dn_skipname __P((const u_char *, const u_char *));
void __fp_resstat __P((struct __res_state *, FILE *));
void __fp_query __P((const u_char *, FILE *));