diff options
author | peter <peter@FreeBSD.org> | 1995-08-20 20:03:06 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-08-20 20:03:06 +0000 |
commit | bbe6ab41603ea223c7c921bd48586ed795917870 (patch) | |
tree | 32821775fcd4108257c3d49593dadeb5a5f18b17 /lib | |
parent | 2dd1919d1c22bd3dc75ab1064352572d401b1ab9 (diff) | |
download | FreeBSD-src-bbe6ab41603ea223c7c921bd48586ed795917870.zip FreeBSD-src-bbe6ab41603ea223c7c921bd48586ed795917870.tar.gz |
Update the resolver part of libc to bind-4.9.3-beta24 level (from beta9p1)
Note that this was done by selective patching from diffs, to not conflict
with the 4.4bsd base code.. This was *not* a trivial task.. I have been
testing this code (apart from cosmetic changes) in my libc for a while now.
Obtained from: Paul Vixie <paul@vix.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libc/net/gethostbydns.c | 131 | ||||
-rw-r--r-- | lib/libc/net/herror.c | 17 | ||||
-rw-r--r-- | lib/libc/net/res_config.h | 7 | ||||
-rw-r--r-- | lib/libc/net/res_debug.c | 141 | ||||
-rw-r--r-- | lib/libc/net/res_init.c | 108 | ||||
-rw-r--r-- | lib/libc/net/res_mkquery.c | 21 | ||||
-rw-r--r-- | lib/libc/net/res_query.c | 67 | ||||
-rw-r--r-- | lib/libc/net/res_send.c | 142 |
9 files changed, 420 insertions, 215 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 4bcd682..a3eda64 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -3,6 +3,7 @@ # machine-independent net sources .PATH: ${.CURDIR}/${MACHINE}/net ${.CURDIR}/net +CFLAGS+= -I${.CURDIR}/net SRCS+= gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \ getproto.c getprotoent.c getprotoname.c getservbyname.c \ diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c index 6db04f9..cf3455a 100644 --- a/lib/libc/net/gethostbydns.c +++ b/lib/libc/net/gethostbydns.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: gethostbydns.c,v 1.3 1994/12/01 22:25:38 wollman Exp $"; +static char rcsid[] = "$Id: gethostbydns.c,v 1.4 1995/05/30 05:40:43 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -61,16 +61,16 @@ static char rcsid[] = "$Id: gethostbydns.c,v 1.3 1994/12/01 22:25:38 wollman Exp #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> + +#include <stdio.h> +#include <string.h> #include <netdb.h> #include <resolv.h> -#include <stdio.h> #include <ctype.h> #include <errno.h> -#include <string.h> #include <syslog.h> -#define BYADDR 0 -#define BYNAME 1 +#include <res_config.h> #define MAXALIASES 35 #define MAXADDRS 35 @@ -78,7 +78,7 @@ static char rcsid[] = "$Id: gethostbydns.c,v 1.3 1994/12/01 22:25:38 wollman Exp #define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ static const char AskedForGot[] = - "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; + "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; static char *h_addr_ptrs[MAXADDRS + 1]; @@ -87,8 +87,6 @@ static char *host_aliases[MAXALIASES]; static char hostbuf[8*1024]; static struct in_addr host_addr; static FILE *hostf = NULL; -static char hostaddr[MAXADDRS]; -static char *host_addrs[2]; static int stayopen = 0; #if PACKETSZ > 1024 @@ -109,6 +107,24 @@ typedef union { extern int h_errno; +#ifdef DEBUG +static void +dprintf(msg, num) + char *msg; + int num; +{ + if (_res.options & RES_DEBUG) { + int save = errno; + + printf(msg, num); + errno = save; + } +} +#else +# define dprintf(msg, num) /*nada*/ +#endif + + #ifdef RESOLVSORT static void addrsort(ap, num) @@ -122,7 +138,7 @@ addrsort(ap, num) p = ap; for (i = 0; i < num; i++, p++) { - for (j = 0 ; j < _res.nsort; j++) + for (j = 0 ; (unsigned)j < _res.nsort; j++) if (_res.sort_list[j].addr.s_addr == (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) break; @@ -240,7 +256,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype) cp += n; if (host.h_name && strcasecmp(host.h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"", + "gethostby*.gethostanswer: asked for \"%s\", got CNAME for \"%s\"", host.h_name, bp); continue; /* XXX - had_error++ ? */ } @@ -262,9 +278,12 @@ gethostanswer(answer, anslen, qname, qclass, qtype) continue; } if (type != qtype) { + /* CNAME->PTR should not cause a log message. */ + if (!(qtype == T_PTR && type == T_CNAME)) syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for type %d(%s), got %d(%s)", - qtype, qname, type, bp); + "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"", + qname, p_class(qclass), p_type(qtype), + p_type(type)); cp += n; continue; /* XXX - had_error++ ? */ } @@ -297,6 +316,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype) break; #else host.h_name = bp; + h_errno = NETDB_SUCCESS; return (&host); #endif case T_A: @@ -327,14 +347,13 @@ gethostanswer(answer, anslen, qname, qclass, qtype) bp += sizeof(align) - ((u_long)bp % sizeof(align)); if (bp + n >= &hostbuf[sizeof hostbuf]) { - if (_res.options & RES_DEBUG) - printf("size (%d) too big\n", n); + dprintf("size (%d) too big\n", n); had_error++; continue; } if (hap >= &h_addr_ptrs[MAXADDRS-1]) { - if (_res.options & RES_DEBUG && !toobig++) - printf("Too many addresses (%d)\n", + if (!toobig++) + dprintf("Too many addresses (%d)\n", MAXADDRS); cp += n; continue; @@ -344,7 +363,9 @@ gethostanswer(answer, anslen, qname, qclass, qtype) cp += n; break; default: - abort(); + dprintf("Impossible condition (type=%d)\n", type); + h_errno = NO_RECOVERY; + return (NULL); } /*switch*/ if (!had_error) haveanswer++; @@ -367,6 +388,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype) strcpy(bp, qname); host.h_name = bp; } + h_errno = NETDB_SUCCESS; return (&host); } else { h_errno = TRY_AGAIN; @@ -382,6 +404,19 @@ _gethostbydnsname(name) register const char *cp; int n; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = __hostalias(name))) + name = cp; + /* * disallow names consisting only of digits/dots, unless * they end in a dot. @@ -400,7 +435,9 @@ _gethostbydnsname(name) h_errno = HOST_NOT_FOUND; return (NULL); } - host.h_name = (char *)name; + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + host.h_name = hostbuf; host.h_aliases = host_aliases; host_aliases[0] = NULL; host.h_addrtype = AF_INET; @@ -415,8 +452,7 @@ _gethostbydnsname(name) } if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { - if (_res.options & RES_DEBUG) - printf("res_search failed\n"); + dprintf("res_search failed (%d)\n", n); return (NULL); } return (gethostanswer(&buf, n, name, C_IN, T_A)); @@ -431,33 +467,70 @@ _gethostbydnsaddr(addr, len, type) querybuf buf; register struct hostent *hp; char qbuf[MAXDNAME+1]; - int o_res_options = _res.options; +#ifdef SUNSECURITY + register struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; +#endif /*SUNSECURITY*/ - if (type != AF_INET) + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (NULL); + } + if (type != AF_INET) { + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; return (NULL); + } (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", ((unsigned)addr[3] & 0xff), ((unsigned)addr[2] & 0xff), ((unsigned)addr[1] & 0xff), ((unsigned)addr[0] & 0xff)); - _res.options |= RES_RECURSE; n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); - _res.options = o_res_options; if (n < 0) { - if (_res.options & RES_DEBUG) - printf("res_query failed\n"); + dprintf("res_query failed (%d)\n", n); return (NULL); } if (!(hp = gethostanswer(&buf, n, qbuf, C_IN, T_PTR))) + return (NULL); /* h_errno was set by gethostanswer() */ +#ifdef SUNSECURITY + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = _res.options; + _res.options &= ~RES_DNSRCH; + _res.options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hname2))) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: No A record for %s (verifying [%s])", + hname2, inet_ntoa(*((struct in_addr *)addr))); + _res.options = old_options; + h_errno = HOST_NOT_FOUND; return (NULL); + } + _res.options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: A record of %s != PTR record [%s]", + hname2, inet_ntoa(*((struct in_addr *)addr))); + h_errno = HOST_NOT_FOUND; + return (NULL); + } +#endif /*SUNSECURITY*/ hp->h_addrtype = type; hp->h_length = len; h_addr_ptrs[0] = (char *)&host_addr; h_addr_ptrs[1] = NULL; host_addr = *(struct in_addr *)addr; -#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */ - hp->h_addr = h_addr_ptrs[0]; -#endif + h_errno = NETDB_SUCCESS; return (hp); } diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c index c9135c3..9b94ee4 100644 --- a/lib/libc/net/herror.c +++ b/lib/libc/net/herror.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: herror.c,v 1.1.1.1 1994/05/27 04:57:15 rgrimes Exp $"; +static char rcsid[] = "$Id: herror.c,v 1.2 1995/05/30 05:40:49 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> @@ -62,8 +62,8 @@ static char rcsid[] = "$Id: herror.c,v 1.1.1.1 1994/05/27 04:57:15 rgrimes Exp $ #include <unistd.h> #include <string.h> -char *h_errlist[] = { - "Error 0", +const char *h_errlist[] = { + "Resolver Error 0 (no error)", "Unknown host", /* 1 HOST_NOT_FOUND */ "Host name lookup failure", /* 2 TRY_AGAIN */ "Unknown server error", /* 3 NO_RECOVERY */ @@ -92,8 +92,7 @@ herror(s) v->iov_len = 2; v++; } - v->iov_base = (u_int)h_errno < h_nerr ? - h_errlist[h_errno] : "Unknown error"; + v->iov_base = (char *)hstrerror(h_errno); v->iov_len = strlen(v->iov_base); v++; v->iov_base = "\n"; @@ -101,9 +100,13 @@ herror(s) writev(STDERR_FILENO, iov, (v - iov) + 1); } -char * +const char * hstrerror(err) int err; { - return (u_int)err < h_nerr ? h_errlist[err] : "Unknown resolver error"; + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); } diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h new file mode 100644 index 0000000..3afa321 --- /dev/null +++ b/lib/libc/net/res_config.h @@ -0,0 +1,7 @@ +#define DEBUG /* enable debugging code (needed for dig) */ +#undef ALLOW_T_UNSPEC /* enable the "unspec" RR type for old athena */ +#define RESOLVSORT /* allow sorting of addresses in gethostbyname */ +#undef RFC1535 /* comply with RFC1535 */ +#undef ALLOW_UPDATES /* destroy your system security */ +#undef USELOOPBACK /* res_init() bind to localhost */ +#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */ diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c index 78b11c9..550f552 100644 --- a/lib/libc/net/res_debug.c +++ b/lib/libc/net/res_debug.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_debug.c,v 1.2 1994/09/25 02:12:34 pst Exp $"; +static char rcsid[] = "$Id: res_debug.c,v 1.3 1995/05/30 05:40:54 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -65,13 +65,17 @@ static char rcsid[] = "$Id: res_debug.c,v 1.2 1994/09/25 02:12:34 pst Exp $"; #include <stdio.h> #include <resolv.h> #include <string.h> +#include <netdb.h> + +#include <res_config.h> + const char *_res_opcodes[] = { "QUERY", "IQUERY", "CQUERYM", - "CQUERYU", - "4", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ "5", "6", "7", @@ -104,12 +108,13 @@ const char *_res_resultcodes[] = { "NOCHANGE", }; -static char retbuf[16]; - +/* XXX: we should use getservbyport() instead. */ static const char * dewks(wks) int wks; { + static char nbuf[20]; + switch (wks) { case 5: return "rje"; case 7: return "echo"; @@ -157,14 +162,17 @@ dewks(wks) case 161: return "snmp"; case 162: return "snmp-trap"; case 170: return "print-srv"; - default: (void) sprintf(retbuf, "%d", wks); return (retbuf); + default: (void) sprintf(nbuf, "%d", wks); return (nbuf); } } +/* XXX: we should use getprotobynumber() instead. */ static const char * deproto(protonum) int protonum; { + static char nbuf[20]; + switch (protonum) { case 1: return "icmp"; case 2: return "igmp"; @@ -178,13 +186,13 @@ deproto(protonum) case 12: return "pup"; case 16: return "chaos"; case 17: return "udp"; - default: (void) sprintf(retbuf, "%d", protonum); return (retbuf); + default: (void) sprintf(nbuf, "%d", protonum); return (nbuf); } } static const u_char * -do_rrset(msg, cp, cnt, pflag, file, hs) - int cnt, pflag; +do_rrset(msg, len, cp, cnt, pflag, file, hs) + int cnt, pflag, len; const u_char *cp, *msg; const char *hs; FILE *file; @@ -201,8 +209,19 @@ do_rrset(msg, cp, cnt, pflag, file, hs) ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) fprintf(file, hs); while (--n >= 0) { + if ((!_res.pfcode) || sflag) { cp = p_rr(cp, msg, file); - if ((cp - msg) > PACKETSZ) + } else { + unsigned int dlen; + cp += __dn_skipname(cp, cp + MAXCDNAME); + cp += INT16SZ; + cp += INT16SZ; + cp += INT32SZ; + dlen = _getshort((u_char*)cp); + cp += INT16SZ; + cp += dlen; + } + if ((cp - msg) > len) return (NULL); } if ((!_res.pfcode) || @@ -253,6 +272,9 @@ __fp_nquery(msg, len, file) register const HEADER *hp; register int n; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + #define TruncTest(x) if (x >= endMark) goto trunc #define ErrorTest(x) if (x == NULL) goto error @@ -282,8 +304,6 @@ __fp_nquery(msg, len, file) fprintf(file, " rd"); if (hp->ra) fprintf(file, " ra"); - if (hp->pr) - fprintf(file, " pr"); } if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); @@ -304,7 +324,7 @@ __fp_nquery(msg, len, file) while (--n >= 0) { fprintf(file,";;\t"); TruncTest(cp); - cp = p_cdname(cp, msg, file); + cp = p_cdnname(cp, msg, len, file); ErrorTest(cp); TruncTest(cp); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) @@ -323,7 +343,7 @@ __fp_nquery(msg, len, file) * Print authoritative answer records */ TruncTest(cp); - cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, + cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file, ";; ANSWERS:\n"); ErrorTest(cp); @@ -331,7 +351,7 @@ __fp_nquery(msg, len, file) * print name server records */ TruncTest(cp); - cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, + cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file, ";; AUTHORITY RECORDS:\n"); ErrorTest(cp); @@ -339,7 +359,7 @@ __fp_nquery(msg, len, file) /* * print additional records */ - cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, + cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file, ";; ADDITIONAL RECORDS:\n"); ErrorTest(cp); return; @@ -393,7 +413,7 @@ __p_fqname(cp, msg, file) FILE *file; { char name[MAXDNAME]; - int n, len; + int n; if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0) return (NULL); @@ -422,6 +442,10 @@ __p_rr(cp, msg, file) u_int32_t tmpttl, t; int lcnt; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (NULL); + } if ((cp = p_fqname(cp, msg, file)) == NULL) return (NULL); /* compression error */ type = _getshort((u_char*)cp); @@ -434,7 +458,7 @@ __p_rr(cp, msg, file) cp += INT16SZ; cp1 = cp; if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) - fprintf(file, "\t%lu", tmpttl); + fprintf(file, "\t%lu", (u_long)tmpttl); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) fprintf(file, "\t%s", __p_class(class)); fprintf(file, "\t%s", __p_type(type)); @@ -476,37 +500,46 @@ __p_rr(cp, msg, file) case T_NS: case T_PTR: putc('\t', file); - cp = p_fqname(cp, msg, file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); break; case T_HINFO: case T_ISDN: + cp2 = cp + dlen; if (n = *cp++) { fprintf(file,"\t%.*s", n, cp); cp += n; } - if (n = *cp++) { + if ((cp < cp2) && (n = *cp++)) { fprintf(file,"\t%.*s", n, cp); cp += n; - } + } else if (type == T_HINFO) + fprintf(file, "\n;; *** Warning *** OS-type missing"); break; case T_SOA: putc('\t', file); - cp = p_fqname(cp, msg, file); /* origin */ + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); putc(' ', file); - cp = p_fqname(cp, msg, file); /* mail addr */ + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); fputs(" (\n", file); t = _getlong((u_char*)cp); cp += INT32SZ; - fprintf(file,"\t\t\t%lu\t; serial\n", t); + fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t); t = _getlong((u_char*)cp); cp += INT32SZ; - fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); + fprintf(file, "\t\t\t%lu\t; refresh (%s)\n", + (u_long)t, __p_time(t)); t = _getlong((u_char*)cp); cp += INT32SZ; - fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); + fprintf(file, "\t\t\t%lu\t; retry (%s)\n", + (u_long)t, __p_time(t)); t = _getlong((u_char*)cp); cp += INT32SZ; - fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); + fprintf(file, "\t\t\t%lu\t; expire (%s)\n", + (u_long)t, __p_time(t)); t = _getlong((u_char*)cp); cp += INT32SZ; - fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); + fprintf(file, "\t\t\t%lu )\t; minimum (%s)", + (u_long)t, __p_time(t)); break; case T_MX: @@ -514,7 +547,18 @@ __p_rr(cp, msg, file) case T_RT: fprintf(file,"\t%d ", _getshort((u_char*)cp)); cp += INT16SZ; - cp = p_fqname(cp, msg, file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_PX: + fprintf(file, "\t%d ", _getshort((u_char*)cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); break; case T_TXT: @@ -524,7 +568,7 @@ __p_rr(cp, msg, file) while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) - if (*cp == '\n') { + if ((*cp == '\n') || (*cp == '"')) { (void) putc('\\', file); (void) putc(*cp++, file); } else @@ -546,9 +590,11 @@ __p_rr(cp, msg, file) case T_MINFO: case T_RP: putc('\t', file); - cp = p_fqname(cp, msg, file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); putc(' ', file); - cp = p_fqname(cp, msg, file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); break; case T_UINFO: @@ -628,8 +674,6 @@ __p_rr(cp, msg, file) return (cp); } -static char nbuf[40]; - /* * Return a string for the type */ @@ -637,6 +681,8 @@ const char * __p_type(type) int type; { + static char nbuf[20]; + switch (type) { case T_A: return "A"; case T_NS: return "NS"; @@ -652,12 +698,19 @@ __p_type(type) case T_MINFO: return "MINFO"; case T_MX: return "MX"; case T_TXT: return "TXT"; - case T_NSAP: return "NSAP"; case T_RP: return "RP"; case T_AFSDB: return "AFSDB"; case T_X25: return "X25"; case T_ISDN: return "ISDN"; case T_RT: return "RT"; + case T_NSAP: return "NSAP"; + case T_NSAP_PTR: return "NSAP_PTR"; + case T_SIG: return "SIG"; + case T_KEY: return "KEY"; + case T_PX: return "PX"; + case T_GPOS: return "GPOS"; + case T_AAAA: return "AAAA"; + case T_LOC: return "LOC"; case T_AXFR: return "AXFR"; case T_MAILB: return "MAILB"; case T_MAILA: return "MAILA"; @@ -679,10 +732,12 @@ const char * __p_class(class) int class; { + static char nbuf[20]; + switch (class) { - case C_IN: return("IN"); - case C_HS: return("HS"); - case C_ANY: return("ANY"); + case C_IN: return "IN"; + case C_HS: return "HS"; + case C_ANY: return "ANY"; default: (void)sprintf(nbuf, "%d", class); return (nbuf); } } @@ -694,12 +749,14 @@ const char * __p_option(option) u_long option; { + static char nbuf[40]; + switch (option) { case RES_INIT: return "init"; case RES_DEBUG: return "debug"; - case RES_AAONLY: return "aaonly"; + case RES_AAONLY: return "aaonly(unimpl)"; case RES_USEVC: return "usevc"; - case RES_PRIMARY: return "primry"; + case RES_PRIMARY: return "primry(unimpl)"; case RES_IGNTC: return "igntc"; case RES_RECURSE: return "recurs"; case RES_DEFNAMES: return "defnam"; @@ -707,7 +764,8 @@ __p_option(option) case RES_DNSRCH: return "dnsrch"; case RES_INSECURE1: return "insecure1"; case RES_INSECURE2: return "insecure2"; - default: sprintf(nbuf, "?0x%x?", option); return nbuf; + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); } } @@ -718,6 +776,7 @@ char * __p_time(value) u_int32_t value; { + static char nbuf[40]; int secs, mins, hours, days; register char *p; diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index 347e5b6..c6292c8 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -53,11 +53,12 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id: res_init.c,v 1.3 1994/09/25 17:45:39 pst Exp $"; +static char rcsid[] = "$Id: res_init.c,v 1.4 1995/05/30 05:40:55 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> #include <sys/socket.h> +#include <sys/time.h> #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> @@ -69,9 +70,13 @@ static char rcsid[] = "$Id: res_init.c,v 1.3 1994/09/25 17:45:39 pst Exp $"; #include <stdlib.h> #include <string.h> +#include <res_config.h> + static void res_setoptions __P((char *, char *)); #ifdef RESOLVSORT +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) static u_int32_t net_mask __P((struct in_addr)); #endif @@ -102,11 +107,12 @@ struct __res_state _res; * * Return 0 if completes successfully, -1 on error */ +int res_init() { register FILE *fp; register char *cp, **pp; - register int n, dots; + register int n; char buf[BUFSIZ]; int nserv = 0; /* number of nameserver records read from file */ int haveenv = 0; @@ -115,9 +121,12 @@ res_init() int nsort = 0; char *net; #endif +#ifndef RFC1535 + int dots; +#endif /* - * These four fields used to be statically initialized. This made + * These three fields used to be statically initialized. This made * it hard to use this code in a shared library. It is necessary, * now that we're doing dynamic initialization here, that we preserve * the old semantics: if an application modifies one of these three @@ -128,14 +137,27 @@ res_init() * will follow. Zero for any of these fields would make no sense, * so one can safely assume that the applications were already getting * unexpected results. + * + * _res.options is tricky since some apps were known to diddle the bits + * before res_init() was first called. We can't replicate that semantic + * with dynamic initialization (they may have turned bits off that are + * set in RES_DEFAULT). Our solution is to declare such applications + * "broken". They could fool us by setting RES_INIT but none do (yet). */ if (!_res.retrans) _res.retrans = RES_TIMEOUT; if (!_res.retry) _res.retry = 4; - if (!_res.options) + if (!(_res.options & RES_INIT)) _res.options = RES_DEFAULT; + /* + * This one used to initialize implicitly to zero, so unless the app + * has set it to something in particular, we can randomize it now. + */ + if (!_res.id) + _res.id = res_randomid(); + #ifdef USELOOPBACK _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); #else @@ -181,14 +203,19 @@ res_init() *pp++ = 0; } +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { /* read the config file */ while (fgets(buf, sizeof(buf), fp) != NULL) { /* skip comments */ - if ((*buf == ';') || (*buf == '#')) + if (*buf == ';' || *buf == '#') continue; /* read default domain name */ - if (!strncmp(buf, "domain", sizeof("domain") - 1)) { + if (MATCH(buf, "domain")) { if (haveenv) /* skip if have from environ */ continue; cp = buf + sizeof("domain") - 1; @@ -204,7 +231,7 @@ res_init() continue; } /* set search list */ - if (!strncmp(buf, "search", sizeof("search") - 1)) { + if (MATCH(buf, "search")) { if (haveenv) /* skip if have from environ */ continue; cp = buf + sizeof("search") - 1; @@ -223,9 +250,7 @@ res_init() cp = _res.defdname; pp = _res.dnsrch; *pp++ = cp; - for (n = 0; - *cp && pp < _res.dnsrch + MAXDNSRCH; - cp++) { + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; @@ -243,8 +268,7 @@ res_init() continue; } /* read nameservers to query */ - if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) && - nserv < MAXNS) { + if (MATCH(buf, "nameserver") && nserv < MAXNS) { struct in_addr a; cp = buf + sizeof("nameserver") - 1; @@ -260,7 +284,7 @@ res_init() continue; } #ifdef RESOLVSORT - if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) { + if (MATCH(buf, "sortlist")) { struct in_addr a; cp = buf + sizeof("sortlist") - 1; @@ -270,17 +294,18 @@ res_init() if (*cp == '\0' || *cp == '\n' || *cp == ';') break; net = cp; - while (*cp && *cp != '/' && + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && isascii(*cp) && !isspace(*cp)) cp++; n = *cp; *cp = 0; if (inet_aton(net, &a)) { _res.sort_list[nsort].addr = a; - if (n == '/') { + if (ISSORTMASK(n)) { *cp++ = n; net = cp; - while (*cp && isascii(*cp) && !isspace(*cp)) + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) cp++; n = *cp; *cp = 0; @@ -296,12 +321,12 @@ res_init() } nsort++; } - *cp++ = n; + *cp = n; } continue; } #endif - if (!strncmp(buf, "options", sizeof("options") -1)) { + if (MATCH(buf, "options")) { res_setoptions(buf + sizeof("options") - 1, "conf"); continue; } @@ -312,13 +337,11 @@ res_init() _res.nsort = nsort; #endif (void) fclose(fp); - } /*if(fopen)*/ - if (_res.defdname[0] == 0) { - if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && - (cp = strchr(buf, '.'))) { - (void)strcpy(_res.defdname, cp + 1); - } } + if (_res.defdname[0] == 0 && + gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(_res.defdname, cp + 1); /* find components of local domain that might be searched */ if (havesearch == 0) { @@ -333,32 +356,30 @@ res_init() cp = _res.defdname; while (pp < _res.dnsrch + MAXDFLSRCH) { - if (dots < LOCALDOMAINPARTS) { + if (dots < LOCALDOMAINPARTS) break; - } cp = strchr(cp, '.') + 1; /* we know there is one */ *pp++ = cp; dots--; } *pp = NULL; +#ifdef DEBUG if (_res.options & RES_DEBUG) { printf(";; res_init()... default dnsrch list:\n"); - for (pp = _res.dnsrch; *pp; pp++) { + for (pp = _res.dnsrch; *pp; pp++) printf(";;\t%s\n", *pp); - } printf(";;\t..END..\n"); } +#endif /* DEBUG */ #endif /*!RFC1535*/ } - if ((cp = getenv("RES_OPTIONS")) != NULL) { + if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(cp, "env"); - } _res.options |= RES_INIT; return (0); } - static void res_setoptions(options, source) char *options, *source; @@ -366,10 +387,11 @@ res_setoptions(options, source) char *cp = options; int i; - if (_res.options & RES_DEBUG) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) printf(";; res_setoptions(\"%s\", \"%s\")...\n", options, source); - } +#endif while (*cp) { /* skip leading and inner runs of spaces */ while (*cp == ' ' || *cp == '\t') @@ -381,16 +403,19 @@ res_setoptions(options, source) _res.ndots = i; else _res.ndots = RES_MAXNDOTS; - if (_res.options & RES_DEBUG) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) printf(";;\tndots=%d\n", _res.ndots); - } +#endif } else if (!strncmp(cp, "debug", sizeof("debug")-1)) { +#ifdef DEBUG if (!(_res.options & RES_DEBUG)) { printf(";; res_setoptions(\"%s\", \"%s\")..\n", options, source); _res.options |= RES_DEBUG; } printf(";;\tdebug\n"); +#endif } else { /* XXX - print a warning here? */ } @@ -401,6 +426,7 @@ res_setoptions(options, source) } #ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ static u_int32_t net_mask(in) /* XXX - should really use system's version of this */ struct in_addr in; @@ -411,7 +437,15 @@ net_mask(in) /* XXX - should really use system's version of this */ return (htonl(IN_CLASSA_NET)); else if (IN_CLASSB(i)) return (htonl(IN_CLASSB_NET)); - else - return (htonl(IN_CLASSC_NET)); + return (htonl(IN_CLASSC_NET)); } #endif + +u_int16_t +res_randomid() +{ + struct timeval now; + + gettimeofday(&now, NULL); + return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); +} diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c index 7788d16..979abbd 100644 --- a/lib/libc/net/res_mkquery.c +++ b/lib/libc/net/res_mkquery.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_mkquery.c,v 1.3 1994/09/25 17:45:39 pst Exp $"; +static char rcsid[] = "$Id: res_mkquery.c,v 1.4 1995/05/30 05:40:56 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -63,6 +63,10 @@ static char rcsid[] = "$Id: res_mkquery.c,v 1.3 1994/09/25 17:45:39 pst Exp $"; #include <stdio.h> #include <resolv.h> #include <string.h> +#include <netdb.h> + +#include <res_config.h> + /* * Form all types of queries. @@ -82,12 +86,20 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) register HEADER *hp; register u_char *cp; register int n; +#ifdef ALLOW_UPDATES struct rrec *newrr = (struct rrec *) newrr_in; +#endif u_char *dnptrs[20], **dpp, **lastdnptr; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type); +#endif /* * Initialize header fields. */ @@ -97,7 +109,6 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) hp = (HEADER *) buf; hp->id = htons(++_res.id); hp->opcode = op; - hp->pr = (_res.options & RES_PRIMARY) != 0; hp->rd = (_res.options & RES_RECURSE) != 0; hp->rcode = NOERROR; cp = buf + HFIXEDSZ; @@ -110,7 +121,8 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) * perform opcode specific processing */ switch (op) { - case QUERY: + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: if ((buflen -= QFIXEDSZ) < 0) return(-1); if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) @@ -222,8 +234,9 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) } hp->ancount = htons(0); break; - #endif /* ALLOW_UPDATES */ + default: + return (-1); } return (cp - buf); } diff --git a/lib/libc/net/res_query.c b/lib/libc/net/res_query.c index ed923eb..33d87f2 100644 --- a/lib/libc/net/res_query.c +++ b/lib/libc/net/res_query.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_query.c,v 1.3 1994/09/25 17:45:40 pst Exp $"; +static char rcsid[] = "$Id: res_query.c,v 1.4 1995/05/30 05:40:57 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -66,16 +66,10 @@ static char rcsid[] = "$Id: res_query.c,v 1.3 1994/09/25 17:45:40 pst Exp $"; #include <resolv.h> #include <ctype.h> #include <errno.h> -#if defined(BSD) && (BSD >= 199306) -# include <stdlib.h> -# include <string.h> -#else -# include "../conf/portability.h" -#endif +#include <stdlib.h> +#include <string.h> -#if defined(USE_OPTIONS_H) -# include <../conf/options.h> -#endif +#include <res_config.h> #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ @@ -109,31 +103,41 @@ res_query(name, class, type, answer, anslen) hp->rcode = NOERROR; /* default */ - if ((_res.options & RES_INIT) == 0 && res_init() == -1) + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; return (-1); + } +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, buf, sizeof(buf)); if (n <= 0) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: mkquery failed\n"); +#endif h_errno = NO_RECOVERY; return (n); } n = res_send(buf, n, answer, anslen); if (n < 0) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_query: send error\n"); +#endif h_errno = TRY_AGAIN; return (n); } if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; rcode = %d, ancount=%d\n", hp->rcode, ntohs(hp->ancount)); +#endif switch (hp->rcode) { case NXDOMAIN: h_errno = HOST_NOT_FOUND; @@ -175,22 +179,23 @@ res_search(name, class, type, answer, anslen) int trailing_dot, ret, saved_herrno; int got_nodata = 0, got_servfail = 0, tried_as_is = 0; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; return (-1); - + } errno = 0; h_errno = HOST_NOT_FOUND; /* default, if we never query */ dots = 0; for (cp = name; *cp; cp++) dots += (*cp == '.'); trailing_dot = 0; - if ((cp > name) && (*--cp == '.')) + if (cp > name && *--cp == '.') trailing_dot++; /* * if there aren't any dots, it could be a user-level alias */ - if ((!dots) && (cp = __hostalias(name))) + if (!dots && (cp = __hostalias(name)) != NULL) return (res_query(cp, class, type, answer, anslen)); /* @@ -212,9 +217,8 @@ res_search(name, class, type, answer, anslen) * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ - if (((!dots) && _res.options & RES_DEFNAMES) || - (dots && (!trailing_dot) && _res.options & RES_DNSRCH) - ) { + if ((!dots && (_res.options & RES_DEFNAMES)) || + (dots && !trailing_dot && (_res.options & RES_DNSRCH))) { int done = 0; for (domain = (const char * const *)_res.dnsrch; @@ -279,7 +283,6 @@ res_search(name, class, type, answer, anslen) ret = res_querydomain(name, NULL, class, type, answer, anslen); if (ret > 0) return (ret); - saved_herrno = h_errno; } /* if we got here, we didn't satisfy the search. @@ -313,9 +316,15 @@ res_querydomain(name, domain, class, type, answer, anslen) const char *longname = nbuf; int n; + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG if (_res.options & RES_DEBUG) printf(";; res_querydomain(%s, %s, %d, %d)\n", name, domain?domain:"<Nil>", class, type); +#endif if (domain == NULL) { /* * Check for trailing '.'; @@ -327,10 +336,8 @@ res_querydomain(name, domain, class, type, answer, anslen) nbuf[n] = '\0'; } else longname = name; - } else { - sprintf(nbuf, "%.*s.%.*s", - MAXDNAME, name, MAXDNAME, domain); - } + } else + sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); return (res_query(longname, class, type, answer, anslen)); } @@ -345,22 +352,28 @@ __hostalias(name) char buf[BUFSIZ]; static char abuf[MAXDNAME]; + if (_res.options & RES_NOALIASES) + return (NULL); file = getenv("HOSTALIASES"); if (file == NULL || (fp = fopen(file, "r")) == NULL) return (NULL); + setbuf(fp, NULL); buf[sizeof(buf) - 1] = '\0'; while (fgets(buf, sizeof(buf), fp)) { - for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); + for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1) + ; if (!*cp1) break; *cp1 = '\0'; if (!strcasecmp(buf, name)) { - while (isspace(*++cp1)); + while (isspace(*++cp1)) + ; if (!*cp1) break; - for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); + for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) + ; abuf[sizeof(abuf) - 1] = *cp2 = '\0'; - (void)strncpy(abuf, cp1, sizeof(abuf) - 1); + strncpy(abuf, cp1, sizeof(abuf) - 1); fclose(fp); return (abuf); } diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index 8ee0a92..d5c9c28 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_send.c,v 1.3 1994/09/25 17:45:41 pst Exp $"; +static char rcsid[] = "$Id: res_send.c,v 1.4 1995/05/30 05:40:58 rgrimes Exp $"; #endif /* LIBC_SCCS and not lint */ /* change this to "0" @@ -61,7 +61,7 @@ static char rcsid[] = "$Id: res_send.c,v 1.3 1994/09/25 17:45:41 pst Exp $"; * of multi-homed SunOS * ("broken") name servers. */ -#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */ +#define CHECK_SRVR_ADDR 1 /* XXX - should be in res_config.h */ /* * Send query to name server and wait for reply. @@ -78,8 +78,12 @@ static char rcsid[] = "$Id: res_send.c,v 1.3 1994/09/25 17:45:41 pst Exp $"; #include <stdio.h> #include <errno.h> #include <resolv.h> +#include <netdb.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> + +#include <res_config.h> void _res_close __P((void)); @@ -87,12 +91,17 @@ static int s = -1; /* socket used for communications */ static int connected = 0; /* is the socket connected */ static int vc = 0; /* is the socket a virtual ciruit? */ +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query, size) /*empty*/ +# define Aerror(file, string, error, address) /*empty*/ +# define Perror(file, string, error) /*empty*/ +#else # define Dprint(cond, args) if (cond) {fprintf args;} else {} -# define DprintQ(cond, args, query) if (cond) {\ +# define DprintQ(cond, args, query, size) if (cond) {\ fprintf args;\ - __p_query(query);\ + __fp_nquery(query, size, stdout);\ } else {} - static void Aerror(file, string, error, address) FILE *file; @@ -103,15 +112,14 @@ Aerror(file, string, error, address) int save = errno; if (_res.options & RES_DEBUG) { - fprintf(file, "res_send: %s ([%s].%d): %s\n", + fprintf(file, "res_send: %s ([%s].%u): %s\n", string, inet_ntoa(address.sin_addr), - address.sin_port, + ntohs(address.sin_port), strerror(error)); } errno = save; } - static void Perror(file, string, error) FILE *file; @@ -126,6 +134,7 @@ Perror(file, string, error) } errno = save; } +#endif static res_send_qhook Qhook = NULL; static res_send_rhook Rhook = NULL; @@ -134,6 +143,7 @@ void res_send_setqhook(hook) res_send_qhook hook; { + Qhook = hook; } @@ -141,11 +151,12 @@ void res_send_setrhook(hook) res_send_rhook hook; { + Rhook = hook; } /* int - * our_server(ina) + * res_isourserver(ina) * looks up "ina" in _res.ns_addr_list[] * returns: * 0 : not found @@ -153,8 +164,8 @@ res_send_setrhook(hook) * author: * paul vixie, 29may94 */ -static int -our_server(inp) +int +res_isourserver(inp) const struct sockaddr_in *inp; { struct sockaddr_in ina; @@ -177,15 +188,17 @@ our_server(inp) } /* int - * name_in_query(name, type, class, buf, eom) + * res_nameinquery(name, type, class, buf, eom) * look for (name,type,class) in the query section of packet (buf,eom) * returns: * -1 : format error * 0 : not found * >0 : found + * author: + * paul vixie, 29may94 */ -static int -name_in_query(name, type, class, buf, eom) +int +res_nameinquery(name, type, class, buf, eom) const char *name; register int type, class; const u_char *buf, *eom; @@ -212,16 +225,18 @@ name_in_query(name, type, class, buf, eom) } /* int - * queries_match(buf1, eom1, buf2, eom2) + * res_queriesmatch(buf1, eom1, buf2, eom2) * is there a 1:1 mapping of (name,type,class) * in (buf1,eom1) and (buf2,eom2)? * returns: * -1 : format error * 0 : not a 1:1 mapping * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 */ -static int -queries_match(buf1, eom1, buf2, eom2) +int +res_queriesmatch(buf1, eom1, buf2, eom2) const u_char *buf1, *eom1; const u_char *buf2, *eom2; { @@ -240,7 +255,7 @@ queries_match(buf1, eom1, buf2, eom2) cp += n; ttype = _getshort(cp); cp += INT16SZ; tclass = _getshort(cp); cp += INT16SZ; - if (!name_in_query(tname, ttype, tclass, buf2, eom2)) + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) return (0); } return (1); @@ -255,21 +270,20 @@ res_send(buf, buflen, ans, anssiz) { HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) ans; - int gotsomewhere = 0, - connreset = 0, - terrno = ETIMEDOUT; - + int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; register int n; - int try, v_circuit, resplen, ns; u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ - DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), - (stdout, ";; res_send()\n"), buf); - if (!(_res.options & RES_INIT)) { - if (res_init() == -1) + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ return (-1); } + DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf, buflen); v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + connreset = 0; + terrno = ETIMEDOUT; badns = 0; /* @@ -290,12 +304,8 @@ res_send(buf, buflen, ans, anssiz) do { res_sendhookact act; - act = (*Qhook)(&nsap, - &buf, - &buflen, - ans, - anssiz, - &resplen); + act = (*Qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); switch (act) { case res_goahead: done = 1; @@ -338,16 +348,15 @@ res_send(buf, buflen, ans, anssiz) if (s >= 0) _res_close(); - s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC); + s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) { terrno = errno; Perror(stderr, "socket(vc)", errno); return (-1); } - if (connect(s, - (struct sockaddr *)nsap, - sizeof(struct sockaddr)) - < 0) { + errno = 0; + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr)) < 0) { terrno = errno; Aerror(stderr, "connect/vc", errno, *nsap); @@ -414,8 +423,7 @@ res_send(buf, buflen, ans, anssiz) len = resplen; cp = ans; while (len != 0 && - (n = read(s, (char *)cp, (int)len)) > 0 - ) { + (n = read(s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } @@ -433,7 +441,7 @@ res_send(buf, buflen, ans, anssiz) anhp->tc = 1; len = resplen - anssiz; while (len != 0) { - char junk[512]; + char junk[PACKETSZ]; n = (len > sizeof(junk) ? sizeof(junk) @@ -456,9 +464,9 @@ res_send(buf, buflen, ans, anssiz) if ((s < 0) || vc) { if (vc) _res_close(); - s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC); + s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { - bad_dg_sock: terrno = errno; + terrno = errno; Perror(stderr, "socket(dg)", errno); return (-1); } @@ -485,11 +493,9 @@ res_send(buf, buflen, ans, anssiz) * receive a response from another server. */ if (!connected) { - if (connect(s, - (struct sockaddr *)nsap, + if (connect(s, (struct sockaddr *)nsap, sizeof(struct sockaddr) - ) < 0 - ) { + ) < 0) { Aerror(stderr, "connect(dg)", errno, *nsap); @@ -499,7 +505,7 @@ res_send(buf, buflen, ans, anssiz) } connected = 1; } - if (send(s, buf, buflen, 0) != buflen) { + if (send(s, (char*)buf, buflen, 0) != buflen) { Perror(stderr, "send", errno); badns |= (1<<ns); _res_close(); @@ -523,7 +529,7 @@ res_send(buf, buflen, ans, anssiz) connected = 0; errno = 0; } - if (sendto(s, buf, buflen, 0, + if (sendto(s, (char*)buf, buflen, 0, (struct sockaddr *)nsap, sizeof(struct sockaddr)) != buflen) { @@ -558,14 +564,14 @@ res_send(buf, buflen, ans, anssiz) * timeout */ Dprint(_res.options & RES_DEBUG, - (stdout, ";; timeout\n") - ); + (stdout, ";; timeout\n")); gotsomewhere = 1; _res_close(); goto next_ns; } + errno = 0; fromlen = sizeof(struct sockaddr_in); - resplen = recvfrom(s, ans, anssiz, 0, + resplen = recvfrom(s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); @@ -582,12 +588,12 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; old answer:\n"), - ans); + ans, resplen); goto wait; } #if CHECK_SRVR_ADDR if (!(_res.options & RES_INSECURE1) && - !our_server(&from)) { + !res_isourserver(&from)) { /* * response from wrong server? ignore it. * XXX - potential security hazard could @@ -596,12 +602,12 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; not our server:\n"), - ans); + ans, resplen); goto wait; } #endif if (!(_res.options & RES_INSECURE2) && - !queries_match(buf, buf + buflen, + !res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) { /* * response contains wrong query? ignore it. @@ -611,7 +617,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; wrong query name:\n"), - ans); + ans, resplen); goto wait; } if (anhp->rcode == SERVFAIL || @@ -619,9 +625,11 @@ res_send(buf, buflen, ans, anssiz) anhp->rcode == REFUSED) { DprintQ(_res.options & RES_DEBUG, (stdout, "server rejected query:\n"), - ans); + ans, resplen); badns |= (1<<ns); _res_close(); + /* don't retry if called from dig */ + if (!_res.pfcode) goto next_ns; } if (!(_res.options & RES_IGNTC) && anhp->tc) { @@ -630,8 +638,7 @@ res_send(buf, buflen, ans, anssiz) * use TCP with same server. */ Dprint(_res.options & RES_DEBUG, - (stdout, ";; truncated answer\n") - ); + (stdout, ";; truncated answer\n")); v_circuit = 1; _res_close(); goto same_ns; @@ -640,7 +647,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; got answer:\n"), - ans); + ans, resplen); /* * If using virtual circuits, we assume that the first server * is preferred over the rest (i.e. it is on the local @@ -659,12 +666,8 @@ res_send(buf, buflen, ans, anssiz) do { res_sendhookact act; - act = (*Rhook)(nsap, - buf, - buflen, - ans, - anssiz, - &resplen); + act = (*Rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); switch (act) { case res_goahead: case res_done: @@ -691,14 +694,13 @@ res_send(buf, buflen, ans, anssiz) } /*foreach ns*/ } /*foreach retry*/ _res_close(); - if (!v_circuit) { + if (!v_circuit) if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ else errno = ETIMEDOUT; /* no answer obtained */ - } else { + else errno = terrno; - } return (-1); } |