diff options
author | Roland McGrath <roland@gnu.org> | 1994-07-28 22:01:26 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1994-07-28 22:01:26 +0000 |
commit | e2a7073e7b94478641f2a6e250005f0fc1b30844 (patch) | |
tree | f8498c1ca24fecaaac020b1281482666370b2536 | |
parent | 4e14b2114d1675fe80b16b3c276da98b4c3fda5d (diff) |
Incorporated from BIND-4.9.3-BETA9.
-rw-r--r-- | inet/arpa/inet.h | 30 | ||||
-rw-r--r-- | inet/netdb.h | 33 | ||||
-rw-r--r-- | resolv/arpa/nameser.h | 178 | ||||
-rw-r--r-- | resolv/gethnamaddr.c | 457 | ||||
-rw-r--r-- | resolv/getnetbyaddr.c | 7 | ||||
-rw-r--r-- | resolv/getnetbyname.c | 16 | ||||
-rw-r--r-- | resolv/getnetent.c | 46 | ||||
-rw-r--r-- | resolv/getnetnamadr.c | 303 | ||||
-rw-r--r-- | resolv/herror.c | 17 | ||||
-rw-r--r-- | resolv/nsap_addr.c | 97 | ||||
-rw-r--r-- | resolv/res_comp.c | 118 | ||||
-rw-r--r-- | resolv/res_debug.c | 495 | ||||
-rw-r--r-- | resolv/res_init.c | 289 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 107 | ||||
-rw-r--r-- | resolv/res_query.c | 236 | ||||
-rw-r--r-- | resolv/res_send.c | 705 | ||||
-rw-r--r-- | resolv/resolv.h | 154 | ||||
-rw-r--r-- | resolv/sethostent.c | 38 |
18 files changed, 2373 insertions, 953 deletions
diff --git a/inet/arpa/inet.h b/inet/arpa/inet.h index 6299741aca..5551eb60cf 100644 --- a/inet/arpa/inet.h +++ b/inet/arpa/inet.h @@ -1,13 +1,8 @@ /* - * @(#)inet.h 5.7 (Berkeley) 4/3/91 - * $Id$ - */ - -/* - * ++Copyright++ 1983 + * ++Copyright++ 1983, 1993 * - - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 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 @@ -58,6 +53,11 @@ * --Copyright-- */ +/* + * @(#)inet.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + #ifndef _INET_H_ #define _INET_H_ @@ -72,13 +72,13 @@ #include <sys/cdefs.h> __BEGIN_DECLS -extern u_int32_t inet_addr __P((const char *)); -extern u_int32_t inet_lnaof __P((struct in_addr)); -extern struct in_addr inet_makeaddr __P((u_int32_t, u_int32_t)); -extern u_int32_t inet_netof __P((struct in_addr)); -extern u_int32_t inet_network __P((const char *)); -extern int inet_aton __P((const char *, struct in_addr *)); -extern char *inet_ntoa __P((struct in_addr)); +unsigned long inet_addr __P((const char *)); +int inet_aton __P((const char *, struct in_addr *)); +unsigned long inet_lnaof __P((struct in_addr)); +struct in_addr inet_makeaddr __P((u_long , u_long)); +unsigned long inet_netof __P((struct in_addr)); +unsigned long inet_network __P((const char *)); +char *inet_ntoa __P((struct in_addr)); __END_DECLS #endif /* !_INET_H_ */ diff --git a/inet/netdb.h b/inet/netdb.h index 98490fc5da..e39081c359 100644 --- a/inet/netdb.h +++ b/inet/netdb.h @@ -1,13 +1,8 @@ /* - * @(#)netdb.h 5.15 (Berkeley) 4/3/91 - * $Id$ - */ - -/* - * ++Copyright++ 1980, 1983, 1988 + * ++Copyright++ 1980, 1983, 1988, 1993 * - - * Copyright (c) 1980, 1983, 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1980, 1983, 1988, 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 @@ -58,14 +53,17 @@ * --Copyright-- */ +/* + * @(#)netdb.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + #ifndef _NETDB_H_ #define _NETDB_H_ #include <sys/param.h> #if (!defined(BSD)) || (BSD < 199306) # include <sys/bitypes.h> -#else -# include <sys/types.h> #endif #include <sys/cdefs.h> @@ -91,13 +89,13 @@ struct hostent { /* * Assumption here is that a network number - * fits in 32 bits -- probably a poor one. + * fits in an unsigned long -- probably a poor one. */ struct netent { char *n_name; /* official name of net */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ - u_int32_t n_net; /* network # */ + unsigned long n_net; /* network # */ }; struct servent { @@ -132,8 +130,12 @@ void endservent __P((void)); struct hostent *gethostbyaddr __P((const char *, int, int)); struct hostent *gethostbyname __P((const char *)); struct hostent *gethostent __P((void)); -struct netent *getnetbyaddr __P((int32_t, int)); /* u_int32_t? */ +struct netent *getnetbyaddr __P((long, int)); /* u_long? */ +#ifdef sun +struct netent *getnetbyname __P((char *)); +#else struct netent *getnetbyname __P((const char *)); +#endif struct netent *getnetent __P((void)); struct protoent *getprotobyname __P((const char *)); struct protoent *getprotobynumber __P((int)); @@ -142,7 +144,7 @@ struct servent *getservbyname __P((const char *, const char *)); struct servent *getservbyport __P((int, const char *)); struct servent *getservent __P((void)); void herror __P((const char *)); -char * hstrerror __P((int)); +char *hstrerror __P((int)); void sethostent __P((int)); /* void sethostfile __P((const char *)); */ void setnetent __P((int)); @@ -150,7 +152,4 @@ void setprotoent __P((int)); void setservent __P((int)); __END_DECLS -/* Get `struct rpcent' and the definition for reading /etc/rpc. */ -#include <rpc/netdb.h> - #endif /* !_NETDB_H_ */ diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h index 2e2203aa64..b5bdeaa860 100644 --- a/resolv/arpa/nameser.h +++ b/resolv/arpa/nameser.h @@ -1,13 +1,8 @@ /* - * @(#)nameser.h 5.25 (Berkeley) 4/3/91 - * $Id$ - */ - -/* - * ++Copyright++ 1983, 1989 + * ++Copyright++ 1983, 1989, 1993 * - - * Copyright (c) 1983, 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 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 @@ -58,6 +53,11 @@ * --Copyright-- */ +/* + * @(#)nameser.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + #ifndef _NAMESER_H_ #define _NAMESER_H_ @@ -70,16 +70,28 @@ #include <sys/cdefs.h> /* + * revision information. this is the release date in YYYYMMDD format. + * it can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__BIND > 19931104)". do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __BIND 19940417 /* interface version stamp */ + +/* * Define constants based on rfc883 */ #define PACKETSZ 512 /* maximum packet size */ #define MAXDNAME 256 /* maximum domain name */ #define MAXCDNAME 255 /* maximum compressed domain name */ #define MAXLABEL 63 /* maximum length of domain label */ - /* Number of bytes of fixed size data in query structure */ -#define QFIXEDSZ 4 - /* number of bytes of fixed size data in resource record */ -#define RRFIXEDSZ 10 +#define HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define INT32SZ 4 /* for systems without 32-bit ints */ +#define INT16SZ 2 /* for systems without 16-bit ints */ +#define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */ /* * Internet nameserver port number @@ -135,11 +147,18 @@ #define T_MX 15 /* mail routing information */ #define T_TXT 16 /* text strings */ #define T_RP 17 /* responsible person */ +#define T_AFSDB 18 /* AFS cell database */ +#define T_X25 19 /* X_25 calling address */ +#define T_ISDN 20 /* ISDN calling address */ +#define T_RT 21 /* router */ +#define T_NSAP 22 /* NSAP address */ +#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ /* non standard */ #define T_UINFO 100 /* user (finger) information */ #define T_UID 101 /* user ID */ #define T_GID 102 /* group ID */ #define T_UNSPEC 103 /* Unspecified format (binary data) */ +#define T_SA 200 /* shuffle address */ /* Query type values which do not appear in resource records */ #define T_AXFR 252 /* transfer zone of authority */ #define T_MAILB 253 /* transfer mailbox records */ @@ -152,20 +171,26 @@ #define C_IN 1 /* the arpa internet */ #define C_CHAOS 3 /* for chaos net (MIT) */ -#define C_HS 4 /* for Hesiod name server (MIT) */ +#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ /* Query class values which do not appear in resource records */ #define C_ANY 255 /* wildcard match */ /* * Status return codes for T_UNSPEC conversion routines */ -#define CONV_SUCCESS 0 -#define CONV_OVERFLOW -1 -#define CONV_BADFMT -2 -#define CONV_BADCKSUM -3 -#define CONV_BADBUFLEN -4 +#define CONV_SUCCESS 0 +#define CONV_OVERFLOW (-1) +#define CONV_BADFMT (-2) +#define CONV_BADCKSUM (-3) +#define CONV_BADBUFLEN (-4) #ifndef BYTE_ORDER +#if (BSD >= 199103) +# include <machine/endian.h> +#else +#ifdef linux +# include <endian.h> +#else #define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ #define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ #define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ @@ -178,11 +203,15 @@ #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ - defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || \ - defined(apollo) || defined(hp9000) || defined(hp9000s300) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ defined (BIT_ZERO_ON_LEFT) #define BYTE_ORDER BIG_ENDIAN #endif +#endif /* linux */ +#endif /* BSD */ #endif /* BYTE_ORDER */ #if !defined(BYTE_ORDER) || \ @@ -193,48 +222,49 @@ * which will force your compiles to bomb until you fix * the above macros. */ - #error "Undefined or invalid BYTE_ORDER"; + error "Undefined or invalid BYTE_ORDER"; #endif + /* - * Structure for query header, the order of the fields is machine and - * compiler dependent, in our case, the bits within a byte are assignd - * least significant first, while the order of transmition is most - * significant first. This requires a somewhat confusing rearrangement. + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. */ typedef struct { - u_short id; /* query identification number */ + unsigned id :16; /* query identification number */ #if BYTE_ORDER == BIG_ENDIAN /* fields in third byte */ - u_int qr:1; /* response flag */ - u_int opcode:4; /* purpose of message */ - u_int aa:1; /* authoritive answer */ - u_int tc:1; /* truncated message */ - u_int rd:1; /* recursion desired */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ /* fields in fourth byte */ - u_int ra:1; /* recursion available */ - u_int pr:1; /* primary server required (non standard) */ - u_int unused:2; /* unused bits */ - u_int rcode:4; /* response code */ + unsigned ra: 1; /* recursion available */ + unsigned pr: 1; /* primary server req'd (!standard) */ + unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned rcode :4; /* response code */ #endif #if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN /* fields in third byte */ - u_int rd:1; /* recursion desired */ - u_int tc:1; /* truncated message */ - u_int aa:1; /* authoritive answer */ - u_int opcode:4; /* purpose of message */ - u_int qr:1; /* response flag */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ /* fields in fourth byte */ - u_int rcode:4; /* response code */ - u_int unused:2; /* unused bits */ - u_int pr:1; /* primary server required (non standard) */ - u_int ra:1; /* recursion available */ + unsigned rcode :4; /* response code */ + unsigned unused :2; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned pr :1; /* primary server req'd (!standard) */ + unsigned ra :1; /* recursion available */ #endif /* remaining bytes */ - u_short qdcount; /* number of question entries */ - u_short ancount; /* number of answer entries */ - u_short nscount; /* number of authority entries */ - u_short arcount; /* number of resource entries */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ } HEADER; /* @@ -246,63 +276,57 @@ typedef struct { * Structure for passing resource records around. */ struct rrec { - short r_zone; /* zone number */ - short r_class; /* class number */ - short r_type; /* type number */ + int16_t r_zone; /* zone number */ + int16_t r_class; /* class number */ + int16_t r_type; /* type number */ u_int32_t r_ttl; /* time to live */ - int r_size; /* size of data area */ - char *r_data; /* pointer to data */ + int r_size; /* size of data area */ + char *r_data; /* pointer to data */ }; -extern u_short _getshort(); -extern u_int32_t _getlong(); +extern u_int16_t _getshort __P((const u_char *)); +extern u_int32_t _getlong __P((const u_char *)); /* * Inline versions of get/put short/long. Pointer is advanced. - * We also assume that a "u_short" holds 2 "chars" - * and that a "u_int32_t" holds 4 "chars". * * These macros demonstrate the property of C whereby it can be - * portable or it can be elegant but never both. + * portable or it can be elegant but rarely both. */ #define GETSHORT(s, cp) { \ - register u_char *t_cp = (u_char*)(cp); \ - (s) = (((u_short)t_cp[0]) << 8) \ - | (((u_short)t_cp[1])) \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ ; \ - (cp) += 2; \ + (cp) += INT16SZ; \ } #define GETLONG(l, cp) { \ - register u_char *t_cp = (u_char*)(cp); \ - (l) = (((u_int32_t)t_cp[0]) << 24) \ - | (((u_int32_t)t_cp[1]) << 16) \ - | (((u_int32_t)t_cp[2]) << 8) \ - | (((u_int32_t)t_cp[3])) \ + register u_char *t_cp = (u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ ; \ - (cp) += 4; \ + (cp) += INT32SZ; \ } #define PUTSHORT(s, cp) { \ - register u_short t_s = (u_short)(s); \ - register u_char *t_cp = (u_char*)(cp); \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ - (cp) += 2; \ + (cp) += INT16SZ; \ } -/* - * Warning: PUTLONG --no-longer-- destroys its first argument. if you - * were depending on this "feature", you will lose. - */ #define PUTLONG(l, cp) { \ register u_int32_t t_l = (u_int32_t)(l); \ - register u_char *t_cp = (u_char*)(cp); \ + register u_char *t_cp = (u_char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ *t_cp = t_l; \ - (cp) += 4; \ + (cp) += INT32SZ; \ } #endif /* !_NAMESER_H_ */ diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index 96248bc0de..35e9007ca7 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985, 1988 + * ++Copyright++ 1985, 1988, 1993 * - - * Copyright (c) 1985, 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 1988, 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 @@ -54,7 +54,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)gethostnamadr.c 6.47 (Berkeley) 6/18/92"; +static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ @@ -63,27 +63,47 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> + +#include <stdio.h> #include <netdb.h> #include <resolv.h> -#include <stdio.h> #include <ctype.h> #include <errno.h> -#include "../conf/portability.h" +#include <syslog.h> + +#ifndef LOG_AUTH +# define LOG_AUTH 0 +#endif + +#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ + +#if defined(BSD) && (BSD >= 199103) +# include <string.h> +#else +# include "../conf/portability.h" +#endif +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif #define MAXALIASES 35 #define MAXADDRS 35 +static const char AskedForGot[] = + "gethostby*.getanswer: asked for \"%s\", got \"%s\""; + static char *h_addr_ptrs[MAXADDRS + 1]; static struct hostent host; static char *host_aliases[MAXALIASES]; -static char hostbuf[BUFSIZ+1]; +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; -char *strpbrk(); + +#ifdef RESOLVSORT +static void addrsort __P((char **, int)); +#endif #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ @@ -104,20 +124,23 @@ typedef union { extern int h_errno; static struct hostent * -getanswer(answer, anslen, iquery) - querybuf *answer; +getanswer(answer, anslen, qname, qclass, qtype) + const querybuf *answer; int anslen; - int iquery; + const char *qname; + int qclass, qtype; { - register HEADER *hp; - register u_char *cp; + register const HEADER *hp; + register const u_char *cp; register int n; - u_char *eom; - char *bp, **ap; + const u_char *eom; + char *bp, **ap, **hap; int type, class, buflen, ancount, qdcount; - int haveanswer, getclass = C_ANY; - char **hap; + int haveanswer, had_error; + int toobig = 0; + char tbuf[MAXDNAME+1]; + host.h_name = NULL; eom = answer->buf + anslen; /* * find first satisfactory answer @@ -126,31 +149,28 @@ getanswer(answer, anslen, iquery) ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - buflen = sizeof(hostbuf); - cp = answer->buf + sizeof(HEADER); - if (qdcount) { - if (iquery) { - if ((n = dn_expand((u_char *)answer->buf, - (u_char *)eom, (u_char *)cp, (u_char *)bp, - buflen)) < 0) { - h_errno = NO_RECOVERY; - return ((struct hostent *) NULL); - } - cp += n + QFIXEDSZ; - host.h_name = bp; - n = strlen(bp) + 1; - bp += n; - buflen -= n; - } else - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - while (--qdcount > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - } else if (iquery) { - if (hp->aa) - h_errno = HOST_NOT_FOUND; - else - h_errno = TRY_AGAIN; - return ((struct hostent *) NULL); + buflen = sizeof hostbuf; + cp = answer->buf + HFIXEDSZ; + if (qdcount != 1) { + h_errno = NO_RECOVERY; + return (NULL); + } + if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) { + h_errno = NO_RECOVERY; + return (NULL); + } + cp += n + QFIXEDSZ; + if (qtype == T_A) { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + host.h_name = bp; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = host.h_name; } ap = host_aliases; *ap = NULL; @@ -161,91 +181,174 @@ getanswer(answer, anslen, iquery) host.h_addr_list = h_addr_ptrs; #endif haveanswer = 0; - while (--ancount >= 0 && cp < eom) { - if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, - (u_char *)cp, (u_char *)bp, buflen)) < 0) - break; - cp += n; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) { + had_error++; + continue; + } + cp += n; /* name */ type = _getshort(cp); - cp += sizeof(u_short); + cp += INT16SZ; /* type */ class = _getshort(cp); - cp += sizeof(u_short) + sizeof(u_int32_t); + cp += INT16SZ + INT32SZ; /* class, TTL */ n = _getshort(cp); - cp += sizeof(u_short); - if (type == T_CNAME) { + cp += INT16SZ; /* len */ + if (class != qclass) { + /* XXX - debug? syslog? */ cp += n; + continue; /* XXX - had_error++ ? */ + } + if (qtype == T_A && type == T_CNAME) { if (ap >= &host_aliases[MAXALIASES-1]) continue; + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if (n < 0) { + had_error++; + continue; + } + 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\"", + host.h_name, bp); + continue; /* XXX - had_error++ ? */ + } + /* Store alias. */ *ap++ = bp; - n = strlen(bp) + 1; + n = strlen(bp) + 1; /* for the \0 */ bp += n; buflen -= n; - continue; - } - if (iquery && type == T_PTR) { - if ((n = dn_expand((u_char *)answer->buf, - (u_char *)eom, (u_char *)cp, (u_char *)bp, - buflen)) < 0) { - cp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; continue; } - cp += n; + strcpy(bp, tbuf); host.h_name = bp; - return(&host); + bp += n; + buflen -= n; + continue; } - if (iquery || type != T_A) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("unexpected answer type %d, size %d\n", - type, n); -#endif + if (type != qtype) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostby*.getanswer: asked for type %d(%s), got %d(%s)", + qtype, qname, type, bp); cp += n; - continue; + continue; /* XXX - had_error++ ? */ } - if (haveanswer) { - if (n != host.h_length) { + switch (type) { + case T_PTR: + if (strcasecmp(qname, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, qname, bp); cp += n; - continue; + continue; /* XXX - had_error++ ? */ + } + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) { + had_error++; + break; + } +#if MULTI_PTRS_ARE_ALIASES + cp += n; + if (!haveanswer) + host.h_name = bp; + else if (ap < &host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + bp += n; + buflen -= n; } - if (class != getclass) { + break; +#else + host.h_name = bp; + return (&host); +#endif + case T_A: + if (strcasecmp(host.h_name, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, host.h_name, bp); cp += n; - continue; + continue; /* XXX - had_error++ ? */ } - } else { - host.h_length = n; - getclass = class; - host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; - if (!iquery) { + if (haveanswer) { + if (n != host.h_length) { + cp += n; + continue; + } + } else { + register int nn; + + host.h_length = n; + host.h_addrtype = (class == C_IN) + ? AF_INET + : AF_UNSPEC; host.h_name = bp; - bp += strlen(bp) + 1; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + buflen -= nn; } - } - bp += sizeof(align) - ((u_int32_t)bp % sizeof(align)); + bp += sizeof(align) - ((u_long)bp % sizeof(align)); - if (bp + n >= &hostbuf[sizeof(hostbuf)]) { + if (bp + n >= &hostbuf[sizeof hostbuf]) { #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf("size (%d) too big\n", n); + if (_res.options & RES_DEBUG) + printf("size (%d) too big\n", n); #endif + had_error++; + continue; + } + if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (_res.options & RES_DEBUG && !toobig++) + printf("Too many addresses (%d)\n", + MAXADDRS); + cp += n; + continue; + } + bcopy(cp, *hap++ = bp, n); + bp += n; + cp += n; break; - } - bcopy(cp, *hap++ = bp, n); - bp +=n; - cp += n; - haveanswer++; - } + default: + abort(); + } /*switch*/ + if (!had_error) + haveanswer++; + } /*while*/ if (haveanswer) { *ap = NULL; -#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ *hap = NULL; +# if defined(RESOLVSORT) + /* + * Note: we sort even if host can take only one address + * in its return structures - should give it the "best" + * address in that case, not some random one + */ + if (_res.nsort && haveanswer > 1 && + qclass == C_IN && qtype == T_A) + addrsort(h_addr_ptrs, haveanswer); +# endif /*RESOLVSORT*/ +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + /* nothing */ #else host.h_addr = h_addr_ptrs[0]; -#endif +#endif /*BSD*/ + if (!host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + strcpy(bp, qname); + host.h_name = bp; + } return (&host); } else { h_errno = TRY_AGAIN; - return ((struct hostent *) NULL); + return (NULL); } } @@ -274,15 +377,15 @@ gethostbyname(name) */ if (!inet_aton(name, &host_addr)) { h_errno = HOST_NOT_FOUND; - return((struct hostent *) NULL); + return (NULL); } host.h_name = (char *)name; host.h_aliases = host_aliases; host_aliases[0] = NULL; host.h_addrtype = AF_INET; - host.h_length = sizeof(u_int32_t); + host.h_length = INT32SZ; h_addr_ptrs[0] = (char *)&host_addr; - h_addr_ptrs[1] = (char *)0; + h_addr_ptrs[1] = NULL; #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ host.h_addr_list = h_addr_ptrs; #else @@ -302,9 +405,9 @@ gethostbyname(name) if (errno == ECONNREFUSED) return (_gethtbyname(name)); else - return ((struct hostent *) NULL); + return (NULL); } - return (getanswer(&buf, n, 0)); + return (getanswer(&buf, n, name, C_IN, T_A)); } struct hostent * @@ -315,17 +418,22 @@ gethostbyaddr(addr, len, type) int n; querybuf buf; register struct hostent *hp; - char qbuf[MAXDNAME]; + char qbuf[MAXDNAME+1]; +#ifdef SUNSECURITY + register struct hostent *rhp; + char **haddr; + u_long old_options; +#endif /*SUNSECURITY*/ extern struct hostent *_gethtbyaddr(); if (type != AF_INET) - return ((struct hostent *) NULL); + 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)); - n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); + n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); if (n < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -333,31 +441,57 @@ gethostbyaddr(addr, len, type) #endif if (errno == ECONNREFUSED) return (_gethtbyaddr(addr, len, type)); - return ((struct hostent *) NULL); + return (NULL); + } + if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR))) + return (NULL); +#ifdef SUNSECURITY + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + old_options = _res.options; + _res.options &= ~RES_DNSRCH; + _res.options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hp->h_name))) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: No A record for %s (verifying [%s])", + hp->h_name, inet_ntoa(*((struct in_addr *)addr))); + _res.options = old_options; + return (NULL); } - hp = getanswer(&buf, n, 1); - if (hp == NULL) - return ((struct hostent *) 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]", + hp->h_name, 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] = (char *)0; + 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 - return(hp); + return (hp); } void _sethtent(f) int f; { - if (hostf == NULL) + if (!hostf) hostf = fopen(_PATH_HOSTS, "r" ); else rewind(hostf); - stayopen |= f; + stayopen = f; } void @@ -375,35 +509,36 @@ _gethtent() char *p; register char *cp, **q; - if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) + if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) return (NULL); again: - if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) + if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) return (NULL); if (*p == '#') goto again; - cp = strpbrk(p, "#\n"); - if (cp == NULL) + if (!(cp = strpbrk(p, "#\n"))) goto again; *cp = '\0'; - cp = strpbrk(p, " \t"); - if (cp == NULL) + if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; /* THIS STUFF IS INTERNET SPECIFIC */ + if (!inet_aton(p, &host_addr)) + goto again; + h_addr_ptrs[0] = (char *)&host_addr; + h_addr_ptrs[1] = NULL; #if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ - host.h_addr_list = host_addrs; + host.h_addr_list = h_addr_ptrs; +#else + host.h_addr = h_addr_ptrs[0]; #endif - host.h_addr = hostaddr; - *((u_int32_t *)host.h_addr) = inet_addr(p); - host.h_length = sizeof (u_int32_t); + host.h_length = INT32SZ; host.h_addrtype = AF_INET; while (*cp == ' ' || *cp == '\t') cp++; host.h_name = cp; q = host.h_aliases = host_aliases; - cp = strpbrk(cp, " \t"); - if (cp != NULL) + if (cp = strpbrk(cp, " \t")) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { @@ -412,8 +547,7 @@ again: } if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; - cp = strpbrk(cp, " \t"); - if (cp != NULL) + if (cp = strpbrk(cp, " \t")) *cp++ = '\0'; } *q = NULL; @@ -455,6 +589,51 @@ _gethtbyaddr(addr, len, type) return (p); } +#ifdef RESOLVSORT +static void +addrsort(ap, num) + char **ap; + int num; +{ + int i, j; + char **p; + short aval[MAXADDRS]; + int needsort = 0; + + p = ap; + for (i = 0; i < num; i++, p++) { + for (j = 0 ; j < _res.nsort; j++) + if (_res.sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) + break; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} +#endif + #if defined(BSD43_BSD43_NFS) || defined(sun) /* some libc's out there are bound internally to these names (UMIPS) */ void @@ -474,7 +653,7 @@ struct hostent * ht_gethostbyname(name) char *name; { - return _gethtbyname(name); + return (_gethtbyname(name)); } struct hostent * @@ -482,13 +661,13 @@ ht_gethostbyaddr(addr, len, type) const char *addr; int len, type; { - return _gethtbyaddr(addr, len, type); + return (_gethtbyaddr(addr, len, type)); } struct hostent * gethostent() { - return _gethtent(); + return (_gethtent()); } void @@ -501,6 +680,26 @@ dns_service() dn_skipname(comp_dn, eom) const u_char *comp_dn, *eom; { - return __dn_skipname(comp_dn, eom); + return (__dn_skipname(comp_dn, eom)); } #endif /*old-style libc with yp junk in it*/ + +#ifdef ultrix +/* more icky libc packaging in ultrix */ +int +local_hostname_length(hostname) + const char *hostname; +{ + int len_host, len_domain; + + if (!*_res.defdname) + res_init(); + len_host = strlen(hostname); + len_domain = strlen(_res.defdname); + if (len_host > len_domain && + !strcasecmp(hostname + len_host - len_domain, _res.defdname) && + hostname[len_host - len_domain - 1] == '.') + return (len_host - len_domain - 1); + return (0); +} +#endif diff --git a/resolv/getnetbyaddr.c b/resolv/getnetbyaddr.c index cd6ca20d63..3bc01addb6 100644 --- a/resolv/getnetbyaddr.c +++ b/resolv/getnetbyaddr.c @@ -32,7 +32,8 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetbyaddr.c 5.7 (Berkeley) 6/1/90"; +static char sccsid[] = "@(#)getnetbyaddr.c 1.1 (Coimbra) 93/06/02"; +static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> @@ -40,8 +41,8 @@ static char sccsid[] = "@(#)getnetbyaddr.c 5.7 (Berkeley) 6/1/90"; extern int _net_stayopen; struct netent * -getnetbyaddr(net, type) - register int32_t net; +_getnetbyaddr(net, type) + register long net; register int type; { register struct netent *p; diff --git a/resolv/getnetbyname.c b/resolv/getnetbyname.c index dd4755a98e..907f583fd2 100644 --- a/resolv/getnetbyname.c +++ b/resolv/getnetbyname.c @@ -32,7 +32,8 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetbyname.c 5.7 (Berkeley) 2/24/91"; +static char sccsid[] = "@(#)getnetbyname.c 1.1 (Coimbra) 93/06/02"; +static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <netdb.h> @@ -41,19 +42,24 @@ static char sccsid[] = "@(#)getnetbyname.c 5.7 (Berkeley) 2/24/91"; extern int _net_stayopen; struct netent * -getnetbyname(name) +_getnetbyname(name) +#if (defined(sun) || defined(DGUX)) + register char *name; +#else register const char *name; +#endif { register struct netent *p; register char **cp; 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) + for (cp = p->n_aliases; *cp != 0; cp++){ + if (strcasecmp(*cp, name) == 0) goto found; + } } found: if (!_net_stayopen) diff --git a/resolv/getnetent.c b/resolv/getnetent.c index 5a3779dcd9..6d1728b206 100644 --- a/resolv/getnetent.c +++ b/resolv/getnetent.c @@ -31,18 +31,35 @@ * SUCH DAMAGE. */ +/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro + * Dep. Matematica Universidade de Coimbra, Portugal, Europe + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * from getnetent.c 1.1 (Coimbra) 93/06/02 + */ + #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getnetent.c 5.8 (Berkeley) 2/24/91"; +static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ -#include <sys/types.h> +#include <sys/param.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -#include <netdb.h> +#include <arpa/nameser.h> + #include <stdio.h> +#include <resolv.h> +#include <netdb.h> #include <string.h> +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + #define MAXALIASES 35 static FILE *netf; @@ -51,9 +68,26 @@ static struct netent net; static char *net_aliases[MAXALIASES]; int _net_stayopen; +void _setnetent __P((int)), _endnetent __P((void)); + void -setnetent(f) - int f; +setnetent(stayopen) +int stayopen; +{ + sethostent(stayopen); + _setnetent(stayopen); +} + +void +endnetent() +{ + endhostent(); + _endnetent(); +} + +void +_setnetent(f) +int f; { if (netf == NULL) netf = fopen(_PATH_NETWORKS, "r" ); @@ -63,7 +97,7 @@ setnetent(f) } void -endnetent() +_endnetent() { if (netf) { fclose(netf); diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c new file mode 100644 index 0000000000..acb958cbeb --- /dev/null +++ b/resolv/getnetnamadr.c @@ -0,0 +1,303 @@ +/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro + * Dep. Matematica Universidade de Coimbra, Portugal, Europe + */ +/* + * Copyright (c) 1983 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) +static char sccsid[] = "@(#)getnetnamadr.c 1.4 (Coimbra) 93/06/03"; +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <stdio.h> +#include <netdb.h> +#include <resolv.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> + +extern int h_errno; + +#if defined(mips) && defined(SYSTYPE_BSD43) +extern int errno; +#endif + +struct netent *_getnetbyaddr __P((long net, int type)); +#if defined(sun) +struct netent *_getnetbyname __P((char *name)); +#else +struct netent *_getnetbyname __P((const char *name)); +#endif + +#define BYADDR 0 +#define BYNAME 1 +#define MAXALIASES 35 + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +typedef union { + long al; + char ac; +} align; + +static struct netent * +getnetanswer(answer, anslen, net_i) + querybuf *answer; + int anslen; + int net_i; +{ + + register HEADER *hp; + register u_char *cp; + register int n; + u_char *eom; + int type, class, buflen, ancount, qdcount, + haveanswer, i, nchar, + getclass = C_ANY, + net_length = 0; + char aux1[30], aux2[30], ans[30], + *in, *st, *pauxt, *bp, **ap, + *paux1 = &aux1[0], + *paux2 = &aux2[0], + flag = 0; +static struct netent net_entry; +static char *net_aliases[MAXALIASES], + netbuf[BUFSIZ+1]; + + /* + * find first satisfactory answer + * + * answer --> +------------+ ( MESSAGE ) + * | Header | + * +------------+ + * | Question | the question for the name server + * +------------+ + * | Answer | RRs answering the question + * +------------+ + * | Authority | RRs pointing toward an authority + * | Additional | RRs holding additional information + * +------------+ + */ + eom = answer->buf + anslen; + hp = &answer->hdr; + ancount = ntohs(hp->ancount); /* #/records in the answer section */ + qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ + bp = netbuf; + buflen = sizeof(netbuf); + cp = answer->buf + HFIXEDSZ; + if (!qdcount) { + if (hp->aa) + h_errno = HOST_NOT_FOUND; + else + h_errno = TRY_AGAIN; + + return ((struct netent *) NULL); + } + while (qdcount-- > 0){ + cp += __dn_skipname(cp, eom) + QFIXEDSZ; + } + ap = net_aliases; + *ap = NULL; + net_entry.n_aliases = net_aliases; + haveanswer = 0; + while (--ancount >= 0 && cp < eom) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) + break; + cp += n; + ans[0] = '\0'; + (void)strcpy(&ans[0], bp); + GETSHORT(type, cp); + GETSHORT(class, cp); + cp += INT32SZ; /* TTL */ + GETSHORT(n, cp); + if (class == C_IN && type == T_PTR) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if (n < 0) { + cp += n; + return (NULL); + } + cp += n; + *ap++ = bp; + bp += (strlen(bp) + 1); + net_entry.n_addrtype = (class == C_IN) + ? AF_INET + : AF_UNSPEC; + haveanswer++; + } + } + if (haveanswer) { + *ap = NULL; + switch (net_i) { + case BYADDR : + net_entry.n_name = *net_entry.n_aliases; + net_entry.n_net = 0L; + break; + case BYNAME : + in = *net_entry.n_aliases; + net_entry.n_name = &ans[0]; + aux2[0] = '\0'; + for (i = 0; i < 4; i++) { + for (st = in, nchar = 0; + *st != '.'; + st++, nchar++) + ; + if (nchar != 1 || *in != '0' || flag) { + flag = 1; + (void)strncpy(paux1, + (i==0) ?in :in-1, + (i==0) ?nchar :nchar+1); + paux1[(i==0) ?nchar :nchar+1] = '\0'; + pauxt = paux2; + paux2 = strcat(paux1, paux2); + paux1 = pauxt; + } + in = ++st; + } + net_entry.n_net = inet_network(paux2); + } + net_entry.n_aliases++; + return (&net_entry); + } else { + h_errno = TRY_AGAIN; + return ((struct netent *) NULL); + } +} + +struct netent * +getnetbyaddr(net, net_type) + register long net; + register int net_type; +{ + unsigned int netbr[4]; + int nn, anslen; + querybuf buf; + char qbuf[MAXDNAME]; + unsigned long net2; + struct netent *net_entry; + + if (net_type != AF_INET) + return (_getnetbyaddr(net, net_type)); + + for (nn = 4, net2 = net; net2; net2 >>= 8) { + netbr[--nn] = net2 & 0xff; + } + switch (nn) { + case 3: /* Class A */ + (void)sprintf(qbuf, "0.0.0.%u.in-addr.arpa", + netbr[3]); + break; + case 2: /* Class B */ + (void)sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", + netbr[3], netbr[2]); + break; + case 1: /* Class C */ + (void)sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", + netbr[3], netbr[2], netbr[1]); + break; + case 0: /* Class D - E */ + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + netbr[3], netbr[2], netbr[1], netbr[0]); + break; + } + anslen = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); + if (anslen < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("res_query failed\n"); +#endif + if (errno == ECONNREFUSED) + return (_getnetbyaddr(net, net_type)); + return (_getnetbyaddr(net, net_type)); + } + net_entry = getnetanswer(&buf, anslen, BYADDR); + if (net_entry) { + unsigned u_net = net; /* maybe net should be unsigned ? */ + + /* Strip trailing zeros */ + while ((u_net & 0xff) == 0 && u_net != 0) { + u_net >>= 8; + } + net_entry->n_net = u_net; + return (net_entry); + } else { + return (_getnetbyaddr(net, net_type)); + } +} + +struct netent * +getnetbyname(net) +#if defined(sun) + register char *net; +#else + register const char *net; +#endif +{ + unsigned int netbr[4]; + int anslen; + querybuf buf; + char qbuf[MAXDNAME]; + struct netent *net_entry; + + (void)strcpy(&qbuf[0],net); + anslen = res_search(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); + if (anslen < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf("res_query failed\n"); +#endif + if (errno == ECONNREFUSED) + return (_getnetbyname(net)); + return (_getnetbyname(net)); + } + net_entry = getnetanswer(&buf, anslen, BYNAME); + if (net_entry) + return (net_entry); + else + return (_getnetbyname(net)); +} diff --git a/resolv/herror.c b/resolv/herror.c index 236824e9ac..759ff7b65e 100644 --- a/resolv/herror.c +++ b/resolv/herror.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1987 + * ++Copyright++ 1987, 1993 * - - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1987, 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 @@ -54,14 +54,19 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)herror.c 6.6 (Berkeley) 2/24/91"; +static char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ -#include <sys/types.h> +#include <sys/param.h> #include <sys/uio.h> #include <netdb.h> -#include "../conf/portability.h" +#if defined(BSD) && (BSD >= 199103) +# include <unistd.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif char *h_errlist[] = { "Error 0", diff --git a/resolv/nsap_addr.c b/resolv/nsap_addr.c new file mode 100644 index 0000000000..ea1850132a --- /dev/null +++ b/resolv/nsap_addr.c @@ -0,0 +1,97 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id$"; +#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> + +#include "../conf/portability.h" + +#if !defined(isxdigit) /* XXX - could be a function */ +static int +isxdigit(c) + register int c; +{ + return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')); +} +#endif + +static char +xtob(c) + register int c; +{ + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(ascii, binary, maxlen) + const char *ascii; + u_char *binary; + int maxlen; +{ + register u_char c, nib; + u_char *start = binary; + 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/resolv/res_comp.c b/resolv/res_comp.c index f8890f3938..ae40d6334f 100644 --- a/resolv/res_comp.c +++ b/resolv/res_comp.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985 + * ++Copyright++ 1985, 1993 * - - * Copyright (c) 1985 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 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 @@ -54,18 +54,27 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_comp.c 6.22 (Berkeley) 3/19/91"; +static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> -#include <arpa/nameser.h> #include <netinet/in.h> -#include <resolv.h> +#include <arpa/nameser.h> + #include <stdio.h> -#include "../conf/portability.h" +#include <resolv.h> +#include <ctype.h> -static int dn_find(); +#if defined(BSD) && (BSD >= 199103) +# include <unistd.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +static int dn_find __P((u_char *exp_dn, u_char *msg, + u_char **dnptrs, u_char **lastdnptr)); /* * Expand compressed domain name 'comp_dn' to full domain name. @@ -74,18 +83,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 @@ -119,7 +130,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length) 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); checked += 2; @@ -137,6 +148,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); @@ -154,8 +168,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; { @@ -167,6 +182,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++) @@ -232,31 +248,44 @@ 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 */ switch (n & INDIR_MASK) { - case 0: /* normal case, n == len */ + case 0: /* normal case, n == len */ cp += n; continue; - default: /* illegal type */ - return (-1); case INDIR_MASK: /* indirection */ cp++; + break; + default: /* illegal type */ + return -1; } break; } + if (cp > eom) + return -1; 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. @@ -286,7 +315,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') @@ -317,32 +346,32 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr) * used by sendmail. */ -u_short +u_int16_t _getshort(msgp) - register u_char *msgp; + register const u_char *msgp; { - register u_short u; + register u_int16_t u; GETSHORT(u, msgp); - return u; + return (u); } u_int32_t _getlong(msgp) - register u_char *msgp; + register const u_char *msgp; { register u_int32_t u; GETLONG(u, msgp); - return u; + return (u); } void #if defined(__STDC__) || defined(__cplusplus) -__putshort(register u_short s, register u_char *msgp) +__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */ #else __putshort(s, msgp) - register u_short s; + register u_int16_t s; register u_char *msgp; #endif { @@ -356,3 +385,36 @@ __putlong(l, msgp) { PUTLONG(l, msgp); } + +#ifdef ultrix +/* ultrix 4.0 had some icky packaging in its libc.a. alias for it here. + * there is more gunk of this kind over in res_debug.c. + */ +#undef putshort +void +#if defined(__STDC__) || defined(__cplusplus) +putshort(register u_short s, register u_char *msgp) +#else +putshort(s, msgp) + register u_short s; + register u_char *msgp; +#endif +{ + __putshort(s, msgp); +} +#undef putlong +void +putlong(l, msgp) + register u_int32_t l; + register u_char *msgp; +{ + __putlong(l, msgp); +} + +#undef dn_skipname +dn_skipname(comp_dn, eom) + const u_char *comp_dn, *eom; +{ + return __dn_skipname(comp_dn, eom); +} +#endif /* Ultrix 4.0 hackery */ diff --git a/resolv/res_debug.c b/resolv/res_debug.c index 15e716947e..c16bea8bc5 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985, 1990 + * ++Copyright++ 1985, 1990, 1993 * - - * Copyright (c) 1985, 1990 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 1990, 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 @@ -54,7 +54,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_debug.c 5.36 (Berkeley) 3/6/91"; +static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ @@ -62,16 +62,20 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> -#include <resolv.h> + #include <stdio.h> -#include "../conf/portability.h" +#include <resolv.h> +#if defined(BSD) && (BSD >= 199103) +# include <string.h> +#else +# include "../conf/portability.h" +#endif -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)); +#if defined(USE_OPTIONS_H) +# include "../conf/options.h" +#endif -char *_res_opcodes[] = { +const char *_res_opcodes[] = { "QUERY", "IQUERY", "CQUERYM", @@ -90,7 +94,7 @@ char *_res_opcodes[] = { "ZONEREF", }; -char *_res_resultcodes[] = { +const char *_res_resultcodes[] = { "NOERROR", "FORMERR", "SERVFAIL", @@ -111,116 +115,131 @@ char *_res_resultcodes[] = { static char retbuf[16]; -static char * +static const char * dewks(wks) int wks; { 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(retbuf, "%d", wks); return (retbuf); } } -static char * +static const char * deproto(protonum) int protonum; { 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(retbuf, "%d", protonum); return (retbuf); } } -static char * +static const u_char * do_rrset(msg, cp, cnt, pflag, file, hs) int cnt, pflag; - char *cp,*msg, *hs; + const u_char *cp, *msg; + const char *hs; FILE *file; { int n; - char *t1, *t2, *list[100],**tt; int sflag; + /* - * Print answer records + * Print answer records. */ sflag = (_res.pfcode & pflag); if (n = ntohs(cnt)) { - *list=NULL; - if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + 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 ((cp - msg) > PACKETSZ) return (NULL); } - if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + if ((!_res.pfcode) || + ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) putc('\n', file); } - return(cp); + return (cp); } +void __p_query(msg) - char *msg; + const u_char *msg; { __fp_query(msg, stdout); } +#ifdef ultrix +/* ultrix 4.0's packaging has some icky packaging. alias for it here. + * there is more junk of this kind over in res_comp.c. + */ +void +p_query(msg) + const u_char *msg; +{ + __p_query(msg); +} +#endif + /* * Print the current options. * This is intended to be primarily a debugging routine. @@ -230,15 +249,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); } @@ -247,21 +265,26 @@ __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; +#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", + fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d", _res_opcodes[hp->opcode], _res_resultcodes[hp->rcode], ntohs(hp->id)); @@ -271,29 +294,28 @@ __fp_query(msg,file) if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { fprintf(file,"; flags:"); if (hp->qr) - fprintf(file," qr"); + fprintf(file, " qr"); if (hp->aa) - fprintf(file," aa"); + fprintf(file, " aa"); if (hp->tc) - fprintf(file," tc"); + fprintf(file, " tc"); if (hp->rd) - fprintf(file," rd"); + fprintf(file, " rd"); if (hp->ra) - fprintf(file," ra"); + fprintf(file, " ra"); if (hp->pr) - fprintf(file," 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, "; Ques: %d", ntohs(hp->qdcount)); + fprintf(file, ", Ans: %d", ntohs(hp->ancount)); + fprintf(file, ", Auth: %d", ntohs(hp->nscount)); + 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,73 +324,99 @@ __fp_query(msg,file) fprintf(file,";; QUESTIONS:\n"); while (--n >= 0) { fprintf(file,";;\t"); + TruncTest(cp); cp = p_cdname(cp, msg, file); - if (cp == NULL) - return; + ErrorTest(cp); + TruncTest(cp); if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) fprintf(file, ", type = %s", - __p_type(_getshort(cp))); - cp += sizeof(u_short); + __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_short); + fprintf(file, ", class = %s\n", + __p_class(_getshort((u_char*)cp))); + cp += INT16SZ; + putc('\n', file); } } /* * Print authoritative answer records */ + TruncTest(cp); cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file, ";; ANSWERS:\n"); - if (cp == NULL) - return; + ErrorTest(cp); /* * print name server records */ + TruncTest(cp); cp = do_rrset(msg, 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, ";; ADDITIONAL RECORDS:\n"); - if (!cp) - return; + 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 *)msg + 512, (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') { + if (name[0] == '\0') putc('.', file); - } else { + else fputs(name, 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; - if ((n = dn_expand((u_char *)msg, (u_char *)msg + 512, (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); @@ -380,32 +428,30 @@ p_fqname(cp, msg, file) return (cp + n); } - - /* * 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 ((cp = p_fqname(cp, msg, file)) == NULL) return (NULL); /* compression error */ - type = _getshort(cp); - cp += sizeof(u_short); - class = _getshort(cp); - cp += sizeof(u_short); - tmpttl = _getlong(cp); - cp += sizeof(u_int32_t); - dlen = _getshort(cp); - cp += sizeof(u_short); + type = _getshort((u_char*)cp); + cp += INT16SZ; + class = _getshort((u_char*)cp); + cp += INT16SZ; + tmpttl = _getlong((u_char*)cp); + cp += INT32SZ; + dlen = _getshort((u_char*)cp); + cp += INT16SZ; cp1 = cp; if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID)) fprintf(file, "\t%lu", tmpttl); @@ -420,7 +466,7 @@ p_rr(cp, msg, file) switch (class) { case C_IN: case C_HS: - bcopy(cp, (char *)&inaddr, sizeof(inaddr)); + bcopy(cp, (char *)&inaddr, INADDRSZ); if (dlen == 4) { fprintf(file,"\t%s", inet_ntoa(inaddr)); cp += dlen; @@ -430,11 +476,11 @@ p_rr(cp, msg, file) u_short port; address = inet_ntoa(inaddr); - cp += sizeof(inaddr); + cp += INADDRSZ; protocol = *(u_char*)cp; cp += sizeof(u_char); - port = _getshort(cp); - cp += sizeof(u_short); + port = _getshort((u_char*)cp); + cp += INT16SZ; fprintf(file, "\t%s\t; proto %d, port %d", address, protocol, port); } @@ -454,6 +500,7 @@ p_rr(cp, msg, file) break; case T_HINFO: + case T_ISDN: if (n = *cp++) { fprintf(file,"\t%.*s", n, cp); cp += n; @@ -470,25 +517,28 @@ p_rr(cp, msg, file) putc(' ', file); cp = p_fqname(cp, msg, file); /* mail addr */ fputs(" (\n", file); - t = _getlong(cp); cp += sizeof(u_int32_t); + t = _getlong((u_char*)cp); cp += INT32SZ; fprintf(file,"\t\t\t%lu\t; serial\n", t); - t = _getlong(cp); cp += sizeof(u_int32_t); + t = _getlong((u_char*)cp); cp += INT32SZ; fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); - t = _getlong(cp); cp += sizeof(u_int32_t); + t = _getlong((u_char*)cp); cp += INT32SZ; fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); - t = _getlong(cp); cp += sizeof(u_int32_t); + t = _getlong((u_char*)cp); cp += INT32SZ; fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); - t = _getlong(cp); cp += sizeof(u_int32_t); + t = _getlong((u_char*)cp); cp += INT32SZ; fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t)); break; case T_MX: - fprintf(file,"\t%d ", _getshort(cp)); - cp += sizeof(u_short); + case T_AFSDB: + case T_RT: + fprintf(file,"\t%d ", _getshort((u_char*)cp)); + cp += INT16SZ; cp = p_fqname(cp, msg, file); break; case T_TXT: + case T_X25: (void) fputs("\t\"", file); cp2 = cp1 + dlen; while (cp < cp2) { @@ -504,6 +554,11 @@ 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); @@ -514,23 +569,23 @@ p_rr(cp, msg, file) case T_UINFO: putc('\t', file); - fputs(cp, file); + fputs((char *)cp, file); cp += dlen; break; case T_UID: case T_GID: if (dlen == 4) { - fprintf(file,"\t%u", _getlong(cp)); - cp += sizeof(int32_t); + fprintf(file,"\t%u", _getlong((u_char*)cp)); + cp += INT32SZ; } break; case T_WKS: - if (dlen < sizeof(u_int32_t) + 1) + if (dlen < INT32SZ + 1) break; - bcopy(cp, (char *)&inaddr, sizeof(inaddr)); - cp += sizeof(u_int32_t); + bcopy(cp, (char *)&inaddr, INADDRSZ); + cp += INT32SZ; fprintf(file, "\t%s %s ( ", inet_ntoa(inaddr), deproto((int) *cp)); @@ -559,7 +614,7 @@ p_rr(cp, msg, file) case T_UNSPEC: { int NumBytes = 8; - char *DataPtr; + u_char *DataPtr; int i; if (dlen < NumBytes) NumBytes = dlen; @@ -594,92 +649,66 @@ static char nbuf[40]; /* * Return a string for the type */ -char * +const char * __p_type(type) int type; { 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_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_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_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; { - 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; { switch (option) { case RES_INIT: return "init"; @@ -692,6 +721,8 @@ p_option(option) case RES_DEFNAMES: return "defnam"; case RES_STAYOPEN: return "styopn"; case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; default: sprintf(nbuf, "?0x%x?", option); return nbuf; } } @@ -708,7 +739,7 @@ __p_time(value) if (value == 0) { strcpy(nbuf, "0 secs"); - return(nbuf); + return (nbuf); } secs = value % 60; @@ -743,5 +774,5 @@ __p_time(value) *p++ = ' '; (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); } - return(nbuf); + return (nbuf); } diff --git a/resolv/res_init.c b/resolv/res_init.c index f3bcebc099..b6b1368ea5 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985, 1989 + * ++Copyright++ 1985, 1989, 1993 * - - * Copyright (c) 1985, 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 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 @@ -54,7 +54,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_init.c 6.15 (Berkeley) 2/24/91"; +static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ @@ -63,36 +63,56 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> -#include <resolv.h> + #include <stdio.h> -#include "../conf/portability.h" +#include <ctype.h> +#include <resolv.h> +#if defined(BSD) && (BSD >= 199103) +# include <unistd.h> +# include <stdlib.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +#if defined(USE_OPTIONS_H) +# include "../conf/options.h" +#endif + +static void res_setoptions __P((char *, char *)); + +#ifdef RESOLVSORT +static u_int32_t net_mask __P((struct in_addr)); +#endif +#if !defined(isascii) /* XXX - could be a function */ +# define isascii(c) (!(c & 0200)) +#endif /* - * Resolver state default settings + * Resolver state default settings. */ -struct __res_state _res = { - RES_TIMEOUT, /* retransmition time interval */ - 4, /* number of times to retransmit */ - RES_DEFAULT, /* options flags */ - 1, /* number of name servers */ -}; +struct __res_state _res; /* * Set up default settings. If the configuration file exist, the values * there will have precedence. Otherwise, the server address is set to - * 127.0.0.1 and the default domain name comes from the gethostname(). + * INADDR_ANY and the default domain name comes from the gethostname(). * - * Previous resolver versions used INADDR_ANY rather than IN_LOOPBACKNET. - * This has bad side-effects in the kernel since 0.0.0.0 means "any interface" - * and the first one found may or may not be the loopback interface. - * If it is a point-to-point interface, then the SLIP or PPP or DDCMP state - * must be "up" in order for the packets to loop correctly. This is deemed - * "bad". + * 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 only be used if you want to redefine your - * domain or run without a server on your machine. + * 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 */ @@ -100,24 +120,79 @@ res_init() { register FILE *fp; register char *cp, **pp; - register int n; + register int n, dots; char buf[BUFSIZ]; int nserv = 0; /* number of nameserver records read from file */ int haveenv = 0; int havesearch = 0; +#ifdef RESOLVSORT + int nsort = 0; + char *net; +#endif + /* + * These four 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 + * fields of _res before res_init() is called, res_init() will not + * alter them. Of course, if an application is setting them to + * _zero_ before calling res_init(), hoping to override what used + * to be the static default, we can't detect it and unexpected results + * 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. + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!_res.options) + _res.options = RES_DEFAULT; + +#ifdef USELOOPBACK _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); +#else + _res.nsaddr.sin_addr.s_addr = INADDR_ANY; +#endif _res.nsaddr.sin_family = AF_INET; _res.nsaddr.sin_port = htons(NAMESERVER_PORT); _res.nscount = 1; + _res.ndots = 1; _res.pfcode = 0; /* Allow user to override the local domain definition */ if ((cp = getenv("LOCALDOMAIN")) != NULL) { - (void)strncpy(_res.defdname, cp, sizeof(_res.defdname)); - if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) - *cp = '\0'; + (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); haveenv++; + + /* + * Set search list to be blank-separated strings + * from rest of env value. Permits users of LOCALDOMAIN + * to still have a search list, and anyone to set the + * one that they want to use as an individual (even more + * important now that the rfc1535 stuff restricts searches) + */ + cp = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == '\n') /* silly backwards compat */ + break; + else if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + havesearch = 1; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') + cp++; + *cp = '\0'; + *pp++ = 0; } if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { @@ -162,7 +237,9 @@ 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; @@ -196,33 +273,167 @@ res_init() } continue; } +#ifdef RESOLVSORT + if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) { + struct in_addr a; + + cp = buf + sizeof("sortlist") - 1; + while (nsort < MAXRESOLVSORT) { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + net = cp; + while (*cp && *cp != '/' && + isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + _res.sort_list[nsort].addr = a; + if (n == '/') { + *cp++ = n; + net = cp; + while (*cp && isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + _res.sort_list[nsort].mask = a.s_addr; + } else { + _res.sort_list[nsort].mask = + net_mask(_res.sort_list[nsort].addr); + } + } else { + _res.sort_list[nsort].mask = + net_mask(_res.sort_list[nsort].addr); + } + nsort++; + } + *cp++ = n; + } + continue; + } +#endif + if (!strncmp(buf, "options", sizeof("options") -1)) { + res_setoptions(buf + sizeof("options") - 1, "conf"); + continue; + } } if (nserv > 1) _res.nscount = nserv; +#ifdef RESOLVSORT + _res.nsort = nsort; +#endif (void) fclose(fp); - } + } /*if(fopen)*/ if (_res.defdname[0] == 0) { - if (gethostname(buf, sizeof(_res.defdname)) == 0 && - (cp = strchr(buf, '.'))) + if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + (cp = strchr(buf, '.'))) { (void)strcpy(_res.defdname, cp + 1); + } } /* find components of local domain that might be searched */ if (havesearch == 0) { pp = _res.dnsrch; *pp++ = _res.defdname; - for (cp = _res.defdname, n = 0; *cp; cp++) - if (*cp == '.') - n++; + *pp = NULL; + +#ifndef RFC1535 + dots = 0; + for (cp = _res.defdname; *cp; cp++) + dots += (*cp == '.'); + cp = _res.defdname; - for (; - n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; - n--) { - cp = strchr(cp, '.'); - *pp++ = ++cp; + while (pp < _res.dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) { + break; + } + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; } - *pp++ = 0; + *pp = NULL; +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + 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) { + res_setoptions(cp, "env"); } _res.options |= RES_INIT; return (0); } + + +static void +res_setoptions(options, source) + char *options, *source; +{ + char *cp = options; + int i; + +#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') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + _res.ndots = i; + else + _res.ndots = RES_MAXNDOTS; +#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? */ + } + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + else + return (htonl(IN_CLASSC_NET)); +} +#endif diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 8d0e768b58..ade1ed2794 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985 + * ++Copyright++ 1985, 1993 * - - * Copyright (c) 1985 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 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 @@ -54,36 +54,46 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_mkquery.c 6.16 (Berkeley) 3/6/91"; +static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> #include <netinet/in.h> #include <arpa/nameser.h> -#include <resolv.h> + #include <stdio.h> -#include "../conf/portability.h" +#include <resolv.h> +#if defined(BSD) && (BSD >= 199103) +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif /* * 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 */ + 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[20], **dpp, **lastdnptr; #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -93,21 +103,21 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) /* * Initialize header fields. */ - if ((buf == NULL) || (buflen < sizeof(HEADER))) + if ((buf == NULL) || (buflen < HFIXEDSZ)) return(-1); - bzero(buf, sizeof(HEADER)); + bzero(buf, HFIXEDSZ); 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 + sizeof(HEADER); - buflen -= sizeof(HEADER); + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; dpp = dnptrs; *dpp++ = buf; *dpp++ = NULL; - lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; /* * perform opcode specific processing */ @@ -115,15 +125,14 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) case QUERY: 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); - cp += sizeof(u_short); - __putshort(class, (u_char *)cp); - cp += sizeof(u_short); + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; hp->qdcount = htons(1); if (op == QUERY || data == NULL) break; @@ -131,19 +140,19 @@ 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) + n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); + if (n < 0) return (-1); cp += n; buflen -= n; - __putshort(T_NULL, (u_char *)cp); - cp += sizeof(u_short); - __putshort(class, (u_char *)cp); - cp += sizeof(u_short); - __putlong(0, (u_char *)cp); - cp += sizeof(u_int32_t); - __putshort(0, (u_char *)cp); - cp += sizeof(u_short); + __putshort(T_NULL, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(0, cp); + cp += INT16SZ; hp->arcount = htons(1); break; @@ -154,14 +163,14 @@ 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); - cp += sizeof(u_short); - __putshort(class, (u_char *)cp); - cp += sizeof(u_short); - __putlong(0, (u_char *)cp); - cp += sizeof(u_int32_t); - __putshort(datalen, (u_char *)cp); - cp += sizeof(u_short); + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(datalen, cp); + cp += INT16SZ; if (datalen) { bcopy(data, cp, datalen); cp += datalen; @@ -189,13 +198,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) return (-1); cp += n; __putshort(type, cp); - cp += sizeof(u_short); + cp += INT16SZ; __putshort(class, cp); - cp += sizeof(u_short); + cp += INT16SZ; __putlong(0, cp); - cp += sizeof(u_int32_t); + cp += INT32SZ; __putshort(datalen, cp); - cp += sizeof(u_short); + cp += INT16SZ; if (datalen) { bcopy(data, cp, datalen); cp += datalen; @@ -212,13 +221,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen) return (-1); cp += n; __putshort(newrr->r_type, cp); - cp += sizeof(u_short); + cp += INT16SZ; __putshort(newrr->r_class, cp); - cp += sizeof(u_short); + cp += INT16SZ; __putlong(0, cp); - cp += sizeof(u_int32_t); + cp += INT32SZ; __putshort(newrr->r_size, cp); - cp += sizeof(u_short); + cp += INT16SZ; if (newrr->r_size) { bcopy(newrr->r_data, cp, newrr->r_size); cp += newrr->r_size; diff --git a/resolv/res_query.c b/resolv/res_query.c index 782e183701..7d552df7f3 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1988 + * ++Copyright++ 1988, 1993 * - - * Copyright (c) 1988 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1988, 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 @@ -54,7 +54,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_query.c 5.11 (Berkeley) 3/6/91"; +static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ @@ -62,12 +62,22 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> + +#include <stdio.h> #include <netdb.h> #include <resolv.h> -#include <stdio.h> #include <ctype.h> #include <errno.h> -#include "../conf/portability.h" +#if defined(BSD) && (BSD >= 199306) +# include <stdlib.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ @@ -75,6 +85,7 @@ static char rcsid[] = "$Id$"; #define MAXPACKET 1024 #endif +char *__hostalias __P((const char *)); int h_errno; /* @@ -84,27 +95,31 @@ 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; + hp->rcode = NOERROR; /* default */ + if ((_res.options & RES_INIT) == 0 && res_init() == -1) 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) @@ -113,17 +128,16 @@ 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) printf(";; res_query: send error\n"); #endif h_errno = TRY_AGAIN; - return(n); + return (n); } - hp = (HEADER *) answer; if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) @@ -149,86 +163,148 @@ res_query(name, class, type, answer, anslen) } return (-1); } - return(n); + return (n); } /* * Formulate a normal query, send, and retrieve answer in supplied buffer. * Return the size of the response on success, -1 on error. * If enabled, implement search rules until answer or unrecoverable failure - * is detected. Error number is left in h_errno. - * Only useful for queries in the same name hierarchy as the local host - * (not, for example, for host address-to-name lookups in domain in-addr.arpa). + * is detected. Error code, if any, is left in h_errno. */ int res_search(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 */ { - register char *cp, **domain; - int n, ret, got_nodata = 0; - char *__hostalias(); + register const char *cp, * const *domain; + 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) return (-1); errno = 0; h_errno = HOST_NOT_FOUND; /* default, if we never query */ - for (cp = name, n = 0; *cp; cp++) - if (*cp == '.') - n++; - if (n == 0 && (cp = __hostalias(name))) + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if ((cp > name) && (*--cp == '.')) + trailing_dot++; + + /* + * if there aren't any dots, it could be a user-level alias + */ + if ((!dots) && (cp = __hostalias(name))) return (res_query(cp, class, type, answer, anslen)); /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + if (dots >= _res.ndots) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return (ret); + saved_herrno = h_errno; + tried_as_is++; + } + + /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ - if ((n == 0 && _res.options & RES_DEFNAMES) || - (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) - for (domain = _res.dnsrch; *domain; domain++) { - ret = res_querydomain(name, *domain, class, type, - answer, anslen); + if (((!dots) && _res.options & RES_DEFNAMES) || + (dots && (!trailing_dot) && _res.options & RES_DNSRCH) + ) { + int done = 0; + + for (domain = (const char * const *)_res.dnsrch; + *domain && !done; + domain++) { + + ret = res_querydomain(name, *domain, class, type, + answer, anslen); + if (ret > 0) + return (ret); + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + h_errno = TRY_AGAIN; + return (-1); + } + + switch (h_errno) { + case NO_DATA: + got_nodata++; + /* FALLTHROUGH */ + 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++; + } + + /* if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if (!(_res.options & RES_DNSRCH)) + done++; + } + } + + /* if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!tried_as_is) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); if (ret > 0) return (ret); - /* - * If no server present, give up. - * If name isn't found in this domain, - * keep trying higher domains in the search list - * (if that's enabled). - * On a NO_DATA error, keep trying, otherwise - * a wildcard entry of another type could keep us - * from finding this entry higher in the domain. - * If we get some other error (negative answer or - * server failure), then stop searching up, - * but try the input name below in case it's fully-qualified. - */ - if (errno == ECONNREFUSED) { - h_errno = TRY_AGAIN; - return (-1); - } - if (h_errno == NO_DATA) - got_nodata++; - if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) || - (_res.options & RES_DNSRCH) == 0) - break; + saved_herrno = h_errno; } - /* - * If the search/default failed, try the name as fully-qualified, - * but only if it contained at least one dot (even trailing). - * This is purely a heuristic; we assume that any reasonable query - * about a top-level domain (for servers, SOA, etc) will not use - * res_search. + + /* if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's h_errno + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless h_errno, that being the one from + * the last DNSRCH we did. */ - if (n && (ret = res_querydomain(name, (char *)NULL, class, type, - answer, anslen)) > 0) - return (ret); - if (got_nodata) + if (saved_herrno != -1) + h_errno = saved_herrno; + else if (got_nodata) h_errno = NO_DATA; + else if (got_servfail) + h_errno = TRY_AGAIN; return (-1); } @@ -236,20 +312,21 @@ 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; #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) { /* @@ -257,14 +334,15 @@ res_querydomain(name, domain, class, type, answer, anslen) * copy without '.' if present. */ n = strlen(name) - 1; - if (name[n] == '.' && n < sizeof(nbuf) - 1) { + if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) { bcopy(name, nbuf, n); nbuf[n] = '\0'; } else longname = name; - } else - (void)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)); } @@ -273,9 +351,9 @@ char * __hostalias(name) register const char *name; { - register char *C1, *C2; + register char *cp1, *cp2; FILE *fp; - char *file, *getenv(), *strcpy(), *strncpy(); + char *file; char buf[BUFSIZ]; static char abuf[MAXDNAME]; @@ -284,17 +362,17 @@ __hostalias(name) return (NULL); buf[sizeof(buf) - 1] = '\0'; while (fgets(buf, sizeof(buf), fp)) { - for (C1 = buf; *C1 && !isspace(*C1); ++C1); - if (!*C1) + for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); + if (!*cp1) break; - *C1 = '\0'; + *cp1 = '\0'; if (!strcasecmp(buf, name)) { - while (isspace(*++C1)); - if (!*C1) + while (isspace(*++cp1)); + if (!*cp1) break; - for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); - abuf[sizeof(abuf) - 1] = *C2 = '\0'; - (void)strncpy(abuf, C1, sizeof(abuf) - 1); + for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); + abuf[sizeof(abuf) - 1] = *cp2 = '\0'; + (void)strncpy(abuf, cp1, sizeof(abuf) - 1); fclose(fp); return (abuf); } diff --git a/resolv/res_send.c b/resolv/res_send.c index 65763fddb8..9a3bafe1f2 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -1,8 +1,8 @@ /* - * ++Copyright++ 1985, 1989 + * ++Copyright++ 1985, 1989, 1993 * - - * Copyright (c) 1985, 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1985, 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 @@ -54,10 +54,17 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_send.c 6.27 (Berkeley) 2/24/91"; +static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$Id$"; #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. */ @@ -69,15 +76,29 @@ static char rcsid[] = "$Id$"; #include <netinet/in.h> #include <arpa/nameser.h> #include <arpa/inet.h> + #include <stdio.h> #include <errno.h> #include <resolv.h> -#include "../conf/portability.h" +#if defined(BSD) && (BSD >= 199306) +# include <stdlib.h> +# include <string.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; +static int connected = 0; /* is the socket connected */ +static int vc = 0; /* is the socket a virtual ciruit? */ #ifndef FD_SET +/* XXX - should be in portability.h */ #define NFDBITS 32 #define FD_SETSIZE 32 #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) @@ -86,121 +107,310 @@ static struct sockaddr no_addr; #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) #endif -res_send(buf, buflen, answer, anslen) - const char *buf; - int buflen; - char *answer; - int anslen; -{ - 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); +#ifndef DEBUG +# define Dprint(cond, args) /*empty*/ +# define DprintQ(cond, args, query) /*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) {\ + fprintf args;\ + __p_query(query);\ + } 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].%d): %s\n", + string, + inet_ntoa(address.sin_addr), + 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 - if (!(_res.options & RES_INIT)) - if (res_init() == -1) { - return(-1); + +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 + * our_server(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +static int +our_server(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 + * name_in_query(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 + */ +static int +name_in_query(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 + * queries_match(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 + */ +static int +queries_match(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 (!name_in_query(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_send(buf, buflen, ans, anssiz) + const u_char *buf; + int buflen; + u_char *ans; + int anssiz; +{ + HEADER *hp = (HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + int gotsomewhere = 0, + connreset = 0, + terrno = ETIMEDOUT; + + 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) + return (-1); + } v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; - id = hp->id; 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(AF_INET, SOCK_STREAM, PF_UNSPEC); 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) { + (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 @@ -212,35 +422,33 @@ 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) { /* @@ -248,10 +456,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[512]; + + n = (len > sizeof(junk) + ? sizeof(junk) + : len); if ((n = read(s, junk, n)) > 0) len -= n; else @@ -262,20 +473,23 @@ 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(AF_INET, SOCK_DGRAM, PF_UNSPEC); if (s < 0) { - terrno = errno; -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("socket (dg) failed"); -#endif - continue; + bad_dg_sock: terrno = errno; + Perror(stderr, "socket(dg)", errno); + return (-1); } + connected = 0; } -#if BSD >= 43 /* - * 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 @@ -292,30 +506,29 @@ 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 (!connected) { if (connect(s, - (struct sockaddr *) - &_res.nsaddr_list[ns], + (struct sockaddr *)nsap, sizeof(struct sockaddr) - ) < 0) { -#ifdef DEBUG - if (_res.options & RES_DEBUG) - perror("connect"); -#endif - continue; + ) < 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; + Perror(stderr, "send", errno); + badns |= (1<<ns); + _res_close(); + goto next_ns; } } else { /* @@ -323,23 +536,39 @@ res_send(buf, buflen, answer, anslen) * for responses from more than one server. */ if (connected) { - (void) connect(s, &no_addr, - sizeof(no_addr)); +#if defined(BSD) && (BSD >= 199103) + 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(AF_INET, SOCK_DGRAM, + PF_UNSPEC); + 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; } -#endif /* BSD */ 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; + (struct sockaddr *)nsap, + sizeof(struct sockaddr)) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1<<ns); + _res_close(); + goto next_ns; } -#if BSD >= 43 } -#endif /* * Wait for reply @@ -350,115 +579,162 @@ 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 -#if BSD >= 43 + Dprint(_res.options & RES_DEBUG, + (stdout, ";; timeout\n") + ); gotsomewhere = 1; -#endif - 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; + fromlen = sizeof(struct sockaddr_in); + resplen = recvfrom(s, 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); + goto wait; + } +#if CHECK_SRVR_ADDR + if (!(_res.options & RES_INSECURE1) && + !our_server(&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); + goto wait; + } #endif + if (!(_res.options & RES_INSECURE2) && + !queries_match(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); goto wait; } - 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 DEBUG + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(_res.options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans); badns |= (1<<ns); - continue; + _res_close(); + 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*/ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; got answer:\n"), + ans); /* * 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 */ - else + } else { errno = terrno; + } return (-1); } @@ -469,10 +745,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/resolv/resolv.h b/resolv/resolv.h index b8f1f65605..aa3efa0be1 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -1,13 +1,8 @@ /* - * @(#)resolv.h 5.15 (Berkeley) 4/3/91 - * $Id$ - */ - -/* - * ++Copyright++ 1983, 1987, 1989 + * ++Copyright++ 1983, 1987, 1989, 1993 * - - * Copyright (c) 1983, 1987, 1989 Regents of the University of California. - * All rights reserved. + * Copyright (c) 1983, 1987, 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 @@ -58,6 +53,11 @@ * --Copyright-- */ +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + #ifndef _RESOLV_H_ #define _RESOLV_H_ @@ -71,6 +71,16 @@ #include <stdio.h> /* + * revision information. this is the release date in YYYYMMDD format. + * it can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19940415 + +/* * Resolver configuration file. * Normally not present, but may contain the address of the * inital name server(s) to query and the domain search list. @@ -89,86 +99,134 @@ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ #define RES_TIMEOUT 5 /* min. seconds between retries */ +#define MAXRESOLVSORT 10 /* number of net to sort on */ +#define RES_MAXNDOTS 15 /* should reflect bit field size */ -/* this was "struct state" until 4.9 */ struct __res_state { int retrans; /* retransmition time interval */ int retry; /* number of times to retransmit */ - u_int32_t options; /* option flags - see below. */ + u_long options; /* option flags - see below. */ int nscount; /* number of name servers */ - struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ #define nsaddr nsaddr_list[0] /* for backward compatibility */ u_short id; /* current packet id */ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ char defdname[MAXDNAME]; /* default domain */ - u_int32_t pfcode; /* RES_PRF_ flags - see below. */ + u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + char unused[3]; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; }; /* * Resolver options (keep these in synch with res_debug.c, please) */ -#define RES_INIT 0x0001 /* address initialized */ -#define RES_DEBUG 0x0002 /* print debug messages */ -#define RES_AAONLY 0x0004 /* authoritative answers only */ -#define RES_USEVC 0x0008 /* use virtual circuit */ -#define RES_PRIMARY 0x0010 /* query primary server only */ -#define RES_IGNTC 0x0020 /* ignore trucation errors */ -#define RES_RECURSE 0x0040 /* recursion desired */ -#define RES_DEFNAMES 0x0080 /* use default domain name */ -#define RES_STAYOPEN 0x0100 /* Keep TCP socket open */ -#define RES_DNSRCH 0x0200 /* search up local domain tree */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only */ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) /* * Resolver "pfcode" values. Used by dig. */ -#define RES_PRF_STATS 0x0001 -/* 0x0002 */ -#define RES_PRF_CLASS 0x0004 -#define RES_PRF_CMD 0x0008 -#define RES_PRF_QUES 0x0010 -#define RES_PRF_ANS 0x0020 -#define RES_PRF_AUTH 0x0040 -#define RES_PRF_ADD 0x0080 -#define RES_PRF_HEAD1 0x0100 -#define RES_PRF_HEAD2 0x0200 -#define RES_PRF_TTLID 0x0400 -#define RES_PRF_HEADX 0x0800 -#define RES_PRF_QUERY 0x1000 -#define RES_PRF_REPLY 0x2000 -#define RES_PRF_INIT 0x4000 -/* 0x8000 */ +#define RES_PRF_STATS 0x00000001 +/* 0x00000002 */ +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* hooks are still experimental as of 4.9.2 */ +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr_in * const *ns, + const u_char **query, + int *querylen, + u_char *ans, + int anssiz, + int *resplen)); + +typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr_in *ns, + const u_char *query, + int querylen, + u_char *ans, + int anssiz, + int *resplen)); extern struct __res_state _res; /* Private routines shared between libc/net, named, nslookup and others. */ #define dn_skipname __dn_skipname #define fp_query __fp_query +#define fp_nquery __fp_nquery #define hostalias __hostalias #define putlong __putlong #define putshort __putshort #define p_class __p_class #define p_time __p_time #define p_type __p_type +#define p_cdnname __p_cdnname +#define p_cdname __p_cdname +#define p_fqname __p_fqname +#define p_rr __p_rr +#define p_option __p_option __BEGIN_DECLS int __dn_skipname __P((const u_char *, const u_char *)); void __fp_resstat __P((struct __res_state *, FILE *)); -void __fp_query __P((char *, FILE *)); +void __fp_query __P((const u_char *, FILE *)); +void __fp_nquery __P((const u_char *, int, FILE *)); char *__hostalias __P((const char *)); void __putlong __P((u_int32_t, u_char *)); -void __putshort __P((u_short, u_char *)); -char *__p_class __P((int)); +void __putshort __P((u_int16_t, u_char *)); char *__p_time __P((u_int32_t)); -char *__p_type __P((int)); - -int dn_comp __P((const u_char *, u_char *, int, u_char **, u_char **)); +void __p_query __P((const u_char *)); +const u_char *__p_cdnname __P((const u_char *, const u_char *, int, FILE *)); +const u_char *__p_cdname __P((const u_char *, const u_char *, FILE *)); +const u_char *__p_fqname __P((const u_char *, const u_char *, FILE *)); +const u_char *__p_rr __P((const u_char *, const u_char *, FILE *)); +const char *__p_type __P((int)); +const char *__p_class __P((int)); +const char *__p_option __P((u_long option)); +int dn_comp __P((const char *, u_char *, int, u_char **, u_char **)); int dn_expand __P((const u_char *, const u_char *, const u_char *, - u_char *, int)); + char *, int)); int res_init __P((void)); -int res_mkquery __P((int, const char *, int, int, const char *, int, - const char *, char *, int)); -int res_send __P((const char *, int, char *, int)); +int res_query __P((const char *, int, int, u_char *, int)); +int res_search __P((const char *, int, int, u_char *, int)); +int res_querydomain __P((const char *, const char *, int, int, + u_char *, int)); +int res_mkquery __P((int, const char *, int, int, const u_char *, int, + const u_char *, u_char *, int)); +int res_send __P((const u_char *, int, u_char *, int)); +/* XXX - these last two don't belong in the resolver */ +u_int inet_nsap_addr __P((const char *, u_char *, int maxlen)); +char *inet_nsap_ntoa __P((int, const u_char *, char *ascii)); __END_DECLS #endif /* !_RESOLV_H_ */ diff --git a/resolv/sethostent.c b/resolv/sethostent.c index 8f82227fd6..709b518a40 100644 --- a/resolv/sethostent.c +++ b/resolv/sethostent.c @@ -1,7 +1,9 @@ /* - * Copyright (c) 1985 Regents of the University of California. - * All rights reserved. - * + * ++Copyright++ 1985, 1993 + * - + * Copyright (c) 1985, 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: @@ -12,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 @@ -29,10 +31,31 @@ * 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. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)sethostent.c 6.9 (Berkeley) 3/19/91"; +static char sccsid[] = "@(#)sethostent.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -43,6 +66,7 @@ static char sccsid[] = "@(#)sethostent.c 6.9 (Berkeley) 3/19/91"; void sethostent(stayopen) + int stayopen; { if (stayopen) _res.options |= RES_STAYOPEN | RES_USEVC; |