~ubuntu-branches/ubuntu/oneiric/nis/oneiric-proposed

« back to all changes in this revision

Viewing changes to ypbind-mt-1.19/lib/dns_hosts.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2005-11-16 23:42:06 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20051116234206-p00omaw5ji5q0qhr
Tags: 3.15-3ubuntu1
Resynchronise with Debian.  (me)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
** dns_hosts.c              DNS/Hesiod Hosts map access routines
3
 
**
4
 
** Copyright (c) 1993 Signum Support AB, Sweden
5
 
**
6
 
** This file is part of the NYS Library.
7
 
**
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.
12
 
**
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.
17
 
**
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.
22
 
**
23
 
**
24
 
** This file contains software derived from the gethostnamadr.c file
25
 
** from lib/libc/net/ in the 4.3BSD NET.2 distribution:
26
 
**
27
 
** Copyright (c) 1985, 1988 Regents of the University of California.
28
 
** All rights reserved.
29
 
**
30
 
** Redistribution and use in source and binary forms, with or without
31
 
** modification, are permitted provided that the following conditions
32
 
** are met:
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.
45
 
**
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
56
 
** SUCH DAMAGE.
57
 
*/
58
 
 
59
 
#if defined(HAVE_CONFIG_H)
60
 
#include "config.h"
61
 
#endif
62
 
 
63
 
#if defined(linux) && !defined(HAVE__DNS_GETHOSTBYNAME) && !defined(HAVE_RES_GETHOSTBYNAME) && !defined(HAVE___NSS_CONFIGURE_LOOKUP)
64
 
 
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>
70
 
 
71
 
#include <stdio.h>
72
 
#include <netdb.h>
73
 
#include <resolv.h>
74
 
#include <ctype.h>
75
 
#include <errno.h>
76
 
#include <syslog.h>
77
 
#include <string.h>
78
 
 
79
 
#include "res_options.h"
80
 
 
81
 
extern void _res_close(void);
82
 
extern struct hostent *_gethtbyaddr(const char *, int, int);
83
 
 
84
 
#ifndef LOG_AUTH
85
 
# define LOG_AUTH 0
86
 
#endif
87
 
 
88
 
#define MULTI_PTRS_ARE_ALIASES 1        /* XXX - experimental */
89
 
 
90
 
#define MAXALIASES      35
91
 
#define MAXADDRS        35
92
 
 
93
 
static const char AskedForGot[] =
94
 
                          "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
95
 
 
96
 
static char *h_addr_ptrs[MAXADDRS + 1];
97
 
 
98
 
static struct hostent host;
99
 
static char *host_aliases[MAXALIASES];
100
 
static char hostbuf[8*1024];
101
 
static struct in_addr host_addr;
102
 
 
103
 
#ifdef RESOLVSORT
104
 
static void addrsort __P((char **, int));
105
 
#endif
106
 
 
107
 
#if PACKETSZ > 1024
108
 
#define MAXPACKET       PACKETSZ
109
 
#else
110
 
#define MAXPACKET       1024
111
 
#endif
112
 
 
113
 
typedef union {
114
 
    HEADER hdr;
115
 
    u_char buf[MAXPACKET];
116
 
} querybuf;
117
 
 
118
 
typedef union {
119
 
    int32_t al;
120
 
    char ac;
121
 
} align;
122
 
 
123
 
# define dprintf(msg, num) /*nada*/
124
 
 
125
 
static struct hostent *
126
 
getanswer(const querybuf *answer, int anslen, const char *qname, int qclass, int qtype)
127
 
