summaryrefslogtreecommitdiff
path: root/resolv
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1994-07-28 22:01:26 +0000
committerRoland McGrath <roland@gnu.org>1994-07-28 22:01:26 +0000
commite2a7073e7b94478641f2a6e250005f0fc1b30844 (patch)
treef8498c1ca24fecaaac020b1281482666370b2536 /resolv
parent4e14b2114d1675fe80b16b3c276da98b4c3fda5d (diff)
Incorporated from BIND-4.9.3-BETA9.
Diffstat (limited to 'resolv')
-rw-r--r--resolv/arpa/nameser.h178
-rw-r--r--resolv/gethnamaddr.c457
-rw-r--r--resolv/getnetbyaddr.c7
-rw-r--r--resolv/getnetbyname.c16
-rw-r--r--resolv/getnetent.c46
-rw-r--r--resolv/getnetnamadr.c303
-rw-r--r--resolv/herror.c17
-rw-r--r--resolv/nsap_addr.c97
-rw-r--r--resolv/res_comp.c118
-rw-r--r--resolv/res_debug.c495
-rw-r--r--resolv/res_init.c289
-rw-r--r--resolv/res_mkquery.c107
-rw-r--r--resolv/res_query.c236
-rw-r--r--resolv/res_send.c705
-rw-r--r--resolv/resolv.h154
-rw-r--r--resolv/sethostent.c38
16 files changed, 2342 insertions, 921 deletions
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;