diff options
author | dm <dm@cvs.openbsd.org> | 1996-02-19 19:54:44 +0000 |
---|---|---|
committer | dm <dm@cvs.openbsd.org> | 1996-02-19 19:54:44 +0000 |
commit | 34dfcd3c571a64de57872aa758d1b228d7b22a02 (patch) | |
tree | 22b14dd50dff4fc41ec5c5f2ee3e20f4b7f1d141 /lib/libc/net | |
parent | d134390523f594c4e7f1b453b8026b993a1aeebb (diff) |
netbsd: bind 4.9.3
Diffstat (limited to 'lib/libc/net')
-rw-r--r-- | lib/libc/net/Makefile.inc | 8 | ||||
-rw-r--r-- | lib/libc/net/gethostnamadr.c | 2 | ||||
-rw-r--r-- | lib/libc/net/getnetbyname.c | 10 | ||||
-rw-r--r-- | lib/libc/net/getnetent.c | 25 | ||||
-rw-r--r-- | lib/libc/net/herror.c | 23 | ||||
-rw-r--r-- | lib/libc/net/inet_addr.c | 7 | ||||
-rw-r--r-- | lib/libc/net/nsap_addr.c | 130 | ||||
-rw-r--r-- | lib/libc/net/res_comp.c | 63 | ||||
-rw-r--r-- | lib/libc/net/res_debug.c | 513 | ||||
-rw-r--r-- | lib/libc/net/res_init.c | 32 | ||||
-rw-r--r-- | lib/libc/net/res_mkquery.c | 46 | ||||
-rw-r--r-- | lib/libc/net/res_query.c | 73 | ||||
-rw-r--r-- | lib/libc/net/res_send.c | 718 | ||||
-rw-r--r-- | lib/libc/net/resolver.3 | 3 | ||||
-rw-r--r-- | lib/libc/net/sethostent.c | 9 |
15 files changed, 1120 insertions, 542 deletions
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index 2d220067e40..054d9a74927 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -1,4 +1,4 @@ -# $NetBSD: Makefile.inc,v 1.23 1995/03/02 09:09:07 chopps Exp $ +# $NetBSD: Makefile.inc,v 1.24 1996/02/02 15:22:14 mrg Exp $ # @(#)Makefile.inc 8.2 (Berkeley) 9/5/93 # net sources @@ -8,9 +8,9 @@ SRCS+= gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ getproto.c getprotoent.c getprotoname.c getservbyname.c \ getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \ inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \ - iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \ - res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \ - send.c sethostent.c ethers.c + iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c nsap_addr.c rcmd.c recv.c \ + res_comp.c res_debug.c res_init.c res_mkquery.c res_query.c \ + res_send.c send.c sethostent.c ethers.c # machine-dependent net sources # m-d Makefile.inc must include sources for: diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index 2c0595803b7..ec3f14a9002 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -270,7 +270,6 @@ gethostbyname(name) register struct hostent *hp; char lookups[MAXDNSLUS]; -#ifdef insecure /* * disallow names consisting only of digits/dots, unless * they end in a dot. @@ -302,7 +301,6 @@ gethostbyname(name) if (!isdigit(*cp) && *cp != '.') break; } -#endif if ((_res.options & RES_INIT) == 0 && res_init() == -1) return (_gethtbyname(name)); diff --git a/lib/libc/net/getnetbyname.c b/lib/libc/net/getnetbyname.c index 93a2e1256cd..f660f79b20e 100644 --- a/lib/libc/net/getnetbyname.c +++ b/lib/libc/net/getnetbyname.c @@ -1,4 +1,4 @@ -/* $NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $ */ +/* $NetBSD: getnetbyname.c,v 1.5 1996/02/02 15:22:20 mrg Exp $ */ /* * Copyright (c) 1983, 1993 @@ -35,9 +35,11 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 +static char sccsid_[] = "from getnetbyname.c 1.1 (Coimbra) 93/06/02"; +static char rcsid[] = "=Id: getnetbyname.c,v 1.6 1994/05/31 01:49:35 vixie Exp ="; static char sccsid[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93"; #else -static char rcsid[] = "$NetBSD: getnetbyname.c,v 1.4 1995/02/25 06:20:31 cgd Exp $"; +static char rcsid[] = "$NetBSD: getnetbyname.c,v 1.5 1996/02/02 15:22:20 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -55,10 +57,10 @@ getnetbyname(name) setnetent(_net_stayopen); while (p = getnetent()) { - if (strcmp(p->n_name, name) == 0) + if (strcasecmp(p->n_name, name) == 0) break; for (cp = p->n_aliases; *cp != 0; cp++) - if (strcmp(*cp, name) == 0) + if (strcasecmp(*cp, name) == 0) goto found; } found: diff --git a/lib/libc/net/getnetent.c b/lib/libc/net/getnetent.c index 8ecdf6c5a36..2e897201a82 100644 --- a/lib/libc/net/getnetent.c +++ b/lib/libc/net/getnetent.c @@ -1,4 +1,4 @@ -/* $NetBSD: getnetent.c,v 1.5 1996/01/14 05:02:41 ghudson Exp $ */ +/* $NetBSD: getnetent.c,v 1.6 1996/02/02 15:22:21 mrg Exp $ */ /* * Copyright (c) 1983, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93"; #else -static char rcsid[] = "$NetBSD: getnetent.c,v 1.5 1996/01/14 05:02:41 ghudson Exp $"; +static char rcsid[] = "$NetBSD: getnetent.c,v 1.6 1996/02/02 15:22:21 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -109,19 +109,18 @@ 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; - } - if (q < &net_aliases[MAXALIASES - 1]) - *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) - *cp++ = '\0'; + 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'; } *q = NULL; return (&net); diff --git a/lib/libc/net/herror.c b/lib/libc/net/herror.c index 41adbf10554..f2d241385da 100644 --- a/lib/libc/net/herror.c +++ b/lib/libc/net/herror.c @@ -1,4 +1,4 @@ -/* $NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $ */ +/* $NetBSD: herror.c,v 1.6 1996/02/02 15:22:22 mrg Exp $ */ /*- * Copyright (c) 1987, 1993 @@ -56,9 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: herror.c,v 4.9.1.1 1993/05/02 23:14:35 vixie Rel "; +static char rcsid[] = "$Id: herror.c,v 8.2 1995/06/19 08:35:01 vixie Exp "; #else -static char rcsid[] = "$NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd Exp $"; +static char rcsid[] = "$NetBSD: herror.c,v 1.6 1996/02/02 15:22:22 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -68,14 +68,14 @@ static char rcsid[] = "$NetBSD: herror.c,v 1.5 1995/02/25 06:20:39 cgd 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 */ "No address associated with name", /* 4 NO_ADDRESS */ }; -int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; extern int h_errno; @@ -98,8 +98,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"; @@ -107,9 +106,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/inet_addr.c b/lib/libc/net/inet_addr.c index b5b9d8302fa..e527c6b384b 100644 --- a/lib/libc/net/inet_addr.c +++ b/lib/libc/net/inet_addr.c @@ -1,4 +1,4 @@ -/* $NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $ */ +/* $NetBSD: inet_addr.c,v 1.6 1996/02/02 15:22:23 mrg Exp $ */ /* * Copyright (c) 1983, 1990, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; #else -static char rcsid[] = "$NetBSD: inet_addr.c,v 1.5 1995/02/25 06:20:41 cgd Exp $"; +static char rcsid[] = "$NetBSD: inet_addr.c,v 1.6 1996/02/02 15:22:23 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -131,6 +131,9 @@ inet_aton(cp, addr) n = pp - parts + 1; switch (n) { + case 0: + return (0); /* initial nondigit */ + case 1: /* a -- 32 bits */ break; diff --git a/lib/libc/net/nsap_addr.c b/lib/libc/net/nsap_addr.c new file mode 100644 index 00000000000..e4583a3db80 --- /dev/null +++ b/lib/libc/net/nsap_addr.c @@ -0,0 +1,130 @@ +/* $NetBSD: nsap_addr.c,v 1.1 1996/02/02 15:22:24 mrg Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char rcsid[] = "$Id: lib-libc-net,v 8.1 1995/12/22 21:59:52 vixie Exp "; +#else +static char rcsid[] = "$NetBSD: nsap_addr.c,v 1.1 1996/02/02 15:22:24 mrg Exp $"; +#endif +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> + +static char +xtob(c) + register int c; +{ + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +/* These have to be here for BIND and its utilities (DiG, nslookup, et al) + * but should not be promulgated since the calling interface is not pretty. + * (They do, however, implement the RFC standard way of representing ISO NSAPs + * and as such, are preferred over the more general iso_addr.c routines. + */ + +u_int +inet_nsap_addr(ascii, binary, maxlen) + const char *ascii; + u_char *binary; + int maxlen; +{ + register u_char c, nib; + u_int len = 0; + + while ((c = *ascii++) != '\0' && len < maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + if (islower(c)) + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + if (c = *ascii++) { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(binlen, binary, ascii) + int binlen; + register const u_char *binary; + register char *ascii; +{ + register int nib; + int i; + static char tmpbuf[255*3]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c index 9d7bbecdda5..2d81327aafd 100644 --- a/lib/libc/net/res_comp.c +++ b/lib/libc/net/res_comp.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $ */ +/* $NetBSD: res_comp.c,v 1.7 1996/02/02 15:22:26 mrg Exp $ */ /*- * Copyright (c) 1985, 1993 @@ -56,9 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; +static char rcsid[] = "$Id: res_comp.c,v 8.3 1995/12/06 20:34:50 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $"; +static char rcsid[] = "$NetBSD: res_comp.c,v 1.7 1996/02/02 15:22:26 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -67,8 +67,11 @@ static char rcsid[] = "$NetBSD: res_comp.c,v 1.6 1995/02/25 06:20:55 cgd Exp $"; #include <netinet/in.h> #include <resolv.h> #include <stdio.h> +#include <ctype.h> +#include <unistd.h> +#include <string.h> -static int dn_find(); +static int dn_find __P((u_char *, u_char *, u_char **, u_char **)); /* * Expand compressed domain name 'comp_dn' to full domain name. @@ -77,18 +80,20 @@ static int dn_find(); * 'exp_dn' is a pointer to a buffer of size 'length' for the result. * Return size of compressed name or -1 if there was an error. */ +int dn_expand(msg, eomorig, comp_dn, exp_dn, length) const u_char *msg, *eomorig, *comp_dn; - u_char *exp_dn; + char *exp_dn; int length; { - register u_char *cp, *dn; + register const u_char *cp; + register char *dn; register int n, c; - u_char *eom; + char *eom; int len = -1, checked = 0; dn = exp_dn; - cp = (u_char *)comp_dn; + cp = comp_dn; eom = exp_dn + length; /* * fetch next label in domain name @@ -108,23 +113,23 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length) return (-1); checked += n + 1; while (--n >= 0) { - if ((c = *cp++) == '.') { + if ((c = *cp++) == '.' || c == '\\') { if (dn + n + 2 >= eom) return (-1); *dn++ = '\\'; } *dn++ = c; if (cp >= eomorig) /* out of range */ - return(-1); + return (-1); } break; case INDIR_MASK: if (len < 0) len = cp - comp_dn + 1; - cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff)); + cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); if (cp < msg || cp >= eomorig) /* out of range */ - return(-1); + return (-1); checked += 2; /* * Check for loops in the compressed name; @@ -140,6 +145,9 @@ 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); @@ -157,8 +165,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length) * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' * is NULL, we don't update the list. */ +int dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) - const u_char *exp_dn; + const char *exp_dn; u_char *comp_dn, **dnptrs, **lastdnptr; int length; { @@ -170,6 +179,7 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) dn = (u_char *)exp_dn; cp = comp_dn; eob = cp + length; + lpp = cpp = NULL; if (dnptrs != NULL) { if ((msg = *dnptrs++) != NULL) { for (cpp = dnptrs; *cpp != NULL; cpp++) @@ -235,13 +245,14 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) /* * Skip over a compressed domain name. Return the size or -1. */ +int __dn_skipname(comp_dn, eom) const u_char *comp_dn, *eom; { - register u_char *cp; + register const u_char *cp; register int n; - cp = (u_char *)comp_dn; + cp = comp_dn; while (cp < eom && (n = *cp++)) { /* * check for indirection @@ -263,6 +274,15 @@ __dn_skipname(comp_dn, eom) return (cp - comp_dn); } +static int +mklower(ch) + register int ch; +{ + if (isascii(ch) && isupper(ch)) + return (tolower(ch)); + return (ch); +} + /* * Search for expanded name from a list of previously compressed names. * Return the offset from msg if found or -1. @@ -292,7 +312,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) goto next; if (*dn == '\\') dn++; - if (*dn++ != *cp++) + if (mklower(*dn++) != mklower(*cp++)) goto next; } if ((n = *dn++) == '\0' && *cp == '\0') @@ -301,11 +321,12 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) continue; goto next; - default: /* illegal type */ - return (-1); - case INDIR_MASK: /* indirection */ cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + return (-1); } } if (*dn == '\0') @@ -325,7 +346,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) u_short _getshort(msgp) - register u_char *msgp; + register const u_char *msgp; { register u_int16_t u; @@ -335,7 +356,7 @@ _getshort(msgp) u_int32_t _getlong(msgp) - register u_char *msgp; + register const u_char *msgp; { register u_int32_t u; diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c index d841293f18d..14e5ddf790d 100644 --- a/lib/libc/net/res_debug.c +++ b/lib/libc/net/res_debug.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $ */ +/* $NetBSD: res_debug.c,v 1.8 1996/02/02 15:22:27 mrg Exp $ */ /*- * Copyright (c) 1985, 1990, 1993 @@ -56,8 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_debug.c,v 8.7 1995/12/22 10:20:39 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $"; +static char rcsid[] = "$NetBSD: res_debug.c,v 1.8 1996/02/02 15:22:27 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -68,18 +69,16 @@ static char rcsid[] = "$NetBSD: res_debug.c,v 1.7 1995/02/25 06:20:56 cgd Exp $" #include <resolv.h> #include <stdio.h> #include <string.h> +#include <netdb.h> void __fp_query(); -char *__p_class(), *__p_time(), *__p_type(); -char *p_cdname(), *p_fqname(), *p_rr(); -static char *p_option __P((u_int32_t)); char *_res_opcodes[] = { "QUERY", "IQUERY", "CQUERYM", - "CQUERYU", - "4", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ "5", "6", "7", @@ -112,102 +111,118 @@ char *_res_resultcodes[] = { "NOCHANGE", }; -static char retbuf[16]; - static char * dewks(wks) int wks; { + static char nbuf[20]; + switch (wks) { - case 5: return("rje"); - case 7: return("echo"); - case 9: return("discard"); - case 11: return("systat"); - case 13: return("daytime"); - case 15: return("netstat"); - case 17: return("qotd"); - case 19: return("chargen"); - case 20: return("ftp-data"); - case 21: return("ftp"); - case 23: return("telnet"); - case 25: return("smtp"); - case 37: return("time"); - case 39: return("rlp"); - case 42: return("name"); - case 43: return("whois"); - case 53: return("domain"); - case 57: return("apts"); - case 59: return("apfs"); - case 67: return("bootps"); - case 68: return("bootpc"); - case 69: return("tftp"); - case 77: return("rje"); - case 79: return("finger"); - case 87: return("link"); - case 95: return("supdup"); - case 100: return("newacct"); - case 101: return("hostnames"); - case 102: return("iso-tsap"); - case 103: return("x400"); - case 104: return("x400-snd"); - case 105: return("csnet-ns"); - case 109: return("pop-2"); - case 111: return("sunrpc"); - case 113: return("auth"); - case 115: return("sftp"); - case 117: return("uucp-path"); - case 119: return("nntp"); - case 121: return("erpc"); - case 123: return("ntp"); - case 133: return("statsrv"); - case 136: return("profile"); - case 144: return("NeWS"); - case 161: return("snmp"); - case 162: return("snmp-trap"); - case 170: return("print-srv"); - default: (void) sprintf(retbuf, "%d", wks); return(retbuf); + case 5: return "rje"; + case 7: return "echo"; + case 9: return "discard"; + case 11: return "systat"; + case 13: return "daytime"; + case 15: return "netstat"; + case 17: return "qotd"; + case 19: return "chargen"; + case 20: return "ftp-data"; + case 21: return "ftp"; + case 23: return "telnet"; + case 25: return "smtp"; + case 37: return "time"; + case 39: return "rlp"; + case 42: return "name"; + case 43: return "whois"; + case 53: return "domain"; + case 57: return "apts"; + case 59: return "apfs"; + case 67: return "bootps"; + case 68: return "bootpc"; + case 69: return "tftp"; + case 77: return "rje"; + case 79: return "finger"; + case 87: return "link"; + case 95: return "supdup"; + case 100: return "newacct"; + case 101: return "hostnames"; + case 102: return "iso-tsap"; + case 103: return "x400"; + case 104: return "x400-snd"; + case 105: return "csnet-ns"; + case 109: return "pop-2"; + case 111: return "sunrpc"; + case 113: return "auth"; + case 115: return "sftp"; + case 117: return "uucp-path"; + case 119: return "nntp"; + case 121: return "erpc"; + case 123: return "ntp"; + case 133: return "statsrv"; + case 136: return "profile"; + case 144: return "NeWS"; + case 161: return "snmp"; + case 162: return "snmp-trap"; + case 170: return "print-srv"; + default: (void) sprintf(nbuf, "%d", wks); return (nbuf); } } -static char * +/* 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"); - case 3: return("ggp"); - case 5: return("st"); - case 6: return("tcp"); - case 7: return("ucl"); - case 8: return("egp"); - case 9: return("igp"); - case 11: return("nvp-II"); - case 12: return("pup"); - case 16: return("chaos"); - case 17: return("udp"); - default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); + case 1: return "icmp"; + case 2: return "igmp"; + case 3: return "ggp"; + case 5: return "st"; + case 6: return "tcp"; + case 7: return "ucl"; + case 8: return "egp"; + case 9: return "igp"; + case 11: return "nvp-II"; + case 12: return "pup"; + case 16: return "chaos"; + case 17: return "udp"; + default: (void) sprintf(nbuf, "%d", protonum); return (nbuf); } } -static char * -do_rrset(msg, cp, cnt, pflag, file, hs) - int cnt, pflag; - char *cp,*msg, *hs; +static const u_char * +do_rrset(msg, len, cp, cnt, pflag, file, hs) + int cnt, pflag, len; + const u_char *cp, *msg; + const char *hs; FILE *file; { int n; int sflag; + /* - * Print answer records + * Print answer records. */ sflag = (_res.pfcode & pflag); if (n = ntohs(cnt)) { if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) fprintf(file, hs); while (--n >= 0) { - cp = p_rr(cp, msg, file); - if ((cp-msg) > PACKETSZ) + if ((!_res.pfcode) || sflag) { + cp = p_rr(cp, msg, file); + } else { + unsigned int dlen; + cp += __dn_skipname(cp, cp + MAXCDNAME); + cp += sizeof(u_int16_t); + cp += sizeof(u_int16_t); + cp += sizeof(u_int32_t); + dlen = _getshort((u_char*)cp); + cp += sizeof(u_int16_t); + cp += dlen; + } + if ((cp - msg) > len) return (NULL); } if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) @@ -216,8 +231,9 @@ do_rrset(msg, cp, cnt, pflag, file, hs) return(cp); } +void __p_query(msg) - char *msg; + const u_char *msg; { __fp_query(msg, stdout); } @@ -231,15 +247,14 @@ __fp_resstat(statp, file) struct __res_state *statp; FILE *file; { - int bit; + register u_long mask; fprintf(file, ";; res options:"); if (!statp) statp = &_res; - for (bit = 0; bit < 32; bit++) { /* XXX 32 - bad assumption! */ - if (statp->options & (1<<bit)) - fprintf(file, " %s", p_option(1<<bit)); - } + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); putc('\n', file); } @@ -248,19 +263,27 @@ __fp_resstat(statp, file) * This is intended to be primarily a debugging routine. */ void -__fp_query(msg,file) - char *msg; +__fp_nquery(msg, len, file) + const u_char *msg; + int len; FILE *file; { - register char *cp; - register HEADER *hp; + register const u_char *cp, *endMark; + 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 + /* * Print header fields. */ hp = (HEADER *)msg; - cp = msg + sizeof(HEADER); + cp = msg + HFIXEDSZ; + endMark = cp + len; if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", _res_opcodes[hp->opcode], @@ -268,7 +291,8 @@ __fp_query(msg,file) ntohs(hp->id)); putc('\n', file); } - putc(';', file); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX)) + putc(';', file); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { fprintf(file,"; flags:"); if (hp->qr) @@ -281,20 +305,17 @@ __fp_query(msg,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)); fprintf(file,", Ans: %d", ntohs(hp->ancount)); fprintf(file,", Auth: %d", ntohs(hp->nscount)); - fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); + fprintf(file, ", Addit: %d", ntohs(hp->arcount)); } -#if 0 - if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { + if ((!_res.pfcode) || (_res.pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { putc('\n',file); } -#endif /* * Print question records. */ @@ -302,55 +323,85 @@ __fp_query(msg,file) if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) fprintf(file,";; QUESTIONS:\n"); while (--n >= 0) { + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) fprintf(file,";;\t"); - cp = p_cdname(cp, msg, file); - if (cp == NULL) - return; + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + cp = p_cdnname(cp, msg, len, file); + else { + int n; + char name[MAXDNAME]; + + if ((n = dn_expand(msg, msg+len, cp, name, + sizeof name)) < 0) + cp = NULL; + else + cp += n; + } + ErrorTest(cp); + TruncTest(cp); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) fprintf(file, ", type = %s", - __p_type(_getshort(cp))); - cp += sizeof(u_int16_t); + __p_type(_getshort((u_char*)cp))); + cp += INT16SZ; + TruncTest(cp); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) - fprintf(file, ", class = %s\n\n", - __p_class(_getshort(cp))); - cp += sizeof(u_int16_t); + fprintf(file, ", class = %s\n", + __p_class(_getshort((u_char*)cp))); + cp += INT16SZ; + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + putc('\n', file); } } /* * Print authoritative answer records */ - cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, + TruncTest(cp); + cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file, ";; ANSWERS:\n"); - if (cp == NULL) - return; + ErrorTest(cp); /* * print name server records */ - cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, + TruncTest(cp); + cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file, ";; AUTHORITY RECORDS:\n"); - if (!cp) - return; + ErrorTest(cp); + TruncTest(cp); /* * 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"); - if (!cp) + ErrorTest(cp); + return; + trunc: + fprintf(file, "\n;; ...truncated\n"); return; + error: + fprintf(file, "\n;; ...malformed\n"); } -char * -p_cdname(cp, msg, file) - char *cp, *msg; +void +__fp_query(msg, file) + const u_char *msg; + FILE *file; +{ + fp_nquery(msg, PACKETSZ, file); +} + +const u_char * +__p_cdnname(cp, msg, len, file) + const u_char *cp, *msg; + int len; FILE *file; { char name[MAXDNAME]; int n; - if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, - (u_char *)cp, (u_char *)name, sizeof(name))) < 0) + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) return (NULL); if (name[0] == '\0') putc('.', file); @@ -359,16 +410,26 @@ p_cdname(cp, msg, file) return (cp + n); } -char * -p_fqname(cp, msg, file) - char *cp, *msg; +const u_char * +__p_cdname(cp, msg, file) + const u_char *cp, *msg; + FILE *file; +{ + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* XXX: the rest of these functions need to become length-limited, too. (vix) + */ + +const u_char * +__p_fqname(cp, msg, file) + const u_char *cp, *msg; FILE *file; { char name[MAXDNAME]; - int n, len; + int n; - if ((n = dn_expand((u_char *)msg, (u_char *)cp + MAXCDNAME, - (u_char *)cp, (u_char *)name, sizeof(name))) < 0) + if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0) return (NULL); if (name[0] == '\0') { putc('.', file); @@ -383,17 +444,21 @@ p_fqname(cp, msg, file) /* * Print resource record fields in human readable form. */ -char * -p_rr(cp, msg, file) - char *cp, *msg; +const u_char * +__p_rr(cp, msg, file) + const u_char *cp, *msg; FILE *file; { int type, class, dlen, n, c; struct in_addr inaddr; - char *cp1, *cp2; + const u_char *cp1, *cp2; 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(cp); @@ -406,7 +471,7 @@ p_rr(cp, msg, file) cp += sizeof(u_int16_t); 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)); @@ -429,7 +494,7 @@ p_rr(cp, msg, file) address = inet_ntoa(inaddr); cp += sizeof(inaddr); - protocol = *(u_char*)cp; + protocol = *cp; cp += sizeof(u_char); port = _getshort(cp); cp += sizeof(u_int16_t); @@ -448,52 +513,75 @@ 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(cp); cp += sizeof(u_int32_t); - fprintf(file,"\t\t\t%lu\t; serial\n", t); + fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t); t = _getlong(cp); cp += sizeof(u_int32_t); - 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(cp); cp += sizeof(u_int32_t); - 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(cp); cp += sizeof(u_int32_t); - 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(cp); cp += sizeof(u_int32_t); - 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: case T_AFSDB: - fprintf(file,"\t%d ", _getshort(cp)); - cp += sizeof(u_int16_t); - cp = p_fqname(cp, msg, file); + case T_RT: + fprintf(file, "\t%d ", _getshort(cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_PX: + fprintf(file, "\t%d ", _getshort(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: + case T_X25: (void) fputs("\t\"", file); cp2 = cp1 + dlen; 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 @@ -503,12 +591,19 @@ p_rr(cp, msg, file) putc('"', file); break; + case T_NSAP: + (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL)); + cp += dlen; + break; + 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: @@ -558,7 +653,7 @@ p_rr(cp, msg, file) case T_UNSPEC: { int NumBytes = 8; - char *DataPtr; + u_char *DataPtr; int i; if (dlen < NumBytes) NumBytes = dlen; @@ -588,113 +683,98 @@ p_rr(cp, msg, file) return (cp); } -static char nbuf[40]; - /* * Return a string for the type */ -char * +const char * __p_type(type) int type; { + static char nbuf[20]; + switch (type) { - case T_A: - return("A"); - case T_NS: /* authoritative server */ - return("NS"); - case T_CNAME: /* canonical name */ - return("CNAME"); - case T_SOA: /* start of authority zone */ - return("SOA"); - case T_MB: /* mailbox domain name */ - return("MB"); - case T_MG: /* mail group member */ - return("MG"); - case T_MR: /* mail rename name */ - return("MR"); - case T_NULL: /* null resource record */ - return("NULL"); - case T_WKS: /* well known service */ - return("WKS"); - case T_PTR: /* domain name pointer */ - return("PTR"); - case T_HINFO: /* host information */ - return("HINFO"); - case T_MINFO: /* mailbox information */ - return("MINFO"); - case T_MX: /* mail routing info */ - return("MX"); - case T_TXT: /* text */ - return("TXT"); - case T_RP: /* responsible person */ - return("RP"); - case T_AFSDB: /* AFS cell database */ - return("AFSDB"); - case T_AXFR: /* zone transfer */ - return("AXFR"); - case T_MAILB: /* mail box */ - return("MAILB"); - case T_MAILA: /* mail address */ - return("MAILA"); - case T_ANY: /* matches any type */ - return("ANY"); - case T_UINFO: - return("UINFO"); - case T_UID: - return("UID"); - case T_GID: - return("GID"); + case T_A: return "A"; + case T_NS: return "NS"; + case T_CNAME: return "CNAME"; + case T_SOA: return "SOA"; + case T_MB: return "MB"; + case T_MG: return "MG"; + case T_MR: return "MR"; + case T_NULL: return "NULL"; + case T_WKS: return "WKS"; + case T_PTR: return "PTR"; + case T_HINFO: return "HINFO"; + case T_MINFO: return "MINFO"; + case T_MX: return "MX"; + case T_TXT: return "TXT"; + 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"; + case T_ANY: return "ANY"; + case T_UINFO: return "UINFO"; + case T_UID: return "UID"; + case T_GID: return "GID"; #ifdef ALLOW_T_UNSPEC - case T_UNSPEC: - return("UNSPEC"); + case T_UNSPEC: return "UNSPEC"; #endif /* ALLOW_T_UNSPEC */ - - default: - (void)sprintf(nbuf, "%d", type); - return(nbuf); + default: (void)sprintf(nbuf, "%d", type); return (nbuf); } } /* * Return a mnemonic for class */ -char * +const char * __p_class(class) int class; { + static char nbuf[20]; switch (class) { - case C_IN: /* internet class */ - return("IN"); - case C_HS: /* hesiod class */ - return("HS"); - case C_ANY: /* matches any class */ - return("ANY"); - default: - (void)sprintf(nbuf, "%d", class); - return(nbuf); + case C_IN: return "IN"; + case C_HS: return "HS"; + case C_ANY: return "ANY"; + default: (void)sprintf(nbuf, "%d", class); return (nbuf); } } /* * Return a mnemonic for an option */ -static char * -p_option(option) - u_int32_t option; +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"; case RES_STAYOPEN: return "styopn"; case RES_DNSRCH: return "dnsrch"; - default: sprintf(nbuf, "?0x%x?", option); return nbuf; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); } } @@ -705,6 +785,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 33cc8d39f1d..ff8e1b1e5e6 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $ */ +/* $NetBSD: res_init.c,v 1.9 1996/02/02 15:22:30 mrg Exp $ */ /*- * Copyright (c) 1985, 1989, 1993 @@ -56,9 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; +static char rcsid[] = "$Id: res_init.c,v 8.3 1995/06/29 09:26:28 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_init.c,v 1.8 1995/06/03 22:33:36 mycroft Exp $"; +static char rcsid[] = "$NetBSD: res_init.c,v 1.9 1996/02/02 15:22:30 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -92,11 +92,23 @@ struct __res_state _res = { * there will have precedence. Otherwise, the server address is set to * INADDR_ANY and the default domain name comes from the gethostname(). * - * The configuration file should only be used if you want to redefine your - * domain or run without a server on your machine. + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. * * Return 0 if completes successfully, -1 on error */ +int res_init() { register FILE *fp; @@ -107,6 +119,7 @@ res_init() int haveenv = 0; int havesearch = 0; int nsort = 0; + int dots; u_long mask; _res.nsaddr.sin_len = sizeof(struct sockaddr_in); @@ -392,3 +405,12 @@ net_mask(in) /* XXX - should really use system's version of this */ return (htonl(IN_CLASSB_NET)); return (htonl(IN_CLASSC_NET)); } + +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 25f025e147f..1f04c962720 100644 --- a/lib/libc/net/res_mkquery.c +++ b/lib/libc/net/res_mkquery.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $ */ +/* $NetBSD: res_mkquery.c,v 1.6 1996/02/02 15:22:32 mrg Exp $ */ /*- * Copyright (c) 1985, 1993 @@ -56,9 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp "; +static char rcsid[] = "$Id: res_mkquery.c,v 8.3 1995/06/29 09:26:28 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp $"; +static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.6 1996/02/02 15:22:32 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -73,21 +73,22 @@ static char rcsid[] = "$NetBSD: res_mkquery.c,v 1.5 1995/02/25 06:20:58 cgd Exp * Form all types of queries. * Returns the size of the result or -1. */ +int res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) int op; /* opcode of query */ const char *dname; /* domain name */ int class, type; /* class and type of query */ - const char *data; /* resource record data */ + const u_char *data; /* resource record data */ int datalen; /* length of data */ - const char *newrr_in; /* new rr for modify or append */ - char *buf; /* buffer to put query */ + const u_char *newrr_in; /* new rr for modify or append */ + u_char *buf; /* buffer to put query */ int buflen; /* size of buffer */ { register HEADER *hp; - register char *cp; + register u_char *cp; register int n; struct rrec *newrr = (struct rrec *) newrr_in; - char *dnptrs[10], **dpp, **lastdnptr; + u_char *dnptrs[10], **dpp, **lastdnptr; #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -117,16 +118,16 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) */ switch (op) { case QUERY: + case NS_NOTIFY_OP: if ((buflen -= QFIXEDSZ) < 0) return(-1); - if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, - (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; buflen -= n; - __putshort(type, (u_char *)cp); + __putshort(type, cp); cp += sizeof(u_int16_t); - __putshort(class, (u_char *)cp); + __putshort(class, cp); cp += sizeof(u_int16_t); hp->qdcount = htons(1); if (op == QUERY || data == NULL) @@ -135,18 +136,17 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) * Make an additional record for completion domain. */ buflen -= RRFIXEDSZ; - if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, - (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) + if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0) return (-1); cp += n; buflen -= n; - __putshort(T_NULL, (u_char *)cp); + __putshort(T_NULL, cp); cp += sizeof(u_int16_t); - __putshort(class, (u_char *)cp); + __putshort(class, cp); cp += sizeof(u_int16_t); - __putlong(0, (u_char *)cp); + __putlong(0, cp); cp += sizeof(u_int32_t); - __putshort(0, (u_char *)cp); + __putshort(0, cp); cp += sizeof(u_int16_t); hp->arcount = htons(1); break; @@ -158,13 +158,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) if (buflen < 1 + RRFIXEDSZ + datalen) return (-1); *cp++ = '\0'; /* no domain name */ - __putshort(type, (u_char *)cp); + __putshort(type, cp); cp += sizeof(u_int16_t); - __putshort(class, (u_char *)cp); + __putshort(class, cp); cp += sizeof(u_int16_t); - __putlong(0, (u_char *)cp); + __putlong(0, cp); cp += sizeof(u_int32_t); - __putshort(datalen, (u_char *)cp); + __putshort(datalen, cp); cp += sizeof(u_int16_t); if (datalen) { bcopy(data, cp, datalen); @@ -231,6 +231,8 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) 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 7649462e563..81c4d3194d3 100644 --- a/lib/libc/net/res_query.c +++ b/lib/libc/net/res_query.c @@ -1,4 +1,4 @@ -/* $NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $ */ +/* $NetBSD: res_query.c,v 1.10 1996/02/02 15:22:34 mrg Exp $ */ /*- * Copyright (c) 1988, 1993 @@ -56,9 +56,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixie "; +static char rcsid[] = "$Id: res_query.c,v 8.6 1995/06/29 09:26:28 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_query.c,v 1.9 1995/02/25 06:58:58 cgd Exp $"; +static char rcsid[] = "$NetBSD: res_query.c,v 1.10 1996/02/02 15:22:34 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -90,27 +90,33 @@ int h_errno; * if no error is indicated and the answer count is nonzero. * Return the size of the response on success, -1 on error. * Error number is left in h_errno. + * * Caller must parse answer and determine whether it answers the question. */ +int res_query(name, class, type, answer, anslen) - char *name; /* domain name */ + const char *name; /* domain name */ int class, type; /* class and type of query */ u_char *answer; /* buffer to put answer */ int anslen; /* size of answer buffer */ { - char buf[MAXPACKET]; - HEADER *hp; + u_char buf[MAXPACKET]; + register HEADER *hp = (HEADER *) answer; int n; - if ((_res.options & RES_INIT) == 0 && res_init() == -1) + hp->rcode = NOERROR; /* default */ + + 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, (char *)NULL, 0, NULL, - buf, sizeof(buf)); + n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); if (n <= 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -119,7 +125,7 @@ res_query(name, class, type, answer, anslen) h_errno = NO_RECOVERY; return (n); } - n = res_send(buf, n, (char *)answer, anslen); + n = res_send(buf, n, answer, anslen); if (n < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -174,10 +180,15 @@ res_search(name, class, type, answer, anslen) int anslen; /* size of answer */ { register char *cp, **domain; - int dots, trailing_dot, ret, got_nodata, saved_herrno, tried_as_is; + HEADER *hp = (HEADER *) answer; + u_int dots; + 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); + } got_nodata = 0; errno = 0; @@ -188,13 +199,13 @@ res_search(name, class, type, answer, anslen) dots++; } 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)); /* @@ -251,6 +262,13 @@ res_search(name, class, type, answer, anslen) case HOST_NOT_FOUND: /* keep trying */ break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + got_servfail++; + break; + } + /* FALLTHROUGH */ default: /* anything else implies that we're done */ done++; @@ -291,6 +309,8 @@ res_search(name, class, type, answer, anslen) h_errno = saved_herrno; else if (got_nodata) h_errno = NO_DATA; + else if (got_servfail) + h_errno = TRY_AGAIN; return (-1); } @@ -298,20 +318,25 @@ res_search(name, class, type, answer, anslen) * Perform a call on res_query on the concatenation of name and domain, * removing a trailing dot from name if domain is NULL. */ +int res_querydomain(name, domain, class, type, answer, anslen) - char *name, *domain; + const char *name, *domain; int class, type; /* class and type of query */ u_char *answer; /* buffer to put answer */ int anslen; /* size of answer */ { char nbuf[2*MAXDNAME+2]; - char *longname = nbuf; + 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, class, type); + name, domain?domain:"<Nil>", class, type); #endif if (domain == NULL) { /* @@ -337,24 +362,30 @@ __hostalias(name) { register char *cp1, *cp2; FILE *fp; - char *file, *getenv(), *strcpy(), *strncpy(); + char *file; 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); fclose(fp); diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index e6083581805..f0e9b098b6e 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -1,9 +1,9 @@ -/* $NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $ */ +/* $NetBSD: res_send.c,v 1.5 1996/02/02 15:22:36 mrg Exp $ */ /*- * Copyright (c) 1985, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * + * The Regents of the University of California. All rights reserved. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -14,12 +14,12 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. + * This product includes software developed by the University of + * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -56,12 +56,19 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_send.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel "; +static char rcsid[] = "$Id: res_send.c,v 8.7 1995/12/03 08:31:17 vixie Exp "; #else -static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $"; +static char rcsid[] = "$NetBSD: res_send.c,v 1.5 1996/02/02 15:22:36 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ + /* change this to "0" + * if you talk to a lot + * of multi-homed SunOS + * ("broken") name servers. + */ +#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */ + /* * Send query to name server and wait for reply. */ @@ -73,139 +80,335 @@ static char rcsid[] = "$NetBSD: res_send.c,v 1.4 1995/02/25 06:21:01 cgd Exp $"; #include <netinet/in.h> #include <arpa/nameser.h> #include <arpa/inet.h> + #include <stdio.h> +#include <netdb.h> #include <errno.h> #include <resolv.h> -#include <unistd.h> -#include <string.h> +#if defined(BSD) && (BSD >= 199306) +# include <stdlib.h> +# include <string.h> +# include <unistd.h> +#else +# include "../conf/portability.h" +#endif + +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif + +void _res_close __P((void)); static int s = -1; /* socket used for communications */ -static struct sockaddr no_addr; - -#ifndef FD_SET -#define NFDBITS 32 -#define FD_SETSIZE 32 -#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) -#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) -#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) -#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +static int connected = 0; /* is the socket connected */ +static int vc = 0; /* is the socket a virtual ciruit? */ + +#define CAN_RECONNECT 1 + +#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, size) if (cond) {\ + fprintf args;\ + __fp_nquery(query, size, stdout);\ + } else {} + static void + Aerror(file, string, error, address) + FILE *file; + char *string; + int error; + struct sockaddr_in address; + { + int save = errno; + + if (_res.options & RES_DEBUG) { + fprintf(file, "res_send: %s ([%s].%u): %s\n", + string, + inet_ntoa(address.sin_addr), + ntohs(address.sin_port), + strerror(error)); + } + errno = save; + } + static void + Perror(file, string, error) + FILE *file; + char *string; + int error; + { + int save = errno; + + if (_res.options & RES_DEBUG) { + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + } + errno = save; + } #endif -res_send(buf, buflen, answer, anslen) - const char *buf; +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; + +void +res_send_setqhook(hook) + res_send_qhook hook; +{ + + Qhook = hook; +} + +void +res_send_setrhook(hook) + res_send_rhook hook; +{ + + Rhook = hook; +} + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_isourserver(inp) + const struct sockaddr_in *inp; +{ + struct sockaddr_in ina; + register int ns, ret; + + ina = *inp; + ret = 0; + for (ns = 0; ns < _res.nscount; ns++) { + register const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; + + if (srv->sin_family == ina.sin_family && + srv->sin_port == ina.sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { + ret++; + break; + } + } + return (ret); +} + +/* int + * 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 + */ +int +res_nameinquery(name, type, class, buf, eom) + const char *name; + register int type, class; + const u_char *buf, *eom; +{ + register const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(cp); cp += INT16SZ; + if (ttype == type && + tclass == class && + strcasecmp(tname, name) == 0) + return (1); + } + return (0); +} + +/* int + * 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 + */ +int +res_queriesmatch(buf1, eom1, buf2, eom2) + const u_char *buf1, *eom1; + const u_char *buf2, *eom2; +{ + register const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf1)->qdcount); + + if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_send(buf, buflen, ans, anssiz) + const u_char *buf; int buflen; - char *answer; - int anslen; + u_char *ans; + int anssiz; { - register int n; - int try, v_circuit, resplen, ns; - int gotsomewhere = 0, connected = 0; - int connreset = 0; - u_short id, len; - char *cp; - fd_set dsmask; - struct timeval timeout; HEADER *hp = (HEADER *) buf; - HEADER *anhp = (HEADER *) answer; - u_int badns; /* XXX NSMAX can't exceed #/bits per this */ - struct iovec iov[2]; - int terrno = ETIMEDOUT; - char junk[512]; - -#ifdef DEBUG - if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) { - printf(";; res_send()\n"); - __p_query(buf); + HEADER *anhp = (HEADER *) ans; + int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; + register int n; + u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + /* errno should have been set by res_init() in this case. */ + return (-1); } -#endif - if (!(_res.options & RES_INIT)) - if (res_init() == -1) { - 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; - id = hp->id; + gotsomewhere = 0; + connreset = 0; + terrno = ETIMEDOUT; badns = 0; + /* * Send request, RETRY times, or until successful */ for (try = 0; try < _res.retry; try++) { for (ns = 0; ns < _res.nscount; ns++) { - if (badns & (1<<ns)) - continue; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";; Querying server (# %d) address = %s\n", - ns+1, - inet_ntoa(_res.nsaddr_list[ns].sin_addr)); -#endif - usevc: + struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; + same_ns: + if (badns & (1 << ns)) { + _res_close(); + goto next_ns; + } + + if (Qhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*Qhook)(&nsap, &buf, &buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + done = 1; + break; + case res_nextns: + _res_close(); + goto next_ns; + case res_done: + return (resplen); + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + return (-1); + } + } while (!done); + } + + Dprint(_res.options & RES_DEBUG, + (stdout, ";; Querying server (# %d) address = %s\n", + ns + 1, inet_ntoa(nsap->sin_addr))); + if (v_circuit) { - int truncated = 0; + int truncated; + struct iovec iov[2]; + u_short len; + u_char *cp; /* * Use virtual circuit; * at most one attempt per server. */ try = _res.retry; - if (s < 0) { - s = socket(AF_INET, SOCK_STREAM, 0); + truncated = 0; + if ((s < 0) || (!vc)) { + if (s >= 0) + _res_close(); + + s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) { terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("socket (vc) failed"); -#endif - continue; + Perror(stderr, "socket(vc)", errno); + return (-1); } - if (connect(s, - (struct sockaddr *)&(_res.nsaddr_list[ns]), - sizeof(struct sockaddr)) < 0) { + errno = 0; + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr)) < 0) { terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("connect failed"); -#endif - (void) close(s); - s = -1; - continue; + Aerror(stderr, "connect/vc", + errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; } + vc = 1; } /* * Send length & message */ - len = htons((u_short)buflen); + putshort((u_short)buflen, (u_char*)&len); iov[0].iov_base = (caddr_t)&len; - iov[0].iov_len = sizeof(len); - iov[1].iov_base = (char *)buf; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; - if (writev(s, iov, 2) != sizeof(len) + buflen) { + if (writev(s, iov, 2) != (INT16SZ + buflen)) { terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("write failed"); -#endif - (void) close(s); - s = -1; - continue; + Perror(stderr, "write failed", errno); + badns |= (1 << ns); + _res_close(); + goto next_ns; } /* * Receive length & response */ - cp = answer; - len = sizeof(short); - while (len != 0 && - (n = read(s, (char *)cp, (int)len)) > 0) { + cp = ans; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { cp += n; - len -= n; + if ((len -= n) <= 0) + break; } if (n <= 0) { terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("read failed"); -#endif - (void) close(s); - s = -1; + Perror(stderr, "read failed", errno); + _res_close(); /* * A long running process might get its TCP * connection reset if the remote server was @@ -217,35 +420,32 @@ res_send(buf, buflen, answer, anslen) */ if (terrno == ECONNRESET && !connreset) { connreset = 1; - ns--; + _res_close(); + goto same_ns; } - continue; + _res_close(); + goto next_ns; } - cp = answer; - if ((resplen = ntohs(*(u_short *)cp)) > anslen) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - fprintf(stderr, - ";; response truncated\n"); -#endif - len = anslen; + resplen = _getshort(ans); + if (resplen > anssiz) { + Dprint(_res.options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); truncated = 1; + len = anssiz; } else 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; } if (n <= 0) { terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("read failed"); -#endif - (void) close(s); - s = -1; - continue; + Perror(stderr, "read(vc)", errno); + _res_close(); + goto next_ns; } if (truncated) { /* @@ -253,10 +453,13 @@ res_send(buf, buflen, answer, anslen) * so connection stays in synch. */ anhp->tc = 1; - len = resplen - anslen; + len = resplen - anssiz; while (len != 0) { - n = (len > sizeof(junk) ? - sizeof(junk) : len); + char junk[PACKETSZ]; + + n = (len > sizeof(junk) + ? sizeof(junk) + : len); if ((n = read(s, junk, n)) > 0) len -= n; else @@ -267,19 +470,26 @@ res_send(buf, buflen, answer, anslen) /* * Use datagrams. */ - if (s < 0) { - s = socket(AF_INET, SOCK_DGRAM, 0); + struct timeval timeout; + fd_set dsmask; + struct sockaddr_in from; + int fromlen; + + if ((s < 0) || vc) { + if (vc) + _res_close(); + s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { - terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("socket (dg) failed"); +#if !CAN_RECONNECT + bad_dg_sock: #endif - continue; + terrno = errno; + Perror(stderr, "socket(dg)", errno); + return (-1); } + connected = 0; } /* - * I'm tired of answering this question, so: * On a 4.3BSD+ machine (client and server, * actually), sending to a nameserver datagram * port with no nameserver will cause an @@ -296,29 +506,27 @@ res_send(buf, buflen, answer, anslen) */ if (_res.nscount == 1 || (try == 0 && ns == 0)) { /* - * Don't use connect if we might - * still receive a response - * from another server. + * Connect only if we are sure we won't + * receive a response from another server. */ - if (connected == 0) { - if (connect(s, - (struct sockaddr *) - &_res.nsaddr_list[ns], - sizeof(struct sockaddr)) < 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("connect"); -#endif - continue; + if (!connected) { + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr) + ) < 0) { + Aerror(stderr, + "connect(dg)", + errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; } connected = 1; } - if (send(s, buf, buflen, 0) != buflen) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("send"); -#endif - continue; + if (send(s, (char*)buf, buflen, 0) != buflen) { + Perror(stderr, "send", errno); + badns |= (1 << ns); + _res_close(); + goto next_ns; } } else { /* @@ -326,18 +534,36 @@ res_send(buf, buflen, answer, anslen) * for responses from more than one server. */ if (connected) { - (void) connect(s, &no_addr, - sizeof(no_addr)); +#if CAN_RECONNECT + struct sockaddr_in no_addr; + + no_addr.sin_family = AF_INET; + no_addr.sin_addr.s_addr = INADDR_ANY; + no_addr.sin_port = 0; + (void) connect(s, + (struct sockaddr *) + &no_addr, + sizeof(no_addr)); +#else + int s1 = socket(PF_INET, SOCK_DGRAM,0); + if (s1 < 0) + goto bad_dg_sock; + (void) dup2(s1, s); + (void) close(s1); + Dprint(_res.options & RES_DEBUG, + (stdout, ";; new DG socket\n")) +#endif connected = 0; + errno = 0; } - if (sendto(s, buf, buflen, 0, - (struct sockaddr *)&_res.nsaddr_list[ns], - sizeof(struct sockaddr)) != buflen) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("sendto"); -#endif - continue; + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, + sizeof(struct sockaddr)) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; } } @@ -350,106 +576,157 @@ res_send(buf, buflen, answer, anslen) if ((long) timeout.tv_sec <= 0) timeout.tv_sec = 1; timeout.tv_usec = 0; -wait: + wait: FD_ZERO(&dsmask); FD_SET(s, &dsmask); n = select(s+1, &dsmask, (fd_set *)NULL, - (fd_set *)NULL, &timeout); + (fd_set *)NULL, &timeout); if (n < 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("select"); -#endif - continue; + Perror(stderr, "select", errno); + _res_close(); + goto next_ns; } if (n == 0) { /* * timeout */ -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";; timeout\n"); -#endif + Dprint(_res.options & RES_DEBUG, + (stdout, ";; timeout\n")); gotsomewhere = 1; - continue; + _res_close(); + goto next_ns; } - if ((resplen = recv(s, answer, anslen, 0)) <= 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("recvfrom"); -#endif - continue; + errno = 0; + fromlen = sizeof(struct sockaddr_in); + resplen = recvfrom(s, (char*)ans, anssiz, 0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(stderr, "recvfrom", errno); + _res_close(); + goto next_ns; } gotsomewhere = 1; - if (id != anhp->id) { + if (hp->id != anhp->id) { /* - * response from old query, ignore it + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. */ -#ifdef DEBUG - if ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY)) { - printf(";; old answer:\n"); - __p_query(answer); - } + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; old answer:\n"), + ans, resplen); + goto wait; + } +#if CHECK_SRVR_ADDR + if (!(_res.options & RES_INSECURE1) && + !res_isourserver(&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans, resplen); + goto wait; + } #endif + if (!(_res.options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans, resplen); goto wait; } - if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || anhp->rcode == REFUSED) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) { - printf("server rejected query:\n"); - __p_query(answer); - } -#endif - badns |= (1<<ns); - continue; + DprintQ(_res.options & RES_DEBUG, + (stdout, "server rejected query:\n"), + 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) { /* * get rest of answer; * use TCP with same server. */ -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";; truncated answer\n"); -#endif - (void) close(s); - s = -1; + Dprint(_res.options & RES_DEBUG, + (stdout, ";; truncated answer\n")); v_circuit = 1; - goto usevc; + _res_close(); + goto same_ns; } - } -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";; got answer:\n"); - if ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY)) - __p_query(answer); -#endif + } /*if vc/dg*/ + Dprint((_res.options & RES_DEBUG) || + ((_res.pfcode & RES_PRF_REPLY) && + (_res.pfcode & RES_PRF_HEAD1)), + (stdout, ";; got answer:\n")); + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ""), + ans, resplen); /* * If using virtual circuits, we assume that the first server - * is preferred * over the rest (i.e. it is on the local + * is preferred over the rest (i.e. it is on the local * machine) and only keep that one open. * If we have temporarily opened a virtual circuit, * or if we haven't been asked to keep a socket open, * close the socket. */ - if ((v_circuit && - ((_res.options & RES_USEVC) == 0 || ns != 0)) || - (_res.options & RES_STAYOPEN) == 0) { - (void) close(s); - s = -1; + if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || + !(_res.options & RES_STAYOPEN)) { + _res_close(); + } + if (Rhook) { + int done = 0, loops = 0; + + do { + res_sendhookact act; + + act = (*Rhook)(nsap, buf, buflen, + ans, anssiz, &resplen); + switch (act) { + case res_goahead: + case res_done: + done = 1; + break; + case res_nextns: + _res_close(); + goto next_ns; + case res_modified: + /* give the hook another try */ + if (++loops < 42) /*doug adams*/ + break; + /*FALLTHROUGH*/ + case res_error: + /*FALLTHROUGH*/ + default: + return (-1); + } + } while (!done); + } return (resplen); - } - } - if (s >= 0) { - (void) close(s); - s = -1; - } - if (v_circuit == 0) - if (gotsomewhere == 0) + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + _res_close(); + if (!v_circuit) + if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ else errno = ETIMEDOUT; /* no answer obtained */ @@ -465,10 +742,13 @@ wait: * * This routine is not expected to be user visible. */ +void _res_close() { - if (s != -1) { + if (s >= 0) { (void) close(s); s = -1; + connected = 0; + vc = 0; } } diff --git a/lib/libc/net/resolver.3 b/lib/libc/net/resolver.3 index 99abe17f036..07bc10c393a 100644 --- a/lib/libc/net/resolver.3 +++ b/lib/libc/net/resolver.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: resolver.3,v 1.5 1995/02/25 06:21:02 cgd Exp $ +.\" $NetBSD: resolver.3,v 1.6 1996/02/02 15:22:37 mrg Exp $ .\" .\" Copyright (c) 1985, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -333,6 +333,7 @@ see .%T RFC1033 , .%T RFC1034 , .%T RFC1035 , +.%T RFC1535 , .%T RFC974 .Rs .%T "Name Server Operations Guide for BIND" diff --git a/lib/libc/net/sethostent.c b/lib/libc/net/sethostent.c index 00f64996950..df58b1bc928 100644 --- a/lib/libc/net/sethostent.c +++ b/lib/libc/net/sethostent.c @@ -1,4 +1,4 @@ -/* $NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $ */ +/* $NetBSD: sethostent.c,v 1.5 1996/02/02 15:22:39 mrg Exp $ */ /* * Copyright (c) 1985, 1993 @@ -36,8 +36,9 @@ #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: sethostent.c,v 8.3 1995/06/29 09:26:28 vixie Exp "; #else -static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $"; +static char rcsid[] = "$NetBSD: sethostent.c,v 1.5 1996/02/02 15:22:39 mrg Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -49,7 +50,11 @@ static char rcsid[] = "$NetBSD: sethostent.c,v 1.4 1995/02/25 06:21:03 cgd Exp $ void sethostent(stayopen) + int stayopen; { + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; } |