about summary refs log tree commit diff
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 f72444abdd..c4233e2a85 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 41be4fc10d..6872be0b7e 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 3bc01addb6..32513cc387 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 fb47c30c99..7ec5607781 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 b2c911844e..fad2b8c0cd 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 822b621363..fd06e17bb4 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 1342205f28..f234772e41 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 b3dfcdf8f6..85ec628b89 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 5a10faa393..d2c97d0cd4 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 fb3de282b2..1a4a0dec89 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 *));