summaryrefslogtreecommitdiff
path: root/resolv/gethnamaddr.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/gethnamaddr.c')
-rw-r--r--resolv/gethnamaddr.c457
1 files changed, 328 insertions, 129 deletions
diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c
index 96248bc0de..35e9007ca7 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/gethnamaddr.c
@@ -1,8 +1,8 @@
/*
- * ++Copyright++ 1985, 1988
+ * ++Copyright++ 1985, 1988, 1993
* -
- * Copyright (c) 1985, 1988 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -54,7 +54,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)gethostnamadr.c 6.47 (Berkeley) 6/18/92";
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
static char rcsid[] = "$Id$";
#endif /* LIBC_SCCS and not lint */
@@ -63,27 +63,47 @@ static char rcsid[] = "$Id$";
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
+
+#include <stdio.h>
#include <netdb.h>
#include <resolv.h>
-#include <stdio.h>
#include <ctype.h>
#include <errno.h>
-#include "../conf/portability.h"
+#include <syslog.h>
+
+#ifndef LOG_AUTH
+# define LOG_AUTH 0
+#endif
+
+#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
+
+#if defined(BSD) && (BSD >= 199103)
+# include <string.h>
+#else
+# include "../conf/portability.h"
+#endif
+#if defined(USE_OPTIONS_H)
+# include <../conf/options.h>
+#endif
#define MAXALIASES 35
#define MAXADDRS 35
+static const char AskedForGot[] =
+ "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+
static char *h_addr_ptrs[MAXADDRS + 1];
static struct hostent host;
static char *host_aliases[MAXALIASES];
-static char hostbuf[BUFSIZ+1];
+static char hostbuf[8*1024];
static struct in_addr host_addr;
static FILE *hostf = NULL;
-static char hostaddr[MAXADDRS];
-static char *host_addrs[2];
static int stayopen = 0;
-char *strpbrk();
+
+#ifdef RESOLVSORT
+static void addrsort __P((char **, int));
+#endif
#if PACKETSZ > 1024
#define MAXPACKET PACKETSZ
@@ -104,20 +124,23 @@ typedef union {
extern int h_errno;
static struct hostent *
-getanswer(answer, anslen, iquery)
- querybuf *answer;
+getanswer(answer, anslen, qname, qclass, qtype)
+ const querybuf *answer;
int anslen;
- int iquery;
+ const char *qname;
+ int qclass, qtype;
{
- register HEADER *hp;
- register u_char *cp;
+ register const HEADER *hp;
+ register const u_char *cp;
register int n;
- u_char *eom;
- char *bp, **ap;
+ const u_char *eom;
+ char *bp, **ap, **hap;
int type, class, buflen, ancount, qdcount;
- int haveanswer, getclass = C_ANY;
- char **hap;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME+1];
+ host.h_name = NULL;
eom = answer->buf + anslen;
/*
* find first satisfactory answer
@@ -126,31 +149,28 @@ getanswer(answer, anslen, iquery)
ancount = ntohs(hp->ancount);
qdcount = ntohs(hp->qdcount);
bp = hostbuf;
- buflen = sizeof(hostbuf);
- cp = answer->buf + sizeof(HEADER);
- if (qdcount) {
- if (iquery) {
- if ((n = dn_expand((u_char *)answer->buf,
- (u_char *)eom, (u_char *)cp, (u_char *)bp,
- buflen)) < 0) {
- h_errno = NO_RECOVERY;
- return ((struct hostent *) NULL);
- }
- cp += n + QFIXEDSZ;
- host.h_name = bp;
- n = strlen(bp) + 1;
- bp += n;
- buflen -= n;
- } else
- cp += __dn_skipname(cp, eom) + QFIXEDSZ;
- while (--qdcount > 0)
- cp += __dn_skipname(cp, eom) + QFIXEDSZ;
- } else if (iquery) {
- if (hp->aa)
- h_errno = HOST_NOT_FOUND;
- else
- h_errno = TRY_AGAIN;
- return ((struct hostent *) NULL);
+ buflen = sizeof hostbuf;
+ cp = answer->buf + HFIXEDSZ;
+ if (qdcount != 1) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
+ h_errno = NO_RECOVERY;
+ return (NULL);
+ }
+ cp += n + QFIXEDSZ;
+ if (qtype == T_A) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ host.h_name = bp;
+ bp += n;
+ buflen -= n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = host.h_name;
}
ap = host_aliases;
*ap = NULL;
@@ -161,91 +181,174 @@ getanswer(answer, anslen, iquery)
host.h_addr_list = h_addr_ptrs;
#endif
haveanswer = 0;
- while (--ancount >= 0 && cp < eom) {
- if ((n = dn_expand((u_char *)answer->buf, (u_char *)eom,
- (u_char *)cp, (u_char *)bp, buflen)) < 0)
- break;
- cp += n;
+ had_error = 0;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if (n < 0) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
type = _getshort(cp);
- cp += sizeof(u_short);
+ cp += INT16SZ; /* type */
class = _getshort(cp);
- cp += sizeof(u_short) + sizeof(u_int32_t);
+ cp += INT16SZ + INT32SZ; /* class, TTL */
n = _getshort(cp);
- cp += sizeof(u_short);
- if (type == T_CNAME) {
+ cp += INT16SZ; /* len */
+ if (class != qclass) {
+ /* XXX - debug? syslog? */
cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (qtype == T_A && type == T_CNAME) {
if (ap >= &host_aliases[MAXALIASES-1])
continue;
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if (n < 0) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
+ host.h_name, bp);
+ continue; /* XXX - had_error++ ? */
+ }
+ /* Store alias. */
*ap++ = bp;
- n = strlen(bp) + 1;
+ n = strlen(bp) + 1; /* for the \0 */
bp += n;
buflen -= n;
- continue;
- }
- if (iquery && type == T_PTR) {
- if ((n = dn_expand((u_char *)answer->buf,
- (u_char *)eom, (u_char *)cp, (u_char *)bp,
- buflen)) < 0) {
- cp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > buflen) {
+ had_error++;
continue;
}
- cp += n;
+ strcpy(bp, tbuf);
host.h_name = bp;
- return(&host);
+ bp += n;
+ buflen -= n;
+ continue;
}
- if (iquery || type != T_A) {
-#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("unexpected answer type %d, size %d\n",
- type, n);
-#endif
+ if (type != qtype) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.getanswer: asked for type %d(%s), got %d(%s)",
+ qtype, qname, type, bp);
cp += n;
- continue;
+ continue; /* XXX - had_error++ ? */
}
- if (haveanswer) {
- if (n != host.h_length) {
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(qname, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, qname, bp);
cp += n;
- continue;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, buflen);
+ if (n < 0) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (!haveanswer)
+ host.h_name = bp;
+ else if (ap < &host_aliases[MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = strlen(bp) + 1; /* for the \0 */
+ bp += n;
+ buflen -= n;
}
- if (class != getclass) {
+ break;
+#else
+ host.h_name = bp;
+ return (&host);
+#endif
+ case T_A:
+ if (strcasecmp(host.h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, host.h_name, bp);
cp += n;
- continue;
+ continue; /* XXX - had_error++ ? */
}
- } else {
- host.h_length = n;
- getclass = class;
- host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
- if (!iquery) {
+ if (haveanswer) {
+ if (n != host.h_length) {
+ cp += n;
+ continue;
+ }
+ } else {
+ register int nn;
+
+ host.h_length = n;
+ host.h_addrtype = (class == C_IN)
+ ? AF_INET
+ : AF_UNSPEC;
host.h_name = bp;
- bp += strlen(bp) + 1;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ buflen -= nn;
}
- }
- bp += sizeof(align) - ((u_int32_t)bp % sizeof(align));
+ bp += sizeof(align) - ((u_long)bp % sizeof(align));
- if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
+ if (bp + n >= &hostbuf[sizeof hostbuf]) {
#ifdef DEBUG
- if (_res.options & RES_DEBUG)
- printf("size (%d) too big\n", n);
+ if (_res.options & RES_DEBUG)
+ printf("size (%d) too big\n", n);
#endif
+ had_error++;
+ continue;
+ }
+ if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
+ if (_res.options & RES_DEBUG && !toobig++)
+ printf("Too many addresses (%d)\n",
+ MAXADDRS);
+ cp += n;
+ continue;
+ }
+ bcopy(cp, *hap++ = bp, n);
+ bp += n;
+ cp += n;
break;
- }
- bcopy(cp, *hap++ = bp, n);
- bp +=n;
- cp += n;
- haveanswer++;
- }
+ default:
+ abort();
+ } /*switch*/
+ if (!had_error)
+ haveanswer++;
+ } /*while*/
if (haveanswer) {
*ap = NULL;
-#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
*hap = NULL;
+# if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (_res.nsort && haveanswer > 1 &&
+ qclass == C_IN && qtype == T_A)
+ addrsort(h_addr_ptrs, haveanswer);
+# endif /*RESOLVSORT*/
+#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
+ /* nothing */
#else
host.h_addr = h_addr_ptrs[0];
-#endif
+#endif /*BSD*/
+ if (!host.h_name) {
+ n = strlen(qname) + 1; /* for the \0 */
+ strcpy(bp, qname);
+ host.h_name = bp;
+ }
return (&host);
} else {
h_errno = TRY_AGAIN;
- return ((struct hostent *) NULL);
+ return (NULL);
}
}
@@ -274,15 +377,15 @@ gethostbyname(name)
*/
if (!inet_aton(name, &host_addr)) {
h_errno = HOST_NOT_FOUND;
- return((struct hostent *) NULL);
+ return (NULL);
}
host.h_name = (char *)name;
host.h_aliases = host_aliases;
host_aliases[0] = NULL;
host.h_addrtype = AF_INET;
- host.h_length = sizeof(u_int32_t);
+ host.h_length = INT32SZ;
h_addr_ptrs[0] = (char *)&host_addr;
- h_addr_ptrs[1] = (char *)0;
+ h_addr_ptrs[1] = NULL;
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
host.h_addr_list = h_addr_ptrs;
#else
@@ -302,9 +405,9 @@ gethostbyname(name)
if (errno == ECONNREFUSED)
return (_gethtbyname(name));
else
- return ((struct hostent *) NULL);
+ return (NULL);
}
- return (getanswer(&buf, n, 0));
+ return (getanswer(&buf, n, name, C_IN, T_A));
}
struct hostent *
@@ -315,17 +418,22 @@ gethostbyaddr(addr, len, type)
int n;
querybuf buf;
register struct hostent *hp;
- char qbuf[MAXDNAME];
+ char qbuf[MAXDNAME+1];
+#ifdef SUNSECURITY
+ register struct hostent *rhp;
+ char **haddr;
+ u_long old_options;
+#endif /*SUNSECURITY*/
extern struct hostent *_gethtbyaddr();
if (type != AF_INET)
- return ((struct hostent *) NULL);
+ return (NULL);
(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
((unsigned)addr[3] & 0xff),
((unsigned)addr[2] & 0xff),
((unsigned)addr[1] & 0xff),
((unsigned)addr[0] & 0xff));
- n = res_query(qbuf, C_IN, T_PTR, (char *)&buf, sizeof(buf));
+ n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
if (n < 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)
@@ -333,31 +441,57 @@ gethostbyaddr(addr, len, type)
#endif
if (errno == ECONNREFUSED)
return (_gethtbyaddr(addr, len, type));
- return ((struct hostent *) NULL);
+ return (NULL);
+ }
+ if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR)))
+ return (NULL);
+#ifdef SUNSECURITY
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ old_options = _res.options;
+ _res.options &= ~RES_DNSRCH;
+ _res.options |= RES_DEFNAMES;
+ if (!(rhp = gethostbyname(hp->h_name))) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hp->h_name, inet_ntoa(*((struct in_addr *)addr)));
+ _res.options = old_options;
+ return (NULL);
}
- hp = getanswer(&buf, n, 1);
- if (hp == NULL)
- return ((struct hostent *) NULL);
+ _res.options = old_options;
+ for (haddr = rhp->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, INADDRSZ))
+ break;
+ if (!*haddr) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hp->h_name, inet_ntoa(*((struct in_addr *)addr)));
+ h_errno = HOST_NOT_FOUND;
+ return (NULL);
+ }
+#endif /*SUNSECURITY*/
hp->h_addrtype = type;
hp->h_length = len;
h_addr_ptrs[0] = (char *)&host_addr;
- h_addr_ptrs[1] = (char *)0;
+ h_addr_ptrs[1] = NULL;
host_addr = *(struct in_addr *)addr;
#if BSD < 43 && !defined(h_addr) /* new-style hostent structure */
hp->h_addr = h_addr_ptrs[0];
#endif
- return(hp);
+ return (hp);
}
void
_sethtent(f)
int f;
{
- if (hostf == NULL)
+ if (!hostf)
hostf = fopen(_PATH_HOSTS, "r" );
else
rewind(hostf);
- stayopen |= f;
+ stayopen = f;
}
void
@@ -375,35 +509,36 @@ _gethtent()
char *p;
register char *cp, **q;
- if (hostf == NULL && (hostf = fopen(_PATH_HOSTS, "r" )) == NULL)
+ if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" )))
return (NULL);
again:
- if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
return (NULL);
if (*p == '#')
goto again;
- cp = strpbrk(p, "#\n");
- if (cp == NULL)
+ if (!(cp = strpbrk(p, "#\n")))
goto again;
*cp = '\0';
- cp = strpbrk(p, " \t");
- if (cp == NULL)
+ if (!(cp = strpbrk(p, " \t")))
goto again;
*cp++ = '\0';
/* THIS STUFF IS INTERNET SPECIFIC */
+ if (!inet_aton(p, &host_addr))
+ goto again;
+ h_addr_ptrs[0] = (char *)&host_addr;
+ h_addr_ptrs[1] = NULL;
#if BSD >= 43 || defined(h_addr) /* new-style hostent structure */
- host.h_addr_list = host_addrs;
+ host.h_addr_list = h_addr_ptrs;
+#else
+ host.h_addr = h_addr_ptrs[0];
#endif
- host.h_addr = hostaddr;
- *((u_int32_t *)host.h_addr) = inet_addr(p);
- host.h_length = sizeof (u_int32_t);
+ host.h_length = INT32SZ;
host.h_addrtype = AF_INET;
while (*cp == ' ' || *cp == '\t')
cp++;
host.h_name = cp;
q = host.h_aliases = host_aliases;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
+ if (cp = strpbrk(cp, " \t"))
*cp++ = '\0';
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
@@ -412,8 +547,7 @@ again:
}
if (q < &host_aliases[MAXALIASES - 1])
*q++ = cp;
- cp = strpbrk(cp, " \t");
- if (cp != NULL)
+ if (cp = strpbrk(cp, " \t"))
*cp++ = '\0';
}
*q = NULL;
@@ -455,6 +589,51 @@ _gethtbyaddr(addr, len, type)
return (p);
}
+#ifdef RESOLVSORT
+static void
+addrsort(ap, num)
+ char **ap;
+ int num;
+{
+ int i, j;
+ char **p;
+ short aval[MAXADDRS];
+ int needsort = 0;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; j < _res.nsort; j++)
+ if (_res.sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+#endif
+
#if defined(BSD43_BSD43_NFS) || defined(sun)
/* some libc's out there are bound internally to these names (UMIPS) */
void
@@ -474,7 +653,7 @@ struct hostent *
ht_gethostbyname(name)
char *name;
{
- return _gethtbyname(name);
+ return (_gethtbyname(name));
}
struct hostent *
@@ -482,13 +661,13 @@ ht_gethostbyaddr(addr, len, type)
const char *addr;
int len, type;
{
- return _gethtbyaddr(addr, len, type);
+ return (_gethtbyaddr(addr, len, type));
}
struct hostent *
gethostent()
{
- return _gethtent();
+ return (_gethtent());
}
void
@@ -501,6 +680,26 @@ dns_service()
dn_skipname(comp_dn, eom)
const u_char *comp_dn, *eom;
{
- return __dn_skipname(comp_dn, eom);
+ return (__dn_skipname(comp_dn, eom));
}
#endif /*old-style libc with yp junk in it*/
+
+#ifdef ultrix
+/* more icky libc packaging in ultrix */
+int
+local_hostname_length(hostname)
+ const char *hostname;
+{
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif