diff options
| -rw-r--r-- | include/arpa/nameser.h | 284 | ||||
| -rw-r--r-- | include/resolv.h | 158 | ||||
| -rw-r--r-- | lib/libc/net/Makefile.inc | 9 | ||||
| -rw-r--r-- | lib/libc/net/gethostbydns.c | 480 | ||||
| -rw-r--r-- | lib/libc/net/gethostbyht.c | 182 | ||||
| -rw-r--r-- | lib/libc/net/gethostbynis.c | 115 | ||||
| -rw-r--r-- | lib/libc/net/gethostnamadr.c | 522 | ||||
| -rw-r--r-- | lib/libc/net/getnetbydns.c | 308 | ||||
| -rw-r--r-- | lib/libc/net/getnetbyht.c | 159 | ||||
| -rw-r--r-- | lib/libc/net/getnetbynis.c | 117 | ||||
| -rw-r--r-- | lib/libc/net/getnetnamadr.c | 190 | ||||
| -rw-r--r-- | lib/libc/net/res_comp.c | 70 | ||||
| -rw-r--r-- | lib/libc/net/res_debug.c | 467 | ||||
| -rw-r--r-- | lib/libc/net/res_init.c | 256 | ||||
| -rw-r--r-- | lib/libc/net/res_mkquery.c | 91 | ||||
| -rw-r--r-- | lib/libc/net/res_query.c | 231 | ||||
| -rw-r--r-- | lib/libc/net/res_send.c | 678 | 
17 files changed, 3030 insertions, 1287 deletions
| diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h index 81e71fbde8e4..dfaa3dbe59f2 100644 --- a/include/arpa/nameser.h +++ b/include/arpa/nameser.h @@ -30,7 +30,6 @@   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * SUCH DAMAGE.   * - *      @(#)nameser.h	8.2 (Berkeley) 2/16/94   * -   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *  @@ -51,142 +50,134 @@   * SOFTWARE.   * -   * --Copyright-- + * + *      @(#)nameser.h	8.2 (Berkeley) 2/16/94 + *	From Id: nameser.h,v 4.9.1.15 1994/07/19 22:51:24 vixie Exp   */ -#ifndef _ARPA_NAMESER_H_ -#define	_ARPA_NAMESER_H_ +#ifndef _NAMESER_H_ +#define	_NAMESER_H_ +#include <sys/param.h>  #include <sys/types.h> +#include <sys/cdefs.h> +#include <machine/endian.h> + + +/* + * revision information.  this is the release date in YYYYMMDD format. + * it can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__BIND > 19931104)".  do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define	__BIND		19940417	/* interface version stamp */  /*   * Define constants based on rfc883   */ -#define PACKETSZ	512		/* maximum packet size */ -#define MAXDNAME	256		/* maximum domain name */ -#define MAXCDNAME	255		/* maximum compressed domain name */ -#define MAXLABEL	63		/* maximum length of domain label */ -	/* Number of bytes of fixed size data in query structure */ -#define QFIXEDSZ	4 -	/* number of bytes of fixed size data in resource record */ -#define RRFIXEDSZ	10 +#define	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 +#define	NAMESERVER_PORT	53  /* - * Currently defined opcodes + * Currently define	d opcodes   */ -#define QUERY		0x0		/* standard query */ -#define IQUERY		0x1		/* inverse query */ -#define STATUS		0x2		/* nameserver status query */ -/*#define xxx		0x3		/* 0x3 reserved */ +#define	QUERY		0x0		/* standard query */ +#define	IQUERY		0x1		/* inverse query */ +#define	STATUS		0x2		/* nameserver status query */ +			/* 0x3		   reserved */  	/* 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	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 */ +#define	ZONEINIT	0xe		/* initial zone transfer */ +#define	ZONEREF		0xf		/* incremental zone referesh */  /* - * Currently defined response codes + * Currently define	d 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 */ +#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 */  	/* non standard */ -#define NOCHANGE	0xf		/* update failed to change db */ +#define	NOCHANGE	0xf		/* update failed to change db */  /*   * 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		/* connonical 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_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		/* connonical 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 lookup for NSAP */ +#define	T_NSAP_PTR	23		/* reverse NSAP lookup (deprecated) */  	/* non standard */ -#define T_UINFO		100		/* user (finger) information */ -#define T_UID		101		/* user ID */ -#define T_GID		102		/* group ID */ -#define T_UNSPEC	103		/* Unspecified format (binary data) */ +#define	T_UINFO		100		/* user (finger) information */ +#define	T_UID		101		/* user ID */ +#define	T_GID		102		/* group ID */ +#define	T_UNSPEC	103		/* Unspecified format (binary data) */ +#define	T_SA		200		/* shuffle address */  	/* Query type values which do not appear in resource records */ -#define T_AXFR		252		/* transfer zone of authority */ -#define T_MAILB		253		/* transfer mailbox records */ -#define T_MAILA		254		/* transfer mail agent records */ -#define T_ANY		255		/* wildcard match */ +#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) */ +#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 */ +#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 -#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(apollo) || defined(hp9000) || defined(hp9000s300) || \ -    defined (BIT_ZERO_ON_LEFT) -#define BYTE_ORDER	BIG_ENDIAN -#endif -#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 +#define	CONV_SUCCESS	0 +#define	CONV_OVERFLOW	(-1) +#define	CONV_BADFMT	(-2) +#define	CONV_BADCKSUM	(-3) +#define	CONV_BADBUFLEN	(-4)  /*   * Structure for query header.  The order of the fields is machine- and @@ -196,103 +187,100 @@   */  typedef struct { -	u_int16_t id;		/* query identification number */ +	unsigned	id :16;		/* query identification number */  #if BYTE_ORDER == BIG_ENDIAN  			/* fields in third byte */ -	u_int	qr:1;		/* response flag */ -	u_int	opcode:4;	/* purpose of message */ -	u_int	aa:1;		/* authoritive answer */ -	u_int	tc:1;		/* truncated message */ -	u_int	rd:1;		/* recursion desired */ +	unsigned	qr: 1;		/* response flag */ +	unsigned	opcode: 4;	/* purpose of message */ +	unsigned	aa: 1;		/* authoritive answer */ +	unsigned	tc: 1;		/* truncated message */ +	unsigned	rd: 1;		/* recursion desired */  			/* fields in fourth byte */ -	u_int	ra:1;		/* recursion available */ -	u_int	pr:1;		/* primary server required (non standard) */ -	u_int	unused:2;	/* unused bits */ -	u_int	rcode:4;	/* response code */ +	unsigned	ra: 1;		/* recursion available */ +	unsigned	pr: 1;		/* primary server req'd (!standard) */ +	unsigned	unused :2;	/* unused bits (MBZ as of 4.9.3a3) */ +	unsigned	rcode :4;	/* response code */  #endif  #if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN  			/* fields in third byte */ -	u_int	rd:1;		/* recursion desired */ -	u_int	tc:1;		/* truncated message */ -	u_int	aa:1;		/* authoritive answer */ -	u_int	opcode:4;	/* purpose of message */ -	u_int	qr:1;		/* response flag */ +	unsigned	rd :1;		/* recursion desired */ +	unsigned	tc :1;		/* truncated message */ +	unsigned	aa :1;		/* authoritive answer */ +	unsigned	opcode :4;	/* purpose of message */ +	unsigned	qr :1;		/* response flag */  			/* fields in fourth byte */ -	u_int	rcode:4;	/* response code */ -	u_int	unused:2;	/* unused bits */ -	u_int	pr:1;		/* primary server required (non standard) */ -	u_int	ra:1;		/* recursion available */ +	unsigned	rcode :4;	/* response code */ +	unsigned	unused :2;	/* unused bits (MBZ as of 4.9.3a3) */ +	unsigned	pr :1;		/* primary server req'd (!standard) */ +	unsigned	ra :1;		/* recursion available */  #endif  			/* remaining bytes */ -	u_int16_t qdcount;	/* number of question entries */ -	u_int16_t ancount;	/* number of answer entries */ -	u_int16_t nscount;	/* number of authority entries */ -	u_int16_t arcount;	/* number of resource entries */ +	unsigned	qdcount :16;	/* number of question entries */ +	unsigned	ancount :16;	/* number of answer entries */ +	unsigned	nscount :16;	/* number of authority entries */ +	unsigned	arcount :16;	/* number of resource entries */  } HEADER;  /*   * Defines for handling compressed domain names   */ -#define INDIR_MASK	0xc0 +#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 */ +	int16_t		r_zone;			/* zone number */ +	int16_t		r_class;		/* class number */ +	int16_t		r_type;			/* type number */  	u_int32_t	r_ttl;			/* time to live */ -	int	r_size;			/* size of data area */ -	char	*r_data;		/* pointer to data */ +	int		r_size;			/* size of data area */ +	char		*r_data;		/* pointer to data */  }; -extern	u_int16_t	_getshort(); -extern	u_int32_t	_getlong(); +extern	u_int16_t	_getshort __P((const u_char *)); +extern	u_int32_t	_getlong __P((const u_char *));  /*   * Inline versions of get/put short/long.  Pointer is advanced. - * We also assume that a "u_int16_t" holds 2 "chars" - * and that a "u_int32_t" holds 4 "chars".   *   * These macros demonstrate the property of C whereby it can be - * portable or it can be elegant but never both. + * portable or it can be elegant but rarely both.   */ -#define GETSHORT(s, cp) { \ +#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) += 2; \ +	(s) = ((u_int16_t)t_cp[0] << 8) \ +	    | ((u_int16_t)t_cp[1]) \ +	    ; \ +	(cp) += INT16SZ; \  } -#define GETLONG(l, cp) { \ +#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) += 4; \ +	(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) { \ +#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) += 2; \ +	(cp) += INT16SZ; \  } -/* - * Warning: PUTLONG --no-longer-- destroys its first argument.  if you - * were depending on this "feature", you will lose. - */ -#define PUTLONG(l, cp) { \ +#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) += 4; \ +	(cp) += INT32SZ; \  }  #endif /* !_NAMESER_H_ */ diff --git a/include/resolv.h b/include/resolv.h index cf8fe761989c..c903a20e58cf 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -30,8 +30,6 @@   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF   * SUCH DAMAGE.   * - *	@(#)resolv.h	8.1 (Berkeley) 6/2/93 - *	$Id: resolv.h,v 4.9.1.2 1993/05/17 09:59:01 vixie Exp $   * -   * Portions Copyright (c) 1993 by Digital Equipment Corporation.   *  @@ -52,12 +50,30 @@   * SOFTWARE.   * -   * --Copyright-- + * + *	@(#)resolv.h	8.1 (Berkeley) 6/2/93 + *	From Id: resolv.h,v 4.9.1.2 1993/05/17 09:59:01 vixie Exp + *	$Id$   */  #ifndef _RESOLV_H_  #define	_RESOLV_H_ +#include <sys/param.h>  #include <sys/types.h> +#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	19940415 +  /*   * Resolver configuration file.   * Normally not present, but may contain the address of the @@ -65,7 +81,7 @@   */  #ifndef _PATH_RESCONF -#define _PATH_RESCONF        "/etc/resolv.conf" +#define	_PATH_RESCONF        "/etc/resolv.conf"  #endif  /* @@ -77,88 +93,132 @@  #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 */ -	long	options;		/* option flags - see below. */ +	u_long	options;		/* option flags - see below. */  	int	nscount;		/* number of name servers */ -	struct	sockaddr_in nsaddr_list[MAXNS];	/* address of name server */ +	struct sockaddr_in +		nsaddr_list[MAXNS];	/* address of name server */  #define	nsaddr	nsaddr_list[0]		/* for backward compatibility */  	u_short	id;			/* current packet id */  	char	*dnsrch[MAXDNSRCH+1];	/* components of domain to search */  	char	defdname[MAXDNAME];	/* default domain */ -	long	pfcode;			/* RES_PRF_ flags - see below. */ +	u_long	pfcode;			/* RES_PRF_ flags - see below. */ +	unsigned ndots:4;		/* threshold for initial abs. query */ +	unsigned nsort:4;		/* number of elements in sort_list[] */ +	char	unused[3]; +	struct { +		struct in_addr	addr; +		u_int32_t	mask; +	} sort_list[MAXRESOLVSORT];  };  /*   * Resolver options (keep these in synch with res_debug.c, please)   */ -#define RES_INIT	0x0001		/* address initialized */ -#define RES_DEBUG	0x0002		/* print debug messages */ -#define RES_AAONLY	0x0004		/* authoritative answers only */ -#define RES_USEVC	0x0008		/* use virtual circuit */ -#define RES_PRIMARY	0x0010		/* query primary server only */ -#define RES_IGNTC	0x0020		/* ignore trucation errors */ -#define RES_RECURSE	0x0040		/* recursion desired */ -#define RES_DEFNAMES	0x0080		/* use default domain name */ -#define RES_STAYOPEN	0x0100		/* Keep TCP socket open */ -#define RES_DNSRCH	0x0200		/* search up local domain tree */ - -#define RES_DEFAULT	(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) +#define	RES_INIT	0x00000001	/* address initialized */ +#define	RES_DEBUG	0x00000002	/* print debug messages */ +#define	RES_AAONLY	0x00000004	/* authoritative answers only */ +#define	RES_USEVC	0x00000008	/* use virtual circuit */ +#define	RES_PRIMARY	0x00000010	/* query primary server only */ +#define	RES_IGNTC	0x00000020	/* ignore trucation errors */ +#define	RES_RECURSE	0x00000040	/* recursion desired */ +#define	RES_DEFNAMES	0x00000080	/* use default domain name */ +#define	RES_STAYOPEN	0x00000100	/* Keep TCP socket open */ +#define	RES_DNSRCH	0x00000200	/* search up local domain tree */ +#define	RES_INSECURE1	0x00000400	/* type 1 security disabled */ +#define	RES_INSECURE2	0x00000800	/* type 2 security disabled */ + +#define	RES_DEFAULT	(RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)  /*   * Resolver "pfcode" values.  Used by dig.   */ -#define RES_PRF_STATS	0x0001 -/*			0x0002	*/ -#define RES_PRF_CLASS   0x0004 -#define RES_PRF_CMD	0x0008 -#define RES_PRF_QUES	0x0010 -#define RES_PRF_ANS	0x0020 -#define RES_PRF_AUTH	0x0040 -#define RES_PRF_ADD	0x0080 -#define RES_PRF_HEAD1	0x0100 -#define RES_PRF_HEAD2	0x0200 -#define RES_PRF_TTLID	0x0400 -#define RES_PRF_HEADX	0x0800 -#define RES_PRF_QUERY	0x1000 -#define RES_PRF_REPLY	0x2000 -#define RES_PRF_INIT    0x4000 -/*			0x8000	*/ +#define	RES_PRF_STATS	0x00000001 +/*			0x00000002	*/ +#define	RES_PRF_CLASS   0x00000004 +#define	RES_PRF_CMD	0x00000008 +#define	RES_PRF_QUES	0x00000010 +#define	RES_PRF_ANS	0x00000020 +#define	RES_PRF_AUTH	0x00000040 +#define	RES_PRF_ADD	0x00000080 +#define	RES_PRF_HEAD1	0x00000100 +#define	RES_PRF_HEAD2	0x00000200 +#define	RES_PRF_TTLID	0x00000400 +#define	RES_PRF_HEADX	0x00000800 +#define	RES_PRF_QUERY	0x00001000 +#define	RES_PRF_REPLY	0x00002000 +#define	RES_PRF_INIT    0x00004000 +/*			0x00008000	*/ -#include <sys/cdefs.h> -#include <stdio.h> +/* 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_class		__p_class +#define	p_time		__p_time +#define	p_type		__p_type +#define	p_cdnname	__p_cdnname +#define	p_cdname	__p_cdname +#define	p_fqname	__p_fqname +#define	p_rr		__p_rr +#define	p_option	__p_option +  __BEGIN_DECLS  int	 __dn_skipname __P((const u_char *, const u_char *));  void	 __fp_resstat __P((struct __res_state *, FILE *)); -void	 __fp_query __P((char *, FILE *)); +void	 __fp_query __P((const u_char *, FILE *)); +void	 __fp_nquery __P((const u_char *, int, FILE *));  char	*__hostalias __P((const char *));  void	 __putlong __P((u_int32_t, u_char *)); -void	 __putshort __P((u_short, u_char *)); -char	*__p_class __P((int)); +void	 __putshort __P((u_int16_t, u_char *));  char	*__p_time __P((u_int32_t)); -char	*__p_type __P((int)); - -int	 dn_comp __P((const u_char *, u_char *, int, u_char **, u_char **)); +void	 __p_query __P((const u_char *)); +const u_char *__p_cdnname __P((const u_char *, const u_char *, int, FILE *)); +const u_char *__p_cdname __P((const u_char *, const u_char *, FILE *)); +const u_char *__p_fqname __P((const u_char *, const u_char *, FILE *)); +const u_char *__p_rr __P((const u_char *, const u_char *, FILE *)); +const char *__p_type __P((int)); +const char *__p_class __P((int)); +const char *__p_option __P((u_long option)); +int	 dn_comp __P((const char *, u_char *, int, u_char **, u_char **));  int	 dn_expand __P((const u_char *, const u_char *, const u_char *, -			u_char *, int)); +			char *, int));  int	 res_init __P((void)); -int	 res_mkquery __P((int, const char *, int, int, const char *, int, -			  const char *, char *, int)); -int	 res_send __P((const char *, int, char *, int)); +int	 res_query __P((const char *, int, int, u_char *, int)); +int	 res_search __P((const char *, int, int, u_char *, int)); +int	 res_querydomain __P((const char *, const char *, int, int, +			      u_char *, int)); +int	 res_mkquery __P((int, const char *, int, int, const u_char *, int, +			  const u_char *, u_char *, int)); +int	 res_send __P((const u_char *, int, u_char *, int));  __END_DECLS  #endif /* !_RESOLV_H_ */ diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc index c505940aea79..d0b0673ddbf1 100644 --- a/lib/libc/net/Makefile.inc +++ b/lib/libc/net/Makefile.inc @@ -3,13 +3,18 @@  # machine-independent net sources  .PATH: ${.CURDIR}/${MACHINE}/net ${.CURDIR}/net -SRCS+=	gethostnamadr.c getnetbyaddr.c getnetbyname.c getnetent.c \ +SRCS+=	gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \ +	getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \  	getproto.c getprotoent.c getprotoname.c getservbyname.c \  	getservbyport.c getservent.c herror.c inet_addr.c inet_lnaof.c \  	inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c \  	iso_addr.c linkaddr.c ns_addr.c ns_ntoa.c rcmd.c recv.c res_comp.c \  	res_debug.c res_init.c res_mkquery.c res_query.c res_send.c \ -	send.c sethostent.c +	send.c + +# dig(1) requires the resolver to be compiled with debugging enabled +# if you don't care abut dig, you may comment this out +CFLAGS+=-DDEBUG  # machine-dependent net sources  .include "${.CURDIR}/${MACHINE}/net/Makefile.inc" diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c new file mode 100644 index 000000000000..24a8733a33fb --- /dev/null +++ b/lib/libc/net/gethostbydns.c @@ -0,0 +1,480 @@ +/*- + * 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: gethnamaddr.c,v 4.9.1.19 1994/07/22 08:42:54 vixie Exp $"; +#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 <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> + +#define	BYADDR		0 +#define	BYNAME		1 + +#define	MAXALIASES	35 +#define	MAXADDRS	35 + +#define	MULTI_PTRS_ARE_ALIASES 1	/* XXX - experimental */ + +static const char AskedForGot[] = +	"gethostby*.gethostanswer: 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 char hostaddr[MAXADDRS]; +static char *host_addrs[2]; +static int stayopen = 0; + +#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 RESOLVSORT +static void +addrsort(ap, num) +	char **ap; +	int num; +{ +	int i, j; +	char **p; +	short aval[MAXADDRS]; +	int needsort = 0; + +	p = ap; +	for (i = 0; i < num; i++, p++) { +	    for (j = 0 ; j < _res.nsort; j++) +		if (_res.sort_list[j].addr.s_addr ==  +		    (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) +			break; +	    aval[i] = j; +	    if (needsort == 0 && i > 0 && j < aval[i-1]) +		needsort = i; +	} +	if (!needsort) +	    return; + +	while (needsort < num) { +	    for (j = needsort - 1; j >= 0; j--) { +		if (aval[j] > aval[j+1]) { +		    char *hp; + +		    i = aval[j]; +		    aval[j] = aval[j+1]; +		    aval[j+1] = i; + +		    hp = ap[j]; +		    ap[j] = ap[j+1]; +		    ap[j+1] = hp; + +		} else +		    break; +	    } +	    needsort++; +	} +} +#endif + +static struct hostent * +gethostanswer(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; +	host.h_addr_list = h_addr_ptrs; +	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 type %d(%s), got %d(%s)", +			       qtype, qname, type, bp); +			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; +			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]) { +#ifdef DEBUG +				if (_res.options & RES_DEBUG) +					printf("size (%d) too big\n", n); +#endif +				had_error++; +				continue; +			} +			if (hap >= &h_addr_ptrs[MAXADDRS-1]) { +				if (_res.options & RES_DEBUG && !toobig++) +					printf("Too many addresses (%d)\n", +					       MAXADDRS); +				cp += n; +				continue; +			} +			bcopy(cp, *hap++ = bp, n); +			bp += n; +			cp += n; +			break; +		default: +			abort(); +		} /*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 (!host.h_name) { +			n = strlen(qname) + 1;	/* for the \0 */ +			strcpy(bp, qname); +			host.h_name = bp; +		} +		return (&host); +	} else { +		h_errno = TRY_AGAIN; +		return (NULL); +	} +} + +struct hostent * +_gethostbydnsname(name) +	const char *name; +{ +	querybuf buf; +	register const char *cp; +	int n; + +	/* +	 * 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; +				host.h_addr_list = h_addr_ptrs; +				return (&host); +			} +			if (!isdigit(*cp) && *cp != '.')  +				break; +		} + +	if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { +#ifdef DEBUG +		if (_res.options & RES_DEBUG) +			printf("res_search failed\n"); +#endif +		return (NULL); +	} +	return (gethostanswer(&buf, n, name, C_IN, T_A)); +} + +struct hostent * +_gethostbydnsaddr(addr, len, type) +	const char *addr; +	int len, type; +{ +	int n; +	querybuf buf; +	register struct hostent *hp; +	char qbuf[MAXDNAME+1]; +	 +	if (type != AF_INET) +		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) { +#ifdef DEBUG +		if (_res.options & RES_DEBUG) +			printf("res_query failed\n"); +#endif +		return (NULL); +	} +	if (!(hp = gethostanswer(&buf, n, qbuf, C_IN, T_PTR))) +		return (NULL); +	hp->h_addrtype = type; +	hp->h_length = len; +	h_addr_ptrs[0] = (char *)&host_addr; +	h_addr_ptrs[1] = NULL; +	host_addr = *(struct in_addr *)addr; +#if BSD < 43 && !defined(h_addr)	/* new-style hostent structure */ +	hp->h_addr = h_addr_ptrs[0]; +#endif +	return (hp); +} + +void +_sethostdnsent(stayopen) +	int stayopen; +{ +	if (stayopen) +		_res.options |= RES_STAYOPEN | RES_USEVC; +} + +void +_endhostdnsent() +{ +	_res.options &= ~(RES_STAYOPEN | RES_USEVC); +	_res_close(); +} diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c new file mode 100644 index 000000000000..78e0c305c099 --- /dev/null +++ b/lib/libc/net/gethostbyht.c @@ -0,0 +1,182 @@ +/*- + * 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: gethostnamadr.c,v 1.1 1994/05/27 04:57:16 rgrimes Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> + +#define	MAXALIASES	35 +#define	MAXADDRS	35 + +static struct hostent host; +static char *host_aliases[MAXALIASES]; +static char hostbuf[BUFSIZ+1]; +static FILE *hostf = NULL; +static char hostaddr[MAXADDRS]; +static char *host_addrs[2]; +static int stayopen = 0; + +void +_sethosthtent(f) +	int f; +{ +	if (hostf == NULL) +		hostf = fopen(_PATH_HOSTS, "r" ); +	else +		rewind(hostf); +	stayopen |= f; +} + +void +_endhosthtent() +{ +	if (hostf && !stayopen) { +		(void) fclose(hostf); +		hostf = NULL; +	} +} + +struct hostent * +gethostent() +{ +	char *p; +	register char *cp, **q; + +	if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) +		return (NULL); +again: +	if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) +		return (NULL); +	if (*p == '#') +		goto again; +	cp = strpbrk(p, "#\n"); +	if (cp == NULL) +		goto again; +	*cp = '\0'; +	cp = strpbrk(p, " \t"); +	if (cp == NULL) +		goto again; +	*cp++ = '\0'; +	/* THIS STUFF IS INTERNET SPECIFIC */ +	host.h_addr_list = host_addrs; +	host.h_addr = hostaddr; +	*((u_int32_t *)host.h_addr) = inet_addr(p); +	host.h_length = sizeof (u_int32_t); +	host.h_addrtype = AF_INET; +	while (*cp == ' ' || *cp == '\t') +		cp++; +	host.h_name = cp; +	q = host.h_aliases = host_aliases; +	cp = strpbrk(cp, " \t"); +	if (cp != NULL)  +		*cp++ = '\0'; +	while (cp && *cp) { +		if (*cp == ' ' || *cp == '\t') { +			cp++; +			continue; +		} +		if (q < &host_aliases[MAXALIASES - 1]) +			*q++ = cp; +		cp = strpbrk(cp, " \t"); +		if (cp != NULL) +			*cp++ = '\0'; +	} +	*q = NULL; +	return (&host); +} + +struct hostent * +_gethostbyhtname(name) +	char *name; +{ +	register struct hostent *p; +	register char **cp; +	 +	sethostent(0); +	while ((p = gethostent())) { +		if (strcasecmp(p->h_name, name) == 0) +			break; +		for (cp = p->h_aliases; *cp != 0; cp++) +			if (strcasecmp(*cp, name) == 0) +				goto found; +	} +found: +	endhostent(); +	return (p); +} + +struct hostent * +_gethostbyhtaddr(addr, len, type) +	const char *addr; +	int len, type; +{ +	register struct hostent *p; + +	sethostent(0); +	while ((p = gethostent())) +		if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len)) +			break; +	endhostent(); +	return (p); +} diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c new file mode 100644 index 000000000000..53b426d19a21 --- /dev/null +++ b/lib/libc/net/gethostbynis.c @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 1994, Garrett Wollman + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE 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[] = "@(#)$Id$"; +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 <netdb.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> + +#define	MAXALIASES	35 +#define	MAXADDRS	35 + +#ifdef YP +static char *host_aliases[MAXALIASES]; +static char hostaddr[MAXADDRS]; +static char *host_addrs[2]; +#endif /* YP */ + +static struct hostent * +_gethostbynis(name, map) +	char *name, *map; +{ +#ifdef YP +	register char *cp, **q; +	char *result; +	int resultlen; +	static struct hostent h; +	static char *domain = (char *)NULL; + +	if (domain == (char *)NULL) +		if (yp_get_default_domain (&domain)) +			return ((struct hostent *)NULL); + +	if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) +		return ((struct hostent *)NULL); + +	if ((cp = index(result, '\n'))) +		*cp = '\0'; + +	cp = strpbrk(result, " \t"); +	*cp++ = '\0'; +	h.h_addr_list = host_addrs; +	h.h_addr = hostaddr; +	*((u_long *)h.h_addr) = inet_addr(result); +	h.h_length = sizeof(u_long); +	h.h_addrtype = AF_INET; +	while (*cp == ' ' || *cp == '\t') +		cp++; +	h.h_name = cp; +	q = h.h_aliases = host_aliases; +	cp = strpbrk(cp, " \t"); +	if (cp != NULL) +		*cp++ = '\0'; +	while (cp && *cp) { +		if (*cp == ' ' || *cp == '\t') { +			cp++; +			continue; +		} +		if (q < &host_aliases[MAXALIASES - 1]) +			*q++ = cp; +		cp = strpbrk(cp, " \t"); +		if (cp != NULL) +			*cp++ = '\0'; +	} +	*q = NULL; +	return (&h); +#else +	return (NULL); +#endif /* YP */ +} + +struct hostent * +_gethostbynisname(name) +	char *name; +{ +	return _gethostbynis(name, "hosts.byname"); +} + +struct hostent * +_gethostbynisaddr(name) +	char *name; +{ +	return _gethostbynis(name, "hosts.byaddr"); +} diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c index cbb7d7439f0f..1e8672a6bf36 100644 --- a/lib/libc/net/gethostnamadr.c +++ b/lib/libc/net/gethostnamadr.c @@ -1,6 +1,5 @@  /*- - * Copyright (c) 1985, 1988, 1993 - *	The Regents of the University of California.  All rights reserved. + * Copyright (c) 1994, Garrett Wollman   *   * Redistribution and use in source and binary forms, with or without   * modification, are permitted provided that the following conditions @@ -10,15 +9,8 @@   * 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 + * THIS SOFTWARE IS PROVIDED BY THE 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 @@ -29,49 +21,29 @@   * 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[] = "From: @(#)gethostnamadr.c	8.1 (Berkeley) 6/4/93"; -/*static char rcsid[] = "From: Id: gethnamaddr.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel ";*/ -static const char rcsid[] = -  "$Id: gethostnamadr.c,v 1.3 1994/08/09 22:44:12 wollman Exp $"; +static char sccsid[] = "@(#)$Id$"; +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 <netdb.h> -#include <resolv.h>  #include <stdio.h>  #include <ctype.h>  #include <errno.h>  #include <string.h> -#define	MAXALIASES	35 -#define	MAXADDRS	35 +extern struct hostent * _gethostbyhtname  __P((const char *)); +extern struct hostent * _gethostbydnsname __P((const char *)); +extern struct hostent * _gethostbynisname __P((const char *)); +extern struct hostent * _gethostbyhtaddr  __P((const char *, int, int)); +extern struct hostent * _gethostbydnsaddr __P((const char *, int, int)); +extern struct hostent * _gethostbynisaddr __P((const char *, int, int));  #define _PATH_HOSTCONF	"/etc/host.conf" @@ -102,35 +74,6 @@ static struct {  static enum service_type service_order[SERVICE_MAX + 1];  static int service_done = 0; -static char *h_addr_ptrs[MAXADDRS + 1]; - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[BUFSIZ+1]; -static struct in_addr host_addr; -static FILE *hostf = NULL; -static char hostaddr[MAXADDRS]; -static char *host_addrs[2]; -static int stayopen = 0; - -#if PACKETSZ > 1024 -#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; -  static enum service_type  get_service_name(const char *name) {  	int i; @@ -174,429 +117,27 @@ init_services()  	service_done = 1;  } -static struct hostent * -getanswer(answer, anslen, iquery) -	querybuf *answer; -	int anslen; -	int iquery; -{ -	register HEADER *hp; -	register u_char *cp; -	register int n; -	u_char *eom; -	char *bp, **ap; -	int type, class, buflen, ancount, qdcount; -	int haveanswer, getclass = C_ANY; -	char **hap; - -	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 + sizeof(HEADER); -	if (qdcount) { -		if (iquery) { -			if ((n = dn_expand((u_char *)answer->buf, -			    (u_char *)eom, (u_char *)cp, (u_char *)bp, -			    buflen)) < 0) { -				h_errno = NO_RECOVERY; -				return ((struct hostent *) NULL); -			} -			cp += n + QFIXEDSZ; -			host.h_name = bp; -			n = strlen(bp) + 1; -			bp += n; -			buflen -= n; -		} else -			cp += __dn_skipname(cp, eom) + QFIXEDSZ; -		while (--qdcount > 0) -			cp += __dn_skipname(cp, eom) + QFIXEDSZ; -	} else if (iquery) { -		if (hp->aa) -			h_errno = HOST_NOT_FOUND; -		else -			h_errno = TRY_AGAIN; -		return ((struct hostent *) NULL); -	} -	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; -	while (--ancount >= 0 && cp < eom) { -		if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom, -		    (u_char *)cp, (u_char *)bp, buflen)) < 0) -			break; -		cp += n; -		type = _getshort(cp); - 		cp += sizeof(u_int16_t); -		class = _getshort(cp); - 		cp += sizeof(u_int16_t) + sizeof(u_int32_t); -		n = _getshort(cp); -		cp += sizeof(u_int16_t); -		if (type == T_CNAME) { -			cp += n; -			if (ap >= &host_aliases[MAXALIASES-1]) -				continue; -			*ap++ = bp; -			n = strlen(bp) + 1; -			bp += n; -			buflen -= n; -			continue; -		} -		if (iquery && type == T_PTR) { -			if ((n = dn_expand((u_char *)answer->buf, -			    (u_char *)eom, (u_char *)cp, (u_char *)bp, -			    buflen)) < 0) -				break; -			cp += n; -			host.h_name = bp; -			return(&host); -		} -		if (iquery || type != T_A)  { -#ifdef DEBUG -			if (_res.options & RES_DEBUG) -				printf("unexpected answer type %d, size %d\n", -					type, n); -#endif -			cp += n; -			continue; -		} -		if (haveanswer) { -			if (n != host.h_length) { -				cp += n; -				continue; -			} -			if (class != getclass) { -				cp += n; -				continue; -			} -		} else { -			host.h_length = n; -			getclass = class; -			host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; -			if (!iquery) { -				host.h_name = bp; -				bp += strlen(bp) + 1; -			} -		} - -		bp += sizeof(align) - ((u_int32_t)bp % sizeof(align)); - -		if (bp + n >= &hostbuf[sizeof(hostbuf)]) { -#ifdef DEBUG -			if (_res.options & RES_DEBUG) -				printf("size (%d) too big\n", n); -#endif -			break; -		} -		bcopy(cp, *hap++ = bp, n); -		bp +=n; -		cp += n; -		haveanswer++; -	} -	if (haveanswer) { -		*ap = NULL; -#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */ -		*hap = NULL; -#else -		host.h_addr = h_addr_ptrs[0]; -#endif -		return (&host); -	} else { -		h_errno = TRY_AGAIN; -		return ((struct hostent *) NULL); -	} -} - -struct hostent * -_getdnsbyname(name) -	const char *name; -{ -	querybuf buf; -	register const char *cp; -	int n; -	extern struct hostent *_gethtbyname(); - -	/* -	 * 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((struct hostent *) NULL); -				} -				host.h_name = (char *)name; -				host.h_aliases = host_aliases; -				host_aliases[0] = NULL; -				host.h_addrtype = AF_INET; -				host.h_length = sizeof(u_int32_t); -				h_addr_ptrs[0] = (char *)&host_addr; -				h_addr_ptrs[1] = (char *)0; -#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 -				return (&host); -			} -			if (!isdigit(*cp) && *cp != '.')  -				break; -		} - -	if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) { -#ifdef DEBUG -		if (_res.options & RES_DEBUG) -			printf("res_search failed\n"); -#endif -		return ((struct hostent *) NULL); -	} -	return (getanswer(&buf, n, 0)); -} - -struct hostent * -_getdnsbyaddr(addr, len, type) -	const char *addr; -	int len, type; -{ -	int n; -	querybuf buf; -	register struct hostent *hp; -	char qbuf[MAXDNAME]; -	extern struct hostent *_gethtbyaddr(); -	 -	if (type != AF_INET) -		return ((struct hostent *) NULL); -	(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", -		((unsigned)addr[3] & 0xff), -		((unsigned)addr[2] & 0xff), -		((unsigned)addr[1] & 0xff), -		((unsigned)addr[0] & 0xff)); -	n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf)); -	if (n < 0) { -#ifdef DEBUG -		if (_res.options & RES_DEBUG) -			printf("res_query failed\n"); -#endif -		return ((struct hostent *) NULL); -	} -	hp = getanswer(&buf, n, 1); -	if (hp == NULL) -		return ((struct hostent *) NULL); -	hp->h_addrtype = type; -	hp->h_length = len; -	h_addr_ptrs[0] = (char *)&host_addr; -	h_addr_ptrs[1] = (char *)0; -	host_addr = *(struct in_addr *)addr; -#if BSD < 43 && !defined(h_addr)	/* new-style hostent structure */ -	hp->h_addr = h_addr_ptrs[0]; -#endif -	return(hp); -} - -void -_sethtent(f) -	int f; -{ -	if (hostf == NULL) -		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 == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL) -		return (NULL); -again: -	if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL) -		return (NULL); -	if (*p == '#') -		goto again; -	cp = strpbrk(p, "#\n"); -	if (cp == NULL) -		goto again; -	*cp = '\0'; -	cp = strpbrk(p, " \t"); -	if (cp == NULL) -		goto again; -	*cp++ = '\0'; -	/* THIS STUFF IS INTERNET SPECIFIC */ -#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */ -	host.h_addr_list = host_addrs; -#endif -	host.h_addr = hostaddr; -	*((u_int32_t *)host.h_addr) = inet_addr(p); -	host.h_length = sizeof (u_int32_t); -	host.h_addrtype = AF_INET; -	while (*cp == ' ' || *cp == '\t') -		cp++; -	host.h_name = cp; -	q = host.h_aliases = host_aliases; -	cp = strpbrk(cp, " \t"); -	if (cp != NULL)  -		*cp++ = '\0'; -	while (cp && *cp) { -		if (*cp == ' ' || *cp == '\t') { -			cp++; -			continue; -		} -		if (q < &host_aliases[MAXALIASES - 1]) -			*q++ = cp; -		cp = strpbrk(cp, " \t"); -		if (cp != NULL) -			*cp++ = '\0'; -	} -	*q = NULL; -	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 YP -struct hostent * -_getnishost(name, map) -	char *name, *map; -{ -	register char *cp, *dp, **q; -	char *result; -	int resultlen; -	static struct hostent h; -	static char *domain = (char *)NULL; - -	if (domain == (char *)NULL) -		if (yp_get_default_domain (&domain)) -			return ((struct hostent *)NULL); - -	if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) -		return ((struct hostent *)NULL); - -	if (cp = index(result, '\n')) -		*cp = '\0'; - -	cp = strpbrk(result, " \t"); -	*cp++ = '\0'; -#if BSD >= 43 || defined(h_addr)	/* new-style hostent structure */ -	h.h_addr_list = host_addrs; -#endif -	h.h_addr = hostaddr; -	*((u_long *)h.h_addr) = inet_addr(result); -	h.h_length = sizeof(u_long); -	h.h_addrtype = AF_INET; -	while (*cp == ' ' || *cp == '\t') -		cp++; -	h.h_name = cp; -	q = h.h_aliases = host_aliases; -	cp = strpbrk(cp, " \t"); -	if (cp != NULL) -		*cp++ = '\0'; -	while (cp && *cp) { -		if (*cp == ' ' || *cp == '\t') { -			cp++; -			continue; -		} -		if (q < &host_aliases[MAXALIASES - 1]) -			*q++ = cp; -		cp = strpbrk(cp, " \t"); -		if (cp != NULL) -			*cp++ = '\0'; -	} -	*q = NULL; -	return (&h); -} -#endif /* YP */ -  struct hostent *  gethostbyname(const char *name)  {  	struct hostent *hp = 0;  	int nserv = 0; -	if(!service_done) { +	if (!service_done)  		init_services(); -	} -	while(!hp) { -		switch(service_order[nserv]) { +	while (!hp) { +		switch (service_order[nserv]) {  		      case SERVICE_NONE: -			return 0; +			return NULL;  		      case SERVICE_HOSTS: -			hp = _gethtbyname(name); +			hp = _gethostbyhtname(name);  			break;  		      case SERVICE_BIND: -			hp = _getdnsbyname(name); +			hp = _gethostbydnsname(name);  			break;  		      case SERVICE_NIS: -#ifdef YP -			hp = _getnishost(name, "hosts.byname"); -#endif +			hp = _gethostbynisname(name);  			break;  		}  		nserv++; @@ -610,24 +151,21 @@ gethostbyaddr(const char *addr, int len, int type)  	struct hostent *hp = 0;  	int nserv = 0; -	if(!service_done) { +	if (!service_done)  		init_services(); -	} -	while(!hp) { -		switch(service_order[nserv]) { +	while (!hp) { +		switch (service_order[nserv]) {  		      case SERVICE_NONE:  			return 0;  		      case SERVICE_HOSTS: -			hp = _gethtbyaddr(addr, len, type); +			hp = _gethostbyhtaddr(addr, len, type);  			break;  		      case SERVICE_BIND: -			hp = _getdnsbyaddr(addr, len, type); +			hp = _gethostbydnsaddr(addr, len, type);  			break;  		      case SERVICE_NIS: -#ifdef YP -			hp = _getnishost(addr, "hosts.byaddr"); -#endif +			hp = _gethostbynisaddr(addr, len, type);  			break;  		}  		nserv++; @@ -635,3 +173,17 @@ gethostbyaddr(const char *addr, int len, int type)  	return hp;  } +void +sethostent(stayopen) +	int stayopen; +{ +	_sethosthtent(stayopen); +	_sethostdnsent(stayopen); +} + +void +endhostent() +{ +	_endhosthtent(); +	_endhostdnsent(); +} diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c new file mode 100644 index 000000000000..02e5088568a3 --- /dev/null +++ b/lib/libc/net/getnetbydns.c @@ -0,0 +1,308 @@ +/*- + * 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 <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> + +#define	BYNAME		0 +#define	BYADDR		1 + +#define	MAXALIASES	35 +#define	MAXADDRS	35 + +#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; + +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; +	char		aux1[30], aux2[30], ans[30], +			*in, *st, *pauxt, *bp, **ap, +			*paux1 = &aux1[0], +			*paux2 = &aux2[0], +			flag = 0; +static	struct netent	net_entry; +static	char		*net_aliases[MAXALIASES], +			netbuf[BUFSIZ+1]; + +	/* +	 * find first satisfactory answer +	 * +	 *      answer --> +------------+  ( MESSAGE ) +	 *		   |   Header   | +	 *		   +------------+ +	 *		   |  Question  | the question for the name server +	 *		   +------------+ +	 *		   |   Answer   | RRs answering the question +	 *		   +------------+ +	 *		   | Authority  | RRs pointing toward an authority +	 *		   | Additional | RRs holding additional information +	 *		   +------------+ +	 */ +	eom = answer->buf + anslen; +	hp = &answer->hdr; +	ancount = ntohs(hp->ancount); /* #/records in the answer section */ +	qdcount = ntohs(hp->qdcount); /* #/entries in the question section */ +	bp = netbuf; +	buflen = sizeof(netbuf); +	cp = answer->buf + HFIXEDSZ; +	if (!qdcount) { +		if (hp->aa) +			h_errno = HOST_NOT_FOUND; +		else +			h_errno = TRY_AGAIN; + +		return ((struct netent *) NULL); +	} +	while (qdcount-- > 0){ +		cp += __dn_skipname(cp, eom) + QFIXEDSZ; +        } +	ap = net_aliases; +	*ap = NULL; +	net_entry.n_aliases = net_aliases; +	haveanswer = 0; +	while (--ancount >= 0 && cp < eom) { +		n = dn_expand(answer->buf, eom, cp, bp, buflen); +		if (n < 0) +			break; +		cp += n; +		ans[0] = '\0'; +		(void)strcpy(&ans[0], bp); +		GETSHORT(type, cp); +		GETSHORT(class, cp); +		cp += INT32SZ;		/* TTL */ +		GETSHORT(n, cp); +		if (class == C_IN && type == T_PTR) { +			n = dn_expand(answer->buf, eom, cp, bp, buflen); +			if (n < 0) { +				cp += n; +				return (NULL); +			} +			cp += n;  +			*ap++ = bp; +			bp += (strlen(bp) + 1); +			net_entry.n_addrtype = (class == C_IN) +						? AF_INET +						: AF_UNSPEC; +			haveanswer++; +		} +	} +	if (haveanswer) { +		*ap = NULL; +		switch (net_i) { +		   case BYADDR : +			net_entry.n_name = *net_entry.n_aliases; +			net_entry.n_net = 0L; +			break; +		   case BYNAME : +			in = *net_entry.n_aliases; +			net_entry.n_name = &ans[0]; +			aux2[0] = '\0'; +			for (i = 0;  i < 4;  i++) { +				for (st = in, nchar = 0; +				     *st != '.'; +				     st++, nchar++) +					; +				if (nchar != 1 || *in != '0' || flag) { +					flag = 1; +					(void)strncpy(paux1, +						      (i==0) ?in :in-1, +						      (i==0) ?nchar :nchar+1); +					paux1[(i==0) ?nchar :nchar+1] = '\0'; +					pauxt = paux2; +					paux2 = strcat(paux1, paux2); +					paux1 = pauxt; +				} +				in = ++st; +			}		   +			net_entry.n_net = inet_network(paux2); +		} +		net_entry.n_aliases++; +		return (&net_entry); +	} else { +		h_errno = TRY_AGAIN; +		return ((struct netent *) NULL); +	} +} + +struct netent * +_getnetbydnsaddr(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 (NULL); + +	for (nn = 4, net2 = net;  net2;  net2 >>= 8) { +		netbr[--nn] = net2 & 0xff; +	} +	switch (nn) { +		case 3: 	/* Class A */ +			(void)sprintf(qbuf, "0.0.0.%u.in-addr.arpa", +				      netbr[3]); +			break; +		case 2: 	/* Class B */ +			(void)sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", +				      netbr[3], netbr[2]); +			break; +		case 1: 	/* Class C */ +			(void)sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", +				      netbr[3], netbr[2], netbr[1]); +			break; +		case 0: 	/* Class D - E */ +			(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", +				      netbr[3], netbr[2], netbr[1], netbr[0]); +			break; +	} +	anslen = res_query(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); +	if (anslen < 0) { +#ifdef DEBUG +		if (_res.options & RES_DEBUG) +			printf("res_query failed\n"); +#endif +		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); +} + +struct netent * +_getnetbydnsname(net) +	register const char *net; +{ +	int		anslen; +	querybuf	buf; +	char		qbuf[MAXDNAME]; +        +	(void)strcpy(&qbuf[0],net); +	anslen = res_search(qbuf, C_IN, T_PTR, buf.buf, sizeof buf.buf); +	if (anslen < 0) { +#ifdef DEBUG +		if (_res.options & RES_DEBUG) +			printf("res_query failed\n"); +#endif +		return NULL; +	} +	return getnetanswer(&buf, anslen, BYNAME); +} + +void +_setnetdnsent(stayopen) +	int stayopen; +{ +	if (stayopen) +		_res.options |= RES_STAYOPEN | RES_USEVC; +} + +void +_endnetdnsent() +{ +	_res.options &= ~(RES_STAYOPEN | RES_USEVC); +	_res_close(); +} diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c new file mode 100644 index 000000000000..cdb5e4933b76 --- /dev/null +++ b/lib/libc/net/getnetbyht.c @@ -0,0 +1,159 @@ +/* + * 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[] = "@(#)getnetent.c	8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <string.h> + +#define	MAXALIASES	35 + +static FILE *netf; +static char line[BUFSIZ+1]; +static struct netent net; +static char *net_aliases[MAXALIASES]; +static int _net_stayopen; + +void +_setnethtent(f) +	int f; +{ +	if (netf == NULL) +		netf = fopen(_PATH_NETWORKS, "r" ); +	else +		rewind(netf); +	_net_stayopen |= f; +} + +void +_endnethtent() +{ +	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); +} + +struct netent * +_getnetbyhtname(name) +	register const char *name; +{ +	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); +} + + +struct netent * +_getnetbyhtaddr(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/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c new file mode 100644 index 000000000000..654a278d46d9 --- /dev/null +++ b/lib/libc/net/getnetbynis.c @@ -0,0 +1,117 @@ +/*- + * Copyright (c) 1994, Garrett Wollman + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE 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[] = "@(#)$Id$"; +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 <netdb.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> + +#define	MAXALIASES	35 +#define	MAXADDRS	35 + +#ifdef YP +static char *host_aliases[MAXALIASES]; +#endif /* YP */ + +static struct netent * +_getnetbynis(name, map) +	char *name, *map; +{ +#ifdef YP +	register char *cp, **q; +	char *result; +	int resultlen; +	static struct netent h; +	static char *domain = (char *)NULL; + +	if (domain == (char *)NULL) +		if (yp_get_default_domain (&domain)) +			return (NULL); + +	if (yp_match(domain, map, name, strlen(name), &result, &resultlen)) +		return (NULL); + +	if ((cp = index(result, '\n'))) +		*cp = '\0'; + +	cp = strpbrk(result, " \t"); +	*cp++ = '\0'; +	h.n_net = inet_addr(result); +	h.n_addrtype = AF_INET; +	while (*cp == ' ' || *cp == '\t') +		cp++; +	h.n_name = cp; +	q = h.n_aliases = host_aliases; +	cp = strpbrk(cp, " \t"); +	if (cp != NULL) +		*cp++ = '\0'; +	while (cp && *cp) { +		if (*cp == ' ' || *cp == '\t') { +			cp++; +			continue; +		} +		if (q < &host_aliases[MAXALIASES - 1]) +			*q++ = cp; +		cp = strpbrk(cp, " \t"); +		if (cp != NULL) +			*cp++ = '\0'; +	} +	*q = NULL; +	return (&h); +#else +	return (NULL); +#endif +} + +struct netent * +_getnetbynisname(name) +	char *name; +{ +	return _getnetbynis(name, "networks.byname"); +} + +struct netent * +_getnetbynisaddr(addr, type) +	long addr; +	int type; +{ +	struct in_addr in; + +	if (type != AF_INET) +		return (NULL); + +	in.s_addr = addr;	 +	return _getnetbynis(inet_ntoa(in), "networks.byaddr"); +} diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c new file mode 100644 index 000000000000..c85af02a22c5 --- /dev/null +++ b/lib/libc/net/getnetnamadr.c @@ -0,0 +1,190 @@ +/*- + * Copyright (c) 1994, Garrett Wollman + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE 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[] = "@(#)$Id$"; +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 <netdb.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> + +extern struct netent * _getnetbyhtname  __P((const char *)); +extern struct netent * _getnetbydnsname __P((const char *)); +extern struct netent * _getnetbynisname __P((const char *)); +extern struct netent * _getnetbyhtaddr  __P((long, int)); +extern struct netent * _getnetbydnsaddr __P((long, int)); +extern struct netent * _getnetbynisaddr __P((long, int)); + +#define _PATH_NETCONF	"/etc/net.conf" + +enum service_type {  +  SERVICE_NONE = 0, +  SERVICE_BIND, +  SERVICE_TABLE, +  SERVICE_NIS }; +#define SERVICE_MAX	SERVICE_NIS + +static struct { +  const char *name; +  enum service_type type; +} service_names[] = { +  { "nets", SERVICE_TABLE }, +  { "/etc/nets", SERVICE_TABLE }, +  { "nettable", SERVICE_TABLE }, +  { "ntable", SERVICE_TABLE }, +  { "bind", SERVICE_BIND }, +  { "dns", SERVICE_BIND }, +  { "domain", SERVICE_BIND }, +  { "yp", SERVICE_NIS }, +  { "yellowpages", SERVICE_NIS }, +  { "nis", SERVICE_NIS }, +  { 0, SERVICE_NONE } +}; + +static enum service_type service_order[SERVICE_MAX + 1]; +static int service_done = 0; + +static enum service_type +get_service_name(const char *name) { +	int i; +	for(i = 0; service_names[i].type != SERVICE_NONE; i++) { +		if(!strcasecmp(name, service_names[i].name)) { +			return service_names[i].type; +		} +	} +	return SERVICE_NONE; +} + +static void +init_services() +{ +	char *cp, buf[BUFSIZ]; +	register int cc = 0; +	FILE *fd; + +	if ((fd = (FILE *)fopen(_PATH_NETCONF, "r")) == NULL) { +				/* make some assumptions */ +		service_order[0] = SERVICE_TABLE; +		service_order[1] = SERVICE_NONE; +	} else { +		while (fgets(buf, BUFSIZ, fd) != NULL && cc < SERVICE_MAX) { +			if(buf[0] == '#') +				continue; + +			cp = strtok(buf, "\n \t,:;"); +			do { +				if(!isalpha(cp[0])) continue; +				service_order[cc] = get_service_name(buf); +				if(service_order[cc] != SERVICE_NONE) +					cc++; +			} while((cp = strtok((char *)0, "\n \t,:;")) +				&& (cc < SERVICE_MAX)); +		} +		service_order[cc] = SERVICE_NONE; +		fclose(fd); +	} +	service_done = 1; +} + +struct netent * +getnetbyname(const char *name) +{ +	struct netent *hp = 0; +	int nserv = 0; + +	if (!service_done) +		init_services(); + +	while (!hp) { +		switch (service_order[nserv]) { +		      case SERVICE_NONE: +			return NULL; +		      case SERVICE_TABLE: +			hp = _getnetbyhtname(name); +			break; +		      case SERVICE_BIND: +			hp = _getnetbydnsname(name); +			break; +		      case SERVICE_NIS: +			hp = _getnetbynisname(name); +			break; +		} +		nserv++; +	} +	return hp; +} + +struct netent * +getnetbyaddr(addr, type) +	long addr; +	int type; +{ +	struct netent *hp = 0; +	int nserv = 0; + +	if (!service_done) +		init_services(); + +	while (!hp) { +		switch (service_order[nserv]) { +		      case SERVICE_NONE: +			return 0; +		      case SERVICE_TABLE: +			hp = _getnetbyhtaddr(addr, type); +			break; +		      case SERVICE_BIND: +			hp = _getnetbydnsaddr(addr, type); +			break; +		      case SERVICE_NIS: +			hp = _getnetbynisaddr(addr, type); +			break; +		} +		nserv++; +	} +	return hp; +} + +void +setnetent(stayopen) +	int stayopen; +{ +	_setnethtent(stayopen); +	_setnetdnsent(stayopen); +} + +void +endnetent() +{ +	_endnethtent(); +	_endnetdnsent(); +} diff --git a/lib/libc/net/res_comp.c b/lib/libc/net/res_comp.c index 66f37ba261cb..1e7653555586 100644 --- a/lib/libc/net/res_comp.c +++ b/lib/libc/net/res_comp.c @@ -53,16 +53,22 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_comp.c	8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_comp.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; +static char rcsid[] = "$Id: res_comp.c,v 4.9.1.11 1994/07/23 23:24:11 vixie Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> -#include <arpa/nameser.h>  #include <netinet/in.h> -#include <resolv.h> +#include <arpa/nameser.h> +  #include <stdio.h> +#include <resolv.h> +#include <ctype.h> -static int dn_find(); +#include <unistd.h> +#include <string.h> + +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. @@ -71,23 +77,25 @@ static int dn_find();   * 'exp_dn' is a pointer to a buffer of size 'length' for the result.   * Return size of compressed name or -1 if there was an error.   */ +int  dn_expand(msg, eomorig, comp_dn, exp_dn, length)  	const u_char *msg, *eomorig, *comp_dn; -	u_char *exp_dn; +	char *exp_dn;  	int length;  { -	register u_char *cp, *dn; +	register const u_char *cp; +	register char *dn;  	register int n, c; -	u_char *eom; +	char *eom;  	int len = -1, checked = 0;  	dn = exp_dn; -	cp = (u_char *)comp_dn; +	cp = comp_dn;  	eom = exp_dn + length;  	/*  	 * fetch next label in domain name  	 */ -	while (n = *cp++) { +	while ((n = *cp++)) {  		/*  		 * Check for indirection  		 */ @@ -116,7 +124,7 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)  		case INDIR_MASK:  			if (len < 0)  				len = cp - comp_dn + 1; -			cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff)); +			cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));  			if (cp < msg || cp >= eomorig)	/* out of range */  				return(-1);  			checked += 2; @@ -134,6 +142,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)  		}  	}  	*dn = '\0'; +	for (dn = exp_dn; (c = *dn) != '\0'; dn++) +		if (isascii(c) && isspace(c)) +			return (-1);  	if (len < 0)  		len = cp - comp_dn;  	return (len); @@ -151,8 +162,9 @@ dn_expand(msg, eomorig, comp_dn, exp_dn, length)   * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'   * is NULL, we don't update the list.   */ +int  dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) -	const u_char *exp_dn; +	const char *exp_dn;  	u_char *comp_dn, **dnptrs, **lastdnptr;  	int length;  { @@ -164,6 +176,7 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)  	dn = (u_char *)exp_dn;  	cp = comp_dn;  	eob = cp + length; +	lpp = cpp = NULL;  	if (dnptrs != NULL) {  		if ((msg = *dnptrs++) != NULL) {  			for (cpp = dnptrs; *cpp != NULL; cpp++) @@ -229,31 +242,44 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)  /*   * Skip over a compressed domain name. Return the size or -1.   */ +int  __dn_skipname(comp_dn, eom)  	const u_char *comp_dn, *eom;  { -	register u_char *cp; +	register const u_char *cp;  	register int n; -	cp = (u_char *)comp_dn; +	cp = comp_dn;  	while (cp < eom && (n = *cp++)) {  		/*  		 * check for indirection  		 */  		switch (n & INDIR_MASK) { -		case 0:		/* normal case, n == len */ +		case 0:			/* normal case, n == len */  			cp += n;  			continue; -		default:	/* illegal type */ -			return (-1);  		case INDIR_MASK:	/* indirection */  			cp++; +			break; +		default:		/* illegal type */ +			return -1;  		}  		break;  	} +	if (cp > eom) +		return -1;  	return (cp - comp_dn);  } +static int +mklower(ch) +	register int ch; +{ +	if (isascii(ch) && isupper(ch)) +		return (tolower(ch)); +	return (ch); +} +  /*   * Search for expanded name from a list of previously compressed names.   * Return the offset from msg if found or -1. @@ -272,7 +298,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)  	for (cpp = dnptrs; cpp < lastdnptr; cpp++) {  		dn = exp_dn;  		sp = cp = *cpp; -		while (n = *cp++) { +		while ((n = *cp++)) {  			/*  			 * check for indirection  			 */ @@ -283,7 +309,7 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)  						goto next;  					if (*dn == '\\')  						dn++; -					if (*dn++ != *cp++) +					if (mklower(*dn++) != mklower(*cp++))  						goto next;  				}  				if ((n = *dn++) == '\0' && *cp == '\0') @@ -314,9 +340,9 @@ dn_find(exp_dn, msg, dnptrs, lastdnptr)   * used by sendmail.   */ -u_short +u_int16_t  _getshort(msgp) -	register u_char *msgp; +	register const u_char *msgp;  {  	register u_int16_t u; @@ -326,7 +352,7 @@ _getshort(msgp)  u_int32_t  _getlong(msgp) -	register u_char *msgp; +	register const u_char *msgp;  {  	register u_int32_t u; @@ -336,7 +362,7 @@ _getlong(msgp)  void  #if defined(__STDC__) || defined(__cplusplus) -__putshort(register u_short s, register u_char *msgp) +__putshort(register u_int16_t s, register u_char *msgp)	/* must match proto */  #else  __putshort(s, msgp)  	register u_int16_t s; diff --git a/lib/libc/net/res_debug.c b/lib/libc/net/res_debug.c index 0bd882ad2d91..a40a3895f321 100644 --- a/lib/libc/net/res_debug.c +++ b/lib/libc/net/res_debug.c @@ -53,22 +53,20 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_debug.c	8.1 (Berkeley) 6/4/93"; +static char rcsid[] = "$Id: res_debug.c,v 4.9.1.16 1994/07/11 07:41:13 vixie Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h>  #include <netinet/in.h> +#include <netiso/iso.h>  #include <arpa/inet.h>  #include <arpa/nameser.h> -#include <resolv.h> +  #include <stdio.h> +#include <resolv.h>  #include <string.h> -void __fp_query(); -char *__p_class(), *__p_time(), *__p_type(); -char *p_cdname(), *p_fqname(), *p_rr(); -static char *p_option __P((u_int32_t)); - -char *_res_opcodes[] = { +const char *_res_opcodes[] = {  	"QUERY",  	"IQUERY",  	"CQUERYM", @@ -87,7 +85,7 @@ char *_res_opcodes[] = {  	"ZONEREF",  }; -char *_res_resultcodes[] = { +const char *_res_resultcodes[] = {  	"NOERROR",  	"FORMERR",  	"SERVFAIL", @@ -108,110 +106,115 @@ char *_res_resultcodes[] = {  static char retbuf[16]; -static char * +static const char *  dewks(wks)  	int wks;  {  	switch (wks) { -	case 5: return("rje"); -	case 7: return("echo"); -	case 9: return("discard"); -	case 11: return("systat"); -	case 13: return("daytime"); -	case 15: return("netstat"); -	case 17: return("qotd"); -	case 19: return("chargen"); -	case 20: return("ftp-data"); -	case 21: return("ftp"); -	case 23: return("telnet"); -	case 25: return("smtp"); -	case 37: return("time"); -	case 39: return("rlp"); -	case 42: return("name"); -	case 43: return("whois"); -	case 53: return("domain"); -	case 57: return("apts"); -	case 59: return("apfs"); -	case 67: return("bootps"); -	case 68: return("bootpc"); -	case 69: return("tftp"); -	case 77: return("rje"); -	case 79: return("finger"); -	case 87: return("link"); -	case 95: return("supdup"); -	case 100: return("newacct"); -	case 101: return("hostnames"); -	case 102: return("iso-tsap"); -	case 103: return("x400"); -	case 104: return("x400-snd"); -	case 105: return("csnet-ns"); -	case 109: return("pop-2"); -	case 111: return("sunrpc"); -	case 113: return("auth"); -	case 115: return("sftp"); -	case 117: return("uucp-path"); -	case 119: return("nntp"); -	case 121: return("erpc"); -	case 123: return("ntp"); -	case 133: return("statsrv"); -	case 136: return("profile"); -	case 144: return("NeWS"); -	case 161: return("snmp"); -	case 162: return("snmp-trap"); -	case 170: return("print-srv"); -	default: (void) sprintf(retbuf, "%d", wks); return(retbuf); +	case 5: return "rje"; +	case 7: return "echo"; +	case 9: return "discard"; +	case 11: return "systat"; +	case 13: return "daytime"; +	case 15: return "netstat"; +	case 17: return "qotd"; +	case 19: return "chargen"; +	case 20: return "ftp-data"; +	case 21: return "ftp"; +	case 23: return "telnet"; +	case 25: return "smtp"; +	case 37: return "time"; +	case 39: return "rlp"; +	case 42: return "name"; +	case 43: return "whois"; +	case 53: return "domain"; +	case 57: return "apts"; +	case 59: return "apfs"; +	case 67: return "bootps"; +	case 68: return "bootpc"; +	case 69: return "tftp"; +	case 77: return "rje"; +	case 79: return "finger"; +	case 87: return "link"; +	case 95: return "supdup"; +	case 100: return "newacct"; +	case 101: return "hostnames"; +	case 102: return "iso-tsap"; +	case 103: return "x400"; +	case 104: return "x400-snd"; +	case 105: return "csnet-ns"; +	case 109: return "pop-2"; +	case 111: return "sunrpc"; +	case 113: return "auth"; +	case 115: return "sftp"; +	case 117: return "uucp-path"; +	case 119: return "nntp"; +	case 121: return "erpc"; +	case 123: return "ntp"; +	case 133: return "statsrv"; +	case 136: return "profile"; +	case 144: return "NeWS"; +	case 161: return "snmp"; +	case 162: return "snmp-trap"; +	case 170: return "print-srv"; +	default: (void) sprintf(retbuf, "%d", wks); return (retbuf);  	}  } -static char * +static const char *  deproto(protonum)  	int protonum;  {  	switch (protonum) { -	case 1: return("icmp"); -	case 2: return("igmp"); -	case 3: return("ggp"); -	case 5: return("st"); -	case 6: return("tcp"); -	case 7: return("ucl"); -	case 8: return("egp"); -	case 9: return("igp"); -	case 11: return("nvp-II"); -	case 12: return("pup"); -	case 16: return("chaos"); -	case 17: return("udp"); -	default: (void) sprintf(retbuf, "%d", protonum); return(retbuf); +	case 1: return "icmp"; +	case 2: return "igmp"; +	case 3: return "ggp"; +	case 5: return "st"; +	case 6: return "tcp"; +	case 7: return "ucl"; +	case 8: return "egp"; +	case 9: return "igp"; +	case 11: return "nvp-II"; +	case 12: return "pup"; +	case 16: return "chaos"; +	case 17: return "udp"; +	default: (void) sprintf(retbuf, "%d", protonum); return (retbuf);  	}  } -static char * +static const u_char *  do_rrset(msg, cp, cnt, pflag, file, hs)  	int cnt, pflag; -	char *cp,*msg, *hs; +	const u_char *cp, *msg; +	const char *hs;  	FILE *file;  {  	int n;  	int sflag; +  	/* -	 * Print  answer records +	 * Print answer records.  	 */  	sflag = (_res.pfcode & pflag); -	if (n = ntohs(cnt)) { -		if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) +	if ((n = ntohs(cnt))) { +		if ((!_res.pfcode) || +		    ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))  			fprintf(file, hs);  		while (--n >= 0) {  			cp = p_rr(cp, msg, file); -			if ((cp-msg) > PACKETSZ) +			if ((cp - msg) > PACKETSZ)  				return (NULL);  		} -		if ((!_res.pfcode) || ((sflag) && (_res.pfcode & RES_PRF_HEAD1))) +		if ((!_res.pfcode) || +		    ((sflag) && (_res.pfcode & RES_PRF_HEAD1)))  			putc('\n', file);  	} -	return(cp); +	return (cp);  } +void  __p_query(msg) -	char *msg; +	const u_char *msg;  {  	__fp_query(msg, stdout);  } @@ -225,15 +228,14 @@ __fp_resstat(statp, file)  	struct __res_state *statp;  	FILE *file;  { -	int bit; +	register u_long mask;  	fprintf(file, ";; res options:");  	if (!statp)  		statp = &_res; -	for (bit = 0;  bit < 32;  bit++) {	/* XXX 32 - bad assumption! */ -		if (statp->options & (1<<bit)) -			fprintf(file, " %s", p_option(1<<bit)); -	} +	for (mask = 1;  mask != 0;  mask <<= 1) +		if (statp->options & mask) +			fprintf(file, " %s", p_option(mask));  	putc('\n', file);  } @@ -242,21 +244,26 @@ __fp_resstat(statp, file)   * This is intended to be primarily a debugging routine.   */  void -__fp_query(msg,file) -	char *msg; +__fp_nquery(msg, len, file) +	const u_char *msg; +	int len;  	FILE *file;  { -	register char *cp; -	register HEADER *hp; +	register const u_char *cp, *endMark; +	register const HEADER *hp;  	register int n; +#define TruncTest(x) if (x >= endMark) goto trunc +#define	ErrorTest(x) if (x == NULL) goto error +  	/*  	 * Print header fields.  	 */  	hp = (HEADER *)msg; -	cp = msg + sizeof(HEADER); +	cp = msg + HFIXEDSZ; +	endMark = cp + len;  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) { -		fprintf(file,";; ->>HEADER<<- opcode: %s, status: %s, id: %d", +		fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",  			_res_opcodes[hp->opcode],  			_res_resultcodes[hp->rcode],  			ntohs(hp->id)); @@ -266,29 +273,28 @@ __fp_query(msg,file)  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {  		fprintf(file,"; flags:");  		if (hp->qr) -			fprintf(file," qr"); +			fprintf(file, " qr");  		if (hp->aa) -			fprintf(file," aa"); +			fprintf(file, " aa");  		if (hp->tc) -			fprintf(file," tc"); +			fprintf(file, " tc");  		if (hp->rd) -			fprintf(file," rd"); +			fprintf(file, " rd");  		if (hp->ra) -			fprintf(file," ra"); +			fprintf(file, " ra");  		if (hp->pr) -			fprintf(file," pr"); +			fprintf(file, " pr");  	}  	if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) { -		fprintf(file,"; Ques: %d", ntohs(hp->qdcount)); -		fprintf(file,", Ans: %d", ntohs(hp->ancount)); -		fprintf(file,", Auth: %d", ntohs(hp->nscount)); -		fprintf(file,", Addit: %d\n", ntohs(hp->arcount)); +		fprintf(file, "; Ques: %d", ntohs(hp->qdcount)); +		fprintf(file, ", Ans: %d", ntohs(hp->ancount)); +		fprintf(file, ", Auth: %d", ntohs(hp->nscount)); +		fprintf(file, ", Addit: %d", ntohs(hp->arcount));  	} -#if 0 -	if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) { +	if ((!_res.pfcode) || (_res.pfcode &  +		(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {  		putc('\n',file);  	} -#endif  	/*  	 * Print question records.  	 */ @@ -297,54 +303,71 @@ __fp_query(msg,file)  			fprintf(file,";; QUESTIONS:\n");  		while (--n >= 0) {  			fprintf(file,";;\t"); +			TruncTest(cp);  			cp = p_cdname(cp, msg, file); -			if (cp == NULL) -				return; +			ErrorTest(cp); +			TruncTest(cp);  			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))  				fprintf(file, ", type = %s", -					__p_type(_getshort(cp))); -			cp += sizeof(u_int16_t); +					__p_type(_getshort((u_char*)cp))); +			cp += INT16SZ; +			TruncTest(cp);  			if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES)) -				fprintf(file, ", class = %s\n\n", -					__p_class(_getshort(cp))); -			cp += sizeof(u_int16_t); +				fprintf(file, ", class = %s\n", +					__p_class(_getshort((u_char*)cp))); +			cp += INT16SZ; +			putc('\n', file);  		}  	}  	/*  	 * Print authoritative answer records  	 */ +	TruncTest(cp);  	cp = do_rrset(msg, cp, hp->ancount, RES_PRF_ANS, file,  		      ";; ANSWERS:\n"); -	if (cp == NULL) -		return; +	ErrorTest(cp);  	/*  	 * print name server records  	 */ +	TruncTest(cp);  	cp = do_rrset(msg, cp, hp->nscount, RES_PRF_AUTH, file,  		      ";; AUTHORITY RECORDS:\n"); -	if (!cp) -		return; +	ErrorTest(cp); +	TruncTest(cp);  	/*  	 * print additional records  	 */  	cp = do_rrset(msg, cp, hp->arcount, RES_PRF_ADD, file,  		      ";; ADDITIONAL RECORDS:\n"); -	if (!cp) -		return; +	ErrorTest(cp); +	return; + trunc: +	fprintf(file, "\n;; ...truncated\n"); +	return; + error: +	fprintf(file, "\n;; ...malformed\n");  } -char * -p_cdname(cp, msg, file) -	char *cp, *msg; +void +__fp_query(msg, file) +	const u_char *msg; +	FILE *file; +{ +	fp_nquery(msg, PACKETSZ, file); +} + +const u_char * +__p_cdnname(cp, msg, len, file) +	const u_char *cp, *msg; +	int len;  	FILE *file;  {  	char name[MAXDNAME];  	int n; -	if ((n = dn_expand((u_char *)msg, (u_char *)msg + MAXCDNAME, -	    (u_char *)cp, (u_char *)name, sizeof(name))) < 0) +	if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)  		return (NULL);  	if (name[0] == '\0')  		putc('.', file); @@ -353,16 +376,26 @@ p_cdname(cp, msg, file)  	return (cp + n);  } -char * -p_fqname(cp, msg, file) -	char *cp, *msg; +const u_char * +__p_cdname(cp, msg, file) +	const u_char *cp, *msg; +	FILE *file; +{ +	return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* XXX:	the rest of these functions need to become length-limited, too. (vix) + */ + +const u_char * +__p_fqname(cp, msg, file) +	const u_char *cp, *msg;  	FILE *file;  {  	char name[MAXDNAME];  	int n, len; -	if ((n = dn_expand((u_char *)msg, (u_char *)msg + MAXCDNAME, -	    (u_char *)cp, (u_char *)name, sizeof(name))) < 0) +	if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)  		return (NULL);  	if (name[0] == '\0') {  		putc('.', file); @@ -377,27 +410,28 @@ p_fqname(cp, msg, file)  /*   * Print resource record fields in human readable form.   */ -char * -p_rr(cp, msg, file) -	char *cp, *msg; +const u_char * +__p_rr(cp, msg, file) +	const u_char *cp, *msg;  	FILE *file;  {  	int type, class, dlen, n, c;  	struct in_addr inaddr; -	char *cp1, *cp2; +	struct iso_addr isoa; +	const u_char *cp1, *cp2;  	u_int32_t tmpttl, t;  	int lcnt;  	if ((cp = p_fqname(cp, msg, file)) == NULL)  		return (NULL);			/* compression error */ -	type = _getshort(cp); -	cp += sizeof(u_int16_t); -	class = _getshort(cp); -	cp += sizeof(u_int16_t); -	tmpttl = _getlong(cp); -	cp += sizeof(u_int32_t); -	dlen = _getshort(cp); -	cp += sizeof(u_int16_t); +	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); @@ -412,7 +446,7 @@ p_rr(cp, msg, file)  		switch (class) {  		case C_IN:  		case C_HS: -			bcopy(cp, (char *)&inaddr, sizeof(inaddr)); +			bcopy(cp, (char *)&inaddr, INADDRSZ);  			if (dlen == 4) {  				fprintf(file,"\t%s", inet_ntoa(inaddr));  				cp += dlen; @@ -422,11 +456,11 @@ p_rr(cp, msg, file)  				u_short port;  				address = inet_ntoa(inaddr); -				cp += sizeof(inaddr); +				cp += INADDRSZ;  				protocol = *(u_char*)cp;  				cp += sizeof(u_char); -				port = _getshort(cp); -				cp += sizeof(u_int16_t); +				port = _getshort((u_char*)cp); +				cp += INT16SZ;  				fprintf(file, "\t%s\t; proto %d, port %d",  					address, protocol, port);  			} @@ -446,6 +480,7 @@ p_rr(cp, msg, file)  		break;  	case T_HINFO: +	case T_ISDN:  		if (n = *cp++) {  			fprintf(file,"\t%.*s", n, cp);  			cp += n; @@ -462,25 +497,28 @@ p_rr(cp, msg, file)  		putc(' ', file);  		cp = p_fqname(cp, msg, file);	/* mail addr */  		fputs(" (\n", file); -		t = _getlong(cp);  cp += sizeof(u_int32_t); +		t = _getlong((u_char*)cp);  cp += INT32SZ;  		fprintf(file,"\t\t\t%lu\t; serial\n", t); -		t = _getlong(cp);  cp += sizeof(u_int32_t); +		t = _getlong((u_char*)cp);  cp += INT32SZ;  		fprintf(file,"\t\t\t%lu\t; refresh (%s)\n", t, __p_time(t)); -		t = _getlong(cp);  cp += sizeof(u_int32_t); +		t = _getlong((u_char*)cp);  cp += INT32SZ;  		fprintf(file,"\t\t\t%lu\t; retry (%s)\n", t, __p_time(t)); -		t = _getlong(cp);  cp += sizeof(u_int32_t); +		t = _getlong((u_char*)cp);  cp += INT32SZ;  		fprintf(file,"\t\t\t%lu\t; expire (%s)\n", t, __p_time(t)); -		t = _getlong(cp);  cp += sizeof(u_int32_t); +		t = _getlong((u_char*)cp);  cp += INT32SZ;  		fprintf(file,"\t\t\t%lu )\t; minimum (%s)", t, __p_time(t));  		break;  	case T_MX: -		fprintf(file,"\t%d ", _getshort(cp)); -		cp += sizeof(u_int16_t); +	case T_AFSDB: +	case T_RT: +		fprintf(file,"\t%d ", _getshort((u_char*)cp)); +		cp += INT16SZ;  		cp = p_fqname(cp, msg, file);  		break;    	case T_TXT: +	case T_X25:  		(void) fputs("\t\"", file);  		cp2 = cp1 + dlen;  		while (cp < cp2) { @@ -496,6 +534,15 @@ p_rr(cp, msg, file)  		putc('"', file);    		break; +  	case T_NSAP: +		isoa.isoa_len = dlen; +		if (isoa.isoa_len > sizeof(isoa.isoa_genaddr)) +			isoa.isoa_len = sizeof(isoa.isoa_genaddr); +		bcopy(cp, isoa.isoa_genaddr, isoa.isoa_len); +		(void) fprintf(file, "\t%s", iso_ntoa(&isoa)); +		cp += dlen; +  		break; +  	case T_MINFO:  	case T_RP:  		putc('\t', file); @@ -506,23 +553,23 @@ p_rr(cp, msg, file)  	case T_UINFO:  		putc('\t', file); -		fputs(cp, file); +		fputs((char *)cp, file);  		cp += dlen;  		break;  	case T_UID:  	case T_GID:  		if (dlen == 4) { -			fprintf(file,"\t%u", _getlong(cp)); -			cp += sizeof(int32_t); +			fprintf(file,"\t%u", _getlong((u_char*)cp)); +			cp += INT32SZ;  		}  		break;  	case T_WKS: -		if (dlen < sizeof(u_int32_t) + 1) +		if (dlen < INT32SZ + 1)  			break; -		bcopy(cp, (char *)&inaddr, sizeof(inaddr)); -		cp += sizeof(u_int32_t); +		bcopy(cp, (char *)&inaddr, INADDRSZ); +		cp += INT32SZ;  		fprintf(file, "\t%s %s ( ",  			inet_ntoa(inaddr),  			deproto((int) *cp)); @@ -551,7 +598,7 @@ p_rr(cp, msg, file)  	case T_UNSPEC:  		{  			int NumBytes = 8; -			char *DataPtr; +			u_char *DataPtr;  			int i;  			if (dlen < NumBytes) NumBytes = dlen; @@ -586,92 +633,66 @@ static	char nbuf[40];  /*   * Return a string for the type   */ -char * +const char *  __p_type(type)  	int type;  {  	switch (type) { -	case T_A: -		return("A"); -	case T_NS:		/* authoritative server */ -		return("NS"); -	case T_CNAME:		/* canonical name */ -		return("CNAME"); -	case T_SOA:		/* start of authority zone */ -		return("SOA"); -	case T_MB:		/* mailbox domain name */ -		return("MB"); -	case T_MG:		/* mail group member */ -		return("MG"); -	case T_MR:		/* mail rename name */ -		return("MR"); -	case T_NULL:		/* null resource record */ -		return("NULL"); -	case T_WKS:		/* well known service */ -		return("WKS"); -	case T_PTR:		/* domain name pointer */ -		return("PTR"); -	case T_HINFO:		/* host information */ -		return("HINFO"); -	case T_MINFO:		/* mailbox information */ -		return("MINFO"); -	case T_MX:		/* mail routing info */ -		return("MX"); -	case T_TXT:		/* text */ -		return("TXT"); -	case T_RP:		/* responsible person */ -		return("RP"); -	case T_AXFR:		/* zone transfer */ -		return("AXFR"); -	case T_MAILB:		/* mail box */ -		return("MAILB"); -	case T_MAILA:		/* mail address */ -		return("MAILA"); -	case T_ANY:		/* matches any type */ -		return("ANY"); -	case T_UINFO: -		return("UINFO"); -	case T_UID: -		return("UID"); -	case T_GID: -		return("GID"); +	case T_A:	return "A"; +	case T_NS:	return "NS"; +	case T_CNAME:	return "CNAME"; +	case T_SOA:	return "SOA"; +	case T_MB:	return "MB"; +	case T_MG:	return "MG"; +	case T_MR:	return "MR"; +	case T_NULL:	return "NULL"; +	case T_WKS:	return "WKS"; +	case T_PTR:	return "PTR"; +	case T_HINFO:	return "HINFO"; +	case T_MINFO:	return "MINFO"; +	case T_MX:	return "MX"; +	case T_TXT:	return "TXT"; +	case T_NSAP:	return "NSAP"; +	case T_RP:	return "RP"; +	case T_AFSDB:	return "AFSDB"; +	case T_X25:	return "X25"; +	case T_ISDN:	return "ISDN"; +	case T_RT:	return "RT"; +	case T_AXFR:	return "AXFR"; +	case T_MAILB:	return "MAILB"; +	case T_MAILA:	return "MAILA"; +	case T_ANY:	return "ANY"; +	case T_UINFO:	return "UINFO"; +	case T_UID:	return "UID"; +	case T_GID:	return "GID";  #ifdef ALLOW_T_UNSPEC -	case T_UNSPEC: -		return("UNSPEC"); +	case T_UNSPEC:	return "UNSPEC";  #endif /* ALLOW_T_UNSPEC */ -	default: -		(void)sprintf(nbuf, "%d", type); -		return(nbuf); +	default:	(void)sprintf(nbuf, "%d", type); return (nbuf);  	}  }  /*   * Return a mnemonic for class   */ -char * +const char *  __p_class(class)  	int class;  { -  	switch (class) { -	case C_IN:		/* internet class */ -		return("IN"); -	case C_HS:		/* hesiod class */ -		return("HS"); -	case C_ANY:		/* matches any class */ -		return("ANY"); -	default: -		(void)sprintf(nbuf, "%d", class); -		return(nbuf); +	case C_IN:	return("IN"); +	case C_HS:	return("HS"); +	case C_ANY:	return("ANY"); +	default:	(void)sprintf(nbuf, "%d", class); return (nbuf);  	}  }  /*   * Return a mnemonic for an option   */ -static char * -p_option(option) -	u_int32_t option; +const char * +__p_option(option) +	u_long option;  {  	switch (option) {  	case RES_INIT:		return "init"; @@ -684,6 +705,8 @@ p_option(option)  	case RES_DEFNAMES:	return "defnam";  	case RES_STAYOPEN:	return "styopn";  	case RES_DNSRCH:	return "dnsrch"; +	case RES_INSECURE1:	return "insecure1"; +	case RES_INSECURE2:	return "insecure2";  	default:		sprintf(nbuf, "?0x%x?", option); return nbuf;  	}  } @@ -700,7 +723,7 @@ __p_time(value)  	if (value == 0) {  		strcpy(nbuf, "0 secs"); -		return(nbuf); +		return (nbuf);  	}  	secs = value % 60; @@ -735,5 +758,5 @@ __p_time(value)  			*p++ = ' ';  		(void)sprintf(p, "%d sec%s", PLURALIZE(secs));  	} -	return(nbuf); +	return (nbuf);  } diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index 1e0fd05f68ea..e32f8d33f72e 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -53,7 +53,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_init.c	8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; +static char rcsid[] = "$Id: res_init.c,v 4.9.1.12 1994/06/11 22:05:04 vixie Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h> @@ -61,30 +61,44 @@ static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $  #include <netinet/in.h>  #include <arpa/inet.h>  #include <arpa/nameser.h> + +#include <stdio.h> +#include <ctype.h>  #include <resolv.h>  #include <unistd.h> -#include <stdio.h>  #include <stdlib.h>  #include <string.h> +static void res_setoptions __P((char *, char *)); + +#ifdef RESOLVSORT +static u_int32_t net_mask __P((struct in_addr)); +#endif +  /* - * Resolver state default settings + * Resolver state default settings.   */ -struct __res_state _res = { -	RES_TIMEOUT,               	/* retransmition time interval */ -	4,                         	/* number of times to retransmit */ -	RES_DEFAULT,			/* options flags */ -	1,                         	/* number of name servers */ -}; +struct __res_state _res;  /*   * Set up default settings.  If the configuration file exist, the values   * there will have precedence.  Otherwise, the server address is set to   * INADDR_ANY and the default domain name comes from the gethostname().   * - * The configuration file should only be used if you want to redefine your - * domain or run without a server on your machine. + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * since it was noted that INADDR_ANY actually meant ``the first interface + * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, + * it had to be "up" in order for you to reach your own name server.  It + * was later decided that since the recommended practice is to always  + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain.  If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file.   *   * Return 0 if completes successfully, -1 on error   */ @@ -92,11 +106,35 @@ res_init()  {  	register FILE *fp;  	register char *cp, **pp; -	register int n; +	register int n, dots;  	char buf[BUFSIZ];  	int nserv = 0;    /* number of nameserver records read from file */  	int haveenv = 0;  	int havesearch = 0; +#ifdef RESOLVSORT +	int nsort = 0; +	char *net; +#endif + +	/* +	 * These four fields used to be statically initialized.  This made +	 * it hard to use this code in a shared library.  It is necessary, +	 * now that we're doing dynamic initialization here, that we preserve +	 * the old semantics: if an application modifies one of these three +	 * fields of _res before res_init() is called, res_init() will not +	 * alter them.  Of course, if an application is setting them to +	 * _zero_ before calling res_init(), hoping to override what used +	 * to be the static default, we can't detect it and unexpected results +	 * will follow.  Zero for any of these fields would make no sense, +	 * so one can safely assume that the applications were already getting +	 * unexpected results. +	 */ +	if (!_res.retrans) +		_res.retrans = RES_TIMEOUT; +	if (!_res.retry) +		_res.retry = 4; +	if (!_res.options) +		_res.options = RES_DEFAULT;  #ifdef USELOOPBACK  	_res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); @@ -106,14 +144,41 @@ res_init()  	_res.nsaddr.sin_family = AF_INET;  	_res.nsaddr.sin_port = htons(NAMESERVER_PORT);  	_res.nscount = 1; +	_res.ndots = 1;  	_res.pfcode = 0;  	/* Allow user to override the local domain definition */  	if ((cp = getenv("LOCALDOMAIN")) != NULL) { -		(void)strncpy(_res.defdname, cp, sizeof(_res.defdname)); -		if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) -			*cp = '\0'; +		(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);  		haveenv++; + +		/* +		 * Set search list to be blank-separated strings +		 * from rest of env value.  Permits users of LOCALDOMAIN +		 * to still have a search list, and anyone to set the +		 * one that they want to use as an individual (even more +		 * important now that the rfc1535 stuff restricts searches) +		 */ +		cp = _res.defdname; +		pp = _res.dnsrch; +		*pp++ = cp; +		for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { +			if (*cp == '\n')	/* silly backwards compat */ +				break; +			else if (*cp == ' ' || *cp == '\t') { +				*cp = 0; +				n = 1; +			} else if (n) { +				*pp++ = cp; +				n = 0; +				havesearch = 1; +			} +		} +		/* null terminate last domain if there are excess */ +		while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') +			cp++; +		*cp = '\0'; +		*pp++ = 0;  	}  	if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { @@ -158,7 +223,9 @@ res_init()  		    cp = _res.defdname;  		    pp = _res.dnsrch;  		    *pp++ = cp; -		    for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { +		    for (n = 0; +			 *cp && pp < _res.dnsrch + MAXDNSRCH; +			 cp++) {  			    if (*cp == ' ' || *cp == '\t') {  				    *cp = 0;  				    n = 1; @@ -192,32 +259,167 @@ res_init()  		    }  		    continue;  		} +#ifdef RESOLVSORT +		if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) { +		    struct in_addr a; + +		    cp = buf + sizeof("sortlist") - 1; +		    while (nsort < MAXRESOLVSORT) { +			while (*cp == ' ' || *cp == '\t') +			    cp++; +			if (*cp == '\0' || *cp == '\n' || *cp == ';') +			    break; +			net = cp; +			while (*cp && *cp != '/' && +			    isascii(*cp) && !isspace(*cp)) +				cp++; +			n = *cp; +			*cp = 0; +			if (inet_aton(net, &a)) { +			    _res.sort_list[nsort].addr = a; +			    if (n == '/') { +				*cp++ = n; +				net = cp; +				while (*cp && isascii(*cp) && !isspace(*cp)) +				    cp++; +				n = *cp; +				*cp = 0; +				if (inet_aton(net, &a)) { +				    _res.sort_list[nsort].mask = a.s_addr; +				} else { +				    _res.sort_list[nsort].mask =  +					net_mask(_res.sort_list[nsort].addr); +				} +			    } else { +				_res.sort_list[nsort].mask =  +				    net_mask(_res.sort_list[nsort].addr); +			    } +			    nsort++; +			} +			*cp++ = n; +		    } +		    continue; +		} +#endif +		if (!strncmp(buf, "options", sizeof("options") -1)) { +		    res_setoptions(buf + sizeof("options") - 1, "conf"); +		    continue; +		}  	    }  	    if (nserv > 1)   		_res.nscount = nserv; +#ifdef RESOLVSORT +	    _res.nsort = nsort; +#endif  	    (void) fclose(fp); -	} +	} /*if(fopen)*/  	if (_res.defdname[0] == 0) { -		if (gethostname(buf, sizeof(_res.defdname)) == 0 && -		   (cp = strchr(buf, '.'))) +		if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && +		   (cp = strchr(buf, '.'))) {  			(void)strcpy(_res.defdname, cp + 1); +		}  	}  	/* find components of local domain that might be searched */  	if (havesearch == 0) {  		pp = _res.dnsrch;  		*pp++ = _res.defdname; -		for (cp = _res.defdname, n = 0; *cp; cp++) -			if (*cp == '.') -				n++; +		*pp = NULL; + +#ifndef RFC1535 +		dots = 0; +		for (cp = _res.defdname;  *cp;  cp++) +			dots += (*cp == '.'); +  		cp = _res.defdname; -		for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; -		    n--) { -			cp = strchr(cp, '.'); -			*pp++ = ++cp; +		while (pp < _res.dnsrch + MAXDFLSRCH) { +			if (dots < LOCALDOMAINPARTS) { +				break; +			} +			cp = strchr(cp, '.') + 1;    /* we know there is one */ +			*pp++ = cp; +			dots--;  		} -		*pp++ = 0; +		*pp = NULL; +#ifdef DEBUG +		if (_res.options & RES_DEBUG) { +			printf(";; res_init()... default dnsrch list:\n"); +			for (pp = _res.dnsrch;  *pp;  pp++) { +				printf(";;\t%s\n", *pp); +			} +			printf(";;\t..END..\n"); +		} +#endif /*DEBUG*/ +#endif /*!RFC1535*/ +	} + +	if ((cp = getenv("RES_OPTIONS")) != NULL) { +		res_setoptions(cp, "env");  	}  	_res.options |= RES_INIT;  	return (0);  } + + +static void +res_setoptions(options, source) +	char *options, *source; +{ +	char *cp = options; +	int i; + +#ifdef DEBUG +	if (_res.options & RES_DEBUG) { +		printf(";; res_setoptions(\"%s\", \"%s\")...\n", +		       options, source); +	} +#endif +	while (*cp) { +		/* skip leading and inner runs of spaces */ +		while (*cp == ' ' || *cp == '\t') +			cp++; +		/* search for and process individual options */ +		if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { +			i = atoi(cp + sizeof("ndots:") - 1); +			if (i <= RES_MAXNDOTS) +				_res.ndots = i; +			else +				_res.ndots = RES_MAXNDOTS; +#ifdef DEBUG +			if (_res.options & RES_DEBUG) { +				printf(";;\tndots=%d\n", _res.ndots); +			} +#endif +		} else if (!strncmp(cp, "debug", sizeof("debug")-1)) { +#ifdef DEBUG +			if (!(_res.options & RES_DEBUG)) { +				printf(";; res_setoptions(\"%s\", \"%s\")..\n", +				       options, source); +				_res.options |= RES_DEBUG; +			} +			printf(";;\tdebug\n"); +#endif +		} else { +			/* XXX - print a warning here? */ +		} +		/* skip to next run of spaces */ +		while (*cp && *cp != ' ' && *cp != '\t') +			cp++; +	} +} + +#ifdef RESOLVSORT +static u_int32_t +net_mask(in)		/* XXX - should really use system's version of this */ +	struct in_addr in; +{ +        register u_int32_t i = ntohl(in.s_addr); + +        if (IN_CLASSA(i)) +                return (htonl(IN_CLASSA_NET)); +        else if (IN_CLASSB(i)) +                return (htonl(IN_CLASSB_NET)); +        else +                return (htonl(IN_CLASSC_NET)); +} +#endif diff --git a/lib/libc/net/res_mkquery.c b/lib/libc/net/res_mkquery.c index a284562837f9..f89b1c98a195 100644 --- a/lib/libc/net/res_mkquery.c +++ b/lib/libc/net/res_mkquery.c @@ -53,35 +53,37 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_mkquery.c	8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.2 1993/05/17 10:00:01 vixie Exp $"; +static char rcsid[] = "$Id: res_mkquery.c,v 4.9.1.7 1994/06/01 21:09:58 vixie Exp $";  #endif /* LIBC_SCCS and not lint */  #include <sys/param.h>  #include <netinet/in.h>  #include <arpa/nameser.h> -#include <resolv.h> +  #include <stdio.h> +#include <resolv.h>  #include <string.h>  /*   * Form all types of queries.   * Returns the size of the result or -1.   */ +int  res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  	int op;			/* opcode of query */ -	const char *dname;		/* domain name */ +	const char *dname;	/* domain name */  	int class, type;	/* class and type of query */ -	const char *data;		/* resource record data */ +	const u_char *data;	/* resource record data */  	int datalen;		/* length of data */ -	const char *newrr_in;	/* new rr for modify or append */ -	char *buf;		/* buffer to put query */ +	const u_char *newrr_in;	/* new rr for modify or append */ +	u_char *buf;		/* buffer to put query */  	int buflen;		/* size of buffer */  {  	register HEADER *hp; -	register char *cp; +	register u_char *cp;  	register int n;  	struct rrec *newrr = (struct rrec *) newrr_in; -	char *dnptrs[10], **dpp, **lastdnptr; +	u_char *dnptrs[20], **dpp, **lastdnptr;  #ifdef DEBUG  	if (_res.options & RES_DEBUG) @@ -91,21 +93,21 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  	/*  	 * Initialize header fields.  	 */ -	if ((buf == NULL) || (buflen < sizeof(HEADER))) +	if ((buf == NULL) || (buflen < HFIXEDSZ))  		return(-1); -	bzero(buf, sizeof(HEADER)); +	bzero(buf, HFIXEDSZ);  	hp = (HEADER *) buf;  	hp->id = htons(++_res.id);  	hp->opcode = op;  	hp->pr = (_res.options & RES_PRIMARY) != 0;  	hp->rd = (_res.options & RES_RECURSE) != 0;  	hp->rcode = NOERROR; -	cp = buf + sizeof(HEADER); -	buflen -= sizeof(HEADER); +	cp = buf + HFIXEDSZ; +	buflen -= HFIXEDSZ;  	dpp = dnptrs;  	*dpp++ = buf;  	*dpp++ = NULL; -	lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); +	lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];  	/*  	 * perform opcode specific processing  	 */ @@ -113,15 +115,14 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  	case QUERY:  		if ((buflen -= QFIXEDSZ) < 0)  			return(-1); -		if ((n = dn_comp((u_char *)dname, (u_char *)cp, buflen, -		    (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) +		if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)  			return (-1);  		cp += n;  		buflen -= n; -		__putshort(type, (u_char *)cp); -		cp += sizeof(u_int16_t); -		__putshort(class, (u_char *)cp); -		cp += sizeof(u_int16_t); +		__putshort(type, cp); +		cp += INT16SZ; +		__putshort(class, cp); +		cp += INT16SZ;  		hp->qdcount = htons(1);  		if (op == QUERY || data == NULL)  			break; @@ -129,19 +130,19 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  		 * Make an additional record for completion domain.  		 */  		buflen -= RRFIXEDSZ; -		if ((n = dn_comp((u_char *)data, (u_char *)cp, buflen, -		    (u_char **)dnptrs, (u_char **)lastdnptr)) < 0) +		n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr); +		if (n < 0)  			return (-1);  		cp += n;  		buflen -= n; -		__putshort(T_NULL, (u_char *)cp); -		cp += sizeof(u_int16_t); -		__putshort(class, (u_char *)cp); -		cp += sizeof(u_int16_t); -		__putlong(0, (u_char *)cp); -		cp += sizeof(u_int32_t); -		__putshort(0, (u_char *)cp); -		cp += sizeof(u_int16_t); +		__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; @@ -152,14 +153,14 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  		if (buflen < 1 + RRFIXEDSZ + datalen)  			return (-1);  		*cp++ = '\0';	/* no domain name */ -		__putshort(type, (u_char *)cp); -		cp += sizeof(u_int16_t); -		__putshort(class, (u_char *)cp); -		cp += sizeof(u_int16_t); -		__putlong(0, (u_char *)cp); -		cp += sizeof(u_int32_t); -		__putshort(datalen, (u_char *)cp); -		cp += sizeof(u_int16_t); +		__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; @@ -187,13 +188,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  			return (-1);  		cp += n;  		__putshort(type, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;                  __putshort(class, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;  		__putlong(0, cp); -		cp += sizeof(u_int32_t); +		cp += INT32SZ;  		__putshort(datalen, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;  		if (datalen) {  			bcopy(data, cp, datalen);  			cp += datalen; @@ -210,13 +211,13 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)  			return (-1);  		cp += n;  		__putshort(newrr->r_type, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;                  __putshort(newrr->r_class, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;  		__putlong(0, cp); -		cp += sizeof(u_int32_t); +		cp += INT32SZ;  		__putshort(newrr->r_size, cp); -                cp += sizeof(u_int16_t); +                cp += INT16SZ;  		if (newrr->r_size) {  			bcopy(newrr->r_data, cp, newrr->r_size);  			cp += newrr->r_size; diff --git a/lib/libc/net/res_query.c b/lib/libc/net/res_query.c index 4980af17b9d8..17318b76c765 100644 --- a/lib/libc/net/res_query.c +++ b/lib/libc/net/res_query.c @@ -53,20 +53,29 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_query.c	8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixie $"; +static char rcsid[] = "$Id: res_query.c,v 4.9.1.13 1994/06/11 22:05:04 vixie Exp $";  #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 <stdio.h>  #include <ctype.h>  #include <errno.h> -#include <stdlib.h> -#include <string.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 @@ -74,6 +83,7 @@ static char rcsid[] = "$Id: res_query.c,v 1.1 1993/06/01 09:42:14 vixie Exp vixi  #define MAXPACKET	1024  #endif +char *__hostalias __P((const char *));  int h_errno;  /* @@ -83,27 +93,31 @@ int h_errno;   * if no error is indicated and the answer count is nonzero.   * Return the size of the response on success, -1 on error.   * Error number is left in h_errno. + *   * Caller must parse answer and determine whether it answers the question.   */ +int  res_query(name, class, type, answer, anslen) -	char *name;		/* domain name */ +	const char *name;	/* domain name */  	int class, type;	/* class and type of query */  	u_char *answer;		/* buffer to put answer */  	int anslen;		/* size of answer buffer */  { -	char buf[MAXPACKET]; -	HEADER *hp; +	u_char buf[MAXPACKET]; +	register HEADER *hp = (HEADER *) answer;  	int n; +	hp->rcode = NOERROR;	/* default */ +  	if ((_res.options & RES_INIT) == 0 && res_init() == -1)  		return (-1);  #ifdef DEBUG  	if (_res.options & RES_DEBUG)  		printf(";; res_query(%s, %d, %d)\n", name, class, type);  #endif -	n = res_mkquery(QUERY, name, class, type, (char *)NULL, 0, NULL, -	    buf, sizeof(buf)); +	n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL, +			buf, sizeof(buf));  	if (n <= 0) {  #ifdef DEBUG  		if (_res.options & RES_DEBUG) @@ -112,17 +126,16 @@ res_query(name, class, type, answer, anslen)  		h_errno = NO_RECOVERY;  		return (n);  	} -	n = res_send(buf, n, (char *)answer, anslen); +	n = res_send(buf, n, answer, anslen);  	if (n < 0) {  #ifdef DEBUG  		if (_res.options & RES_DEBUG)  			printf(";; res_query: send error\n");  #endif  		h_errno = TRY_AGAIN; -		return(n); +		return (n);  	} -	hp = (HEADER *) answer;  	if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {  #ifdef DEBUG  		if (_res.options & RES_DEBUG) @@ -148,86 +161,148 @@ res_query(name, class, type, answer, anslen)  		}  		return (-1);  	} -	return(n); +	return (n);  }  /*   * Formulate a normal query, send, and retrieve answer in supplied buffer.   * Return the size of the response on success, -1 on error.   * If enabled, implement search rules until answer or unrecoverable failure - * is detected.  Error number is left in h_errno. - * Only useful for queries in the same name hierarchy as the local host - * (not, for example, for host address-to-name lookups in domain in-addr.arpa). + * is detected.  Error code, if any, is left in h_errno.   */  int  res_search(name, class, type, answer, anslen) -	char *name;		/* domain name */ +	const char *name;	/* domain name */  	int class, type;	/* class and type of query */  	u_char *answer;		/* buffer to put answer */  	int anslen;		/* size of answer */  { -	register char *cp, **domain; -	int n, ret, got_nodata = 0; -	char *__hostalias(); +	register const char *cp, * const *domain; +	HEADER *hp = (HEADER *) answer; +	u_int dots; +	int trailing_dot, ret, saved_herrno; +	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;  	if ((_res.options & RES_INIT) == 0 && res_init() == -1)  		return (-1);  	errno = 0;  	h_errno = HOST_NOT_FOUND;	/* default, if we never query */ -	for (cp = name, n = 0; *cp; cp++) -		if (*cp == '.') -			n++; -	if (n == 0 && (cp = __hostalias(name))) +	dots = 0; +	for (cp = name;  *cp;  cp++) +		dots += (*cp == '.'); +	trailing_dot = 0; +	if ((cp > name) && (*--cp == '.')) +		trailing_dot++; + +	/* +	 * if there aren't any dots, it could be a user-level alias +	 */ +	if ((!dots) && (cp = __hostalias(name)))  		return (res_query(cp, class, type, answer, anslen));  	/* +	 * If there are dots in the name already, let's just give it a try +	 * 'as is'.  The threshold can be set with the "ndots" option. +	 */ +	saved_herrno = -1; +	if (dots >= _res.ndots) { +		ret = res_querydomain(name, NULL, class, type, answer, anslen); +		if (ret > 0) +			return (ret); +		saved_herrno = h_errno; +		tried_as_is++; +	} + +	/*  	 * We do at least one level of search if  	 *	- there is no dot and RES_DEFNAME is set, or  	 *	- there is at least one dot, there is no trailing dot,  	 *	  and RES_DNSRCH is set.  	 */ -	if ((n == 0 && _res.options & RES_DEFNAMES) || -	   (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) -	     for (domain = _res.dnsrch; *domain; domain++) { -		ret = res_querydomain(name, *domain, class, type, -		    answer, anslen); +	if (((!dots) && _res.options & RES_DEFNAMES) || +	    (dots && (!trailing_dot) && _res.options & RES_DNSRCH) +	    ) { +		int done = 0; + +		for (domain = (const char * const *)_res.dnsrch; +		     *domain && !done; +		     domain++) { + +			ret = res_querydomain(name, *domain, class, type, +					      answer, anslen); +			if (ret > 0) +				return (ret); + +			/* +			 * If no server present, give up. +			 * If name isn't found in this domain, +			 * keep trying higher domains in the search list +			 * (if that's enabled). +			 * On a NO_DATA error, keep trying, otherwise +			 * a wildcard entry of another type could keep us +			 * from finding this entry higher in the domain. +			 * If we get some other error (negative answer or +			 * server failure), then stop searching up, +			 * but try the input name below in case it's +			 * fully-qualified. +			 */ +			if (errno == ECONNREFUSED) { +				h_errno = TRY_AGAIN; +				return (-1); +			} + +			switch (h_errno) { +			case NO_DATA: +				got_nodata++; +				/* FALLTHROUGH */ +			case HOST_NOT_FOUND: +				/* keep trying */ +				break; +			case TRY_AGAIN: +				if (hp->rcode == SERVFAIL) { +					/* try next search element, if any */ +					got_servfail++; +					break; +				} +				/* FALLTHROUGH */ +			default: +				/* anything else implies that we're done */ +				done++; +			} + +			/* if we got here for some reason other than DNSRCH, +			 * we only wanted one iteration of the loop, so stop. +			 */ +			if (!(_res.options & RES_DNSRCH)) +				done++; +		} +	} + +	/* if we have not already tried the name "as is", do that now. +	 * note that we do this regardless of how many dots were in the +	 * name or whether it ends with a dot. +	 */ +	if (!tried_as_is) { +		ret = res_querydomain(name, NULL, class, type, answer, anslen);  		if (ret > 0)  			return (ret); -		/* -		 * If no server present, give up. -		 * If name isn't found in this domain, -		 * keep trying higher domains in the search list -		 * (if that's enabled). -		 * On a NO_DATA error, keep trying, otherwise -		 * a wildcard entry of another type could keep us -		 * from finding this entry higher in the domain. -		 * If we get some other error (negative answer or -		 * server failure), then stop searching up, -		 * but try the input name below in case it's fully-qualified. -		 */ -		if (errno == ECONNREFUSED) { -			h_errno = TRY_AGAIN; -			return (-1); -		} -		if (h_errno == NO_DATA) -			got_nodata++; -		if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) || -		    (_res.options & RES_DNSRCH) == 0) -			break; +		saved_herrno = h_errno;  	} -	/* -	 * If the search/default failed, try the name as fully-qualified, -	 * but only if it contained at least one dot (even trailing). -	 * This is purely a heuristic; we assume that any reasonable query -	 * about a top-level domain (for servers, SOA, etc) will not use -	 * res_search. + +	/* if we got here, we didn't satisfy the search. +	 * if we did an initial full query, return that query's h_errno +	 * (note that we wouldn't be here if that query had succeeded). +	 * else if we ever got a nodata, send that back as the reason. +	 * else send back meaningless h_errno, that being the one from +	 * the last DNSRCH we did.  	 */ -	if (n && (ret = res_querydomain(name, (char *)NULL, class, type, -	    answer, anslen)) > 0) -		return (ret); -	if (got_nodata) +	if (saved_herrno != -1) +		h_errno = saved_herrno; +	else if (got_nodata)  		h_errno = NO_DATA; +	else if (got_servfail) +		h_errno = TRY_AGAIN;  	return (-1);  } @@ -235,20 +310,21 @@ res_search(name, class, type, answer, anslen)   * Perform a call on res_query on the concatenation of name and domain,   * removing a trailing dot from name if domain is NULL.   */ +int  res_querydomain(name, domain, class, type, answer, anslen) -	char *name, *domain; +	const char *name, *domain;  	int class, type;	/* class and type of query */  	u_char *answer;		/* buffer to put answer */  	int anslen;		/* size of answer */  {  	char nbuf[2*MAXDNAME+2]; -	char *longname = nbuf; +	const char *longname = nbuf;  	int n;  #ifdef DEBUG  	if (_res.options & RES_DEBUG)  		printf(";; res_querydomain(%s, %s, %d, %d)\n", -		    name, domain, class, type); +		       name, domain?domain:"<Nil>", class, type);  #endif  	if (domain == NULL) {  		/* @@ -256,14 +332,15 @@ res_querydomain(name, domain, class, type, answer, anslen)  		 * copy without '.' if present.  		 */  		n = strlen(name) - 1; -		if (name[n] == '.' && n < sizeof(nbuf) - 1) { +		if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {  			bcopy(name, nbuf, n);  			nbuf[n] = '\0';  		} else  			longname = name; -	} else -		(void)sprintf(nbuf, "%.*s.%.*s", -		    MAXDNAME, name, MAXDNAME, domain); +	} else { +		sprintf(nbuf, "%.*s.%.*s", +			MAXDNAME, name, MAXDNAME, domain); +	}  	return (res_query(longname, class, type, answer, anslen));  } @@ -272,9 +349,9 @@ char *  __hostalias(name)  	register const char *name;  { -	register char *C1, *C2; +	register char *cp1, *cp2;  	FILE *fp; -	char *file, *getenv(), *strcpy(), *strncpy(); +	char *file;  	char buf[BUFSIZ];  	static char abuf[MAXDNAME]; @@ -283,17 +360,17 @@ __hostalias(name)  		return (NULL);  	buf[sizeof(buf) - 1] = '\0';  	while (fgets(buf, sizeof(buf), fp)) { -		for (C1 = buf; *C1 && !isspace(*C1); ++C1); -		if (!*C1) +		for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1); +		if (!*cp1)  			break; -		*C1 = '\0'; +		*cp1 = '\0';  		if (!strcasecmp(buf, name)) { -			while (isspace(*++C1)); -			if (!*C1) +			while (isspace(*++cp1)); +			if (!*cp1)  				break; -			for (C2 = C1 + 1; *C2 && !isspace(*C2); ++C2); -			abuf[sizeof(abuf) - 1] = *C2 = '\0'; -			(void)strncpy(abuf, C1, sizeof(abuf) - 1); +			for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2); +			abuf[sizeof(abuf) - 1] = *cp2 = '\0'; +			(void)strncpy(abuf, cp1, sizeof(abuf) - 1);  			fclose(fp);  			return (abuf);  		} diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index 5c80cf4d6869..8abcd0a84c9d 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -53,9 +53,16 @@  #if defined(LIBC_SCCS) && !defined(lint)  static char sccsid[] = "@(#)res_send.c	8.1 (Berkeley) 6/4/93"; -static char rcsid[] = "$Id: res_send.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; +static char rcsid[] = "$Id: res_send.c,v 4.9.1.12 1994/06/26 04:00:18 vixie Exp $";  #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.   */ @@ -67,139 +74,323 @@ static char rcsid[] = "$Id: res_send.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $  #include <netinet/in.h>  #include <arpa/nameser.h>  #include <arpa/inet.h> +  #include <stdio.h>  #include <errno.h>  #include <resolv.h> -#include <unistd.h> +#include <stdlib.h>  #include <string.h> +void _res_close __P((void)); +  static int s = -1;	/* socket used for communications */ -static struct sockaddr no_addr; - -#ifndef FD_SET -#define	NFDBITS		32 -#define	FD_SETSIZE	32 -#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) -#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) -#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) -#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p))) -#endif +static int connected = 0;	/* is the socket connected */ +static int vc = 0;	/* is the socket a virtual ciruit? */ -res_send(buf, buflen, answer, anslen) -	const char *buf; -	int buflen; -	char *answer; -	int anslen; -{ -	register int n; -	int try, v_circuit, resplen, ns; -	int gotsomewhere = 0, connected = 0; -	int connreset = 0; -	u_short id, len; -	char *cp; -	fd_set dsmask; -	struct timeval timeout; -	HEADER *hp = (HEADER *) buf; -	HEADER *anhp = (HEADER *) answer; -	u_int badns;		/* XXX NSMAX can't exceed #/bits per this */ -	struct iovec iov[2]; -	int terrno = ETIMEDOUT; -	char junk[512]; - -#ifdef DEBUG -	if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) { -		printf(";; res_send()\n"); -		__p_query(buf); +#ifndef DEBUG +#   define Dprint(cond, args) /*empty*/ +#   define DprintQ(cond, args, query) /*empty*/ +#   define Aerror(file, string, error, address) /*empty*/ +#   define Perror(file, string, error) /*empty*/ +#else +#   define Dprint(cond, args) if (cond) {fprintf args;} else {} +#   define DprintQ(cond, args, query) if (cond) {\ +			fprintf args;\ +			__p_query(query);\ +		} else {} +    static void +    Aerror(file, string, error, address) +	FILE *file; +	char *string; +	int error; +	struct sockaddr_in address; +    { +	int save = errno; + +	if (_res.options & RES_DEBUG) { +		fprintf(file, "res_send: %s ([%s].%d): %s\n", +			string, +			inet_ntoa(address.sin_addr), +			address.sin_port, +			strerror(error));  	} +	errno = save; +    } +    static void +    Perror(file, string, error) +	FILE *file; +	char *string; +	int error; +    { +	int save = errno; + +	if (_res.options & RES_DEBUG) { +		fprintf(file, "res_send: %s: %s\n", +			string, strerror(error)); +	} +	errno = save; +    }  #endif -	if (!(_res.options & RES_INIT)) -		if (res_init() == -1) { -			return(-1); + +static res_send_qhook Qhook = NULL; +static res_send_rhook Rhook = NULL; + +void +res_send_setqhook(hook) +	res_send_qhook hook; +{ +	Qhook = hook; +} + +void +res_send_setrhook(hook) +	res_send_rhook hook; +{ +	Rhook = hook; +} + +/* int + * our_server(ina) + *	looks up "ina" in _res.ns_addr_list[] + * returns: + *	0  : not found + *	>0 : found + * author: + *	paul vixie, 29may94 + */ +static int +our_server(inp) +	const struct sockaddr_in *inp; +{ +	struct sockaddr_in ina; +	register int ns, ret; + +	ina = *inp; +	ret = 0; +	for (ns = 0;  ns < _res.nscount;  ns++) { +		register const struct sockaddr_in *srv = &_res.nsaddr_list[ns]; + +		if (srv->sin_family == ina.sin_family && +		    srv->sin_port == ina.sin_port && +		    (srv->sin_addr.s_addr == INADDR_ANY || +		     srv->sin_addr.s_addr == ina.sin_addr.s_addr)) { +			ret++; +			break;  		} +	} +	return (ret); +} + +/* int + * name_in_query(name, type, class, buf, eom) + *	look for (name,type,class) in the query section of packet (buf,eom) + * returns: + *	-1 : format error + *	0  : not found + *	>0 : found + */ +static int +name_in_query(name, type, class, buf, eom) +	const char *name; +	register int type, class; +	const u_char *buf, *eom; +{ +	register const u_char *cp = buf + HFIXEDSZ; +	int qdcount = ntohs(((HEADER*)buf)->qdcount); + +	while (qdcount-- > 0) { +		char tname[MAXDNAME+1]; +		register int n, ttype, tclass; + +		n = dn_expand(buf, eom, cp, tname, sizeof tname); +		if (n < 0) +			return (-1); +		cp += n; +		ttype = _getshort(cp);	cp += INT16SZ; +		tclass = _getshort(cp); cp += INT16SZ; +		if (ttype == type && +		    tclass == class && +		    strcasecmp(tname, name) == 0) +			return (1); +	} +	return (0); +} + +/* int + * queries_match(buf1, eom1, buf2, eom2) + *	is there a 1:1 mapping of (name,type,class) + *	in (buf1,eom1) and (buf2,eom2)? + * returns: + *	-1 : format error + *	0  : not a 1:1 mapping + *	>0 : is a 1:1 mapping + */ +static int +queries_match(buf1, eom1, buf2, eom2) +	const u_char *buf1, *eom1; +	const u_char *buf2, *eom2; +{ +	register const u_char *cp = buf1 + HFIXEDSZ; +	int qdcount = ntohs(((HEADER*)buf1)->qdcount); + +	if (qdcount != ntohs(((HEADER*)buf2)->qdcount)) +		return (0); +	while (qdcount-- > 0) { +		char tname[MAXDNAME+1]; +		register int n, ttype, tclass; + +		n = dn_expand(buf1, eom1, cp, tname, sizeof tname); +		if (n < 0) +			return (-1); +		cp += n; +		ttype = _getshort(cp);	cp += INT16SZ; +		tclass = _getshort(cp); cp += INT16SZ; +		if (!name_in_query(tname, ttype, tclass, buf2, eom2)) +			return (0); +	} +	return (1); +} + +int +res_send(buf, buflen, ans, anssiz) +	const u_char	*buf; +	int		buflen; +	u_char		*ans; +	int		anssiz; +{ +	HEADER		*hp = (HEADER *) buf; +	HEADER		*anhp = (HEADER *) ans; +	int		gotsomewhere = 0, +			connreset = 0, +			terrno = ETIMEDOUT; + +	register int	n; +	int		try, v_circuit, resplen, ns; +	u_int		badns;	/* XXX NSMAX can't exceed #/bits in this var */ + +	DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), +		(stdout, ";; res_send()\n"), buf); +	if (!(_res.options & RES_INIT)) { +		if (res_init() == -1) +			return (-1); +	}  	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; -	id = hp->id;  	badns = 0; +  	/*  	 * Send request, RETRY times, or until successful  	 */  	for (try = 0; try < _res.retry; try++) {  	    for (ns = 0; ns < _res.nscount; ns++) { -		if (badns & (1<<ns)) -			continue; -#ifdef DEBUG -		if (_res.options & RES_DEBUG) -			printf(";; Querying server (# %d) address = %s\n", -			       ns+1, -			       inet_ntoa(_res.nsaddr_list[ns].sin_addr)); -#endif -	usevc: +		struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; +    same_ns: +		if (badns & (1<<ns)) { +			_res_close(); +			goto next_ns; +		} + +		if (Qhook) { +			int done = 0, loops = 0; + +			do { +				res_sendhookact act; + +				act = (*Qhook)(&nsap, +					       &buf, +					       &buflen, +					       ans, +					       anssiz, +					       &resplen); +				switch (act) { +				case res_goahead: +					done = 1; +					break; +				case res_nextns: +					_res_close(); +					goto next_ns; +				case res_done: +					return (resplen); +				case res_modified: +					/* give the hook another try */ +					if (++loops < 42) /*doug adams*/ +						break; +					/*FALLTHROUGH*/ +				case res_error: +					/*FALLTHROUGH*/ +				default: +					return (-1); +				} +			} while (!done); +		} + +		Dprint(_res.options & RES_DEBUG, +		       (stdout, ";; Querying server (# %d) address = %s\n", +			ns+1, inet_ntoa(nsap->sin_addr))); +  		if (v_circuit) { -			int truncated = 0; +			int		truncated; +			struct iovec	iov[2]; +			u_short		len; +			u_char		*cp;  			/*  			 * Use virtual circuit;  			 * at most one attempt per server.  			 */  			try = _res.retry; -			if (s < 0) { -				s = socket(AF_INET, SOCK_STREAM, 0); +			truncated = 0; +			if ((s < 0) || (!vc)) { +				if (s >= 0) +					_res_close(); + +				s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC);  				if (s < 0) {  					terrno = errno; -#ifdef DEBUG -					if (_res.options & RES_DEBUG) -					    perror("socket (vc) failed"); -#endif -					continue; +					Perror(stderr, "socket(vc)", errno); +					return (-1);  				}  				if (connect(s, -				    (struct sockaddr *)&(_res.nsaddr_list[ns]), -				    sizeof(struct sockaddr)) < 0) { +					    (struct sockaddr *)nsap, +					    sizeof(struct sockaddr)) +				    < 0) {  					terrno = errno; -#ifdef DEBUG -					if (_res.options & RES_DEBUG) -					    perror("connect failed"); -#endif -					(void) close(s); -					s = -1; -					continue; +					Aerror(stderr, "connect/vc", +					       errno, *nsap); +					badns |= (1<<ns); +					_res_close(); +					goto next_ns;  				} +				vc = 1;  			}  			/*  			 * Send length & message  			 */ -			len = htons((u_short)buflen); +			putshort((u_short)buflen, (u_char*)&len);  			iov[0].iov_base = (caddr_t)&len; -			iov[0].iov_len = sizeof(len); -			iov[1].iov_base = (char *)buf; +			iov[0].iov_len = INT16SZ; +			iov[1].iov_base = (caddr_t)buf;  			iov[1].iov_len = buflen; -			if (writev(s, iov, 2) != sizeof(len) + buflen) { +			if (writev(s, iov, 2) != (INT16SZ + buflen)) {  				terrno = errno; -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					perror("write failed"); -#endif -				(void) close(s); -				s = -1; -				continue; +				Perror(stderr, "write failed", errno); +				badns |= (1<<ns); +				_res_close(); +				goto next_ns;  			}  			/*  			 * Receive length & response  			 */ -			cp = answer; -			len = sizeof(short); -			while (len != 0 && -			    (n = read(s, (char *)cp, (int)len)) > 0) { +			cp = ans; +			len = INT16SZ; +			while ((n = read(s, (char *)cp, (int)len)) > 0) {  				cp += n; -				len -= n; +				if ((len -= n) <= 0) +					break;  			}  			if (n <= 0) {  				terrno = errno; -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					perror("read failed"); -#endif -				(void) close(s); -				s = -1; +				Perror(stderr, "read failed", errno); +				_res_close();  				/*  				 * A long running process might get its TCP  				 * connection reset if the remote server was @@ -211,35 +402,33 @@ res_send(buf, buflen, answer, anslen)  				 */  				if (terrno == ECONNRESET && !connreset) {  					connreset = 1; -					ns--; +					_res_close(); +					goto same_ns;  				} -				continue; +				_res_close(); +				goto next_ns;  			} -			cp = answer; -			if ((resplen = ntohs(*(u_short *)cp)) > anslen) { -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					fprintf(stderr, -						";; response truncated\n"); -#endif -				len = anslen; +			resplen = _getshort(ans); +			if (resplen > anssiz) { +				Dprint(_res.options & RES_DEBUG, +				       (stdout, ";; response truncated\n") +				       );  				truncated = 1; +				len = anssiz;  			} else  				len = resplen; +			cp = ans;  			while (len != 0 && -			   (n = read(s, (char *)cp, (int)len)) > 0) { +			       (n = read(s, (char *)cp, (int)len)) > 0 +			       ) {  				cp += n;  				len -= n;  			}  			if (n <= 0) {  				terrno = errno; -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					perror("read failed"); -#endif -				(void) close(s); -				s = -1; -				continue; +				Perror(stderr, "read(vc)", errno); +				_res_close(); +				goto next_ns;  			}  			if (truncated) {  				/* @@ -247,10 +436,13 @@ res_send(buf, buflen, answer, anslen)  				 * so connection stays in synch.  				 */  				anhp->tc = 1; -				len = resplen - anslen; +				len = resplen - anssiz;  				while (len != 0) { -					n = (len > sizeof(junk) ? -					    sizeof(junk) : len); +					char junk[512]; + +					n = (len > sizeof(junk) +					     ? sizeof(junk) +					     : len);  					if ((n = read(s, junk, n)) > 0)  						len -= n;  					else @@ -261,19 +453,23 @@ res_send(buf, buflen, answer, anslen)  			/*  			 * Use datagrams.  			 */ -			if (s < 0) { -				s = socket(AF_INET, SOCK_DGRAM, 0); +			struct timeval	timeout; +			fd_set		dsmask; +			struct sockaddr_in from; +			int		fromlen; + +			if ((s < 0) || vc) { +				if (vc) +					_res_close(); +				s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);  				if (s < 0) { -					terrno = errno; -#ifdef DEBUG -					if (_res.options & RES_DEBUG) -					    perror("socket (dg) failed"); -#endif -					continue; + bad_dg_sock:				terrno = errno; +					Perror(stderr, "socket(dg)", errno); +					return (-1);  				} +				connected = 0;  			}  			/* -			 * I'm tired of answering this question, so:  			 * On a 4.3BSD+ machine (client and server,  			 * actually), sending to a nameserver datagram  			 * port with no nameserver will cause an @@ -290,29 +486,29 @@ res_send(buf, buflen, answer, anslen)  			 */  			if (_res.nscount == 1 || (try == 0 && ns == 0)) {  				/* -				 * Don't use connect if we might -				 * still receive a response -				 * from another server. +				 * Connect only if we are sure we won't +				 * receive a response from another server.  				 */ -				if (connected == 0) { +				if (!connected) {  					if (connect(s, -					    (struct sockaddr *) -					    &_res.nsaddr_list[ns], -					    sizeof(struct sockaddr)) < 0) { -#ifdef DEBUG -						if (_res.options & RES_DEBUG) -							perror("connect"); -#endif -						continue; +						    (struct sockaddr *)nsap, +						    sizeof(struct sockaddr) +						    ) < 0 +					    ) { +						Aerror(stderr, +						       "connect(dg)", +						       errno, *nsap); +						badns |= (1<<ns); +						_res_close(); +						goto next_ns;  					}  					connected = 1;  				}  				if (send(s, buf, buflen, 0) != buflen) { -#ifdef DEBUG -					if (_res.options & RES_DEBUG) -						perror("send"); -#endif -					continue; +					Perror(stderr, "send", errno); +					badns |= (1<<ns); +					_res_close(); +					goto next_ns;  				}  			} else {  				/* @@ -320,18 +516,26 @@ res_send(buf, buflen, answer, anslen)  				 * for responses from more than one server.  				 */  				if (connected) { -					(void) connect(s, &no_addr, -					    sizeof(no_addr)); +					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));  					connected = 0; +					errno = 0;  				}  				if (sendto(s, buf, buflen, 0, -				    (struct sockaddr *)&_res.nsaddr_list[ns], -				    sizeof(struct sockaddr)) != buflen) { -#ifdef DEBUG -					if (_res.options & RES_DEBUG) -						perror("sendto"); -#endif -					continue; +					   (struct sockaddr *)nsap, +					   sizeof(struct sockaddr)) +				    != buflen) { +					Aerror(stderr, "sendto", errno, *nsap); +					badns |= (1<<ns); +					_res_close(); +					goto next_ns;  				}  			} @@ -344,111 +548,162 @@ res_send(buf, buflen, answer, anslen)  			if ((long) timeout.tv_sec <= 0)  				timeout.tv_sec = 1;  			timeout.tv_usec = 0; -wait: +    wait:  			FD_ZERO(&dsmask);  			FD_SET(s, &dsmask);  			n = select(s+1, &dsmask, (fd_set *)NULL, -				(fd_set *)NULL, &timeout); +				   (fd_set *)NULL, &timeout);  			if (n < 0) { -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					perror("select"); -#endif -				continue; +				Perror(stderr, "select", errno); +				_res_close(); +				goto next_ns;  			}  			if (n == 0) {  				/*  				 * timeout  				 */ -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					printf(";; timeout\n"); -#endif +				Dprint(_res.options & RES_DEBUG, +				       (stdout, ";; timeout\n") +				       );  				gotsomewhere = 1; -				continue; +				_res_close(); +				goto next_ns;  			} -			if ((resplen = recv(s, answer, anslen, 0)) <= 0) { -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					perror("recvfrom"); -#endif -				continue; +			fromlen = sizeof(struct sockaddr_in); +			resplen = recvfrom(s, ans, anssiz, 0, +					   (struct sockaddr *)&from, &fromlen); +			if (resplen <= 0) { +				Perror(stderr, "recvfrom", errno); +				_res_close(); +				goto next_ns;  			}  			gotsomewhere = 1; -			if (id != anhp->id) { +			if (hp->id != anhp->id) {  				/* -				 * response from old query, ignore it +				 * response from old query, ignore it. +				 * XXX - potential security hazard could +				 *	 be detected here.  				 */ -#ifdef DEBUG -				if ((_res.options & RES_DEBUG) || -				    (_res.pfcode & RES_PRF_REPLY)) { -					printf(";; old answer:\n"); -					__p_query(answer); -				} +				DprintQ((_res.options & RES_DEBUG) || +					(_res.pfcode & RES_PRF_REPLY), +					(stdout, ";; old answer:\n"), +					ans); +				goto wait; +			} +#if CHECK_SRVR_ADDR +			if (!(_res.options & RES_INSECURE1) && +			    !our_server(&from)) { +				/* +				 * response from wrong server? ignore it. +				 * XXX - potential security hazard could +				 *	 be detected here. +				 */ +				DprintQ((_res.options & RES_DEBUG) || +					(_res.pfcode & RES_PRF_REPLY), +					(stdout, ";; not our server:\n"), +					ans); +				goto wait; +			}  #endif +			if (!(_res.options & RES_INSECURE2) && +			    !queries_match(buf, buf + buflen, +					   ans, ans + anssiz)) { +				/* +				 * response contains wrong query? ignore it. +				 * XXX - potential security hazard could +				 *	 be detected here. +				 */ +				DprintQ((_res.options & RES_DEBUG) || +					(_res.pfcode & RES_PRF_REPLY), +					(stdout, ";; wrong query name:\n"), +					ans);  				goto wait;  			} -			if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || +			if (anhp->rcode == SERVFAIL || +			    anhp->rcode == NOTIMP ||  			    anhp->rcode == REFUSED) { -#ifdef DEBUG -				if (_res.options & RES_DEBUG) { -					printf("server rejected query:\n"); -					__p_query(answer); -				} -#endif +				DprintQ(_res.options & RES_DEBUG, +					(stdout, "server rejected query:\n"), +					ans);  				badns |= (1<<ns); -				continue; +				_res_close(); +				goto next_ns;  			}  			if (!(_res.options & RES_IGNTC) && anhp->tc) {  				/*  				 * get rest of answer;  				 * use TCP with same server.  				 */ -#ifdef DEBUG -				if (_res.options & RES_DEBUG) -					printf(";; truncated answer\n"); -#endif -				(void) close(s); -				s = -1; +				Dprint(_res.options & RES_DEBUG, +				       (stdout, ";; truncated answer\n") +				       );  				v_circuit = 1; -				goto usevc; +				_res_close(); +				goto same_ns;  			} -		} -#ifdef DEBUG -		if (_res.options & RES_DEBUG) -			printf(";; got answer:\n"); -		if ((_res.options & RES_DEBUG) || -		    (_res.pfcode & RES_PRF_REPLY)) -			__p_query(answer); -#endif +		} /*if vc/dg*/ +		DprintQ((_res.options & RES_DEBUG) || +			(_res.pfcode & RES_PRF_REPLY), +			(stdout, ";; got answer:\n"), +			ans);  		/*  		 * If using virtual circuits, we assume that the first server -		 * is preferred * over the rest (i.e. it is on the local +		 * is preferred over the rest (i.e. it is on the local  		 * machine) and only keep that one open.  		 * If we have temporarily opened a virtual circuit,  		 * or if we haven't been asked to keep a socket open,  		 * close the socket.  		 */ -		if ((v_circuit && -		    ((_res.options & RES_USEVC) == 0 || ns != 0)) || -		    (_res.options & RES_STAYOPEN) == 0) { -			(void) close(s); -			s = -1; +		if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || +		    !(_res.options & RES_STAYOPEN)) { +			_res_close(); +		} +		if (Rhook) { +			int done = 0, loops = 0; + +			do { +				res_sendhookact act; + +				act = (*Rhook)(nsap, +					       buf, +					       buflen, +					       ans, +					       anssiz, +					       &resplen); +				switch (act) { +				case res_goahead: +				case res_done: +					done = 1; +					break; +				case res_nextns: +					_res_close(); +					goto next_ns; +				case res_modified: +					/* give the hook another try */ +					if (++loops < 42) /*doug adams*/ +						break; +					/*FALLTHROUGH*/ +				case res_error: +					/*FALLTHROUGH*/ +				default: +					return (-1); +				} +			} while (!done); +  		}  		return (resplen); -	   } -	} -	if (s >= 0) { -		(void) close(s); -		s = -1; -	} -	if (v_circuit == 0) -		if (gotsomewhere == 0) +    next_ns: ; +	   } /*foreach ns*/ +	} /*foreach retry*/ +	_res_close(); +	if (!v_circuit) { +		if (!gotsomewhere)  			errno = ECONNREFUSED;	/* no nameservers found */  		else  			errno = ETIMEDOUT;	/* no answer obtained */ -	else +	} else {  		errno = terrno; +	}  	return (-1);  } @@ -459,10 +714,13 @@ wait:   *   * This routine is not expected to be user visible.   */ +void  _res_close()  { -	if (s != -1) { +	if (s >= 0) {  		(void) close(s);  		s = -1; +		connected = 0; +		vc = 0;  	}  } | 