{
128
 
        register const HEADER *hp;
129
 
        register const u_char *cp;
130
 
        register int n;
131
 
        const u_char *eom;
132
 
        char *bp, **ap, **hap;
133
 
        int type, class, buflen, ancount, qdcount;
134
 
        int haveanswer, had_error;
135
 
        int toobig = 0;
136
 
        char tbuf[MAXDNAME+1];
137
 
 
138
 
        host.h_name = NULL;
139
 
        eom = answer->buf + anslen;
140
 
        /*
141
 
         * find first satisfactory answer
142
 
         */
143
 
        hp = &answer->hdr;
144
 
        ancount = ntohs(hp->ancount);
145
 
        qdcount = ntohs(hp->qdcount);
146
 
        bp = hostbuf;
147
 
        buflen = sizeof hostbuf;
148
 
        cp = answer->buf + HFIXEDSZ;
149
 
        if (qdcount != 1) {
150
 
                h_errno = NO_RECOVERY;
151
 
                return (NULL);
152
 
        }
153
 
        if ((n = dn_expand(answer->buf, eom, cp, bp, buflen)) < 0) {
154
 
                h_errno = NO_RECOVERY;
155
 
                return (NULL);
156
 
        }
157
 
        cp += n + QFIXEDSZ;
158
 
        if (qtype == T_A) {
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).
162
 
                 */
163
 
                n = strlen(bp) + 1;             /* for the \0 */
164
 
                host.h_name = bp;
165
 
                bp += n;
166
 
                buflen -= n;
167
 
                /* The qname can be abbreviated, but h_name is now absolute. */
168
 
                qname = host.h_name;
169
 
        }
170
 
        ap = host_aliases;
171
 
        *ap = NULL;
172
 
        host.h_aliases = host_aliases;
173
 
        hap = h_addr_ptrs;
174
 
        *hap = NULL;
175
 
        host.h_addr_list = h_addr_ptrs;
176
 
        haveanswer = 0;
177
 
        had_error = 0;
178
 
        while (ancount-- > 0 && cp < eom && !had_error) {
179
 
                n = dn_expand(answer->buf, eom, cp, bp, buflen);
180
 
                if (n < 0) {
181
 
                        had_error++;
182
 
                        continue;
183
 
                }
184
 
                cp += n;                        /* name */
185
 
                type = _getshort(cp);
186
 
                cp += INT16SZ;                  /* type */
187
 
                class = _getshort(cp);
188
 
                cp += INT16SZ + INT32SZ;        /* class, TTL */
189
 
                n = _getshort(cp);
190
 
                cp += INT16SZ;                  /* len */
191
 
                if (class != qclass) {
192
 
                        /* XXX - debug? syslog? */
193
 
                        cp += n;
194
 
                        continue;               /* XXX - had_error++ ? */
195
 
                }
196
 
                if (qtype == T_A && type == T_CNAME) {
197
 
                        if (ap >= &host_aliases[MAXALIASES-1])
198
 
                                continue;
199
 
                        n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
200
 
                        if (n < 0) {
201
 
                                had_error++;
202
 
                                continue;
203
 
                        }
204
 
                        cp += n;
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\"",
208
 
                                       host.h_name, bp);
209
 
                                continue;       /* XXX - had_error++ ? */
210
 
                        }
211
 
                        /* Store alias. */
212
 
                        *ap++ = bp;
213
 
                        n = strlen(bp) + 1;     /* for the \0 */
214
 
                        bp += n;
215
 
                        buflen -= n;
216
 
                        /* Get canonical name. */
217
 
                        n = strlen(tbuf) + 1;   /* for the \0 */
218
 
                        if (n > buflen) {
219
 
                                had_error++;
220
 
                                continue;
221
 
                        }
222
 
                        strcpy(bp, tbuf);
223
 
                        host.h_name = bp;
224
 
                        bp += n;
225
 
                        buflen -= n;
226
 
                        continue;
227
 
                }
228
 
                if (type != qtype) {
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),
232
 
                               p_type(type));
233
 
                        cp += n;
234
 
                        continue;               /* XXX - had_error++ ? */
235
 
                }
