summaryrefslogtreecommitdiff
path: root/src/lib/libc/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net')
-rw-r--r--src/lib/libc/net/getaddrinfo.c1755
-rw-r--r--src/lib/libc/net/gethostnamadr.c1131
-rw-r--r--src/lib/libc/net/getnameinfo.c351
-rw-r--r--src/lib/libc/net/getnetnamadr.c384
-rw-r--r--src/lib/libc/net/getrrsetbyname.c517
-rw-r--r--src/lib/libc/net/res_debug.c1395
-rw-r--r--src/lib/libc/net/res_init.c707
-rw-r--r--src/lib/libc/net/res_mkquery.c232
-rw-r--r--src/lib/libc/net/res_query.c403
-rw-r--r--src/lib/libc/net/res_send.c853
-rw-r--r--src/lib/libc/net/sethostent.c57
11 files changed, 0 insertions, 7785 deletions
diff --git a/src/lib/libc/net/getaddrinfo.c b/src/lib/libc/net/getaddrinfo.c
deleted file mode 100644
index 29cc1f463e..0000000000
--- a/src/lib/libc/net/getaddrinfo.c
+++ /dev/null
@@ -1,1755 +0,0 @@
1/* $OpenBSD: getaddrinfo.c,v 1.72 2011/04/05 00:46:06 matthew Exp $ */
2/* $KAME: getaddrinfo.c,v 1.31 2000/08/31 17:36:43 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked.
36 * - Return values. There are nonstandard return values defined and used
37 * in the source code. This is because RFC2553 is silent about which error
38 * code must be returned for which situation.
39 * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2
40 * says to use inet_aton() to convert IPv4 numeric to binary (allows
41 * classful form as a result).
42 * current code - disallow classful form for IPv4 (due to use of inet_pton).
43 * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
44 * invalid.
45 * current code - SEGV on freeaddrinfo(NULL)
46 * Note:
47 * - We use getipnodebyname() just for thread-safeness. There's no intent
48 * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to
49 * getipnodebyname().
50 * - The code filters out AFs that are not supported by the kernel,
51 * when globbing NULL hostname (to loopback, or wildcard). Is it the right
52 * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
53 * in ai_flags?
54 * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
55 * (1) what should we do against numeric hostname (2) what should we do
56 * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
57 * non-loopback address configured? global address configured?
58 * - To avoid search order issue, we have a big amount of code duplicate
59 * from gethnamaddr.c and some other places. The issues that there's no
60 * lower layer function to lookup "IPv4 or IPv6" record. Calling
61 * gethostbyname2 from getaddrinfo will end up in wrong search order, as
62 * follows:
63 * - The code makes use of following calls when asked to resolver with
64 * ai_family = PF_UNSPEC:
65 * getipnodebyname(host, AF_INET6);
66 * getipnodebyname(host, AF_INET);
67 * This will result in the following queries if the node is configure to
68 * prefer /etc/hosts than DNS:
69 * lookup /etc/hosts for IPv6 address
70 * lookup DNS for IPv6 address
71 * lookup /etc/hosts for IPv4 address
72 * lookup DNS for IPv4 address
73 * which may not meet people's requirement.
74 * The right thing to happen is to have underlying layer which does
75 * PF_UNSPEC lookup (lookup both) and return chain of addrinfos.
76 * This would result in a bit of code duplicate with _dns_ghbyname() and
77 * friends.
78 */
79
80#ifndef INET6
81#define INET6
82#endif
83
84#include <sys/types.h>
85#include <sys/param.h>
86#include <sys/socket.h>
87#include <net/if.h>
88#include <netinet/in.h>
89#include <arpa/inet.h>
90#include <arpa/nameser.h>
91#include <netdb.h>
92#include <resolv.h>
93#include <string.h>
94#include <stdint.h>
95#include <stdlib.h>
96#include <stddef.h>
97#include <ctype.h>
98#include <unistd.h>
99#include <stdio.h>
100#include <errno.h>
101
102#include <syslog.h>
103#include <stdarg.h>
104
105#ifdef YP
106#include <rpc/rpc.h>
107#include <rpcsvc/yp.h>
108#include <rpcsvc/ypclnt.h>
109#include "ypinternal.h"
110#endif
111
112#include "thread_private.h"
113
114#define SUCCESS 0
115#define ANY 0
116#define YES 1
117#define NO 0
118
119static const char in_addrany[] = { 0, 0, 0, 0 };
120static const char in6_addrany[] = {
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
122};
123static const char in_loopback[] = { 127, 0, 0, 1 };
124static const char in6_loopback[] = {
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
126};
127
128static const struct afd {
129 int a_af;
130 int a_addrlen;
131 int a_socklen;
132 int a_off;
133 const char *a_addrany;
134 const char *a_loopback;
135 int a_scoped;
136} afdl [] = {
137#ifdef INET6
138 {PF_INET6, sizeof(struct in6_addr),
139 sizeof(struct sockaddr_in6),
140 offsetof(struct sockaddr_in6, sin6_addr),
141 in6_addrany, in6_loopback, 1},
142#endif
143 {PF_INET, sizeof(struct in_addr),
144 sizeof(struct sockaddr_in),
145 offsetof(struct sockaddr_in, sin_addr),
146 in_addrany, in_loopback, 0},
147 {0, 0, 0, 0, NULL, NULL, 0},
148};
149
150struct explore {
151 int e_af;
152 int e_socktype;
153 int e_protocol;
154 const char *e_protostr;
155 int e_wild;
156#define WILD_AF(ex) ((ex)->e_wild & 0x01)
157#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
158#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
159};
160
161static const struct explore explore[] = {
162#if 0
163 { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
164#endif
165#ifdef INET6
166 { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
167 { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
168 { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
169#endif
170 { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
171 { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
172 { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
173 { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
174 { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
175 { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
176 { -1, 0, 0, NULL, 0 },
177};
178
179#ifdef INET6
180#define PTON_MAX 16
181#else
182#define PTON_MAX 4
183#endif
184
185#define MAXPACKET (64*1024)
186
187typedef union {
188 HEADER hdr;
189 u_char buf[MAXPACKET];
190} querybuf;
191
192struct res_target {
193 struct res_target *next;
194 const char *name; /* domain name */
195 int qclass, qtype; /* class and type of query */
196 u_char *answer; /* buffer to put answer */
197 int anslen; /* size of answer buffer */
198 int n; /* result length */
199};
200
201static int explore_fqdn(const struct addrinfo *, const char *,
202 const char *, struct addrinfo **);
203static int explore_null(const struct addrinfo *,
204 const char *, struct addrinfo **);
205static int explore_numeric(const struct addrinfo *, const char *,
206 const char *, struct addrinfo **, const char *);
207static int explore_numeric_scope(const struct addrinfo *, const char *,
208 const char *, struct addrinfo **);
209static int get_canonname(const struct addrinfo *,
210 struct addrinfo *, const char *);
211static struct addrinfo *get_ai(const struct addrinfo *,
212 const struct afd *, const char *);
213static int get_portmatch(const struct addrinfo *, const char *);
214static int get_port(struct addrinfo *, const char *, int);
215static const struct afd *find_afd(int);
216#ifdef INET6
217static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
218#endif
219
220static struct addrinfo * _gethtent(const char *, const struct addrinfo *,
221 FILE *);
222static struct addrinfo *_files_getaddrinfo(const char *,
223 const struct addrinfo *);
224
225#ifdef YP
226static struct addrinfo *_yphostent(char *, const struct addrinfo *);
227static struct addrinfo *_yp_getaddrinfo(const char *,
228 const struct addrinfo *);
229#endif
230
231static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
232 const struct addrinfo *);
233static int res_queryN(const char *, struct res_target *);
234static int res_searchN(const char *, struct res_target *);
235static int res_querydomainN(const char *, const char *, struct res_target *);
236static struct addrinfo *_dns_getaddrinfo(const char *, const struct addrinfo *,
237 const struct __res_state *);
238
239
240/* XXX macros that make external reference is BAD. */
241
242#define GET_AI(ai, afd, addr) \
243do { \
244 /* external reference: pai, error, and label free */ \
245 (ai) = get_ai(pai, (afd), (addr)); \
246 if ((ai) == NULL) { \
247 error = EAI_MEMORY; \
248 goto free; \
249 } \
250} while (/*CONSTCOND*/0)
251
252#define GET_PORT(ai, serv) \
253do { \
254 /* external reference: error and label free */ \
255 error = get_port((ai), (serv), 0); \
256 if (error != 0) \
257 goto free; \
258} while (/*CONSTCOND*/0)
259
260#define GET_CANONNAME(ai, str) \
261do { \
262 /* external reference: pai, error and label free */ \
263 error = get_canonname(pai, (ai), (str)); \
264 if (error != 0) \
265 goto free; \
266} while (/*CONSTCOND*/0)
267
268#define ERR(err) \
269do { \
270 /* external reference: error, and label bad */ \
271 error = (err); \
272 goto bad; \
273 /*NOTREACHED*/ \
274} while (/*CONSTCOND*/0)
275
276#define MATCH_FAMILY(x, y, w) \
277 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
278#define MATCH(x, y, w) \
279 ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
280
281int
282getaddrinfo(const char *hostname, const char *servname,
283 const struct addrinfo *hints, struct addrinfo **res)
284{
285 struct addrinfo sentinel;
286 struct addrinfo *cur;
287 int error = 0;
288 struct addrinfo ai;
289 struct addrinfo ai0;
290 struct addrinfo *pai;
291 const struct explore *ex;
292
293 memset(&sentinel, 0, sizeof(sentinel));
294 cur = &sentinel;
295 pai = &ai;
296 pai->ai_flags = 0;
297 pai->ai_family = PF_UNSPEC;
298 pai->ai_socktype = ANY;
299 pai->ai_protocol = ANY;
300 pai->ai_addrlen = 0;
301 pai->ai_canonname = NULL;
302 pai->ai_addr = NULL;
303 pai->ai_next = NULL;
304
305 if (hostname == NULL && servname == NULL)
306 return EAI_NONAME;
307 if (hints) {
308 /* error check for hints */
309 if (hints->ai_addrlen || hints->ai_canonname ||
310 hints->ai_addr || hints->ai_next)
311 ERR(EAI_BADHINTS); /* xxx */
312 if ((hints->ai_flags & ~AI_MASK) != 0 ||
313 (hints->ai_flags & (AI_CANONNAME | AI_FQDN)) ==
314 (AI_CANONNAME | AI_FQDN))
315 ERR(EAI_BADFLAGS);
316 switch (hints->ai_family) {
317 case PF_UNSPEC:
318 case PF_INET:
319#ifdef INET6
320 case PF_INET6:
321#endif
322 break;
323 default:
324 ERR(EAI_FAMILY);
325 }
326 memcpy(pai, hints, sizeof(*pai));
327
328 /*
329 * if both socktype/protocol are specified, check if they
330 * are meaningful combination.
331 */
332 if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
333 for (ex = explore; ex->e_af >= 0; ex++) {
334 if (pai->ai_family != ex->e_af)
335 continue;
336 if (ex->e_socktype == ANY)
337 continue;
338 if (ex->e_protocol == ANY)
339 continue;
340 if (pai->ai_socktype == ex->e_socktype
341 && pai->ai_protocol != ex->e_protocol) {
342 ERR(EAI_BADHINTS);
343 }
344 }
345 }
346 }
347
348 /*
349 * check for special cases. (1) numeric servname is disallowed if
350 * socktype/protocol are left unspecified. (2) servname is disallowed
351 * for raw and other inet{,6} sockets.
352 */
353 if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
354#ifdef PF_INET6
355 || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
356#endif
357 ) {
358 ai0 = *pai; /* backup *pai */
359
360 if (pai->ai_family == PF_UNSPEC) {
361#ifdef PF_INET6
362 pai->ai_family = PF_INET6;
363#else
364 pai->ai_family = PF_INET;
365#endif
366 }
367 error = get_portmatch(pai, servname);
368 if (error)
369 ERR(error);
370
371 *pai = ai0;
372 }
373
374 ai0 = *pai;
375
376 /* NULL hostname, or numeric hostname */
377 for (ex = explore; ex->e_af >= 0; ex++) {
378 *pai = ai0;
379
380 /* PF_UNSPEC entries are prepared for DNS queries only */
381 if (ex->e_af == PF_UNSPEC)
382 continue;
383
384 if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
385 continue;
386 if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
387 continue;
388 if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
389 continue;
390
391 if (pai->ai_family == PF_UNSPEC)
392 pai->ai_family = ex->e_af;
393 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
394 pai->ai_socktype = ex->e_socktype;
395 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
396 pai->ai_protocol = ex->e_protocol;
397
398 if (hostname == NULL)
399 error = explore_null(pai, servname, &cur->ai_next);
400 else
401 error = explore_numeric_scope(pai, hostname, servname,
402 &cur->ai_next);
403
404 if (error)
405 goto free;
406
407 while (cur && cur->ai_next)
408 cur = cur->ai_next;
409 }
410
411 /*
412 * XXX
413 * If numeric representation of AF1 can be interpreted as FQDN
414 * representation of AF2, we need to think again about the code below.
415 */
416 if (sentinel.ai_next)
417 goto good;
418
419 if (hostname == NULL)
420 ERR(EAI_NODATA);
421 if (pai->ai_flags & AI_NUMERICHOST)
422 ERR(EAI_NONAME);
423
424 /*
425 * hostname as alphabetical name.
426 * we would like to prefer AF_INET6 than AF_INET, so we'll make an
427 * outer loop by AFs.
428 */
429 for (ex = explore; ex->e_af >= 0; ex++) {
430 *pai = ai0;
431
432 /* require exact match for family field */
433 if (pai->ai_family != ex->e_af)
434 continue;
435
436 if (!MATCH(pai->ai_socktype, ex->e_socktype,
437 WILD_SOCKTYPE(ex))) {
438 continue;
439 }
440 if (!MATCH(pai->ai_protocol, ex->e_protocol,
441 WILD_PROTOCOL(ex))) {
442 continue;
443 }
444
445 if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
446 pai->ai_socktype = ex->e_socktype;
447 if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
448 pai->ai_protocol = ex->e_protocol;
449
450 error = explore_fqdn(pai, hostname, servname,
451 &cur->ai_next);
452
453 while (cur && cur->ai_next)
454 cur = cur->ai_next;
455 }
456
457 /* XXX */
458 if (sentinel.ai_next)
459 error = 0;
460
461 if (error == 0) {
462 if (sentinel.ai_next) {
463 good:
464 *res = sentinel.ai_next;
465 return SUCCESS;
466 } else
467 error = EAI_FAIL;
468 }
469 free:
470 bad:
471 if (sentinel.ai_next)
472 freeaddrinfo(sentinel.ai_next);
473 *res = NULL;
474 return error;
475}
476
477/*
478 * FQDN hostname, DNS lookup
479 */
480
481static int
482explore_fqdn(const struct addrinfo *pai, const char *hostname,
483 const char *servname, struct addrinfo **res)
484{
485 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
486 struct addrinfo *result;
487 struct addrinfo *cur;
488 int error = 0;
489 char lookups[MAXDNSLUS];
490 int i;
491 _THREAD_PRIVATE_MUTEX(_explore_mutex);
492
493 result = NULL;
494
495 /*
496 * if the servname does not match socktype/protocol, ignore it.
497 */
498 if (get_portmatch(pai, servname) != 0) {
499 return 0;
500 }
501
502 if (_res_init(0) == -1)
503 strlcpy(lookups, "f", sizeof lookups);
504 else {
505 bcopy(_resp->lookups, lookups, sizeof lookups);
506 if (lookups[0] == '\0')
507 strlcpy(lookups, "bf", sizeof lookups);
508 }
509
510 /*
511 * The yp/dns/files getaddrinfo functions are not thread safe.
512 * Protect them with a mutex.
513 */
514 _THREAD_PRIVATE_MUTEX_LOCK(_explore_mutex);
515 for (i = 0; i < MAXDNSLUS && result == NULL && lookups[i]; i++) {
516 switch (lookups[i]) {
517#ifdef YP
518 case 'y':
519 result = _yp_getaddrinfo(hostname, pai);
520 break;
521#endif
522 case 'b':
523 result = _dns_getaddrinfo(hostname, pai, _resp);
524 break;
525 case 'f':
526 result = _files_getaddrinfo(hostname, pai);
527 break;
528 }
529 }
530 _THREAD_PRIVATE_MUTEX_UNLOCK(_explore_mutex);
531 if (result) {
532 for (cur = result; cur; cur = cur->ai_next) {
533 GET_PORT(cur, servname);
534 /* canonname should be filled already */
535 }
536 *res = result;
537 return 0;
538 } else {
539 /* translate error code */
540 switch (h_errno) {
541 case NETDB_SUCCESS:
542 error = EAI_FAIL; /*XXX strange */
543 break;
544 case HOST_NOT_FOUND:
545 error = EAI_NODATA;
546 break;
547 case TRY_AGAIN:
548 error = EAI_AGAIN;
549 break;
550 case NO_RECOVERY:
551 error = EAI_FAIL;
552 break;
553 case NO_DATA:
554#if NO_ADDRESS != NO_DATA
555 case NO_ADDRESS:
556#endif
557 error = EAI_NODATA;
558 break;
559 default: /* unknown ones */
560 error = EAI_FAIL;
561 break;
562 }
563 }
564
565free:
566 if (result)
567 freeaddrinfo(result);
568 return error;
569}
570
571/*
572 * hostname == NULL.
573 * passive socket -> anyaddr (0.0.0.0 or ::)
574 * non-passive socket -> localhost (127.0.0.1 or ::1)
575 */
576static int
577explore_null(const struct addrinfo *pai, const char *servname,
578 struct addrinfo **res)
579{
580 int s;
581 const struct afd *afd;
582 struct addrinfo *cur;
583 struct addrinfo sentinel;
584 int error;
585
586 *res = NULL;
587 sentinel.ai_next = NULL;
588 cur = &sentinel;
589
590 /*
591 * filter out AFs that are not supported by the kernel
592 * XXX errno?
593 */
594 s = socket(pai->ai_family, SOCK_DGRAM, 0);
595 if (s < 0) {
596 if (errno != EMFILE)
597 return 0;
598 } else
599 close(s);
600
601 /*
602 * if the servname does not match socktype/protocol, ignore it.
603 */
604 if (get_portmatch(pai, servname) != 0)
605 return 0;
606
607 afd = find_afd(pai->ai_family);
608 if (afd == NULL)
609 return 0;
610
611 if (pai->ai_flags & AI_PASSIVE) {
612 GET_AI(cur->ai_next, afd, afd->a_addrany);
613 /* xxx meaningless?
614 * GET_CANONNAME(cur->ai_next, "anyaddr");
615 */
616 } else {
617 GET_AI(cur->ai_next, afd, afd->a_loopback);
618 /* xxx meaningless?
619 * GET_CANONNAME(cur->ai_next, "localhost");
620 */
621 }
622 GET_PORT(cur->ai_next, servname);
623 cur = cur->ai_next;
624
625 *res = sentinel.ai_next;
626 return 0;
627
628free:
629 if (sentinel.ai_next)
630 freeaddrinfo(sentinel.ai_next);
631 return error;
632}
633
634/*
635 * numeric hostname
636 */
637static int
638explore_numeric(const struct addrinfo *pai, const char *hostname,
639 const char *servname, struct addrinfo **res, const char *canonname)
640{
641 const struct afd *afd;
642 struct addrinfo *cur;
643 struct addrinfo sentinel;
644 int error;
645 char pton[PTON_MAX];
646
647 *res = NULL;
648 sentinel.ai_next = NULL;
649 cur = &sentinel;
650
651 /*
652 * if the servname does not match socktype/protocol, ignore it.
653 */
654 if (get_portmatch(pai, servname) != 0)
655 return 0;
656
657 afd = find_afd(pai->ai_family);
658 if (afd == NULL)
659 return 0;
660
661 switch (afd->a_af) {
662#if 0 /*X/Open spec*/
663 case AF_INET:
664 error = inet_aton(hostname, (struct in_addr *)pton);
665 break;
666#endif
667 default:
668 error = inet_pton(afd->a_af, hostname, pton);
669 break;
670 }
671 if (error == 1) {
672 if (pai->ai_family == afd->a_af ||
673 pai->ai_family == PF_UNSPEC /*?*/) {
674 GET_AI(cur->ai_next, afd, pton);
675 GET_PORT(cur->ai_next, servname);
676 /*
677 * Set the numeric address itself as
678 * the canonical name, based on a
679 * clarification in rfc2553bis-03.
680 */
681 GET_CANONNAME(cur->ai_next, canonname);
682
683 while (cur && cur->ai_next)
684 cur = cur->ai_next;
685 } else
686 ERR(EAI_FAMILY); /*xxx*/
687 }
688
689 *res = sentinel.ai_next;
690 return 0;
691
692free:
693bad:
694 if (sentinel.ai_next)
695 freeaddrinfo(sentinel.ai_next);
696 return error;
697}
698
699/*
700 * numeric hostname with scope
701 */
702static int
703explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
704 const char *servname, struct addrinfo **res)
705{
706#if !defined(SCOPE_DELIMITER) || !defined(INET6)
707 return explore_numeric(pai, hostname, servname, res, hostname);
708#else
709 const struct afd *afd;
710 struct addrinfo *cur;
711 int error;
712 char *cp, *hostname2 = NULL, *scope, *addr;
713 struct sockaddr_in6 *sin6;
714
715 /*
716 * if the servname does not match socktype/protocol, ignore it.
717 */
718 if (get_portmatch(pai, servname) != 0)
719 return 0;
720
721 afd = find_afd(pai->ai_family);
722 if (afd == NULL)
723 return 0;
724
725 if (!afd->a_scoped)
726 return explore_numeric(pai, hostname, servname, res, hostname);
727
728 cp = strchr(hostname, SCOPE_DELIMITER);
729 if (cp == NULL)
730 return explore_numeric(pai, hostname, servname, res, hostname);
731
732 /*
733 * Handle special case of <scoped_address><delimiter><scope id>
734 */
735 hostname2 = strdup(hostname);
736 if (hostname2 == NULL)
737 return EAI_MEMORY;
738 /* terminate at the delimiter */
739 hostname2[cp - hostname] = '\0';
740 addr = hostname2;
741 scope = cp + 1;
742
743 error = explore_numeric(pai, addr, servname, res, hostname);
744 if (error == 0) {
745 u_int32_t scopeid;
746
747 for (cur = *res; cur; cur = cur->ai_next) {
748 if (cur->ai_family != AF_INET6)
749 continue;
750 sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
751 if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
752 free(hostname2);
753 return(EAI_NODATA); /* XXX: is return OK? */
754 }
755 sin6->sin6_scope_id = scopeid;
756 }
757 }
758
759 free(hostname2);
760
761 return error;
762#endif
763}
764
765static int
766get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
767{
768 if ((pai->ai_flags & (AI_CANONNAME | AI_FQDN)) != 0) {
769 ai->ai_canonname = strdup(str);
770 if (ai->ai_canonname == NULL)
771 return EAI_MEMORY;
772 }
773 return 0;
774}
775
776static struct addrinfo *
777get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
778{
779 char *p;
780 struct addrinfo *ai;
781
782 ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
783 + (afd->a_socklen));
784 if (ai == NULL)
785 return NULL;
786
787 memcpy(ai, pai, sizeof(struct addrinfo));
788 ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
789 memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
790 ai->ai_addr->sa_len = afd->a_socklen;
791 ai->ai_addrlen = afd->a_socklen;
792 ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
793 p = (char *)(void *)(ai->ai_addr);
794 memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
795 return ai;
796}
797
798static int
799get_portmatch(const struct addrinfo *ai, const char *servname)
800{
801
802 /* get_port does not touch first argument. when matchonly == 1. */
803 /* LINTED const cast */
804 return get_port((struct addrinfo *)ai, servname, 1);
805}
806
807static int
808get_port(struct addrinfo *ai, const char *servname, int matchonly)
809{
810 const char *errstr, *proto;
811 int port;
812 int allownumeric;
813
814 if (servname == NULL)
815 return 0;
816 switch (ai->ai_family) {
817 case AF_INET:
818#ifdef AF_INET6
819 case AF_INET6:
820#endif
821 break;
822 default:
823 return 0;
824 }
825
826 switch (ai->ai_socktype) {
827 case SOCK_RAW:
828 return EAI_SERVICE;
829 case SOCK_DGRAM:
830 case SOCK_STREAM:
831 case ANY:
832 allownumeric = 1;
833 break;
834 default:
835 return EAI_SOCKTYPE;
836 }
837
838 port = (int)strtonum(servname, 0, USHRT_MAX, &errstr);
839 if (!errstr) {
840 if (!allownumeric)
841 return EAI_SERVICE;
842 port = htons(port);
843 } else {
844 struct servent sp;
845 struct servent_data sd;
846
847 if (errno == ERANGE)
848 return EAI_SERVICE;
849 if (ai->ai_flags & AI_NUMERICSERV)
850 return EAI_NONAME;
851
852 switch (ai->ai_socktype) {
853 case SOCK_DGRAM:
854 proto = "udp";
855 break;
856 case SOCK_STREAM:
857 proto = "tcp";
858 break;
859 default:
860 proto = NULL;
861 break;
862 }
863
864 (void)memset(&sd, 0, sizeof(sd));
865 if (getservbyname_r(servname, proto, &sp, &sd) == -1)
866 return EAI_SERVICE;
867 port = sp.s_port;
868 endservent_r(&sd);
869 }
870
871 if (!matchonly) {
872 switch (ai->ai_family) {
873 case AF_INET:
874 ((struct sockaddr_in *)(void *)
875 ai->ai_addr)->sin_port = port;
876 break;
877#ifdef INET6
878 case AF_INET6:
879 ((struct sockaddr_in6 *)(void *)
880 ai->ai_addr)->sin6_port = port;
881 break;
882#endif
883 }
884 }
885
886 return 0;
887}
888
889static const struct afd *
890find_afd(int af)
891{
892 const struct afd *afd;
893
894 if (af == PF_UNSPEC)
895 return NULL;
896 for (afd = afdl; afd->a_af; afd++) {
897 if (afd->a_af == af)
898 return afd;
899 }
900 return NULL;
901}
902
903#ifdef INET6
904/* convert a string to a scope identifier. XXX: IPv6 specific */
905static int
906ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
907{
908 struct in6_addr *a6 = &sin6->sin6_addr;
909 const char *errstr;
910
911 /* empty scopeid portion is invalid */
912 if (*scope == '\0')
913 return -1;
914
915 if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
916 IN6_IS_ADDR_MC_INTFACELOCAL(a6)) {
917 /*
918 * We currently assume a one-to-one mapping between links
919 * and interfaces, so we simply use interface indices for
920 * like-local scopes.
921 */
922 *scopeid = if_nametoindex(scope);
923 if (*scopeid == 0)
924 goto trynumeric;
925 return 0;
926 }
927
928 /* still unclear about literal, allow numeric only - placeholder */
929 if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
930 goto trynumeric;
931 if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
932 goto trynumeric;
933 else
934 goto trynumeric; /* global */
935
936 /* try to convert to a numeric id as a last resort */
937 trynumeric:
938 *scopeid = (u_int32_t)strtonum(scope, 0, UINT32_MAX, &errstr);
939 if (errstr)
940 return (-1);
941 return (0);
942}
943#endif
944
945/* code duplicate with gethnamaddr.c */
946
947static const char AskedForGot[] =
948 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
949
950static struct addrinfo *
951getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
952 const struct addrinfo *pai)
953{
954 struct addrinfo sentinel, *cur;
955 struct addrinfo ai;
956 const struct afd *afd;
957 char *canonname;
958 const HEADER *hp;
959 const u_char *cp;
960 int n;
961 const u_char *eom;
962 char *bp, *ep;
963 int type, class, ancount, qdcount;
964 int haveanswer, had_error;
965 char tbuf[MAXDNAME];
966 int (*name_ok)(const char *);
967 char hostbuf[8*1024];
968
969 memset(&sentinel, 0, sizeof(sentinel));
970 cur = &sentinel;
971
972 canonname = NULL;
973 eom = answer->buf + anslen;
974 switch (qtype) {
975 case T_A:
976 case T_AAAA:
977 case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
978 name_ok = res_hnok;
979 break;
980 default:
981 return (NULL); /* XXX should be abort() -- but that is illegal */
982 }
983 /*
984 * find first satisfactory answer
985 */
986 hp = &answer->hdr;
987 ancount = ntohs(hp->ancount);
988 qdcount = ntohs(hp->qdcount);
989 bp = hostbuf;
990 ep = hostbuf + sizeof hostbuf;
991 cp = answer->buf + HFIXEDSZ;
992 if (qdcount != 1) {
993 h_errno = NO_RECOVERY;
994 return (NULL);
995 }
996 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
997 if ((n < 0) || !(*name_ok)(bp)) {
998 h_errno = NO_RECOVERY;
999 return (NULL);
1000 }
1001 cp += n + QFIXEDSZ;
1002 if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
1003 size_t len;
1004
1005 /* res_send() has already verified that the query name is the
1006 * same as the one we sent; this just gets the expanded name
1007 * (i.e., with the succeeding search-domain tacked on).
1008 */
1009 len = strlen(bp) + 1; /* for the \0 */
1010 if (len >= MAXHOSTNAMELEN) {
1011 h_errno = NO_RECOVERY;
1012 return (NULL);
1013 }
1014 canonname = bp;
1015 bp += len;
1016 /* The qname can be abbreviated, but h_name is now absolute. */
1017 qname = canonname;
1018 }
1019 haveanswer = 0;
1020 had_error = 0;
1021 while (ancount-- > 0 && cp < eom && !had_error) {
1022 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
1023 if ((n < 0) || !(*name_ok)(bp)) {
1024 had_error++;
1025 continue;
1026 }
1027 cp += n; /* name */
1028 type = _getshort(cp);
1029 cp += INT16SZ; /* type */
1030 class = _getshort(cp);
1031 cp += INT16SZ + INT32SZ; /* class, TTL */
1032 n = _getshort(cp);
1033 cp += INT16SZ; /* len */
1034 if (class != C_IN) {
1035 /* XXX - debug? syslog? */
1036 cp += n;
1037 continue; /* XXX - had_error++ ? */
1038 }
1039 if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
1040 type == T_CNAME) {
1041 size_t len;
1042
1043 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
1044 if ((n < 0) || !(*name_ok)(tbuf)) {
1045 had_error++;
1046 continue;
1047 }
1048 cp += n;
1049 /* Get canonical name. */
1050 len = strlen(tbuf) + 1; /* for the \0 */
1051 if (len > ep - bp || len >= MAXHOSTNAMELEN) {
1052 had_error++;
1053 continue;
1054 }
1055 strlcpy(bp, tbuf, ep - bp);
1056 canonname = bp;
1057 bp += len;
1058 continue;
1059 }
1060 if (qtype == T_ANY) {
1061 if (!(type == T_A || type == T_AAAA)) {
1062 cp += n;
1063 continue;
1064 }
1065 } else if (type != qtype) {
1066#ifndef NO_LOG_BAD_DNS_RESPONSES
1067 if (type != T_KEY && type != T_SIG) {
1068 struct syslog_data sdata = SYSLOG_DATA_INIT;
1069
1070 syslog_r(LOG_NOTICE|LOG_AUTH, &sdata,
1071 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
1072 qname, p_class(C_IN), p_type(qtype),
1073 p_type(type));
1074 }
1075#endif /* NO_LOG_BAD_DNS_RESPONSES */
1076 cp += n;
1077 continue; /* XXX - had_error++ ? */
1078 }
1079 switch (type) {
1080 case T_A:
1081 case T_AAAA:
1082 if (strcasecmp(canonname, bp) != 0) {
1083 struct syslog_data sdata = SYSLOG_DATA_INIT;
1084
1085 syslog_r(LOG_NOTICE|LOG_AUTH, &sdata,
1086 AskedForGot, canonname, bp);
1087 cp += n;
1088 continue; /* XXX - had_error++ ? */
1089 }
1090 if (type == T_A && n != INADDRSZ) {
1091 cp += n;
1092 continue;
1093 }
1094 if (type == T_AAAA && n != IN6ADDRSZ) {
1095 cp += n;
1096 continue;
1097 }
1098 if (type == T_AAAA) {
1099 struct in6_addr in6;
1100 memcpy(&in6, cp, IN6ADDRSZ);
1101 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
1102 cp += n;
1103 continue;
1104 }
1105 }
1106 if (!haveanswer) {
1107 canonname = bp;
1108 bp += strlen(bp) + 1; /* for the \0 */
1109 }
1110
1111 /* don't overwrite pai */
1112 ai = *pai;
1113 ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
1114 afd = find_afd(ai.ai_family);
1115 if (afd == NULL) {
1116 cp += n;
1117 continue;
1118 }
1119 cur->ai_next = get_ai(&ai, afd, (const char *)cp);
1120 if (cur->ai_next == NULL)
1121 had_error++;
1122 while (cur && cur->ai_next)
1123 cur = cur->ai_next;
1124 cp += n;
1125 break;
1126 default:
1127 abort(); /* XXX abort illegal in library */
1128 }
1129 if (!had_error)
1130 haveanswer++;
1131 }
1132 if (haveanswer) {
1133 if (!canonname || (pai->ai_flags & AI_FQDN) != 0)
1134 (void)get_canonname(pai, sentinel.ai_next, qname);
1135 else
1136 (void)get_canonname(pai, sentinel.ai_next, canonname);
1137 h_errno = NETDB_SUCCESS;
1138 return sentinel.ai_next;
1139 }
1140
1141 h_errno = NO_RECOVERY;
1142 return NULL;
1143}
1144
1145/*ARGSUSED*/
1146static struct addrinfo *
1147_dns_getaddrinfo(const char *name, const struct addrinfo *pai,
1148 const struct __res_state *_resp)
1149{
1150 struct addrinfo *ai;
1151 querybuf *buf, *buf2;
1152 struct addrinfo sentinel, *cur;
1153 struct res_target q, q2;
1154
1155 memset(&q, 0, sizeof(q));
1156 memset(&q2, 0, sizeof(q2));
1157 memset(&sentinel, 0, sizeof(sentinel));
1158 cur = &sentinel;
1159
1160 buf = malloc(sizeof(*buf));
1161 if (buf == NULL) {
1162 h_errno = NETDB_INTERNAL;
1163 return NULL;
1164 }
1165 buf2 = malloc(sizeof(*buf2));
1166 if (buf2 == NULL) {
1167 free(buf);
1168 h_errno = NETDB_INTERNAL;
1169 return NULL;
1170 }
1171
1172 switch (pai->ai_family) {
1173 case AF_UNSPEC:
1174 /* respect user supplied order */
1175 q.qclass = C_IN;
1176 q.qtype = (_resp->family[0] == AF_INET6) ? T_AAAA : T_A;
1177 q.answer = buf->buf;
1178 q.anslen = sizeof(buf->buf);
1179 q.next = &q2;
1180
1181 if (_resp->family[1] == -1) {
1182 /* stop here if only one family was given */
1183 q.next = NULL;
1184 break;
1185 }
1186
1187 q2.qclass = C_IN;
1188 q2.qtype = (_resp->family[1] == AF_INET6) ? T_AAAA : T_A;
1189 q2.answer = buf2->buf;
1190 q2.anslen = sizeof(buf2->buf);
1191 break;
1192 case AF_INET:
1193 q.qclass = C_IN;
1194 q.qtype = T_A;
1195 q.answer = buf->buf;
1196 q.anslen = sizeof(buf->buf);
1197 break;
1198 case AF_INET6:
1199 q.qclass = C_IN;
1200 q.qtype = T_AAAA;
1201 q.answer = buf->buf;
1202 q.anslen = sizeof(buf->buf);
1203 break;
1204 default:
1205 free(buf);
1206 free(buf2);
1207 return NULL;
1208 }
1209 if (res_searchN(name, &q) < 0) {
1210 free(buf);
1211 free(buf2);
1212 return NULL;
1213 }
1214 ai = getanswer(buf, q.n, q.name, q.qtype, pai);
1215 if (ai) {
1216 cur->ai_next = ai;
1217 while (cur && cur->ai_next)
1218 cur = cur->ai_next;
1219 }
1220 if (q.next) {
1221 ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai);
1222 if (ai)
1223 cur->ai_next = ai;
1224 }
1225 free(buf);
1226 free(buf2);
1227 return sentinel.ai_next;
1228}
1229
1230static struct addrinfo *
1231_gethtent(const char *name, const struct addrinfo *pai, FILE *hostf)
1232{
1233 char *p;
1234 char *cp, *tname, *cname;
1235 struct addrinfo hints, *res0, *res;
1236 int error;
1237 const char *addr;
1238 char hostbuf[8*1024];
1239
1240 again:
1241 if (!(p = fgets(hostbuf, sizeof hostbuf, hostf)))
1242 return (NULL);
1243 if (*p == '#')
1244 goto again;
1245 if (!(cp = strpbrk(p, "#\n")))
1246 goto again;
1247 *cp = '\0';
1248 if (!(cp = strpbrk(p, " \t")))
1249 goto again;
1250 *cp++ = '\0';
1251 addr = p;
1252 /* if this is not something we're looking for, skip it. */
1253 cname = NULL;
1254 while (cp && *cp) {
1255 if (*cp == ' ' || *cp == '\t') {
1256 cp++;
1257 continue;
1258 }
1259 if (!cname)
1260 cname = cp;
1261 tname = cp;
1262 if ((cp = strpbrk(cp, " \t")) != NULL)
1263 *cp++ = '\0';
1264 if (strcasecmp(name, tname) == 0)
1265 goto found;
1266 }
1267 goto again;
1268
1269found:
1270 hints = *pai;
1271 hints.ai_flags = AI_NUMERICHOST;
1272 error = getaddrinfo(addr, NULL, &hints, &res0);
1273 if (error)
1274 goto again;
1275 for (res = res0; res; res = res->ai_next) {
1276 /* cover it up */
1277 res->ai_flags = pai->ai_flags;
1278
1279 if (get_canonname(pai, res, cname) != 0) {
1280 freeaddrinfo(res0);
1281 goto again;
1282 }
1283 }
1284 return res0;
1285}
1286
1287/*ARGSUSED*/
1288static struct addrinfo *
1289_files_getaddrinfo(const char *name, const struct addrinfo *pai)
1290{
1291 struct addrinfo sentinel, *cur;
1292 struct addrinfo *p;
1293 FILE *hostf;
1294
1295 hostf = fopen(_PATH_HOSTS, "r");
1296 if (hostf == NULL)
1297 return NULL;
1298
1299 memset(&sentinel, 0, sizeof(sentinel));
1300 cur = &sentinel;
1301
1302 while ((p = _gethtent(name, pai, hostf)) != NULL) {
1303 cur->ai_next = p;
1304 while (cur && cur->ai_next)
1305 cur = cur->ai_next;
1306 }
1307 fclose(hostf);
1308
1309 return sentinel.ai_next;
1310}
1311
1312#ifdef YP
1313static char *__ypdomain;
1314
1315/*ARGSUSED*/
1316static struct addrinfo *
1317_yphostent(char *line, const struct addrinfo *pai)
1318{
1319 struct addrinfo sentinel, *cur;
1320 struct addrinfo hints, *res, *res0;
1321 int error;
1322 char *p = line;
1323 const char *addr, *canonname;
1324 char *nextline;
1325 char *cp;
1326
1327 addr = canonname = NULL;
1328
1329 memset(&sentinel, 0, sizeof(sentinel));
1330 cur = &sentinel;
1331
1332nextline:
1333 /* terminate line */
1334 cp = strchr(p, '\n');
1335 if (cp) {
1336 *cp++ = '\0';
1337 nextline = cp;
1338 } else
1339 nextline = NULL;
1340
1341 cp = strpbrk(p, " \t");
1342 if (cp == NULL) {
1343 if (canonname == NULL)
1344 return (NULL);
1345 else
1346 goto done;
1347 }
1348 *cp++ = '\0';
1349
1350 addr = p;
1351
1352 while (cp && *cp) {
1353 if (*cp == ' ' || *cp == '\t') {
1354 cp++;
1355 continue;
1356 }
1357 if (!canonname)
1358 canonname = cp;
1359 if ((cp = strpbrk(cp, " \t")) != NULL)
1360 *cp++ = '\0';
1361 }
1362
1363 hints = *pai;
1364 hints.ai_flags = AI_NUMERICHOST;
1365 error = getaddrinfo(addr, NULL, &hints, &res0);
1366 if (error == 0) {
1367 for (res = res0; res; res = res->ai_next) {
1368 /* cover it up */
1369 res->ai_flags = pai->ai_flags;
1370
1371 (void)get_canonname(pai, res, canonname);
1372 }
1373 } else
1374 res0 = NULL;
1375 if (res0) {
1376 cur->ai_next = res0;
1377 while (cur && cur->ai_next)
1378 cur = cur->ai_next;
1379 }
1380
1381 if (nextline) {
1382 p = nextline;
1383 goto nextline;
1384 }
1385
1386done:
1387 return sentinel.ai_next;
1388}
1389
1390/*ARGSUSED*/
1391static struct addrinfo *
1392_yp_getaddrinfo(const char *name, const struct addrinfo *pai)
1393{
1394 struct addrinfo sentinel, *cur;
1395 struct addrinfo *ai = NULL;
1396 static char *__ypcurrent;
1397 int __ypcurrentlen, r;
1398
1399 memset(&sentinel, 0, sizeof(sentinel));
1400 cur = &sentinel;
1401
1402 if (!__ypdomain) {
1403 if (_yp_check(&__ypdomain) == 0)
1404 return NULL;
1405 }
1406 if (__ypcurrent)
1407 free(__ypcurrent);
1408 __ypcurrent = NULL;
1409
1410 /* hosts.byname is only for IPv4 (Solaris8) */
1411 if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
1412 r = yp_match(__ypdomain, "hosts.byname", name,
1413 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1414 if (r == 0) {
1415 struct addrinfo ai4;
1416
1417 ai4 = *pai;
1418 ai4.ai_family = AF_INET;
1419 ai = _yphostent(__ypcurrent, &ai4);
1420 if (ai) {
1421 cur->ai_next = ai;
1422 while (cur && cur->ai_next)
1423 cur = cur->ai_next;
1424 }
1425 }
1426 }
1427
1428 /* ipnodes.byname can hold both IPv4/v6 */
1429 r = yp_match(__ypdomain, "ipnodes.byname", name,
1430 (int)strlen(name), &__ypcurrent, &__ypcurrentlen);
1431 if (r == 0) {
1432 ai = _yphostent(__ypcurrent, pai);
1433 if (ai) {
1434 cur->ai_next = ai;
1435 while (cur && cur->ai_next)
1436 cur = cur->ai_next;
1437 }
1438 }
1439
1440 return sentinel.ai_next;
1441}
1442#endif
1443
1444
1445/* resolver logic */
1446
1447extern const char *__hostalias(const char *);
1448extern int h_errno;
1449extern int res_opt(int, u_char *, int, int);
1450
1451/*
1452 * Formulate a normal query, send, and await answer.
1453 * Returned answer is placed in supplied buffer "answer".
1454 * Perform preliminary check of answer, returning success only
1455 * if no error is indicated and the answer count is nonzero.
1456 * Return the size of the response on success, -1 on error.
1457 * Error number is left in h_errno.
1458 *
1459 * Caller must parse answer and determine whether it answers the question.
1460 */
1461static int
1462res_queryN(const char *name, struct res_target *target)
1463{
1464 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1465 u_char *buf;
1466 HEADER *hp;
1467 int n;
1468 struct res_target *t;
1469 int rcode;
1470 int ancount;
1471
1472 buf = malloc(MAXPACKET);
1473 if (buf == NULL) {
1474 h_errno = NETDB_INTERNAL;
1475 return (-1);
1476 }
1477
1478 rcode = NOERROR;
1479 ancount = 0;
1480
1481 if (_res_init(0) == -1) {
1482 h_errno = NETDB_INTERNAL;
1483 free(buf);
1484 return (-1);
1485 }
1486
1487 for (t = target; t; t = t->next) {
1488 int class, type;
1489 u_char *answer;
1490 int anslen;
1491
1492 hp = (HEADER *)(void *)t->answer;
1493 hp->rcode = NOERROR; /* default */
1494
1495 /* make it easier... */
1496 class = t->qclass;
1497 type = t->qtype;
1498 answer = t->answer;
1499 anslen = t->anslen;
1500#ifdef DEBUG
1501 if (_resp->options & RES_DEBUG)
1502 printf(";; res_query(%s, %d, %d)\n", name, class, type);
1503#endif
1504
1505 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
1506 buf, MAXPACKET);
1507 if (n > 0 && (_resp->options & RES_USE_EDNS0) != 0)
1508 n = res_opt(n, buf, MAXPACKET, anslen);
1509 if (n <= 0) {
1510#ifdef DEBUG
1511 if (_resp->options & RES_DEBUG)
1512 printf(";; res_query: mkquery failed\n");
1513#endif
1514 h_errno = NO_RECOVERY;
1515 free(buf);
1516 return (n);
1517 }
1518 n = res_send(buf, n, answer, anslen);
1519#if 0
1520 if (n < 0) {
1521#ifdef DEBUG
1522 if (_resp->options & RES_DEBUG)
1523 printf(";; res_query: send error\n");
1524#endif
1525 h_errno = TRY_AGAIN;
1526 free(buf);
1527 return (n);
1528 }
1529#endif
1530
1531 if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
1532 rcode = hp->rcode; /* record most recent error */
1533#ifdef DEBUG
1534 if (_resp->options & RES_DEBUG)
1535 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
1536 ntohs(hp->ancount));
1537#endif
1538 continue;
1539 }
1540
1541 ancount += ntohs(hp->ancount);
1542
1543 t->n = n;
1544 }
1545
1546 if (ancount == 0) {
1547 switch (rcode) {
1548 case NXDOMAIN:
1549 h_errno = HOST_NOT_FOUND;
1550 break;
1551 case SERVFAIL:
1552 h_errno = TRY_AGAIN;
1553 break;
1554 case NOERROR:
1555 h_errno = NO_DATA;
1556 break;
1557 case FORMERR:
1558 case NOTIMP:
1559 case REFUSED:
1560 default:
1561 h_errno = NO_RECOVERY;
1562 break;
1563 }
1564 free(buf);
1565 return (-1);
1566 }
1567 free(buf);
1568 return (ancount);
1569}
1570
1571/*
1572 * Formulate a normal query, send, and retrieve answer in supplied buffer.
1573 * Return the size of the response on success, -1 on error.
1574 * If enabled, implement search rules until answer or unrecoverable failure
1575 * is detected. Error code, if any, is left in h_errno.
1576 */
1577static int
1578res_searchN(const char *name, struct res_target *target)
1579{
1580 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1581 const char *cp, * const *domain;
1582 HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
1583 u_int dots;
1584 int trailing_dot, ret, saved_herrno;
1585 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
1586
1587 if (_res_init(0) == -1) {
1588 h_errno = NETDB_INTERNAL;
1589 return (-1);
1590 }
1591
1592 errno = 0;
1593 h_errno = HOST_NOT_FOUND; /* default, if we never query */
1594 dots = 0;
1595 for (cp = name; *cp; cp++)
1596 dots += (*cp == '.');
1597 trailing_dot = 0;
1598 if (cp > name && *--cp == '.')
1599 trailing_dot++;
1600
1601 /*
1602 * if there aren't any dots, it could be a user-level alias
1603 */
1604 if (!dots && (cp = __hostalias(name)) != NULL)
1605 return (res_queryN(cp, target));
1606
1607 /*
1608 * If there are dots in the name already, let's just give it a try
1609 * 'as is'. The threshold can be set with the "ndots" option.
1610 */
1611 saved_herrno = -1;
1612 if (dots >= _resp->ndots) {
1613 ret = res_querydomainN(name, NULL, target);
1614 if (ret > 0)
1615 return (ret);
1616 saved_herrno = h_errno;
1617 tried_as_is++;
1618 }
1619
1620 /*
1621 * We do at least one level of search if
1622 * - there is no dot and RES_DEFNAME is set, or
1623 * - there is at least one dot, there is no trailing dot,
1624 * and RES_DNSRCH is set.
1625 */
1626 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
1627 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
1628 int done = 0;
1629
1630 for (domain = (const char * const *)_resp->dnsrch;
1631 *domain && !done;
1632 domain++) {
1633
1634 ret = res_querydomainN(name, *domain, target);
1635 if (ret > 0)
1636 return (ret);
1637
1638 /*
1639 * If no server present, give up.
1640 * If name isn't found in this domain,
1641 * keep trying higher domains in the search list
1642 * (if that's enabled).
1643 * On a NO_DATA error, keep trying, otherwise
1644 * a wildcard entry of another type could keep us
1645 * from finding this entry higher in the domain.
1646 * If we get some other error (negative answer or
1647 * server failure), then stop searching up,
1648 * but try the input name below in case it's
1649 * fully-qualified.
1650 */
1651 if (errno == ECONNREFUSED) {
1652 h_errno = TRY_AGAIN;
1653 return (-1);
1654 }
1655
1656 switch (h_errno) {
1657 case NO_DATA:
1658 got_nodata++;
1659 /* FALLTHROUGH */
1660 case HOST_NOT_FOUND:
1661 /* keep trying */
1662 break;
1663 case TRY_AGAIN:
1664 if (hp->rcode == SERVFAIL) {
1665 /* try next search element, if any */
1666 got_servfail++;
1667 break;
1668 }
1669 /* FALLTHROUGH */
1670 default:
1671 /* anything else implies that we're done */
1672 done++;
1673 }
1674 /*
1675 * if we got here for some reason other than DNSRCH,
1676 * we only wanted one iteration of the loop, so stop.
1677 */
1678 if (!(_resp->options & RES_DNSRCH))
1679 done++;
1680 }
1681 }
1682
1683 /*
1684 * if we have not already tried the name "as is", do that now.
1685 * note that we do this regardless of how many dots were in the
1686 * name or whether it ends with a dot.
1687 */
1688 if (!tried_as_is) {
1689 ret = res_querydomainN(name, NULL, target);
1690 if (ret > 0)
1691 return (ret);
1692 }
1693
1694 /*
1695 * if we got here, we didn't satisfy the search.
1696 * if we did an initial full query, return that query's h_errno
1697 * (note that we wouldn't be here if that query had succeeded).
1698 * else if we ever got a nodata, send that back as the reason.
1699 * else send back meaningless h_errno, that being the one from
1700 * the last DNSRCH we did.
1701 */
1702 if (saved_herrno != -1)
1703 h_errno = saved_herrno;
1704 else if (got_nodata)
1705 h_errno = NO_DATA;
1706 else if (got_servfail)
1707 h_errno = TRY_AGAIN;
1708 return (-1);
1709}
1710
1711/*
1712 * Perform a call on res_query on the concatenation of name and domain,
1713 * removing a trailing dot from name if domain is NULL.
1714 */
1715static int
1716res_querydomainN(const char *name, const char *domain,
1717 struct res_target *target)
1718{
1719 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1720 char nbuf[MAXDNAME];
1721 const char *longname = nbuf;
1722 size_t len;
1723
1724 if (_res_init(0) == -1) {
1725 h_errno = NETDB_INTERNAL;
1726 return (-1);
1727 }
1728#ifdef DEBUG
1729 if (_resp->options & RES_DEBUG)
1730 printf(";; res_querydomain(%s, %s)\n",
1731 name, domain?domain:"<Nil>");
1732#endif
1733 if (domain == NULL) {
1734 /*
1735 * Check for trailing '.';
1736 * copy without '.' if present.
1737 */
1738 len = strlcpy(nbuf, name, sizeof(nbuf));
1739 if (len >= sizeof(nbuf)) {
1740 h_errno = NO_RECOVERY;
1741 return (-1);
1742 }
1743 if (len > 0 && nbuf[len - 1] == '.')
1744 nbuf[len - 1] = '\0';
1745 } else {
1746 int i;
1747
1748 i = snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
1749 if (i < 0 || i >= sizeof(nbuf)) {
1750 h_errno = NO_RECOVERY;
1751 return (-1);
1752 }
1753 }
1754 return (res_queryN(longname, target));
1755}
diff --git a/src/lib/libc/net/gethostnamadr.c b/src/lib/libc/net/gethostnamadr.c
deleted file mode 100644
index f4e655eeaf..0000000000
--- a/src/lib/libc/net/gethostnamadr.c
+++ /dev/null
@@ -1,1131 +0,0 @@
1/* $OpenBSD: gethostnamadr.c,v 1.73 2009/11/18 07:43:22 guenther Exp $ */
2/*-
3 * Copyright (c) 1985, 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 * -
30 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies, and that
35 * the name of Digital Equipment Corporation not be used in advertising or
36 * publicity pertaining to distribution of the document or software without
37 * specific, written prior permission.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
40 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
42 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 * SOFTWARE.
47 * -
48 * --Copyright--
49 */
50
51#include <sys/param.h>
52#include <sys/socket.h>
53#include <netinet/in.h>
54#include <arpa/inet.h>
55#include <arpa/nameser.h>
56#include <netdb.h>
57#include <resolv.h>
58#include <stdio.h>
59#include <ctype.h>
60#include <errno.h>
61#include <string.h>
62#include <syslog.h>
63#include <stdlib.h>
64#ifdef YP
65#include <rpc/rpc.h>
66#include <rpcsvc/yp.h>
67#include <rpcsvc/ypclnt.h>
68#include "ypinternal.h"
69#endif
70#include "thread_private.h"
71
72#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
73
74#define MAXALIASES 35
75#define MAXADDRS 35
76
77static char *h_addr_ptrs[MAXADDRS + 1];
78
79#ifdef YP
80static char *__ypdomain;
81#endif
82
83static struct hostent host;
84static char *host_aliases[MAXALIASES];
85static char hostbuf[BUFSIZ+1];
86static union {
87 struct in_addr _host_in_addr;
88 u_char _host_addr[16]; /* IPv4 or IPv6 */
89} _host_addr_u;
90#define host_addr _host_addr_u._host_addr
91static FILE *hostf = NULL;
92static int stayopen = 0;
93
94static void map_v4v6_address(const char *src, char *dst);
95static void map_v4v6_hostent(struct hostent *hp, char **bp, char *);
96
97#ifdef RESOLVSORT
98static void addrsort(char **, int);
99#endif
100
101int _hokchar(const char *);
102
103static const char AskedForGot[] =
104 "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
105
106#define MAXPACKET (64*1024)
107
108typedef union {
109 HEADER hdr;
110 u_char buf[MAXPACKET];
111} querybuf;
112
113typedef union {
114 int32_t al;
115 char ac;
116} align;
117
118static struct hostent *getanswer(const querybuf *, int, const char *, int);
119
120extern int h_errno;
121
122int
123_hokchar(const char *p)
124{
125 char c;
126
127 /*
128 * Many people do not obey RFC 822 and 1035. The valid
129 * characters are a-z, A-Z, 0-9, '-' and . But the others
130 * tested for below can happen, and we must be more permissive
131 * than the resolver until those idiots clean up their act.
132 * We let '/' through, but not '..'
133 */
134 while ((c = *p++)) {
135 if (('a' <= c && c <= 'z') ||
136 ('A' <= c && c <= 'Z') ||
137 ('0' <= c && c <= '9'))
138 continue;
139 if (strchr("-_/", c))
140 continue;
141 if (c == '.' && *p != '.')
142 continue;
143 return 0;
144 }
145 return 1;
146}
147
148static struct hostent *
149getanswer(const querybuf *answer, int anslen, const char *qname, int qtype)
150{
151 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
152 const HEADER *hp;
153 const u_char *cp, *eom;
154 char tbuf[MAXDNAME];
155 char *bp, **ap, **hap, *ep;
156 int type, class, ancount, qdcount, n;
157 int haveanswer, had_error, toobig = 0;
158 const char *tname;
159 int (*name_ok)(const char *);
160
161 tname = qname;
162 host.h_name = NULL;
163 eom = answer->buf + anslen;
164 switch (qtype) {
165 case T_A:
166 case T_AAAA:
167#ifdef USE_RESOLV_NAME_OK
168 name_ok = res_hnok;
169 break;
170#endif
171 case T_PTR:
172#ifdef USE_RESOLV_NAME_OK
173 name_ok = res_dnok;
174#else
175 name_ok = _hokchar;
176#endif
177 break;
178 default:
179 return (NULL);
180 }
181 /*
182 * find first satisfactory answer
183 */
184 hp = &answer->hdr;
185 ancount = ntohs(hp->ancount);
186 qdcount = ntohs(hp->qdcount);
187 bp = hostbuf;
188 ep = hostbuf + sizeof hostbuf;
189 cp = answer->buf + HFIXEDSZ;
190 if (qdcount != 1) {
191 h_errno = NO_RECOVERY;
192 return (NULL);
193 }
194 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
195 if ((n < 0) || !(*name_ok)(bp)) {
196 h_errno = NO_RECOVERY;
197 return (NULL);
198 }
199 cp += n + QFIXEDSZ;
200 if (qtype == T_A || qtype == T_AAAA) {
201 /* res_send() has already verified that the query name is the
202 * same as the one we sent; this just gets the expanded name
203 * (i.e., with the succeeding search-domain tacked on).
204 */
205 host.h_name = bp;
206 bp += strlen(bp) + 1; /* for the \0 */
207 /* The qname can be abbreviated, but h_name is now absolute. */
208 qname = host.h_name;
209 }
210 ap = host_aliases;
211 *ap = NULL;
212 host.h_aliases = host_aliases;
213 hap = h_addr_ptrs;
214 *hap = NULL;
215 host.h_addr_list = h_addr_ptrs;
216 haveanswer = 0;
217 had_error = 0;
218 while (ancount-- > 0 && cp < eom && !had_error) {
219 size_t len;
220
221 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
222 if ((n < 0) || !(*name_ok)(bp)) {
223 had_error++;
224 continue;
225 }
226 cp += n; /* name */
227 if (cp >= eom)
228 break;
229 type = _getshort(cp);
230 cp += INT16SZ; /* type */
231 if (cp >= eom)
232 break;
233 class = _getshort(cp);
234 cp += INT16SZ + INT32SZ; /* class, TTL */
235 if (cp >= eom)
236 break;
237 n = _getshort(cp);
238 cp += INT16SZ; /* len */
239 if (cp >= eom)
240 break;
241 if (type == T_SIG || type == T_RRSIG) {
242 /* XXX - ignore signatures as we don't use them yet */
243 cp += n;
244 continue;
245 }
246 if (class != C_IN) {
247 /* XXX - debug? syslog? */
248 cp += n;
249 continue; /* XXX - had_error++ ? */
250 }
251 if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
252 if (ap >= &host_aliases[MAXALIASES-1])
253 continue;
254 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
255 if ((n < 0) || !(*name_ok)(tbuf)) {
256 had_error++;
257 continue;
258 }
259 cp += n;
260 /* Store alias. */
261 *ap++ = bp;
262 bp += strlen(bp) + 1; /* for the \0 */
263 /* Get canonical name. */
264 len = strlen(tbuf) + 1; /* for the \0 */
265 if (len > ep - bp) {
266 had_error++;
267 continue;
268 }
269 strlcpy(bp, tbuf, ep - bp);
270 host.h_name = bp;
271 bp += len;
272 continue;
273 }
274 if (qtype == T_PTR && type == T_CNAME) {
275 n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
276#ifdef USE_RESOLV_NAME_OK
277 if ((n < 0) || !res_hnok(tbuf)) {
278#else
279 if ((n < 0) || !_hokchar(tbuf)) {
280#endif
281 had_error++;
282 continue;
283 }
284 cp += n;
285 /* Get canonical name. */
286 len = strlen(tbuf) + 1; /* for the \0 */
287 if (len > ep - bp) {
288 had_error++;
289 continue;
290 }
291 strlcpy(bp, tbuf, ep - bp);
292 tname = bp;
293 bp += len;
294 continue;
295 }
296 if (type != qtype) {
297#ifndef NO_LOG_BAD_DNS_RESPONSES
298 syslog(LOG_NOTICE|LOG_AUTH,
299 "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
300 qname, p_class(C_IN), p_type(qtype),
301 p_type(type));
302#endif /* NO_LOG_BAD_DNS_RESPONSES */
303 cp += n;
304 continue; /* XXX - had_error++ ? */
305 }
306 switch (type) {
307 case T_PTR:
308 if (strcasecmp(tname, bp) != 0) {
309 syslog(LOG_NOTICE|LOG_AUTH,
310 AskedForGot, qname, bp);
311 cp += n;
312 continue; /* XXX - had_error++ ? */
313 }
314 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
315#ifdef USE_RESOLV_NAME_OK
316 if ((n < 0) || !res_hnok(bp)) {
317#else
318 if ((n < 0) || !_hokchar(bp)) {
319#endif
320 had_error++;
321 break;
322 }
323#if MULTI_PTRS_ARE_ALIASES
324 cp += n;
325 if (!haveanswer)
326 host.h_name = bp;
327 else if (ap < &host_aliases[MAXALIASES-1])
328 *ap++ = bp;
329 else
330 n = -1;
331 if (n != -1) {
332 n = strlen(bp) + 1; /* for the \0 */
333 bp += n;
334 }
335 break;
336#else
337 host.h_name = bp;
338 if (_resp->options & RES_USE_INET6) {
339 n = strlen(bp) + 1; /* for the \0 */
340 bp += n;
341 map_v4v6_hostent(&host, &bp, ep);
342 }
343 h_errno = NETDB_SUCCESS;
344 return (&host);
345#endif
346 case T_A:
347 case T_AAAA:
348 if (strcasecmp(host.h_name, bp) != 0) {
349 syslog(LOG_NOTICE|LOG_AUTH,
350 AskedForGot, host.h_name, bp);
351 cp += n;
352 continue; /* XXX - had_error++ ? */
353 }
354 if (n != host.h_length) {
355 cp += n;
356 continue;
357 }
358 if (type == T_AAAA) {
359 struct in6_addr in6;
360 memcpy(&in6, cp, IN6ADDRSZ);
361 if (IN6_IS_ADDR_V4MAPPED(&in6)) {
362 cp += n;
363 continue;
364 }
365 }
366 if (!haveanswer) {
367 host.h_name = bp;
368 bp += strlen(bp) + 1; /* for the \0 */
369 }
370
371 bp += sizeof(align) - ((u_long)bp % sizeof(align));
372
373 if (bp + n >= &hostbuf[sizeof hostbuf]) {
374#ifdef DEBUG
375 if (_resp->options & RES_DEBUG)
376 printf("size (%d) too big\n", n);
377#endif
378 had_error++;
379 continue;
380 }
381 if (hap >= &h_addr_ptrs[MAXADDRS-1]) {
382 if (!toobig++)
383#ifdef DEBUG
384 if (_resp->options & RES_DEBUG)
385 printf("Too many addresses (%d)\n", MAXADDRS);
386#endif
387 cp += n;
388 continue;
389 }
390 bcopy(cp, *hap++ = bp, n);
391 bp += n;
392 cp += n;
393 break;
394 }
395 if (!had_error)
396 haveanswer++;
397 }
398 if (haveanswer) {
399 *ap = NULL;
400 *hap = NULL;
401# if defined(RESOLVSORT)
402 /*
403 * Note: we sort even if host can take only one address
404 * in its return structures - should give it the "best"
405 * address in that case, not some random one
406 */
407 if (_resp->nsort && haveanswer > 1 && qtype == T_A)
408 addrsort(h_addr_ptrs, haveanswer);
409# endif /*RESOLVSORT*/
410 if (!host.h_name) {
411 size_t len;
412
413 len = strlen(qname) + 1;
414 if (len > ep - bp) /* for the \0 */
415 goto try_again;
416 strlcpy(bp, qname, ep - bp);
417 host.h_name = bp;
418 bp += len;
419 }
420 if (_resp->options & RES_USE_INET6)
421 map_v4v6_hostent(&host, &bp, ep);
422 h_errno = NETDB_SUCCESS;
423 return (&host);
424 }
425 try_again:
426 h_errno = TRY_AGAIN;
427 return (NULL);
428}
429
430#ifdef notyet
431/*
432 * XXX This is an extremely bogus implementation.
433 *
434 * FreeBSD has this interface:
435 * int gethostbyaddr_r(const char *addr, int len, int type,
436 * struct hostent *result, struct hostent_data *buffer)
437 */
438
439struct hostent *
440gethostbyname_r(const char *name, struct hostent *hp, char *buf, int buflen,
441 int *errorp)
442{
443 struct hostent *res;
444
445 res = gethostbyname(name);
446 *errorp = h_errno;
447 if (res == NULL)
448 return NULL;
449 memcpy(hp, res, sizeof *hp); /* XXX not sufficient */
450 return hp;
451}
452
453/*
454 * XXX This is an extremely bogus implementation.
455 */
456struct hostent *
457gethostbyaddr_r(const char *addr, int len, int af, struct hostent *he,
458 char *buf, int buflen, int *errorp)
459{
460 struct hostent * res;
461
462 res = gethostbyaddr(addr, len, af);
463 *errorp = h_errno;
464 if (res == NULL)
465 return NULL;
466 memcpy(he, res, sizeof *he); /* XXX not sufficient */
467 return he;
468}
469
470/* XXX RFC2133 expects a gethostbyname2_r() -- unimplemented */
471#endif
472
473struct hostent *
474gethostbyname(const char *name)
475{
476 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
477 struct hostent *hp;
478 extern struct hostent *_gethtbyname2(const char *, int);
479
480 if (_res_init(0) == -1)
481 hp = _gethtbyname2(name, AF_INET);
482
483 else if (_resp->options & RES_USE_INET6) {
484 hp = gethostbyname2(name, AF_INET6);
485 if (hp == NULL)
486 hp = gethostbyname2(name, AF_INET);
487 }
488 else
489 hp = gethostbyname2(name, AF_INET);
490 return hp;
491}
492
493struct hostent *
494gethostbyname2(const char *name, int af)
495{
496 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
497 querybuf *buf;
498 const char *cp;
499 char *bp, *ep;
500 int n, size, type, i;
501 struct hostent *hp;
502 char lookups[MAXDNSLUS];
503 extern struct hostent *_gethtbyname2(const char *, int);
504#ifdef YP
505 extern struct hostent *_yp_gethtbyname(const char *);
506#endif
507
508 if (_res_init(0) == -1)
509 return (_gethtbyname2(name, af));
510
511 switch (af) {
512 case AF_INET:
513 size = INADDRSZ;
514 type = T_A;
515 break;
516 case AF_INET6:
517 size = IN6ADDRSZ;
518 type = T_AAAA;
519 break;
520 default:
521 h_errno = NETDB_INTERNAL;
522 errno = EAFNOSUPPORT;
523 return (NULL);
524 }
525
526 host.h_addrtype = af;
527 host.h_length = size;
528
529 /*
530 * if there aren't any dots, it could be a user-level alias.
531 * this is also done in res_query() since we are not the only
532 * function that looks up host names.
533 */
534 if (!strchr(name, '.') && (cp = __hostalias(name)))
535 name = cp;
536
537 /*
538 * disallow names consisting only of digits/dots, unless
539 * they end in a dot.
540 */
541 if (isdigit(name[0]))
542 for (cp = name;; ++cp) {
543 if (!*cp) {
544 if (*--cp == '.')
545 break;
546 /*
547 * All-numeric, no dot at the end.
548 * Fake up a hostent as if we'd actually
549 * done a lookup.
550 */
551 if (inet_pton(af, name, host_addr) <= 0) {
552 h_errno = HOST_NOT_FOUND;
553 return (NULL);
554 }
555 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
556 bp = hostbuf + MAXHOSTNAMELEN;
557 ep = hostbuf + sizeof(hostbuf);
558 host.h_name = hostbuf;
559 host.h_aliases = host_aliases;
560 host_aliases[0] = NULL;
561 h_addr_ptrs[0] = (char *)host_addr;
562 h_addr_ptrs[1] = NULL;
563 host.h_addr_list = h_addr_ptrs;
564 if (_resp->options & RES_USE_INET6)
565 map_v4v6_hostent(&host, &bp, ep);
566 h_errno = NETDB_SUCCESS;
567 return (&host);
568 }
569 if (!isdigit(*cp) && *cp != '.')
570 break;
571 }
572 if ((isxdigit(name[0]) && strchr(name, ':') != NULL) ||
573 name[0] == ':')
574 for (cp = name;; ++cp) {
575 if (!*cp) {
576 if (*--cp == '.')
577 break;
578 /*
579 * All-IPv6-legal, no dot at the end.
580 * Fake up a hostent as if we'd actually
581 * done a lookup.
582 */
583 if (inet_pton(af, name, host_addr) <= 0) {
584 h_errno = HOST_NOT_FOUND;
585 return (NULL);
586 }
587 strlcpy(hostbuf, name, MAXHOSTNAMELEN);
588 bp = hostbuf + MAXHOSTNAMELEN;
589 ep = hostbuf + sizeof(hostbuf);
590 host.h_name = hostbuf;
591 host.h_aliases = host_aliases;
592 host_aliases[0] = NULL;
593 h_addr_ptrs[0] = (char *)host_addr;
594 h_addr_ptrs[1] = NULL;
595 host.h_addr_list = h_addr_ptrs;
596 h_errno = NETDB_SUCCESS;
597 return (&host);
598 }
599 if (!isxdigit(*cp) && *cp != ':' && *cp != '.')
600 break;
601 }
602
603 bcopy(_resp->lookups, lookups, sizeof lookups);
604 if (lookups[0] == '\0')
605 strlcpy(lookups, "bf", sizeof lookups);
606
607 hp = (struct hostent *)NULL;
608 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
609 switch (lookups[i]) {
610#ifdef YP
611 case 'y':
612 /* YP only supports AF_INET. */
613 if (af == AF_INET)
614 hp = _yp_gethtbyname(name);
615 break;
616#endif
617 case 'b':
618 buf = malloc(sizeof(*buf));
619 if (buf == NULL)
620 break;
621 if ((n = res_search(name, C_IN, type, buf->buf,
622 sizeof(buf->buf))) < 0) {
623 free(buf);
624#ifdef DEBUG
625 if (_resp->options & RES_DEBUG)
626 printf("res_search failed\n");
627#endif
628 break;
629 }
630 hp = getanswer(buf, n, name, type);
631 free(buf);
632 break;
633 case 'f':
634 hp = _gethtbyname2(name, af);
635 break;
636 }
637 }
638 /* XXX h_errno not correct in all cases... */
639 return (hp);
640}
641
642struct hostent *
643gethostbyaddr(const void *addr, socklen_t len, int af)
644{
645 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
646 const u_char *uaddr = (const u_char *)addr;
647 int n, size, i;
648 querybuf *buf;
649 struct hostent *hp;
650 char qbuf[MAXDNAME+1], *qp, *ep;
651 char lookups[MAXDNSLUS];
652 struct hostent *res;
653 extern struct hostent *_gethtbyaddr(const void *, socklen_t, int);
654#ifdef YP
655 extern struct hostent *_yp_gethtbyaddr(const void *);
656#endif
657
658 if (_res_init(0) == -1) {
659 res = _gethtbyaddr(addr, len, af);
660 return (res);
661 }
662
663 if (af == AF_INET6 && len == IN6ADDRSZ &&
664 (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)uaddr) ||
665 IN6_IS_ADDR_SITELOCAL((struct in6_addr *)uaddr))) {
666 h_errno = HOST_NOT_FOUND;
667 return (NULL);
668 }
669 if (af == AF_INET6 && len == IN6ADDRSZ &&
670 (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)uaddr) ||
671 IN6_IS_ADDR_V4COMPAT((struct in6_addr *)uaddr))) {
672 /* Unmap. */
673 uaddr += IN6ADDRSZ - INADDRSZ;
674 af = AF_INET;
675 len = INADDRSZ;
676 }
677 switch (af) {
678 case AF_INET:
679 size = INADDRSZ;
680 break;
681 case AF_INET6:
682 size = IN6ADDRSZ;
683 break;
684 default:
685 errno = EAFNOSUPPORT;
686 h_errno = NETDB_INTERNAL;
687 return (NULL);
688 }
689 if (size != len) {
690 errno = EINVAL;
691 h_errno = NETDB_INTERNAL;
692 return (NULL);
693 }
694 ep = qbuf + sizeof(qbuf);
695 switch (af) {
696 case AF_INET:
697 (void) snprintf(qbuf, sizeof qbuf, "%u.%u.%u.%u.in-addr.arpa",
698 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
699 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
700 break;
701 case AF_INET6:
702 qp = qbuf;
703 for (n = IN6ADDRSZ - 1; n >= 0; n--) {
704 i = snprintf(qp, ep - qp, "%x.%x.",
705 uaddr[n] & 0xf, (uaddr[n] >> 4) & 0xf);
706 if (i <= 0 || i >= ep - qp) {
707 errno = EINVAL;
708 h_errno = NETDB_INTERNAL;
709 return (NULL);
710 }
711 qp += i;
712 }
713 strlcpy(qp, "ip6.arpa", ep - qp);
714 break;
715 }
716
717 bcopy(_resp->lookups, lookups, sizeof lookups);
718 if (lookups[0] == '\0')
719 strlcpy(lookups, "bf", sizeof lookups);
720
721 hp = (struct hostent *)NULL;
722 for (i = 0; i < MAXDNSLUS && hp == NULL && lookups[i]; i++) {
723 switch (lookups[i]) {
724#ifdef YP
725 case 'y':
726 /* YP only supports AF_INET. */
727 if (af == AF_INET)
728 hp = _yp_gethtbyaddr(uaddr);
729 break;
730#endif
731 case 'b':
732 buf = malloc(sizeof(*buf));
733 if (!buf)
734 break;
735 n = res_query(qbuf, C_IN, T_PTR, buf->buf,
736 sizeof(buf->buf));
737 if (n < 0) {
738 free(buf);
739#ifdef DEBUG
740 if (_resp->options & RES_DEBUG)
741 printf("res_query failed\n");
742#endif
743 break;
744 }
745 if (!(hp = getanswer(buf, n, qbuf, T_PTR))) {
746 free(buf);
747 break;
748 }
749 free(buf);
750 hp->h_addrtype = af;
751 hp->h_length = len;
752 bcopy(uaddr, host_addr, len);
753 h_addr_ptrs[0] = (char *)host_addr;
754 h_addr_ptrs[1] = NULL;
755 if (af == AF_INET && (_resp->options & RES_USE_INET6)) {
756 map_v4v6_address((char*)host_addr,
757 (char*)host_addr);
758 hp->h_addrtype = AF_INET6;
759 hp->h_length = IN6ADDRSZ;
760 }
761 h_errno = NETDB_SUCCESS;
762 break;
763 case 'f':
764 hp = _gethtbyaddr(uaddr, len, af);
765 break;
766 }
767 }
768 /* XXX h_errno not correct in all cases... */
769 return (hp);
770}
771
772void
773_sethtent(int f)
774{
775 if (hostf == NULL)
776 hostf = fopen(_PATH_HOSTS, "r" );
777 else
778 rewind(hostf);
779 stayopen = f;
780}
781
782void
783_endhtent(void)
784{
785 if (hostf && !stayopen) {
786 (void) fclose(hostf);
787 hostf = NULL;
788 }
789}
790
791static struct hostent *
792_gethtent(void)
793{
794 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
795 char *p, *cp, **q;
796 int af;
797 size_t len;
798
799 if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) {
800 h_errno = NETDB_INTERNAL;
801 return (NULL);
802 }
803 again:
804 if ((p = fgetln(hostf, &len)) == NULL) {
805 h_errno = HOST_NOT_FOUND;
806 return (NULL);
807 }
808 if (p[len-1] == '\n')
809 len--;
810 if (len >= sizeof(hostbuf) || len == 0)
811 goto again;
812 p = memcpy(hostbuf, p, len);
813 hostbuf[len] = '\0';
814 if (*p == '#')
815 goto again;
816 if ((cp = strchr(p, '#')))
817 *cp = '\0';
818 if (!(cp = strpbrk(p, " \t")))
819 goto again;
820 *cp++ = '\0';
821 if (inet_pton(AF_INET6, p, host_addr) > 0) {
822 af = AF_INET6;
823 len = IN6ADDRSZ;
824 } else if (inet_pton(AF_INET, p, host_addr) > 0) {
825 if (_resp->options & RES_USE_INET6) {
826 map_v4v6_address((char*)host_addr, (char*)host_addr);
827 af = AF_INET6;
828 len = IN6ADDRSZ;
829 } else {
830 af = AF_INET;
831 len = INADDRSZ;
832 }
833 } else {
834 goto again;
835 }
836 /* if this is not something we're looking for, skip it. */
837 if (host.h_addrtype != AF_UNSPEC && host.h_addrtype != af)
838 goto again;
839 if (host.h_length != 0 && host.h_length != len)
840 goto again;
841 h_addr_ptrs[0] = (char *)host_addr;
842 h_addr_ptrs[1] = NULL;
843 host.h_addr_list = h_addr_ptrs;
844 host.h_length = len;
845 host.h_addrtype = af;
846 while (*cp == ' ' || *cp == '\t')
847 cp++;
848 host.h_name = cp;
849 q = host.h_aliases = host_aliases;
850 if ((cp = strpbrk(cp, " \t")))
851 *cp++ = '\0';
852 while (cp && *cp) {
853 if (*cp == ' ' || *cp == '\t') {
854 cp++;
855 continue;
856 }
857 if (q < &host_aliases[MAXALIASES - 1])
858 *q++ = cp;
859 if ((cp = strpbrk(cp, " \t")))
860 *cp++ = '\0';
861 }
862 *q = NULL;
863 if (_resp->options & RES_USE_INET6) {
864 char *bp = hostbuf;
865 char *ep = hostbuf + sizeof hostbuf;
866
867 map_v4v6_hostent(&host, &bp, ep);
868 }
869 h_errno = NETDB_SUCCESS;
870 return (&host);
871}
872
873struct hostent *
874_gethtbyname2(const char *name, int af)
875{
876 struct hostent *p;
877 char **cp;
878
879 _sethtent(0);
880 while ((p = _gethtent())) {
881 if (p->h_addrtype != af)
882 continue;
883 if (strcasecmp(p->h_name, name) == 0)
884 break;
885 for (cp = p->h_aliases; *cp != 0; cp++)
886 if (strcasecmp(*cp, name) == 0)
887 goto found;
888 }
889 found:
890 _endhtent();
891 return (p);
892}
893
894struct hostent *
895_gethtbyaddr(const void *addr, socklen_t len, int af)
896{
897 struct hostent *p;
898
899 host.h_length = len;
900 host.h_addrtype = af;
901
902 _sethtent(0);
903 while ((p = _gethtent()))
904 if (p->h_addrtype == af && p->h_length == len &&
905 !bcmp(p->h_addr, addr, len))
906 break;
907 _endhtent();
908 return (p);
909}
910
911#ifdef YP
912struct hostent *
913_yphostent(char *line)
914{
915 static struct in_addr host_addrs[MAXADDRS];
916 char *p = line;
917 char *cp, **q;
918 char **hap;
919 struct in_addr *buf;
920 int more;
921
922 host.h_name = NULL;
923 host.h_addr_list = h_addr_ptrs;
924 host.h_length = INADDRSZ;
925 host.h_addrtype = AF_INET;
926 hap = h_addr_ptrs;
927 buf = host_addrs;
928 q = host.h_aliases = host_aliases;
929
930nextline:
931 /* check for host_addrs overflow */
932 if (buf >= &host_addrs[sizeof(host_addrs) / sizeof(host_addrs[0])])
933 goto done;
934
935 more = 0;
936 cp = strpbrk(p, " \t");
937 if (cp == NULL)
938 goto done;
939 *cp++ = '\0';
940
941 *hap++ = (char *)buf;
942 (void) inet_aton(p, buf++);
943
944 while (*cp == ' ' || *cp == '\t')
945 cp++;
946 p = cp;
947 cp = strpbrk(p, " \t\n");
948 if (cp != NULL) {
949 if (*cp == '\n')
950 more = 1;
951 *cp++ = '\0';
952 }
953 if (!host.h_name)
954 host.h_name = p;
955 else if (strcmp(host.h_name, p)==0)
956 ;
957 else if (q < &host_aliases[MAXALIASES - 1])
958 *q++ = p;
959 p = cp;
960 if (more)
961 goto nextline;
962
963 while (cp && *cp) {
964 if (*cp == ' ' || *cp == '\t') {
965 cp++;
966 continue;
967 }
968 if (*cp == '\n') {
969 cp++;
970 goto nextline;
971 }
972 if (q < &host_aliases[MAXALIASES - 1])
973 *q++ = cp;
974 cp = strpbrk(cp, " \t");
975 if (cp != NULL)
976 *cp++ = '\0';
977 }
978done:
979 if (host.h_name == NULL)
980 return (NULL);
981 *q = NULL;
982 *hap = NULL;
983 return (&host);
984}
985
986struct hostent *
987_yp_gethtbyaddr(const void *addr)
988{
989 struct hostent *hp = NULL;
990 const u_char *uaddr = (const u_char *)addr;
991 static char *__ypcurrent;
992 int __ypcurrentlen, r;
993 char name[sizeof("xxx.xxx.xxx.xxx")];
994
995 if (!__ypdomain) {
996 if (_yp_check(&__ypdomain) == 0)
997 return (hp);
998 }
999 snprintf(name, sizeof name, "%u.%u.%u.%u", (uaddr[0] & 0xff),
1000 (uaddr[1] & 0xff), (uaddr[2] & 0xff), (uaddr[3] & 0xff));
1001 if (__ypcurrent)
1002 free(__ypcurrent);
1003 __ypcurrent = NULL;
1004 r = yp_match(__ypdomain, "hosts.byaddr", name,
1005 strlen(name), &__ypcurrent, &__ypcurrentlen);
1006 if (r==0)
1007 hp = _yphostent(__ypcurrent);
1008 if (hp==NULL)
1009 h_errno = HOST_NOT_FOUND;
1010 return (hp);
1011}
1012
1013struct hostent *
1014_yp_gethtbyname(const char *name)
1015{
1016 struct hostent *hp = (struct hostent *)NULL;
1017 static char *__ypcurrent;
1018 int __ypcurrentlen, r;
1019
1020 if (strlen(name) >= MAXHOSTNAMELEN)
1021 return (NULL);
1022 if (!__ypdomain) {
1023 if (_yp_check(&__ypdomain) == 0)
1024 return (hp);
1025 }
1026 if (__ypcurrent)
1027 free(__ypcurrent);
1028 __ypcurrent = NULL;
1029 r = yp_match(__ypdomain, "hosts.byname", name,
1030 strlen(name), &__ypcurrent, &__ypcurrentlen);
1031 if (r == 0)
1032 hp = _yphostent(__ypcurrent);
1033 if (hp == NULL)
1034 h_errno = HOST_NOT_FOUND;
1035 return (hp);
1036}
1037#endif
1038
1039static void
1040map_v4v6_address(const char *src, char *dst)
1041{
1042 u_char *p = (u_char *)dst;
1043 char tmp[INADDRSZ];
1044 int i;
1045
1046 /* Stash a temporary copy so our caller can update in place. */
1047 bcopy(src, tmp, INADDRSZ);
1048 /* Mark this ipv6 addr as a mapped ipv4. */
1049 for (i = 0; i < 10; i++)
1050 *p++ = 0x00;
1051 *p++ = 0xff;
1052 *p++ = 0xff;
1053 /* Retrieve the saved copy and we're done. */
1054 bcopy(tmp, (void*)p, INADDRSZ);
1055}
1056
1057static void
1058map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep)
1059{
1060 char **ap;
1061
1062 if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
1063 return;
1064 hp->h_addrtype = AF_INET6;
1065 hp->h_length = IN6ADDRSZ;
1066 for (ap = hp->h_addr_list; *ap; ap++) {
1067 int i = sizeof(align) - ((u_long)*bpp % sizeof(align));
1068
1069 if (ep - *bpp < (i + IN6ADDRSZ)) {
1070 /* Out of memory. Truncate address list here. XXX */
1071 *ap = NULL;
1072 return;
1073 }
1074 *bpp += i;
1075 map_v4v6_address(*ap, *bpp);
1076 *ap = *bpp;
1077 *bpp += IN6ADDRSZ;
1078 }
1079}
1080
1081struct hostent *
1082gethostent(void)
1083{
1084 host.h_addrtype = AF_UNSPEC;
1085 host.h_length = 0;
1086 return (_gethtent());
1087}
1088
1089#ifdef RESOLVSORT
1090static void
1091addrsort(char **ap, int num)
1092{
1093 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
1094 int i, j;
1095 char **p;
1096 short aval[MAXADDRS];
1097 int needsort = 0;
1098
1099 p = ap;
1100 for (i = 0; i < num; i++, p++) {
1101 for (j = 0 ; (unsigned)j < _resp->nsort; j++)
1102 if (_resp->sort_list[j].addr.s_addr ==
1103 (((struct in_addr *)(*p))->s_addr &
1104 _resp->sort_list[j].mask))
1105 break;
1106 aval[i] = j;
1107 if (needsort == 0 && i > 0 && j < aval[i-1])
1108 needsort = i;
1109 }
1110 if (!needsort)
1111 return;
1112
1113 while (needsort < num) {
1114 for (j = needsort - 1; j >= 0; j--) {
1115 if (aval[j] > aval[j+1]) {
1116 char *hp;
1117
1118 i = aval[j];
1119 aval[j] = aval[j+1];
1120 aval[j+1] = i;
1121
1122 hp = ap[j];
1123 ap[j] = ap[j+1];
1124 ap[j+1] = hp;
1125 } else
1126 break;
1127 }
1128 needsort++;
1129 }
1130}
1131#endif
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c
deleted file mode 100644
index 7041a4ee48..0000000000
--- a/src/lib/libc/net/getnameinfo.c
+++ /dev/null
@@ -1,351 +0,0 @@
1/* $OpenBSD: getnameinfo.c,v 1.33 2007/02/15 04:25:35 ray Exp $ */
2/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */
3
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Issues to be discussed:
35 * - Thread safe-ness must be checked
36 * - RFC2553 says that we should raise error on short buffer. X/Open says
37 * we need to truncate the result. We obey RFC2553 (and X/Open should be
38 * modified). ipngwg rough consensus seems to follow RFC2553.
39 * - What is "local" in NI_FQDN?
40 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
41 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
42 * sin6_scope_id is filled - standardization status?
43 * XXX breaks backward compat for code that expects no scopeid.
44 * beware on merge.
45 */
46
47#ifndef INET6
48#define INET6
49#endif
50
51#include <sys/types.h>
52#include <sys/socket.h>
53#include <net/if.h>
54#include <netinet/in.h>
55#include <arpa/inet.h>
56#include <arpa/nameser.h>
57#include <netdb.h>
58#include <resolv.h>
59#include <string.h>
60#include <stddef.h>
61
62#include "thread_private.h"
63
64static const struct afd {
65 int a_af;
66 int a_addrlen;
67 int a_socklen;
68 int a_off;
69} afdl [] = {
70#ifdef INET6
71 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
72 offsetof(struct sockaddr_in6, sin6_addr)},
73#endif
74 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
75 offsetof(struct sockaddr_in, sin_addr)},
76 {0, 0, 0},
77};
78
79struct sockinet {
80 u_char si_len;
81 u_char si_family;
82 u_short si_port;
83};
84
85#ifdef INET6
86static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
87 size_t, int);
88static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
89#endif
90
91void *__THREAD_NAME(serv_mutex);
92
93int
94getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host,
95 size_t hostlen, char *serv, size_t servlen, int flags)
96{
97 const struct afd *afd;
98 struct hostent *hp;
99 u_short port;
100 int family, i;
101 const char *addr;
102 u_int32_t v4a;
103 char numserv[512];
104 char numaddr[512];
105
106 if (sa == NULL)
107 return EAI_FAIL;
108
109 family = sa->sa_family;
110 for (i = 0; afdl[i].a_af; i++)
111 if (afdl[i].a_af == family) {
112 afd = &afdl[i];
113 goto found;
114 }
115 return EAI_FAMILY;
116
117 found:
118 if (salen != afd->a_socklen)
119 return EAI_FAIL;
120
121 /* network byte order */
122 port = ((const struct sockinet *)sa)->si_port;
123 addr = (const char *)sa + afd->a_off;
124
125 if (serv == NULL || servlen == 0) {
126 /*
127 * do nothing in this case.
128 * in case you are wondering if "&&" is more correct than
129 * "||" here: rfc2553bis-03 says that serv == NULL OR
130 * servlen == 0 means that the caller does not want the result.
131 */
132 } else if (!(flags & NI_NUMERICSERV)) {
133 struct servent sp;
134 struct servent_data sd;
135
136 (void)memset(&sd, 0, sizeof(sd));
137 if (getservbyport_r(port,
138 (flags & NI_DGRAM) ? "udp" : "tcp", &sp, &sd) == -1)
139 goto numeric;
140
141 if (strlen(sp.s_name) + 1 > servlen) {
142 endservent_r(&sd);
143 return EAI_MEMORY;
144 }
145 strlcpy(serv, sp.s_name, servlen);
146 endservent_r(&sd);
147 } else {
148 numeric:
149 i = snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
150 if (i < 0 || i >= servlen || i >= sizeof(numserv))
151 return EAI_MEMORY;
152 strlcpy(serv, numserv, servlen);
153 }
154
155 switch (sa->sa_family) {
156 case AF_INET:
157 v4a = (u_int32_t)
158 ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
159 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
160 flags |= NI_NUMERICHOST;
161 v4a >>= IN_CLASSA_NSHIFT;
162 if (v4a == 0)
163 flags |= NI_NUMERICHOST;
164 break;
165#ifdef INET6
166 case AF_INET6:
167 {
168 const struct sockaddr_in6 *sin6;
169 sin6 = (const struct sockaddr_in6 *)sa;
170 switch (sin6->sin6_addr.s6_addr[0]) {
171 case 0x00:
172 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
173 ;
174 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
175 ;
176 else
177 flags |= NI_NUMERICHOST;
178 break;
179 default:
180 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
181 flags |= NI_NUMERICHOST;
182 }
183 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
184 flags |= NI_NUMERICHOST;
185 break;
186 }
187 }
188 break;
189#endif
190 }
191 if (host == NULL || hostlen == 0) {
192 /*
193 * do nothing in this case.
194 * in case you are wondering if "&&" is more correct than
195 * "||" here: rfc2553bis-03 says that host == NULL or
196 * hostlen == 0 means that the caller does not want the result.
197 */
198 } else if (flags & NI_NUMERICHOST) {
199 int numaddrlen;
200
201 /* NUMERICHOST and NAMEREQD conflicts with each other */
202 if (flags & NI_NAMEREQD)
203 return EAI_NONAME;
204
205 switch(afd->a_af) {
206#ifdef INET6
207 case AF_INET6:
208 {
209 int error;
210
211 if ((error = ip6_parsenumeric(sa, addr, host,
212 hostlen, flags)) != 0)
213 return(error);
214 break;
215 }
216#endif
217 default:
218 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
219 == NULL)
220 return EAI_SYSTEM;
221 numaddrlen = strlen(numaddr);
222 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
223 return EAI_MEMORY;
224 strlcpy(host, numaddr, hostlen);
225 break;
226 }
227 } else {
228 _THREAD_PRIVATE_MUTEX_LOCK(serv_mutex);
229 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
230 _THREAD_PRIVATE_MUTEX_UNLOCK(serv_mutex);
231
232 if (hp) {
233#if 0
234 /*
235 * commented out, since "for local host" is not
236 * implemented here - see RFC2553 p30
237 */
238 if (flags & NI_NOFQDN) {
239 char *p;
240 p = strchr(hp->h_name, '.');
241 if (p)
242 *p = '\0';
243 }
244#endif
245 if (strlen(hp->h_name) + 1 > hostlen) {
246 return EAI_MEMORY;
247 }
248 strlcpy(host, hp->h_name, hostlen);
249 } else {
250 if (flags & NI_NAMEREQD)
251 return EAI_NONAME;
252 switch(afd->a_af) {
253#ifdef INET6
254 case AF_INET6:
255 {
256 int error;
257
258 if ((error = ip6_parsenumeric(sa, addr, host,
259 hostlen,
260 flags)) != 0)
261 return(error);
262 break;
263 }
264#endif
265 default:
266 if (inet_ntop(afd->a_af, addr, host,
267 hostlen) == NULL)
268 return EAI_SYSTEM;
269 break;
270 }
271 }
272 }
273 return(0);
274}
275
276#ifdef INET6
277static int
278ip6_parsenumeric(const struct sockaddr *sa, const char *addr, char *host,
279 size_t hostlen, int flags)
280{
281 int numaddrlen;
282 char numaddr[512];
283
284 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
285 return EAI_SYSTEM;
286
287 numaddrlen = strlen(numaddr);
288 if (numaddrlen + 1 > hostlen) /* don't forget terminator */
289 return EAI_MEMORY;
290 strlcpy(host, numaddr, hostlen);
291
292 if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
293 char zonebuf[MAXHOSTNAMELEN];
294 int zonelen;
295
296 zonelen = ip6_sa2str(
297 (const struct sockaddr_in6 *)(const void *)sa,
298 zonebuf, sizeof(zonebuf), flags);
299 if (zonelen < 0)
300 return EAI_MEMORY;
301 if (zonelen + 1 + numaddrlen + 1 > hostlen)
302 return EAI_MEMORY;
303
304 /* construct <numeric-addr><delim><zoneid> */
305 memcpy(host + numaddrlen + 1, zonebuf,
306 (size_t)zonelen);
307 host[numaddrlen] = SCOPE_DELIMITER;
308 host[numaddrlen + 1 + zonelen] = '\0';
309 }
310
311 return 0;
312}
313
314/* ARGSUSED */
315static int
316ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
317{
318 unsigned int ifindex;
319 const struct in6_addr *a6;
320 int n;
321
322 ifindex = (unsigned int)sa6->sin6_scope_id;
323 a6 = &sa6->sin6_addr;
324
325#ifdef notdef
326 if ((flags & NI_NUMERICSCOPE) != 0) {
327 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
328 if (n < 0 || n >= bufsiz)
329 return -1;
330 else
331 return n;
332 }
333#endif
334
335 /* if_indextoname() does not take buffer size. not a good api... */
336 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
337 IN6_IS_ADDR_MC_INTFACELOCAL(a6)) && bufsiz >= IF_NAMESIZE) {
338 char *p = if_indextoname(ifindex, buf);
339 if (p) {
340 return(strlen(p));
341 }
342 }
343
344 /* last resort */
345 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
346 if (n < 0 || n >= bufsiz)
347 return -1;
348 else
349 return n;
350}
351#endif /* INET6 */
diff --git a/src/lib/libc/net/getnetnamadr.c b/src/lib/libc/net/getnetnamadr.c
deleted file mode 100644
index 7b770f1ce7..0000000000
--- a/src/lib/libc/net/getnetnamadr.c
+++ /dev/null
@@ -1,384 +0,0 @@
1/* $OpenBSD: getnetnamadr.c,v 1.26 2005/08/06 20:30:03 espie Exp $ */
2
3/*
4 * Copyright (c) 1997, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
28 * Dep. Matematica Universidade de Coimbra, Portugal, Europe
29 *
30 * Permission to use, copy, modify, and distribute this software for any
31 * purpose with or without fee is hereby granted, provided that the above
32 * copyright notice and this permission notice appear in all copies.
33 */
34/*
35 * Copyright (c) 1983, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. Neither the name of the University nor the names of its contributors
47 * may be used to endorse or promote products derived from this software
48 * without specific prior written permission.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60 * SUCH DAMAGE.
61 */
62
63#include <sys/types.h>
64#include <sys/param.h>
65#include <sys/socket.h>
66#include <netinet/in.h>
67#include <arpa/inet.h>
68#include <arpa/nameser.h>
69
70#include <stdio.h>
71#include <netdb.h>
72#include <resolv.h>
73#include <ctype.h>
74#include <errno.h>
75#include <string.h>
76#include <stdlib.h>
77
78#include "thread_private.h"
79
80extern int h_errno;
81
82struct netent *_getnetbyaddr(in_addr_t net, int type);
83struct netent *_getnetbyname(const char *name);
84
85int _hokchar(const char *);
86
87#define BYADDR 0
88#define BYNAME 1
89#define MAXALIASES 35
90
91#define MAXPACKET (64*1024)
92
93typedef union {
94 HEADER hdr;
95 u_char buf[MAXPACKET];
96} querybuf;
97
98typedef union {
99 long al;
100 char ac;
101} align;
102
103static struct netent *
104getnetanswer(querybuf *answer, int anslen, int net_i)
105{
106
107 HEADER *hp;
108 u_char *cp;
109 int n;
110 u_char *eom;
111 int type, class, ancount, qdcount, haveanswer, i, nchar;
112 char aux1[MAXHOSTNAMELEN], aux2[MAXHOSTNAMELEN], ans[MAXHOSTNAMELEN];
113 char *in, *st, *pauxt, *bp, **ap, *ep;
114 char *paux1 = &aux1[0], *paux2 = &aux2[0];
115 static struct netent net_entry;
116 static char *net_aliases[MAXALIASES], netbuf[BUFSIZ+1];
117
118 /*
119 * find first satisfactory answer
120 *
121 * answer --> +------------+ ( MESSAGE )
122 * | Header |
123 * +------------+
124 * | Question | the question for the name server
125 * +------------+
126 * | Answer | RRs answering the question
127 * +------------+
128 * | Authority | RRs pointing toward an authority
129 * | Additional | RRs holding additional information
130 * +------------+
131 */
132 eom = answer->buf + anslen;
133 hp = &answer->hdr;
134 ancount = ntohs(hp->ancount); /* #/records in the answer section */
135 qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
136 bp = netbuf;
137 ep = netbuf + sizeof(netbuf);
138 cp = answer->buf + HFIXEDSZ;
139 if (!qdcount) {
140 if (hp->aa)
141 h_errno = HOST_NOT_FOUND;
142 else
143 h_errno = TRY_AGAIN;
144 return (NULL);
145 }
146 while (qdcount-- > 0) {
147 n = __dn_skipname(cp, eom);
148 if (n < 0 || (cp + n + QFIXEDSZ) > eom) {
149 h_errno = NO_RECOVERY;
150 return(NULL);
151 }
152 cp += n + QFIXEDSZ;
153 }
154 ap = net_aliases;
155 *ap = NULL;
156 net_entry.n_aliases = net_aliases;
157 haveanswer = 0;
158 while (--ancount >= 0 && cp < eom) {
159 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
160#ifdef USE_RESOLV_NAME_OK
161 if ((n < 0) || !res_dnok(bp))
162#else
163 if ((n < 0) || !_hokchar(bp))
164#endif
165 break;
166 cp += n;
167 ans[0] = '\0';
168 strlcpy(&ans[0], bp, sizeof ans);
169 GETSHORT(type, cp);
170 GETSHORT(class, cp);
171 cp += INT32SZ; /* TTL */
172 GETSHORT(n, cp);
173 if (class == C_IN && type == T_PTR) {
174 n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
175#ifdef USE_RESOLV_NAME_OK
176 if ((n < 0) || !res_hnok(bp))
177#else
178 if ((n < 0) || !_hokchar(bp))
179#endif
180 {
181 cp += n;
182 return (NULL);
183 }
184 cp += n;
185 if ((ap + 2) < &net_aliases[MAXALIASES]) {
186 *ap++ = bp;
187 bp += strlen(bp) + 1;
188 net_entry.n_addrtype =
189 (class == C_IN) ? AF_INET : AF_UNSPEC;
190 haveanswer++;
191 }
192 }
193 }
194 if (haveanswer) {
195 *ap = NULL;
196 switch (net_i) {
197 case BYADDR:
198 net_entry.n_name = *net_entry.n_aliases;
199 net_entry.n_net = 0L;
200 break;
201 case BYNAME:
202 ap = net_entry.n_aliases;
203 next_alias:
204 in = *ap++;
205 if (in == NULL) {
206 h_errno = HOST_NOT_FOUND;
207 return (NULL);
208 }
209 net_entry.n_name = ans;
210 aux2[0] = '\0';
211 for (i = 0; i < 4; i++) {
212 for (st = in, nchar = 0;
213 isdigit((unsigned char)*st);
214 st++, nchar++)
215 ;
216 if (*st != '.' || nchar == 0 || nchar > 3)
217 goto next_alias;
218 if (i != 0)
219 nchar++;
220 strlcpy(paux1, in, nchar+1);
221 strlcat(paux1, paux2, MAXHOSTNAMELEN);
222 pauxt = paux2;
223 paux2 = paux1;
224 paux1 = pauxt;
225 in = ++st;
226 }
227 if (strcasecmp(in, "IN-ADDR.ARPA") != 0)
228 goto next_alias;
229 net_entry.n_net = inet_network(paux2);
230 break;
231 }
232 net_entry.n_aliases++;
233 return (&net_entry);
234 }
235 h_errno = TRY_AGAIN;
236 return (NULL);
237}
238
239struct netent *
240getnetbyaddr(in_addr_t net, int net_type)
241{
242 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
243 unsigned int netbr[4];
244 int nn, anslen;
245 querybuf *buf;
246 char qbuf[MAXDNAME];
247 in_addr_t net2;
248 struct netent *net_entry = NULL;
249 char lookups[MAXDNSLUS];
250 int i;
251
252 if (_res_init(0) == -1)
253 return(_getnetbyaddr(net, net_type));
254
255 bcopy(_resp->lookups, lookups, sizeof lookups);
256 if (lookups[0] == '\0')
257 strlcpy(lookups, "bf", sizeof lookups);
258
259 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
260 switch (lookups[i]) {
261#ifdef YP
262 case 'y':
263 /* There is no YP support. */
264 break;
265#endif /* YP */
266 case 'b':
267 if (net_type != AF_INET)
268 break; /* DNS only supports AF_INET? */
269
270 for (nn = 4, net2 = net; net2; net2 >>= 8)
271 netbr[--nn] = net2 & 0xff;
272 switch (nn) {
273 case 3: /* Class A */
274 snprintf(qbuf, sizeof(qbuf),
275 "0.0.0.%u.in-addr.arpa", netbr[3]);
276 break;
277 case 2: /* Class B */
278 snprintf(qbuf, sizeof(qbuf),
279 "0.0.%u.%u.in-addr.arpa",
280 netbr[3], netbr[2]);
281 break;
282 case 1: /* Class C */
283 snprintf(qbuf, sizeof(qbuf),
284 "0.%u.%u.%u.in-addr.arpa",
285 netbr[3], netbr[2], netbr[1]);
286 break;
287 case 0: /* Class D - E */
288 snprintf(qbuf, sizeof(qbuf),
289 "%u.%u.%u.%u.in-addr.arpa",
290 netbr[3], netbr[2], netbr[1], netbr[0]);
291 break;
292 }
293 buf = malloc(sizeof(*buf));
294 if (buf == NULL)
295 break;
296 anslen = res_query(qbuf, C_IN, T_PTR, buf->buf,
297 sizeof(buf->buf));
298 if (anslen < 0) {
299 free(buf);
300#ifdef DEBUG
301 if (_resp->options & RES_DEBUG)
302 printf("res_query failed\n");
303#endif
304 break;
305 }
306 net_entry = getnetanswer(buf, anslen, BYADDR);
307 free(buf);
308 if (net_entry != NULL) {
309 unsigned u_net = net; /* maybe net should be unsigned ? */
310
311 /* Strip trailing zeros */
312 while ((u_net & 0xff) == 0 && u_net != 0)
313 u_net >>= 8;
314 net_entry->n_net = u_net;
315 return (net_entry);
316 }
317 break;
318 case 'f':
319 net_entry = _getnetbyaddr(net, net_type);
320 if (net_entry != NULL)
321 return (net_entry);
322 }
323 }
324
325 /* Nothing matched. */
326 return (NULL);
327}
328
329struct netent *
330getnetbyname(const char *net)
331{
332 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
333 int anslen;
334 querybuf *buf;
335 char qbuf[MAXDNAME];
336 struct netent *net_entry = NULL;
337 char lookups[MAXDNSLUS];
338 int i;
339
340 if (_res_init(0) == -1)
341 return (_getnetbyname(net));
342
343 bcopy(_resp->lookups, lookups, sizeof lookups);
344 if (lookups[0] == '\0')
345 strlcpy(lookups, "bf", sizeof lookups);
346
347 for (i = 0; i < MAXDNSLUS && lookups[i]; i++) {
348 switch (lookups[i]) {
349#ifdef YP
350 case 'y':
351 /* There is no YP support. */
352 break;
353#endif /* YP */
354 case 'b':
355 strlcpy(qbuf, net, sizeof qbuf);
356 buf = malloc(sizeof(*buf));
357 if (buf == NULL)
358 break;
359 anslen = res_search(qbuf, C_IN, T_PTR, buf->buf,
360 sizeof(buf->buf));
361 if (anslen < 0) {
362 free(buf);
363#ifdef DEBUG
364 if (_resp->options & RES_DEBUG)
365 printf("res_query failed\n");
366#endif
367 break;
368 }
369 net_entry = getnetanswer(buf, anslen, BYNAME);
370 free(buf);
371 if (net_entry != NULL)
372 return (net_entry);
373 break;
374 case 'f':
375 net_entry = _getnetbyname(net);
376 if (net_entry != NULL)
377 return (net_entry);
378 break;
379 }
380 }
381
382 /* Nothing matched. */
383 return (NULL);
384}
diff --git a/src/lib/libc/net/getrrsetbyname.c b/src/lib/libc/net/getrrsetbyname.c
deleted file mode 100644
index 2bbb6ccf83..0000000000
--- a/src/lib/libc/net/getrrsetbyname.c
+++ /dev/null
@@ -1,517 +0,0 @@
1/* $OpenBSD: getrrsetbyname.c,v 1.12 2010/06/29 09:22:06 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2001 Jakob Schlyter. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Portions Copyright (c) 1999-2001 Internet Software Consortium.
31 *
32 * Permission to use, copy, modify, and distribute this software for any
33 * purpose with or without fee is hereby granted, provided that the above
34 * copyright notice and this permission notice appear in all copies.
35 *
36 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
37 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
39 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
40 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
41 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
42 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
43 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 */
45
46#include <sys/types.h>
47#include <netinet/in.h>
48#include <arpa/nameser.h>
49#include <netdb.h>
50#include <resolv.h>
51#include <stdlib.h>
52#include <string.h>
53
54#include "thread_private.h"
55
56#define MAXPACKET 1024*64
57
58struct dns_query {
59 char *name;
60 u_int16_t type;
61 u_int16_t class;
62 struct dns_query *next;
63};
64
65struct dns_rr {
66 char *name;
67 u_int16_t type;
68 u_int16_t class;
69 u_int16_t ttl;
70 u_int16_t size;
71 void *rdata;
72 struct dns_rr *next;
73};
74
75struct dns_response {
76 HEADER header;
77 struct dns_query *query;
78 struct dns_rr *answer;
79 struct dns_rr *authority;
80 struct dns_rr *additional;
81};
82
83static struct dns_response *parse_dns_response(const u_char *, int);
84static struct dns_query *parse_dns_qsection(const u_char *, int,
85 const u_char **, int);
86static struct dns_rr *parse_dns_rrsection(const u_char *, int, const u_char **,
87 int);
88
89static void free_dns_query(struct dns_query *);
90static void free_dns_rr(struct dns_rr *);
91static void free_dns_response(struct dns_response *);
92
93static int count_dns_rr(struct dns_rr *, u_int16_t, u_int16_t);
94
95int
96getrrsetbyname(const char *hostname, unsigned int rdclass,
97 unsigned int rdtype, unsigned int flags,
98 struct rrsetinfo **res)
99{
100 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
101 int result;
102 struct rrsetinfo *rrset = NULL;
103 struct dns_response *response = NULL;
104 struct dns_rr *rr;
105 struct rdatainfo *rdata;
106 int length;
107 unsigned int index_ans, index_sig;
108 union {
109 HEADER hdr;
110 u_char buf[MAXPACKET];
111 } answer;
112
113 /* check for invalid class and type */
114 if (rdclass > 0xffff || rdtype > 0xffff) {
115 result = ERRSET_INVAL;
116 goto fail;
117 }
118
119 /* don't allow queries of class or type ANY */
120 if (rdclass == 0xff || rdtype == 0xff) {
121 result = ERRSET_INVAL;
122 goto fail;
123 }
124
125 /* don't allow flags yet, unimplemented */
126 if (flags) {
127 result = ERRSET_INVAL;
128 goto fail;
129 }
130
131 /* initialize resolver */
132 if (_res_init(0) == -1) {
133 result = ERRSET_FAIL;
134 goto fail;
135 }
136
137#ifdef DEBUG
138 _resp->options |= RES_DEBUG;
139#endif /* DEBUG */
140
141#ifdef RES_USE_DNSSEC
142 /* turn on DNSSEC if EDNS0 is configured */
143 if (_resp->options & RES_USE_EDNS0)
144 _resp->options |= RES_USE_DNSSEC;
145#endif /* RES_USE_DNSEC */
146
147 /* make query */
148 length = res_query(hostname, (signed int) rdclass, (signed int) rdtype,
149 answer.buf, sizeof(answer.buf));
150 if (length < 0) {
151 switch(h_errno) {
152 case HOST_NOT_FOUND:
153 result = ERRSET_NONAME;
154 goto fail;
155 case NO_DATA:
156 result = ERRSET_NODATA;
157 goto fail;
158 default:
159 result = ERRSET_FAIL;
160 goto fail;
161 }
162 }
163
164 /* parse result */
165 response = parse_dns_response(answer.buf, length);
166 if (response == NULL) {
167 result = ERRSET_FAIL;
168 goto fail;
169 }
170
171 if (response->header.qdcount != 1) {
172 result = ERRSET_FAIL;
173 goto fail;
174 }
175
176 /* initialize rrset */
177 rrset = calloc(1, sizeof(struct rrsetinfo));
178 if (rrset == NULL) {
179 result = ERRSET_NOMEMORY;
180 goto fail;
181 }
182 rrset->rri_rdclass = response->query->class;
183 rrset->rri_rdtype = response->query->type;
184 rrset->rri_ttl = response->answer->ttl;
185 rrset->rri_nrdatas = response->header.ancount;
186
187 /* check for authenticated data */
188 if (response->header.ad == 1)
189 rrset->rri_flags |= RRSET_VALIDATED;
190
191 /* copy name from answer section */
192 rrset->rri_name = strdup(response->answer->name);
193 if (rrset->rri_name == NULL) {
194 result = ERRSET_NOMEMORY;
195 goto fail;
196 }
197
198 /* count answers */
199 rrset->rri_nrdatas = count_dns_rr(response->answer, rrset->rri_rdclass,
200 rrset->rri_rdtype);
201 rrset->rri_nsigs = count_dns_rr(response->answer, rrset->rri_rdclass,
202 T_RRSIG);
203
204 /* allocate memory for answers */
205 rrset->rri_rdatas = calloc(rrset->rri_nrdatas,
206 sizeof(struct rdatainfo));
207 if (rrset->rri_rdatas == NULL) {
208 result = ERRSET_NOMEMORY;
209 goto fail;
210 }
211
212 /* allocate memory for signatures */
213 rrset->rri_sigs = calloc(rrset->rri_nsigs, sizeof(struct rdatainfo));
214 if (rrset->rri_sigs == NULL) {
215 result = ERRSET_NOMEMORY;
216 goto fail;
217 }
218
219 /* copy answers & signatures */
220 for (rr = response->answer, index_ans = 0, index_sig = 0;
221 rr; rr = rr->next) {
222
223 rdata = NULL;
224
225 if (rr->class == rrset->rri_rdclass &&
226 rr->type == rrset->rri_rdtype)
227 rdata = &rrset->rri_rdatas[index_ans++];
228
229 if (rr->class == rrset->rri_rdclass &&
230 rr->type == T_RRSIG)
231 rdata = &rrset->rri_sigs[index_sig++];
232
233 if (rdata) {
234 rdata->rdi_length = rr->size;
235 rdata->rdi_data = malloc(rr->size);
236
237 if (rdata->rdi_data == NULL) {
238 result = ERRSET_NOMEMORY;
239 goto fail;
240 }
241 memcpy(rdata->rdi_data, rr->rdata, rr->size);
242 }
243 }
244 free_dns_response(response);
245
246 *res = rrset;
247 return (ERRSET_SUCCESS);
248
249fail:
250 if (rrset != NULL)
251 freerrset(rrset);
252 if (response != NULL)
253 free_dns_response(response);
254 return (result);
255}
256
257void
258freerrset(struct rrsetinfo *rrset)
259{
260 u_int16_t i;
261
262 if (rrset == NULL)
263 return;
264
265 if (rrset->rri_rdatas) {
266 for (i = 0; i < rrset->rri_nrdatas; i++) {
267 if (rrset->rri_rdatas[i].rdi_data == NULL)
268 break;
269 free(rrset->rri_rdatas[i].rdi_data);
270 }
271 free(rrset->rri_rdatas);
272 }
273
274 if (rrset->rri_sigs) {
275 for (i = 0; i < rrset->rri_nsigs; i++) {
276 if (rrset->rri_sigs[i].rdi_data == NULL)
277 break;
278 free(rrset->rri_sigs[i].rdi_data);
279 }
280 free(rrset->rri_sigs);
281 }
282
283 if (rrset->rri_name)
284 free(rrset->rri_name);
285 free(rrset);
286}
287
288/*
289 * DNS response parsing routines
290 */
291static struct dns_response *
292parse_dns_response(const u_char *answer, int size)
293{
294 struct dns_response *resp;
295 const u_char *cp;
296
297 /* allocate memory for the response */
298 resp = calloc(1, sizeof(*resp));
299 if (resp == NULL)
300 return (NULL);
301
302 /* initialize current pointer */
303 cp = answer;
304
305 /* copy header */
306 memcpy(&resp->header, cp, HFIXEDSZ);
307 cp += HFIXEDSZ;
308
309 /* fix header byte order */
310 resp->header.qdcount = ntohs(resp->header.qdcount);
311 resp->header.ancount = ntohs(resp->header.ancount);
312 resp->header.nscount = ntohs(resp->header.nscount);
313 resp->header.arcount = ntohs(resp->header.arcount);
314
315 /* there must be at least one query */
316 if (resp->header.qdcount < 1) {
317 free_dns_response(resp);
318 return (NULL);
319 }
320
321 /* parse query section */
322 resp->query = parse_dns_qsection(answer, size, &cp,
323 resp->header.qdcount);
324 if (resp->header.qdcount && resp->query == NULL) {
325 free_dns_response(resp);
326 return (NULL);
327 }
328
329 /* parse answer section */
330 resp->answer = parse_dns_rrsection(answer, size, &cp,
331 resp->header.ancount);
332 if (resp->header.ancount && resp->answer == NULL) {
333 free_dns_response(resp);
334 return (NULL);
335 }
336
337 /* parse authority section */
338 resp->authority = parse_dns_rrsection(answer, size, &cp,
339 resp->header.nscount);
340 if (resp->header.nscount && resp->authority == NULL) {
341 free_dns_response(resp);
342 return (NULL);
343 }
344
345 /* parse additional section */
346 resp->additional = parse_dns_rrsection(answer, size, &cp,
347 resp->header.arcount);
348 if (resp->header.arcount && resp->additional == NULL) {
349 free_dns_response(resp);
350 return (NULL);
351 }
352
353 return (resp);
354}
355
356static struct dns_query *
357parse_dns_qsection(const u_char *answer, int size, const u_char **cp, int count)
358{
359 struct dns_query *head, *curr, *prev;
360 int i, length;
361 char name[MAXDNAME];
362
363 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
364
365 /* allocate and initialize struct */
366 curr = calloc(1, sizeof(struct dns_query));
367 if (curr == NULL) {
368 free_dns_query(head);
369 return (NULL);
370 }
371 if (head == NULL)
372 head = curr;
373 if (prev != NULL)
374 prev->next = curr;
375
376 /* name */
377 length = dn_expand(answer, answer + size, *cp, name,
378 sizeof(name));
379 if (length < 0) {
380 free_dns_query(head);
381 return (NULL);
382 }
383 curr->name = strdup(name);
384 if (curr->name == NULL) {
385 free_dns_query(head);
386 return (NULL);
387 }
388 *cp += length;
389
390 /* type */
391 curr->type = _getshort(*cp);
392 *cp += INT16SZ;
393
394 /* class */
395 curr->class = _getshort(*cp);
396 *cp += INT16SZ;
397 }
398
399 return (head);
400}
401
402static struct dns_rr *
403parse_dns_rrsection(const u_char *answer, int size, const u_char **cp,
404 int count)
405{
406 struct dns_rr *head, *curr, *prev;
407 int i, length;
408 char name[MAXDNAME];
409
410 for (i = 1, head = NULL, prev = NULL; i <= count; i++, prev = curr) {
411
412 /* allocate and initialize struct */
413 curr = calloc(1, sizeof(struct dns_rr));
414 if (curr == NULL) {
415 free_dns_rr(head);
416 return (NULL);
417 }
418 if (head == NULL)
419 head = curr;
420 if (prev != NULL)
421 prev->next = curr;
422
423 /* name */
424 length = dn_expand(answer, answer + size, *cp, name,
425 sizeof(name));
426 if (length < 0) {
427 free_dns_rr(head);
428 return (NULL);
429 }
430 curr->name = strdup(name);
431 if (curr->name == NULL) {
432 free_dns_rr(head);
433 return (NULL);
434 }
435 *cp += length;
436
437 /* type */
438 curr->type = _getshort(*cp);
439 *cp += INT16SZ;
440
441 /* class */
442 curr->class = _getshort(*cp);
443 *cp += INT16SZ;
444
445 /* ttl */
446 curr->ttl = _getlong(*cp);
447 *cp += INT32SZ;
448
449 /* rdata size */
450 curr->size = _getshort(*cp);
451 *cp += INT16SZ;
452
453 /* rdata itself */
454 curr->rdata = malloc(curr->size);
455 if (curr->rdata == NULL) {
456 free_dns_rr(head);
457 return (NULL);
458 }
459 memcpy(curr->rdata, *cp, curr->size);
460 *cp += curr->size;
461 }
462
463 return (head);
464}
465
466static void
467free_dns_query(struct dns_query *p)
468{
469 if (p == NULL)
470 return;
471
472 if (p->name)
473 free(p->name);
474 free_dns_query(p->next);
475 free(p);
476}
477
478static void
479free_dns_rr(struct dns_rr *p)
480{
481 if (p == NULL)
482 return;
483
484 if (p->name)
485 free(p->name);
486 if (p->rdata)
487 free(p->rdata);
488 free_dns_rr(p->next);
489 free(p);
490}
491
492static void
493free_dns_response(struct dns_response *p)
494{
495 if (p == NULL)
496 return;
497
498 free_dns_query(p->query);
499 free_dns_rr(p->answer);
500 free_dns_rr(p->authority);
501 free_dns_rr(p->additional);
502 free(p);
503}
504
505static int
506count_dns_rr(struct dns_rr *p, u_int16_t class, u_int16_t type)
507{
508 int n = 0;
509
510 while(p) {
511 if (p->class == class && p->type == type)
512 n++;
513 p = p->next;
514 }
515
516 return (n);
517}
diff --git a/src/lib/libc/net/res_debug.c b/src/lib/libc/net/res_debug.c
deleted file mode 100644
index 246fefef3c..0000000000
--- a/src/lib/libc/net/res_debug.c
+++ /dev/null
@@ -1,1395 +0,0 @@
1/* $OpenBSD: res_debug.c,v 1.22 2007/10/11 18:36:41 jakob Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1990, 1993
5 * -
6 * Copyright (c) 1985, 1990, 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 * Portions Copyright (c) 1995 by International Business Machines, Inc.
52 *
53 * International Business Machines, Inc. (hereinafter called IBM) grants
54 * permission under its copyrights to use, copy, modify, and distribute this
55 * Software with or without fee, provided that the above copyright notice and
56 * all paragraphs of this notice appear in all copies, and that the name of IBM
57 * not be used in connection with the marketing of any product incorporating
58 * the Software or modifications thereof, without specific, written prior
59 * permission.
60 *
61 * To the extent it has a right to do so, IBM grants an immunity from suit
62 * under its patents, if any, for the use, sale or manufacture of products to
63 * the extent that such products are used for performing Domain Name System
64 * dynamic updates in TCP/IP networks by means of the Software. No immunity is
65 * granted for any product per se or for any other function of any product.
66 *
67 * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
68 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
69 * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
70 * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
71 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
72 * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
73 * --Copyright--
74 */
75
76#include <sys/param.h>
77#include <sys/types.h>
78#include <sys/socket.h>
79#include <netinet/in.h>
80#include <arpa/inet.h>
81#include <arpa/nameser.h>
82
83#include <ctype.h>
84#include <netdb.h>
85#include <resolv.h>
86#include <stdio.h>
87#include <time.h>
88
89#include <stdlib.h>
90#include <string.h>
91
92#include "thread_private.h"
93
94extern const char *_res_opcodes[];
95extern const char *_res_resultcodes[];
96
97static const char *loc_ntoal(const u_char *binary, char *ascii, int ascii_len);
98
99/* XXX: we should use getservbyport() instead. */
100static const char *
101dewks(int wks)
102{
103 static char nbuf[20];
104
105 switch (wks) {
106 case 5: return "rje";
107 case 7: return "echo";
108 case 9: return "discard";
109 case 11: return "systat";
110 case 13: return "daytime";
111 case 15: return "netstat";
112 case 17: return "qotd";
113 case 19: return "chargen";
114 case 20: return "ftp-data";
115 case 21: return "ftp";
116 case 23: return "telnet";
117 case 25: return "smtp";
118 case 37: return "time";
119 case 39: return "rlp";
120 case 42: return "name";
121 case 43: return "whois";
122 case 53: return "domain";
123 case 57: return "apts";
124 case 59: return "apfs";
125 case 67: return "bootps";
126 case 68: return "bootpc";
127 case 69: return "tftp";
128 case 77: return "rje";
129 case 79: return "finger";
130 case 87: return "link";
131 case 95: return "supdup";
132 case 100: return "newacct";
133 case 101: return "hostnames";
134 case 102: return "iso-tsap";
135 case 103: return "x400";
136 case 104: return "x400-snd";
137 case 105: return "csnet-ns";
138 case 109: return "pop-2";
139 case 111: return "sunrpc";
140 case 113: return "auth";
141 case 115: return "sftp";
142 case 117: return "uucp-path";
143 case 119: return "nntp";
144 case 121: return "erpc";
145 case 123: return "ntp";
146 case 133: return "statsrv";
147 case 136: return "profile";
148 case 144: return "NeWS";
149 case 161: return "snmp";
150 case 162: return "snmp-trap";
151 case 170: return "print-srv";
152 default:
153 (void) snprintf(nbuf, sizeof nbuf, "%d", wks);
154 return (nbuf);
155 }
156}
157
158/* XXX: we should use getprotobynumber() instead. */
159static const char *
160deproto(int protonum)
161{
162 static char nbuf[20];
163
164 switch (protonum) {
165 case 1: return "icmp";
166 case 2: return "igmp";
167 case 3: return "ggp";
168 case 5: return "st";
169 case 6: return "tcp";
170 case 7: return "ucl";
171 case 8: return "egp";
172 case 9: return "igp";
173 case 11: return "nvp-II";
174 case 12: return "pup";
175 case 16: return "chaos";
176 case 17: return "udp";
177 default:
178 (void) snprintf(nbuf, sizeof nbuf, "%d", protonum);
179 return (nbuf);
180 }
181}
182
183static const u_char *
184do_rrset(const u_char *msg, int len, const u_char *cp, int cnt, int pflag,
185 FILE *file, const char *hs)
186{
187 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
188 int n;
189 int sflag;
190
191 /*
192 * Print answer records.
193 */
194 sflag = (_resp->pfcode & pflag);
195 if ((n = ntohs(cnt))) {
196 if ((!_resp->pfcode) ||
197 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
198 fprintf(file, "%s", hs);
199 while (--n >= 0) {
200 if ((!_resp->pfcode) || sflag) {
201 cp = p_rr(cp, msg, file);
202 } else {
203 unsigned int dlen;
204 cp += __dn_skipname(cp, cp + MAXCDNAME);
205 cp += INT16SZ;
206 cp += INT16SZ;
207 cp += INT32SZ;
208 dlen = _getshort((u_char*)cp);
209 cp += INT16SZ;
210 cp += dlen;
211 }
212 if ((cp - msg) > len)
213 return (NULL);
214 }
215 if ((!_resp->pfcode) ||
216 ((sflag) && (_resp->pfcode & RES_PRF_HEAD1)))
217 putc('\n', file);
218 }
219 return (cp);
220}
221
222void
223__p_query(const u_char *msg)
224{
225 __fp_query(msg, stdout);
226}
227
228/*
229 * Print the current options.
230 * This is intended to be primarily a debugging routine.
231 */
232void
233__fp_resstat(struct __res_state *statp, FILE *file)
234{
235 u_long mask;
236
237 fprintf(file, ";; res options:");
238 if (!statp)
239 statp = &_res;
240 for (mask = 1; mask != 0; mask <<= 1)
241 if (statp->options & mask)
242 fprintf(file, " %s", p_option(mask));
243 putc('\n', file);
244}
245
246/*
247 * Print the contents of a query.
248 * This is intended to be primarily a debugging routine.
249 */
250void
251__fp_nquery(const u_char *msg, int len, FILE *file)
252{
253 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
254 const u_char *cp, *endMark;
255 const HEADER *hp;
256 int n;
257
258 if (_res_init(0) == -1)
259 return;
260
261#define TruncTest(x) if (x > endMark) goto trunc
262#define ErrorTest(x) if (x == NULL) goto error
263
264 /*
265 * Print header fields.
266 */
267 hp = (HEADER *)msg;
268 cp = msg + HFIXEDSZ;
269 endMark = msg + len;
270 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX) || hp->rcode) {
271 fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %u",
272 _res_opcodes[hp->opcode],
273 _res_resultcodes[hp->rcode],
274 ntohs(hp->id));
275 putc('\n', file);
276 }
277 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEADX))
278 putc(';', file);
279 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD2)) {
280 fprintf(file, "; flags:");
281 if (hp->qr)
282 fprintf(file, " qr");
283 if (hp->aa)
284 fprintf(file, " aa");
285 if (hp->tc)
286 fprintf(file, " tc");
287 if (hp->rd)
288 fprintf(file, " rd");
289 if (hp->ra)
290 fprintf(file, " ra");
291 if (hp->unused)
292 fprintf(file, " UNUSED-BIT-ON");
293 if (hp->ad)
294 fprintf(file, " ad");
295 if (hp->cd)
296 fprintf(file, " cd");
297 }
298 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_HEAD1)) {
299 fprintf(file, "; Ques: %u", ntohs(hp->qdcount));
300 fprintf(file, ", Ans: %u", ntohs(hp->ancount));
301 fprintf(file, ", Auth: %u", ntohs(hp->nscount));
302 fprintf(file, ", Addit: %u", ntohs(hp->arcount));
303 }
304 if ((!_resp->pfcode) || (_resp->pfcode &
305 (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
306 putc('\n',file);
307 }
308 /*
309 * Print question records.
310 */
311 if ((n = ntohs(hp->qdcount))) {
312 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
313 fprintf(file, ";; QUESTIONS:\n");
314 while (--n >= 0) {
315 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
316 fprintf(file, ";;\t");
317 TruncTest(cp);
318 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
319 cp = p_cdnname(cp, msg, len, file);
320 else {
321 int n;
322 char name[MAXDNAME];
323
324 if ((n = dn_expand(msg, msg+len, cp, name,
325 sizeof name)) < 0)
326 cp = NULL;
327 else
328 cp += n;
329 }
330 ErrorTest(cp);
331 TruncTest(cp);
332 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
333 fprintf(file, ", type = %s",
334 __p_type(_getshort((u_char*)cp)));
335 cp += INT16SZ;
336 TruncTest(cp);
337 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
338 fprintf(file, ", class = %s\n",
339 __p_class(_getshort((u_char*)cp)));
340 cp += INT16SZ;
341 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_QUES))
342 putc('\n', file);
343 }
344 }
345 /*
346 * Print authoritative answer records
347 */
348 TruncTest(cp);
349 cp = do_rrset(msg, len, cp, hp->ancount, RES_PRF_ANS, file,
350 ";; ANSWERS:\n");
351 ErrorTest(cp);
352
353 /*
354 * print name server records
355 */
356 TruncTest(cp);
357 cp = do_rrset(msg, len, cp, hp->nscount, RES_PRF_AUTH, file,
358 ";; AUTHORITY RECORDS:\n");
359 ErrorTest(cp);
360
361 TruncTest(cp);
362 /*
363 * print additional records
364 */
365 cp = do_rrset(msg, len, cp, hp->arcount, RES_PRF_ADD, file,
366 ";; ADDITIONAL RECORDS:\n");
367 ErrorTest(cp);
368 return;
369 trunc:
370 fprintf(file, "\n;; ...truncated\n");
371 return;
372 error:
373 fprintf(file, "\n;; ...malformed\n");
374}
375
376void
377__fp_query(const u_char *msg, FILE *file)
378{
379 fp_nquery(msg, PACKETSZ, file);
380}
381
382const u_char *
383__p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file)
384{
385 char name[MAXDNAME];
386 int n;
387
388 if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
389 return (NULL);
390 if (name[0] == '\0')
391 putc('.', file);
392 else
393 fputs(name, file);
394 return (cp + n);
395}
396
397const u_char *
398__p_cdname(const u_char *cp, const u_char *msg, FILE *file)
399{
400 return (p_cdnname(cp, msg, PACKETSZ, file));
401}
402
403
404/* Return a fully-qualified domain name from a compressed name (with
405 length supplied). */
406
407const u_char *
408__p_fqnname(const u_char *cp, const u_char *msg, int msglen, char *name, int namelen)
409{
410 int n, newlen;
411
412 if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
413 return (NULL);
414 newlen = strlen(name);
415 if (newlen == 0 || name[newlen - 1] != '.') {
416 if (newlen + 1 >= namelen) /* Lack space for final dot */
417 return (NULL);
418 else
419 strlcpy(name + newlen, ".", namelen - newlen);
420 }
421 return (cp + n);
422}
423
424/* XXX: the rest of these functions need to become length-limited, too. (vix)
425 */
426
427const u_char *
428__p_fqname(const u_char *cp, const u_char *msg, FILE *file)
429{
430 char name[MAXDNAME];
431 const u_char *n;
432
433 n = __p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
434 if (n == NULL)
435 return (NULL);
436 fputs(name, file);
437 return (n);
438}
439
440/*
441 * Print resource record fields in human readable form.
442 */
443const u_char *
444__p_rr(const u_char *cp, const u_char *msg, FILE *file)
445{
446 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
447 int type, class, dlen, n, c;
448 struct in_addr inaddr;
449 const u_char *cp1, *cp2;
450 u_int32_t tmpttl, t;
451 int lcnt;
452 u_int16_t keyflags;
453 char rrname[MAXDNAME]; /* The fqdn of this RR */
454 char base64_key[MAX_KEY_BASE64];
455
456 if (_res_init(0) == -1) {
457 h_errno = NETDB_INTERNAL;
458 return (NULL);
459 }
460 cp = __p_fqnname(cp, msg, MAXCDNAME, rrname, sizeof rrname);
461 if (!cp)
462 return (NULL); /* compression error */
463 fputs(rrname, file);
464
465 type = _getshort((u_char*)cp);
466 cp += INT16SZ;
467 class = _getshort((u_char*)cp);
468 cp += INT16SZ;
469 tmpttl = _getlong((u_char*)cp);
470 cp += INT32SZ;
471 dlen = _getshort((u_char*)cp);
472 cp += INT16SZ;
473 cp1 = cp;
474 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_TTLID))
475 fprintf(file, "\t%lu", (u_long)tmpttl);
476 if ((!_resp->pfcode) || (_resp->pfcode & RES_PRF_CLASS))
477 fprintf(file, "\t%s", __p_class(class));
478 fprintf(file, "\t%s", __p_type(type));
479 /*
480 * Print type specific data, if appropriate
481 */
482 switch (type) {
483 case T_A:
484 switch (class) {
485 case C_IN:
486 case C_HS:
487 bcopy(cp, (char *)&inaddr, INADDRSZ);
488 if (dlen == 4) {
489 fprintf(file, "\t%s", inet_ntoa(inaddr));
490 cp += dlen;
491 } else if (dlen == 7) {
492 char *address;
493 u_char protocol;
494 in_port_t port;
495
496 address = inet_ntoa(inaddr);
497 cp += INADDRSZ;
498 protocol = *(u_char*)cp;
499 cp += sizeof (u_char);
500 port = _getshort((u_char*)cp);
501 cp += INT16SZ;
502 fprintf(file, "\t%s\t; proto %u, port %u",
503 address, protocol, port);
504 }
505 break;
506 default:
507 cp += dlen;
508 }
509 break;
510 case T_CNAME:
511 case T_MB:
512 case T_MG:
513 case T_MR:
514 case T_NS:
515 case T_PTR:
516 putc('\t', file);
517 if ((cp = p_fqname(cp, msg, file)) == NULL)
518 return (NULL);
519 break;
520
521 case T_HINFO:
522 case T_ISDN:
523 cp2 = cp + dlen;
524 (void) fputs("\t\"", file);
525 if ((n = (unsigned char) *cp++) != 0) {
526 for (c = n; c > 0 && cp < cp2; c--) {
527 if (strchr("\n\"\\", *cp))
528 (void) putc('\\', file);
529 (void) putc(*cp++, file);
530 }
531 }
532 putc('"', file);
533 if (cp < cp2 && (n = (unsigned char) *cp++) != 0) {
534 (void) fputs ("\t\"", file);
535 for (c = n; c > 0 && cp < cp2; c--) {
536 if (strchr("\n\"\\", *cp))
537 (void) putc('\\', file);
538 (void) putc(*cp++, file);
539 }
540 putc('"', file);
541 } else if (type == T_HINFO) {
542 (void) fputs("\"?\"", file);
543 fprintf(file, "\n;; *** Warning *** OS-type missing");
544 }
545 break;
546
547 case T_SOA:
548 putc('\t', file);
549 if ((cp = p_fqname(cp, msg, file)) == NULL)
550 return (NULL);
551 putc(' ', file);
552 if ((cp = p_fqname(cp, msg, file)) == NULL)
553 return (NULL);
554 fputs(" (\n", file);
555 t = _getlong((u_char*)cp); cp += INT32SZ;
556 fprintf(file, "\t\t\t%lu\t; serial\n", (u_long)t);
557 t = _getlong((u_char*)cp); cp += INT32SZ;
558 fprintf(file, "\t\t\t%lu\t; refresh (%s)\n",
559 (u_long)t, __p_time(t));
560 t = _getlong((u_char*)cp); cp += INT32SZ;
561 fprintf(file, "\t\t\t%lu\t; retry (%s)\n",
562 (u_long)t, __p_time(t));
563 t = _getlong((u_char*)cp); cp += INT32SZ;
564 fprintf(file, "\t\t\t%lu\t; expire (%s)\n",
565 (u_long)t, __p_time(t));
566 t = _getlong((u_char*)cp); cp += INT32SZ;
567 fprintf(file, "\t\t\t%lu )\t; minimum (%s)",
568 (u_long)t, __p_time(t));
569 break;
570
571 case T_MX:
572 case T_AFSDB:
573 case T_RT:
574 fprintf(file, "\t%u ", _getshort((u_char*)cp));
575 cp += INT16SZ;
576 if ((cp = p_fqname(cp, msg, file)) == NULL)
577 return (NULL);
578 break;
579
580 case T_PX:
581 fprintf(file, "\t%u ", _getshort((u_char*)cp));
582 cp += INT16SZ;
583 if ((cp = p_fqname(cp, msg, file)) == NULL)
584 return (NULL);
585 putc(' ', file);
586 if ((cp = p_fqname(cp, msg, file)) == NULL)
587 return (NULL);
588 break;
589
590 case T_X25:
591 cp2 = cp + dlen;
592 (void) fputs("\t\"", file);
593 if ((n = (unsigned char) *cp++) != 0) {
594 for (c = n; c > 0 && cp < cp2; c--) {
595 if (strchr("\n\"\\", *cp))
596 (void) putc('\\', file);
597 (void) putc(*cp++, file);
598 }
599 }
600 putc('"', file);
601 break;
602
603 case T_TXT:
604 (void) putc('\t', file);
605 cp2 = cp1 + dlen;
606 while (cp < cp2) {
607 putc('"', file);
608 if ((n = (unsigned char) *cp++)) {
609 for (c = n; c > 0 && cp < cp2; c--) {
610 if (strchr("\n\"\\", *cp))
611 (void) putc('\\', file);
612 (void) putc(*cp++, file);
613 }
614 }
615 putc('"', file);
616 if (cp < cp2)
617 putc(' ', file);
618 }
619 break;
620
621 case T_NSAP:
622 (void) fprintf(file, "\t%s", inet_nsap_ntoa(dlen, cp, NULL));
623 cp += dlen;
624 break;
625
626 case T_AAAA: {
627 char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
628
629 fprintf(file, "\t%s", inet_ntop(AF_INET6, cp, t, sizeof t));
630 cp += dlen;
631 break;
632 }
633
634 case T_LOC: {
635 char t[255];
636
637 fprintf(file, "\t%s", loc_ntoal(cp, t, sizeof t));
638 cp += dlen;
639 break;
640 }
641
642 case T_NAPTR: {
643 u_int order, preference;
644
645 order = _getshort(cp); cp += INT16SZ;
646 preference = _getshort(cp); cp += INT16SZ;
647 fprintf(file, "\t%u %u ",order, preference);
648 /* Flags */
649 n = *cp++;
650 fprintf(file,"\"%.*s\" ", (int)n, cp);
651 cp += n;
652 /* Service */
653 n = *cp++;
654 fprintf(file,"\"%.*s\" ", (int)n, cp);
655 cp += n;
656 /* Regexp */
657 n = *cp++;
658 fprintf(file,"\"%.*s\" ", (int)n, cp);
659 cp += n;
660 if ((cp = p_fqname(cp, msg, file)) == NULL)
661 return (NULL);
662 break;
663 }
664
665 case T_SRV: {
666 u_int priority, weight, port;
667
668 priority = _getshort(cp); cp += INT16SZ;
669 weight = _getshort(cp); cp += INT16SZ;
670 port = _getshort(cp); cp += INT16SZ;
671 fprintf(file, "\t%u %u %u ", priority, weight, port);
672 if ((cp = p_fqname(cp, msg, file)) == NULL)
673 return (NULL);
674 break;
675 }
676
677 case T_MINFO:
678 case T_RP:
679 putc('\t', file);
680 if ((cp = p_fqname(cp, msg, file)) == NULL)
681 return (NULL);
682 putc(' ', file);
683 if ((cp = p_fqname(cp, msg, file)) == NULL)
684 return (NULL);
685 break;
686
687 case T_UINFO:
688 putc('\t', file);
689 fputs((char *)cp, file);
690 cp += dlen;
691 break;
692
693 case T_UID:
694 case T_GID:
695 if (dlen == 4) {
696 fprintf(file, "\t%u", _getlong((u_char*)cp));
697 cp += INT32SZ;
698 }
699 break;
700
701 case T_WKS:
702 if (dlen < INT32SZ + 1)
703 break;
704 bcopy(cp, (char *)&inaddr, INADDRSZ);
705 cp += INT32SZ;
706 fprintf(file, "\t%s %s ( ",
707 inet_ntoa(inaddr),
708 deproto((int) *cp));
709 cp += sizeof (u_char);
710 n = 0;
711 lcnt = 0;
712 while (cp < cp1 + dlen) {
713 c = *cp++;
714 do {
715 if (c & 0200) {
716 if (lcnt == 0) {
717 fputs("\n\t\t\t", file);
718 lcnt = 5;
719 }
720 fputs(dewks(n), file);
721 putc(' ', file);
722 lcnt--;
723 }
724 c <<= 1;
725 } while (++n & 07);
726 }
727 putc(')', file);
728 break;
729
730 case T_KEY:
731 putc('\t', file);
732 keyflags = _getshort(cp);
733 cp += 2;
734 fprintf(file,"0x%04x", keyflags ); /* flags */
735 fprintf(file," %u", *cp++); /* protocol */
736 fprintf(file," %u (", *cp++); /* algorithm */
737
738 n = b64_ntop(cp, (cp1 + dlen) - cp,
739 base64_key, sizeof base64_key);
740 for (c = 0; c < n; ++c) {
741 if (0 == (c & 0x3F))
742 fprintf(file, "\n\t");
743 putc(base64_key[c], file); /* public key data */
744 }
745
746 fprintf(file, " )");
747 if (n < 0)
748 fprintf(file, "\t; BAD BASE64");
749 fflush(file);
750 cp = cp1 + dlen;
751 break;
752
753 case T_SIG:
754 case T_RRSIG:
755 type = _getshort((u_char*)cp);
756 cp += INT16SZ;
757 fprintf(file, " %s", p_type(type));
758 fprintf(file, "\t%u", *cp++); /* algorithm */
759 /* Check label value and print error if wrong. */
760 n = *cp++;
761 c = dn_count_labels (rrname);
762 if (n != c)
763 fprintf(file, "\t; LABELS WRONG (%d should be %d)\n\t",
764 n, c);
765 /* orig ttl */
766 n = _getlong((u_char*)cp);
767 if (n != tmpttl)
768 fprintf(file, " %u", n);
769 cp += INT32SZ;
770 /* sig expire */
771 fprintf(file, " (\n\t%s",
772 __p_secstodate(_getlong((u_char*)cp)));
773 cp += INT32SZ;
774 /* time signed */
775 fprintf(file, " %s", __p_secstodate(_getlong((u_char*)cp)));
776 cp += INT32SZ;
777 /* sig footprint */
778 fprintf(file," %u ", _getshort((u_char*)cp));
779 cp += INT16SZ;
780 /* signer's name */
781 cp = p_fqname(cp, msg, file);
782 n = b64_ntop(cp, (cp1 + dlen) - cp,
783 base64_key, sizeof base64_key);
784 for (c = 0; c < n; c++) {
785 if (0 == (c & 0x3F))
786 fprintf (file, "\n\t");
787 putc(base64_key[c], file); /* signature */
788 }
789 /* Clean up... */
790 fprintf(file, " )");
791 if (n < 0)
792 fprintf(file, "\t; BAD BASE64");
793 fflush(file);
794 cp = cp1+dlen;
795 break;
796
797#ifdef ALLOW_T_UNSPEC
798 case T_UNSPEC:
799 {
800 int NumBytes = 8;
801 u_char *DataPtr;
802 int i;
803
804 if (dlen < NumBytes) NumBytes = dlen;
805 fprintf(file, "\tFirst %d bytes of hex data:",
806 NumBytes);
807 for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++)
808 fprintf(file, " %x", *DataPtr);
809 cp += dlen;
810 }
811 break;
812#endif /* ALLOW_T_UNSPEC */
813
814 default:
815 fprintf(file, "\t?%d?", type);
816 cp += dlen;
817 }
818#if 0
819 fprintf(file, "\t; dlen=%d, ttl %s\n", dlen, __p_time(tmpttl));
820#else
821 putc('\n', file);
822#endif
823 if (cp - cp1 != dlen) {
824 fprintf(file, ";; packet size error (found %ld, dlen was %d)\n",
825 (long)(cp - cp1), dlen);
826 cp = NULL;
827 }
828 return (cp);
829}
830
831int
832__sym_ston(const struct res_sym *syms, char *name, int *success)
833{
834 for (; syms->name != 0; syms++) {
835 if (strcasecmp (name, syms->name) == 0) {
836 if (success)
837 *success = 1;
838 return (syms->number);
839 }
840 }
841 if (success)
842 *success = 0;
843 return (syms->number); /* The default value. */
844}
845
846
847const char *
848__sym_ntop(const struct res_sym *syms, int number, int *success)
849{
850 static char unname[20];
851
852 for (; syms->name != 0; syms++) {
853 if (number == syms->number) {
854 if (success)
855 *success = 1;
856 return (syms->humanname);
857 }
858 }
859 snprintf(unname, sizeof unname, "%d", number);
860 if (success)
861 *success = 0;
862 return (unname);
863}
864
865/*
866 * Return a mnemonic for an option
867 */
868const char *
869__p_option(u_long option)
870{
871 static char nbuf[40];
872
873 switch (option) {
874 case RES_INIT: return "init";
875 case RES_DEBUG: return "debug";
876 case RES_AAONLY: return "aaonly(unimpl)";
877 case RES_USEVC: return "usevc";
878 case RES_PRIMARY: return "primry(unimpl)";
879 case RES_IGNTC: return "igntc";
880 case RES_RECURSE: return "recurs";
881 case RES_DEFNAMES: return "defnam";
882 case RES_STAYOPEN: return "styopn";
883 case RES_DNSRCH: return "dnsrch";
884 case RES_INSECURE1: return "insecure1";
885 case RES_INSECURE2: return "insecure2";
886 case RES_USE_INET6: return "inet6";
887 case RES_USE_EDNS0: return "edns0";
888 default:
889 snprintf(nbuf, sizeof nbuf, "?0x%lx?", (u_long)option);
890 return (nbuf);
891 }
892}
893
894/*
895 * Return a mnemonic for a time to live
896 */
897const char *
898p_time(u_int32_t value)
899{
900 static char nbuf[40];
901 char *ebuf;
902 int secs, mins, hours, days;
903 char *p;
904 int tmp;
905
906 if (value == 0) {
907 strlcpy(nbuf, "0 secs", sizeof nbuf);
908 return (nbuf);
909 }
910
911 secs = value % 60;
912 value /= 60;
913 mins = value % 60;
914 value /= 60;
915 hours = value % 24;
916 value /= 24;
917 days = value;
918 value = 0;
919
920#define PLURALIZE(x) x, (x == 1) ? "" : "s"
921 p = nbuf;
922 ebuf = nbuf + sizeof(nbuf);
923 if (days) {
924 if ((tmp = snprintf(p, ebuf - p, "%d day%s",
925 PLURALIZE(days))) >= ebuf - p || tmp < 0)
926 goto full;
927 p += tmp;
928 }
929 if (hours) {
930 if (days)
931 *p++ = ' ';
932 if (p >= ebuf)
933 goto full;
934 if ((tmp = snprintf(p, ebuf - p, "%d hour%s",
935 PLURALIZE(hours))) >= ebuf - p || tmp < 0)
936 goto full;
937 p += tmp;
938 }
939 if (mins) {
940 if (days || hours)
941 *p++ = ' ';
942 if (p >= ebuf)
943 goto full;
944 if ((tmp = snprintf(p, ebuf - p, "%d min%s",
945 PLURALIZE(mins))) >= ebuf - p || tmp < 0)
946 goto full;
947 p += tmp;
948 }
949 if (secs || ! (days || hours || mins)) {
950 if (days || hours || mins)
951 *p++ = ' ';
952 if (p >= ebuf)
953 goto full;
954 if ((tmp = snprintf(p, ebuf - p, "%d sec%s",
955 PLURALIZE(secs))) >= ebuf - p || tmp < 0)
956 goto full;
957 }
958 return (nbuf);
959full:
960 p = nbuf + sizeof(nbuf) - 4;
961 *p++ = '.';
962 *p++ = '.';
963 *p++ = '.';
964 *p++ = '\0';
965 return (nbuf);
966}
967
968/*
969 * routines to convert between on-the-wire RR format and zone file format.
970 * Does not contain conversion to/from decimal degrees; divide or multiply
971 * by 60*60*1000 for that.
972 */
973
974static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
975 1000000,10000000,100000000,1000000000};
976
977/* takes an XeY precision/size value, returns a string representation. */
978static const char *
979precsize_ntoa(u_int8_t prec)
980{
981 static char retbuf[sizeof "90000000.00"];
982 unsigned long val;
983 int mantissa, exponent;
984
985 mantissa = (int)((prec >> 4) & 0x0f) % 10;
986 exponent = (int)((prec >> 0) & 0x0f) % 10;
987
988 val = mantissa * poweroften[exponent];
989
990 (void) snprintf(retbuf, sizeof retbuf, "%ld.%.2ld", val/100, val%100);
991 return (retbuf);
992}
993
994/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
995static u_int8_t
996precsize_aton(char **strptr)
997{
998 unsigned int mval = 0, cmval = 0;
999 u_int8_t retval = 0;
1000 char *cp;
1001 int exponent;
1002 int mantissa;
1003
1004 cp = *strptr;
1005
1006 while (isdigit(*cp))
1007 mval = mval * 10 + (*cp++ - '0');
1008
1009 if (*cp == '.') { /* centimeters */
1010 cp++;
1011 if (isdigit(*cp)) {
1012 cmval = (*cp++ - '0') * 10;
1013 if (isdigit(*cp)) {
1014 cmval += (*cp++ - '0');
1015 }
1016 }
1017 }
1018 cmval = (mval * 100) + cmval;
1019
1020 for (exponent = 0; exponent < 9; exponent++)
1021 if (cmval < poweroften[exponent+1])
1022 break;
1023
1024 mantissa = cmval / poweroften[exponent];
1025 if (mantissa > 9)
1026 mantissa = 9;
1027
1028 retval = (mantissa << 4) | exponent;
1029
1030 *strptr = cp;
1031
1032 return (retval);
1033}
1034
1035/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
1036static u_int32_t
1037latlon2ul(char **latlonstrptr, int *which)
1038{
1039 char *cp;
1040 u_int32_t retval;
1041 int deg = 0, min = 0, secs = 0, secsfrac = 0;
1042
1043 cp = *latlonstrptr;
1044
1045 while (isdigit(*cp))
1046 deg = deg * 10 + (*cp++ - '0');
1047
1048 while (isspace(*cp))
1049 cp++;
1050
1051 if (!(isdigit(*cp)))
1052 goto fndhemi;
1053
1054 while (isdigit(*cp))
1055 min = min * 10 + (*cp++ - '0');
1056
1057 while (isspace(*cp))
1058 cp++;
1059
1060 if (!(isdigit(*cp)))
1061 goto fndhemi;
1062
1063 while (isdigit(*cp))
1064 secs = secs * 10 + (*cp++ - '0');
1065
1066 if (*cp == '.') { /* decimal seconds */
1067 cp++;
1068 if (isdigit(*cp)) {
1069 secsfrac = (*cp++ - '0') * 100;
1070 if (isdigit(*cp)) {
1071 secsfrac += (*cp++ - '0') * 10;
1072 if (isdigit(*cp)) {
1073 secsfrac += (*cp++ - '0');
1074 }
1075 }
1076 }
1077 }
1078
1079 while (!isspace(*cp)) /* if any trailing garbage */
1080 cp++;
1081
1082 while (isspace(*cp))
1083 cp++;
1084
1085 fndhemi:
1086 switch (*cp) {
1087 case 'N': case 'n':
1088 case 'E': case 'e':
1089 retval = ((unsigned)1<<31)
1090 + (((((deg * 60) + min) * 60) + secs) * 1000)
1091 + secsfrac;
1092 break;
1093 case 'S': case 's':
1094 case 'W': case 'w':
1095 retval = ((unsigned)1<<31)
1096 - (((((deg * 60) + min) * 60) + secs) * 1000)
1097 - secsfrac;
1098 break;
1099 default:
1100 retval = 0; /* invalid value -- indicates error */
1101 break;
1102 }
1103
1104 switch (*cp) {
1105 case 'N': case 'n':
1106 case 'S': case 's':
1107 *which = 1; /* latitude */
1108 break;
1109 case 'E': case 'e':
1110 case 'W': case 'w':
1111 *which = 2; /* longitude */
1112 break;
1113 default:
1114 *which = 0; /* error */
1115 break;
1116 }
1117
1118 cp++; /* skip the hemisphere */
1119
1120 while (!isspace(*cp)) /* if any trailing garbage */
1121 cp++;
1122
1123 while (isspace(*cp)) /* move to next field */
1124 cp++;
1125
1126 *latlonstrptr = cp;
1127
1128 return (retval);
1129}
1130
1131/* converts a zone file representation in a string to an RDATA on-the-wire
1132 * representation. */
1133int
1134loc_aton(const char *ascii, u_char *binary)
1135{
1136 const char *maxcp;
1137 u_char *bcp;
1138 char *cp;
1139
1140 u_int32_t latit = 0, longit = 0, alt = 0;
1141 u_int32_t lltemp1 = 0, lltemp2 = 0;
1142 int altmeters = 0, altfrac = 0, altsign = 1;
1143 u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
1144 u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
1145 u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
1146 int which1 = 0, which2 = 0;
1147
1148 cp = (char *)ascii;
1149 maxcp = cp + strlen(ascii);
1150
1151 lltemp1 = latlon2ul(&cp, &which1);
1152
1153 lltemp2 = latlon2ul(&cp, &which2);
1154
1155 switch (which1 + which2) {
1156 case 3: /* 1 + 2, the only valid combination */
1157 if ((which1 == 1) && (which2 == 2)) { /* normal case */
1158 latit = lltemp1;
1159 longit = lltemp2;
1160 } else if ((which1 == 2) && (which2 == 1)) { /* reversed */
1161 longit = lltemp1;
1162 latit = lltemp2;
1163 } else { /* some kind of brokenness */
1164 return (0);
1165 }
1166 break;
1167 default: /* we didn't get one of each */
1168 return (0);
1169 }
1170
1171 /* altitude */
1172 if (*cp == '-') {
1173 altsign = -1;
1174 cp++;
1175 }
1176
1177 if (*cp == '+')
1178 cp++;
1179
1180 while (isdigit(*cp))
1181 altmeters = altmeters * 10 + (*cp++ - '0');
1182
1183 if (*cp == '.') { /* decimal meters */
1184 cp++;
1185 if (isdigit(*cp)) {
1186 altfrac = (*cp++ - '0') * 10;
1187 if (isdigit(*cp)) {
1188 altfrac += (*cp++ - '0');
1189 }
1190 }
1191 }
1192
1193 alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
1194
1195 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1196 cp++;
1197
1198 while (isspace(*cp) && (cp < maxcp))
1199 cp++;
1200
1201 if (cp >= maxcp)
1202 goto defaults;
1203
1204 siz = precsize_aton(&cp);
1205
1206 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1207 cp++;
1208
1209 while (isspace(*cp) && (cp < maxcp))
1210 cp++;
1211
1212 if (cp >= maxcp)
1213 goto defaults;
1214
1215 hp = precsize_aton(&cp);
1216
1217 while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */
1218 cp++;
1219
1220 while (isspace(*cp) && (cp < maxcp))
1221 cp++;
1222
1223 if (cp >= maxcp)
1224 goto defaults;
1225
1226 vp = precsize_aton(&cp);
1227
1228 defaults:
1229
1230 bcp = binary;
1231 *bcp++ = (u_int8_t) 0; /* version byte */
1232 *bcp++ = siz;
1233 *bcp++ = hp;
1234 *bcp++ = vp;
1235 PUTLONG(latit,bcp);
1236 PUTLONG(longit,bcp);
1237 PUTLONG(alt,bcp);
1238
1239 return (16); /* size of RR in octets */
1240}
1241
1242const char *
1243loc_ntoa(const u_char *binary, char *ascii)
1244{
1245 return loc_ntoal(binary, ascii, 255);
1246}
1247
1248/* takes an on-the-wire LOC RR and formats it in a human readable format. */
1249static const char *
1250loc_ntoal(const u_char *binary, char *ascii, int ascii_len)
1251{
1252 static char *error = "?";
1253 const u_char *cp = binary;
1254
1255 int latdeg, latmin, latsec, latsecfrac;
1256 int longdeg, longmin, longsec, longsecfrac;
1257 char northsouth, eastwest;
1258 int altmeters, altfrac, altsign;
1259
1260 const int referencealt = 100000 * 100;
1261
1262 int32_t latval, longval, altval;
1263 u_int32_t templ;
1264 u_int8_t sizeval, hpval, vpval, versionval;
1265
1266 char *sizestr, *hpstr, *vpstr;
1267
1268 versionval = *cp++;
1269
1270 if (versionval) {
1271 snprintf(ascii, ascii_len, "; error: unknown LOC RR version");
1272 return (ascii);
1273 }
1274
1275 sizeval = *cp++;
1276
1277 hpval = *cp++;
1278 vpval = *cp++;
1279
1280 GETLONG(templ, cp);
1281 latval = (templ - ((unsigned)1<<31));
1282
1283 GETLONG(templ, cp);
1284 longval = (templ - ((unsigned)1<<31));
1285
1286 GETLONG(templ, cp);
1287 if (templ < referencealt) { /* below WGS 84 spheroid */
1288 altval = referencealt - templ;
1289 altsign = -1;
1290 } else {
1291 altval = templ - referencealt;
1292 altsign = 1;
1293 }
1294
1295 if (latval < 0) {
1296 northsouth = 'S';
1297 latval = -latval;
1298 } else
1299 northsouth = 'N';
1300
1301 latsecfrac = latval % 1000;
1302 latval = latval / 1000;
1303 latsec = latval % 60;
1304 latval = latval / 60;
1305 latmin = latval % 60;
1306 latval = latval / 60;
1307 latdeg = latval;
1308
1309 if (longval < 0) {
1310 eastwest = 'W';
1311 longval = -longval;
1312 } else
1313 eastwest = 'E';
1314
1315 longsecfrac = longval % 1000;
1316 longval = longval / 1000;
1317 longsec = longval % 60;
1318 longval = longval / 60;
1319 longmin = longval % 60;
1320 longval = longval / 60;
1321 longdeg = longval;
1322
1323 altfrac = altval % 100;
1324 altmeters = (altval / 100) * altsign;
1325
1326 if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL)
1327 sizestr = error;
1328 if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL)
1329 hpstr = error;
1330 if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL)
1331 vpstr = error;
1332
1333 snprintf(ascii, ascii_len,
1334 "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm",
1335 latdeg, latmin, latsec, latsecfrac, northsouth,
1336 longdeg, longmin, longsec, longsecfrac, eastwest,
1337 altmeters, altfrac, sizestr, hpstr, vpstr);
1338
1339 if (sizestr != error)
1340 free(sizestr);
1341 if (hpstr != error)
1342 free(hpstr);
1343 if (vpstr != error)
1344 free(vpstr);
1345
1346 return (ascii);
1347}
1348
1349
1350/* Return the number of DNS hierarchy levels in the name. */
1351int
1352__dn_count_labels(char *name)
1353{
1354 int i, len, count;
1355
1356 len = strlen(name);
1357
1358 for(i = 0, count = 0; i < len; i++) {
1359 if (name[i] == '.')
1360 count++;
1361 }
1362
1363 /* don't count initial wildcard */
1364 if (name[0] == '*')
1365 if (count)
1366 count--;
1367
1368 /* don't count the null label for root. */
1369 /* if terminating '.' not found, must adjust */
1370 /* count to include last label */
1371 if (len > 0 && name[len-1] != '.')
1372 count++;
1373 return (count);
1374}
1375
1376
1377/*
1378 * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
1379 * SIG records are required to be printed like this, by the Secure DNS RFC.
1380 */
1381char *
1382__p_secstodate (long unsigned int secs)
1383{
1384 static char output[15]; /* YYYYMMDDHHMMSS and null */
1385 time_t clock = secs;
1386 struct tm *time;
1387
1388 time = gmtime(&clock);
1389 time->tm_year += 1900;
1390 time->tm_mon += 1;
1391 snprintf(output, sizeof output, "%04d%02d%02d%02d%02d%02d",
1392 time->tm_year, time->tm_mon, time->tm_mday,
1393 time->tm_hour, time->tm_min, time->tm_sec);
1394 return (output);
1395}
diff --git a/src/lib/libc/net/res_init.c b/src/lib/libc/net/res_init.c
deleted file mode 100644
index 18de3550e6..0000000000
--- a/src/lib/libc/net/res_init.c
+++ /dev/null
@@ -1,707 +0,0 @@
1/* $OpenBSD: res_init.c,v 1.40 2009/06/05 09:52:26 pyr Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 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#ifndef INET6
55#define INET6
56#endif
57
58#include <sys/types.h>
59#include <sys/param.h>
60#include <sys/socket.h>
61#include <sys/time.h>
62#include <sys/stat.h>
63#include <netinet/in.h>
64#include <arpa/inet.h>
65#include <arpa/nameser.h>
66
67#include <stdio.h>
68#include <ctype.h>
69#include <resolv.h>
70#include <unistd.h>
71#include <stdlib.h>
72#include <string.h>
73#ifdef INET6
74#include <netdb.h>
75#endif /* INET6 */
76
77#include "thread_private.h"
78
79/*-------------------------------------- info about "sortlist" --------------
80 * Marc Majka 1994/04/16
81 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x)
82 *
83 * NetInfo resolver configuration directory support.
84 *
85 * Allow a NetInfo directory to be created in the hierarchy which
86 * contains the same information as the resolver configuration file.
87 *
88 * - The local domain name is stored as the value of the "domain" property.
89 * - The Internet address(es) of the name server(s) are stored as values
90 * of the "nameserver" property.
91 * - The name server addresses are stored as values of the "nameserver"
92 * property.
93 * - The search list for host-name lookup is stored as values of the
94 * "search" property.
95 * - The sortlist comprised of IP address netmask pairs are stored as
96 * values of the "sortlist" property. The IP address and optional netmask
97 * should be separated by a slash (/) or ampersand (&) character.
98 * - Internal resolver variables can be set from the value of the "options"
99 * property.
100 */
101
102static void res_setoptions(char *, char *);
103
104#ifdef RESOLVSORT
105static const char sort_mask[] = "/&";
106#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
107static u_int32_t net_mask(struct in_addr);
108#endif
109
110/*
111 * Resolver state default settings.
112 */
113void *__THREAD_NAME(_res);
114
115struct __res_state _res
116# if defined(__BIND_RES_TEXT)
117 = { RES_TIMEOUT, } /* Motorola, et al. */
118# endif
119 ;
120#ifdef INET6
121void *__THREAD_NAME(_res_ext);
122
123struct __res_state_ext _res_ext;
124#endif /* INET6 */
125
126int __res_chktime = 30;
127
128/*
129 * Set up default settings. If the configuration file exist, the values
130 * there will have precedence. Otherwise, the server address is set to
131 * INADDR_ANY and the default domain name comes from the gethostname().
132 *
133 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
134 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
135 * since it was noted that INADDR_ANY actually meant ``the first interface
136 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
137 * it had to be "up" in order for you to reach your own name server. It
138 * was later decided that since the recommended practice is to always
139 * install local static routes through 127.0.0.1 for all your network
140 * interfaces, that we could solve this problem without a code change.
141 *
142 * The configuration file should always be used, since it is the only way
143 * to specify a default domain. If you are running a server on your local
144 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
145 * in the configuration file.
146 *
147 * Return 0 if completes successfully, -1 on error
148 */
149int
150res_init(void)
151{
152
153 return (_res_init(1));
154}
155
156int
157_res_init(int usercall)
158{
159 struct stat sb;
160 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
161#ifdef INET6
162 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
163 &_res_ext);
164#endif
165 FILE *fp;
166 char *cp, **pp;
167 int n;
168 int findex;
169 char buf[BUFSIZ];
170 int nserv = 0; /* number of nameserver records read from file */
171 int haveenv = 0;
172 int havesearch = 0;
173 size_t len;
174#ifdef RESOLVSORT
175 int nsort = 0;
176 char *net;
177#endif
178#ifndef RFC1535
179 int dots;
180#endif
181
182 if (!usercall && _resp->options & RES_INIT &&
183 _resp->reschktime >= time(NULL))
184 return (0);
185 _resp->reschktime = time(NULL) + __res_chktime;
186 if (stat(_PATH_RESCONF, &sb) != -1) {
187 if (!usercall && timespeccmp(&sb.st_mtimespec,
188 &_resp->restimespec, ==))
189 return (0);
190 else
191 _resp->restimespec = sb.st_mtimespec;
192 } else {
193 /*
194 * Lost the file, in chroot?
195 * Don't trash settings
196 */
197 if (!usercall && timespecisset(&_resp->restimespec))
198 return (0);
199 }
200
201
202 /*
203 * These three fields used to be statically initialized. This made
204 * it hard to use this code in a shared library. It is necessary,
205 * now that we're doing dynamic initialization here, that we preserve
206 * the old semantics: if an application modifies one of these three
207 * fields of _res before res_init() is called, res_init() will not
208 * alter them. Of course, if an application is setting them to
209 * _zero_ before calling res_init(), hoping to override what used
210 * to be the static default, we can't detect it and unexpected results
211 * will follow. Zero for any of these fields would make no sense,
212 * so one can safely assume that the applications were already getting
213 * unexpected results.
214 *
215 * _res.options is tricky since some apps were known to diddle the bits
216 * before res_init() was first called. We can't replicate that semantic
217 * with dynamic initialization (they may have turned bits off that are
218 * set in RES_DEFAULT). Our solution is to declare such applications
219 * "broken". They could fool us by setting RES_INIT but none do (yet).
220 */
221 if (!_resp->retrans)
222 _resp->retrans = RES_TIMEOUT;
223 if (!_resp->retry)
224 _resp->retry = 4;
225 if (!(_resp->options & RES_INIT))
226 _resp->options = RES_DEFAULT;
227
228#ifdef USELOOPBACK
229 _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
230#else
231 _resp->nsaddr.sin_addr.s_addr = INADDR_ANY;
232#endif
233 _resp->nsaddr.sin_family = AF_INET;
234 _resp->nsaddr.sin_port = htons(NAMESERVER_PORT);
235 _resp->nsaddr.sin_len = sizeof(struct sockaddr_in);
236#ifdef INET6
237 if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len)
238 memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len);
239#endif
240 _resp->nscount = 1;
241 _resp->ndots = 1;
242 _resp->pfcode = 0;
243 strlcpy(_resp->lookups, "f", sizeof _resp->lookups);
244
245 /* Allow user to override the local domain definition */
246 if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
247 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
248 haveenv++;
249
250 /*
251 * Set search list to be blank-separated strings
252 * from rest of env value. Permits users of LOCALDOMAIN
253 * to still have a search list, and anyone to set the
254 * one that they want to use as an individual (even more
255 * important now that the rfc1535 stuff restricts searches)
256 */
257 cp = _resp->defdname;
258 pp = _resp->dnsrch;
259 *pp++ = cp;
260 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
261 if (*cp == '\n') /* silly backwards compat */
262 break;
263 else if (*cp == ' ' || *cp == '\t') {
264 *cp = 0;
265 n = 1;
266 } else if (n) {
267 *pp++ = cp;
268 n = 0;
269 havesearch = 1;
270 }
271 }
272 /* null terminate last domain if there are excess */
273 while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
274 cp++;
275 *cp = '\0';
276 *pp++ = 0;
277 }
278
279#define MATCH(line, name) \
280 (!strncmp(line, name, sizeof(name) - 1) && \
281 (line[sizeof(name) - 1] == ' ' || \
282 line[sizeof(name) - 1] == '\t'))
283
284 /* initialize family lookup preference: inet4 first */
285 _resp->family[0] = AF_INET;
286 _resp->family[1] = AF_INET6;
287 if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
288 strlcpy(_resp->lookups, "bf", sizeof _resp->lookups);
289
290 /* read the config file */
291 buf[0] = '\0';
292 while ((cp = fgetln(fp, &len)) != NULL) {
293 /* skip lines that are too long */
294 if (len >= sizeof(buf))
295 continue;
296 (void)memcpy(buf, cp, len);
297 buf[len] = '\0';
298 /* skip comments */
299 if ((cp = strpbrk(buf, ";#")) != NULL)
300 *cp = '\0';
301 if (buf[0] == '\0')
302 continue;
303 /* set family lookup order */
304 if (MATCH(buf, "family")) {
305 cp = buf + sizeof("family") - 1;
306 cp += strspn(cp, " \t");
307 cp[strcspn(cp, "\n")] = '\0';
308 findex = 0;
309 _resp->family[0] = _resp->family[1] = -1;
310#define INETLEN (sizeof("inetX") - 1)
311 while (*cp != '\0' && findex < 2) {
312 if (!strncmp(cp, "inet6", INETLEN)) {
313 _resp->family[findex] = AF_INET6;
314 cp += INETLEN;
315 } else if (!strncmp(cp, "inet4", INETLEN)) {
316 _resp->family[findex] = AF_INET;
317 cp += INETLEN;
318 } else {
319 _resp->family[0] = -1;
320 break;
321 }
322 if (*cp != ' ' && *cp != '\t' && *cp != '\0') {
323 _resp->family[findex] = -1;
324 break;
325 }
326 findex++;
327 cp += strspn(cp, " \t");
328 }
329
330 if (_resp->family[0] == -1) {
331 /* line contains errors, reset to defaults */
332 _resp->family[0] = AF_INET;
333 _resp->family[1] = AF_INET6;
334 }
335 if (_resp->family[0] == _resp->family[1])
336 _resp->family[1] = -1;
337 }
338 /* read default domain name */
339 if (MATCH(buf, "domain")) {
340 if (haveenv) /* skip if have from environ */
341 continue;
342 cp = buf + sizeof("domain") - 1;
343 while (*cp == ' ' || *cp == '\t')
344 cp++;
345 if ((*cp == '\0') || (*cp == '\n'))
346 continue;
347 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
348 if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL)
349 *cp = '\0';
350 havesearch = 0;
351 continue;
352 }
353 /* lookup types */
354 if (MATCH(buf, "lookup")) {
355 char *sp = NULL;
356
357 bzero(_resp->lookups, sizeof _resp->lookups);
358 cp = buf + sizeof("lookup") - 1;
359 for (n = 0;; cp++) {
360 if (n == MAXDNSLUS)
361 break;
362 if ((*cp == '\0') || (*cp == '\n')) {
363 if (sp) {
364 if (*sp=='y' || *sp=='b' || *sp=='f')
365 _resp->lookups[n++] = *sp;
366 sp = NULL;
367 }
368 break;
369 } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) {
370 if (sp) {
371 if (*sp=='y' || *sp=='b' || *sp=='f')
372 _resp->lookups[n++] = *sp;
373 sp = NULL;
374 }
375 } else if (sp == NULL)
376 sp = cp;
377 }
378 continue;
379 }
380 /* set search list */
381 if (MATCH(buf, "search")) {
382 if (haveenv) /* skip if have from environ */
383 continue;
384 cp = buf + sizeof("search") - 1;
385 while (*cp == ' ' || *cp == '\t')
386 cp++;
387 if ((*cp == '\0') || (*cp == '\n'))
388 continue;
389 strlcpy(_resp->defdname, cp, sizeof(_resp->defdname));
390 if ((cp = strchr(_resp->defdname, '\n')) != NULL)
391 *cp = '\0';
392 /*
393 * Set search list to be blank-separated strings
394 * on rest of line.
395 */
396 cp = _resp->defdname;
397 pp = _resp->dnsrch;
398 *pp++ = cp;
399 for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) {
400 if (*cp == ' ' || *cp == '\t') {
401 *cp = 0;
402 n = 1;
403 } else if (n) {
404 *pp++ = cp;
405 n = 0;
406 }
407 }
408 /* null terminate last domain if there are excess */
409 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
410 cp++;
411 *cp = '\0';
412 *pp++ = 0;
413 havesearch = 1;
414 continue;
415 }
416 /* read nameservers to query */
417 if (MATCH(buf, "nameserver") && nserv < MAXNS) {
418 char *q;
419 struct addrinfo hints, *res;
420 char pbuf[NI_MAXSERV];
421
422 cp = buf + sizeof("nameserver") - 1;
423 while (*cp == ' ' || *cp == '\t')
424 cp++;
425 if ((*cp == '\0') || (*cp == '\n'))
426 continue;
427 for (q = cp; *q; q++) {
428 if (isspace(*q)) {
429 *q = '\0';
430 break;
431 }
432 }
433
434 /* Handle addresses enclosed in [] */
435 *pbuf = '\0';
436 if (*cp == '[') {
437 cp++;
438 if ((q = strchr(cp, ']')) == NULL)
439 continue;
440 *q++ = '\0';
441 /* Extract port, if specified */
442 if (*q++ == ':') {
443 if (strlcpy(pbuf, q, sizeof(pbuf)) >= sizeof(pbuf))
444 continue;
445 }
446 }
447 if (*pbuf == '\0')
448 snprintf(pbuf, sizeof(pbuf), "%u", NAMESERVER_PORT);
449
450 memset(&hints, 0, sizeof(hints));
451 hints.ai_flags = AI_NUMERICHOST;
452 hints.ai_socktype = SOCK_DGRAM;
453 res = NULL;
454 if (getaddrinfo(cp, pbuf, &hints, &res) == 0 &&
455 res->ai_next == NULL) {
456 if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) {
457 memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr,
458 res->ai_addrlen);
459 } else {
460 memset(&_res_extp->nsaddr_list[nserv], 0,
461 sizeof(_res_extp->nsaddr_list[nserv]));
462 }
463 if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) {
464 memcpy(&_resp->nsaddr_list[nserv], res->ai_addr,
465 res->ai_addrlen);
466 } else {
467 memset(&_resp->nsaddr_list[nserv], 0,
468 sizeof(_resp->nsaddr_list[nserv]));
469 }
470 nserv++;
471 }
472 if (res)
473 freeaddrinfo(res);
474 continue;
475 }
476#ifdef RESOLVSORT
477 if (MATCH(buf, "sortlist")) {
478 struct in_addr a;
479#ifdef INET6
480 struct in6_addr a6;
481 int m, i;
482 u_char *u;
483#endif /* INET6 */
484
485 cp = buf + sizeof("sortlist") - 1;
486 while (nsort < MAXRESOLVSORT) {
487 while (*cp == ' ' || *cp == '\t')
488 cp++;
489 if (*cp == '\0' || *cp == '\n' || *cp == ';')
490 break;
491 net = cp;
492 while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
493 isascii(*cp) && !isspace(*cp))
494 cp++;
495 n = *cp;
496 *cp = 0;
497 if (inet_aton(net, &a)) {
498 _resp->sort_list[nsort].addr = a;
499 if (ISSORTMASK(n)) {
500 *cp++ = n;
501 net = cp;
502 while (*cp && *cp != ';' &&
503 isascii(*cp) && !isspace(*cp))
504 cp++;
505 n = *cp;
506 *cp = 0;
507 if (inet_aton(net, &a)) {
508 _resp->sort_list[nsort].mask = a.s_addr;
509 } else {
510 _resp->sort_list[nsort].mask =
511 net_mask(_resp->sort_list[nsort].addr);
512 }
513 } else {
514 _resp->sort_list[nsort].mask =
515 net_mask(_resp->sort_list[nsort].addr);
516 }
517#ifdef INET6
518 _res_extp->sort_list[nsort].af = AF_INET;
519 _res_extp->sort_list[nsort].addr.ina =
520 _resp->sort_list[nsort].addr;
521 _res_extp->sort_list[nsort].mask.ina.s_addr =
522 _resp->sort_list[nsort].mask;
523#endif /* INET6 */
524 nsort++;
525 }
526#ifdef INET6
527 else if (inet_pton(AF_INET6, net, &a6) == 1) {
528 _res_extp->sort_list[nsort].af = AF_INET6;
529 _res_extp->sort_list[nsort].addr.in6a = a6;
530 u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a;
531 *cp++ = n;
532 net = cp;
533 while (*cp && *cp != ';' &&
534 isascii(*cp) && !isspace(*cp))
535 cp++;
536 m = n;
537 n = *cp;
538 *cp = 0;
539 switch (m) {
540 case '/':
541 m = atoi(net);
542 break;
543 case '&':
544 if (inet_pton(AF_INET6, net, u) == 1) {
545 m = -1;
546 break;
547 }
548 /* FALLTHROUGH */
549 default:
550 m = sizeof(struct in6_addr) * NBBY;
551 break;
552 }
553 if (m >= 0) {
554 for (i = 0; i < sizeof(struct in6_addr); i++) {
555 if (m <= 0) {
556 *u = 0;
557 } else {
558 m -= NBBY;
559 *u = (u_char)~0;
560 if (m < 0)
561 *u <<= -m;
562 }
563 u++;
564 }
565 }
566 nsort++;
567 }
568#endif /* INET6 */
569 *cp = n;
570 }
571 continue;
572 }
573#endif
574 if (MATCH(buf, "options")) {
575 res_setoptions(buf + sizeof("options") - 1, "conf");
576 continue;
577 }
578 }
579 if (nserv > 1)
580 _resp->nscount = nserv;
581#ifdef RESOLVSORT
582 _resp->nsort = nsort;
583#endif
584 (void) fclose(fp);
585 }
586 if (_resp->defdname[0] == 0 &&
587 gethostname(buf, sizeof(_resp->defdname) - 1) == 0 &&
588 (cp = strchr(buf, '.')) != NULL)
589 {
590 strlcpy(_resp->defdname, cp + 1,
591 sizeof(_resp->defdname));
592 }
593
594 /* find components of local domain that might be searched */
595 if (havesearch == 0) {
596 pp = _resp->dnsrch;
597 *pp++ = _resp->defdname;
598 *pp = NULL;
599
600#ifndef RFC1535
601 dots = 0;
602 for (cp = _resp->defdname; *cp; cp++)
603 dots += (*cp == '.');
604
605 cp = _resp->defdname;
606 while (pp < _resp->dnsrch + MAXDFLSRCH) {
607 if (dots < LOCALDOMAINPARTS)
608 break;
609 cp = strchr(cp, '.') + 1; /* we know there is one */
610 *pp++ = cp;
611 dots--;
612 }
613 *pp = NULL;
614#ifdef DEBUG
615 if (_resp->options & RES_DEBUG) {
616 printf(";; res_init()... default dnsrch list:\n");
617 for (pp = _resp->dnsrch; *pp; pp++)
618 printf(";;\t%s\n", *pp);
619 printf(";;\t..END..\n");
620 }
621#endif /* DEBUG */
622#endif /* !RFC1535 */
623 }
624
625 if (issetugid())
626 _resp->options |= RES_NOALIASES;
627 else if ((cp = getenv("RES_OPTIONS")) != NULL)
628 res_setoptions(cp, "env");
629 _resp->options |= RES_INIT;
630 return (0);
631}
632
633/* ARGSUSED */
634static void
635res_setoptions(char *options, char *source)
636{
637 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
638 char *cp = options;
639 char *endp;
640 long l;
641
642#ifdef DEBUG
643 if (_resp->options & RES_DEBUG)
644 printf(";; res_setoptions(\"%s\", \"%s\")...\n",
645 options, source);
646#endif
647 while (*cp) {
648 /* skip leading and inner runs of spaces */
649 while (*cp == ' ' || *cp == '\t')
650 cp++;
651 /* search for and process individual options */
652 if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
653 char *p = cp + sizeof("ndots:") - 1;
654 l = strtol(p, &endp, 10);
655 if (l >= 0 && endp != p &&
656 (*endp = '\0' || isspace(*endp))) {
657 if (l <= RES_MAXNDOTS)
658 _resp->ndots = l;
659 else
660 _resp->ndots = RES_MAXNDOTS;
661#ifdef DEBUG
662 if (_resp->options & RES_DEBUG)
663 printf(";;\tndots=%u\n", _resp->ndots);
664#endif
665 }
666 } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
667#ifdef DEBUG
668 if (!(_resp->options & RES_DEBUG)) {
669 printf(";; res_setoptions(\"%s\", \"%s\")..\n",
670 options, source);
671 _resp->options |= RES_DEBUG;
672 }
673 printf(";;\tdebug\n");
674#endif
675 } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
676 _resp->options |= RES_USE_INET6;
677 } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
678 _resp->options |= RES_INSECURE1;
679 } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
680 _resp->options |= RES_INSECURE2;
681 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
682 _resp->options |= RES_USE_EDNS0;
683 } else if (!strncmp(cp, "tcp", sizeof("tcp") - 1)) {
684 _resp->options |= RES_USEVC;
685 } else {
686 /* XXX - print a warning here? */
687 }
688 /* skip to next run of spaces */
689 while (*cp && *cp != ' ' && *cp != '\t')
690 cp++;
691 }
692}
693
694#ifdef RESOLVSORT
695/* XXX - should really support CIDR which means explicit masks always. */
696static u_int32_t
697net_mask(struct in_addr in) /* XXX - should really use system's version of this */
698{
699 u_int32_t i = ntohl(in.s_addr);
700
701 if (IN_CLASSA(i))
702 return (htonl(IN_CLASSA_NET));
703 else if (IN_CLASSB(i))
704 return (htonl(IN_CLASSB_NET));
705 return (htonl(IN_CLASSC_NET));
706}
707#endif
diff --git a/src/lib/libc/net/res_mkquery.c b/src/lib/libc/net/res_mkquery.c
deleted file mode 100644
index 5c6b273abe..0000000000
--- a/src/lib/libc/net/res_mkquery.c
+++ /dev/null
@@ -1,232 +0,0 @@
1/* $OpenBSD: res_mkquery.c,v 1.17 2005/08/06 20:30:04 espie Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1993
5 * -
6 * Copyright (c) 1985, 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/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/nameser.h>
58
59#include <stdio.h>
60#include <netdb.h>
61#include <resolv.h>
62#include <string.h>
63
64#include "thread_private.h"
65
66/*
67 * Form all types of queries.
68 * Returns the size of the result or -1.
69 */
70/* ARGSUSED */
71int
72res_mkquery(int op,
73 const char *dname, /* opcode of query */
74 int class, /* domain name */
75 int type, /* class and type of query */
76 const u_char *data, /* resource record data */
77 int datalen, /* length of data */
78 const u_char *newrr_in, /* new rr for modify or append */
79 u_char *buf, /* buffer to put query */
80 int buflen) /* size of buffer */
81{
82 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
83 HEADER *hp;
84 u_char *cp, *ep;
85 int n;
86 u_char *dnptrs[20], **dpp, **lastdnptr;
87
88 if (_res_init(0) == -1) {
89 h_errno = NETDB_INTERNAL;
90 return (-1);
91 }
92#ifdef DEBUG
93 if (_resp->options & RES_DEBUG)
94 printf(";; res_mkquery(%d, %s, %d, %d)\n",
95 op, dname, class, type);
96#endif
97 /*
98 * Initialize header fields.
99 *
100 * A special random number generator is used to create non predictable
101 * and non repeating ids over a long period. It also avoids reuse
102 * by switching between two distinct number cycles.
103 */
104
105 if ((buf == NULL) || (buflen < HFIXEDSZ))
106 return (-1);
107 bzero(buf, HFIXEDSZ);
108 hp = (HEADER *) buf;
109 _resp->id = res_randomid();
110 hp->id = htons(_resp->id);
111 hp->opcode = op;
112 hp->rd = (_resp->options & RES_RECURSE) != 0;
113 hp->rcode = NOERROR;
114 cp = buf + HFIXEDSZ;
115 ep = buf + buflen;
116 dpp = dnptrs;
117 *dpp++ = buf;
118 *dpp++ = NULL;
119 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
120 /*
121 * perform opcode specific processing
122 */
123 switch (op) {
124 case QUERY: /*FALLTHROUGH*/
125 case NS_NOTIFY_OP:
126 if (ep - cp < QFIXEDSZ)
127 return (-1);
128 if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
129 lastdnptr)) < 0)
130 return (-1);
131 cp += n;
132 __putshort(type, cp);
133 cp += INT16SZ;
134 __putshort(class, cp);
135 cp += INT16SZ;
136 hp->qdcount = htons(1);
137 if (op == QUERY || data == NULL)
138 break;
139 /*
140 * Make an additional record for completion domain.
141 */
142 if (ep - cp < RRFIXEDSZ)
143 return (-1);
144 n = dn_comp((char *)data, cp, ep - cp - RRFIXEDSZ, dnptrs,
145 lastdnptr);
146 if (n < 0)
147 return (-1);
148 cp += n;
149 __putshort(T_NULL, cp);
150 cp += INT16SZ;
151 __putshort(class, cp);
152 cp += INT16SZ;
153 __putlong(0, cp);
154 cp += INT32SZ;
155 __putshort(0, cp);
156 cp += INT16SZ;
157 hp->arcount = htons(1);
158 break;
159
160 case IQUERY:
161 /*
162 * Initialize answer section
163 */
164 if (ep - cp < 1 + RRFIXEDSZ + datalen)
165 return (-1);
166 *cp++ = '\0'; /* no domain name */
167 __putshort(type, cp);
168 cp += INT16SZ;
169 __putshort(class, cp);
170 cp += INT16SZ;
171 __putlong(0, cp);
172 cp += INT32SZ;
173 __putshort(datalen, cp);
174 cp += INT16SZ;
175 if (datalen) {
176 bcopy(data, cp, datalen);
177 cp += datalen;
178 }
179 hp->ancount = htons(1);
180 break;
181
182 default:
183 return (-1);
184 }
185 return (cp - buf);
186}
187
188/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
189int
190res_opt(int n0,
191 u_char *buf, /* buffer to put query */
192 int buflen, /* size of buffer */
193 int anslen) /* answer buffer length */
194{
195 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
196 HEADER *hp;
197 u_char *cp, *ep;
198
199 hp = (HEADER *) buf;
200 cp = buf + n0;
201 ep = buf + buflen;
202
203 if (ep - cp < 1 + RRFIXEDSZ)
204 return -1;
205
206 *cp++ = 0; /* "." */
207
208 __putshort(T_OPT, cp); /* TYPE */
209 cp += INT16SZ;
210 if (anslen > 0xffff)
211 anslen = 0xffff; /* limit to 16bit value */
212 __putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
213 cp += INT16SZ;
214 *cp++ = NOERROR; /* extended RCODE */
215 *cp++ = 0; /* EDNS version */
216 if (_resp->options & RES_USE_DNSSEC) {
217#ifdef DEBUG
218 if (_resp->options & RES_DEBUG)
219 printf(";; res_opt()... ENDS0 DNSSEC OK\n");
220#endif /* DEBUG */
221 __putshort(DNS_MESSAGEEXTFLAG_DO, cp); /* EDNS Z field */
222 cp += INT16SZ;
223 } else {
224 __putshort(0, cp); /* EDNS Z field */
225 cp += INT16SZ;
226 }
227 __putshort(0, cp); /* RDLEN */
228 cp += INT16SZ;
229 hp->arcount = htons(ntohs(hp->arcount) + 1);
230
231 return cp - buf;
232}
diff --git a/src/lib/libc/net/res_query.c b/src/lib/libc/net/res_query.c
deleted file mode 100644
index 1485abb2d7..0000000000
--- a/src/lib/libc/net/res_query.c
+++ /dev/null
@@ -1,403 +0,0 @@
1/* $OpenBSD: res_query.c,v 1.26 2010/06/29 21:08:54 deraadt Exp $ */
2
3/*
4 * ++Copyright++ 1988, 1993
5 * -
6 * Copyright (c) 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/types.h>
55#include <sys/param.h>
56#include <netinet/in.h>
57#include <arpa/inet.h>
58#include <arpa/nameser.h>
59
60#include <stdio.h>
61#include <netdb.h>
62#include <resolv.h>
63#include <ctype.h>
64#include <errno.h>
65#include <stdlib.h>
66#include <string.h>
67#include <unistd.h>
68
69#include "thread_private.h"
70
71#if PACKETSZ > 1024
72#define MAXPACKET PACKETSZ
73#else
74#define MAXPACKET 1024
75#endif
76
77const char *hostalias(const char *);
78int h_errno;
79extern int res_opt(int, u_char *, int, int);
80
81/*
82 * Formulate a normal query, send, and await answer.
83 * Returned answer is placed in supplied buffer "answer".
84 * Perform preliminary check of answer, returning success only
85 * if no error is indicated and the answer count is nonzero.
86 * Return the size of the response on success, -1 on error.
87 * Error number is left in h_errno.
88 *
89 * Caller must parse answer and determine whether it answers the question.
90 */
91int
92res_query(const char *name,
93 int class, /* domain name */
94 int type, /* class and type of query */
95 u_char *answer, /* buffer to put answer */
96 int anslen) /* size of answer buffer */
97{
98 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
99 union {
100 HEADER hdr;
101 u_char buf[MAXPACKET];
102 } buf;
103 HEADER *hp = (HEADER *) answer;
104 int n;
105
106 hp->rcode = NOERROR; /* default */
107
108 if (_res_init(0) == -1) {
109 h_errno = NETDB_INTERNAL;
110 return (-1);
111 }
112#ifdef DEBUG
113 if (_resp->options & RES_DEBUG)
114 printf(";; res_query(%s, %d, %d)\n", name, class, type);
115#endif
116
117 n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
118 buf.buf, sizeof(buf.buf));
119 if (n > 0 && ((_resp->options & RES_USE_EDNS0) ||
120 (_resp->options & RES_USE_DNSSEC))) {
121 n = res_opt(n, buf.buf, sizeof(buf.buf), anslen);
122 }
123
124 if (n <= 0) {
125#ifdef DEBUG
126 if (_resp->options & RES_DEBUG)
127 printf(";; res_query: mkquery failed\n");
128#endif
129 h_errno = NO_RECOVERY;
130 return (n);
131 }
132 n = res_send(buf.buf, n, answer, anslen);
133 if (n < 0) {
134#ifdef DEBUG
135 if (_resp->options & RES_DEBUG)
136 printf(";; res_query: send error\n");
137#endif
138 h_errno = TRY_AGAIN;
139 return (n);
140 }
141
142 if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
143#ifdef DEBUG
144 if (_resp->options & RES_DEBUG)
145 printf(";; rcode = %u, ancount=%u\n", hp->rcode,
146 ntohs(hp->ancount));
147#endif
148 switch (hp->rcode) {
149 case NXDOMAIN:
150 h_errno = HOST_NOT_FOUND;
151 break;
152 case SERVFAIL:
153 h_errno = TRY_AGAIN;
154 break;
155 case NOERROR:
156 h_errno = NO_DATA;
157 break;
158 case FORMERR:
159 case NOTIMP:
160 case REFUSED:
161 default:
162 h_errno = NO_RECOVERY;
163 break;
164 }
165 return (-1);
166 }
167 return (n);
168}
169
170/*
171 * Formulate a normal query, send, and retrieve answer in supplied buffer.
172 * Return the size of the response on success, -1 on error.
173 * If enabled, implement search rules until answer or unrecoverable failure
174 * is detected. Error code, if any, is left in h_errno.
175 */
176int
177res_search(const char *name,
178 int class, /* domain name */
179 int type, /* class and type of query */
180 u_char *answer, /* buffer to put answer */
181 int anslen) /* size of answer */
182{
183 const char *cp, * const *domain;
184 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
185 HEADER *hp = (HEADER *) answer;
186 u_int dots;
187 int trailing_dot, ret, saved_herrno;
188 int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
189
190 if (_res_init(0) == -1) {
191 h_errno = NETDB_INTERNAL;
192 return (-1);
193 }
194 errno = 0;
195 h_errno = HOST_NOT_FOUND; /* default, if we never query */
196 dots = 0;
197 for (cp = name; *cp; cp++)
198 dots += (*cp == '.');
199 trailing_dot = 0;
200 if (cp > name && *--cp == '.')
201 trailing_dot++;
202
203 /*
204 * if there aren't any dots, it could be a user-level alias
205 */
206 if (!dots && (cp = __hostalias(name)) != NULL)
207 return (res_query(cp, class, type, answer, anslen));
208
209 /*
210 * If there are dots in the name already, let's just give it a try
211 * 'as is'. The threshold can be set with the "ndots" option.
212 */
213 saved_herrno = -1;
214 if (dots >= _resp->ndots) {
215 ret = res_querydomain(name, NULL, class, type, answer, anslen);
216 if (ret > 0)
217 return (ret);
218 saved_herrno = h_errno;
219 tried_as_is++;
220 }
221
222 /*
223 * We do at least one level of search if
224 * - there is no dot and RES_DEFNAME is set, or
225 * - there is at least one dot, there is no trailing dot,
226 * and RES_DNSRCH is set.
227 */
228 if ((!dots && (_resp->options & RES_DEFNAMES)) ||
229 (dots && !trailing_dot && (_resp->options & RES_DNSRCH))) {
230 int done = 0;
231
232 for (domain = (const char * const *)_resp->dnsrch;
233 *domain && !done;
234 domain++) {
235
236 ret = res_querydomain(name, *domain, class, type,
237 answer, anslen);
238 if (ret > 0)
239 return (ret);
240
241 /*
242 * If no server present, give up.
243 * If name isn't found in this domain,
244 * keep trying higher domains in the search list
245 * (if that's enabled).
246 * On a NO_DATA error, keep trying, otherwise
247 * a wildcard entry of another type could keep us
248 * from finding this entry higher in the domain.
249 * If we get some other error (negative answer or
250 * server failure), then stop searching up,
251 * but try the input name below in case it's
252 * fully-qualified.
253 */
254 if (errno == ECONNREFUSED) {
255 h_errno = TRY_AGAIN;
256 return (-1);
257 }
258
259 switch (h_errno) {
260 case NO_DATA:
261 got_nodata++;
262 /* FALLTHROUGH */
263 case HOST_NOT_FOUND:
264 /* keep trying */
265 break;
266 case TRY_AGAIN:
267 if (hp->rcode == SERVFAIL) {
268 /* try next search element, if any */
269 got_servfail++;
270 break;
271 }
272 /* FALLTHROUGH */
273 default:
274 /* anything else implies that we're done */
275 done++;
276 }
277
278 /* if we got here for some reason other than DNSRCH,
279 * we only wanted one iteration of the loop, so stop.
280 */
281 if (!(_resp->options & RES_DNSRCH))
282 done++;
283 }
284 }
285
286 /* if we have not already tried the name "as is", do that now.
287 * note that we do this regardless of how many dots were in the
288 * name or whether it ends with a dot.
289 */
290 if (!tried_as_is) {
291 ret = res_querydomain(name, NULL, class, type, answer, anslen);
292 if (ret > 0)
293 return (ret);
294 }
295
296 /* if we got here, we didn't satisfy the search.
297 * if we did an initial full query, return that query's h_errno
298 * (note that we wouldn't be here if that query had succeeded).
299 * else if we ever got a nodata, send that back as the reason.
300 * else send back meaningless h_errno, that being the one from
301 * the last DNSRCH we did.
302 */
303 if (saved_herrno != -1)
304 h_errno = saved_herrno;
305 else if (got_nodata)
306 h_errno = NO_DATA;
307 else if (got_servfail)
308 h_errno = TRY_AGAIN;
309 return (-1);
310}
311
312/*
313 * Perform a call on res_query on the concatenation of name and domain,
314 * removing a trailing dot from name if domain is NULL.
315 */
316int
317res_querydomain(const char *name,
318 const char *domain,
319 int class, /* class and type of query */
320 int type,
321 u_char *answer, /* buffer to put answer */
322 int anslen) /* size of answer */
323{
324#ifdef DEBUG
325 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
326#endif
327 char nbuf[MAXDNAME*2+1+1];
328 const char *longname = nbuf;
329 int n;
330
331 if (_res_init(0) == -1) {
332 h_errno = NETDB_INTERNAL;
333 return (-1);
334 }
335#ifdef DEBUG
336 if (_resp->options & RES_DEBUG)
337 printf(";; res_querydomain(%s, %s, %d, %d)\n",
338 name, domain?domain:"<Nil>", class, type);
339#endif
340 if (domain == NULL) {
341 /*
342 * Check for trailing '.';
343 * copy without '.' if present.
344 */
345 n = strlen(name) - 1;
346 if (n != (0 - 1) && name[n] == '.' && n < sizeof(nbuf) - 1) {
347 bcopy(name, nbuf, n);
348 nbuf[n] = '\0';
349 } else
350 longname = name;
351 } else
352 snprintf(nbuf, sizeof nbuf, "%.*s.%.*s",
353 MAXDNAME, name, MAXDNAME, domain);
354
355 return (res_query(longname, class, type, answer, anslen));
356}
357
358const char *
359hostalias(const char *name)
360{
361 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
362 char *cp1, *cp2;
363 FILE *fp;
364 char *file;
365 char buf[BUFSIZ];
366 static char abuf[MAXDNAME];
367 size_t len;
368
369 if (_resp->options & RES_NOALIASES)
370 return (NULL);
371 file = getenv("HOSTALIASES");
372 if (issetugid() != 0 || file == NULL || (fp = fopen(file, "r")) == NULL)
373 return (NULL);
374 setbuf(fp, NULL);
375 while ((cp1 = fgetln(fp, &len)) != NULL) {
376 if (cp1[len-1] == '\n')
377 len--;
378 if (len >= sizeof(buf) || len == 0)
379 continue;
380 (void)memcpy(buf, cp1, len);
381 buf[len] = '\0';
382
383 for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1)
384 ;
385 if (!*cp1)
386 break;
387 *cp1 = '\0';
388 if (!strcasecmp(buf, name)) {
389 while (isspace(*++cp1))
390 ;
391 if (!*cp1)
392 break;
393 for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2)
394 ;
395 *cp2 = '\0';
396 strlcpy(abuf, cp1, sizeof(abuf));
397 fclose(fp);
398 return (abuf);
399 }
400 }
401 fclose(fp);
402 return (NULL);
403}
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
deleted file mode 100644
index 09b1385892..0000000000
--- a/src/lib/libc/net/res_send.c
+++ /dev/null
@@ -1,853 +0,0 @@
1/* $OpenBSD: res_send.c,v 1.21 2008/05/11 05:03:03 brad Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
6 * Copyright (c) 1985, 1989, 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#ifndef INET6
55#define INET6
56#endif
57
58 /* change this to "0"
59 * if you talk to a lot
60 * of multi-homed SunOS
61 * ("broken") name servers.
62 */
63#define CHECK_SRVR_ADDR 1 /* XXX - should be in options.h */
64
65/*
66 * Send query to name server and wait for reply.
67 */
68
69#include <sys/types.h>
70#include <sys/param.h>
71#include <sys/time.h>
72#include <sys/socket.h>
73#include <sys/uio.h>
74#include <netinet/in.h>
75#include <arpa/nameser.h>
76#include <arpa/inet.h>
77
78#include <errno.h>
79#include <netdb.h>
80#include <poll.h>
81#include <resolv.h>
82#include <stdio.h>
83#include <stdlib.h>
84#include <string.h>
85#include <unistd.h>
86
87#include "thread_private.h"
88
89static int s = -1; /* socket used for communications */
90static int connected = 0; /* is the socket connected */
91static int vc = 0; /* is the socket a virtual ciruit? */
92static int af = 0; /* address family of socket */
93
94#define CAN_RECONNECT 1
95
96#ifndef DEBUG
97# define Dprint(cond, args) /*empty*/
98# define DprintQ(cond, args, query, size) /*empty*/
99# define Aerror(file, string, error, address) /*empty*/
100# define Perror(file, string, error) /*empty*/
101#else
102# define Dprint(cond, args) if (cond) {fprintf args;} else {}
103# define DprintQ(cond, args, query, size) if (cond) {\
104 fprintf args;\
105 __fp_nquery(query, size, stdout);\
106 } else {}
107static char abuf[NI_MAXHOST];
108static char pbuf[NI_MAXSERV];
109static void Aerror(FILE *, char *, int, struct sockaddr *);
110static void Perror(FILE *, char *, int);
111
112 static void
113 Aerror(FILE *file, char *string, int error, struct sockaddr *address)
114 {
115 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
116 int save = errno;
117
118 if (_resp->options & RES_DEBUG) {
119 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
120 pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
121 strlcpy(abuf, "?", sizeof(abuf));
122 strlcpy(pbuf, "?", sizeof(pbuf));
123 }
124 fprintf(file, "res_send: %s ([%s].%s): %s\n",
125 string, abuf, pbuf, strerror(error));
126 }
127 errno = save;
128 }
129 static void
130 Perror(FILE *file, char *string, int error)
131 {
132 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
133 int save = errno;
134
135 if (_resp->options & RES_DEBUG) {
136 fprintf(file, "res_send: %s: %s\n",
137 string, strerror(error));
138 }
139 errno = save;
140 }
141#endif
142
143static res_send_qhook Qhook = NULL;
144static res_send_rhook Rhook = NULL;
145
146void
147res_send_setqhook(res_send_qhook hook)
148{
149
150 Qhook = hook;
151}
152
153void
154res_send_setrhook(res_send_rhook hook)
155{
156
157 Rhook = hook;
158}
159
160#ifdef INET6
161static struct sockaddr * get_nsaddr(size_t);
162
163/*
164 * pick appropriate nsaddr_list for use. see res_init() for initialization.
165 */
166static struct sockaddr *
167get_nsaddr(size_t n)
168{
169 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
170 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
171 &_res_ext);
172
173 if (!_resp->nsaddr_list[n].sin_family) {
174 /*
175 * - _res_extp->nsaddr_list[n] holds an address that is larger
176 * than struct sockaddr, and
177 * - user code did not update _resp->nsaddr_list[n].
178 */
179 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
180 } else {
181 /*
182 * - user code updated _res.nsaddr_list[n], or
183 * - _resp->nsaddr_list[n] has the same content as
184 * _res_extp->nsaddr_list[n].
185 */
186 return (struct sockaddr *)&_resp->nsaddr_list[n];
187 }
188}
189#else
190#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
191#endif
192
193/* int
194 * res_isourserver(ina)
195 * looks up "ina" in _resp->ns_addr_list[]
196 * returns:
197 * 0 : not found
198 * >0 : found
199 * author:
200 * paul vixie, 29may94
201 */
202int
203res_isourserver(const struct sockaddr_in *inp)
204{
205 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
206#ifdef INET6
207 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
208 const struct sockaddr_in6 *srv6;
209#endif
210 const struct sockaddr_in *srv;
211 int ns, ret;
212
213 ret = 0;
214 switch (inp->sin_family) {
215#ifdef INET6
216 case AF_INET6:
217 for (ns = 0; ns < _resp->nscount; ns++) {
218 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
219 if (srv6->sin6_family == in6p->sin6_family &&
220 srv6->sin6_port == in6p->sin6_port &&
221 srv6->sin6_scope_id == in6p->sin6_scope_id &&
222 (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
223 IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr,
224 &in6p->sin6_addr))) {
225 ret++;
226 break;
227 }
228 }
229 break;
230#endif
231 case AF_INET:
232 for (ns = 0; ns < _resp->nscount; ns++) {
233 srv = (struct sockaddr_in *)get_nsaddr(ns);
234 if (srv->sin_family == inp->sin_family &&
235 srv->sin_port == inp->sin_port &&
236 (srv->sin_addr.s_addr == INADDR_ANY ||
237 srv->sin_addr.s_addr == inp->sin_addr.s_addr)) {
238 ret++;
239 break;
240 }
241 }
242 break;
243 }
244 return (ret);
245}
246
247/* int
248 * res_nameinquery(name, type, class, buf, eom)
249 * look for (name,type,class) in the query section of packet (buf,eom)
250 * returns:
251 * -1 : format error
252 * 0 : not found
253 * >0 : found
254 * author:
255 * paul vixie, 29may94
256 */
257int
258res_nameinquery(const char *name, int type, int class, const u_char *buf,
259 const u_char *eom)
260{
261 const u_char *cp = buf + HFIXEDSZ;
262 int qdcount = ntohs(((HEADER*)buf)->qdcount);
263
264 while (qdcount-- > 0) {
265 char tname[MAXDNAME+1];
266 int n, ttype, tclass;
267
268 n = dn_expand(buf, eom, cp, tname, sizeof tname);
269 if (n < 0)
270 return (-1);
271 cp += n;
272 ttype = _getshort(cp); cp += INT16SZ;
273 tclass = _getshort(cp); cp += INT16SZ;
274 if (ttype == type &&
275 tclass == class &&
276 strcasecmp(tname, name) == 0)
277 return (1);
278 }
279 return (0);
280}
281
282/* int
283 * res_queriesmatch(buf1, eom1, buf2, eom2)
284 * is there a 1:1 mapping of (name,type,class)
285 * in (buf1,eom1) and (buf2,eom2)?
286 * returns:
287 * -1 : format error
288 * 0 : not a 1:1 mapping
289 * >0 : is a 1:1 mapping
290 * author:
291 * paul vixie, 29may94
292 */
293int
294res_queriesmatch(const u_char *buf1, const u_char *eom1, const u_char *buf2,
295 const u_char *eom2)
296{
297 const u_char *cp = buf1 + HFIXEDSZ;
298 int qdcount = ntohs(((HEADER*)buf1)->qdcount);
299
300 if (qdcount != ntohs(((HEADER*)buf2)->qdcount))
301 return (0);
302 while (qdcount-- > 0) {
303 char tname[MAXDNAME+1];
304 int n, ttype, tclass;
305
306 n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
307 if (n < 0)
308 return (-1);
309 cp += n;
310 ttype = _getshort(cp); cp += INT16SZ;
311 tclass = _getshort(cp); cp += INT16SZ;
312 if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
313 return (0);
314 }
315 return (1);
316}
317
318int
319res_send(const u_char *buf, int buflen, u_char *ans, int anssiz)
320{
321 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
322 HEADER *hp = (HEADER *) buf;
323 HEADER *anhp = (HEADER *) ans;
324 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
325 int n;
326 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
327
328 if (_res_init(0) == -1) {
329 /* errno should have been set by res_init() in this case. */
330 return (-1);
331 }
332 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
333 (stdout, ";; res_send()\n"), buf, buflen);
334 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
335 gotsomewhere = 0;
336 connreset = 0;
337 terrno = ETIMEDOUT;
338 badns = 0;
339
340 /*
341 * Send request, RETRY times, or until successful
342 */
343 for (try = 0; try < _resp->retry; try++) {
344 for (ns = 0; ns < _resp->nscount; ns++) {
345 struct sockaddr *nsap = get_nsaddr(ns);
346 socklen_t salen;
347
348 if (nsap->sa_len)
349 salen = nsap->sa_len;
350#ifdef INET6
351 else if (nsap->sa_family == AF_INET6)
352 salen = sizeof(struct sockaddr_in6);
353#endif
354 else if (nsap->sa_family == AF_INET)
355 salen = sizeof(struct sockaddr_in);
356 else
357 salen = 0; /*unknown, die on connect*/
358
359 same_ns:
360 if (badns & (1 << ns)) {
361 res_close();
362 goto next_ns;
363 }
364
365 if (Qhook) {
366 int done = 0, loops = 0;
367
368 do {
369 res_sendhookact act;
370
371 act = (*Qhook)((struct sockaddr_in **)&nsap,
372 &buf, &buflen,
373 ans, anssiz, &resplen);
374 switch (act) {
375 case res_goahead:
376 done = 1;
377 break;
378 case res_nextns:
379 res_close();
380 goto next_ns;
381 case res_done:
382 return (resplen);
383 case res_modified:
384 /* give the hook another try */
385 if (++loops < 42) /*doug adams*/
386 break;
387 /*FALLTHROUGH*/
388 case res_error:
389 /*FALLTHROUGH*/
390 default:
391 return (-1);
392 }
393 } while (!done);
394 }
395
396 Dprint((_resp->options & RES_DEBUG) &&
397 getnameinfo(nsap, salen, abuf, sizeof(abuf),
398 NULL, 0, NI_NUMERICHOST) == 0,
399 (stdout, ";; Querying server (# %d) address = %s\n",
400 ns + 1, abuf));
401
402 if (v_circuit) {
403 int truncated;
404 struct iovec iov[2];
405 u_short len;
406 u_char *cp;
407
408 /*
409 * Use virtual circuit;
410 * at most one attempt per server.
411 */
412 try = _resp->retry;
413 truncated = 0;
414 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
415 if (s >= 0)
416 res_close();
417
418 af = nsap->sa_family;
419 s = socket(af, SOCK_STREAM, 0);
420 if (s < 0) {
421 terrno = errno;
422 Perror(stderr, "socket(vc)", errno);
423#if 0
424 return (-1);
425#else
426 badns |= (1 << ns);
427 res_close();
428 goto next_ns;
429#endif
430 }
431 errno = 0;
432 if (connect(s, nsap, salen) < 0) {
433 terrno = errno;
434 Aerror(stderr, "connect/vc",
435 errno, nsap);
436 badns |= (1 << ns);
437 res_close();
438 goto next_ns;
439 }
440 vc = 1;
441 }
442 /*
443 * Send length & message
444 */
445 putshort((u_short)buflen, (u_char*)&len);
446 iov[0].iov_base = (caddr_t)&len;
447 iov[0].iov_len = INT16SZ;
448 iov[1].iov_base = (caddr_t)buf;
449 iov[1].iov_len = buflen;
450 if (writev(s, iov, 2) != (INT16SZ + buflen)) {
451 terrno = errno;
452 Perror(stderr, "write failed", errno);
453 badns |= (1 << ns);
454 res_close();
455 goto next_ns;
456 }
457 /*
458 * Receive length & response
459 */
460 read_len:
461 cp = ans;
462 len = INT16SZ;
463 while ((n = read(s, (char *)cp, (int)len)) > 0) {
464 cp += n;
465 if ((len -= n) <= 0)
466 break;
467 }
468 if (n <= 0) {
469 terrno = errno;
470 Perror(stderr, "read failed", errno);
471 res_close();
472 /*
473 * A long running process might get its TCP
474 * connection reset if the remote server was
475 * restarted. Requery the server instead of
476 * trying a new one. When there is only one
477 * server, this means that a query might work
478 * instead of failing. We only allow one reset
479 * per query to prevent looping.
480 */
481 if (terrno == ECONNRESET && !connreset) {
482 connreset = 1;
483 res_close();
484 goto same_ns;
485 }
486 res_close();
487 goto next_ns;
488 }
489 resplen = _getshort(ans);
490 if (resplen > anssiz) {
491 Dprint(_resp->options & RES_DEBUG,
492 (stdout, ";; response truncated\n")
493 );
494 truncated = 1;
495 len = anssiz;
496 } else
497 len = resplen;
498 cp = ans;
499 while (len != 0 &&
500 (n = read(s, (char *)cp, (int)len)) > 0) {
501 cp += n;
502 len -= n;
503 }
504 if (n <= 0) {
505 terrno = errno;
506 Perror(stderr, "read(vc)", errno);
507 res_close();
508 goto next_ns;
509 }
510 if (truncated) {
511 /*
512 * Flush rest of answer
513 * so connection stays in synch.
514 */
515 anhp->tc = 1;
516 len = resplen - anssiz;
517 while (len != 0) {
518 char junk[PACKETSZ];
519
520 n = (len > sizeof(junk)
521 ? sizeof(junk)
522 : len);
523 if ((n = read(s, junk, n)) > 0)
524 len -= n;
525 else
526 break;
527 }
528 }
529 /*
530 * The calling applicating has bailed out of
531 * a previous call and failed to arrange to have
532 * the circuit closed or the server has got
533 * itself confused. Anyway drop the packet and
534 * wait for the correct one.
535 */
536 if (hp->id != anhp->id) {
537 DprintQ((_resp->options & RES_DEBUG) ||
538 (_resp->pfcode & RES_PRF_REPLY),
539 (stdout, ";; old answer (unexpected):\n"),
540 ans, (resplen>anssiz)?anssiz:resplen);
541 goto read_len;
542 }
543 } else {
544 /*
545 * Use datagrams.
546 */
547 struct pollfd pfd;
548 int timeout;
549 struct sockaddr_storage from;
550 socklen_t fromlen;
551
552 if ((s < 0) || vc || (af != nsap->sa_family)) {
553 if (vc)
554 res_close();
555 af = nsap->sa_family;
556 s = socket(af, SOCK_DGRAM, 0);
557 if (s < 0) {
558#if !CAN_RECONNECT
559 bad_dg_sock:
560#endif
561 terrno = errno;
562 Perror(stderr, "socket(dg)", errno);
563#if 0
564 return (-1);
565#else
566 badns |= (1 << ns);
567 res_close();
568 goto next_ns;
569#endif
570 }
571#ifdef IPV6_MINMTU
572 if (af == AF_INET6) {
573 const int yes = 1;
574 (void)setsockopt(s, IPPROTO_IPV6,
575 IPV6_USE_MIN_MTU, &yes,
576 sizeof(yes));
577 }
578#endif
579 connected = 0;
580 }
581 /*
582 * On a 4.3BSD+ machine (client and server,
583 * actually), sending to a nameserver datagram
584 * port with no nameserver will cause an
585 * ICMP port unreachable message to be returned.
586 * If our datagram socket is "connected" to the
587 * server, we get an ECONNREFUSED error on the next
588 * socket operation, and poll returns if the
589 * error message is received. We can thus detect
590 * the absence of a nameserver without timing out.
591 * If we have sent queries to at least two servers,
592 * however, we don't want to remain connected,
593 * as we wish to receive answers from the first
594 * server to respond.
595 */
596 if (!(_resp->options & RES_INSECURE1) &&
597 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
598 /*
599 * Connect only if we are sure we won't
600 * receive a response from another server.
601 */
602 if (!connected) {
603 if (connect(s, nsap, salen) < 0) {
604 Aerror(stderr,
605 "connect(dg)",
606 errno, nsap);
607 badns |= (1 << ns);
608 res_close();
609 goto next_ns;
610 }
611 connected = 1;
612 }
613 if (send(s, (char*)buf, buflen, 0) != buflen) {
614 Perror(stderr, "send", errno);
615 badns |= (1 << ns);
616 res_close();
617 goto next_ns;
618 }
619 } else {
620 /*
621 * Disconnect if we want to listen
622 * for responses from more than one server.
623 */
624 if (connected) {
625#if CAN_RECONNECT
626#ifdef INET6
627 /* XXX: any errornous address */
628#endif /* INET6 */
629 struct sockaddr_in no_addr;
630
631 no_addr.sin_family = AF_INET;
632 no_addr.sin_addr.s_addr = INADDR_ANY;
633 no_addr.sin_port = 0;
634 (void) connect(s,
635 (struct sockaddr *)
636 &no_addr,
637 sizeof(no_addr));
638#else
639 int s1 = socket(af, SOCK_DGRAM,0);
640 if (s1 < 0)
641 goto bad_dg_sock;
642 (void) dup2(s1, s);
643 (void) close(s1);
644 Dprint(_resp->options & RES_DEBUG,
645 (stdout, ";; new DG socket\n"))
646#endif
647#ifdef IPV6_MINMTU
648 if (af == AF_INET6) {
649 const int yes = 1;
650 (void)setsockopt(s, IPPROTO_IPV6,
651 IPV6_USE_MIN_MTU, &yes,
652 sizeof(yes));
653 }
654#endif
655 connected = 0;
656 errno = 0;
657 }
658 if (sendto(s, (char*)buf, buflen, 0,
659 nsap, salen) != buflen) {
660 Aerror(stderr, "sendto", errno, nsap);
661 badns |= (1 << ns);
662 res_close();
663 goto next_ns;
664 }
665 }
666
667 /*
668 * Wait for reply
669 */
670 timeout = 1000 * (_resp->retrans << try);
671 if (try > 0)
672 timeout /= _resp->nscount;
673 if (timeout < 1000)
674 timeout = 1000;
675 wait:
676 pfd.fd = s;
677 pfd.events = POLLIN;
678 n = poll(&pfd, 1, timeout);
679 if (n < 0) {
680 if (errno == EINTR)
681 goto wait;
682 Perror(stderr, "poll", errno);
683 res_close();
684 goto next_ns;
685 }
686 if (n == 0) {
687 /*
688 * timeout
689 */
690 Dprint(_resp->options & RES_DEBUG,
691 (stdout, ";; timeout\n"));
692 gotsomewhere = 1;
693 res_close();
694 goto next_ns;
695 }
696 errno = 0;
697 fromlen = sizeof(from);
698 resplen = recvfrom(s, (char*)ans, anssiz, 0,
699 (struct sockaddr *)&from, &fromlen);
700 if (resplen <= 0) {
701 Perror(stderr, "recvfrom", errno);
702 res_close();
703 goto next_ns;
704 }
705 gotsomewhere = 1;
706 if (hp->id != anhp->id) {
707 /*
708 * response from old query, ignore it.
709 * XXX - potential security hazard could
710 * be detected here.
711 */
712 DprintQ((_resp->options & RES_DEBUG) ||
713 (_resp->pfcode & RES_PRF_REPLY),
714 (stdout, ";; old answer:\n"),
715 ans, (resplen>anssiz)?anssiz:resplen);
716 goto wait;
717 }
718#if CHECK_SRVR_ADDR
719 if (!(_resp->options & RES_INSECURE1) &&
720 !res_isourserver((struct sockaddr_in *)&from)) {
721 /*
722 * response from wrong server? ignore it.
723 * XXX - potential security hazard could
724 * be detected here.
725 */
726 DprintQ((_resp->options & RES_DEBUG) ||
727 (_resp->pfcode & RES_PRF_REPLY),
728 (stdout, ";; not our server:\n"),
729 ans, (resplen>anssiz)?anssiz:resplen);
730 goto wait;
731 }
732#endif
733 if (!(_resp->options & RES_INSECURE2) &&
734 !res_queriesmatch(buf, buf + buflen,
735 ans, ans + anssiz)) {
736 /*
737 * response contains wrong query? ignore it.
738 * XXX - potential security hazard could
739 * be detected here.
740 */
741 DprintQ((_resp->options & RES_DEBUG) ||
742 (_resp->pfcode & RES_PRF_REPLY),
743 (stdout, ";; wrong query name:\n"),
744 ans, (resplen>anssiz)?anssiz:resplen);
745 goto wait;
746 }
747 if (anhp->rcode == SERVFAIL ||
748 anhp->rcode == NOTIMP ||
749 anhp->rcode == REFUSED) {
750 DprintQ(_resp->options & RES_DEBUG,
751 (stdout, "server rejected query:\n"),
752 ans, (resplen>anssiz)?anssiz:resplen);
753 badns |= (1 << ns);
754 res_close();
755 /* don't retry if called from dig */
756 if (!_resp->pfcode)
757 goto next_ns;
758 }
759 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
760 /*
761 * get rest of answer;
762 * use TCP with same server.
763 */
764 Dprint(_resp->options & RES_DEBUG,
765 (stdout, ";; truncated answer\n"));
766 v_circuit = 1;
767 res_close();
768 goto same_ns;
769 }
770 } /*if vc/dg*/
771 Dprint((_resp->options & RES_DEBUG) ||
772 ((_resp->pfcode & RES_PRF_REPLY) &&
773 (_resp->pfcode & RES_PRF_HEAD1)),
774 (stdout, ";; got answer:\n"));
775 DprintQ((_resp->options & RES_DEBUG) ||
776 (_resp->pfcode & RES_PRF_REPLY),
777 (stdout, "%s", ""),
778 ans, (resplen>anssiz)?anssiz:resplen);
779 /*
780 * If using virtual circuits, we assume that the first server
781 * is preferred over the rest (i.e. it is on the local
782 * machine) and only keep that one open.
783 * If we have temporarily opened a virtual circuit,
784 * or if we haven't been asked to keep a socket open,
785 * close the socket.
786 */
787 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
788 !(_resp->options & RES_STAYOPEN)) {
789 res_close();
790 }
791 if (Rhook) {
792 int done = 0, loops = 0;
793
794 do {
795 res_sendhookact act;
796
797 act = (*Rhook)((struct sockaddr_in *)nsap,
798 buf, buflen,
799 ans, anssiz, &resplen);
800 switch (act) {
801 case res_goahead:
802 case res_done:
803 done = 1;
804 break;
805 case res_nextns:
806 res_close();
807 goto next_ns;
808 case res_modified:
809 /* give the hook another try */
810 if (++loops < 42) /*doug adams*/
811 break;
812 /*FALLTHROUGH*/
813 case res_error:
814 /*FALLTHROUGH*/
815 default:
816 return (-1);
817 }
818 } while (!done);
819
820 }
821 return (resplen);
822 next_ns: ;
823 } /*foreach ns*/
824 } /*foreach retry*/
825 res_close();
826 if (!v_circuit) {
827 if (!gotsomewhere)
828 errno = ECONNREFUSED; /* no nameservers found */
829 else
830 errno = ETIMEDOUT; /* no answer obtained */
831 } else
832 errno = terrno;
833 return (-1);
834}
835
836/*
837 * This routine is for closing the socket if a virtual circuit is used and
838 * the program wants to close it. This provides support for endhostent()
839 * which expects to close the socket.
840 *
841 * This routine is not expected to be user visible.
842 */
843void
844res_close(void)
845{
846 if (s >= 0) {
847 (void) close(s);
848 s = -1;
849 connected = 0;
850 vc = 0;
851 af = 0;
852 }
853}
diff --git a/src/lib/libc/net/sethostent.c b/src/lib/libc/net/sethostent.c
deleted file mode 100644
index 6f6d0e405a..0000000000
--- a/src/lib/libc/net/sethostent.c
+++ /dev/null
@@ -1,57 +0,0 @@
1/* $OpenBSD: sethostent.c,v 1.9 2005/08/06 20:30:04 espie Exp $ */
2/*
3 * Copyright (c) 1985, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/param.h>
32#include <netinet/in.h>
33#include <arpa/nameser.h>
34#include <netdb.h>
35#include <resolv.h>
36
37#include "thread_private.h"
38
39void
40sethostent(int stayopen)
41{
42 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
43
44 if (_res_init(0) == -1)
45 return;
46 if (stayopen)
47 _resp->options |= RES_STAYOPEN | RES_USEVC;
48}
49
50void
51endhostent(void)
52{
53 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
54
55 _resp->options &= ~(RES_STAYOPEN | RES_USEVC);
56 res_close();
57}