Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/net/gethostbydns.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* ++Copyright++ 1985, 1988, 1993
5
* -
6
* Copyright (c) 1985, 1988, 1993
7
* The Regents of the University of California. All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
* 3. Neither the name of the University nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
20
*
21
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
* SUCH DAMAGE.
32
* -
33
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
34
*
35
* Permission to use, copy, modify, and distribute this software for any
36
* purpose with or without fee is hereby granted, provided that the above
37
* copyright notice and this permission notice appear in all copies, and that
38
* the name of Digital Equipment Corporation not be used in advertising or
39
* publicity pertaining to distribution of the document or software without
40
* specific, written prior permission.
41
*
42
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
43
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
44
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
45
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
46
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
47
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
48
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49
* SOFTWARE.
50
* -
51
* --Copyright--
52
*/
53
54
#include <sys/param.h>
55
#include <sys/socket.h>
56
#include <netinet/in.h>
57
#include <arpa/inet.h>
58
#include <arpa/nameser.h>
59
60
#include <stdio.h>
61
#include <stdlib.h>
62
#include <unistd.h>
63
#include <string.h>
64
#include <netdb.h>
65
#include <resolv.h>
66
#include <ctype.h>
67
#include <errno.h>
68
#include <syslog.h>
69
#include <stdarg.h>
70
#include <nsswitch.h>
71
72
#include "netdb_private.h"
73
#include "res_config.h"
74
75
#define SPRINTF(x) ((size_t)sprintf x)
76
77
#ifdef DEBUG
78
static const char AskedForGot[] =
79
"gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
80
#endif
81
82
#ifdef RESOLVSORT
83
static void addrsort(char **, int, res_state);
84
#endif
85
86
#ifdef DEBUG
87
static void dbg_printf(char *, int, res_state) __printflike(1, 0);
88
#endif
89
90
#define MAXPACKET (64*1024)
91
92
typedef union {
93
HEADER hdr;
94
u_char buf[MAXPACKET];
95
} querybuf;
96
97
typedef union {
98
int32_t al;
99
char ac;
100
} align;
101
102
int _dns_ttl_;
103
104
#ifdef DEBUG
105
static void
106
dbg_printf(char *msg, int num, res_state res)
107
{
108
if (res->options & RES_DEBUG) {
109
int save = errno;
110
111
printf(msg, num);
112
errno = save;
113
}
114
}
115
#else
116
# define dbg_printf(msg, num, res) /*nada*/
117
#endif
118
119
#define BOUNDED_INCR(x) \
120
do { \
121
cp += x; \
122
if (cp > eom) { \
123
RES_SET_H_ERRNO(statp, NO_RECOVERY); \
124
return (-1); \
125
} \
126
} while (0)
127
128
#define BOUNDS_CHECK(ptr, count) \
129
do { \
130
if ((ptr) + (count) > eom) { \
131
RES_SET_H_ERRNO(statp, NO_RECOVERY); \
132
return (-1); \
133
} \
134
} while (0)
135
136
static int
137
gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
138
struct hostent *he, struct hostent_data *hed, res_state statp)
139
{
140
const HEADER *hp;
141
const u_char *cp;
142
int n;
143
const u_char *eom, *erdata;
144
char *bp, *ep, **ap, **hap;
145
int type, class, ancount, qdcount;
146
int haveanswer, had_error;
147
int toobig = 0;
148
char tbuf[MAXDNAME];
149
const char *tname;
150
int (*name_ok)(const char *);
151
152
tname = qname;
153
he->h_name = NULL;
154
eom = answer->buf + anslen;
155
switch (qtype) {
156
case T_A:
157
case T_AAAA:
158
name_ok = res_hnok;
159
break;
160
case T_PTR:
161
name_ok = res_dnok;
162
break;
163
default:
164
RES_SET_H_ERRNO(statp, NO_RECOVERY);
165
return (-1); /* XXX should be abort(); */
166
}
167
/*
168
* find first satisfactory answer
169
*/
170
hp = &answer->hdr;
171
ancount = ntohs(hp->ancount);
172
qdcount = ntohs(hp->qdcount);
173
bp = hed->hostbuf;
174
ep = hed->hostbuf + sizeof hed->hostbuf;
175
cp = answer->buf;
176
BOUNDED_INCR(HFIXEDSZ);
177
if (qdcount != 1) {
178
RES_SET_H_ERRNO(statp, NO_RECOVERY);
179
return (-1);
180
}
181
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
182
if ((n < 0) || !(*name_ok)(bp)) {
183
RES_SET_H_ERRNO(statp, NO_RECOVERY);
184
return (-1);
185
}
186
BOUNDED_INCR(n + QFIXEDSZ);
187
if (qtype == T_A || qtype == T_AAAA) {
188
/* res_send() has already verified that the query name is the
189
* same as the one we sent; this just gets the expanded name
190
* (i.e., with the succeeding search-domain tacked on).
191
*/
192
n = strlen(bp) + 1; /* for the \0 */
193
if (n >= MAXHOSTNAMELEN) {
194
RES_SET_H_ERRNO(statp, NO_RECOVERY);
195
return (-1);
196
}
197
he->h_name = bp;
198
bp += n;
199
/* The qname can be abbreviated, but h_name is now absolute. */
200
qname = he->h_name;
201
}
202
ap = hed->host_aliases;
203
*ap = NULL;
204
he->h_aliases = hed->host_aliases;
205
hap = hed->h_addr_ptrs;
206
*hap = NULL;
207
he->h_addr_list = hed->h_addr_ptrs;
208
haveanswer = 0;
209
had_error = 0;
210
_dns_ttl_ = -1;
211
while (ancount-- > 0 && cp < eom && !had_error) {
212
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
213
if ((n < 0) || !(*name_ok)(bp)) {
214
had_error++;
215
continue;
216
}
217
cp += n; /* name */
218
BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
219
type = _getshort(cp);
220
cp += INT16SZ; /* type */
221
class = _getshort(cp);
222
cp += INT16SZ; /* class */
223
if (qtype == T_A && type == T_A)
224
_dns_ttl_ = _getlong(cp);
225
cp += INT32SZ; /* TTL */
226
n = _getshort(cp);
227
cp += INT16SZ; /* len */
228
BOUNDS_CHECK(cp, n);
229
erdata = cp + n;
230
if (class != C_IN) {
231
/* XXX - debug? syslog? */
232
cp += n;
233
continue; /* XXX - had_error++ ? */
234
}
235
if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
236
if (ap >= &hed->host_aliases[_MAXALIASES-1])
237
continue;
238
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
239
if ((n < 0) || !(*name_ok)(tbuf)) {
240
had_error++;
241
continue;
242
}
243
cp += n;
244
if (cp != erdata) {
245
RES_SET_H_ERRNO(statp, NO_RECOVERY);
246
return (-1);
247
}
248
/* Store alias. */
249
*ap++ = bp;
250
n = strlen(bp) + 1; /* for the \0 */
251
if (n >= MAXHOSTNAMELEN) {
252
had_error++;
253
continue;
254
}
255
bp += n;
256
/* Get canonical name. */
257
n = strlen(tbuf) + 1; /* for the \0 */
258
if (n > ep - bp || n >= MAXHOSTNAMELEN) {
259
had_error++;
260
continue;
261
}
262
strcpy(bp, tbuf);
263
he->h_name = bp;
264
bp += n;
265
continue;
266
}
267
if (qtype == T_PTR && type == T_CNAME) {
268
n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
269
if (n < 0 || !res_dnok(tbuf)) {
270
had_error++;
271
continue;
272
}
273
cp += n;
274
if (cp != erdata) {
275
RES_SET_H_ERRNO(statp, NO_RECOVERY);
276
return (-1);
277
}
278
/* Get canonical name. */
279
n = strlen(tbuf) + 1; /* for the \0 */
280
if (n > ep - bp || n >= MAXHOSTNAMELEN) {
281
had_error++;
282
continue;
283
}
284
strcpy(bp, tbuf);
285
tname = bp;
286
bp += n;
287
continue;
288
}
289
if (type != qtype) {
290
#ifdef DEBUG
291
if (type != T_KEY && type != T_SIG &&
292
type != T_DNAME && type != T_RRSIG)
293
syslog(LOG_NOTICE|LOG_AUTH,
294
"gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
295
qname, p_class(C_IN), p_type(qtype),
296
p_type(type));
297
#endif
298
cp += n;
299
continue; /* XXX - had_error++ ? */
300
}
301
switch (type) {
302
case T_PTR:
303
if (strcasecmp(tname, bp) != 0) {
304
#ifdef DEBUG
305
syslog(LOG_NOTICE|LOG_AUTH,
306
AskedForGot, qname, bp);
307
#endif
308
cp += n;
309
continue; /* XXX - had_error++ ? */
310
}
311
n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
312
if ((n < 0) || !res_hnok(bp)) {
313
had_error++;
314
break;
315
}
316
#if MULTI_PTRS_ARE_ALIASES
317
cp += n;
318
if (cp != erdata) {
319
RES_SET_H_ERRNO(statp, NO_RECOVERY);
320
return (-1);
321
}
322
if (!haveanswer)
323
he->h_name = bp;
324
else if (ap < &hed->host_aliases[_MAXALIASES-1])
325
*ap++ = bp;
326
else
327
n = -1;
328
if (n != -1) {
329
n = strlen(bp) + 1; /* for the \0 */
330
if (n >= MAXHOSTNAMELEN) {
331
had_error++;
332
break;
333
}
334
bp += n;
335
}
336
break;
337
#else
338
he->h_name = bp;
339
if (statp->options & RES_USE_INET6) {
340
n = strlen(bp) + 1; /* for the \0 */
341
if (n >= MAXHOSTNAMELEN) {
342
had_error++;
343
break;
344
}
345
bp += n;
346
_map_v4v6_hostent(he, &bp, ep);
347
}
348
RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
349
return (0);
350
#endif
351
case T_A:
352
case T_AAAA:
353
if (strcasecmp(he->h_name, bp) != 0) {
354
#ifdef DEBUG
355
syslog(LOG_NOTICE|LOG_AUTH,
356
AskedForGot, he->h_name, bp);
357
#endif
358
cp += n;
359
continue; /* XXX - had_error++ ? */
360
}
361
if (n != he->h_length) {
362
cp += n;
363
continue;
364
}
365
if (!haveanswer) {
366
int nn;
367
368
he->h_name = bp;
369
nn = strlen(bp) + 1; /* for the \0 */
370
bp += nn;
371
}
372
373
bp += sizeof(align) - ((u_long)bp % sizeof(align));
374
375
if (bp + n >= ep) {
376
dbg_printf("size (%d) too big\n", n, statp);
377
had_error++;
378
continue;
379
}
380
if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) {
381
if (!toobig++)
382
dbg_printf("Too many addresses (%d)\n",
383
_MAXADDRS, statp);
384
cp += n;
385
continue;
386
}
387
memcpy(*hap++ = bp, cp, n);
388
bp += n;
389
cp += n;
390
if (cp != erdata) {
391
RES_SET_H_ERRNO(statp, NO_RECOVERY);
392
return (-1);
393
}
394
break;
395
default:
396
dbg_printf("Impossible condition (type=%d)\n", type,
397
statp);
398
RES_SET_H_ERRNO(statp, NO_RECOVERY);
399
return (-1);
400
/* BIND has abort() here, too risky on bad data */
401
}
402
if (!had_error)
403
haveanswer++;
404
}
405
if (haveanswer) {
406
*ap = NULL;
407
*hap = NULL;
408
# if defined(RESOLVSORT)
409
/*
410
* Note: we sort even if host can take only one address
411
* in its return structures - should give it the "best"
412
* address in that case, not some random one
413
*/
414
if (statp->nsort && haveanswer > 1 && qtype == T_A)
415
addrsort(hed->h_addr_ptrs, haveanswer, statp);
416
# endif /*RESOLVSORT*/
417
if (!he->h_name) {
418
n = strlen(qname) + 1; /* for the \0 */
419
if (n > ep - bp || n >= MAXHOSTNAMELEN)
420
goto no_recovery;
421
strcpy(bp, qname);
422
he->h_name = bp;
423
bp += n;
424
}
425
if (statp->options & RES_USE_INET6)
426
_map_v4v6_hostent(he, &bp, ep);
427
RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
428
return (0);
429
}
430
no_recovery:
431
RES_SET_H_ERRNO(statp, NO_RECOVERY);
432
return (-1);
433
}
434
435
/* XXX: for async DNS resolver in ypserv */
436
struct hostent *
437
__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
438
{
439
struct hostent *he;
440
struct hostent_data *hed;
441
int error;
442
res_state statp;
443
444
statp = __res_state();
445
if ((he = __hostent_init()) == NULL ||
446
(hed = __hostent_data_init()) == NULL) {
447
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
448
return (NULL);
449
}
450
switch (qtype) {
451
case T_AAAA:
452
he->h_addrtype = AF_INET6;
453
he->h_length = NS_IN6ADDRSZ;
454
break;
455
case T_A:
456
default:
457
he->h_addrtype = AF_INET;
458
he->h_length = NS_INADDRSZ;
459
break;
460
}
461
462
error = gethostanswer((const querybuf *)answer, anslen, qname, qtype,
463
he, hed, statp);
464
return (error == 0) ? he : NULL;
465
}
466
467
int
468
_dns_gethostbyname(void *rval, void *cb_data, va_list ap)
469
{
470
const char *name;
471
int af;
472
char *buffer;
473
size_t buflen;
474
int *errnop, *h_errnop;
475
struct hostent *hptr, he;
476
struct hostent_data *hed;
477
querybuf *buf;
478
int n, type, error;
479
res_state statp;
480
481
name = va_arg(ap, const char *);
482
af = va_arg(ap, int);
483
hptr = va_arg(ap, struct hostent *);
484
buffer = va_arg(ap, char *);
485
buflen = va_arg(ap, size_t);
486
errnop = va_arg(ap, int *);
487
h_errnop = va_arg(ap, int *);
488
489
*((struct hostent **)rval) = NULL;
490
491
statp = __res_state();
492
if ((hed = __hostent_data_init()) == NULL) {
493
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
494
*h_errnop = statp->res_h_errno;
495
return (NS_NOTFOUND);
496
}
497
498
he.h_addrtype = af;
499
switch (af) {
500
case AF_INET:
501
he.h_length = NS_INADDRSZ;
502
type = T_A;
503
break;
504
case AF_INET6:
505
he.h_length = NS_IN6ADDRSZ;
506
type = T_AAAA;
507
break;
508
default:
509
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
510
*h_errnop = statp->res_h_errno;
511
errno = EAFNOSUPPORT;
512
return (NS_UNAVAIL);
513
}
514
515
if ((buf = malloc(sizeof(*buf))) == NULL) {
516
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
517
*h_errnop = statp->res_h_errno;
518
return (NS_NOTFOUND);
519
}
520
n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf));
521
if (n < 0) {
522
free(buf);
523
dbg_printf("res_nsearch failed (%d)\n", n, statp);
524
*h_errnop = statp->res_h_errno;
525
return (NS_NOTFOUND);
526
} else if (n > sizeof(buf->buf)) {
527
free(buf);
528
dbg_printf("static buffer is too small (%d)\n", n, statp);
529
*h_errnop = statp->res_h_errno;
530
return (NS_UNAVAIL);
531
}
532
error = gethostanswer(buf, n, name, type, &he, hed, statp);
533
free(buf);
534
if (error != 0) {
535
*h_errnop = statp->res_h_errno;
536
switch (statp->res_h_errno) {
537
case HOST_NOT_FOUND:
538
return (NS_NOTFOUND);
539
case TRY_AGAIN:
540
return (NS_TRYAGAIN);
541
default:
542
return (NS_UNAVAIL);
543
}
544
/*NOTREACHED*/
545
}
546
if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
547
*errnop = errno;
548
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
549
*h_errnop = statp->res_h_errno;
550
return (NS_RETURN);
551
}
552
RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
553
*((struct hostent **)rval) = hptr;
554
return (NS_SUCCESS);
555
}
556
557
int
558
_dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
559
{
560
const void *addr;
561
socklen_t len;
562
int af;
563
char *buffer;
564
size_t buflen;
565
int *errnop, *h_errnop;
566
const u_char *uaddr;
567
struct hostent *hptr, he;
568
struct hostent_data *hed;
569
int n;
570
querybuf *buf;
571
char qbuf[MAXDNAME+1], *qp;
572
res_state statp;
573
#ifdef SUNSECURITY
574
struct hostdata rhd;
575
struct hostent *rhe;
576
char **haddr;
577
u_long old_options;
578
char hname2[MAXDNAME+1], numaddr[46];
579
int ret_h_error;
580
#endif /*SUNSECURITY*/
581
582
addr = va_arg(ap, const void *);
583
len = va_arg(ap, socklen_t);
584
af = va_arg(ap, int);
585
hptr = va_arg(ap, struct hostent *);
586
buffer = va_arg(ap, char *);
587
buflen = va_arg(ap, size_t);
588
errnop = va_arg(ap, int *);
589
h_errnop = va_arg(ap, int *);
590
uaddr = (const u_char *)addr;
591
592
*((struct hostent **)rval) = NULL;
593
594
statp = __res_state();
595
if ((hed = __hostent_data_init()) == NULL) {
596
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
597
*h_errnop = statp->res_h_errno;
598
return (NS_NOTFOUND);
599
}
600
601
switch (af) {
602
case AF_INET:
603
(void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
604
(uaddr[3] & 0xff),
605
(uaddr[2] & 0xff),
606
(uaddr[1] & 0xff),
607
(uaddr[0] & 0xff));
608
break;
609
case AF_INET6:
610
qp = qbuf;
611
for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
612
qp += SPRINTF((qp, "%x.%x.",
613
uaddr[n] & 0xf,
614
(uaddr[n] >> 4) & 0xf));
615
}
616
strlcat(qbuf, "ip6.arpa", sizeof(qbuf));
617
break;
618
default:
619
abort();
620
}
621
if ((buf = malloc(sizeof(*buf))) == NULL) {
622
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
623
*h_errnop = statp->res_h_errno;
624
return NS_NOTFOUND;
625
}
626
n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf,
627
sizeof buf->buf);
628
if (n < 0) {
629
free(buf);
630
dbg_printf("res_nquery failed (%d)\n", n, statp);
631
*h_errnop = statp->res_h_errno;
632
return (NS_UNAVAIL);
633
}
634
if (n > sizeof buf->buf) {
635
free(buf);
636
dbg_printf("static buffer is too small (%d)\n", n, statp);
637
*h_errnop = statp->res_h_errno;
638
return (NS_UNAVAIL);
639
}
640
if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) {
641
free(buf);
642
*h_errnop = statp->res_h_errno;
643
switch (statp->res_h_errno) {
644
case HOST_NOT_FOUND:
645
return (NS_NOTFOUND);
646
case TRY_AGAIN:
647
return (NS_TRYAGAIN);
648
default:
649
return (NS_UNAVAIL);
650
}
651
/*NOTREACHED*/
652
}
653
free(buf);
654
#ifdef SUNSECURITY
655
if (af == AF_INET) {
656
/*
657
* turn off search as the name should be absolute,
658
* 'localhost' should be matched by defnames
659
*/
660
strncpy(hname2, he.h_name, MAXDNAME);
661
hname2[MAXDNAME] = '\0';
662
old_options = statp->options;
663
statp->options &= ~RES_DNSRCH;
664
statp->options |= RES_DEFNAMES;
665
memset(&rhd, 0, sizeof rhd);
666
rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data,
667
sizeof(rhd.data), &ret_h_error);
668
if (rhe == NULL) {
669
if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
670
strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
671
syslog(LOG_NOTICE|LOG_AUTH,
672
"gethostbyaddr: No A record for %s (verifying [%s])",
673
hname2, numaddr);
674
statp->options = old_options;
675
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
676
*h_errnop = statp->res_h_errno;
677
return (NS_NOTFOUND);
678
}
679
statp->options = old_options;
680
for (haddr = rhe->h_addr_list; *haddr; haddr++)
681
if (!memcmp(*haddr, addr, NS_INADDRSZ))
682
break;
683
if (!*haddr) {
684
if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
685
strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
686
syslog(LOG_NOTICE|LOG_AUTH,
687
"gethostbyaddr: A record of %s != PTR record [%s]",
688
hname2, numaddr);
689
RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
690
*h_errnop = statp->res_h_errno;
691
return (NS_NOTFOUND);
692
}
693
}
694
#endif /*SUNSECURITY*/
695
he.h_addrtype = af;
696
he.h_length = len;
697
memcpy(hed->host_addr, uaddr, len);
698
hed->h_addr_ptrs[0] = (char *)hed->host_addr;
699
hed->h_addr_ptrs[1] = NULL;
700
if (af == AF_INET && (statp->options & RES_USE_INET6)) {
701
_map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
702
he.h_addrtype = AF_INET6;
703
he.h_length = NS_IN6ADDRSZ;
704
}
705
if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
706
*errnop = errno;
707
RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
708
*h_errnop = statp->res_h_errno;
709
return (NS_RETURN);
710
}
711
RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
712
*((struct hostent **)rval) = hptr;
713
return (NS_SUCCESS);
714
}
715
716
#ifdef RESOLVSORT
717
static void
718
addrsort(char **ap, int num, res_state res)
719
{
720
int i, j;
721
char **p;
722
short aval[_MAXADDRS];
723
int needsort = 0;
724
725
p = ap;
726
for (i = 0; i < num; i++, p++) {
727
for (j = 0 ; (unsigned)j < res->nsort; j++)
728
if (res->sort_list[j].addr.s_addr ==
729
(((struct in_addr *)(*p))->s_addr & res->sort_list[j].mask))
730
break;
731
aval[i] = j;
732
if (needsort == 0 && i > 0 && j < aval[i-1])
733
needsort = i;
734
}
735
if (!needsort)
736
return;
737
738
while (needsort < num) {
739
for (j = needsort - 1; j >= 0; j--) {
740
if (aval[j] > aval[j+1]) {
741
char *hp;
742
743
i = aval[j];
744
aval[j] = aval[j+1];
745
aval[j+1] = i;
746
747
hp = ap[j];
748
ap[j] = ap[j+1];
749
ap[j+1] = hp;
750
751
} else
752
break;
753
}
754
needsort++;
755
}
756
}
757
#endif
758
759
void
760
_sethostdnsent(int stayopen)
761
{
762
res_state statp;
763
764
statp = __res_state();
765
if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)
766
return;
767
if (stayopen)
768
statp->options |= RES_STAYOPEN | RES_USEVC;
769
}
770
771
void
772
_endhostdnsent(void)
773
{
774
res_state statp;
775
776
statp = __res_state();
777
statp->options &= ~(RES_STAYOPEN | RES_USEVC);
778
res_nclose(statp);
779
}
780
781