236
 
                switch (type) {
237
 
                case T_PTR:
238
 
                        if (strcasecmp(qname, bp) != 0) {
239
 
                                syslog(LOG_NOTICE|LOG_AUTH,
240
 
                                       AskedForGot, qname, bp);
241
 
                                cp += n;
242
 
                                continue;       /* XXX - had_error++ ? */
243
 
                        }
244
 
                        n = dn_expand(answer->buf, eom, cp, bp, buflen);
245
 
                        if (n < 0) {
246
 
                                had_error++;
247
 
                                break;
248
 
                        }
249
 
#if MULTI_PTRS_ARE_ALIASES
250
 
                        cp += n;
251
 
                        if (!haveanswer)
252
 
                                host.h_name = bp;
253
 
                        else if (ap < &host_aliases[MAXALIASES-1])
254
 
                                *ap++ = bp;
255
 
                        else
256
 
                                n = -1;
257
 
                        if (n != -1) {
258
 
                                n = strlen(bp) + 1;     /* for the \0 */
259
 
                                bp += n;
260
 
                                buflen -= n;
261
 
                        }
262
 
                        break;
263
 
#else
264
 
                        host.h_name = bp;
265
 
                        h_errno = NETDB_SUCCESS;
266
 
                        return (&host);
267
 
#endif
268
 
                case T_A:
269
 
                        if (strcasecmp(host.h_name, bp) != 0) {
270
 
                                syslog(LOG_NOTICE|LOG_AUTH,
271
 
                                       AskedForGot, host.h_name, bp);
272
 
                                cp += n;
273
 
                                continue;       /* XXX - had_error++ ? */
274
 
                        }
275
 
                        if (haveanswer) {
276
 
                                if (n != host.h_length) {
277
 
                                        cp += n;
278
 
                                        continue;
279
 
                                }
280
 
                        } else {
281
 
                                register int nn;
282
 
 
283
 
                                host.h_length = n;
284
 
                                host.h_addrtype = (class == C_IN)
285
 
                                                  ? AF_INET
286
 
                                                  : AF_UNSPEC;
287
 
                                host.h_name = bp;
288
 
                                nn = strlen(bp) + 1;    /* for the \0 */
289
 
                                bp += nn;
290
 
                                buflen -= nn;
291
 
                        }
292
 
 
293
 
                        bp += sizeof(align) - ((u_long)bp % sizeof(align));
294
 
 
295
 
                        if (bp + n >= &hostbuf[sizeof hostbuf]) {
296
 
                                dprintf("size (%d) too big\n", n);
297
 
                                had_error++;
298
 
                                continue;
299
 
                        }
300
 
                        if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
301
 
                                if (!toobig++)
302
 
                                        dprintf("Too many addresses (%d)\n",
303
 
                                                MAXADDRS);
304
 
                                cp += n;
305
 
                                continue;
306
 
                        }
307
 
                        bcopy(cp, *hap++ = bp, n);
308
 
                        bp += n;
309
 
                        cp += n;
310
 
                        break;
311
 
                default:
312
 
                        dprintf("Impossible condition (type=%d)\n", type);
313
 
                        h_errno = NO_RECOVERY;
314
 
                        return (NULL);
315
 
                } /*switch*/
316
 
                if (!had_error)
317
 
                        haveanswer++;
318
 
        } /*while*/
319
 
        if (haveanswer) {
320
 
                *ap = NULL;
321
 
                *hap = NULL;
322
 
# if defined(RESOLVSORT)
323
 
                /*
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
327
 
                 */
328
 
                if (_res.nsort && haveanswer > 1 &&
329
 
                    qclass == C_IN && qtype == T_A)
330
 
                        addrsort(h_addr_ptrs, haveanswer);
331
 
# endif /*RESOLVSORT*/
332
 
                if (!host.h_name) {
333
 
                        n = strlen(qname) + 1;  /* for the \0 */
334
 
                        strcpy(bp, qname);
335
 
                        host.h_name = bp;
336
 
                }
337
 
                h_errno = NETDB_SUCCESS;
338
 
                return (&host);
339
 
        } else {
340
 
                h_errno = TRY_AGAIN;
341
 
                return (NULL);
342
 
        }
343
 
}
344
 
 
345
 
 
346
 
#ifdef RESOLVSORT
347
 
static void
348
 
addrsort(char **ap, int num)
349
 
{
350
 
        int i, j;
351
 
        char **p;
352
 
        short aval[MAXADDRS];
353
 
        int needsort = 0;
354
 
 
355
 
        p = ap;
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))
360
 
                        break;
361
 
            aval[i] = j;
362
 
            if (needsort == 0 && i > 0 && j < aval[i-1])
