get* rework and new bind code
This commit is contained in:
parent
08a0aca6e2
commit
1363f04ce1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3070
@ -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,12 +50,29 @@
|
||||
* 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
|
||||
@ -65,10 +81,12 @@
|
||||
#define MAXDNAME 256 /* maximum domain name */
|
||||
#define MAXCDNAME 255 /* maximum compressed domain name */
|
||||
#define MAXLABEL 63 /* maximum length of domain label */
|
||||
/* Number of bytes of fixed size data in query structure */
|
||||
#define QFIXEDSZ 4
|
||||
/* number of bytes of fixed size data in resource record */
|
||||
#define RRFIXEDSZ 10
|
||||
#define HFIXEDSZ 12 /* #/bytes of fixed data in header */
|
||||
#define QFIXEDSZ 4 /* #/bytes of fixed data in query */
|
||||
#define RRFIXEDSZ 10 /* #/bytes of fixed data in r record */
|
||||
#define INT32SZ 4 /* for systems without 32-bit ints */
|
||||
#define INT16SZ 2 /* for systems without 16-bit ints */
|
||||
#define INADDRSZ 4 /* for sizeof(struct inaddr) != 4 */
|
||||
|
||||
/*
|
||||
* Internet nameserver port number
|
||||
@ -81,7 +99,7 @@
|
||||
#define QUERY 0x0 /* standard query */
|
||||
#define IQUERY 0x1 /* inverse query */
|
||||
#define STATUS 0x2 /* nameserver status query */
|
||||
/*#define xxx 0x3 /* 0x3 reserved */
|
||||
/* 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 */
|
||||
@ -125,13 +143,17 @@
|
||||
#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_SA 200 /* shuffle address */
|
||||
/* Query type values which do not appear in resource records */
|
||||
#define T_AXFR 252 /* transfer zone of authority */
|
||||
#define T_MAILB 253 /* transfer mailbox records */
|
||||
@ -152,41 +174,10 @@
|
||||
* 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_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,38 +187,38 @@
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -247,30 +238,31 @@ struct rrec {
|
||||
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) { \
|
||||
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) { \
|
||||
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) { \
|
||||
@ -278,13 +270,9 @@ extern u_int32_t _getlong();
|
||||
register u_char *t_cp = (u_char *)(cp); \
|
||||
*t_cp++ = t_s >> 8; \
|
||||
*t_cp = t_s; \
|
||||
(cp) += 2; \
|
||||
(cp) += INT16SZ; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Warning: PUTLONG --no-longer-- destroys its first argument. if you
|
||||
* were depending on this "feature", you will lose.
|
||||
*/
|
||||
#define PUTLONG(l, cp) { \
|
||||
register u_int32_t t_l = (u_int32_t)(l); \
|
||||
register u_char *t_cp = (u_char *)(cp); \
|
||||
@ -292,7 +280,7 @@ extern u_int32_t _getlong();
|
||||
*t_cp++ = t_l >> 16; \
|
||||
*t_cp++ = t_l >> 8; \
|
||||
*t_cp = t_l; \
|
||||
(cp) += 4; \
|
||||
(cp) += INT32SZ; \
|
||||
}
|
||||
|
||||
#endif /* !_NAMESER_H_ */
|
||||
|
146
include/resolv.h
146
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
|
||||
@ -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_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_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_ */
|
||||
|
@ -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"
|
||||
|
480
lib/libc/net/gethostbydns.c
Normal file
480
lib/libc/net/gethostbydns.c
Normal file
@ -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();
|
||||
}
|
182
lib/libc/net/gethostbyht.c
Normal file
182
lib/libc/net/gethostbyht.c
Normal file
@ -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);
|
||||
}
|
115
lib/libc/net/gethostbynis.c
Normal file
115
lib/libc/net/gethostbynis.c
Normal file
@ -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");
|
||||
}
|
@ -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]) {
|
||||
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]) {
|
||||
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();
|
||||
}
|
||||
|
308
lib/libc/net/getnetbydns.c
Normal file
308
lib/libc/net/getnetbydns.c
Normal file
@ -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();
|
||||
}
|
159
lib/libc/net/getnetbyht.c
Normal file
159
lib/libc/net/getnetbyht.c
Normal file
@ -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);
|
||||
}
|
117
lib/libc/net/getnetbynis.c
Normal file
117
lib/libc/net/getnetbynis.c
Normal file
@ -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");
|
||||
}
|
190
lib/libc/net/getnetnamadr.c
Normal file
190
lib/libc/net/getnetnamadr.c
Normal file
@ -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();
|
||||
}
|
@ -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 <stdio.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
static int dn_find();
|
||||
#include <stdio.h>
|
||||
#include <resolv.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#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,13 +242,14 @@ dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
|
||||
/*
|
||||
* Skip over a compressed domain name. Return the size or -1.
|
||||
*/
|
||||
int
|
||||
__dn_skipname(comp_dn, eom)
|
||||
const u_char *comp_dn, *eom;
|
||||
{
|
||||
register u_char *cp;
|
||||
register const u_char *cp;
|
||||
register int n;
|
||||
|
||||
cp = (u_char *)comp_dn;
|
||||
cp = comp_dn;
|
||||
while (cp < eom && (n = *cp++)) {
|
||||
/*
|
||||
* check for indirection
|
||||
@ -244,16 +258,28 @@ __dn_skipname(comp_dn, eom)
|
||||
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;
|
||||
|
@ -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");
|
||||
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");
|
||||
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)
|
||||
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);
|
||||
}
|
||||
|
||||
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,19 +244,24 @@ __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",
|
||||
_res_opcodes[hp->opcode],
|
||||
@ -282,13 +289,12 @@ __fp_query(msg,file)
|
||||
fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
|
||||
fprintf(file, ", Ans: %d", ntohs(hp->ancount));
|
||||
fprintf(file, ", Auth: %d", ntohs(hp->nscount));
|
||||
fprintf(file,", Addit: %d\n", ntohs(hp->arcount));
|
||||
fprintf(file, ", Addit: %d", ntohs(hp->arcount));
|
||||
}
|
||||
#if 0
|
||||
if (_res.pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1)) {
|
||||
if ((!_res.pfcode) || (_res.pfcode &
|
||||
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
|
||||
putc('\n',file);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Print question records.
|
||||
*/
|
||||
@ -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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
*pp++ = 0;
|
||||
cp = strchr(cp, '.') + 1; /* we know there is one */
|
||||
*pp++ = cp;
|
||||
dots--;
|
||||
}
|
||||
*pp = NULL;
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG) {
|
||||
printf(";; res_init()... default dnsrch list:\n");
|
||||
for (pp = _res.dnsrch; *pp; pp++) {
|
||||
printf(";;\t%s\n", *pp);
|
||||
}
|
||||
printf(";;\t..END..\n");
|
||||
}
|
||||
#endif /*DEBUG*/
|
||||
#endif /*!RFC1535*/
|
||||
}
|
||||
|
||||
if ((cp = getenv("RES_OPTIONS")) != NULL) {
|
||||
res_setoptions(cp, "env");
|
||||
}
|
||||
_res.options |= RES_INIT;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
res_setoptions(options, source)
|
||||
char *options, *source;
|
||||
{
|
||||
char *cp = options;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG) {
|
||||
printf(";; res_setoptions(\"%s\", \"%s\")...\n",
|
||||
options, source);
|
||||
}
|
||||
#endif
|
||||
while (*cp) {
|
||||
/* skip leading and inner runs of spaces */
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
/* search for and process individual options */
|
||||
if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) {
|
||||
i = atoi(cp + sizeof("ndots:") - 1);
|
||||
if (i <= RES_MAXNDOTS)
|
||||
_res.ndots = i;
|
||||
else
|
||||
_res.ndots = RES_MAXNDOTS;
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG) {
|
||||
printf(";;\tndots=%d\n", _res.ndots);
|
||||
}
|
||||
#endif
|
||||
} else if (!strncmp(cp, "debug", sizeof("debug")-1)) {
|
||||
#ifdef DEBUG
|
||||
if (!(_res.options & RES_DEBUG)) {
|
||||
printf(";; res_setoptions(\"%s\", \"%s\")..\n",
|
||||
options, source);
|
||||
_res.options |= RES_DEBUG;
|
||||
}
|
||||
printf(";;\tdebug\n");
|
||||
#endif
|
||||
} else {
|
||||
/* XXX - print a warning here? */
|
||||
}
|
||||
/* skip to next run of spaces */
|
||||
while (*cp && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
static u_int32_t
|
||||
net_mask(in) /* XXX - should really use system's version of this */
|
||||
struct in_addr in;
|
||||
{
|
||||
register u_int32_t i = ntohl(in.s_addr);
|
||||
|
||||
if (IN_CLASSA(i))
|
||||
return (htonl(IN_CLASSA_NET));
|
||||
else if (IN_CLASSB(i))
|
||||
return (htonl(IN_CLASSB_NET));
|
||||
else
|
||||
return (htonl(IN_CLASSC_NET));
|
||||
}
|
||||
#endif
|
||||
|
@ -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 */
|
||||
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;
|
||||
|
@ -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>
|
||||
#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,7 +126,7 @@ res_query(name, class, type, answer, anslen)
|
||||
h_errno = NO_RECOVERY;
|
||||
return (n);
|
||||
}
|
||||
n = res_send(buf, n, (char *)answer, anslen);
|
||||
n = res_send(buf, n, answer, anslen);
|
||||
if (n < 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
@ -122,7 +136,6 @@ res_query(name, class, type, answer, anslen)
|
||||
return (n);
|
||||
}
|
||||
|
||||
hp = (HEADER *) answer;
|
||||
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
@ -155,45 +168,72 @@ res_query(name, class, type, answer, anslen)
|
||||
* 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++) {
|
||||
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,
|
||||
@ -204,30 +244,65 @@ res_search(name, class, type, answer, anslen)
|
||||
* 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.
|
||||
* 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)
|
||||
|
||||
switch (h_errno) {
|
||||
case NO_DATA:
|
||||
got_nodata++;
|
||||
if ((h_errno != HOST_NOT_FOUND && h_errno != NO_DATA) ||
|
||||
(_res.options & RES_DNSRCH) == 0)
|
||||
/* FALLTHROUGH */
|
||||
case HOST_NOT_FOUND:
|
||||
/* keep trying */
|
||||
break;
|
||||
case TRY_AGAIN:
|
||||
if (hp->rcode == SERVFAIL) {
|
||||
/* try next search element, if any */
|
||||
got_servfail++;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
/* 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 (n && (ret = res_querydomain(name, (char *)NULL, class, type,
|
||||
answer, anslen)) > 0)
|
||||
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 (got_nodata)
|
||||
saved_herrno = h_errno;
|
||||
}
|
||||
|
||||
/* if we got here, we didn't satisfy the search.
|
||||
* if we did an initial full query, return that query's h_errno
|
||||
* (note that we wouldn't be here if that query had succeeded).
|
||||
* else if we ever got a nodata, send that back as the reason.
|
||||
* else send back meaningless h_errno, that being the one from
|
||||
* the last DNSRCH we did.
|
||||
*/
|
||||
if (saved_herrno != -1)
|
||||
h_errno = saved_herrno;
|
||||
else if (got_nodata)
|
||||
h_errno = NO_DATA;
|
||||
else if (got_servfail)
|
||||
h_errno = TRY_AGAIN;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -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",
|
||||
} 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);
|
||||
}
|
||||
|
@ -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;
|
||||
static int connected = 0; /* is the socket connected */
|
||||
static int vc = 0; /* is the socket a virtual ciruit? */
|
||||
|
||||
#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
|
||||
|
||||
res_send(buf, buflen, answer, anslen)
|
||||
const char *buf;
|
||||
int buflen;
|
||||
char *answer;
|
||||
int anslen;
|
||||
#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;
|
||||
{
|
||||
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];
|
||||
int save = errno;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY)) {
|
||||
printf(";; res_send()\n");
|
||||
__p_query(buf);
|
||||
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) {
|
||||
|
||||
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.
|
||||
*/
|
||||
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) {
|
||||
s = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
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,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,105 +554,156 @@ res_send(buf, buflen, answer, anslen)
|
||||
n = select(s+1, &dsmask, (fd_set *)NULL,
|
||||
(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);
|
||||
}
|
||||
#endif
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; old answer:\n"),
|
||||
ans);
|
||||
goto wait;
|
||||
}
|
||||
if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP ||
|
||||
anhp->rcode == REFUSED) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG) {
|
||||
printf("server rejected query:\n");
|
||||
__p_query(answer);
|
||||
#if CHECK_SRVR_ADDR
|
||||
if (!(_res.options & RES_INSECURE1) &&
|
||||
!our_server(&from)) {
|
||||
/*
|
||||
* response from wrong server? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; not our server:\n"),
|
||||
ans);
|
||||
goto wait;
|
||||
}
|
||||
#endif
|
||||
if (!(_res.options & RES_INSECURE2) &&
|
||||
!queries_match(buf, buf + buflen,
|
||||
ans, ans + anssiz)) {
|
||||
/*
|
||||
* response contains wrong query? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; wrong query name:\n"),
|
||||
ans);
|
||||
goto wait;
|
||||
}
|
||||
if (anhp->rcode == SERVFAIL ||
|
||||
anhp->rcode == NOTIMP ||
|
||||
anhp->rcode == REFUSED) {
|
||||
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 @@ res_send(buf, buflen, answer, anslen)
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user