diff options
author | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
commit | 28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch) | |
tree | 15f07c4c43d635959c6afee96bde71fb1b3614ee /resolv | |
download | glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.bz2 glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.zip |
initial import
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/Makefile | 31 | ||||
-rw-r--r-- | resolv/arpa/nameser.h | 347 | ||||
-rw-r--r-- | resolv/gethnamaddr.c | 736 | ||||
-rw-r--r-- | resolv/getnetbyaddr.c | 57 | ||||
-rw-r--r-- | resolv/getnetbyname.c | 68 | ||||
-rw-r--r-- | resolv/getnetent.c | 161 | ||||
-rw-r--r-- | resolv/getnetnamadr.c | 294 | ||||
-rw-r--r-- | resolv/herror.c | 118 | ||||
-rw-r--r-- | resolv/nsap_addr.c | 97 | ||||
-rw-r--r-- | resolv/res_comp.c | 433 | ||||
-rw-r--r-- | resolv/res_debug.c | 814 | ||||
-rw-r--r-- | resolv/res_init.c | 609 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 247 | ||||
-rw-r--r-- | resolv/res_query.c | 384 | ||||
-rw-r--r-- | resolv/res_send.c | 746 | ||||
-rw-r--r-- | resolv/resolv.h | 240 | ||||
-rw-r--r-- | resolv/sethostent.c | 80 | ||||
-rw-r--r-- | resolv/sys/bitypes.h | 3 |
18 files changed, 5465 insertions, 0 deletions
diff --git a/resolv/Makefile b/resolv/Makefile new file mode 100644 index 0000000000..510f16c179 --- /dev/null +++ b/resolv/Makefile @@ -0,0 +1,31 @@ +# Copyright (C) 1994 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Library General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Library General Public License for more details. + +# You should have received a copy of the GNU Library General Public +# License along with the GNU C Library; see the file COPYING.LIB. If +# not, write to the Free Software Foundation, Inc., 675 Mass Ave, +# Cambridge, MA 02139, USA. + +# +# Sub-makefile for resolv portion of the library. +# +subdir := resolv + +headers := resolv.h arpa/nameser.h sys/bitypes.h +distribute := ../conf/portability.h + +routines := gethnamaddr getnetbyaddr getnetbyname getnetent getnetnamadr \ + herror nsap_addr res_comp res_debug res_init res_mkquery \ + res_query res_send sethostent + +include ../Rules diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h new file mode 100644 index 0000000000..1a660ade63 --- /dev/null +++ b/resolv/arpa/nameser.h @@ -0,0 +1,347 @@ +/* + * ++Copyright++ 1983, 1989, 1993 + * - + * 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 + * 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. + * - + * 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-- + */ + +/* + * @(#)nameser.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + +#ifndef _NAMESER_H_ +#define _NAMESER_H_ + +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif +#include <sys/cdefs.h> + +#ifdef _AUX_SOURCE +#include <sys/types.h> /* ech for A/UX */ +#define res_send ucb_res_send /* already def'd in libc */ +#define _res_close _ucb_res_close /* removing res_send.o from the library */ +#endif /* gives an undefined symbol... */ + +/* + * 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 */ +#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 + */ +#define NAMESERVER_PORT 53 + +/* + * Currently defined opcodes + */ +#define QUERY 0x0 /* standard query */ +#define IQUERY 0x1 /* inverse query */ +#define STATUS 0x2 /* nameserver status query */ +/*#define xxx 0x3 /* 0x3 reserved */ +#define NS_NOTIFY_OP 0x4 /* notify secondary of SOA change */ +#ifdef ALLOW_UPDATES + /* non standard - supports ALLOW_UPDATES stuff from Mike Schwartz */ +# define UPDATEA 0x9 /* add resource record */ +# define UPDATED 0xa /* delete a specific resource record */ +# define UPDATEDA 0xb /* delete all named resource record */ +# define UPDATEM 0xc /* modify a specific resource record */ +# define UPDATEMA 0xd /* modify all named resource record */ +# define ZONEINIT 0xe /* initial zone transfer */ +# define ZONEREF 0xf /* incremental zone referesh */ +#endif + +/* + * Currently defined response codes + */ +#define NOERROR 0 /* no error */ +#define FORMERR 1 /* format error */ +#define SERVFAIL 2 /* server failure */ +#define NXDOMAIN 3 /* non existent domain */ +#define NOTIMP 4 /* not implemented */ +#define REFUSED 5 /* query refused */ +#ifdef ALLOW_UPDATES + /* non standard */ +# define NOCHANGE 0xf /* update failed to change db */ +#endif + +/* + * Type values for resources and queries + */ +#define T_A 1 /* host address */ +#define T_NS 2 /* authoritative server */ +#define T_MD 3 /* mail destination */ +#define T_MF 4 /* mail forwarder */ +#define T_CNAME 5 /* canonical name */ +#define T_SOA 6 /* start of authority zone */ +#define T_MB 7 /* mailbox domain name */ +#define T_MG 8 /* mail group member */ +#define T_MR 9 /* mail rename name */ +#define T_NULL 10 /* null resource record */ +#define T_WKS 11 /* well known service */ +#define T_PTR 12 /* domain name pointer */ +#define T_HINFO 13 /* host information */ +#define T_MINFO 14 /* mailbox information */ +#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) */ +#define T_SIG 24 /* security signature */ +#define T_KEY 25 /* security key */ +#define T_PX 26 /* X.400 mail mapping */ +#define T_GPOS 27 /* geographical position (withdrawn) */ +#define T_AAAA 28 /* IP6 Address */ +#define T_LOC 29 /* Location Information */ + /* 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) */ + /* 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 */ +#define T_MAILA 254 /* transfer mail agent records */ +#define T_ANY 255 /* wildcard match */ + +/* + * Values for class field + */ + +#define C_IN 1 /* the arpa internet */ +#define C_CHAOS 3 /* for chaos net (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) + +#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)*/ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + 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) || defined(m68k) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ + BYTE_ORDER != PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ + error "Undefined or invalid BYTE_ORDER"; +#endif + +/* + * 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 { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + 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 */ + 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 */ + 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 */ + 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 */ + 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; + +/* + * Defines for handling compressed domain names + */ +#define INDIR_MASK 0xc0 + +/* + * Structure for passing resource records around. + */ +struct rrec { + 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 */ +}; + +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. + * + * These macros demonstrate the property of C whereby it can be + * portable or it can be elegant but rarely both. + */ +#define GETSHORT(s, cp) { \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (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]) \ + ; \ + (cp) += INT32SZ; \ +} + +#define PUTSHORT(s, 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) += INT16SZ; \ +} + +#define PUTLONG(l, cp) { \ + register u_int32_t t_l = (u_int32_t)(l); \ + 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) += INT32SZ; \ +} + +#endif /* !_NAMESER_H_ */ diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c new file mode 100644 index 0000000000..55a3fb09a4 --- /dev/null +++ b/resolv/gethnamaddr.c @@ -0,0 +1,736 @@ +/* + * ++Copyright++ 1985, 1988, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; +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 <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[8*1024]; +static struct in_addr host_addr; +static FILE *hostf = NULL; +static int stayopen = 0; + +#ifdef RESOLVSORT +static void addrsort __P((char **, int)); +#endif + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +typedef union { + int32_t al; + char ac; +} align; + +extern int h_errno; + +#ifdef DEBUG +static void +dprintf(msg, num) + char *msg; + int num; +{ + if (_res.options & RES_DEBUG) { + int save = errno; + + printf(msg, num); + errno = save; + } +} +#else +# define dprintf(msg, num) /*nada*/ +#endif + +static struct hostent * +getanswer(answer, anslen, qname, qclass, qtype) + const querybuf *answer; + int anslen; + const char *qname; + int qclass, qtype; +{ + register const HEADER *hp; + register const u_char *cp; + register int n; + const u_char *eom; + char *bp, **ap, **hap; + int type, class, buflen, ancount, qdcount; + int haveanswer, had_error; + int toobig = 0; + char tbuf[MAXDNAME+1]; + + host.h_name = NULL; + eom = answer->buf + anslen; + /* + * find first satisfactory answer + */ + hp = &answer->hdr; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = hostbuf; + 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; + host.h_aliases = host_aliases; + hap = h_addr_ptrs; + *hap = NULL; +#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */ + host.h_addr_list = h_addr_ptrs; +#endif + haveanswer = 0; + 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 += INT16SZ; /* type */ + class = _getshort(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = _getshort(cp); + 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; /* for the \0 */ + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen) { + had_error++; + continue; + } + strcpy(bp, tbuf); + host.h_name = bp; + bp += n; + buflen -= n; + continue; + } + if (type != qtype) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", + qname, p_class(qclass), p_type(qtype), + p_type(type)); + cp += n; + continue; /* XXX - had_error++ ? */ + } + switch (type) { + case T_PTR: + if (strcasecmp(qname, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, qname, bp); + cp += n; + 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; + } + break; +#else + host.h_name = bp; + h_errno = NETDB_SUCCESS; + 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; /* XXX - had_error++ ? */ + } + 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; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + buflen -= nn; + } + + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + + if (bp + n >= &hostbuf[sizeof hostbuf]) { + dprintf("size (%d) too big\n", n); + had_error++; + continue; + } + if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (!toobig++) + dprintf("Too many addresses (%d)\n", + MAXADDRS); + cp += n; + continue; + } + bcopy(cp, *hap++ = bp, n); + bp += n; + cp += n; + break; + default: + dprintf("Impossible condition (type=%d)\n", type); + h_errno = NO_RECOVERY; + return (NULL); + } /*switch*/ + if (!had_error) + haveanswer++; + } /*while*/ + if (haveanswer) { + *ap = NULL; + *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 /*BSD*/ + if (!host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + strcpy(bp, qname); + host.h_name = bp; + } + h_errno = NETDB_SUCCESS; + return (&host); + } else { + h_errno = TRY_AGAIN; + return (NULL); + } +} + +struct hostent * +gethostbyname(name) + const char *name; +{ + querybuf buf; + register const char *cp; + int n; + extern struct hostent *_gethtbyname(); + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (!strchr(name, '.') && (cp = __hostalias(name))) + name = cp; + + /* + * disallow names consisting only of digits/dots, unless + * they end in a dot. + */ + if (isdigit(name[0])) + for (cp = name;; ++cp) { + if (!*cp) { + if (*--cp == '.') + break; + /* + * All-numeric, no dot at the end. + * Fake up a hostent as if we'd actually + * done a lookup. + */ + if (!inet_aton(name, &host_addr)) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + host.h_name = (char *)name; + host.h_aliases = host_aliases; + host_aliases[0] = NULL; + host.h_addrtype = AF_INET; + host.h_length = INT32SZ; + 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 = h_addr_ptrs; +#else + host.h_addr = h_addr_ptrs[0]; +#endif + h_errno = NETDB_SUCCESS; + return (&host); + } + if (!isdigit(*cp) && *cp != '.') + break; + } + + if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { + dprintf("res_search failed (%d)\n", n); + if (errno == ECONNREFUSED) + return (_gethtbyname(name)); + return (NULL); + } + return (getanswer(&buf, n, name, C_IN, T_A)); +} + +struct hostent * +gethostbyaddr(addr, len, type) + const char *addr; + int len, type; +{ + int n; + querybuf buf; + register struct hostent *hp; + char qbuf[MAXDNAME+1]; +#ifdef SUNSECURITY + register struct hostent *rhp; + char **haddr; + u_long old_options; + char hname2[MAXDNAME+1]; +#endif /*SUNSECURITY*/ + extern struct hostent *_gethtbyaddr(); + + if (type != AF_INET) { + errno = EAFNOSUPPORT; + h_errno = NETDB_INTERNAL; + return (NULL); + } + (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + ((unsigned)addr[3] & 0xff), + ((unsigned)addr[2] & 0xff), + ((unsigned)addr[1] & 0xff), + ((unsigned)addr[0] & 0xff)); + n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf); + if (n < 0) { + dprintf("res_query failed (%d)\n", n); + if (errno == ECONNREFUSED) + return (_gethtbyaddr(addr, len, type)); + return (NULL); + } + if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR))) + return (NULL); /* h_errno was set by getanswer() */ +#ifdef SUNSECURITY + /* + * turn off search as the name should be absolute, + * 'localhost' should be matched by defnames + */ + strncpy(hname2, hp->h_name, MAXDNAME); + hname2[MAXDNAME] = '\0'; + old_options = _res.options; + _res.options &= ~RES_DNSRCH; + _res.options |= RES_DEFNAMES; + if (!(rhp = gethostbyname(hp->h_name))) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: No A record for %s (verifying [%s])", + hname2, inet_ntoa(*((struct in_addr *)addr))); + _res.options = old_options; + h_errno = HOST_NOT_FOUND; + return (NULL); + } + _res.options = old_options; + for (haddr = rhp->h_addr_list; *haddr; haddr++) + if (!memcmp(*haddr, addr, INADDRSZ)) + break; + if (!*haddr) { + syslog(LOG_NOTICE|LOG_AUTH, + "gethostbyaddr: A record of %s != PTR record [%s]", + hname2, inet_ntoa(*((struct in_addr *)addr))); + h_errno = HOST_NOT_FOUND; + return (NULL); + } +#endif /*SUNSECURITY*/ + hp->h_addrtype = type; + hp->h_length = len; + h_addr_ptrs[0] = (char *)&host_addr; + h_addr_ptrs[1] = NULL; + host_addr = *(struct in_addr *)addr; + h_errno = NETDB_SUCCESS; + return (hp); +} + +void +_sethtent(f) + int f; +{ + if (!hostf) + hostf = fopen(_PATH_HOSTS, "r" ); + else + rewind(hostf); + stayopen = f; +} + +void +_endhtent() +{ + if (hostf && !stayopen) { + (void) fclose(hostf); + hostf = NULL; + } +} + +struct hostent * +_gethtent() +{ + char *p; + register char *cp, **q; + + if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { + h_errno = NETDB_INTERNAL; + return (NULL); + } +again: + if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { + h_errno = HOST_NOT_FOUND; + return (NULL); + } + if (*p == '#') + goto again; + if (!(cp = strpbrk(p, "#\n"))) + goto again; + *cp = '\0'; + 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 = h_addr_ptrs; +#else + host.h_addr = h_addr_ptrs[0]; +#endif + host.h_length = INT32SZ; + host.h_addrtype = AF_INET; + while (*cp == ' ' || *cp == '\t') + cp++; + host.h_name = cp; + q = host.h_aliases = host_aliases; + if (cp = strpbrk(cp, " \t")) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &host_aliases[MAXALIASES - 1]) + *q++ = cp; + if (cp = strpbrk(cp, " \t")) + *cp++ = '\0'; + } + *q = NULL; + h_errno = NETDB_SUCCESS; + return (&host); +} + +struct hostent * +_gethtbyname(name) + char *name; +{ + register struct hostent *p; + register char **cp; + + _sethtent(0); + while (p = _gethtent()) { + if (strcasecmp(p->h_name, name) == 0) + break; + for (cp = p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0) + goto found; + } +found: + _endhtent(); + return (p); +} + +struct hostent * +_gethtbyaddr(addr, len, type) + const char *addr; + int len, type; +{ + register struct hostent *p; + + _sethtent(0); + while (p = _gethtent()) + if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) + break; + _endhtent(); + 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 ; (unsigned)j < _res.nsort; j++) + if (_res.sort_list[j].addr.s_addr == + (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) + break; + 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 +ht_sethostent(stayopen) + int stayopen; +{ + _sethtent(stayopen); +} + +void +ht_endhostent() +{ + _endhtent(); +} + +struct hostent * +ht_gethostbyname(name) + char *name; +{ + return (_gethtbyname(name)); +} + +struct hostent * +ht_gethostbyaddr(addr, len, type) + const char *addr; + int len, type; +{ + return (_gethtbyaddr(addr, len, type)); +} + +struct hostent * +gethostent() +{ + return (_gethtent()); +} + +void +dns_service() +{ + return; +} + +#undef dn_skipname +dn_skipname(comp_dn, eom) + const u_char *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 new file mode 100644 index 0000000000..3bc01addb6 --- /dev/null +++ b/resolv/getnetbyaddr.c @@ -0,0 +1,57 @@ +/* + * 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[] = "@(#)getnetbyaddr.c 1.1 (Coimbra) 93/06/02"; +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <netdb.h> + +extern int _net_stayopen; + +struct netent * +_getnetbyaddr(net, type) + register long net; + register int type; +{ + register struct netent *p; + + setnetent(_net_stayopen); + while (p = getnetent()) + if (p->n_addrtype == type && p->n_net == net) + break; + if (!_net_stayopen) + endnetent(); + return (p); +} diff --git a/resolv/getnetbyname.c b/resolv/getnetbyname.c new file mode 100644 index 0000000000..1d2029fe6c --- /dev/null +++ b/resolv/getnetbyname.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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[] = "@(#)getnetbyname.c 8.1 (Berkeley) 6/4/93"; +static char sccsid_[] = "from getnetbyname.c 1.1 (Coimbra) 93/06/02"; +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <netdb.h> +#include <string.h> + +extern int _net_stayopen; + +struct netent * +_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 (strcasecmp(p->n_name, name) == 0) + break; + for (cp = p->n_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0) + goto found; + } +found: + if (!_net_stayopen) + endnetent(); + return (p); +} diff --git a/resolv/getnetent.c b/resolv/getnetent.c new file mode 100644 index 0000000000..fb47c30c99 --- /dev/null +++ b/resolv/getnetent.c @@ -0,0 +1,161 @@ +/* + * 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. + */ + +/* 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 8.1 (Berkeley) 6/4/93"; +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 <resolv.h> +#include <netdb.h> +#include <string.h> + +#ifndef _PATH_NETWORKS +#define _PATH_NETWORKS "/etc/networks" +#endif + +#define MAXALIASES 35 + +static FILE *netf; +static char line[BUFSIZ+1]; +static struct netent net; +static char *net_aliases[MAXALIASES]; +int _net_stayopen; + +void _setnetent __P((int)); +void _endnetent __P((void)); + +void +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" ); + else + rewind(netf); + _net_stayopen |= f; +} + +void +_endnetent() +{ + + if (netf) { + fclose(netf); + netf = NULL; + } + _net_stayopen = 0; +} + +struct netent * +getnetent() +{ + char *p; + register char *cp, **q; + + if (netf == NULL && (netf = fopen(_PATH_NETWORKS, "r" )) == NULL) + return (NULL); +again: + p = fgets(line, BUFSIZ, netf); + if (p == NULL) + return (NULL); + if (*p == '#') + goto again; + cp = strpbrk(p, "#\n"); + if (cp == NULL) + goto again; + *cp = '\0'; + net.n_name = p; + cp = strpbrk(p, " \t"); + if (cp == NULL) + goto again; + *cp++ = '\0'; + while (*cp == ' ' || *cp == '\t') + cp++; + p = strpbrk(cp, " \t"); + if (p != NULL) + *p++ = '\0'; + net.n_net = inet_network(cp); + net.n_addrtype = AF_INET; + q = net.n_aliases = net_aliases; + if (p != NULL) + cp = p; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &net_aliases[MAXALIASES - 1]) + *q++ = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + *q = NULL; + return (&net); +} diff --git a/resolv/getnetnamadr.c b/resolv/getnetnamadr.c new file mode 100644 index 0000000000..19a31afee8 --- /dev/null +++ b/resolv/getnetnamadr.c @@ -0,0 +1,294 @@ +/* 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. + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * 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[] = "@(#)getnetbyaddr.c 8.1 (Berkeley) 6/4/93"; +static char sccsid_[] = "from 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> +#include "conf/portability.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 (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); + break; + } + net_entry.n_aliases++; + return (&net_entry); + } + h_errno = TRY_AGAIN; + return (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 */ + sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]); + break; + case 2: /* Class B */ + sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]); + break; + case 1: /* Class C */ + sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2], + netbr[1]); + break; + case 0: /* Class D - E */ + 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, (u_char *)&buf, sizeof(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 (NULL); + } + 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); + } + 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; + + strcpy(&qbuf[0],net); + anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(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); + return (_getnetbyname(net)); +} diff --git a/resolv/herror.c b/resolv/herror.c new file mode 100644 index 0000000000..872a009a18 --- /dev/null +++ b/resolv/herror.c @@ -0,0 +1,118 @@ +/* + * ++Copyright++ 1987, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id$"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/uio.h> +#include <netdb.h> +#if defined(BSD) && (BSD >= 199103) +# include <unistd.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +char *h_errlist[] = { + "Resolver Error 0 (no error)", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +extern int h_errno; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(s) + const char *s; +{ + struct iovec iov[4]; + register struct iovec *v = iov; + + if (s && *s) { + v->iov_base = (char *)s; + v->iov_len = strlen(s); + v++; + v->iov_base = ": "; + v->iov_len = 2; + v++; + } + v->iov_base = hstrerror(h_errno); + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = "\n"; + v->iov_len = 1; + writev(STDERR_FILENO, iov, (v - iov) + 1); +} + +char * +hstrerror(err) + int err; +{ + if (err < 0) + return ("Resolver internal error"); + else if (err < h_nerr) + return (h_errlist[err]); + return ("Unknown resolver error"); +} 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 new file mode 100644 index 0000000000..ad24a984a1 --- /dev/null +++ b/resolv/res_comp.c @@ -0,0 +1,433 @@ +/* + * ++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: + * 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. + * - + * 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[] = "@(#)res_comp.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 <stdio.h> +#include <resolv.h> +#include <ctype.h> + +#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. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * '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; + char *exp_dn; + int length; +{ + register const u_char *cp; + register char *dn; + register int n, c; + char *eom; + int len = -1, checked = 0; + + dn = exp_dn; + cp = comp_dn; + eom = exp_dn + length; + /* + * fetch next label in domain name + */ + while (n = *cp++) { + /* + * Check for indirection + */ + switch (n & INDIR_MASK) { + case 0: + if (dn != exp_dn) { + if (dn >= eom) + return (-1); + *dn++ = '.'; + } + if (dn+n >= eom) + return (-1); + checked += n + 1; + while (--n >= 0) { + if ((c = *cp++) == '.') { + if (dn + n + 2 >= eom) + return (-1); + *dn++ = '\\'; + } + *dn++ = c; + if (cp >= eomorig) /* out of range */ + return (-1); + } + break; + + case INDIR_MASK: + if (len < 0) + len = cp - comp_dn + 1; + cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); + if (cp < msg || cp >= eomorig) /* out of range */ + return (-1); + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eomorig - msg) + return (-1); + break; + + default: + return (-1); /* flag error */ + } + } + *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); +} + +/* + * Compress domain name 'exp_dn' into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0] + * is a pointer to the beginning of the message. The list ends with NULL. + * 'lastdnptr' is a pointer to the end of the arrary pointed to + * by 'dnptrs'. Side effect is to update the list of pointers for + * labels inserted into the message as we compress the name. + * 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 char *exp_dn; + u_char *comp_dn, **dnptrs, **lastdnptr; + int length; +{ + register u_char *cp, *dn; + register int c, l; + u_char **cpp, **lpp, *sp, *eob; + u_char *msg; + + 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++) + ; + lpp = cpp; /* end of list to search */ + } + } else + msg = NULL; + for (c = *dn++; c != '\0'; ) { + /* look to see if we can use pointers */ + if (msg != NULL) { + if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { + if (cp+1 >= eob) + return (-1); + *cp++ = (l >> 8) | INDIR_MASK; + *cp++ = l % 256; + return (cp - comp_dn); + } + /* not found, save it */ + if (lastdnptr != NULL && cpp < lastdnptr-1) { + *cpp++ = cp; + *cpp = NULL; + } + } + sp = cp++; /* save ptr to length byte */ + do { + if (c == '.') { + c = *dn++; + break; + } + if (c == '\\') { + if ((c = *dn++) == '\0') + break; + } + if (cp >= eob) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *cp++ = c; + } while ((c = *dn++) != '\0'); + /* catch trailing '.'s but not '..' */ + if ((l = cp - sp - 1) == 0 && c == '\0') { + cp--; + break; + } + if (l <= 0 || l > MAXLABEL) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *sp = l; + } + if (cp >= eob) { + if (msg != NULL) + *lpp = NULL; + return (-1); + } + *cp++ = '\0'; + return (cp - comp_dn); +} + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +__dn_skipname(comp_dn, eom) + const u_char *comp_dn, *eom; +{ + register const u_char *cp; + register int n; + + cp = comp_dn; + while (cp < eom && (n = *cp++)) { + /* + * check for indirection + */ + switch (n & INDIR_MASK) { + case 0: /* normal case, n == len */ + cp += n; + continue; + 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. + * dnptrs is the pointer to the first name on the list, + * not the pointer to the start of the message. + */ +static int +dn_find(exp_dn, msg, dnptrs, lastdnptr) + u_char *exp_dn, *msg; + u_char **dnptrs, **lastdnptr; +{ + register u_char *dn, *cp, **cpp; + register int n; + u_char *sp; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + dn = exp_dn; + sp = cp = *cpp; + while (n = *cp++) { + /* + * check for indirection + */ + switch (n & INDIR_MASK) { + case 0: /* normal case, n == len */ + while (--n >= 0) { + if (*dn == '.') + goto next; + if (*dn == '\\') + dn++; + if (mklower(*dn++) != mklower(*cp++)) + goto next; + } + if ((n = *dn++) == '\0' && *cp == '\0') + return (sp - msg); + if (n == '.') + continue; + goto next; + + case INDIR_MASK: /* indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /* illegal type */ + return (-1); + } + } + if (*dn == '\0') + return (sp - msg); + next: ; + } + return (-1); +} + +/* + * Routines to insert/extract short/long's. Must account for byte + * order and non-alignment problems. This code at least has the + * advantage of being portable. + * + * used by sendmail. + */ + +u_int16_t +_getshort(msgp) + register const u_char *msgp; +{ + register u_int16_t u; + + GETSHORT(u, msgp); + return (u); +} + +#ifdef NeXT +/* + * nExt machines have some funky library conventions, which we must maintain. + */ +u_int16_t +res_getshort(msgp) + register const u_char *msgp; +{ + return (_getshort(msgp)); +} +#endif + +u_int32_t +_getlong(msgp) + register const u_char *msgp; +{ + register u_int32_t u; + + GETLONG(u, msgp); + return (u); +} + +void +#if defined(__STDC__) || defined(__cplusplus) +__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */ +#else +__putshort(s, msgp) + register u_int16_t s; + register u_char *msgp; +#endif +{ + PUTSHORT(s, msgp); +} + +void +__putlong(l, msgp) + register u_int32_t l; + register u_char *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 new file mode 100644 index 0000000000..254e1efc39 --- /dev/null +++ b/resolv/res_debug.c @@ -0,0 +1,814 @@ +/* + * ++Copyright++ 1985, 1990, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)res_debug.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/inet.h> +#include <arpa/nameser.h> + +#include <stdio.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 + +const char *_res_opcodes[] = { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "5", + "6", + "7", + "8", + "UPDATEA", + "UPDATED", + "UPDATEDA", + "UPDATEM", + "UPDATEMA", + "ZONEINIT", + "ZONEREF", +}; + +const char *_res_resultcodes[] = { + "NOERROR", + "FORMERR", + "SERVFAIL", + "NXDOMAIN", + "NOTIMP", + "REFUSED", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "NOCHANGE", +}; + +static char retbuf[16]; + +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); + } +} + +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); + } +} + +static const u_char * +do_rrset(msg, cp, cnt, pflag, file, hs) + int cnt, pflag; + const u_char *cp, *msg; + const char *hs; + FILE *file; +{ + int n; + int sflag; + + /* + * Print answer records. + */ + sflag = (_res.pfcode & pflag); + if (n = ntohs(cnt)) { + if ((!_res.pfcode) || + ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + fprintf(file, hs); + while (--n >= 0) { + if ((!_res.pfcode) || sflag) { + cp = p_rr(cp, msg, file); + } else { + unsigned int dlen; + cp += __dn_skipname(cp, cp + MAXCDNAME); + cp += INT16SZ; + cp += INT16SZ; + cp += INT32SZ; + dlen = _getshort((u_char*)cp); + cp += INT16SZ; + cp += dlen; + } + if ((cp - msg) > PACKETSZ) + return (NULL); + } + if ((!_res.pfcode) || + ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) + putc('\n', file); + } + return (cp); +} + +void +__p_query(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. + */ +void +__fp_resstat(statp, file) + struct __res_state *statp; + FILE *file; +{ + register u_long mask; + + fprintf(file, ";; res options:"); + if (!statp) + statp = &_res; + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +__fp_nquery(msg, len, file) + const u_char *msg; + int len; + FILE *file; +{ + 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 + HFIXEDSZ; + endMark = cp + len; + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { + fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d", + _res_opcodes[hp->opcode], + _res_resultcodes[hp->rcode], + ntohs(hp->id)); + putc('\n', file); + } + putc(';', file); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (hp->qr) + fprintf(file, " qr"); + if (hp->aa) + fprintf(file, " aa"); + if (hp->tc) + fprintf(file, " tc"); + if (hp->rd) + fprintf(file, " rd"); + if (hp->ra) + fprintf(file, " ra"); + if (hp->pr) + fprintf(file, " pr"); + } + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); + fprintf(file, ", Ans: %d", ntohs(hp->ancount)); + fprintf(file, ", Auth: %d", ntohs(hp->nscount)); + fprintf(file, ", Addit: %d", ntohs(hp->arcount)); + } + if ((!_res.pfcode) || (_res.pfcode & + (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { + putc('\n',file); + } + /* + * Print question records. + */ + if (n = ntohs(hp->qdcount)) { + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ";; QUESTIONS:\n"); + while (--n >= 0) { + fprintf(file, ";;\t"); + TruncTest(cp); + cp = p_cdname(cp, msg, file); + ErrorTest(cp); + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + fprintf(file, ", type = %s", + __p_type(_getshort((u_char*)cp))); + cp += INT16SZ; + TruncTest(cp); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) + 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"); + ErrorTest(cp); + + /* + * print name server records + */ + TruncTest(cp); + cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file, + ";; AUTHORITY RECORDS:\n"); + ErrorTest(cp); + + TruncTest(cp); + /* + * print additional records + */ + cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file, + ";; ADDITIONAL RECORDS:\n"); + ErrorTest(cp); + return; + trunc: + fprintf(file, "\n;; ...truncated\n"); + return; + error: + fprintf(file, "\n;; ...malformed\n"); +} + +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(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} + +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(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') { + putc('.', file); + } else { + fputs(name, file); + if (name[strlen(name) - 1] != '.') + putc('.', file); + } + return (cp + n); +} + +/* + * Print resource record fields in human readable form. + */ +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; + 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((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); + if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS)) + fprintf(file, "\t%s", __p_class(class)); + fprintf(file, "\t%s", __p_type(type)); + /* + * Print type specific data, if appropriate + */ + switch (type) { + case T_A: + switch (class) { + case C_IN: + case C_HS: + bcopy(cp, (char *)&inaddr, INADDRSZ); + if (dlen == 4) { + fprintf(file, "\t%s", inet_ntoa(inaddr)); + cp += dlen; + } else if (dlen == 7) { + char *address; + u_char protocol; + u_short port; + + address = inet_ntoa(inaddr); + cp += INADDRSZ; + protocol = *(u_char*)cp; + cp += sizeof(u_char); + port = _getshort((u_char*)cp); + cp += INT16SZ; + fprintf(file, "\t%s\t; proto %d, port %d", + address, protocol, port); + } + break; + default: + cp += dlen; + } + break; + case T_CNAME: + case T_MB: + case T_MG: + case T_MR: + case T_NS: + case T_PTR: + putc('\t', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_HINFO: + case T_ISDN: + cp2 = cp + dlen; + if (n = *cp++) { + fprintf(file, "\t%.*s", n, cp); + cp += n; + } + if ((cp < cp2) && (n = *cp++)) { + fprintf(file, "\t%.*s", n, cp); + cp += n; + } else if (type == T_HINFO) + fprintf(file, "\n;; *** Warning *** OS-type missing"); + break; + + case T_SOA: + putc('\t', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + fputs(" (\n", file); + t = _getlong((u_char*)cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; serial\n", t); + t = _getlong((u_char*)cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); + t = _getlong((u_char*)cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); + t = _getlong((u_char*)cp); cp += INT32SZ; + fprintf(file, "\t\t\t%lu\t; expire (%s)\n", t, __p_time(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: + case T_AFSDB: + case T_RT: + fprintf(file, "\t%d ", _getshort((u_char*)cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_PX: + fprintf(file, "\t%d ", _getshort((u_char*)cp)); + cp += INT16SZ; + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_TXT: + case T_X25: + (void) fputs("\t\"", file); + cp2 = cp1 + dlen; + while (cp < cp2) { + if (n = (unsigned char) *cp++) { + for (c = n; c > 0 && cp < cp2; c--) + if ((*cp == '\n') || (*cp == '"')) { + (void) putc('\\', file); + (void) putc(*cp++, file); + } else + (void) putc(*cp++, 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); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + putc(' ', file); + if ((cp = p_fqname(cp, msg, file)) == NULL) + return (NULL); + break; + + case T_UINFO: + putc('\t', file); + fputs((char *)cp, file); + cp += dlen; + break; + + case T_UID: + case T_GID: + if (dlen == 4) { + fprintf(file, "\t%u", _getlong((u_char*)cp)); + cp += INT32SZ; + } + break; + + case T_WKS: + if (dlen < INT32SZ + 1) + break; + bcopy(cp, (char *)&inaddr, INADDRSZ); + cp += INT32SZ; + fprintf(file, "\t%s %s ( ", + inet_ntoa(inaddr), + deproto((int) *cp)); + cp += sizeof(u_char); + n = 0; + lcnt = 0; + while (cp < cp1 + dlen) { + c = *cp++; + do { + if (c & 0200) { + if (lcnt == 0) { + fputs("\n\t\t\t", file); + lcnt = 5; + } + fputs(dewks(n), file); + putc(' ', file); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + putc(')', file); + break; + +#ifdef ALLOW_T_UNSPEC + case T_UNSPEC: + { + int NumBytes = 8; + u_char *DataPtr; + int i; + + if (dlen < NumBytes) NumBytes = dlen; + fprintf(file, "\tFirst %d bytes of hex data:", + NumBytes); + for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) + fprintf(file, " %x", *DataPtr); + cp += dlen; + } + break; +#endif /* ALLOW_T_UNSPEC */ + + default: + fprintf(file, "\t?%d?", type); + cp += dlen; + } +#if 0 + fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl)); +#else + putc('\n', file); +#endif + if (cp - cp1 != dlen) { + fprintf(file, ";; packet size error (found %d, dlen was %d)\n", + cp - cp1, dlen); + cp = NULL; + } + return (cp); +} + +static char nbuf[40]; + +/* + * Return a string for the type + */ +const char * +__p_type(type) + int type; +{ + switch (type) { + case T_A: return "A"; + case T_NS: return "NS"; + case T_CNAME: return "CNAME"; + case T_SOA: return "SOA"; + case T_MB: return "MB"; + case T_MG: return "MG"; + case T_MR: return "MR"; + case T_NULL: return "NULL"; + case T_WKS: return "WKS"; + case T_PTR: return "PTR"; + case T_HINFO: return "HINFO"; + case T_MINFO: return "MINFO"; + case T_MX: return "MX"; + case T_TXT: return "TXT"; + case T_RP: return "RP"; + case T_AFSDB: return "AFSDB"; + case T_X25: return "X25"; + case T_ISDN: return "ISDN"; + case T_RT: return "RT"; + case T_NSAP: return "NSAP"; + case T_NSAP_PTR: return "NSAP_PTR"; + case T_SIG: return "SIG"; + case T_KEY: return "KEY"; + case T_PX: return "PX"; + case T_GPOS: return "GPOS"; + case T_AAAA: return "AAAA"; + case T_LOC: return "LOC"; + case T_AXFR: return "AXFR"; + case T_MAILB: return "MAILB"; + case T_MAILA: return "MAILA"; + case T_ANY: return "ANY"; + case T_UINFO: return "UINFO"; + case T_UID: return "UID"; + case T_GID: return "GID"; +#ifdef ALLOW_T_UNSPEC + case T_UNSPEC: return "UNSPEC"; +#endif /* ALLOW_T_UNSPEC */ + default: (void)sprintf(nbuf, "%d", type); return (nbuf); + } +} + +/* + * Return a mnemonic for class + */ +const char * +__p_class(class) + int class; +{ + switch (class) { + 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 + */ +const char * +__p_option(option) + u_long option; +{ + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_AAONLY: return "aaonly"; + case RES_USEVC: return "usevc"; + case RES_PRIMARY: return "primry"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + default: sprintf(nbuf, "?0x%x?", option); return (nbuf); + } +} + +/* + * Return a mnemonic for a time to live + */ +char * +__p_time(value) + u_int32_t value; +{ + int secs, mins, hours, days; + register char *p; + + if (value == 0) { + strcpy(nbuf, "0 secs"); + return (nbuf); + } + + secs = value % 60; + value /= 60; + mins = value % 60; + value /= 60; + hours = value % 24; + value /= 24; + days = value; + value = 0; + +#define PLURALIZE(x) x, (x == 1) ? "" : "s" + p = nbuf; + if (days) { + (void)sprintf(p, "%d day%s", PLURALIZE(days)); + while (*++p); + } + if (hours) { + if (days) + *p++ = ' '; + (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); + while (*++p); + } + if (mins) { + if (days || hours) + *p++ = ' '; + (void)sprintf(p, "%d min%s", PLURALIZE(mins)); + while (*++p); + } + if (secs || ! (days || hours || mins)) { + if (days || hours || mins) + *p++ = ' '; + (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); + } + return (nbuf); +} diff --git a/resolv/res_init.c b/resolv/res_init.c new file mode 100644 index 0000000000..0092dbcfbc --- /dev/null +++ b/resolv/res_init.c @@ -0,0 +1,609 @@ +/* + * ++Copyright++ 1985, 1989, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +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 <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 + +/* + * Marc Majka 1994/04/16 + * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) + * + * NetInfo resolver configuration directory support. + * + * Allow a NetInfo directory to be created in the hierarchy which + * contains the same information as the resolver configuration file. + * + * - The local domain name is stored as the value of the "domain" property. + * - The Internet address(es) of the name server(s) are stored as values + * of the "nameserver" property. + * - The name server addresses are stored as values of the "nameserver" + * property. + * - The search list for host-name lookup is stored as values of the + * "search" property. + * - The sortlist comprised of IP address netmask pairs are stored as + * values of the "sortlist" property. The IP address and optional netmask + * should be seperated by a slash (/) character. + * - Internal resolver variables can be set from the value of the "options" + * property. + * + */ +#if defined(NeXT) +# include <netinfo/ni.h> +# define NI_PATH_RESCONF "/locations/resolver" +# define NI_TIMEOUT 10 +static int netinfo_res_init __P((int *haveenv, int *havesearch)); +#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. + */ + +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 + * INADDR_ANY and the default domain name comes from the gethostname(). + * + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server. It + * was later decided that since the recommended practice is to always + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. + * + * Return 0 if completes successfully, -1 on error + */ +res_init() +{ + register FILE *fp; + register char *cp, **pp; + 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 three fields used to be statically initialized. This made + * it hard to use this code in a shared library. It is necessary, + * now that we're doing dynamic initialization here, that we preserve + * the old semantics: if an application modifies one of these three + * 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) - 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; + } + +#define MATCH(line, name) \ + (!strncmp(line, name, sizeof(name) - 1) && \ + (line[sizeof(name) - 1] == ' ' || \ + line[sizeof(name) - 1] == '\t')) + +#ifdef NeXT + if (netinfo_res_init(&haveenv, &havesearch) == 0) +#endif + if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { + /* read the config file */ + while (fgets(buf, sizeof(buf), fp) != NULL) { + /* skip comments */ + if (*buf == ';' || *buf == '#') + continue; + /* read default domain name */ + if (MATCH(buf, "domain")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) + *cp = '\0'; + havesearch = 0; + continue; + } + /* set search list */ + if (MATCH(buf, "search")) { + if (haveenv) /* skip if have from environ */ + continue; + cp = buf + sizeof("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + if ((cp = strchr(_res.defdname, '\n')) != NULL) + *cp = '\0'; + /* + * Set search list to be blank-separated strings + * on rest of line. + */ + cp = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + if (*cp == ' ' || *cp == '\t') { + *cp = 0; + n = 1; + } else if (n) { + *pp++ = cp; + n = 0; + } + } + /* null terminate last domain if there are excess */ + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cp = '\0'; + *pp++ = 0; + havesearch = 1; + continue; + } + /* read nameservers to query */ + if (MATCH(buf, "nameserver") && nserv < MAXNS) { + struct in_addr a; + + cp = buf + sizeof("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { + _res.nsaddr_list[nserv].sin_addr = a; + _res.nsaddr_list[nserv].sin_family = AF_INET; + _res.nsaddr_list[nserv].sin_port = + htons(NAMESERVER_PORT); + nserv++; + } + continue; + } +#ifdef RESOLVSORT + if (MATCH(buf, "sortlist")) { + 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 (MATCH(buf, "options")) { + res_setoptions(buf + sizeof("options") - 1, "conf"); + continue; + } + } + if (nserv > 1) + _res.nscount = nserv; +#ifdef RESOLVSORT + _res.nsort = nsort; +#endif + (void) fclose(fp); + } + if (_res.defdname[0] == 0 && + gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + (cp = strchr(buf, '.')) != NULL) + strcpy(_res.defdname, cp + 1); + + /* find components of local domain that might be searched */ + if (havesearch == 0) { + pp = _res.dnsrch; + *pp++ = _res.defdname; + *pp = NULL; + +#ifndef RFC1535 + dots = 0; + for (cp = _res.defdname; *cp; cp++) + dots += (*cp == '.'); + + cp = _res.defdname; + while (pp < _res.dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) + break; + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; + } + *pp = NULL; +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = _res.dnsrch; *pp; pp++) + 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)); + return (htonl(IN_CLASSC_NET)); +} +#endif + +#ifdef NeXT +static int +netinfo_res_init(haveenv, havesearch) + int *haveenv; + int *havesearch; +{ + register int n; + void *domain, *parent; + ni_id dir; + ni_status status; + ni_namelist nl; + int nserv = 0; +#ifdef RESOLVSORT + int nsort = 0; +#endif + + status = ni_open(NULL, ".", &domain); + if (status == NI_OK) { + ni_setreadtimeout(domain, NI_TIMEOUT); + ni_setabort(domain, 1); + + /* climb the NetInfo hierarchy to find a resolver directory */ + while (status == NI_OK) { + status = ni_pathsearch(domain, &dir, NI_PATH_RESCONF); + if (status == NI_OK) { + /* found a resolver directory */ + + if (*haveenv == 0) { + /* get the default domain name */ + status = ni_lookupprop(domain, &dir, "domain", &nl); + if (status == NI_OK && nl.ni_namelist_len > 0) { + (void)strncpy(_res.defdname, + nl.ni_namelist_val[0], + sizeof(_res.defdname) - 1); + _res.defdname[sizeof(_res.defdname) - 1] = '\0'; + ni_namelist_free(&nl); + *havesearch = 0; + } + + /* get search list */ + status = ni_lookupprop(domain, &dir, "search", &nl); + if (status == NI_OK && nl.ni_namelist_len > 0) { + (void)strncpy(_res.defdname, + nl.ni_namelist_val[0], + sizeof(_res.defdname) - 1); + _res.defdname[sizeof(_res.defdname) - 1] = '\0'; + /* copy */ + for (n = 0; + n < nl.ni_namelist_len && n < MAXDNSRCH; + n++) { + /* duplicate up to MAXDNSRCH servers */ + char *cp = nl.ni_namelist_val[n]; + _res.dnsrch[n] = + strcpy((char *)malloc(strlen(cp) + 1), cp); + } + ni_namelist_free(&nl); + *havesearch = 1; + } + } + + /* get list of nameservers */ + status = ni_lookupprop(domain, &dir, "nameserver", &nl); + if (status == NI_OK && nl.ni_namelist_len > 0) { + /* copy up to MAXNS servers */ + for (n = 0; + n < nl.ni_namelist_len && nserv < MAXNS; + n++) { + struct in_addr a; + + if (inet_aton(nl.ni_namelist_val[n], &a)) { + _res.nsaddr_list[nserv].sin_addr = a; + _res.nsaddr_list[nserv].sin_family = AF_INET; + _res.nsaddr_list[nserv].sin_port = + htons(NAMESERVER_PORT); + nserv++; + } + } + ni_namelist_free(&nl); + } + + if (nserv > 1) + _res.nscount = nserv; + +#ifdef RESOLVSORT + /* get sort order */ + status = ni_lookupprop(domain, &dir, "sortlist", &nl); + if (status == NI_OK && nl.ni_namelist_len > 0) { + + /* copy up to MAXRESOLVSORT address/netmask pairs */ + for (n = 0; + n < nl.ni_namelist_len && nsort < MAXRESOLVSORT; + n++) { + char ch; + char *cp; + struct in_addr a; + + cp = strchr(nl.ni_namelist_val[n], '/'); + if (cp != NULL) { + ch = *cp; + *cp = '\0'; + } + + if (inet_aton(nl.ni_namelist_val[n], &a)) { + _res.sort_list[nsort].addr = a; + if (*cp && ch == '/') { + *cp++ = ch; + if (inet_aton(cp, &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++; + } + } + ni_namelist_free(&nl); + } + + _res.nsort = nsort; +#endif + + /* get resolver options */ + status = ni_lookupprop(domain, &dir, "options", &nl); + if (status == NI_OK && nl.ni_namelist_len > 0) { + res_setoptions(nl.ni_namelist_val[0], "conf"); + ni_namelist_free(&nl); + } + + ni_free(domain); + return(1); /* using DNS configuration from NetInfo */ + } + + status = ni_open(domain, "..", &parent); + ni_free(domain); + if (status == NI_OK) + domain = parent; + } + } + return(0); /* if not using DNS configuration from NetInfo */ +} +#endif /* NeXT */ diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c new file mode 100644 index 0000000000..0695670925 --- /dev/null +++ b/resolv/res_mkquery.c @@ -0,0 +1,247 @@ +/* + * ++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: + * 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. + * - + * 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[] = "@(#)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 <stdio.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 */ + int class, type; /* class and type of query */ + const u_char *data; /* resource record data */ + int datalen; /* length of data */ + 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 u_char *cp; + register int n; + struct rrec *newrr = (struct rrec *) newrr_in; + u_char *dnptrs[20], **dpp, **lastdnptr; + +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_mkquery(%d, %s, %d, %d)\n", + op, dname, class, type); +#endif + if (!(_res.options & RES_INIT)) { + if (res_init() == -1) + return (-1); + } + /* + * Initialize header fields. + */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return (-1); + 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 + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + /* + * perform opcode specific processing + */ + switch (op) { + case QUERY: /*FALLTHROUGH*/ + case NS_NOTIFY_OP: + if ((buflen -= QFIXEDSZ) < 0) + return (-1); + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + buflen -= n; + __putshort(type, cp); + cp += INT16SZ; + __putshort(class, cp); + cp += INT16SZ; + hp->qdcount = htons(1); + if (op == QUERY || data == NULL) + break; + /* + * Make an additional record for completion domain. + */ + buflen -= RRFIXEDSZ; + n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); + if (n < 0) + return (-1); + cp += n; + buflen -= n; + __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; + + case IQUERY: + /* + * Initialize answer section + */ + if (buflen < 1 + RRFIXEDSZ + datalen) + return (-1); + *cp++ = '\0'; /* no domain name */ + __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; + } + hp->ancount = htons(1); + break; + +#ifdef ALLOW_UPDATES + /* + * For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA + * (Record to be modified is followed by its replacement in msg.) + */ + case UPDATEM: + case UPDATEMA: + + case UPDATED: + /* + * The res code for UPDATED and UPDATEDA is the same; user + * calls them differently: specifies data for UPDATED; server + * ignores data if specified for UPDATEDA. + */ + case UPDATEDA: + buflen -= RRFIXEDSZ + datalen; + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + __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; + } + if ( (op == UPDATED) || (op == UPDATEDA) ) { + hp->ancount = htons(0); + break; + } + /* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */ + + case UPDATEA: /* Add new resource record */ + buflen -= RRFIXEDSZ + datalen; + if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0) + return (-1); + cp += n; + __putshort(newrr->r_type, cp); + cp += INT16SZ; + __putshort(newrr->r_class, cp); + cp += INT16SZ; + __putlong(0, cp); + cp += INT32SZ; + __putshort(newrr->r_size, cp); + cp += INT16SZ; + if (newrr->r_size) { + bcopy(newrr->r_data, cp, newrr->r_size); + cp += newrr->r_size; + } + hp->ancount = htons(0); + break; +#endif /* ALLOW_UPDATES */ + default: + return (-1); + } + return (cp - buf); +} diff --git a/resolv/res_query.c b/resolv/res_query.c new file mode 100644 index 0000000000..0d11889595 --- /dev/null +++ b/resolv/res_query.c @@ -0,0 +1,384 @@ +/* + * ++Copyright++ 1988, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)res_query.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/inet.h> +#include <arpa/nameser.h> + +#include <stdio.h> +#include <netdb.h> +#include <resolv.h> +#include <ctype.h> +#include <errno.h> +#if defined(BSD) && (BSD >= 199306) +# include <stdlib.h> +# include <string.h> +#else +# include "../conf/portability.h" +#endif + +#if defined(USE_OPTIONS_H) +# include <../conf/options.h> +#endif + +#if PACKETSZ > 1024 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 1024 +#endif + +char *__hostalias __P((const char *)); +int h_errno; + +/* + * Formulate a normal query, send, and await answer. + * Returned answer is placed in supplied buffer "answer". + * Perform preliminary check of answer, returning success only + * 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) + 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 */ +{ + u_char buf[MAXPACKET]; + register HEADER *hp = (HEADER *) answer; + int n; + + hp->rcode = NOERROR; /* default */ + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return (-1); + } +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query(%s, %d, %d)\n", name, class, type); +#endif + + n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); + if (n <= 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query: mkquery failed\n"); +#endif + h_errno = NO_RECOVERY; + return (n); + } + n = res_send(buf, n, answer, anslen); + if (n < 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + h_errno = TRY_AGAIN; + return (n); + } + + if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; rcode = %d, ancount=%d\n", hp->rcode, + ntohs(hp->ancount)); +#endif + switch (hp->rcode) { + case NXDOMAIN: + h_errno = HOST_NOT_FOUND; + break; + case SERVFAIL: + h_errno = TRY_AGAIN; + break; + case NOERROR: + h_errno = NO_DATA; + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + h_errno = NO_RECOVERY; + break; + } + return (-1); + } + 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 code, if any, is left in h_errno. + */ +int +res_search(name, class, type, answer, anslen) + 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 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) { + h_errno = NETDB_INTERNAL; + return (-1); + } + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + trailing_dot++; + + /* + * if there aren't any dots, it could be a user-level alias + */ + if (!dots && (cp = __hostalias(name)) != NULL) + 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 ((!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 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 (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); +} + +/* + * 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) + 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]; + const char *longname = nbuf; + int n; + +#ifdef DEBUG + if (_res.options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", + name, domain?domain:"<Nil>", class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name) - 1; + if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) { + bcopy(name, nbuf, n); + nbuf[n] = '\0'; + } else + longname = name; + } else + sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); + + return (res_query(longname, class, type, answer, anslen)); +} + +char * +__hostalias(name) + register const char *name; +{ + register char *cp1, *cp2; + FILE *fp; + char *file; + char buf[BUFSIZ]; + static char abuf[MAXDNAME]; + + file = getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "r")) == NULL) + return (NULL); + buf[sizeof(buf) - 1] = '\0'; + while (fgets(buf, sizeof(buf), fp)) { + for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (!strcasecmp(buf, name)) { + while (isspace(*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) + ; + abuf[sizeof(abuf) - 1] = *cp2 = '\0'; + strncpy(abuf, cp1, sizeof(abuf) - 1); + fclose(fp); + return (abuf); + } + } + fclose(fp); + return (NULL); +} diff --git a/resolv/res_send.c b/resolv/res_send.c new file mode 100644 index 0000000000..03055d3619 --- /dev/null +++ b/resolv/res_send.c @@ -0,0 +1,746 @@ +/* + * ++Copyright++ 1985, 1989, 1993 + * - + * 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 + * 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. + * - + * 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[] = "@(#)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. + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <stdio.h> +#include <errno.h> +#include <resolv.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 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))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +#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].%u): %s\n", + string, + inet_ntoa(address.sin_addr), + ntohs(address.sin_port), + strerror(error)); + } + errno = save; + } + static void + Perror(file, string, error) + FILE *file; + char *string; + int error; + { + int save = errno; + + if (_res.options & RES_DEBUG) { + fprintf(file, "res_send: %s: %s\n", + string, strerror(error)); + } + errno = save; + } +#endif + +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; + +void +res_send_setqhook(hook) + res_send_qhook hook; +{ + + Qhook = hook; +} + +void +res_send_setrhook(hook) + res_send_rhook hook; +{ + + Rhook = hook; +} + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_isourserver(inp) + const struct sockaddr_in *inp; +{ + struct sockaddr_in ina; + register int ns, ret; + + ina = *inp; + ret = 0; + for (ns = 0; ns < _res.nscount; ns++) { + register const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; + + if (srv->sin_family == ina.sin_family && + srv->sin_port == ina.sin_port && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { + ret++; + break; + } + } + return (ret); +} + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery(name, type, class, buf, eom) + const char *name; + register int type, class; + const u_char *buf, *eom; +{ + register const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(cp); cp += INT16SZ; + if (ttype == type && + tclass == class && + strcasecmp(tname, name) == 0) + return (1); + } + return (0); +} + +/* int + * res_queriesmatch(buf1, eom1, buf2, eom2) + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * returns: + * -1 : format error + * 0 : not a 1:1 mapping + * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 + */ +int +res_queriesmatch(buf1, eom1, buf2, eom2) + const u_char *buf1, *eom1; + const u_char *buf2, *eom2; +{ + register const u_char *cp = buf1 + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf1)->qdcount); + + if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) + return (0); + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + register int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + ttype = _getshort(cp); cp += INT16SZ; + tclass = _getshort(cp); cp += INT16SZ; + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} + +int +res_send(buf, buflen, ans, anssiz) + const u_char *buf; + int buflen; + u_char *ans; + int anssiz; +{ + HEADER *hp = (HEADER *) buf; + HEADER *anhp = (HEADER *) ans; + int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; + register int n; + u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ + + DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), + (stdout, ";; res_send()\n"), buf); + if (!(_res.options & RES_INIT) && res_init() == -1) + return (-1); + v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; + gotsomewhere = 0; + connreset = 0; + terrno = ETIMEDOUT; + badns = 0; + + /* + * Send request, RETRY times, or until successful + */ + for (try = 0; try < _res.retry; try++) { + for (ns = 0; ns < _res.nscount; ns++) { + 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; + struct iovec iov[2]; + u_short len; + u_char *cp; + + /* + * Use virtual circuit; + * at most one attempt per server. + */ + try = _res.retry; + truncated = 0; + if ((s < 0) || (!vc)) { + if (s >= 0) + _res_close(); + + s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC); + if (s < 0) { + terrno = errno; + Perror(stderr, "socket(vc)", errno); + return (-1); + } + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr)) < 0) { + terrno = errno; + Aerror(stderr, "connect/vc", + errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + vc = 1; + } + /* + * Send length & message + */ + putshort((u_short)buflen, (u_char*)&len); + iov[0].iov_base = (caddr_t)&len; + iov[0].iov_len = INT16SZ; + iov[1].iov_base = (caddr_t)buf; + iov[1].iov_len = buflen; + if (writev(s, iov, 2) != (INT16SZ + buflen)) { + terrno = errno; + Perror(stderr, "write failed", errno); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + /* + * Receive length & response + */ + cp = ans; + len = INT16SZ; + while ((n = read(s, (char *)cp, (int)len)) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + terrno = errno; + Perror(stderr, "read failed", errno); + _res_close(); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (terrno == ECONNRESET && !connreset) { + connreset = 1; + _res_close(); + goto same_ns; + } + _res_close(); + goto next_ns; + } + 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) { + cp += n; + len -= n; + } + if (n <= 0) { + terrno = errno; + Perror(stderr, "read(vc)", errno); + _res_close(); + goto next_ns; + } + if (truncated) { + /* + * Flush rest of answer + * so connection stays in synch. + */ + anhp->tc = 1; + len = resplen - anssiz; + while (len != 0) { + char junk[PACKETSZ]; + + n = (len > sizeof(junk) + ? sizeof(junk) + : len); + if ((n = read(s, junk, n)) > 0) + len -= n; + else + break; + } + } + } else { + /* + * Use datagrams. + */ + 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) { + bad_dg_sock: terrno = errno; + Perror(stderr, "socket(dg)", errno); + return (-1); + } + connected = 0; + } + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * error message is received. We can thus detect + * the absence of a nameserver without timing out. + * If we have sent queries to at least two servers, + * however, we don't want to remain connected, + * as we wish to receive answers from the first + * server to respond. + */ + if (_res.nscount == 1 || (try == 0 && ns == 0)) { + /* + * Connect only if we are sure we won't + * receive a response from another server. + */ + if (!connected) { + if (connect(s, (struct sockaddr *)nsap, + sizeof(struct sockaddr) + ) < 0) { + Aerror(stderr, + "connect(dg)", + errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + connected = 1; + } + if (send(s, (char*)buf, buflen, 0) != buflen) { + Perror(stderr, "send", errno); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + } else { + /* + * Disconnect if we want to listen + * for responses from more than one server. + */ + if (connected) { +#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; + } + if (sendto(s, (char*)buf, buflen, 0, + (struct sockaddr *)nsap, + sizeof(struct sockaddr)) + != buflen) { + Aerror(stderr, "sendto", errno, *nsap); + badns |= (1 << ns); + _res_close(); + goto next_ns; + } + } + + /* + * Wait for reply + */ + timeout.tv_sec = (_res.retrans << try); + if (try > 0) + timeout.tv_sec /= _res.nscount; + if ((long) timeout.tv_sec <= 0) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + wait: + FD_ZERO(&dsmask); + FD_SET(s, &dsmask); + n = select(s+1, &dsmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + if (n < 0) { + Perror(stderr, "select", errno); + _res_close(); + goto next_ns; + } + if (n == 0) { + /* + * timeout + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; timeout\n")); + gotsomewhere = 1; + _res_close(); + goto next_ns; + } + fromlen = sizeof(struct sockaddr_in); + resplen = recvfrom(s, (char*)ans, anssiz, 0, + (struct sockaddr *)&from, &fromlen); + if (resplen <= 0) { + Perror(stderr, "recvfrom", errno); + _res_close(); + goto next_ns; + } + gotsomewhere = 1; + if (hp->id != anhp->id) { + /* + * response from old query, ignore it. + * XXX - potential security hazard could + * be detected here. + */ + 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) && + !res_isourserver(&from)) { + /* + * response from wrong server? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; not our server:\n"), + ans); + goto wait; + } +#endif + if (!(_res.options & RES_INSECURE2) && + !res_queriesmatch(buf, buf + buflen, + ans, ans + anssiz)) { + /* + * response contains wrong query? ignore it. + * XXX - potential security hazard could + * be detected here. + */ + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; wrong query name:\n"), + ans); + goto wait; + } + if (anhp->rcode == SERVFAIL || + anhp->rcode == NOTIMP || + anhp->rcode == REFUSED) { + DprintQ(_res.options & RES_DEBUG, + (stdout, "server rejected query:\n"), + ans); + badns |= (1 << ns); + _res_close(); + /* don't retry if called from dig */ + if (!_res.pfcode) + goto next_ns; + } + if (!(_res.options & RES_IGNTC) && anhp->tc) { + /* + * get rest of answer; + * use TCP with same server. + */ + Dprint(_res.options & RES_DEBUG, + (stdout, ";; truncated answer\n")); + v_circuit = 1; + _res_close(); + goto same_ns; + } + } /*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 + * 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) || 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); + 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 + errno = terrno; + return (-1); +} + +/* + * This routine is for closing the socket if a virtual circuit is used and + * the program wants to close it. This provides support for endhostent() + * which expects to close the socket. + * + * This routine is not expected to be user visible. + */ +void +_res_close() +{ + if (s >= 0) { + (void) close(s); + s = -1; + connected = 0; + vc = 0; + } +} diff --git a/resolv/resolv.h b/resolv/resolv.h new file mode 100644 index 0000000000..d62bdf8ef9 --- /dev/null +++ b/resolv/resolv.h @@ -0,0 +1,240 @@ +/* + * ++Copyright++ 1983, 1987, 1989, 1993 + * - + * 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 + * 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. + * - + * 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-- + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + +#ifndef _RESOLV_H_ +#define _RESOLV_H_ + +#include <sys/param.h> +#if (!defined(BSD)) || (BSD < 199306) +# include <sys/bitypes.h> +#else +# include <sys/types.h> +#endif +#include <sys/cdefs.h> +#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 19941130 + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +/* + * Global defines and variables for resolver stub. + */ +#define MAXNS 3 /* max # name servers we'll track */ +#define MAXDFLSRCH 3 /* # default domain levels to try */ +#define MAXDNSRCH 6 /* max # domains in search path */ +#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 */ + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + u_long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + 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_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 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 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 +#define res_isourserver __res_isourserver +#define res_nameinquery __res_nameinquery +#define res_queriesmatch __res_queriesmatch +__BEGIN_DECLS +int __dn_skipname __P((const u_char *, const u_char *)); +void __fp_resstat __P((struct __res_state *, FILE *)); +void __fp_query __P((const u_char *, FILE *)); +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_int16_t, u_char *)); +char *__p_time __P((u_int32_t)); +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 *, + char *, int)); +int res_init __P((void)); +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)); +int res_isourserver __P((const struct sockaddr_in *)); +int res_nameinquery __P((const char *, int, int, + const u_char *, const u_char *)); +int res_queriesmatch __P((const u_char *, const u_char *, + const u_char *, const u_char *)); +/* 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 new file mode 100644 index 0000000000..709b518a40 --- /dev/null +++ b/resolv/sethostent.c @@ -0,0 +1,80 @@ +/* + * ++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: + * 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. + * - + * 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 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 <netdb.h> +#include <resolv.h> + +void +sethostent(stayopen) + int stayopen; +{ + if (stayopen) + _res.options |= RES_STAYOPEN | RES_USEVC; +} + +void +endhostent() +{ + _res.options &= ~(RES_STAYOPEN | RES_USEVC); + _res_close(); +} diff --git a/resolv/sys/bitypes.h b/resolv/sys/bitypes.h new file mode 100644 index 0000000000..3a9860f713 --- /dev/null +++ b/resolv/sys/bitypes.h @@ -0,0 +1,3 @@ +/* The GNU <sys/types.h> defines all the necessary types. */ + +#include <sys/types.h> |