mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Merge in bind-4.9.4-P1 resolver...
This commit is contained in:
parent
74b3fad642
commit
5ce1c533c7
23 changed files with 860 additions and 3930 deletions
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
# machine-independent net sources
|
||||
.PATH: ${.CURDIR}/${MACHINE}/net ${.CURDIR}/net
|
||||
.PATH: ${.CURDIR}/../../contrib/bind/res
|
||||
|
||||
SRCS+= addr2ascii.c ascii2addr.c \
|
||||
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 \
|
||||
linkaddr.c rcmd.c recv.c res_comp.c res_data.c res_debug.c \
|
||||
res_init.c res_mkquery.c res_query.c res_send.c send.c ether_addr.c
|
||||
inet_makeaddr.c inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
|
||||
inet_pton.c linkaddr.c map_v4v6.c nsap_addr.c \
|
||||
rcmd.c recv.c res_comp.c res_data.c res_debug.c \
|
||||
res_init.c res_mkquery.c res_query.c res_send.c send.c ether_addr.c \
|
||||
|
||||
# iso_addr.c
|
||||
# ns_addr.c ns_ntoa.c
|
||||
|
|
@ -19,9 +21,12 @@ SRCS+= addr2ascii.c ascii2addr.c \
|
|||
.include "${.CURDIR}/${MACHINE}/net/Makefile.inc"
|
||||
|
||||
MAN3+= net/addr2ascii.3 \
|
||||
net/byteorder.3 net/ethers.3 net/gethostbyname.3 net/getnetent.3 \
|
||||
net/byteorder.3 net/ethers.3 \
|
||||
net/getprotoent.3 net/getservent.3 net/inet.3 net/linkaddr.3 \
|
||||
net/rcmd.3 net/resolver.3
|
||||
net/rcmd.3
|
||||
|
||||
# not installed from here, see usr.sbin/named/man for huge sed command:
|
||||
# => gethostbyname.3 getnetent.3 resolver.3
|
||||
|
||||
# not installed: net/ns.3 net/iso_addr.3
|
||||
|
||||
|
|
@ -30,11 +35,11 @@ MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
|
|||
byteorder.3 ntohs.3
|
||||
MLINKS+=ethers.3 ether_line.3 ethers.3 ether_aton.3 ethers.3 ether_ntoa.3 \
|
||||
ethers.3 ether_ntohost.3 ethers.3 ether_hostton.3
|
||||
MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
|
||||
gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
|
||||
gethostbyname.3 herror.3
|
||||
MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
|
||||
getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
|
||||
#MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
|
||||
# gethostbyname.3 sethostent.3 gethostbyname.3 gethostent.3 \
|
||||
# gethostbyname.3 herror.3
|
||||
#MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
|
||||
# getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
|
||||
MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
|
||||
getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3
|
||||
MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
|
||||
|
|
@ -45,6 +50,6 @@ MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_lnaof.3 \
|
|||
MLINKS+=linkaddr.3 link_addr.3 linkaddr.3 link_ntoa.3
|
||||
#MLINKS+=ns.3 ns_addr.3 ns.3 ns_ntoa.3
|
||||
MLINKS+=rcmd.3 rresvport.3 rcmd.3 iruserok.3 rcmd.3 ruserok.3
|
||||
MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
|
||||
resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
|
||||
resolver.3 res_search.3
|
||||
#MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
|
||||
# resolver.3 res_mkquery.3 resolver.3 res_send.3 resolver.3 res_query.3 \
|
||||
# resolver.3 res_search.3
|
||||
|
|
|
|||
|
|
@ -53,9 +53,10 @@
|
|||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: gethostbydns.c,v 1.8 1996/01/13 09:03:40 peter Exp $";
|
||||
static char rcsid[] = "$Id: gethostbydns.c,v 1.9 1996/07/12 18:54:33 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
|
@ -75,6 +76,8 @@ static char rcsid[] = "$Id: gethostbydns.c,v 1.8 1996/01/13 09:03:40 peter Exp $
|
|||
|
||||
extern void _res_close __P((void));
|
||||
|
||||
#define SPRINTF(x) ((size_t)sprintf x)
|
||||
|
||||
#define MAXALIASES 35
|
||||
#define MAXADDRS 35
|
||||
|
||||
|
|
@ -82,11 +85,12 @@ static const char AskedForGot[] =
|
|||
"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
|
||||
|
||||
static char *h_addr_ptrs[MAXADDRS + 1];
|
||||
static struct hostent *gethostbyname_ipv4 __P((const char *));
|
||||
|
||||
static struct hostent host;
|
||||
static char *host_aliases[MAXALIASES];
|
||||
static char hostbuf[8*1024];
|
||||
static struct in_addr host_addr;
|
||||
static u_char host_addr[16]; /* IPv4 or IPv6 */
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
static void addrsort __P((char **, int));
|
||||
|
|
@ -127,13 +131,12 @@ dprintf(msg, num)
|
|||
# define dprintf(msg, num) /*nada*/
|
||||
#endif
|
||||
|
||||
|
||||
static struct hostent *
|
||||
gethostanswer(answer, anslen, qname, qclass, qtype)
|
||||
gethostanswer(answer, anslen, qname, qtype)
|
||||
const querybuf *answer;
|
||||
int anslen;
|
||||
const char *qname;
|
||||
int qclass, qtype;
|
||||
int qtype;
|
||||
{
|
||||
register const HEADER *hp;
|
||||
register const u_char *cp;
|
||||
|
|
@ -145,10 +148,23 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
int toobig = 0;
|
||||
char tbuf[MAXDNAME+1];
|
||||
const char *tname;
|
||||
int (*name_ok) __P((const char *));
|
||||
|
||||
tname = qname;
|
||||
host.h_name = NULL;
|
||||
eom = answer->buf + anslen;
|
||||
switch (qtype) {
|
||||
case T_A:
|
||||
case T_AAAA:
|
||||
name_ok = res_hnok;
|
||||
break;
|
||||
case T_PTR:
|
||||
name_ok = res_dnok;
|
||||
break;
|
||||
default:
|
||||
h_errno = NO_RECOVERY;
|
||||
return (NULL); /* XXX should be abort(); */
|
||||
}
|
||||
/*
|
||||
* find first satisfactory answer
|
||||
*/
|
||||
|
|
@ -162,12 +178,13 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
h_errno = NO_RECOVERY;
|
||||
return (NULL);
|
||||
}
|
||||
if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
if ((n < 0) || !(*name_ok)(bp)) {
|
||||
h_errno = NO_RECOVERY;
|
||||
return (NULL);
|
||||
}
|
||||
cp += n + QFIXEDSZ;
|
||||
if (qtype == T_A) {
|
||||
if (qtype == T_A || qtype == T_AAAA) {
|
||||
/* 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).
|
||||
|
|
@ -184,14 +201,12 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
host.h_aliases = host_aliases;
|
||||
hap = h_addr_ptrs;
|
||||
*hap = NULL;
|
||||
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
|
||||
host.h_addr_list = h_addr_ptrs;
|
||||
#endif
|
||||
haveanswer = 0;
|
||||
had_error = 0;
|
||||
while (ancount-- > 0 && cp < eom && !had_error) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
if (n < 0) {
|
||||
if ((n < 0) || !(*name_ok)(bp)) {
|
||||
had_error++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -202,26 +217,20 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
cp += INT16SZ + INT32SZ; /* class, TTL */
|
||||
n = _getshort(cp);
|
||||
cp += INT16SZ; /* len */
|
||||
if (class != qclass) {
|
||||
if (class != C_IN) {
|
||||
/* XXX - debug? syslog? */
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
if (qtype == T_A && type == T_CNAME) {
|
||||
if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
|
||||
if (ap >= &host_aliases[MAXALIASES-1])
|
||||
continue;
|
||||
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
||||
if (n < 0) {
|
||||
if ((n < 0) || !(*name_ok)(tbuf)) {
|
||||
had_error++;
|
||||
continue;
|
||||
}
|
||||
cp += n;
|
||||
if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostby*.gethostanswer: 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 */
|
||||
|
|
@ -241,7 +250,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
}
|
||||
if (qtype == T_PTR && type == T_CNAME) {
|
||||
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
|
||||
if (n < 0) {
|
||||
if ((n < 0) || !res_hnok(tbuf)) {
|
||||
had_error++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -261,7 +270,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
if (type != qtype) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
|
||||
qname, p_class(qclass), p_type(qtype),
|
||||
qname, p_class(C_IN), p_type(qtype),
|
||||
p_type(type));
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
|
|
@ -275,11 +284,11 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
if (n < 0) {
|
||||
if ((n < 0) || !res_hnok(bp)) {
|
||||
had_error++;
|
||||
break;
|
||||
}
|
||||
#ifdef MULTI_PTRS_ARE_ALIASES
|
||||
#if MULTI_PTRS_ARE_ALIASES
|
||||
cp += n;
|
||||
if (!haveanswer)
|
||||
host.h_name = bp;
|
||||
|
|
@ -295,10 +304,17 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
break;
|
||||
#else
|
||||
host.h_name = bp;
|
||||
if (_res.options & RES_USE_INET6) {
|
||||
n = strlen(bp) + 1; /* for the \0 */
|
||||
bp += n;
|
||||
buflen -= n;
|
||||
_map_v4v6_hostent(&host, &bp, &buflen);
|
||||
}
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return (&host);
|
||||
#endif
|
||||
case T_A:
|
||||
case T_AAAA:
|
||||
if (strcasecmp(host.h_name, bp) != 0) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
AskedForGot, host.h_name, bp);
|
||||
|
|
@ -313,10 +329,6 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
} 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;
|
||||
|
|
@ -339,6 +351,7 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
}
|
||||
bcopy(cp, *hap++ = bp, n);
|
||||
bp += n;
|
||||
buflen -= n;
|
||||
cp += n;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -358,41 +371,61 @@ gethostanswer(answer, anslen, qname, qclass, qtype)
|
|||
* 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)
|
||||
if (_res.nsort && haveanswer > 1 && qtype == T_A)
|
||||
addrsort(h_addr_ptrs, haveanswer);
|
||||
# endif /*RESOLVSORT*/
|
||||
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
|
||||
/* nothing */
|
||||
#else
|
||||
host.h_addr = h_addr_ptrs[0];
|
||||
#endif /*BSD*/
|
||||
if (!host.h_name) {
|
||||
n = strlen(qname) + 1; /* for the \0 */
|
||||
if (n > buflen)
|
||||
goto try_again;
|
||||
strcpy(bp, qname);
|
||||
host.h_name = bp;
|
||||
bp += n;
|
||||
buflen -= n;
|
||||
}
|
||||
if (_res.options & RES_USE_INET6)
|
||||
_map_v4v6_hostent(&host, &bp, &buflen);
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return (&host);
|
||||
} else {
|
||||
h_errno = TRY_AGAIN;
|
||||
return (NULL);
|
||||
}
|
||||
try_again:
|
||||
h_errno = TRY_AGAIN;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbydnsname(name)
|
||||
_gethostbydnsname(name, af)
|
||||
const char *name;
|
||||
int af;
|
||||
{
|
||||
querybuf buf;
|
||||
register const char *cp;
|
||||
int n;
|
||||
char *bp;
|
||||
int n, size, type, len;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
size = INADDRSZ;
|
||||
type = T_A;
|
||||
break;
|
||||
case AF_INET6:
|
||||
size = IN6ADDRSZ;
|
||||
type = T_AAAA;
|
||||
break;
|
||||
default:
|
||||
h_errno = NETDB_INTERNAL;
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
host.h_addrtype = af;
|
||||
host.h_length = size;
|
||||
|
||||
/*
|
||||
* if there aren't any dots, it could be a user-level alias.
|
||||
* this is also done in res_query() since we are not the only
|
||||
|
|
@ -415,24 +448,22 @@ _gethostbydnsname(name)
|
|||
* Fake up a hostent as if we'd actually
|
||||
* done a lookup.
|
||||
*/
|
||||
if (!inet_aton(name, &host_addr)) {
|
||||
if (inet_pton(af, name, host_addr) <= 0) {
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return (NULL);
|
||||
}
|
||||
strncpy(hostbuf, name, MAXDNAME);
|
||||
hostbuf[MAXDNAME] = '\0';
|
||||
bp = hostbuf + MAXDNAME;
|
||||
len = sizeof hostbuf - MAXDNAME;
|
||||
host.h_name = hostbuf;
|
||||
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[0] = (char *)host_addr;
|
||||
h_addr_ptrs[1] = NULL;
|
||||
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
|
||||
host.h_addr_list = h_addr_ptrs;
|
||||
#else
|
||||
host.h_addr = h_addr_ptrs[0];
|
||||
#endif
|
||||
if (_res.options & RES_USE_INET6)
|
||||
_map_v4v6_hostent(&host, &bp, &len);
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return (&host);
|
||||
}
|
||||
|
|
@ -440,22 +471,25 @@ _gethostbydnsname(name)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
|
||||
if ((n = res_search(name, C_IN, type, buf.buf, sizeof(buf))) < 0) {
|
||||
dprintf("res_search failed (%d)\n", n);
|
||||
return (NULL);
|
||||
}
|
||||
return (gethostanswer(&buf, n, name, C_IN, T_A));
|
||||
return (gethostanswer(&buf, n, name, type));
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbydnsaddr(addr, len, type)
|
||||
const char *addr;
|
||||
int len, type;
|
||||
_gethostbydnsaddr(addr, len, af)
|
||||
const char *addr; /* XXX should have been def'd as u_char! */
|
||||
int len, af;
|
||||
{
|
||||
int n;
|
||||
const u_char *uaddr = (const u_char *)addr;
|
||||
static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
|
||||
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
|
||||
int n, size;
|
||||
querybuf buf;
|
||||
register struct hostent *hp;
|
||||
char qbuf[MAXDNAME+1];
|
||||
char qbuf[MAXDNAME+1], *qp;
|
||||
#ifdef SUNSECURITY
|
||||
register struct hostent *rhp;
|
||||
char **haddr;
|
||||
|
|
@ -467,58 +501,101 @@ _gethostbydnsaddr(addr, len, type)
|
|||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (type != AF_INET) {
|
||||
if (af == AF_INET6 && len == IN6ADDRSZ &&
|
||||
(!bcmp(uaddr, mapped, sizeof mapped) ||
|
||||
!bcmp(uaddr, tunnelled, sizeof tunnelled))) {
|
||||
/* Unmap. */
|
||||
addr += sizeof mapped;
|
||||
uaddr += sizeof mapped;
|
||||
af = AF_INET;
|
||||
len = INADDRSZ;
|
||||
}
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
size = INADDRSZ;
|
||||
break;
|
||||
case AF_INET6:
|
||||
size = IN6ADDRSZ;
|
||||
break;
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
|
||||
((unsigned)addr[3] & 0xff),
|
||||
((unsigned)addr[2] & 0xff),
|
||||
((unsigned)addr[1] & 0xff),
|
||||
((unsigned)addr[0] & 0xff));
|
||||
if (size != len) {
|
||||
errno = EINVAL;
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
(void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
|
||||
(uaddr[3] & 0xff),
|
||||
(uaddr[2] & 0xff),
|
||||
(uaddr[1] & 0xff),
|
||||
(uaddr[0] & 0xff));
|
||||
break;
|
||||
case AF_INET6:
|
||||
qp = qbuf;
|
||||
for (n = IN6ADDRSZ - 1; n >= 0; n--) {
|
||||
qp += SPRINTF((qp, "%x.%x.",
|
||||
uaddr[n] & 0xf,
|
||||
(uaddr[n] >> 4) & 0xf));
|
||||
}
|
||||
strcpy(qp, "ip6.int");
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
|
||||
if (n < 0) {
|
||||
dprintf("res_query failed (%d)\n", n);
|
||||
return (NULL);
|
||||
}
|
||||
if (!(hp = gethostanswer(&buf, n, qbuf, C_IN, T_PTR)))
|
||||
if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR)))
|
||||
return (NULL); /* h_errno was set by gethostanswer() */
|
||||
#ifdef SUNSECURITY
|
||||
/*
|
||||
* turn off search as the name should be absolute,
|
||||
* 'localhost' should be matched by defnames
|
||||
*/
|
||||
strncpy(hname2, hp->h_name, MAXDNAME);
|
||||
hname2[MAXDNAME] = '\0';
|
||||
old_options = _res.options;
|
||||
_res.options &= ~RES_DNSRCH;
|
||||
_res.options |= RES_DEFNAMES;
|
||||
if (!(rhp = gethostbyname(hname2))) {
|
||||
if (af == AF_INET) {
|
||||
/*
|
||||
* turn off search as the name should be absolute,
|
||||
* 'localhost' should be matched by defnames
|
||||
*/
|
||||
strncpy(hname2, hp->h_name, MAXDNAME);
|
||||
hname2[MAXDNAME] = '\0';
|
||||
old_options = _res.options;
|
||||
_res.options &= ~RES_DNSRCH;
|
||||
_res.options |= RES_DEFNAMES;
|
||||
if (!(rhp = gethostbyname(hname2))) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostbyaddr: No A record for %s (verifying [%s])",
|
||||
hname2, inet_ntoa(*((struct in_addr *)addr)));
|
||||
_res.options = old_options;
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return (NULL);
|
||||
}
|
||||
_res.options = old_options;
|
||||
for (haddr = rhp->h_addr_list; *haddr; haddr++)
|
||||
}
|
||||
_res.options = old_options;
|
||||
for (haddr = rhp->h_addr_list; *haddr; haddr++)
|
||||
if (!memcmp(*haddr, addr, INADDRSZ))
|
||||
break;
|
||||
if (!*haddr) {
|
||||
if (!*haddr) {
|
||||
syslog(LOG_NOTICE|LOG_AUTH,
|
||||
"gethostbyaddr: A record of %s != PTR record [%s]",
|
||||
hname2, inet_ntoa(*((struct in_addr *)addr)));
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
#endif /*SUNSECURITY*/
|
||||
hp->h_addrtype = type;
|
||||
hp->h_addrtype = af;
|
||||
hp->h_length = len;
|
||||
h_addr_ptrs[0] = (char *)&host_addr;
|
||||
bcopy(addr, host_addr, len);
|
||||
h_addr_ptrs[0] = (char *)host_addr;
|
||||
h_addr_ptrs[1] = NULL;
|
||||
host_addr = *(struct in_addr *)addr;
|
||||
if (af == AF_INET && (_res.options & RES_USE_INET6)) {
|
||||
_map_v4v6_address((char*)host_addr, (char*)host_addr);
|
||||
hp->h_addrtype = AF_INET6;
|
||||
hp->h_length = IN6ADDRSZ;
|
||||
}
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return (hp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@
|
|||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: gethostbyht.c,v 1.3 1996/01/13 09:03:45 peter Exp $";
|
||||
static char rcsid[] = "$Id: gethostbyht.c,v 1.4 1996/07/12 18:54:34 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -65,6 +65,8 @@ static char rcsid[] = "$Id: gethostbyht.c,v 1.3 1996/01/13 09:03:45 peter Exp $"
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <arpa/nameser.h> /* XXX */
|
||||
#include <resolv.h> /* XXX */
|
||||
|
||||
#define MAXALIASES 35
|
||||
|
||||
|
|
@ -72,7 +74,7 @@ static struct hostent host;
|
|||
static char *host_aliases[MAXALIASES];
|
||||
static char hostbuf[BUFSIZ+1];
|
||||
static FILE *hostf = NULL;
|
||||
static struct in_addr host_addr;
|
||||
static u_char host_addr[16]; /* IPv4 or IPv6 */
|
||||
static char *h_addr_ptrs[2];
|
||||
static int stayopen = 0;
|
||||
|
||||
|
|
@ -101,12 +103,13 @@ gethostent()
|
|||
{
|
||||
char *p;
|
||||
register char *cp, **q;
|
||||
int af, len;
|
||||
|
||||
if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
again:
|
||||
again:
|
||||
if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) {
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return (NULL);
|
||||
|
|
@ -119,23 +122,32 @@ again:
|
|||
if (!(cp = strpbrk(p, " \t")))
|
||||
goto again;
|
||||
*cp++ = '\0';
|
||||
/* THIS STUFF IS INTERNET SPECIFIC */
|
||||
if (!inet_aton(p, &host_addr))
|
||||
if ((_res.options & RES_USE_INET6) &&
|
||||
inet_pton(AF_INET6, p, host_addr) > 0) {
|
||||
af = AF_INET6;
|
||||
len = IN6ADDRSZ;
|
||||
} else if (inet_pton(AF_INET, p, host_addr) > 0) {
|
||||
if (_res.options & RES_USE_INET6) {
|
||||
_map_v4v6_address((char*)host_addr, (char*)host_addr);
|
||||
af = AF_INET6;
|
||||
len = IN6ADDRSZ;
|
||||
} else {
|
||||
af = AF_INET;
|
||||
len = INADDRSZ;
|
||||
}
|
||||
} else {
|
||||
goto again;
|
||||
h_addr_ptrs[0] = (char *)&host_addr;
|
||||
}
|
||||
h_addr_ptrs[0] = (char *)host_addr;
|
||||
h_addr_ptrs[1] = NULL;
|
||||
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
|
||||
host.h_addr_list = h_addr_ptrs;
|
||||
#else
|
||||
host.h_addr = h_addr_ptrs[0];
|
||||
#endif
|
||||
host.h_length = sizeof(u_int32_t);
|
||||
host.h_addrtype = AF_INET;
|
||||
host.h_length = len;
|
||||
host.h_addrtype = af;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
host.h_name = cp;
|
||||
q = host.h_aliases = host_aliases;
|
||||
if ( (cp = strpbrk(cp, " \t")) )
|
||||
if (cp = strpbrk(cp, " \t"))
|
||||
*cp++ = '\0';
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
|
|
@ -144,23 +156,32 @@ again:
|
|||
}
|
||||
if (q < &host_aliases[MAXALIASES - 1])
|
||||
*q++ = cp;
|
||||
if ( (cp = strpbrk(cp, " \t")) )
|
||||
if (cp = strpbrk(cp, " \t"))
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*q = NULL;
|
||||
if (_res.options & RES_USE_INET6) {
|
||||
char *bp = hostbuf;
|
||||
int buflen = sizeof hostbuf;
|
||||
|
||||
_map_v4v6_hostent(&host, &bp, &buflen);
|
||||
}
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return (&host);
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbyhtname(name)
|
||||
_gethostbyhtname2(name, af)
|
||||
char *name;
|
||||
int af;
|
||||
{
|
||||
register struct hostent *p;
|
||||
register char **cp;
|
||||
|
||||
sethostent(0);
|
||||
while ( (p = gethostent()) ) {
|
||||
if (p->h_addrtype != af)
|
||||
continue;
|
||||
if (strcasecmp(p->h_name, name) == 0)
|
||||
break;
|
||||
for (cp = p->h_aliases; *cp != 0; cp++)
|
||||
|
|
@ -173,15 +194,15 @@ found:
|
|||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbyhtaddr(addr, len, type)
|
||||
_gethostbyhtaddr(addr, len, af)
|
||||
const char *addr;
|
||||
int len, type;
|
||||
int len, af;
|
||||
{
|
||||
register struct hostent *p;
|
||||
|
||||
sethostent(0);
|
||||
while ( (p = gethostent()) )
|
||||
if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
|
||||
if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
|
||||
break;
|
||||
endhostent();
|
||||
return (p);
|
||||
|
|
|
|||
|
|
@ -1,249 +0,0 @@
|
|||
.\" Copyright (c) 1983, 1987, 1991, 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.
|
||||
.\"
|
||||
.\" @(#)gethostbyname.3 8.2 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt GETHOSTBYNAME 3
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm gethostbyname ,
|
||||
.Nm gethostbyaddr ,
|
||||
.Nm gethostent ,
|
||||
.Nm sethostent ,
|
||||
.Nm endhostent ,
|
||||
.Nm herror
|
||||
.Nd get network host entry
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <netdb.h>
|
||||
.Fd extern struct h_errno;
|
||||
.Ft struct hostent *
|
||||
.Fn gethostbyname "char *name"
|
||||
.Ft struct hostent *
|
||||
.Fn gethostbyaddr "char *addr" "int len" "int type"
|
||||
.Ft struct hostent *
|
||||
.Fn gethostent void
|
||||
.Fn sethostent "int stayopen"
|
||||
.Fn endhostent void
|
||||
.Fn herror "char *string"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn gethostbyname
|
||||
and
|
||||
.Fn gethostbyaddr
|
||||
functions
|
||||
each return a pointer to an object with the
|
||||
following structure describing an internet host
|
||||
referenced by name or by address, respectively.
|
||||
This structure contains either the information obtained from the name server,
|
||||
.Xr named 8 ,
|
||||
or broken-out fields from a line in
|
||||
.Pa /etc/hosts .
|
||||
If the local name server is not running these routines do a lookup in
|
||||
.Pa /etc/hosts .
|
||||
.Bd -literal
|
||||
struct hostent {
|
||||
char *h_name; /* official name of host */
|
||||
char **h_aliases; /* alias list */
|
||||
int h_addrtype; /* host address type */
|
||||
int h_length; /* length of address */
|
||||
char **h_addr_list; /* list of addresses from name server */
|
||||
};
|
||||
#define h_addr h_addr_list[0] /* address, for backward compatibility */
|
||||
.Ed
|
||||
.Pp
|
||||
The members of this structure are:
|
||||
.Bl -tag -width h_addr_list
|
||||
.It Fa h_name
|
||||
Official name of the host.
|
||||
.It Fa h_aliases
|
||||
A zero terminated array of alternate names for the host.
|
||||
.It Fa h_addrtype
|
||||
The type of address being returned; currently always
|
||||
.Dv AF_INET .
|
||||
.It Fa h_length
|
||||
The length, in bytes, of the address.
|
||||
.It Fa h_addr_list
|
||||
A zero terminated array of network addresses for the host.
|
||||
Host addresses are returned in network byte order.
|
||||
.It Fa h_addr
|
||||
The first address in
|
||||
.Fa h_addr_list ;
|
||||
this is for backward compatibility.
|
||||
.Pp
|
||||
When using the nameserver,
|
||||
.Fn gethostbyname
|
||||
will search for the named host in the current domain and its parents
|
||||
unless the name ends in a dot.
|
||||
If the name contains no dot, and if the environment variable
|
||||
.Dq Ev HOSTALIASES
|
||||
contains the name of an alias file, the alias file will first be searched
|
||||
for an alias matching the input name.
|
||||
See
|
||||
.Xr hostname 7
|
||||
for the domain search procedure and the alias file format.
|
||||
.Pp
|
||||
The
|
||||
.Fn sethostent
|
||||
function
|
||||
may be used to request the use of a connected
|
||||
.Tn TCP
|
||||
socket for queries.
|
||||
If the
|
||||
.Fa stayopen
|
||||
flag is non-zero,
|
||||
this sets the option to send all queries to the name server using
|
||||
.Tn TCP
|
||||
and to retain the connection after each call to
|
||||
.Fn gethostbyname
|
||||
or
|
||||
.Fn gethostbyaddr .
|
||||
Otherwise, queries are performed using
|
||||
.Tn UDP
|
||||
datagrams.
|
||||
.Pp
|
||||
The
|
||||
.Fn endhostent
|
||||
function
|
||||
closes the
|
||||
.Tn TCP
|
||||
connection.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/hosts -compact
|
||||
.It Pa /etc/hosts
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
Error return status from
|
||||
.Fn gethostbyname
|
||||
and
|
||||
.Fn gethostbyaddr
|
||||
is indicated by return of a null pointer.
|
||||
The external integer
|
||||
.Va h_errno
|
||||
may then be checked to see whether this is a temporary failure
|
||||
or an invalid or unknown host.
|
||||
The routine
|
||||
.Fn herror
|
||||
can be used to print an error message describing the failure.
|
||||
If its argument
|
||||
.Fa string
|
||||
is
|
||||
.Pf non Dv -NULL ,
|
||||
it is printed, followed by a colon and a space.
|
||||
The error message is printed with a trailing newline.
|
||||
.Pp
|
||||
The variable
|
||||
.Va h_errno
|
||||
can have the following values:
|
||||
.Bl -tag -width HOST_NOT_FOUND
|
||||
.It Dv HOST_NOT_FOUND
|
||||
No such host is known.
|
||||
.It Dv TRY_AGAIN
|
||||
This is usually a temporary error
|
||||
and means that the local server did not receive
|
||||
a response from an authoritative server.
|
||||
A retry at some later time may succeed.
|
||||
.It Dv NO_RECOVERY
|
||||
Some unexpected server failure was encountered.
|
||||
This is a non-recoverable error.
|
||||
.It Dv NO_DATA
|
||||
The requested name is valid but does not have an IP address;
|
||||
this is not a temporary error.
|
||||
This means that the name is known to the name server but there is no address
|
||||
associated with this name.
|
||||
Another type of request to the name server using this domain name
|
||||
will result in an answer;
|
||||
for example, a mail-forwarder may be registered for this domain.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr resolver 3 ,
|
||||
.Xr hosts 5 ,
|
||||
.Xr hostname 7 ,
|
||||
.Xr named 8
|
||||
.Sh CAVEAT
|
||||
The
|
||||
.Fn gethostent
|
||||
function
|
||||
is defined, and
|
||||
.Fn sethostent
|
||||
and
|
||||
.Fn endhostent
|
||||
are redefined,
|
||||
when
|
||||
.Xr libc 3
|
||||
is built to use only the routines to lookup in
|
||||
.Pa /etc/hosts
|
||||
and not the name server.
|
||||
.Pp
|
||||
The
|
||||
.Fn gethostent
|
||||
function
|
||||
reads the next line of
|
||||
.Pa /etc/hosts ,
|
||||
opening the file if necessary.
|
||||
.Pp
|
||||
The
|
||||
.Fn sethostent
|
||||
function
|
||||
opens and/or rewinds the file
|
||||
.Pa /etc/hosts .
|
||||
If the
|
||||
.Fa stayopen
|
||||
argument is non-zero,
|
||||
the file will not be closed after each call to
|
||||
.Fn gethostbyname
|
||||
or
|
||||
.Fn gethostbyaddr .
|
||||
.Pp
|
||||
The
|
||||
.Fn endhostent
|
||||
function
|
||||
closes the file.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn herror
|
||||
function appeared in
|
||||
.Bx 4.3 .
|
||||
The
|
||||
.Fn endhostent ,
|
||||
.Fn gethostbyaddr ,
|
||||
.Fn gethostbyname ,
|
||||
.Fn gethostent ,
|
||||
and
|
||||
.Fn sethostent
|
||||
functions appeared in
|
||||
.Bx 4.2 .
|
||||
.Sh BUGS
|
||||
These functions use static data storage;
|
||||
if the data is needed for future use, it should be
|
||||
copied before any subsequent calls overwrite it.
|
||||
Only the Internet
|
||||
address format is currently understood.
|
||||
|
|
@ -24,8 +24,8 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)$Id: gethostbynis.c,v 1.2 1996/03/16 21:25:58 wpaul Exp $";
|
||||
static char rcsid[] = "$Id: gethostbynis.c,v 1.2 1996/03/16 21:25:58 wpaul Exp $";
|
||||
static char sccsid[] = "@(#)$Id: gethostbynis.c,v 1.3 1996/07/12 18:54:35 jkh Exp $";
|
||||
static char rcsid[] = "$Id: gethostbynis.c,v 1.3 1996/07/12 18:54:35 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -54,8 +54,10 @@ static char *host_addrs[2];
|
|||
#endif /* YP */
|
||||
|
||||
static struct hostent *
|
||||
_gethostbynis(name, map)
|
||||
char *name, *map;
|
||||
_gethostbynis(name, map, af)
|
||||
const char *name;
|
||||
char *map;
|
||||
int af;
|
||||
{
|
||||
#ifdef YP
|
||||
register char *cp, **q;
|
||||
|
|
@ -65,6 +67,15 @@ _gethostbynis(name, map)
|
|||
static char *domain = (char *)NULL;
|
||||
static char ypbuf[YPMAXRECORD];
|
||||
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
break;
|
||||
default:
|
||||
case AF_INET6:
|
||||
errno = EAFNOSUPPORT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (domain == (char *)NULL)
|
||||
if (yp_get_default_domain (&domain))
|
||||
return ((struct hostent *)NULL);
|
||||
|
|
@ -113,17 +124,18 @@ _gethostbynis(name, map)
|
|||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbynisname(name)
|
||||
char *name;
|
||||
_gethostbynisname(name, af)
|
||||
const char *name;
|
||||
int af;
|
||||
{
|
||||
return _gethostbynis(name, "hosts.byname");
|
||||
return _gethostbynis(name, "hosts.byname", af);
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
_gethostbynisaddr(addr, len, type)
|
||||
char *addr;
|
||||
_gethostbynisaddr(addr, len, af)
|
||||
const char *addr;
|
||||
int len;
|
||||
int type;
|
||||
int af;
|
||||
{
|
||||
return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr");
|
||||
return _gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.8 1996/07/12 18:54:36 jkh Exp $";
|
||||
static char rcsid[] = "$Id: gethostnamadr.c,v 1.8 1996/07/12 18:54:36 jkh Exp $";
|
||||
static char sccsid[] = "@(#)$Id: gethostnamadr.c,v 1.9 1996/08/20 08:20:21 julian Exp $";
|
||||
static char rcsid[] = "$Id: gethostnamadr.c,v 1.9 1996/08/20 08:20:21 julian Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -37,18 +37,8 @@ static char rcsid[] = "$Id: gethostnamadr.c,v 1.8 1996/07/12 18:54:36 jkh Exp $"
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void _sethosthtent __P(( int ));
|
||||
extern void _endhosthtent __P(( void ));
|
||||
extern void _sethostdnsent __P(( int ));
|
||||
extern void _endhostdnsent __P(( void ));
|
||||
|
||||
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));
|
||||
#include <arpa/nameser.h> /* XXX hack for _res */
|
||||
#include <resolv.h> /* XXX hack for _res */
|
||||
|
||||
#define _PATH_HOSTCONF "/etc/host.conf"
|
||||
|
||||
|
|
@ -130,6 +120,19 @@ init_services()
|
|||
|
||||
struct hostent *
|
||||
gethostbyname(const char *name)
|
||||
{
|
||||
struct hostent *hp;
|
||||
|
||||
if (_res.options & RES_USE_INET6) { /* XXX */
|
||||
hp = gethostbyname2(name, AF_INET6); /* XXX */
|
||||
if (hp) /* XXX */
|
||||
return (hp); /* XXX */
|
||||
} /* XXX */
|
||||
return (gethostbyname2(name, AF_INET));
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
gethostbyname2(const char *name, int type)
|
||||
{
|
||||
struct hostent *hp = 0;
|
||||
int nserv = 0;
|
||||
|
|
@ -142,13 +145,13 @@ gethostbyname(const char *name)
|
|||
case SERVICE_NONE:
|
||||
return NULL;
|
||||
case SERVICE_HOSTS:
|
||||
hp = _gethostbyhtname(name);
|
||||
hp = _gethostbyhtname(name, type);
|
||||
break;
|
||||
case SERVICE_BIND:
|
||||
hp = _gethostbydnsname(name);
|
||||
hp = _gethostbydnsname(name, type);
|
||||
break;
|
||||
case SERVICE_NIS:
|
||||
hp = _gethostbynisname(name);
|
||||
hp = _gethostbynisname(name, type);
|
||||
break;
|
||||
}
|
||||
nserv++;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: getnetbydns.c,v 1.5 1996/01/13 09:03:51 peter Exp $";
|
||||
static char rcsid[] = "$Id: getnetbydns.c,v 1.6 1996/07/12 18:54:37 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -156,7 +156,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
|
|||
haveanswer = 0;
|
||||
while (--ancount >= 0 && cp < eom) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
if (n < 0)
|
||||
if ((n < 0) || !res_dnok(bp))
|
||||
break;
|
||||
cp += n;
|
||||
ans[0] = '\0';
|
||||
|
|
@ -167,7 +167,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
|
|||
GETSHORT(n, cp);
|
||||
if (class == C_IN && type == T_PTR) {
|
||||
n = dn_expand(answer->buf, eom, cp, bp, buflen);
|
||||
if (n < 0) {
|
||||
if ((n < 0) || !res_hnok(bp)) {
|
||||
cp += n;
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
|
|||
|
||||
struct netent *
|
||||
_getnetbydnsaddr(net, net_type)
|
||||
register long net;
|
||||
register unsigned long net;
|
||||
register int net_type;
|
||||
{
|
||||
unsigned int netbr[4];
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ found:
|
|||
|
||||
struct netent *
|
||||
_getnetbyhtaddr(net, type)
|
||||
register long net;
|
||||
register unsigned long net;
|
||||
register int type;
|
||||
{
|
||||
register struct netent *p;
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)$Id: getnetbynis.c,v 1.4 1995/10/22 14:39:06 phk Exp $";
|
||||
static char rcsid[] = "$Id: getnetbynis.c,v 1.4 1995/10/22 14:39:06 phk Exp $";
|
||||
static char sccsid[] = "@(#)$Id: getnetbynis.c,v 1.5 1996/03/23 22:16:22 wpaul Exp $";
|
||||
static char rcsid[] = "$Id: getnetbynis.c,v 1.5 1996/03/23 22:16:22 wpaul Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -53,8 +53,10 @@ static char *host_aliases[MAXALIASES];
|
|||
#endif /* YP */
|
||||
|
||||
static struct netent *
|
||||
_getnetbynis(name, map)
|
||||
char *name, *map;
|
||||
_getnetbynis(name, map, af)
|
||||
const char *name;
|
||||
char *map;
|
||||
int af;
|
||||
{
|
||||
#ifdef YP
|
||||
register char *cp, **q;
|
||||
|
|
@ -64,6 +66,15 @@ _getnetbynis(name, map)
|
|||
static char *domain = (char *)NULL;
|
||||
static char ypbuf[YPMAXRECORD];
|
||||
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
break;
|
||||
default:
|
||||
case AF_INET6:
|
||||
errno = EAFNOSUPPORT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (domain == (char *)NULL)
|
||||
if (yp_get_default_domain (&domain))
|
||||
return (NULL);
|
||||
|
|
@ -112,15 +123,15 @@ _getnetbynis(name, map)
|
|||
|
||||
struct netent *
|
||||
_getnetbynisname(name)
|
||||
char *name;
|
||||
const char *name;
|
||||
{
|
||||
return _getnetbynis(name, "networks.byname");
|
||||
}
|
||||
|
||||
struct netent *
|
||||
_getnetbynisaddr(addr, type)
|
||||
long addr;
|
||||
int type;
|
||||
_getnetbynisaddr(addr, af)
|
||||
unsigned long addr;
|
||||
int af;
|
||||
{
|
||||
char *str, *cp;
|
||||
unsigned long net2;
|
||||
|
|
@ -128,8 +139,10 @@ _getnetbynisaddr(addr, type)
|
|||
unsigned int netbr[4];
|
||||
char buf[MAXDNAME];
|
||||
|
||||
if (type != AF_INET)
|
||||
if (af != AF_INET) {
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
for (nn = 4, net2 = addr; net2; net2 >>= 8) {
|
||||
netbr[--nn] = net2 & 0xff;
|
||||
|
|
@ -159,5 +172,5 @@ _getnetbynisaddr(addr, type)
|
|||
cp = str + (strlen(str) - 2);
|
||||
}
|
||||
|
||||
return _getnetbynis(str, "networks.byaddr");
|
||||
return _getnetbynis(str, "networks.byaddr", af);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,151 +0,0 @@
|
|||
.\" Copyright (c) 1983, 1991, 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.
|
||||
.\"
|
||||
.\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt GETNETENT 3
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm getnetent ,
|
||||
.Nm getnetbyaddr ,
|
||||
.Nm getnetbyname ,
|
||||
.Nm setnetent ,
|
||||
.Nm endnetent
|
||||
.Nd get network entry
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <netdb.h>
|
||||
.Ft struct netent *
|
||||
.Fn getnetent
|
||||
.Ft struct netent *
|
||||
.Fn getnetbyname "char *name"
|
||||
.Ft struct netent *
|
||||
.Fn getnetbyaddr "long net" "int type"
|
||||
.Fn setnetent "int stayopen"
|
||||
.Fn endnetent
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn getnetent ,
|
||||
.Fn getnetbyname ,
|
||||
and
|
||||
.Fn getnetbyaddr
|
||||
functions
|
||||
each return a pointer to an object with the
|
||||
following structure
|
||||
containing the broken-out
|
||||
fields of a line in the network data base,
|
||||
.Pa /etc/networks .
|
||||
.Bd -literal -offset indent
|
||||
struct netent {
|
||||
char *n_name; /* official name of net */
|
||||
char **n_aliases; /* alias list */
|
||||
int n_addrtype; /* net number type */
|
||||
unsigned long n_net; /* net number */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The members of this structure are:
|
||||
.Bl -tag -width n_addrtype
|
||||
.It Fa n_name
|
||||
The official name of the network.
|
||||
.It Fa n_aliases
|
||||
A zero terminated list of alternate names for the network.
|
||||
.It Fa n_addrtype
|
||||
The type of the network number returned; currently only AF_INET.
|
||||
.It Fa n_net
|
||||
The network number. Network numbers are returned in machine byte
|
||||
order.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn getnetent
|
||||
function
|
||||
reads the next line of the file, opening the file if necessary.
|
||||
.Pp
|
||||
The
|
||||
.Fn setnetent
|
||||
function
|
||||
opens and rewinds the file. If the
|
||||
.Fa stayopen
|
||||
flag is non-zero,
|
||||
the net data base will not be closed after each call to
|
||||
.Fn getnetbyname
|
||||
or
|
||||
.Fn getnetbyaddr .
|
||||
.Pp
|
||||
The
|
||||
.Fn endnetent
|
||||
function
|
||||
closes the file.
|
||||
.Pp
|
||||
The
|
||||
.Fn getnetbyname
|
||||
function
|
||||
and
|
||||
.Fn getnetbyaddr
|
||||
sequentially search from the beginning
|
||||
of the file until a matching
|
||||
net name or
|
||||
net address and type is found,
|
||||
or until
|
||||
.Dv EOF
|
||||
is encountered.
|
||||
Network numbers are supplied in host order.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /etc/networks -compact
|
||||
.It Pa /etc/networks
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
Null pointer
|
||||
(0) returned on
|
||||
.Dv EOF
|
||||
or error.
|
||||
.Sh SEE ALSO
|
||||
.Xr networks 5
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn getnetent ,
|
||||
.Fn getnetbyaddr ,
|
||||
.Fn getnetbyname ,
|
||||
.Fn setnetent ,
|
||||
and
|
||||
.Fn endnetent
|
||||
functions appeared in
|
||||
.Bx 4.2 .
|
||||
.Sh BUGS
|
||||
The data space used by
|
||||
these functions is static; if future use requires the data, it should be
|
||||
copied before any subsequent calls to these functions overwrite it.
|
||||
Only Internet network
|
||||
numbers are currently understood.
|
||||
Expecting network numbers to fit
|
||||
in no more than 32 bits is probably
|
||||
naive.
|
||||
|
|
@ -24,8 +24,8 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)$Id: getnetnamadr.c,v 1.4 1995/05/30 05:40:48 rgrimes Exp $";
|
||||
static char rcsid[] = "$Id: getnetnamadr.c,v 1.4 1995/05/30 05:40:48 rgrimes Exp $";
|
||||
static char sccsid[] = "@(#)$Id: getnetnamadr.c,v 1.5 1996/07/12 18:54:40 jkh Exp $";
|
||||
static char rcsid[] = "$Id: getnetnamadr.c,v 1.5 1996/07/12 18:54:40 jkh Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
|
|
@ -38,20 +38,6 @@ static char rcsid[] = "$Id: getnetnamadr.c,v 1.4 1995/05/30 05:40:48 rgrimes Exp
|
|||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
extern void _setnetent __P(( int ));
|
||||
extern void _endnetent __P(( void ));
|
||||
extern void _setnethtent __P(( int ));
|
||||
extern void _endnethtent __P(( void ));
|
||||
extern void _setnetdnsent __P(( int ));
|
||||
extern void _endnetdnsent __P(( void ));
|
||||
|
||||
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));
|
||||
|
||||
#ifndef _PATH_NETCONF
|
||||
#define _PATH_NETCONF "/etc/host.conf"
|
||||
#endif
|
||||
|
|
@ -160,9 +146,9 @@ getnetbyname(const char *name)
|
|||
}
|
||||
|
||||
struct netent *
|
||||
getnetbyaddr(addr, type)
|
||||
getnetbyaddr(addr, af)
|
||||
long addr;
|
||||
int type;
|
||||
int af;
|
||||
{
|
||||
struct netent *hp = 0;
|
||||
int nserv = 0;
|
||||
|
|
@ -175,13 +161,13 @@ getnetbyaddr(addr, type)
|
|||
case SERVICE_NONE:
|
||||
return 0;
|
||||
case SERVICE_TABLE:
|
||||
hp = _getnetbyhtaddr(addr, type);
|
||||
hp = _getnetbyhtaddr(addr, af);
|
||||
break;
|
||||
case SERVICE_BIND:
|
||||
hp = _getnetbydnsaddr(addr, type);
|
||||
hp = _getnetbydnsaddr(addr, af);
|
||||
break;
|
||||
case SERVICE_NIS:
|
||||
hp = _getnetbynisaddr(addr, type);
|
||||
hp = _getnetbynisaddr(addr, af);
|
||||
break;
|
||||
}
|
||||
nserv++;
|
||||
|
|
|
|||
190
lib/libc/net/inet_ntop.c
Normal file
190
lib/libc/net/inet_ntop.c
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id: inet_ntop.c,v 8.7 1996/08/05 08:41:18 vixie Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SPRINTF(x) ((size_t)sprintf x)
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static const char *inet_ntop4 __P((const u_char *src, char *dst, size_t size));
|
||||
static const char *inet_ntop6 __P((const u_char *src, char *dst, size_t size));
|
||||
|
||||
/* char *
|
||||
* inet_ntop(af, src, dst, size)
|
||||
* convert a network format address to presentation format.
|
||||
* return:
|
||||
* pointer to presentation format address (`dst'), or NULL (see errno).
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
const char *
|
||||
inet_ntop(af, src, dst, size)
|
||||
int af;
|
||||
const void *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_ntop4(src, dst, size));
|
||||
case AF_INET6:
|
||||
return (inet_ntop6(src, dst, size));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop4(src, dst, size)
|
||||
* format an IPv4 address, more or less like inet_ntoa()
|
||||
* return:
|
||||
* `dst' (as a const)
|
||||
* notes:
|
||||
* (1) uses no statics
|
||||
* (2) takes a u_char* not an in_addr as input
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop4(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
static const char fmt[] = "%u.%u.%u.%u";
|
||||
char tmp[sizeof "255.255.255.255"];
|
||||
|
||||
if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
|
||||
/* const char *
|
||||
* inet_ntop6(src, dst, size)
|
||||
* convert IPv6 binary address into presentation (printable) format
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static const char *
|
||||
inet_ntop6(src, dst, size)
|
||||
const u_char *src;
|
||||
char *dst;
|
||||
size_t size;
|
||||
{
|
||||
/*
|
||||
* Note that int32_t and int16_t need only be "at least" large enough
|
||||
* to contain a value of the specified size. On some systems, like
|
||||
* Crays, there is no such thing as an integer variable with 16 bits.
|
||||
* Keep this in mind if you think this function should have been coded
|
||||
* to use pointer overlays. All the world's not a VAX.
|
||||
*/
|
||||
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
|
||||
struct { int base, len; } best, cur;
|
||||
u_int words[IN6ADDRSZ / INT16SZ];
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Preprocess:
|
||||
* Copy the input (bytewise) array into a wordwise array.
|
||||
* Find the longest run of 0x00's in src[] for :: shorthanding.
|
||||
*/
|
||||
memset(words, '\0', sizeof words);
|
||||
for (i = 0; i < IN6ADDRSZ; i++)
|
||||
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
|
||||
best.base = -1;
|
||||
cur.base = -1;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
if (words[i] == 0) {
|
||||
if (cur.base == -1)
|
||||
cur.base = i, cur.len = 1;
|
||||
else
|
||||
cur.len++;
|
||||
} else {
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
cur.base = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cur.base != -1) {
|
||||
if (best.base == -1 || cur.len > best.len)
|
||||
best = cur;
|
||||
}
|
||||
if (best.base != -1 && best.len < 2)
|
||||
best.base = -1;
|
||||
|
||||
/*
|
||||
* Format the result.
|
||||
*/
|
||||
tp = tmp;
|
||||
for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) {
|
||||
/* Are we inside the best run of 0x00's? */
|
||||
if (best.base != -1 && i >= best.base &&
|
||||
i < (best.base + best.len)) {
|
||||
if (i == best.base)
|
||||
*tp++ = ':';
|
||||
continue;
|
||||
}
|
||||
/* Are we following an initial run of 0x00s or any real hex? */
|
||||
if (i != 0)
|
||||
*tp++ = ':';
|
||||
/* Is this address an encapsulated IPv4? */
|
||||
if (i == 6 && best.base == 0 &&
|
||||
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
|
||||
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
|
||||
return (NULL);
|
||||
tp += strlen(tp);
|
||||
break;
|
||||
}
|
||||
tp += SPRINTF((tp, "%x", words[i]));
|
||||
}
|
||||
/* Was it a trailing run of 0x00's? */
|
||||
if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
|
||||
*tp++ = ':';
|
||||
*tp++ = '\0';
|
||||
|
||||
/*
|
||||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = ENOSPC;
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
return (dst);
|
||||
}
|
||||
214
lib/libc/net/inet_pton.c
Normal file
214
lib/libc/net/inet_pton.c
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id: inet_pton.c,v 8.7 1996/08/05 08:31:35 vixie Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/*
|
||||
* WARNING: Don't even consider trying to compile this on a system where
|
||||
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
|
||||
*/
|
||||
|
||||
static int inet_pton4 __P((const char *src, u_char *dst));
|
||||
static int inet_pton6 __P((const char *src, u_char *dst));
|
||||
|
||||
/* int
|
||||
* inet_pton(af, src, dst)
|
||||
* convert from presentation format (which usually means ASCII printable)
|
||||
* to network format (which is usually some kind of binary format).
|
||||
* return:
|
||||
* 1 if the address was valid for the specified address family
|
||||
* 0 if the address wasn't valid (`dst' is untouched in this case)
|
||||
* -1 if some other error occurred (`dst' is untouched in this case, too)
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(af, src, dst)
|
||||
int af;
|
||||
const char *src;
|
||||
void *dst;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (inet_pton4(src, dst));
|
||||
case AF_INET6:
|
||||
return (inet_pton6(src, dst));
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton4(src, dst)
|
||||
* like inet_aton() but without all the hexadecimal and shorthand.
|
||||
* return:
|
||||
* 1 if `src' is a valid dotted quad, else 0.
|
||||
* notice:
|
||||
* does not touch `dst' unless it's returning 1.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
u_char tmp[INADDRSZ], *tp;
|
||||
|
||||
saw_digit = 0;
|
||||
octets = 0;
|
||||
*(tp = tmp) = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr(digits, ch)) != NULL) {
|
||||
u_int new = *tp * 10 + (pch - digits);
|
||||
|
||||
if (new > 255)
|
||||
return (0);
|
||||
*tp = new;
|
||||
if (! saw_digit) {
|
||||
if (++octets > 4)
|
||||
return (0);
|
||||
saw_digit = 1;
|
||||
}
|
||||
} else if (ch == '.' && saw_digit) {
|
||||
if (octets == 4)
|
||||
return (0);
|
||||
*++tp = 0;
|
||||
saw_digit = 0;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
if (octets < 4)
|
||||
return (0);
|
||||
|
||||
memcpy(dst, tmp, INADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* int
|
||||
* inet_pton6(src, dst)
|
||||
* convert presentation level address to network order binary form.
|
||||
* return:
|
||||
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
|
||||
* notice:
|
||||
* (1) does not touch `dst' unless it's returning 1.
|
||||
* (2) :: in a full address is silently ignored.
|
||||
* credit:
|
||||
* inspired by Mark Andrews.
|
||||
* author:
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
u_char *dst;
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
|
||||
const char *xdigits, *curtok;
|
||||
int ch, saw_xdigit;
|
||||
u_int val;
|
||||
|
||||
memset((tp = tmp), '\0', IN6ADDRSZ);
|
||||
endp = tp + IN6ADDRSZ;
|
||||
colonp = NULL;
|
||||
/* Leading :: requires some special handling. */
|
||||
if (*src == ':')
|
||||
if (*++src != ':')
|
||||
return (0);
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
while ((ch = *src++) != '\0') {
|
||||
const char *pch;
|
||||
|
||||
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
|
||||
pch = strchr((xdigits = xdigits_u), ch);
|
||||
if (pch != NULL) {
|
||||
val <<= 4;
|
||||
val |= (pch - xdigits);
|
||||
if (val > 0xffff)
|
||||
return (0);
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
if (ch == ':') {
|
||||
curtok = src;
|
||||
if (!saw_xdigit) {
|
||||
if (colonp)
|
||||
return (0);
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
|
||||
inet_pton4(curtok, tp) > 0) {
|
||||
tp += INADDRSZ;
|
||||
saw_xdigit = 0;
|
||||
break; /* '\0' was seen by inet_pton4(). */
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
if (saw_xdigit) {
|
||||
if (tp + INT16SZ > endp)
|
||||
return (0);
|
||||
*tp++ = (u_char) (val >> 8) & 0xff;
|
||||
*tp++ = (u_char) val & 0xff;
|
||||
}
|
||||
if (colonp != NULL) {
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
const int n = tp - colonp;
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i++) {
|
||||
endp[- i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
if (tp != endp)
|
||||
return (0);
|
||||
memcpy(dst, tmp, IN6ADDRSZ);
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* ++Copyright++ 1995
|
||||
* ++Copyright++ 1985, 1988, 1993
|
||||
* -
|
||||
* Copyright (c) 1995
|
||||
* 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
|
||||
|
|
@ -54,61 +54,74 @@
|
|||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id: res_data.c,v 8.1 1995/12/22 10:21:29 vixie Exp $";
|
||||
static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: gethnamaddr.c,v 8.17 1996/08/05 08:31:35 vixie Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#if defined(BSD) && (BSD >= 199103)
|
||||
# include <unistd.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#else
|
||||
# include "../conf/portability.h"
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <syslog.h>
|
||||
|
||||
const char *_res_opcodes[] = {
|
||||
"QUERY",
|
||||
"IQUERY",
|
||||
"CQUERYM",
|
||||
"CQUERYU", /* experimental */
|
||||
"NOTIFY", /* experimental */
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"UPDATEA",
|
||||
"UPDATED",
|
||||
"UPDATEDA",
|
||||
"UPDATEM",
|
||||
"UPDATEMA",
|
||||
"ZONEINIT",
|
||||
"ZONEREF",
|
||||
};
|
||||
typedef union {
|
||||
int32_t al;
|
||||
char ac;
|
||||
} align;
|
||||
|
||||
const char *_res_resultcodes[] = {
|
||||
"NOERROR",
|
||||
"FORMERR",
|
||||
"SERVFAIL",
|
||||
"NXDOMAIN",
|
||||
"NOTIMP",
|
||||
"REFUSED",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"NOCHANGE",
|
||||
};
|
||||
void
|
||||
_map_v4v6_address(src, dst)
|
||||
const char *src;
|
||||
char *dst;
|
||||
{
|
||||
u_char *p = (u_char *)dst;
|
||||
char tmp[INADDRSZ];
|
||||
int i;
|
||||
|
||||
/* Stash a temporary copy so our caller can update in place. */
|
||||
bcopy(src, tmp, INADDRSZ);
|
||||
/* Mark this ipv6 addr as a mapped ipv4. */
|
||||
for (i = 0; i < 10; i++)
|
||||
*p++ = 0x00;
|
||||
*p++ = 0xff;
|
||||
*p++ = 0xff;
|
||||
/* Retrieve the saved copy and we're done. */
|
||||
bcopy(tmp, (void*)p, INADDRSZ);
|
||||
}
|
||||
|
||||
void
|
||||
_map_v4v6_hostent(hp, bpp, lenp)
|
||||
struct hostent *hp;
|
||||
char **bpp;
|
||||
int *lenp;
|
||||
{
|
||||
char **ap;
|
||||
|
||||
if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
|
||||
return;
|
||||
hp->h_addrtype = AF_INET6;
|
||||
hp->h_length = IN6ADDRSZ;
|
||||
for (ap = hp->h_addr_list; *ap; ap++) {
|
||||
int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
|
||||
|
||||
if (*lenp < (i + IN6ADDRSZ)) {
|
||||
/* Out of memory. Truncate address list here. XXX */
|
||||
*ap = NULL;
|
||||
return;
|
||||
}
|
||||
*bpp += i;
|
||||
*lenp -= i;
|
||||
_map_v4v6_address(*ap, *bpp);
|
||||
*ap = *bpp;
|
||||
*bpp += IN6ADDRSZ;
|
||||
*lenp -= IN6ADDRSZ;
|
||||
}
|
||||
}
|
||||
103
lib/libc/net/nsap_addr.c
Normal file
103
lib/libc/net/nsap_addr.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char rcsid[] = "$Id: nsap_addr.c,v 8.3 1996/08/05 08:31:35 vixie Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <ctype.h>
|
||||
#include <resolv.h>
|
||||
|
||||
static char
|
||||
xtob(c)
|
||||
register int c;
|
||||
{
|
||||
return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
|
||||
}
|
||||
|
||||
u_int
|
||||
inet_nsap_addr(ascii, binary, maxlen)
|
||||
const char *ascii;
|
||||
u_char *binary;
|
||||
int maxlen;
|
||||
{
|
||||
register u_char c, nib;
|
||||
u_int len = 0;
|
||||
|
||||
while ((c = *ascii++) != '\0' && len < maxlen) {
|
||||
if (c == '.' || c == '+' || c == '/')
|
||||
continue;
|
||||
if (!isascii(c))
|
||||
return (0);
|
||||
if (islower(c))
|
||||
c = toupper(c);
|
||||
if (isxdigit(c)) {
|
||||
nib = xtob(c);
|
||||
if (c = *ascii++) {
|
||||
c = toupper(c);
|
||||
if (isxdigit(c)) {
|
||||
*binary++ = (nib << 4) | xtob(c);
|
||||
len++;
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
char *
|
||||
inet_nsap_ntoa(binlen, binary, ascii)
|
||||
int binlen;
|
||||
register const u_char *binary;
|
||||
register char *ascii;
|
||||
{
|
||||
register int nib;
|
||||
int i;
|
||||
static char tmpbuf[255*3];
|
||||
char *start;
|
||||
|
||||
if (ascii)
|
||||
start = ascii;
|
||||
else {
|
||||
ascii = tmpbuf;
|
||||
start = tmpbuf;
|
||||
}
|
||||
|
||||
if (binlen > 255)
|
||||
binlen = 255;
|
||||
|
||||
for (i = 0; i < binlen; i++) {
|
||||
nib = *binary >> 4;
|
||||
*ascii++ = nib + (nib < 10 ? '0' : '7');
|
||||
nib = *binary++ & 0x0f;
|
||||
*ascii++ = nib + (nib < 10 ? '0' : '7');
|
||||
if (((i % 2) == 0 && (i + 1) < binlen))
|
||||
*ascii++ = '.';
|
||||
}
|
||||
*ascii = '\0';
|
||||
return (start);
|
||||
}
|
||||
|
|
@ -1,378 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1985, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: res_comp.c,v 1.4 1996/01/07 09:14:54 peter Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <resolv.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#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.
|
||||
* 'msg' is a pointer to the begining of the message,
|
||||
* 'eomorig' points to the first location after the message,
|
||||
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
|
||||
* Return size of compressed name or -1 if there was an error.
|
||||
*/
|
||||
int
|
||||
dn_expand(msg, eomorig, comp_dn, exp_dn, length)
|
||||
const u_char *msg, *eomorig, *comp_dn;
|
||||
char *exp_dn;
|
||||
int length;
|
||||
{
|
||||
register const u_char *cp;
|
||||
register char *dn;
|
||||
register int n, c;
|
||||
char *eom;
|
||||
int len = -1, checked = 0;
|
||||
|
||||
dn = exp_dn;
|
||||
cp = comp_dn;
|
||||
eom = exp_dn + length;
|
||||
/*
|
||||
* fetch next label in domain name
|
||||
*/
|
||||
while ( (n = *cp++) ) {
|
||||
/*
|
||||
* Check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0:
|
||||
if (dn != exp_dn) {
|
||||
if (dn >= eom)
|
||||
return (-1);
|
||||
*dn++ = '.';
|
||||
}
|
||||
if (dn+n >= eom)
|
||||
return (-1);
|
||||
checked += n + 1;
|
||||
while (--n >= 0) {
|
||||
if (((c = *cp++) == '.') || (c == '\\')) {
|
||||
if (dn + n + 2 >= eom)
|
||||
return (-1);
|
||||
*dn++ = '\\';
|
||||
}
|
||||
*dn++ = c;
|
||||
if (cp >= eomorig) /* out of range */
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case INDIR_MASK:
|
||||
if (len < 0)
|
||||
len = cp - comp_dn + 1;
|
||||
cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
|
||||
if (cp < msg || cp >= eomorig) /* out of range */
|
||||
return (-1);
|
||||
checked += 2;
|
||||
/*
|
||||
* Check for loops in the compressed name;
|
||||
* if we've looked at the whole message,
|
||||
* there must be a loop.
|
||||
*/
|
||||
if (checked >= eomorig - msg)
|
||||
return (-1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (-1); /* flag error */
|
||||
}
|
||||
}
|
||||
*dn = '\0';
|
||||
for (dn = exp_dn; (c = *dn) != '\0'; dn++)
|
||||
if (isascii(c) && isspace(c))
|
||||
return (-1);
|
||||
if (len < 0)
|
||||
len = cp - comp_dn;
|
||||
return (len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compress domain name 'exp_dn' into 'comp_dn'.
|
||||
* Return the size of the compressed name or -1.
|
||||
* 'length' is the size of the array pointed to by 'comp_dn'.
|
||||
* 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
|
||||
* is a pointer to the beginning of the message. The list ends with NULL.
|
||||
* 'lastdnptr' is a pointer to the end of the arrary pointed to
|
||||
* by 'dnptrs'. Side effect is to update the list of pointers for
|
||||
* labels inserted into the message as we compress the name.
|
||||
* If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
|
||||
* is NULL, we don't update the list.
|
||||
*/
|
||||
int
|
||||
dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
|
||||
const char *exp_dn;
|
||||
u_char *comp_dn, **dnptrs, **lastdnptr;
|
||||
int length;
|
||||
{
|
||||
register u_char *cp, *dn;
|
||||
register int c, l;
|
||||
u_char **cpp, **lpp, *sp, *eob;
|
||||
u_char *msg;
|
||||
|
||||
dn = (u_char *)exp_dn;
|
||||
cp = comp_dn;
|
||||
eob = cp + length;
|
||||
lpp = cpp = NULL;
|
||||
if (dnptrs != NULL) {
|
||||
if ((msg = *dnptrs++) != NULL) {
|
||||
for (cpp = dnptrs; *cpp != NULL; cpp++)
|
||||
;
|
||||
lpp = cpp; /* end of list to search */
|
||||
}
|
||||
} else
|
||||
msg = NULL;
|
||||
for (c = *dn++; c != '\0'; ) {
|
||||
/* look to see if we can use pointers */
|
||||
if (msg != NULL) {
|
||||
if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
|
||||
if (cp+1 >= eob)
|
||||
return (-1);
|
||||
*cp++ = (l >> 8) | INDIR_MASK;
|
||||
*cp++ = l % 256;
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
/* not found, save it */
|
||||
if (lastdnptr != NULL && cpp < lastdnptr-1) {
|
||||
*cpp++ = cp;
|
||||
*cpp = NULL;
|
||||
}
|
||||
}
|
||||
sp = cp++; /* save ptr to length byte */
|
||||
do {
|
||||
if (c == '.') {
|
||||
c = *dn++;
|
||||
break;
|
||||
}
|
||||
if (c == '\\') {
|
||||
if ((c = *dn++) == '\0')
|
||||
break;
|
||||
}
|
||||
if (cp >= eob) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*cp++ = c;
|
||||
} while ((c = *dn++) != '\0');
|
||||
/* catch trailing '.'s but not '..' */
|
||||
if ((l = cp - sp - 1) == 0 && c == '\0') {
|
||||
cp--;
|
||||
break;
|
||||
}
|
||||
if (l <= 0 || l > MAXLABEL) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*sp = l;
|
||||
}
|
||||
if (cp >= eob) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*cp++ = '\0';
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over a compressed domain name. Return the size or -1.
|
||||
*/
|
||||
int
|
||||
__dn_skipname(comp_dn, eom)
|
||||
const u_char *comp_dn, *eom;
|
||||
{
|
||||
register const u_char *cp;
|
||||
register int n;
|
||||
|
||||
cp = comp_dn;
|
||||
while (cp < eom && (n = *cp++)) {
|
||||
/*
|
||||
* check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0: /* normal case, n == len */
|
||||
cp += n;
|
||||
continue;
|
||||
case INDIR_MASK: /* indirection */
|
||||
cp++;
|
||||
break;
|
||||
default: /* illegal type */
|
||||
return (-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (cp > eom)
|
||||
return (-1);
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
|
||||
static int
|
||||
mklower(ch)
|
||||
register int ch;
|
||||
{
|
||||
if (isascii(ch) && isupper(ch))
|
||||
return (tolower(ch));
|
||||
return (ch);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for expanded name from a list of previously compressed names.
|
||||
* Return the offset from msg if found or -1.
|
||||
* dnptrs is the pointer to the first name on the list,
|
||||
* not the pointer to the start of the message.
|
||||
*/
|
||||
static int
|
||||
dn_find(exp_dn, msg, dnptrs, lastdnptr)
|
||||
u_char *exp_dn, *msg;
|
||||
u_char **dnptrs, **lastdnptr;
|
||||
{
|
||||
register u_char *dn, *cp, **cpp;
|
||||
register int n;
|
||||
u_char *sp;
|
||||
|
||||
for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
|
||||
dn = exp_dn;
|
||||
sp = cp = *cpp;
|
||||
while ( (n = *cp++) ) {
|
||||
/*
|
||||
* check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0: /* normal case, n == len */
|
||||
while (--n >= 0) {
|
||||
if (*dn == '.')
|
||||
goto next;
|
||||
if (*dn == '\\')
|
||||
dn++;
|
||||
if (mklower(*dn++) != mklower(*cp++))
|
||||
goto next;
|
||||
}
|
||||
if ((n = *dn++) == '\0' && *cp == '\0')
|
||||
return (sp - msg);
|
||||
if (n == '.')
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
case INDIR_MASK: /* indirection */
|
||||
cp = msg + (((n & 0x3f) << 8) | *cp);
|
||||
break;
|
||||
|
||||
default: /* illegal type */
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (*dn == '\0')
|
||||
return (sp - msg);
|
||||
next: ;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines to insert/extract short/long's.
|
||||
*/
|
||||
|
||||
u_int16_t
|
||||
_getshort(msgp)
|
||||
register const u_char *msgp;
|
||||
{
|
||||
register u_int16_t u;
|
||||
|
||||
GETSHORT(u, msgp);
|
||||
return (u);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
_getlong(msgp)
|
||||
register const u_char *msgp;
|
||||
{
|
||||
register u_int32_t u;
|
||||
|
||||
GETLONG(u, msgp);
|
||||
return (u);
|
||||
}
|
||||
|
||||
void
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
__putshort(register u_int16_t s, register u_char *msgp) /* must match proto */
|
||||
#else
|
||||
__putshort(s, msgp)
|
||||
register u_int16_t s;
|
||||
register u_char *msgp;
|
||||
#endif
|
||||
{
|
||||
PUTSHORT(s, msgp);
|
||||
}
|
||||
|
||||
void
|
||||
__putlong(l, msgp)
|
||||
register u_int32_t l;
|
||||
register u_char *msgp;
|
||||
{
|
||||
PUTLONG(l, msgp);
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#undef ALLOW_T_UNSPEC /* enable the "unspec" RR type for old athena */
|
||||
#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
|
||||
#define RFC1535 /* comply with RFC1535 (STRONGLY reccomended by vixie)*/
|
||||
#undef ALLOW_UPDATES /* destroy your system security */
|
||||
#undef USELOOPBACK /* res_init() bind to localhost */
|
||||
#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
|
||||
#define MULTI_PTRS_ARE_ALIASES /* fold multiple PTR records into aliases */
|
||||
#undef ALLOW_UPDATES /* compile support for update REQUESTS - harmless */
|
||||
#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
|
||||
|
|
|
|||
|
|
@ -1,806 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1985, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: res_debug.c,v 1.7 1996/02/06 20:35:48 wollman Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef ISO
|
||||
#include <netiso/iso.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "res_config.h"
|
||||
|
||||
extern const char *_res_opcodes[];
|
||||
extern const char *_res_resultcodes[];
|
||||
|
||||
/* XXX: we should use getservbyport() instead. */
|
||||
static const char *
|
||||
dewks(wks)
|
||||
int wks;
|
||||
{
|
||||
static char nbuf[20];
|
||||
|
||||
switch (wks) {
|
||||
case 5: return "rje";
|
||||
case 7: return "echo";
|
||||
case 9: return "discard";
|
||||
case 11: return "systat";
|
||||
case 13: return "daytime";
|
||||
case 15: return "netstat";
|
||||
case 17: return "qotd";
|
||||
case 19: return "chargen";
|
||||
case 20: return "ftp-data";
|
||||
case 21: return "ftp";
|
||||
case 23: return "telnet";
|
||||
case 25: return "smtp";
|
||||
case 37: return "time";
|
||||
case 39: return "rlp";
|
||||
case 42: return "name";
|
||||
case 43: return "whois";
|
||||
case 53: return "domain";
|
||||
case 57: return "apts";
|
||||
case 59: return "apfs";
|
||||
case 67: return "bootps";
|
||||
case 68: return "bootpc";
|
||||
case 69: return "tftp";
|
||||
case 77: return "rje";
|
||||
case 79: return "finger";
|
||||
case 87: return "link";
|
||||
case 95: return "supdup";
|
||||
case 100: return "newacct";
|
||||
case 101: return "hostnames";
|
||||
case 102: return "iso-tsap";
|
||||
case 103: return "x400";
|
||||
case 104: return "x400-snd";
|
||||
case 105: return "csnet-ns";
|
||||
case 109: return "pop-2";
|
||||
case 111: return "sunrpc";
|
||||
case 113: return "auth";
|
||||
case 115: return "sftp";
|
||||
case 117: return "uucp-path";
|
||||
case 119: return "nntp";
|
||||
case 121: return "erpc";
|
||||
case 123: return "ntp";
|
||||
case 133: return "statsrv";
|
||||
case 136: return "profile";
|
||||
case 144: return "NeWS";
|
||||
case 161: return "snmp";
|
||||
case 162: return "snmp-trap";
|
||||
case 170: return "print-srv";
|
||||
default: (void) sprintf(nbuf, "%d", wks); return (nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: we should use getprotobynumber() instead. */
|
||||
static const char *
|
||||
deproto(protonum)
|
||||
int protonum;
|
||||
{
|
||||
static char nbuf[20];
|
||||
|
||||
switch (protonum) {
|
||||
case 1: return "icmp";
|
||||
case 2: return "igmp";
|
||||
case 3: return "ggp";
|
||||
case 5: return "st";
|
||||
case 6: return "tcp";
|
||||
case 7: return "ucl";
|
||||
case 8: return "egp";
|
||||
case 9: return "igp";
|
||||
case 11: return "nvp-II";
|
||||
case 12: return "pup";
|
||||
case 16: return "chaos";
|
||||
case 17: return "udp";
|
||||
default: (void) sprintf(nbuf, "%d", protonum); return (nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
static const u_char *
|
||||
do_rrset(msg, len, cp, cnt, pflag, file, hs)
|
||||
int cnt, pflag, len;
|
||||
const u_char *cp, *msg;
|
||||
const char *hs;
|
||||
FILE *file;
|
||||
{
|
||||
int n;
|
||||
int sflag;
|
||||
|
||||
/*
|
||||
* Print answer records.
|
||||
*/
|
||||
sflag = (_res.pfcode & pflag);
|
||||
if ( (n = ntohs(cnt)) ) {
|
||||
if ((!_res.pfcode) ||
|
||||
((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
|
||||
fprintf(file, hs);
|
||||
while (--n >= 0) {
|
||||
if ((!_res.pfcode) || sflag) {
|
||||
cp = p_rr(cp, msg, file);
|
||||
} else {
|
||||
unsigned int dlen;
|
||||
cp += __dn_skipname(cp, cp + MAXCDNAME);
|
||||
cp += INT16SZ;
|
||||
cp += INT16SZ;
|
||||
cp += INT32SZ;
|
||||
dlen = _getshort((u_char*)cp);
|
||||
cp += INT16SZ;
|
||||
cp += dlen;
|
||||
}
|
||||
if ((cp - msg) > len)
|
||||
return (NULL);
|
||||
}
|
||||
if ((!_res.pfcode) ||
|
||||
((sflag) && (_res.pfcode & RES_PRF_HEAD1)))
|
||||
putc('\n', file);
|
||||
}
|
||||
return (cp);
|
||||
}
|
||||
|
||||
void
|
||||
__p_query(msg)
|
||||
const u_char *msg;
|
||||
{
|
||||
__fp_query(msg, stdout);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the current options.
|
||||
* This is intended to be primarily a debugging routine.
|
||||
*/
|
||||
void
|
||||
__fp_resstat(statp, file)
|
||||
struct __res_state *statp;
|
||||
FILE *file;
|
||||
{
|
||||
register u_long mask;
|
||||
|
||||
fprintf(file, ";; res options:");
|
||||
if (!statp)
|
||||
statp = &_res;
|
||||
for (mask = 1; mask != 0; mask <<= 1)
|
||||
if (statp->options & mask)
|
||||
fprintf(file, " %s", p_option(mask));
|
||||
putc('\n', file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the contents of a query.
|
||||
* This is intended to be primarily a debugging routine.
|
||||
*/
|
||||
void
|
||||
__fp_nquery(msg, len, file)
|
||||
const u_char *msg;
|
||||
int len;
|
||||
FILE *file;
|
||||
{
|
||||
register const u_char *cp, *endMark;
|
||||
register const HEADER *hp;
|
||||
register int n;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1)
|
||||
return;
|
||||
|
||||
#define TruncTest(x) if (x >= endMark) goto trunc
|
||||
#define ErrorTest(x) if (x == NULL) goto error
|
||||
|
||||
/*
|
||||
* Print header fields.
|
||||
*/
|
||||
hp = (HEADER *)msg;
|
||||
cp = msg + HFIXEDSZ;
|
||||
endMark = cp + len;
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX) || hp->rcode) {
|
||||
fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d",
|
||||
_res_opcodes[hp->opcode],
|
||||
_res_resultcodes[hp->rcode],
|
||||
ntohs(hp->id));
|
||||
putc('\n', file);
|
||||
}
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEADX))
|
||||
putc(';', file);
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD2)) {
|
||||
fprintf(file, "; flags:");
|
||||
if (hp->qr)
|
||||
fprintf(file, " qr");
|
||||
if (hp->aa)
|
||||
fprintf(file, " aa");
|
||||
if (hp->tc)
|
||||
fprintf(file, " tc");
|
||||
if (hp->rd)
|
||||
fprintf(file, " rd");
|
||||
if (hp->ra)
|
||||
fprintf(file, " ra");
|
||||
}
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_HEAD1)) {
|
||||
fprintf(file, "; Ques: %d", ntohs(hp->qdcount));
|
||||
fprintf(file, ", Ans: %d", ntohs(hp->ancount));
|
||||
fprintf(file, ", Auth: %d", ntohs(hp->nscount));
|
||||
fprintf(file, ", Addit: %d", ntohs(hp->arcount));
|
||||
}
|
||||
if ((!_res.pfcode) || (_res.pfcode &
|
||||
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
|
||||
putc('\n',file);
|
||||
}
|
||||
/*
|
||||
* Print question records.
|
||||
*/
|
||||
if ( (n = ntohs(hp->qdcount)) ) {
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
fprintf(file, ";; QUESTIONS:\n");
|
||||
while (--n >= 0) {
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
fprintf(file, ";;\t");
|
||||
TruncTest(cp);
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
cp = p_cdnname(cp, msg, len, file);
|
||||
else {
|
||||
int n;
|
||||
char name[MAXDNAME];
|
||||
|
||||
if ((n = dn_expand(msg, msg+len, cp, name,
|
||||
sizeof name)) < 0)
|
||||
cp = NULL;
|
||||
else
|
||||
cp += n;
|
||||
}
|
||||
ErrorTest(cp);
|
||||
TruncTest(cp);
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
fprintf(file, ", type = %s",
|
||||
__p_type(_getshort((u_char*)cp)));
|
||||
cp += INT16SZ;
|
||||
TruncTest(cp);
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
fprintf(file, ", class = %s\n",
|
||||
__p_class(_getshort((u_char*)cp)));
|
||||
cp += INT16SZ;
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_QUES))
|
||||
putc('\n', file);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Print authoritative answer records
|
||||
*/
|
||||
TruncTest(cp);
|
||||
cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
|
||||
";; ANSWERS:\n");
|
||||
ErrorTest(cp);
|
||||
|
||||
/*
|
||||
* print name server records
|
||||
*/
|
||||
TruncTest(cp);
|
||||
cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
|
||||
";; AUTHORITY RECORDS:\n");
|
||||
ErrorTest(cp);
|
||||
|
||||
TruncTest(cp);
|
||||
/*
|
||||
* print additional records
|
||||
*/
|
||||
cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
|
||||
";; ADDITIONAL RECORDS:\n");
|
||||
ErrorTest(cp);
|
||||
return;
|
||||
trunc:
|
||||
fprintf(file, "\n;; ...truncated\n");
|
||||
return;
|
||||
error:
|
||||
fprintf(file, "\n;; ...malformed\n");
|
||||
}
|
||||
|
||||
void
|
||||
__fp_query(msg, file)
|
||||
const u_char *msg;
|
||||
FILE *file;
|
||||
{
|
||||
fp_nquery(msg, PACKETSZ, file);
|
||||
}
|
||||
|
||||
const u_char *
|
||||
__p_cdnname(cp, msg, len, file)
|
||||
const u_char *cp, *msg;
|
||||
int len;
|
||||
FILE *file;
|
||||
{
|
||||
char name[MAXDNAME];
|
||||
int n;
|
||||
|
||||
if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
|
||||
return (NULL);
|
||||
if (name[0] == '\0')
|
||||
putc('.', file);
|
||||
else
|
||||
fputs(name, file);
|
||||
return (cp + n);
|
||||
}
|
||||
|
||||
const u_char *
|
||||
__p_cdname(cp, msg, file)
|
||||
const u_char *cp, *msg;
|
||||
FILE *file;
|
||||
{
|
||||
return (p_cdnname(cp, msg, PACKETSZ, file));
|
||||
}
|
||||
|
||||
/* XXX: the rest of these functions need to become length-limited, too. (vix)
|
||||
*/
|
||||
|
||||
const u_char *
|
||||
__p_fqname(cp, msg, file)
|
||||
const u_char *cp, *msg;
|
||||
FILE *file;
|
||||
{
|
||||
char name[MAXDNAME];
|
||||
int n;
|
||||
|
||||
if ((n = dn_expand(msg, cp + MAXCDNAME, cp, name, sizeof name)) < 0)
|
||||
return (NULL);
|
||||
if (name[0] == '\0') {
|
||||
putc('.', file);
|
||||
} else {
|
||||
fputs(name, file);
|
||||
if (name[strlen(name) - 1] != '.')
|
||||
putc('.', file);
|
||||
}
|
||||
return (cp + n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print resource record fields in human readable form.
|
||||
*/
|
||||
const u_char *
|
||||
__p_rr(cp, msg, file)
|
||||
const u_char *cp, *msg;
|
||||
FILE *file;
|
||||
{
|
||||
int type, class, dlen, n, c;
|
||||
struct in_addr inaddr;
|
||||
#ifdef ISO
|
||||
struct iso_addr isoa;
|
||||
#endif
|
||||
const u_char *cp1, *cp2;
|
||||
u_int32_t tmpttl, t;
|
||||
int lcnt;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (NULL);
|
||||
}
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL); /* compression error */
|
||||
type = _getshort((u_char*)cp);
|
||||
cp += INT16SZ;
|
||||
class = _getshort((u_char*)cp);
|
||||
cp += INT16SZ;
|
||||
tmpttl = _getlong((u_char*)cp);
|
||||
cp += INT32SZ;
|
||||
dlen = _getshort((u_char*)cp);
|
||||
cp += INT16SZ;
|
||||
cp1 = cp;
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_TTLID))
|
||||
fprintf(file, "\t%lu", (u_long)tmpttl);
|
||||
if ((!_res.pfcode) || (_res.pfcode & RES_PRF_CLASS))
|
||||
fprintf(file, "\t%s", __p_class(class));
|
||||
fprintf(file, "\t%s", __p_type(type));
|
||||
/*
|
||||
* Print type specific data, if appropriate
|
||||
*/
|
||||
switch (type) {
|
||||
case T_A:
|
||||
switch (class) {
|
||||
case C_IN:
|
||||
case C_HS:
|
||||
bcopy(cp, (char *)&inaddr, INADDRSZ);
|
||||
if (dlen == 4) {
|
||||
fprintf(file, "\t%s", inet_ntoa(inaddr));
|
||||
cp += dlen;
|
||||
} else if (dlen == 7) {
|
||||
char *address;
|
||||
u_char protocol;
|
||||
u_short port;
|
||||
|
||||
address = inet_ntoa(inaddr);
|
||||
cp += INADDRSZ;
|
||||
protocol = *(u_char*)cp;
|
||||
cp += sizeof(u_char);
|
||||
port = _getshort((u_char*)cp);
|
||||
cp += INT16SZ;
|
||||
fprintf(file, "\t%s\t; proto %d, port %d",
|
||||
address, protocol, port);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cp += dlen;
|
||||
}
|
||||
break;
|
||||
case T_CNAME:
|
||||
case T_MB:
|
||||
case T_MG:
|
||||
case T_MR:
|
||||
case T_NS:
|
||||
case T_PTR:
|
||||
putc('\t', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
break;
|
||||
|
||||
case T_HINFO:
|
||||
case T_ISDN:
|
||||
cp2 = cp + dlen;
|
||||
if ( (n = *cp++) ) {
|
||||
fprintf(file, "\t%.*s", n, cp);
|
||||
cp += n;
|
||||
}
|
||||
if ((cp < cp2) && (n = *cp++)) {
|
||||
fprintf(file, "\t%.*s", n, cp);
|
||||
cp += n;
|
||||
} else if (type == T_HINFO)
|
||||
fprintf(file, "\n;; *** Warning *** OS-type missing");
|
||||
break;
|
||||
|
||||
case T_SOA:
|
||||
putc('\t', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
putc(' ', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
fputs(" (\n", file);
|
||||
t = _getlong((u_char*)cp); cp += INT32SZ;
|
||||
fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
|
||||
t = _getlong((u_char*)cp); cp += INT32SZ;
|
||||
fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
|
||||
(u_long)t, __p_time(t));
|
||||
t = _getlong((u_char*)cp); cp += INT32SZ;
|
||||
fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
|
||||
(u_long)t, __p_time(t));
|
||||
t = _getlong((u_char*)cp); cp += INT32SZ;
|
||||
fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
|
||||
(u_long)t, __p_time(t));
|
||||
t = _getlong((u_char*)cp); cp += INT32SZ;
|
||||
fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
|
||||
(u_long)t, __p_time(t));
|
||||
break;
|
||||
|
||||
case T_MX:
|
||||
case T_AFSDB:
|
||||
case T_RT:
|
||||
fprintf(file, "\t%d ", _getshort((u_char*)cp));
|
||||
cp += INT16SZ;
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
break;
|
||||
|
||||
case T_PX:
|
||||
fprintf(file, "\t%d ", _getshort((u_char*)cp));
|
||||
cp += INT16SZ;
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
putc(' ', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
break;
|
||||
|
||||
case T_TXT:
|
||||
case T_X25:
|
||||
(void) fputs("\t\"", file);
|
||||
cp2 = cp1 + dlen;
|
||||
while (cp < cp2) {
|
||||
if ( (n = (unsigned char) *cp++) ) {
|
||||
for (c = n; c > 0 && cp < cp2; c--)
|
||||
if ((*cp == '\n') || (*cp == '"')) {
|
||||
(void) putc('\\', file);
|
||||
(void) putc(*cp++, file);
|
||||
} else
|
||||
(void) putc(*cp++, file);
|
||||
}
|
||||
}
|
||||
putc('"', file);
|
||||
break;
|
||||
|
||||
#ifdef ISO
|
||||
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;
|
||||
#endif
|
||||
|
||||
case T_MINFO:
|
||||
case T_RP:
|
||||
putc('\t', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
putc(' ', file);
|
||||
if ((cp = p_fqname(cp, msg, file)) == NULL)
|
||||
return (NULL);
|
||||
break;
|
||||
|
||||
case T_UINFO:
|
||||
putc('\t', file);
|
||||
fputs((char *)cp, file);
|
||||
cp += dlen;
|
||||
break;
|
||||
|
||||
case T_UID:
|
||||
case T_GID:
|
||||
if (dlen == 4) {
|
||||
fprintf(file, "\t%u", _getlong((u_char*)cp));
|
||||
cp += INT32SZ;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_WKS:
|
||||
if (dlen < INT32SZ + 1)
|
||||
break;
|
||||
bcopy(cp, (char *)&inaddr, INADDRSZ);
|
||||
cp += INT32SZ;
|
||||
fprintf(file, "\t%s %s ( ",
|
||||
inet_ntoa(inaddr),
|
||||
deproto((int) *cp));
|
||||
cp += sizeof(u_char);
|
||||
n = 0;
|
||||
lcnt = 0;
|
||||
while (cp < cp1 + dlen) {
|
||||
c = *cp++;
|
||||
do {
|
||||
if (c & 0200) {
|
||||
if (lcnt == 0) {
|
||||
fputs("\n\t\t\t", file);
|
||||
lcnt = 5;
|
||||
}
|
||||
fputs(dewks(n), file);
|
||||
putc(' ', file);
|
||||
lcnt--;
|
||||
}
|
||||
c <<= 1;
|
||||
} while (++n & 07);
|
||||
}
|
||||
putc(')', file);
|
||||
break;
|
||||
|
||||
#ifdef ALLOW_T_UNSPEC
|
||||
case T_UNSPEC:
|
||||
{
|
||||
int NumBytes = 8;
|
||||
u_char *DataPtr;
|
||||
int i;
|
||||
|
||||
if (dlen < NumBytes) NumBytes = dlen;
|
||||
fprintf(file, "\tFirst %d bytes of hex data:",
|
||||
NumBytes);
|
||||
for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
|
||||
fprintf(file, " %x", *DataPtr);
|
||||
cp += dlen;
|
||||
}
|
||||
break;
|
||||
#endif /* ALLOW_T_UNSPEC */
|
||||
|
||||
default:
|
||||
fprintf(file, "\t?%d?", type);
|
||||
cp += dlen;
|
||||
}
|
||||
#if 0
|
||||
fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
|
||||
#else
|
||||
putc('\n', file);
|
||||
#endif
|
||||
if (cp - cp1 != dlen) {
|
||||
fprintf(file, ";; packet size error (found %d, dlen was %d)\n",
|
||||
cp - cp1, dlen);
|
||||
cp = NULL;
|
||||
}
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string for the type
|
||||
*/
|
||||
const char *
|
||||
__p_type(type)
|
||||
int type;
|
||||
{
|
||||
static char nbuf[20];
|
||||
|
||||
switch (type) {
|
||||
case T_A: return "A";
|
||||
case T_NS: return "NS";
|
||||
case T_CNAME: return "CNAME";
|
||||
case T_SOA: return "SOA";
|
||||
case T_MB: return "MB";
|
||||
case T_MG: return "MG";
|
||||
case T_MR: return "MR";
|
||||
case T_NULL: return "NULL";
|
||||
case T_WKS: return "WKS";
|
||||
case T_PTR: return "PTR";
|
||||
case T_HINFO: return "HINFO";
|
||||
case T_MINFO: return "MINFO";
|
||||
case T_MX: return "MX";
|
||||
case T_TXT: return "TXT";
|
||||
case T_RP: return "RP";
|
||||
case T_AFSDB: return "AFSDB";
|
||||
case T_X25: return "X25";
|
||||
case T_ISDN: return "ISDN";
|
||||
case T_RT: return "RT";
|
||||
case T_NSAP: return "NSAP";
|
||||
case T_NSAP_PTR: return "NSAP_PTR";
|
||||
case T_SIG: return "SIG";
|
||||
case T_KEY: return "KEY";
|
||||
case T_PX: return "PX";
|
||||
case T_GPOS: return "GPOS";
|
||||
case T_AAAA: return "AAAA";
|
||||
case T_LOC: return "LOC";
|
||||
case T_AXFR: return "AXFR";
|
||||
case T_MAILB: return "MAILB";
|
||||
case T_MAILA: return "MAILA";
|
||||
case T_ANY: return "ANY";
|
||||
case T_UINFO: return "UINFO";
|
||||
case T_UID: return "UID";
|
||||
case T_GID: return "GID";
|
||||
#ifdef ALLOW_T_UNSPEC
|
||||
case T_UNSPEC: return "UNSPEC";
|
||||
#endif /* ALLOW_T_UNSPEC */
|
||||
default: (void)sprintf(nbuf, "%d", type); return (nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a mnemonic for class
|
||||
*/
|
||||
const char *
|
||||
__p_class(class)
|
||||
int class;
|
||||
{
|
||||
static char nbuf[20];
|
||||
|
||||
switch (class) {
|
||||
case C_IN: return "IN";
|
||||
case C_HS: return "HS";
|
||||
case C_ANY: return "ANY";
|
||||
default: (void)sprintf(nbuf, "%d", class); return (nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a mnemonic for an option
|
||||
*/
|
||||
const char *
|
||||
__p_option(option)
|
||||
u_long option;
|
||||
{
|
||||
static char nbuf[40];
|
||||
|
||||
switch (option) {
|
||||
case RES_INIT: return "init";
|
||||
case RES_DEBUG: return "debug";
|
||||
case RES_AAONLY: return "aaonly(unimpl)";
|
||||
case RES_USEVC: return "usevc";
|
||||
case RES_PRIMARY: return "primry(unimpl)";
|
||||
case RES_IGNTC: return "igntc";
|
||||
case RES_RECURSE: return "recurs";
|
||||
case RES_DEFNAMES: return "defnam";
|
||||
case RES_STAYOPEN: return "styopn";
|
||||
case RES_DNSRCH: return "dnsrch";
|
||||
case RES_INSECURE1: return "insecure1";
|
||||
case RES_INSECURE2: return "insecure2";
|
||||
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
|
||||
return (nbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a mnemonic for a time to live
|
||||
*/
|
||||
char *
|
||||
__p_time(value)
|
||||
u_int32_t value;
|
||||
{
|
||||
static char nbuf[40];
|
||||
int secs, mins, hours, days;
|
||||
register char *p;
|
||||
|
||||
if (value == 0) {
|
||||
strcpy(nbuf, "0 secs");
|
||||
return (nbuf);
|
||||
}
|
||||
|
||||
secs = value % 60;
|
||||
value /= 60;
|
||||
mins = value % 60;
|
||||
value /= 60;
|
||||
hours = value % 24;
|
||||
value /= 24;
|
||||
days = value;
|
||||
value = 0;
|
||||
|
||||
#define PLURALIZE(x) x, (x == 1) ? "" : "s"
|
||||
p = nbuf;
|
||||
if (days) {
|
||||
(void)sprintf(p, "%d day%s", PLURALIZE(days));
|
||||
while (*++p);
|
||||
}
|
||||
if (hours) {
|
||||
if (days)
|
||||
*p++ = ' ';
|
||||
(void)sprintf(p, "%d hour%s", PLURALIZE(hours));
|
||||
while (*++p);
|
||||
}
|
||||
if (mins) {
|
||||
if (days || hours)
|
||||
*p++ = ' ';
|
||||
(void)sprintf(p, "%d min%s", PLURALIZE(mins));
|
||||
while (*++p);
|
||||
}
|
||||
if (secs || ! (days || hours || mins)) {
|
||||
if (days || hours || mins)
|
||||
*p++ = ' ';
|
||||
(void)sprintf(p, "%d sec%s", PLURALIZE(secs));
|
||||
}
|
||||
return (nbuf);
|
||||
}
|
||||
|
|
@ -1,449 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1985, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
|
||||
static char rcsid[] = "$Id: res_init.c,v 1.6 1995/08/21 09:15:36 bde Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
#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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "res_config.h"
|
||||
|
||||
static void res_setoptions __P((char *, char *));
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
static const char sort_mask[] = "/&";
|
||||
#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
|
||||
static u_int32_t net_mask __P((struct in_addr));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Resolver state default settings.
|
||||
*/
|
||||
|
||||
struct __res_state _res;
|
||||
|
||||
/*
|
||||
* Set up default settings. If the configuration file exist, the values
|
||||
* there will have precedence. Otherwise, the server address is set to
|
||||
* INADDR_ANY and the default domain name comes from the gethostname().
|
||||
*
|
||||
* An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
|
||||
* rather than INADDR_ANY ("0.0.0.0") as the default name server address
|
||||
* since it was noted that INADDR_ANY actually meant ``the first interface
|
||||
* you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
|
||||
* it had to be "up" in order for you to reach your own name server. It
|
||||
* was later decided that since the recommended practice is to always
|
||||
* install local static routes through 127.0.0.1 for all your network
|
||||
* interfaces, that we could solve this problem without a code change.
|
||||
*
|
||||
* The configuration file should always be used, since it is the only way
|
||||
* to specify a default domain. If you are running a server on your local
|
||||
* machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
|
||||
* in the configuration file.
|
||||
*
|
||||
* Return 0 if completes successfully, -1 on error
|
||||
*/
|
||||
int
|
||||
res_init()
|
||||
{
|
||||
register FILE *fp;
|
||||
register char *cp, **pp;
|
||||
register int n;
|
||||
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
|
||||
#ifndef RFC1535
|
||||
int dots;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These three fields used to be statically initialized. This made
|
||||
* it hard to use this code in a shared library. It is necessary,
|
||||
* now that we're doing dynamic initialization here, that we preserve
|
||||
* the old semantics: if an application modifies one of these three
|
||||
* fields of _res before res_init() is called, res_init() will not
|
||||
* alter them. Of course, if an application is setting them to
|
||||
* _zero_ before calling res_init(), hoping to override what used
|
||||
* to be the static default, we can't detect it and unexpected results
|
||||
* will follow. Zero for any of these fields would make no sense,
|
||||
* so one can safely assume that the applications were already getting
|
||||
* unexpected results.
|
||||
*
|
||||
* _res.options is tricky since some apps were known to diddle the bits
|
||||
* before res_init() was first called. We can't replicate that semantic
|
||||
* with dynamic initialization (they may have turned bits off that are
|
||||
* set in RES_DEFAULT). Our solution is to declare such applications
|
||||
* "broken". They could fool us by setting RES_INIT but none do (yet).
|
||||
*/
|
||||
if (!_res.retrans)
|
||||
_res.retrans = RES_TIMEOUT;
|
||||
if (!_res.retry)
|
||||
_res.retry = 4;
|
||||
if (!(_res.options & RES_INIT))
|
||||
_res.options = RES_DEFAULT;
|
||||
|
||||
/*
|
||||
* This one used to initialize implicitly to zero, so unless the app
|
||||
* has set it to something in particular, we can randomize it now.
|
||||
*/
|
||||
if (!_res.id)
|
||||
_res.id = res_randomid();
|
||||
|
||||
#ifdef USELOOPBACK
|
||||
_res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
|
||||
#else
|
||||
_res.nsaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
#endif
|
||||
_res.nsaddr.sin_family = AF_INET;
|
||||
_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
|
||||
_res.nscount = 1;
|
||||
_res.ndots = 1;
|
||||
_res.pfcode = 0;
|
||||
|
||||
/* Allow user to override the local domain definition */
|
||||
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
|
||||
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
|
||||
haveenv++;
|
||||
|
||||
/*
|
||||
* Set search list to be blank-separated strings
|
||||
* from rest of env value. Permits users of LOCALDOMAIN
|
||||
* to still have a search list, and anyone to set the
|
||||
* one that they want to use as an individual (even more
|
||||
* important now that the rfc1535 stuff restricts searches)
|
||||
*/
|
||||
cp = _res.defdname;
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = cp;
|
||||
for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
|
||||
if (*cp == '\n') /* silly backwards compat */
|
||||
break;
|
||||
else if (*cp == ' ' || *cp == '\t') {
|
||||
*cp = 0;
|
||||
n = 1;
|
||||
} else if (n) {
|
||||
*pp++ = cp;
|
||||
n = 0;
|
||||
havesearch = 1;
|
||||
}
|
||||
}
|
||||
/* null terminate last domain if there are excess */
|
||||
while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
|
||||
cp++;
|
||||
*cp = '\0';
|
||||
*pp++ = 0;
|
||||
}
|
||||
|
||||
#define MATCH(line, name) \
|
||||
(!strncmp(line, name, sizeof(name) - 1) && \
|
||||
(line[sizeof(name) - 1] == ' ' || \
|
||||
line[sizeof(name) - 1] == '\t'))
|
||||
|
||||
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
|
||||
/* read the config file */
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
/* skip comments */
|
||||
if (*buf == ';' || *buf == '#')
|
||||
continue;
|
||||
/* read default domain name */
|
||||
if (MATCH(buf, "domain")) {
|
||||
if (haveenv) /* skip if have from environ */
|
||||
continue;
|
||||
cp = buf + sizeof("domain") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
|
||||
if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL)
|
||||
*cp = '\0';
|
||||
havesearch = 0;
|
||||
continue;
|
||||
}
|
||||
/* set search list */
|
||||
if (MATCH(buf, "search")) {
|
||||
if (haveenv) /* skip if have from environ */
|
||||
continue;
|
||||
cp = buf + sizeof("search") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
|
||||
if ((cp = strchr(_res.defdname, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
/*
|
||||
* Set search list to be blank-separated strings
|
||||
* on rest of line.
|
||||
*/
|
||||
cp = _res.defdname;
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = cp;
|
||||
for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
*cp = 0;
|
||||
n = 1;
|
||||
} else if (n) {
|
||||
*pp++ = cp;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
/* null terminate last domain if there are excess */
|
||||
while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
*cp = '\0';
|
||||
*pp++ = 0;
|
||||
havesearch = 1;
|
||||
continue;
|
||||
}
|
||||
/* read nameservers to query */
|
||||
if (MATCH(buf, "nameserver") && nserv < MAXNS) {
|
||||
struct in_addr a;
|
||||
|
||||
cp = buf + sizeof("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
|
||||
_res.nsaddr_list[nserv].sin_addr = a;
|
||||
_res.nsaddr_list[nserv].sin_family = AF_INET;
|
||||
_res.nsaddr_list[nserv].sin_port =
|
||||
htons(NAMESERVER_PORT);
|
||||
nserv++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#ifdef RESOLVSORT
|
||||
if (MATCH(buf, "sortlist")) {
|
||||
struct in_addr a;
|
||||
|
||||
cp = buf + sizeof("sortlist") - 1;
|
||||
while (nsort < MAXRESOLVSORT) {
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if (*cp == '\0' || *cp == '\n' || *cp == ';')
|
||||
break;
|
||||
net = cp;
|
||||
while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
if (inet_aton(net, &a)) {
|
||||
_res.sort_list[nsort].addr = a;
|
||||
if (ISSORTMASK(n)) {
|
||||
*cp++ = n;
|
||||
net = cp;
|
||||
while (*cp && *cp != ';' &&
|
||||
isascii(*cp) && !isspace(*cp))
|
||||
cp++;
|
||||
n = *cp;
|
||||
*cp = 0;
|
||||
if (inet_aton(net, &a)) {
|
||||
_res.sort_list[nsort].mask = a.s_addr;
|
||||
} else {
|
||||
_res.sort_list[nsort].mask =
|
||||
net_mask(_res.sort_list[nsort].addr);
|
||||
}
|
||||
} else {
|
||||
_res.sort_list[nsort].mask =
|
||||
net_mask(_res.sort_list[nsort].addr);
|
||||
}
|
||||
nsort++;
|
||||
}
|
||||
*cp = n;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (MATCH(buf, "options")) {
|
||||
res_setoptions(buf + sizeof("options") - 1, "conf");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nserv > 1)
|
||||
_res.nscount = nserv;
|
||||
#ifdef RESOLVSORT
|
||||
_res.nsort = nsort;
|
||||
#endif
|
||||
(void) fclose(fp);
|
||||
}
|
||||
if (_res.defdname[0] == 0 &&
|
||||
gethostname(buf, sizeof(_res.defdname) - 1) == 0 &&
|
||||
(cp = strchr(buf, '.')) != NULL)
|
||||
strcpy(_res.defdname, cp + 1);
|
||||
|
||||
/* find components of local domain that might be searched */
|
||||
if (havesearch == 0) {
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = _res.defdname;
|
||||
*pp = NULL;
|
||||
|
||||
#ifndef RFC1535
|
||||
dots = 0;
|
||||
for (cp = _res.defdname; *cp; cp++)
|
||||
dots += (*cp == '.');
|
||||
|
||||
cp = _res.defdname;
|
||||
while (pp < _res.dnsrch + MAXDFLSRCH) {
|
||||
if (dots < LOCALDOMAINPARTS)
|
||||
break;
|
||||
cp = strchr(cp, '.') + 1; /* we know there is one */
|
||||
*pp++ = cp;
|
||||
dots--;
|
||||
}
|
||||
*pp = NULL;
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG) {
|
||||
printf(";; res_init()... default dnsrch list:\n");
|
||||
for (pp = _res.dnsrch; *pp; pp++)
|
||||
printf(";;\t%s\n", *pp);
|
||||
printf(";;\t..END..\n");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
#endif /* !RFC1535 */
|
||||
}
|
||||
|
||||
if ((cp = getenv("RES_OPTIONS")) != NULL)
|
||||
res_setoptions(cp, "env");
|
||||
_res.options |= RES_INIT;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
res_setoptions(options, source)
|
||||
char *options, *source;
|
||||
{
|
||||
char *cp = options;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_setoptions(\"%s\", \"%s\")...\n",
|
||||
options, source);
|
||||
#endif
|
||||
while (*cp) {
|
||||
/* skip leading and inner runs of spaces */
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
/* search for and process individual options */
|
||||
if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
|
||||
i = atoi(cp + sizeof("ndots:") - 1);
|
||||
if (i <= RES_MAXNDOTS)
|
||||
_res.ndots = i;
|
||||
else
|
||||
_res.ndots = RES_MAXNDOTS;
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";;\tndots=%d\n", _res.ndots);
|
||||
#endif
|
||||
} else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
|
||||
#ifdef DEBUG
|
||||
if (!(_res.options & RES_DEBUG)) {
|
||||
printf(";; res_setoptions(\"%s\", \"%s\")..\n",
|
||||
options, source);
|
||||
_res.options |= RES_DEBUG;
|
||||
}
|
||||
printf(";;\tdebug\n");
|
||||
#endif
|
||||
} else {
|
||||
/* XXX - print a warning here? */
|
||||
}
|
||||
/* skip to next run of spaces */
|
||||
while (*cp && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef RESOLVSORT
|
||||
/* XXX - should really support CIDR which means explicit masks always. */
|
||||
static u_int32_t
|
||||
net_mask(in) /* XXX - should really use system's version of this */
|
||||
struct in_addr in;
|
||||
{
|
||||
register u_int32_t i = ntohl(in.s_addr);
|
||||
|
||||
if (IN_CLASSA(i))
|
||||
return (htonl(IN_CLASSA_NET));
|
||||
else if (IN_CLASSB(i))
|
||||
return (htonl(IN_CLASSB_NET));
|
||||
return (htonl(IN_CLASSC_NET));
|
||||
}
|
||||
#endif
|
||||
|
||||
u_int16_t
|
||||
res_randomid()
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
|
||||
}
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1985, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: res_mkquery.c,v 1.6 1995/08/21 09:15:37 bde Exp $";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <resolv.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "res_config.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 u_char *data; /* resource record data */
|
||||
int datalen; /* length of data */
|
||||
const u_char *newrr_in; /* new rr for modify or append */
|
||||
u_char *buf; /* buffer to put query */
|
||||
int buflen; /* size of buffer */
|
||||
{
|
||||
register HEADER *hp;
|
||||
register u_char *cp;
|
||||
register int n;
|
||||
#ifdef ALLOW_UPDATES
|
||||
struct rrec *newrr = (struct rrec *) newrr_in;
|
||||
#endif
|
||||
u_char *dnptrs[20], **dpp, **lastdnptr;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (-1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_mkquery(%d, %s, %d, %d)\n",
|
||||
op, dname, class, type);
|
||||
#endif
|
||||
/*
|
||||
* Initialize header fields.
|
||||
*/
|
||||
if ((buf == NULL) || (buflen < HFIXEDSZ))
|
||||
return (-1);
|
||||
bzero(buf, HFIXEDSZ);
|
||||
hp = (HEADER *) buf;
|
||||
hp->id = htons(++_res.id);
|
||||
hp->opcode = op;
|
||||
hp->rd = (_res.options & RES_RECURSE) != 0;
|
||||
hp->rcode = NOERROR;
|
||||
cp = buf + HFIXEDSZ;
|
||||
buflen -= HFIXEDSZ;
|
||||
dpp = dnptrs;
|
||||
*dpp++ = buf;
|
||||
*dpp++ = NULL;
|
||||
lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
|
||||
/*
|
||||
* perform opcode specific processing
|
||||
*/
|
||||
switch (op) {
|
||||
case QUERY: /*FALLTHROUGH*/
|
||||
case NS_NOTIFY_OP:
|
||||
if ((buflen -= QFIXEDSZ) < 0)
|
||||
return (-1);
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
buflen -= n;
|
||||
__putshort(type, cp);
|
||||
cp += INT16SZ;
|
||||
__putshort(class, cp);
|
||||
cp += INT16SZ;
|
||||
hp->qdcount = htons(1);
|
||||
if (op == QUERY || data == NULL)
|
||||
break;
|
||||
/*
|
||||
* Make an additional record for completion domain.
|
||||
*/
|
||||
buflen -= RRFIXEDSZ;
|
||||
n = dn_comp((char *)data, cp, buflen, dnptrs, lastdnptr);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
buflen -= n;
|
||||
__putshort(T_NULL, cp);
|
||||
cp += INT16SZ;
|
||||
__putshort(class, cp);
|
||||
cp += INT16SZ;
|
||||
__putlong(0, cp);
|
||||
cp += INT32SZ;
|
||||
__putshort(0, cp);
|
||||
cp += INT16SZ;
|
||||
hp->arcount = htons(1);
|
||||
break;
|
||||
|
||||
case IQUERY:
|
||||
/*
|
||||
* Initialize answer section
|
||||
*/
|
||||
if (buflen < 1 + RRFIXEDSZ + datalen)
|
||||
return (-1);
|
||||
*cp++ = '\0'; /* no domain name */
|
||||
__putshort(type, cp);
|
||||
cp += INT16SZ;
|
||||
__putshort(class, cp);
|
||||
cp += INT16SZ;
|
||||
__putlong(0, cp);
|
||||
cp += INT32SZ;
|
||||
__putshort(datalen, cp);
|
||||
cp += INT16SZ;
|
||||
if (datalen) {
|
||||
bcopy(data, cp, datalen);
|
||||
cp += datalen;
|
||||
}
|
||||
hp->ancount = htons(1);
|
||||
break;
|
||||
|
||||
#ifdef ALLOW_UPDATES
|
||||
/*
|
||||
* For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
|
||||
* (Record to be modified is followed by its replacement in msg.)
|
||||
*/
|
||||
case UPDATEM:
|
||||
case UPDATEMA:
|
||||
|
||||
case UPDATED:
|
||||
/*
|
||||
* The res code for UPDATED and UPDATEDA is the same; user
|
||||
* calls them differently: specifies data for UPDATED; server
|
||||
* ignores data if specified for UPDATEDA.
|
||||
*/
|
||||
case UPDATEDA:
|
||||
buflen -= RRFIXEDSZ + datalen;
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
__putshort(type, cp);
|
||||
cp += INT16SZ;
|
||||
__putshort(class, cp);
|
||||
cp += INT16SZ;
|
||||
__putlong(0, cp);
|
||||
cp += INT32SZ;
|
||||
__putshort(datalen, cp);
|
||||
cp += INT16SZ;
|
||||
if (datalen) {
|
||||
bcopy(data, cp, datalen);
|
||||
cp += datalen;
|
||||
}
|
||||
if ( (op == UPDATED) || (op == UPDATEDA) ) {
|
||||
hp->ancount = htons(0);
|
||||
break;
|
||||
}
|
||||
/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
|
||||
|
||||
case UPDATEA: /* Add new resource record */
|
||||
buflen -= RRFIXEDSZ + datalen;
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
__putshort(newrr->r_type, cp);
|
||||
cp += INT16SZ;
|
||||
__putshort(newrr->r_class, cp);
|
||||
cp += INT16SZ;
|
||||
__putlong(0, cp);
|
||||
cp += INT32SZ;
|
||||
__putshort(newrr->r_size, cp);
|
||||
cp += INT16SZ;
|
||||
if (newrr->r_size) {
|
||||
bcopy(newrr->r_data, cp, newrr->r_size);
|
||||
cp += newrr->r_size;
|
||||
}
|
||||
hp->ancount = htons(0);
|
||||
break;
|
||||
#endif /* ALLOW_UPDATES */
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
return (cp - buf);
|
||||
}
|
||||
|
|
@ -1,383 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: res_query.c,v 1.6 1995/08/21 09:15:39 bde 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 <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "res_config.h"
|
||||
|
||||
#if PACKETSZ > 1024
|
||||
#define MAXPACKET PACKETSZ
|
||||
#else
|
||||
#define MAXPACKET 1024
|
||||
#endif
|
||||
|
||||
char *__hostalias __P((const char *));
|
||||
int h_errno;
|
||||
|
||||
/*
|
||||
* Formulate a normal query, send, and await answer.
|
||||
* Returned answer is placed in supplied buffer "answer".
|
||||
* Perform preliminary check of answer, returning success only
|
||||
* if no error is indicated and the answer count is nonzero.
|
||||
* Return the size of the response on success, -1 on error.
|
||||
* Error number is left in h_errno.
|
||||
*
|
||||
* Caller must parse answer and determine whether it answers the question.
|
||||
*/
|
||||
int
|
||||
res_query(name, class, type, answer, anslen)
|
||||
const char *name; /* domain name */
|
||||
int class, type; /* class and type of query */
|
||||
u_char *answer; /* buffer to put answer */
|
||||
int anslen; /* size of answer buffer */
|
||||
{
|
||||
u_char buf[MAXPACKET];
|
||||
register HEADER *hp = (HEADER *) answer;
|
||||
int n;
|
||||
|
||||
hp->rcode = NOERROR; /* default */
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (-1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
||||
#endif
|
||||
|
||||
n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
|
||||
buf, sizeof(buf));
|
||||
if (n <= 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_query: mkquery failed\n");
|
||||
#endif
|
||||
h_errno = NO_RECOVERY;
|
||||
return (n);
|
||||
}
|
||||
n = res_send(buf, n, answer, anslen);
|
||||
if (n < 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_query: send error\n");
|
||||
#endif
|
||||
h_errno = TRY_AGAIN;
|
||||
return (n);
|
||||
}
|
||||
|
||||
if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; rcode = %d, ancount=%d\n", hp->rcode,
|
||||
ntohs(hp->ancount));
|
||||
#endif
|
||||
switch (hp->rcode) {
|
||||
case NXDOMAIN:
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
break;
|
||||
case SERVFAIL:
|
||||
h_errno = TRY_AGAIN;
|
||||
break;
|
||||
case NOERROR:
|
||||
h_errno = NO_DATA;
|
||||
break;
|
||||
case FORMERR:
|
||||
case NOTIMP:
|
||||
case REFUSED:
|
||||
default:
|
||||
h_errno = NO_RECOVERY;
|
||||
break;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Formulate a normal query, send, and retrieve answer in supplied buffer.
|
||||
* Return the size of the response on success, -1 on error.
|
||||
* If enabled, implement search rules until answer or unrecoverable failure
|
||||
* is detected. Error code, if any, is left in h_errno.
|
||||
*/
|
||||
int
|
||||
res_search(name, class, type, answer, anslen)
|
||||
const char *name; /* domain name */
|
||||
int class, type; /* class and type of query */
|
||||
u_char *answer; /* buffer to put answer */
|
||||
int anslen; /* size of answer */
|
||||
{
|
||||
register const char *cp, * const *domain;
|
||||
HEADER *hp = (HEADER *) answer;
|
||||
u_int dots;
|
||||
int trailing_dot, ret, saved_herrno;
|
||||
int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (-1);
|
||||
}
|
||||
errno = 0;
|
||||
h_errno = HOST_NOT_FOUND; /* default, if we never query */
|
||||
dots = 0;
|
||||
for (cp = name; *cp; cp++)
|
||||
dots += (*cp == '.');
|
||||
trailing_dot = 0;
|
||||
if (cp > name && *--cp == '.')
|
||||
trailing_dot++;
|
||||
|
||||
/*
|
||||
* if there aren't any dots, it could be a user-level alias
|
||||
*/
|
||||
if (!dots && (cp = __hostalias(name)) != NULL)
|
||||
return (res_query(cp, class, type, answer, anslen));
|
||||
|
||||
/*
|
||||
* If there are dots in the name already, let's just give it a try
|
||||
* 'as is'. The threshold can be set with the "ndots" option.
|
||||
*/
|
||||
saved_herrno = -1;
|
||||
if (dots >= _res.ndots) {
|
||||
ret = res_querydomain(name, NULL, class, type, answer, anslen);
|
||||
if (ret > 0)
|
||||
return (ret);
|
||||
saved_herrno = h_errno;
|
||||
tried_as_is++;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do at least one level of search if
|
||||
* - there is no dot and RES_DEFNAME is set, or
|
||||
* - there is at least one dot, there is no trailing dot,
|
||||
* and RES_DNSRCH is set.
|
||||
*/
|
||||
if ((!dots && (_res.options & RES_DEFNAMES)) ||
|
||||
(dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
|
||||
int done = 0;
|
||||
|
||||
for (domain = (const char * const *)_res.dnsrch;
|
||||
*domain && !done;
|
||||
domain++) {
|
||||
|
||||
ret = res_querydomain(name, *domain, class, type,
|
||||
answer, anslen);
|
||||
if (ret > 0)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* If no server present, give up.
|
||||
* If name isn't found in this domain,
|
||||
* keep trying higher domains in the search list
|
||||
* (if that's enabled).
|
||||
* On a NO_DATA error, keep trying, otherwise
|
||||
* a wildcard entry of another type could keep us
|
||||
* from finding this entry higher in the domain.
|
||||
* If we get some other error (negative answer or
|
||||
* server failure), then stop searching up,
|
||||
* but try the input name below in case it's
|
||||
* fully-qualified.
|
||||
*/
|
||||
if (errno == ECONNREFUSED) {
|
||||
h_errno = TRY_AGAIN;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
switch (h_errno) {
|
||||
case NO_DATA:
|
||||
got_nodata++;
|
||||
/* FALLTHROUGH */
|
||||
case HOST_NOT_FOUND:
|
||||
/* keep trying */
|
||||
break;
|
||||
case TRY_AGAIN:
|
||||
if (hp->rcode == SERVFAIL) {
|
||||
/* try next search element, if any */
|
||||
got_servfail++;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
/* anything else implies that we're done */
|
||||
done++;
|
||||
}
|
||||
|
||||
/* if we got here for some reason other than DNSRCH,
|
||||
* we only wanted one iteration of the loop, so stop.
|
||||
*/
|
||||
if (!(_res.options & RES_DNSRCH))
|
||||
done++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if we have not already tried the name "as is", do that now.
|
||||
* note that we do this regardless of how many dots were in the
|
||||
* name or whether it ends with a dot.
|
||||
*/
|
||||
if (!tried_as_is) {
|
||||
ret = res_querydomain(name, NULL, class, type, answer, anslen);
|
||||
if (ret > 0)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* if we got here, we didn't satisfy the search.
|
||||
* if we did an initial full query, return that query's h_errno
|
||||
* (note that we wouldn't be here if that query had succeeded).
|
||||
* else if we ever got a nodata, send that back as the reason.
|
||||
* else send back meaningless h_errno, that being the one from
|
||||
* the last DNSRCH we did.
|
||||
*/
|
||||
if (saved_herrno != -1)
|
||||
h_errno = saved_herrno;
|
||||
else if (got_nodata)
|
||||
h_errno = NO_DATA;
|
||||
else if (got_servfail)
|
||||
h_errno = TRY_AGAIN;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform a call on res_query on the concatenation of name and domain,
|
||||
* removing a trailing dot from name if domain is NULL.
|
||||
*/
|
||||
int
|
||||
res_querydomain(name, domain, class, type, answer, anslen)
|
||||
const char *name, *domain;
|
||||
int class, type; /* class and type of query */
|
||||
u_char *answer; /* buffer to put answer */
|
||||
int anslen; /* size of answer */
|
||||
{
|
||||
char nbuf[2*MAXDNAME+2];
|
||||
const char *longname = nbuf;
|
||||
int n;
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
h_errno = NETDB_INTERNAL;
|
||||
return (-1);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf(";; res_querydomain(%s, %s, %d, %d)\n",
|
||||
name, domain?domain:"<Nil>", class, type);
|
||||
#endif
|
||||
if (domain == NULL) {
|
||||
/*
|
||||
* Check for trailing '.';
|
||||
* copy without '.' if present.
|
||||
*/
|
||||
n = strlen(name) - 1;
|
||||
if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
|
||||
bcopy(name, nbuf, n);
|
||||
nbuf[n] = '\0';
|
||||
} else
|
||||
longname = name;
|
||||
} else
|
||||
sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain);
|
||||
|
||||
return (res_query(longname, class, type, answer, anslen));
|
||||
}
|
||||
|
||||
char *
|
||||
__hostalias(name)
|
||||
register const char *name;
|
||||
{
|
||||
register char *cp1, *cp2;
|
||||
FILE *fp;
|
||||
char *file;
|
||||
char buf[BUFSIZ];
|
||||
static char abuf[MAXDNAME];
|
||||
|
||||
if (_res.options & RES_NOALIASES)
|
||||
return (NULL);
|
||||
file = getenv("HOSTALIASES");
|
||||
if (file == NULL || (fp = fopen(file, "r")) == NULL)
|
||||
return (NULL);
|
||||
setbuf(fp, NULL);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
|
||||
;
|
||||
if (!*cp1)
|
||||
break;
|
||||
*cp1 = '\0';
|
||||
if (!strcasecmp(buf, name)) {
|
||||
while (isspace(*++cp1))
|
||||
;
|
||||
if (!*cp1)
|
||||
break;
|
||||
for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
|
||||
;
|
||||
abuf[sizeof(abuf) - 1] = *cp2 = '\0';
|
||||
strncpy(abuf, cp1, sizeof(abuf) - 1);
|
||||
fclose(fp);
|
||||
return (abuf);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return (NULL);
|
||||
}
|
||||
|
|
@ -1,727 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1985, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
* -
|
||||
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies, and that
|
||||
* the name of Digital Equipment Corporation not be used in advertising or
|
||||
* publicity pertaining to distribution of the document or software without
|
||||
* specific, written prior permission.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
* -
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
|
||||
static char rcsid[] = "$Id: res_send.c,v 1.7 1996/01/07 09:15:02 peter 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 res_config.h */
|
||||
|
||||
/*
|
||||
* Send query to name server and wait for reply.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/nameser.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <resolv.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "res_config.h"
|
||||
|
||||
void _res_close __P((void));
|
||||
|
||||
static int s = -1; /* socket used for communications */
|
||||
static int connected = 0; /* is the socket connected */
|
||||
static int vc = 0; /* is the socket a virtual ciruit? */
|
||||
|
||||
#ifndef DEBUG
|
||||
# define Dprint(cond, args) /*empty*/
|
||||
# define DprintQ(cond, args, query, size) /*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, size) if (cond) {\
|
||||
fprintf args;\
|
||||
__fp_nquery(query, size, stdout);\
|
||||
} else {}
|
||||
static void
|
||||
Aerror(file, string, error, address)
|
||||
FILE *file;
|
||||
char *string;
|
||||
int error;
|
||||
struct sockaddr_in address;
|
||||
{
|
||||
int save = errno;
|
||||
|
||||
if (_res.options & RES_DEBUG) {
|
||||
fprintf(file, "res_send: %s ([%s].%u): %s\n",
|
||||
string,
|
||||
inet_ntoa(address.sin_addr),
|
||||
ntohs(address.sin_port),
|
||||
strerror(error));
|
||||
}
|
||||
errno = save;
|
||||
}
|
||||
static void
|
||||
Perror(file, string, error)
|
||||
FILE *file;
|
||||
char *string;
|
||||
int error;
|
||||
{
|
||||
int save = errno;
|
||||
|
||||
if (_res.options & RES_DEBUG) {
|
||||
fprintf(file, "res_send: %s: %s\n",
|
||||
string, strerror(error));
|
||||
}
|
||||
errno = save;
|
||||
}
|
||||
#endif
|
||||
|
||||
static res_send_qhook Qhook = NULL;
|
||||
static res_send_rhook Rhook = NULL;
|
||||
|
||||
void
|
||||
res_send_setqhook(hook)
|
||||
res_send_qhook hook;
|
||||
{
|
||||
|
||||
Qhook = hook;
|
||||
}
|
||||
|
||||
void
|
||||
res_send_setrhook(hook)
|
||||
res_send_rhook hook;
|
||||
{
|
||||
|
||||
Rhook = hook;
|
||||
}
|
||||
|
||||
/* int
|
||||
* res_isourserver(ina)
|
||||
* looks up "ina" in _res.ns_addr_list[]
|
||||
* returns:
|
||||
* 0 : not found
|
||||
* >0 : found
|
||||
* author:
|
||||
* paul vixie, 29may94
|
||||
*/
|
||||
int
|
||||
res_isourserver(inp)
|
||||
const struct sockaddr_in *inp;
|
||||
{
|
||||
struct sockaddr_in ina;
|
||||
register int ns, ret;
|
||||
|
||||
ina = *inp;
|
||||
ret = 0;
|
||||
for (ns = 0; ns < _res.nscount; ns++) {
|
||||
register const struct sockaddr_in *srv = &_res.nsaddr_list[ns];
|
||||
|
||||
if (srv->sin_family == ina.sin_family &&
|
||||
srv->sin_port == ina.sin_port &&
|
||||
(srv->sin_addr.s_addr == INADDR_ANY ||
|
||||
srv->sin_addr.s_addr == ina.sin_addr.s_addr)) {
|
||||
ret++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* int
|
||||
* res_nameinquery(name, type, class, buf, eom)
|
||||
* look for (name,type,class) in the query section of packet (buf,eom)
|
||||
* returns:
|
||||
* -1 : format error
|
||||
* 0 : not found
|
||||
* >0 : found
|
||||
* author:
|
||||
* paul vixie, 29may94
|
||||
*/
|
||||
int
|
||||
res_nameinquery(name, type, class, buf, eom)
|
||||
const char *name;
|
||||
register int type, class;
|
||||
const u_char *buf, *eom;
|
||||
{
|
||||
register const u_char *cp = buf + HFIXEDSZ;
|
||||
int qdcount = ntohs(((HEADER*)buf)->qdcount);
|
||||
|
||||
while (qdcount-- > 0) {
|
||||
char tname[MAXDNAME+1];
|
||||
register int n, ttype, tclass;
|
||||
|
||||
n = dn_expand(buf, eom, cp, tname, sizeof tname);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
ttype = _getshort(cp); cp += INT16SZ;
|
||||
tclass = _getshort(cp); cp += INT16SZ;
|
||||
if (ttype == type &&
|
||||
tclass == class &&
|
||||
strcasecmp(tname, name) == 0)
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* int
|
||||
* res_queriesmatch(buf1, eom1, buf2, eom2)
|
||||
* is there a 1:1 mapping of (name,type,class)
|
||||
* in (buf1,eom1) and (buf2,eom2)?
|
||||
* returns:
|
||||
* -1 : format error
|
||||
* 0 : not a 1:1 mapping
|
||||
* >0 : is a 1:1 mapping
|
||||
* author:
|
||||
* paul vixie, 29may94
|
||||
*/
|
||||
int
|
||||
res_queriesmatch(buf1, eom1, buf2, eom2)
|
||||
const u_char *buf1, *eom1;
|
||||
const u_char *buf2, *eom2;
|
||||
{
|
||||
register const u_char *cp = buf1 + HFIXEDSZ;
|
||||
int qdcount = ntohs(((HEADER*)buf1)->qdcount);
|
||||
|
||||
if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
|
||||
return (0);
|
||||
while (qdcount-- > 0) {
|
||||
char tname[MAXDNAME+1];
|
||||
register int n, ttype, tclass;
|
||||
|
||||
n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
|
||||
if (n < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
ttype = _getshort(cp); cp += INT16SZ;
|
||||
tclass = _getshort(cp); cp += INT16SZ;
|
||||
if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int
|
||||
res_send(buf, buflen, ans, anssiz)
|
||||
const u_char *buf;
|
||||
int buflen;
|
||||
u_char *ans;
|
||||
int anssiz;
|
||||
{
|
||||
HEADER *hp = (HEADER *) buf;
|
||||
HEADER *anhp = (HEADER *) ans;
|
||||
int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
|
||||
register int n;
|
||||
u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
|
||||
|
||||
if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
|
||||
/* errno should have been set by res_init() in this case. */
|
||||
return (-1);
|
||||
}
|
||||
DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY),
|
||||
(stdout, ";; res_send()\n"), buf, buflen);
|
||||
v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
|
||||
gotsomewhere = 0;
|
||||
connreset = 0;
|
||||
terrno = ETIMEDOUT;
|
||||
badns = 0;
|
||||
|
||||
/*
|
||||
* Send request, RETRY times, or until successful
|
||||
*/
|
||||
for (try = 0; try < _res.retry; try++) {
|
||||
for (ns = 0; ns < _res.nscount; ns++) {
|
||||
struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
|
||||
same_ns:
|
||||
if (badns & (1 << ns)) {
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
|
||||
if (Qhook) {
|
||||
int done = 0, loops = 0;
|
||||
|
||||
do {
|
||||
res_sendhookact act;
|
||||
|
||||
act = (*Qhook)(&nsap, &buf, &buflen,
|
||||
ans, anssiz, &resplen);
|
||||
switch (act) {
|
||||
case res_goahead:
|
||||
done = 1;
|
||||
break;
|
||||
case res_nextns:
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
case res_done:
|
||||
return (resplen);
|
||||
case res_modified:
|
||||
/* give the hook another try */
|
||||
if (++loops < 42) /*doug adams*/
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
case res_error:
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
|
||||
Dprint(_res.options & RES_DEBUG,
|
||||
(stdout, ";; Querying server (# %d) address = %s\n",
|
||||
ns + 1, inet_ntoa(nsap->sin_addr)));
|
||||
|
||||
if (v_circuit) {
|
||||
int truncated;
|
||||
struct iovec iov[2];
|
||||
u_short len;
|
||||
u_char *cp;
|
||||
|
||||
/*
|
||||
* Use virtual circuit;
|
||||
* at most one attempt per server.
|
||||
*/
|
||||
try = _res.retry;
|
||||
truncated = 0;
|
||||
if ((s < 0) || (!vc)) {
|
||||
if (s >= 0)
|
||||
_res_close();
|
||||
|
||||
s = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "socket(vc)", errno);
|
||||
return (-1);
|
||||
}
|
||||
errno = 0;
|
||||
if (connect(s, (struct sockaddr *)nsap,
|
||||
sizeof(struct sockaddr)) < 0) {
|
||||
terrno = errno;
|
||||
Aerror(stderr, "connect/vc",
|
||||
errno, *nsap);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
vc = 1;
|
||||
}
|
||||
/*
|
||||
* Send length & message
|
||||
*/
|
||||
putshort((u_short)buflen, (u_char*)&len);
|
||||
iov[0].iov_base = (caddr_t)&len;
|
||||
iov[0].iov_len = INT16SZ;
|
||||
iov[1].iov_base = (caddr_t)buf;
|
||||
iov[1].iov_len = buflen;
|
||||
if (writev(s, iov, 2) != (INT16SZ + buflen)) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "write failed", errno);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
/*
|
||||
* Receive length & response
|
||||
*/
|
||||
cp = ans;
|
||||
len = INT16SZ;
|
||||
while ((n = read(s, (char *)cp, (int)len)) > 0) {
|
||||
cp += n;
|
||||
if ((len -= n) <= 0)
|
||||
break;
|
||||
}
|
||||
if (n <= 0) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "read failed", errno);
|
||||
_res_close();
|
||||
/*
|
||||
* A long running process might get its TCP
|
||||
* connection reset if the remote server was
|
||||
* restarted. Requery the server instead of
|
||||
* trying a new one. When there is only one
|
||||
* server, this means that a query might work
|
||||
* instead of failing. We only allow one reset
|
||||
* per query to prevent looping.
|
||||
*/
|
||||
if (terrno == ECONNRESET && !connreset) {
|
||||
connreset = 1;
|
||||
_res_close();
|
||||
goto same_ns;
|
||||
}
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
resplen = _getshort(ans);
|
||||
if (resplen > anssiz) {
|
||||
Dprint(_res.options & RES_DEBUG,
|
||||
(stdout, ";; response truncated\n")
|
||||
);
|
||||
truncated = 1;
|
||||
len = anssiz;
|
||||
} else
|
||||
len = resplen;
|
||||
cp = ans;
|
||||
while (len != 0 &&
|
||||
(n = read(s, (char *)cp, (int)len)) > 0) {
|
||||
cp += n;
|
||||
len -= n;
|
||||
}
|
||||
if (n <= 0) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "read(vc)", errno);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
if (truncated) {
|
||||
/*
|
||||
* Flush rest of answer
|
||||
* so connection stays in synch.
|
||||
*/
|
||||
anhp->tc = 1;
|
||||
len = resplen - anssiz;
|
||||
while (len != 0) {
|
||||
char junk[PACKETSZ];
|
||||
|
||||
n = (len > sizeof(junk)
|
||||
? sizeof(junk)
|
||||
: len);
|
||||
if ((n = read(s, junk, n)) > 0)
|
||||
len -= n;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Use datagrams.
|
||||
*/
|
||||
struct timeval timeout;
|
||||
fd_set dsmask;
|
||||
struct sockaddr_in from;
|
||||
int fromlen;
|
||||
|
||||
if ((s < 0) || vc) {
|
||||
if (vc)
|
||||
_res_close();
|
||||
s = socket(PF_INET, SOCK_DGRAM, 0);
|
||||
if (s < 0) {
|
||||
terrno = errno;
|
||||
Perror(stderr, "socket(dg)", errno);
|
||||
return (-1);
|
||||
}
|
||||
connected = 0;
|
||||
}
|
||||
/*
|
||||
* On a 4.3BSD+ machine (client and server,
|
||||
* actually), sending to a nameserver datagram
|
||||
* port with no nameserver will cause an
|
||||
* ICMP port unreachable message to be returned.
|
||||
* If our datagram socket is "connected" to the
|
||||
* server, we get an ECONNREFUSED error on the next
|
||||
* socket operation, and select returns if the
|
||||
* error message is received. We can thus detect
|
||||
* the absence of a nameserver without timing out.
|
||||
* If we have sent queries to at least two servers,
|
||||
* however, we don't want to remain connected,
|
||||
* as we wish to receive answers from the first
|
||||
* server to respond.
|
||||
*/
|
||||
if (_res.nscount == 1 || (try == 0 && ns == 0)) {
|
||||
/*
|
||||
* Connect only if we are sure we won't
|
||||
* receive a response from another server.
|
||||
*/
|
||||
if (!connected) {
|
||||
if (connect(s, (struct sockaddr *)nsap,
|
||||
sizeof(struct sockaddr)
|
||||
) < 0) {
|
||||
Aerror(stderr,
|
||||
"connect(dg)",
|
||||
errno, *nsap);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
connected = 1;
|
||||
}
|
||||
if (send(s, (char*)buf, buflen, 0) != buflen) {
|
||||
Perror(stderr, "send", errno);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Disconnect if we want to listen
|
||||
* for responses from more than one server.
|
||||
*/
|
||||
if (connected) {
|
||||
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, (char*)buf, buflen, 0,
|
||||
(struct sockaddr *)nsap,
|
||||
sizeof(struct sockaddr))
|
||||
!= buflen) {
|
||||
Aerror(stderr, "sendto", errno, *nsap);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for reply
|
||||
*/
|
||||
timeout.tv_sec = (_res.retrans << try);
|
||||
if (try > 0)
|
||||
timeout.tv_sec /= _res.nscount;
|
||||
if ((long) timeout.tv_sec <= 0)
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
wait:
|
||||
FD_ZERO(&dsmask);
|
||||
FD_SET(s, &dsmask);
|
||||
n = select(s+1, &dsmask, (fd_set *)NULL,
|
||||
(fd_set *)NULL, &timeout);
|
||||
if (n < 0) {
|
||||
Perror(stderr, "select", errno);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
if (n == 0) {
|
||||
/*
|
||||
* timeout
|
||||
*/
|
||||
Dprint(_res.options & RES_DEBUG,
|
||||
(stdout, ";; timeout\n"));
|
||||
gotsomewhere = 1;
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
errno = 0;
|
||||
fromlen = sizeof(struct sockaddr_in);
|
||||
resplen = recvfrom(s, (char*)ans, anssiz, 0,
|
||||
(struct sockaddr *)&from, &fromlen);
|
||||
if (resplen <= 0) {
|
||||
Perror(stderr, "recvfrom", errno);
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
}
|
||||
gotsomewhere = 1;
|
||||
if (hp->id != anhp->id) {
|
||||
/*
|
||||
* response from old query, ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; old answer:\n"),
|
||||
ans, resplen);
|
||||
goto wait;
|
||||
}
|
||||
#if CHECK_SRVR_ADDR
|
||||
if (!(_res.options & RES_INSECURE1) &&
|
||||
!res_isourserver(&from)) {
|
||||
/*
|
||||
* response from wrong server? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; not our server:\n"),
|
||||
ans, resplen);
|
||||
goto wait;
|
||||
}
|
||||
#endif
|
||||
if (!(_res.options & RES_INSECURE2) &&
|
||||
!res_queriesmatch(buf, buf + buflen,
|
||||
ans, ans + anssiz)) {
|
||||
/*
|
||||
* response contains wrong query? ignore it.
|
||||
* XXX - potential security hazard could
|
||||
* be detected here.
|
||||
*/
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ";; wrong query name:\n"),
|
||||
ans, resplen);
|
||||
goto wait;
|
||||
}
|
||||
if (anhp->rcode == SERVFAIL ||
|
||||
anhp->rcode == NOTIMP ||
|
||||
anhp->rcode == REFUSED) {
|
||||
DprintQ(_res.options & RES_DEBUG,
|
||||
(stdout, "server rejected query:\n"),
|
||||
ans, resplen);
|
||||
badns |= (1 << ns);
|
||||
_res_close();
|
||||
/* don't retry if called from dig */
|
||||
if (!_res.pfcode)
|
||||
goto next_ns;
|
||||
}
|
||||
if (!(_res.options & RES_IGNTC) && anhp->tc) {
|
||||
/*
|
||||
* get rest of answer;
|
||||
* use TCP with same server.
|
||||
*/
|
||||
Dprint(_res.options & RES_DEBUG,
|
||||
(stdout, ";; truncated answer\n"));
|
||||
v_circuit = 1;
|
||||
_res_close();
|
||||
goto same_ns;
|
||||
}
|
||||
} /*if vc/dg*/
|
||||
Dprint((_res.options & RES_DEBUG) ||
|
||||
((_res.pfcode & RES_PRF_REPLY) &&
|
||||
(_res.pfcode & RES_PRF_HEAD1)),
|
||||
(stdout, ";; got answer:\n"));
|
||||
DprintQ((_res.options & RES_DEBUG) ||
|
||||
(_res.pfcode & RES_PRF_REPLY),
|
||||
(stdout, ""),
|
||||
ans, resplen);
|
||||
/*
|
||||
* If using virtual circuits, we assume that the first server
|
||||
* is preferred over the rest (i.e. it is on the local
|
||||
* machine) and only keep that one open.
|
||||
* If we have temporarily opened a virtual circuit,
|
||||
* or if we haven't been asked to keep a socket open,
|
||||
* close the socket.
|
||||
*/
|
||||
if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
|
||||
!(_res.options & RES_STAYOPEN)) {
|
||||
_res_close();
|
||||
}
|
||||
if (Rhook) {
|
||||
int done = 0, loops = 0;
|
||||
|
||||
do {
|
||||
res_sendhookact act;
|
||||
|
||||
act = (*Rhook)(nsap, buf, buflen,
|
||||
ans, anssiz, &resplen);
|
||||
switch (act) {
|
||||
case res_goahead:
|
||||
case res_done:
|
||||
done = 1;
|
||||
break;
|
||||
case res_nextns:
|
||||
_res_close();
|
||||
goto next_ns;
|
||||
case res_modified:
|
||||
/* give the hook another try */
|
||||
if (++loops < 42) /*doug adams*/
|
||||
break;
|
||||
/*FALLTHROUGH*/
|
||||
case res_error:
|
||||
/*FALLTHROUGH*/
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
}
|
||||
return (resplen);
|
||||
next_ns: ;
|
||||
} /*foreach ns*/
|
||||
} /*foreach retry*/
|
||||
_res_close();
|
||||
if (!v_circuit)
|
||||
if (!gotsomewhere)
|
||||
errno = ECONNREFUSED; /* no nameservers found */
|
||||
else
|
||||
errno = ETIMEDOUT; /* no answer obtained */
|
||||
else
|
||||
errno = terrno;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is for closing the socket if a virtual circuit is used and
|
||||
* the program wants to close it. This provides support for endhostent()
|
||||
* which expects to close the socket.
|
||||
*
|
||||
* This routine is not expected to be user visible.
|
||||
*/
|
||||
void
|
||||
_res_close(void)
|
||||
{
|
||||
if (s >= 0) {
|
||||
(void) close(s);
|
||||
s = -1;
|
||||
connected = 0;
|
||||
vc = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,323 +0,0 @@
|
|||
.\" Copyright (c) 1985, 1991, 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.
|
||||
.\"
|
||||
.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dt RESOLVER 3
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm res_query ,
|
||||
.Nm res_search ,
|
||||
.Nm res_mkquery ,
|
||||
.Nm res_send ,
|
||||
.Nm res_init ,
|
||||
.Nm dn_comp ,
|
||||
.Nm dn_expand
|
||||
.Nd resolver routines
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <sys/types.h>
|
||||
.Fd #include <netinet/in.h>
|
||||
.Fd #include <arpa/nameser.h>
|
||||
.Fd #include <resolv.h>
|
||||
.Fo res_query
|
||||
.Fa "char *dname"
|
||||
.Fa "int class"
|
||||
.Fa "int type"
|
||||
.Fa "u_char *answer"
|
||||
.Fa "int anslen"
|
||||
.Fc
|
||||
.Fo res_search
|
||||
.Fa "char *dname"
|
||||
.Fa "int class"
|
||||
.Fa "int type"
|
||||
.Fa "u_char *answer"
|
||||
.Fa "int anslen"
|
||||
.Fc
|
||||
.Fo res_mkquery
|
||||
.Fa "int op"
|
||||
.Fa "char *dname"
|
||||
.Fa "int class"
|
||||
.Fa "int type"
|
||||
.Fa "char *data"
|
||||
.Fa "int datalen"
|
||||
.Fa "struct rrec *newrr"
|
||||
.Fa "char *buf"
|
||||
.Fa "int buflen"
|
||||
.Fc
|
||||
.Fo res_send
|
||||
.Fa "char *msg"
|
||||
.Fa "int msglen"
|
||||
.Fa "char *answer"
|
||||
.Fa "int anslen"
|
||||
.Fc
|
||||
.Fn res_init
|
||||
.Fo dn_comp
|
||||
.Fa "char *exp_dn"
|
||||
.Fa "char *comp_dn"
|
||||
.Fa "int length"
|
||||
.Fa "char **dnptrs"
|
||||
.Fa "char **lastdnptr"
|
||||
.Fc
|
||||
.Fo dn_expand
|
||||
.Fa "u_char *msg"
|
||||
.Fa "u_char *eomorig"
|
||||
.Fa "u_char *comp_dn"
|
||||
.Fa "u_char *exp_dn"
|
||||
.Fa "int length"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
These routines are used for making, sending and interpreting
|
||||
query and reply messages with Internet domain name servers.
|
||||
.Pp
|
||||
Global configuration and state information that is used by the
|
||||
resolver routines is kept in the structure
|
||||
.Em _res .
|
||||
Most of the values have reasonable defaults and can be ignored.
|
||||
Options
|
||||
stored in
|
||||
.Em _res.options
|
||||
are defined in
|
||||
.Pa resolv.h
|
||||
and are as follows.
|
||||
Options are stored as a simple bit mask containing the bitwise ``or''
|
||||
of the options enabled.
|
||||
.Bl -tag -width RES_DEFNAMES
|
||||
.It Dv RES_INIT
|
||||
True if the initial name server address and default domain name are
|
||||
initialized (i.e.,
|
||||
.Fn res_init
|
||||
has been called).
|
||||
.It Dv RES_DEBUG
|
||||
Print debugging messages.
|
||||
.It Dv RES_AAONLY
|
||||
Accept authoritative answers only.
|
||||
With this option,
|
||||
.Fn res_send
|
||||
should continue until it finds an authoritative answer or finds an error.
|
||||
Currently this is not implemented.
|
||||
.It Dv RES_USEVC
|
||||
Use
|
||||
.Tn TCP
|
||||
connections for queries instead of
|
||||
.Tn UDP
|
||||
datagrams.
|
||||
.It Dv RES_STAYOPEN
|
||||
Used with
|
||||
.Dv RES_USEVC
|
||||
to keep the
|
||||
.Tn TCP
|
||||
connection open between
|
||||
queries.
|
||||
This is useful only in programs that regularly do many queries.
|
||||
.Tn UDP
|
||||
should be the normal mode used.
|
||||
.It Dv RES_IGNTC
|
||||
Unused currently (ignore truncation errors, i.e., don't retry with
|
||||
.Tn TCP ) .
|
||||
.It Dv RES_RECURSE
|
||||
Set the recursion-desired bit in queries.
|
||||
This is the default.
|
||||
.Pf ( Fn res_send
|
||||
does not do iterative queries and expects the name server
|
||||
to handle recursion.)
|
||||
.It Dv RES_DEFNAMES
|
||||
If set,
|
||||
.Fn res_search
|
||||
will append the default domain name to single-component names
|
||||
(those that do not contain a dot).
|
||||
This option is enabled by default.
|
||||
.It Dv RES_DNSRCH
|
||||
If this option is set,
|
||||
.Fn res_search
|
||||
will search for host names in the current domain and in parent domains; see
|
||||
.Xr hostname 7 .
|
||||
This is used by the standard host lookup routine
|
||||
.Xr gethostbyname 3 .
|
||||
This option is enabled by default.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn res_init
|
||||
routine
|
||||
reads the configuration file (if any; see
|
||||
.Xr resolver 5 )
|
||||
to get the default domain name,
|
||||
search list and
|
||||
the Internet address of the local name server(s).
|
||||
If no server is configured, the host running
|
||||
the resolver is tried.
|
||||
The current domain name is defined by the hostname
|
||||
if not specified in the configuration file;
|
||||
it can be overridden by the environment variable
|
||||
.Ev LOCALDOMAIN .
|
||||
Initialization normally occurs on the first call
|
||||
to one of the following routines.
|
||||
.Pp
|
||||
The
|
||||
.Fn res_query
|
||||
function provides an interface to the server query mechanism.
|
||||
It constructs a query, sends it to the local server,
|
||||
awaits a response, and makes preliminary checks on the reply.
|
||||
The query requests information of the specified
|
||||
.Fa type
|
||||
and
|
||||
.Fa class
|
||||
for the specified fully-qualified domain name
|
||||
.Fa dname .
|
||||
The reply message is left in the
|
||||
.Fa answer
|
||||
buffer with length
|
||||
.Fa anslen
|
||||
supplied by the caller.
|
||||
.Pp
|
||||
The
|
||||
.Fn res_search
|
||||
routine makes a query and awaits a response like
|
||||
.Fn res_query ,
|
||||
but in addition, it implements the default and search rules
|
||||
controlled by the
|
||||
.Dv RES_DEFNAMES
|
||||
and
|
||||
.Dv RES_DNSRCH
|
||||
options.
|
||||
It returns the first successful reply.
|
||||
.Pp
|
||||
The remaining routines are lower-level routines used by
|
||||
.Fn res_query .
|
||||
The
|
||||
.Fn res_mkquery
|
||||
function
|
||||
constructs a standard query message and places it in
|
||||
.Fa buf .
|
||||
It returns the size of the query, or \-1 if the query is
|
||||
larger than
|
||||
.Fa buflen .
|
||||
The query type
|
||||
.Fa op
|
||||
is usually
|
||||
.Dv QUERY ,
|
||||
but can be any of the query types defined in
|
||||
.Aq Pa arpa/nameser.h .
|
||||
The domain name for the query is given by
|
||||
.Fa dname .
|
||||
.Fa Newrr
|
||||
is currently unused but is intended for making update messages.
|
||||
.Pp
|
||||
The
|
||||
.Fn res_send
|
||||
routine
|
||||
sends a pre-formatted query and returns an answer.
|
||||
It will call
|
||||
.Fn res_init
|
||||
if
|
||||
.Dv RES_INIT
|
||||
is not set, send the query to the local name server, and
|
||||
handle timeouts and retries.
|
||||
The length of the reply message is returned, or
|
||||
\-1 if there were errors.
|
||||
.Pp
|
||||
The
|
||||
.Fn dn_comp
|
||||
function
|
||||
compresses the domain name
|
||||
.Fa exp_dn
|
||||
and stores it in
|
||||
.Fa comp_dn .
|
||||
The size of the compressed name is returned or \-1 if there were errors.
|
||||
The size of the array pointed to by
|
||||
.Fa comp_dn
|
||||
is given by
|
||||
.Fa length .
|
||||
The compression uses
|
||||
an array of pointers
|
||||
.Fa dnptrs
|
||||
to previously-compressed names in the current message.
|
||||
The first pointer points to
|
||||
to the beginning of the message and the list ends with
|
||||
.Dv NULL .
|
||||
The limit to the array is specified by
|
||||
.Fa lastdnptr .
|
||||
A side effect of
|
||||
.Fn dn_comp
|
||||
is to update the list of pointers for
|
||||
labels inserted into the message
|
||||
as the name is compressed.
|
||||
If
|
||||
.Em dnptr
|
||||
is
|
||||
.Dv NULL, names are not compressed.
|
||||
If
|
||||
.Fa lastdnptr
|
||||
is
|
||||
.Dv NULL ,
|
||||
the list of labels is not updated.
|
||||
.Pp
|
||||
The
|
||||
.Fn dn_expand
|
||||
entry
|
||||
expands the compressed domain name
|
||||
.Fa comp_dn
|
||||
to a full domain name
|
||||
The compressed name is contained in a query or reply message;
|
||||
.Fa msg
|
||||
is a pointer to the beginning of the message.
|
||||
The uncompressed name is placed in the buffer indicated by
|
||||
.Fa exp_dn
|
||||
which is of size
|
||||
.Fa length .
|
||||
The size of compressed name is returned or \-1 if there was an error.
|
||||
.Sh FILES
|
||||
.Bl -tag -width Pa
|
||||
/etc/resolv.conf
|
||||
The configuration file
|
||||
see
|
||||
.Xr resolver 5 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr gethostbyname 3 ,
|
||||
.Xr named 8 ,
|
||||
.Xr resolver 5 ,
|
||||
.Xr hostname 7 ,
|
||||
.Pp
|
||||
.%T RFC1032 ,
|
||||
.%T RFC1033 ,
|
||||
.%T RFC1034 ,
|
||||
.%T RFC1035 ,
|
||||
.%T RFC974
|
||||
.Rs
|
||||
.%T "Name Server Operations Guide for BIND"
|
||||
.Re
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
function appeared in
|
||||
.Bx 4.3 .
|
||||
Loading…
Reference in a new issue