363
 
                needsort = i;
364
 
        }
365
 
        if (!needsort)
366
 
            return;
367
 
 
368
 
        while (needsort < num) {
369
 
            for (j = needsort - 1; j >= 0; j--) {
370
 
                if (aval[j] > aval[j+1]) {
371
 
                    char *hp;
372
 
 
373
 
                    i = aval[j];
374
 
                    aval[j] = aval[j+1];
375
 
                    aval[j+1] = i;
376
 
 
377
 
                    hp = ap[j];
378
 
                    ap[j] = ap[j+1];
379
 
                    ap[j+1] = hp;
380
 
 
381
 
                } else
382
 
                    break;
383
 
            }
384
 
            needsort++;
385
 
        }
386
 
}
387
 
#endif
388
 
 
389
 
struct hostent *
390
 
_dns_gethostbyname(const char *name)
391
 
{
392
 
        querybuf buf;
393
 
        register const char *cp;
394
 
        int n;
395
 
 
396
 
        /*
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.
400
 
         */
401
 
        if (!strchr(name, '.') && (cp = __hostalias(name)))
402
 
                name = cp;
403
 
 
404
 
        /*
405
 
         * disallow names consisting only of digits/dots, unless
406
 
         * they end in a dot.
407
 
         */
408
 
        if (isdigit(name[0]))
409
 
                for (cp = name;; ++cp) {
410
 
                        if (!*cp) {
411
 
                                if (*--cp == '.')
412
 
                                        break;
413
 
                                /*
414
 
                                 * All-numeric, no dot at the end.
415
 
                                 * Fake up a hostent as if we'd actually
416
 
                                 * done a lookup.
417
 
                                 */
418
 
                                if (!inet_aton(name, &host_addr)) {
419
 
                                        h_errno = HOST_NOT_FOUND;
420
 
                                        return (NULL);
421
 
                                }
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;
431
 
                                return (&host);
432
 
                        }
433
 
                        if (!isdigit(*cp) && *cp != '.')
434
 
                                break;
435
 
                }
436
 
 
437
 
        if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
438
 
                dprintf("res_search failed (%d)\n", n);
439
 
                return (NULL);
440
 
        }
441
 
        return (getanswer(&buf, n, name, C_IN, T_A));
442
 
}
443
 
 
444
 
struct hostent *
445
 
_dns_gethostbyaddr(const char *addr, int len, int type)
446
 
{
447
 
        int n;
448
 
        querybuf buf;
449
 
        register struct hostent *hp;
450
 
        char qbuf[MAXDNAME+1];
451
 
#ifdef SUNSECURITY
452
 
        register struct hostent *rhp;
453
 
        char **haddr;
454
 
        u_long old_options;
455
 
        char hname2[MAXDNAME+1];
456
 
#endif /*SUNSECURITY*/
457
 
 
458
 
        if (type != AF_INET) {
459
 
                errno = EAFNOSUPPORT;
460
 
                h_errno = NETDB_INTERNAL;
461
 
                return (NULL);
462
 
        }
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);
469
 
        if (n < 0) {
470
 
                dprintf("res_query failed (%d)\n", n);
471
 
                return (NULL);
472
 
        }
473
 
        if (!(hp = getanswer(&buf, n, qbuf, C_IN, T_PTR)))
474
 
                return (NULL);  /* h_errno was set by getanswer() */
475
 
#ifdef SUNSECURITY
476
 
        /*
477
 
         * turn off search as the name should be absolute,
478
 
         * 'localhost' should be matched by defnames
479
 
         */
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;
491
 
                return (NULL);
492
 
        }
493
 
        _res.options = old_options;
494
 
        for (haddr = rhp->h_addr_list; *haddr; haddr++)
495
 
                if (!memcmp(*haddr, addr, INADDRSZ))
496
 
                        break;
497
 
        if (!*haddr) {
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;
502
 
                return (NULL);
503
 
        }
504
 
#endif /*SUNSECURITY*/
505
 
        hp->h_addrtype = type;
506
 
        hp->h_length = len;
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;
511
 
        return (hp);
512
 
}
513
 
#endif