2
** dns_hosts.c DNS/Hesiod Hosts map access routines
4
** Copyright (c) 1993 Signum Support AB, Sweden
6
** This file is part of the NYS Library.
8
** The NYS Library is free software; you can redistribute it and/or
9
** modify it under the terms of the GNU Library General Public License as
10
** published by the Free Software Foundation; either version 2 of the
11
** License, or (at your option) any later version.
13
** The NYS Library is distributed in the hope that it will be useful,
14
** but WITHOUT ANY WARRANTY; without even the implied warranty of
15
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
** Library General Public License for more details.
18
** You should have received a copy of the GNU Library General Public
19
** License along with the NYS Library; see the file COPYING.LIB. If
20
** not, write to the Free Software Foundation, Inc., 675 Mass Ave,
21
** Cambridge, MA 02139, USA.
24
** This file contains software derived from the gethostnamadr.c file
25
** from lib/libc/net/ in the 4.3BSD NET.2 distribution:
27
** Copyright (c) 1985, 1988 Regents of the University of California.
28
** All rights reserved.
30
** Redistribution and use in source and binary forms, with or without
31
** modification, are permitted provided that the following conditions
33
** 1. Redistributions of source code must retain the above copyright
34
** notice, this list of conditions and the following disclaimer.
35
** 2. Redistributions in binary form must reproduce the above copyright
36
** notice, this list of conditions and the following disclaimer in the
37
** documentation and/or other materials provided with the distribution.
38
** 3. All advertising materials mentioning features or use of this software
39
** must display the following acknowledgement:
40
** This product includes software developed by the University of
41
** California, Berkeley and its contributors.
42
** 4. Neither the name of the University nor the names of its contributors
43
** may be used to endorse or promote products derived from this software
44
** without specific prior written permission.
46
** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49
** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59
#if defined(HAVE_CONFIG_H)
63
#if defined(linux) && !defined(HAVE__DNS_GETHOSTBYNAME) && !defined(HAVE_RES_GETHOSTBYNAME) && !defined(HAVE___NSS_CONFIGURE_LOOKUP)
65
#include <sys/param.h>
66
#include <sys/socket.h>
67
#include <netinet/in.h>
68
#include <arpa/inet.h>
69
#include <arpa/nameser.h>
79
#include "res_options.h"
81
extern void _res_close(void);
82
extern struct hostent *_gethtbyaddr(const char *, int, int);
88
#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
93
static const char AskedForGot[] =
94
"gethostby*.getanswer: asked for \"%s\", got \"%s\"";
96
static char *h_addr_ptrs[MAXADDRS + 1];
98
static struct hostent host;
99
static char *host_aliases[MAXALIASES];
100
static char hostbuf[8*1024];
101
static struct in_addr host_addr;
104
static void addrsort __P((char **, int));
108
#define MAXPACKET PACKETSZ
110
#define MAXPACKET 1024
115
u_char buf[MAXPACKET];
123
# define dprintf(msg, num) /*nada*/
125
static struct hostent *
126
getanswer(const querybuf *answer, int anslen, const char *qname, int qclass, int qtype)
128
register const HEADER *hp;
129
register const u_char *cp;
132
char *bp, **ap, **hap;
133
int type, class, buflen, ancount, qdcount;
134
int haveanswer, had_error;
136
char tbuf[MAXDNAME+1];
139
eom = answer->buf + anslen;
141
* find first satisfactory answer
144
ancount = ntohs(hp->ancount);
145
qdcount = ntohs(hp->qdcount);
147
buflen = sizeof hostbuf;
148
cp = answer->buf + HFIXEDSZ;
150
h_errno = NO_RECOVERY;
153
if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
154
h_errno = NO_RECOVERY;
159
/* res_send() has already verified that the query name is the
160
* same as the one we sent; this just gets the expanded name
161
* (i.e., with the succeeding search-domain tacked on).
163
n = strlen(bp) + 1; /* for the \0 */
167
/* The qname can be abbreviated, but h_name is now absolute. */
172
host.h_aliases = host_aliases;
175
host.h_addr_list = h_addr_ptrs;
178
while (ancount-- > 0 && cp < eom && !had_error) {
179
n = dn_expand(answer->buf, eom, cp, bp, buflen);
185
type = _getshort(cp);
186
cp += INT16SZ; /* type */
187
class = _getshort(cp);
188
cp += INT16SZ + INT32SZ; /* class, TTL */
190
cp += INT16SZ; /* len */
191
if (class != qclass) {
192
/* XXX - debug? syslog? */
194
continue; /* XXX - had_error++ ? */
196
if (qtype == T_A && type == T_CNAME) {
197
if (ap >= &host_aliases[MAXALIASES-1])
199
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
205
if (host.h_name && strcasecmp(host.h_name, bp) != 0) {
206
syslog(LOG_NOTICE|LOG_AUTH,
207
"gethostby*.getanswer: asked for \"%s\", got CNAME for \"%s\"",
209
continue; /* XXX - had_error++ ? */
213
n = strlen(bp) + 1; /* for the \0 */
216
/* Get canonical name. */
217
n = strlen(tbuf) + 1; /* for the \0 */
229
syslog(LOG_NOTICE|LOG_AUTH,
230
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
231
qname, p_class(qclass), p_type(qtype),
234
continue; /* XXX - had_error++ ? */
238
if (strcasecmp(qname, bp) != 0) {
239
syslog(LOG_NOTICE|LOG_AUTH,
240
AskedForGot, qname, bp);
242
continue; /* XXX - had_error++ ? */
244
n = dn_expand(answer->buf, eom, cp, bp, buflen);
249
#if MULTI_PTRS_ARE_ALIASES
253
else if (ap < &host_aliases[MAXALIASES-1])
258
n = strlen(bp) + 1; /* for the \0 */
265
h_errno = NETDB_SUCCESS;
269
if (strcasecmp(host.h_name, bp) != 0) {
270
syslog(LOG_NOTICE|LOG_AUTH,
271
AskedForGot, host.h_name, bp);
273
continue; /* XXX - had_error++ ? */
276
if (n != host.h_length) {
284
host.h_addrtype = (class == C_IN)
288
nn = strlen(bp) + 1; /* for the \0 */
293
bp += sizeof(align) - ((u_long)bp % sizeof(align));
295
if (bp + n >= &hostbuf[sizeof hostbuf]) {
296
dprintf("size (%d) too big\n", n);
300
if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
302
dprintf("Too many addresses (%d)\n",
307
bcopy(cp, *hap++ = bp, n);
312
dprintf("Impossible condition (type=%d)\n", type);
313
h_errno = NO_RECOVERY;
322
# if defined(RESOLVSORT)
324
* Note: we sort even if host can take only one address
325
* in its return structures - should give it the "best"
326
* address in that case, not some random one
328
if (_res.nsort && haveanswer > 1 &&
329
qclass == C_IN && qtype == T_A)
330
addrsort(h_addr_ptrs, haveanswer);
331
# endif /*RESOLVSORT*/
333
n = strlen(qname) + 1; /* for the \0 */
337
h_errno = NETDB_SUCCESS;
348
addrsort(char **ap, int num)
352
short aval[MAXADDRS];
356
for (i = 0; i < num; i++, p++) {
357
for (j = 0 ; (unsigned)j < _res.nsort; j++)
358
if (_res.sort_list[j].addr.s_addr ==
359
(((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
362
if (needsort == 0 && i > 0 && j < aval[i-1])
368
while (needsort < num) {
369
for (j = needsort - 1; j >= 0; j--) {
370
if (aval[j] > aval[j+1]) {
390
_dns_gethostbyname(const char *name)
393
register const char *cp;
397
* if there aren't any dots, it could be a user-level alias.
398
* this is also done in res_query() since we are not the only
399
* function that looks up host names.
401
if (!strchr(name, '.') && (cp = __hostalias(name)))
405
* disallow names consisting only of digits/dots, unless
408
if (isdigit(name[0]))
409
for (cp = name;; ++cp) {
414
* All-numeric, no dot at the end.
415
* Fake up a hostent as if we'd actually
418
if (!inet_aton(name, &host_addr)) {
419
h_errno = HOST_NOT_FOUND;
422
host.h_name = (char *)name;
423
host.h_aliases = host_aliases;
424
host_aliases[0] = NULL;
425
host.h_addrtype = AF_INET;
426
host.h_length = INT32SZ;
427
h_addr_ptrs[0] = (char *)&host_addr;
428
h_addr_ptrs[1] = NULL;
429
host.h_addr_list = h_addr_ptrs;
430
h_errno = NETDB_SUCCESS;
433
if (!isdigit(*cp) && *cp != '.')
437
if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
438
dprintf("res_search failed (%d)\n", n);
441
return (getanswer(&buf, n, name, C_IN, T_A));
445
_dns_gethostbyaddr(const char *addr, int len, int type)
449
register struct hostent *hp;
450
char qbuf[MAXDNAME+1];
452
register struct hostent *rhp;
455
char hname2[MAXDNAME+1];
456
#endif /*SUNSECURITY*/
458
if (type != AF_INET) {
459
errno = EAFNOSUPPORT;
460
h_errno = NETDB_INTERNAL;
463
(void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
464
((unsigned)addr[3] & 0xff),
465
((unsigned)addr[2] & 0xff),
466
((unsigned)addr[1] & 0xff),
467
((unsigned)addr[0] & 0xff));
468
n = res_query(qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
470
dprintf("res_query failed (%d)\n", n);
473
if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR)))
474
return (NULL); /* h_errno was set by getanswer() */
477
* turn off search as the name should be absolute,
478
* 'localhost' should be matched by defnames
480
strncpy(hname2, hp->h_name, MAXDNAME);
481
hname2[MAXDNAME] = '\0';
482
old_options = _res.options;
483
_res.options &= ~RES_DNSRCH;
484
_res.options |= RES_DEFNAMES;
485
if (!(rhp = gethostbyname(hp->h_name))) {
486
syslog(LOG_NOTICE|LOG_AUTH,
487
"gethostbyaddr: No A record for %s (verifying [%s])",
488
hname2, inet_ntoa(*((struct in_addr *)addr)));
489
_res.options = old_options;
490
h_errno = HOST_NOT_FOUND;
493
_res.options = old_options;
494
for (haddr = rhp->h_addr_list; *haddr; haddr++)
495
if (!memcmp(*haddr, addr, INADDRSZ))
498
syslog(LOG_NOTICE|LOG_AUTH,
499
"gethostbyaddr: A record of %s != PTR record [%s]",
500
hname2, inet_ntoa(*((struct in_addr *)addr)));
501
h_errno = HOST_NOT_FOUND;
504
#endif /*SUNSECURITY*/
505
hp->h_addrtype = type;
507
h_addr_ptrs[0] = (char *)&host_addr;
508
h_addr_ptrs[1] = NULL;
509
host_addr = *(struct in_addr *)addr;
510
h_errno = NETDB_SUCCESS;