1 /* vi: set sw=4 ts=4: */
2 /* resolv.c: DNS Resolver
4 * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>,
5 * The Silver Hammer Group, Ltd.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
13 * Portions Copyright (c) 1985, 1993
14 * The Regents of the University of California. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
43 * Permission to use, copy, modify, and distribute this software for any
44 * purpose with or without fee is hereby granted, provided that the above
45 * copyright notice and this permission notice appear in all copies, and that
46 * the name of Digital Equipment Corporation not be used in advertising or
47 * publicity pertaining to distribution of the document or software without
48 * specific, written prior permission.
50 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
51 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
52 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
53 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
54 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
55 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
56 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
60 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
62 * Permission to use, copy, modify, and distribute this software for any
63 * purpose with or without fee is hereby granted, provided that the above
64 * copyright notice and this permission notice appear in all copies.
66 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
67 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
68 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
69 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
70 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
71 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
72 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
76 * 5-Oct-2000 W. Greathouse wgreathouse@smva.com
77 * Fix memory leak and memory corruption.
78 * -- Every name resolution resulted in
79 * a new parse of resolv.conf and new
80 * copy of nameservers allocated by
82 * -- Every name resolution resulted in
83 * a new read of resolv.conf without
84 * resetting index from prior read...
85 * resulting in exceeding array bounds.
87 * Limit nameservers read from resolv.conf.
88 * Add "search" domains from resolv.conf.
89 * Some systems will return a security
90 * signature along with query answer for
91 * dynamic DNS entries -- skip/ignore this answer.
92 * Include arpa/nameser.h for defines.
95 * 20-Jun-2001 Michal Moskal <malekith@pld.org.pl>
96 * partial IPv6 support (i.e. gethostbyname2() and resolve_address2()
97 * functions added), IPv6 nameservers are also supported.
99 * 6-Oct-2001 Jari Korva <jari.korva@iki.fi>
100 * more IPv6 support (IPv6 support for gethostbyaddr();
101 * address family parameter and improved IPv6 support for get_hosts_byname
102 * and read_etc_hosts; getnameinfo() port from glibc; defined
103 * defined ip6addr_any and in6addr_loopback)
105 * 2-Feb-2002 Erik Andersen <andersen@codepoet.org>
106 * Added gethostent(), sethostent(), and endhostent()
108 * 17-Aug-2002 Manuel Novoa III <mjn3@codepoet.org>
109 * Fixed __read_etc_hosts_r to return alias list, and modified buffer
110 * allocation accordingly. See MAX_ALIASES and ALIAS_DIM below.
111 * This fixes the segfault in the Python 2.2.1 socket test.
113 * 04-Jan-2003 Jay Kulpinski <jskulpin@berkshire.rr.com>
114 * Fixed __decode_dotted to count the terminating null character
117 * 02-Oct-2003 Tony J. White <tjw@tjw.org>
118 * Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(),
119 * and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools
122 * 7-Sep-2004 Erik Andersen <andersen@codepoet.org>
123 * Added gethostent_r()
125 * 2008, 2009 Denys Vlasenko <vda.linux@googlemail.com>
126 * Cleanups, fixes, readability, more cleanups and more fixes.
128 * March 2010 Bernhard Reutner-Fischer
129 * Switch to common config parser
132 * The whole resolver code has several (severe) problems:
133 * - it doesn't even build without IPv4, i.e. !UCLIBC_HAS_IPV4 but only IPv6
134 * - it is way too big
136 * Both points above are considered bugs, patches/reimplementations welcome.
140 Whenever an octet represents a numeric quantity, the left most bit
141 in the diagram is the high order or most significant bit.
142 That is, the bit labeled 0 is the most significant bit.
145 4.1.1. Header section format
146 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
147 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
149 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
150 |QR| OPCODE |AA|TC|RD|RA| 0 0 0| RCODE |
151 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
153 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
155 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
157 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
159 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
160 ID 16 bit random identifier assigned by querying peer.
161 Used to match query/response.
162 QR message is a query (0), or a response (1).
163 OPCODE 0 standard query (QUERY)
164 1 inverse query (IQUERY)
165 2 server status request (STATUS)
166 AA Authoritative Answer - this bit is valid in responses.
167 Responding name server is an authority for the domain name
168 in question section. Answer section may have multiple owner names
169 because of aliases. The AA bit corresponds to the name which matches
170 the query name, or the first owner name in the answer section.
171 TC TrunCation - this message was truncated.
172 RD Recursion Desired - this bit may be set in a query and
173 is copied into the response. If RD is set, it directs
174 the name server to pursue the query recursively.
175 Recursive query support is optional.
176 RA Recursion Available - this be is set or cleared in a
177 response, and denotes whether recursive query support is
178 available in the name server.
182 2 Server failure - server was unable to process the query
183 due to a problem with the name server.
184 3 Name Error - meaningful only for responses from
185 an authoritative name server. The referenced domain name
189 QDCOUNT number of entries in the question section.
190 ANCOUNT number of records in the answer section.
191 NSCOUNT number of records in the authority records section.
192 ARCOUNT number of records in the additional records section.
194 4.1.2. Question section format
196 The section contains QDCOUNT (usually 1) entries, each of this format:
197 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
198 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
201 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
203 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
205 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
206 QNAME a domain name represented as a sequence of labels, where
207 each label consists of a length octet followed by that
208 number of octets. The domain name terminates with the
209 zero length octet for the null label of the root. Note
210 that this field may be an odd number of octets; no
212 QTYPE a two octet type of the query.
213 1 a host address [REQ_A const]
214 2 an authoritative name server
215 3 a mail destination (Obsolete - use MX)
216 4 a mail forwarder (Obsolete - use MX)
217 5 the canonical name for an alias
218 6 marks the start of a zone of authority
219 7 a mailbox domain name (EXPERIMENTAL)
220 8 a mail group member (EXPERIMENTAL)
221 9 a mail rename domain name (EXPERIMENTAL)
222 10 a null RR (EXPERIMENTAL)
223 11 a well known service description
224 12 a domain name pointer [REQ_PTR const]
226 14 mailbox or mail list information
230 252 a request for a transfer of an entire zone
231 253 a request for mailbox-related records (MB, MG or MR)
232 254 a request for mail agent RRs (Obsolete - see MX)
233 255 a request for all records
234 QCLASS a two octet code that specifies the class of the query.
236 (others are historic only)
239 4.1.3. Resource record format
241 The answer, authority, and additional sections all share the same format:
242 a variable number of resource records, where the number of records
243 is specified in the corresponding count field in the header.
244 Each resource record has this format:
245 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
246 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
249 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
251 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
253 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
256 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
258 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
261 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
262 NAME a domain name to which this resource record pertains.
263 TYPE two octets containing one of the RR type codes. This
264 field specifies the meaning of the data in the RDATA field.
265 CLASS two octets which specify the class of the data in the RDATA field.
266 TTL a 32 bit unsigned integer that specifies the time interval
267 (in seconds) that the record may be cached.
268 RDLENGTH a 16 bit integer, length in octets of the RDATA field.
269 RDATA a variable length string of octets that describes the resource.
270 The format of this information varies according to the TYPE
271 and CLASS of the resource record.
272 If the TYPE is A and the CLASS is IN, it's a 4 octet IP address.
274 4.1.4. Message compression
276 In order to reduce the size of messages, domain names can be compressed.
277 An entire domain name or a list of labels at the end of a domain name
278 is replaced with a pointer to a prior occurance of the same name.
280 The pointer takes the form of a two octet sequence:
281 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
283 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
284 The first two bits are ones. This allows a pointer to be distinguished
285 from a label, since the label must begin with two zero bits because
286 labels are restricted to 63 octets or less. The OFFSET field specifies
287 an offset from the start of the message (i.e., the first octet
288 of the ID field in the domain header).
289 A zero offset specifies the first byte of the ID field, etc.
290 Domain name in a message can be represented as either:
291 - a sequence of labels ending in a zero octet
293 - a sequence of labels ending with a pointer
298 #include <stdio_ext.h>
302 #include <sys/poll.h>
303 #include <sys/socket.h>
304 #include <sys/types.h>
305 #include <sys/time.h>
306 #include <netinet/in.h>
307 #include <arpa/inet.h>
315 #include <arpa/nameser.h>
316 #include <sys/utsname.h>
318 #include <sys/stat.h>
319 #include <sys/param.h>
320 #include <bits/uClibc_mutex.h>
321 #include "internal/parse_config.h"
323 /* poll() is not supported in kernel <= 2.0, therefore if __NR_poll is
324 * not available, we assume an old Linux kernel is in use and we will
325 * use select() instead. */
326 #include <sys/syscall.h>
331 #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__
332 #define IF_HAS_BOTH(...) __VA_ARGS__
334 #define IF_HAS_BOTH(...)
338 #define MAX_RECURSE 5
339 #define MAXALIASES (4)
340 /* 1:ip + 1:full + MAX_ALIASES:aliases + 1:NULL */
341 #define ALIAS_DIM (2 + MAXALIASES + 1)
342 #define BUFSZ (80) /* one line */
344 #define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
345 #define DNS_LABELTYPE_BITSTRING 0x41
351 #define DPRINTF(X,args...) fprintf(stderr, X, ##args)
353 #define DPRINTF(X,args...)
356 /* Make sure the incoming char * buffer is aligned enough to handle our random
357 * structures. This define is the same as we use for malloc alignment (which
358 * has same requirements). The offset is the number of bytes we need to adjust
359 * in order to attain desired alignment.
361 #define ALIGN_ATTR __alignof__(double __attribute_aligned__ (sizeof(size_t)))
362 #define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % ALIGN_ATTR)
366 struct resolv_header
{
368 int qr
, opcode
, aa
, tc
, rd
, ra
, rcode
;
375 struct resolv_question
{
381 struct resolv_answer
{
387 const unsigned char *rdata
;
394 enum etc_hosts_action
{
395 GET_HOSTS_BYNAME
= 0,
400 typedef union sockaddr46_t
{
402 #ifdef __UCLIBC_HAS_IPV4__
403 struct sockaddr_in sa4
;
405 #ifdef __UCLIBC_HAS_IPV6__
406 struct sockaddr_in6 sa6
;
411 __UCLIBC_MUTEX_EXTERN(__resolv_lock
) attribute_hidden
;
413 /* Protected by __resolv_lock */
414 extern void (*__res_sync
)(void) attribute_hidden
;
415 /*extern uint32_t __resolv_opts attribute_hidden; */
416 extern uint8_t __resolv_timeout attribute_hidden
;
417 extern uint8_t __resolv_attempts attribute_hidden
;
418 extern unsigned __nameservers attribute_hidden
;
419 extern unsigned __searchdomains attribute_hidden
;
420 extern sockaddr46_t
*__nameserver attribute_hidden
;
421 extern char **__searchdomain attribute_hidden
;
422 #ifdef __UCLIBC_HAS_IPV4__
423 extern const struct sockaddr_in __local_nameserver attribute_hidden
;
425 extern const struct sockaddr_in6 __local_nameserver attribute_hidden
;
428 #define MAXLEN_searchdomain 128
431 /* prototypes for internal functions */
432 extern void endhostent_unlocked(void) attribute_hidden
;
433 extern int __get_hosts_byname_r(const char *name
,
435 struct hostent
*result_buf
,
438 struct hostent
**result
,
439 int *h_errnop
) attribute_hidden
;
440 extern int __get_hosts_byaddr_r(const char *addr
,
443 struct hostent
*result_buf
,
446 struct hostent
**result
,
447 int *h_errnop
) attribute_hidden
;
448 extern parser_t
*__open_etc_hosts(void) attribute_hidden
;
449 extern int __read_etc_hosts_r(parser_t
*parser
,
452 enum etc_hosts_action action
,
453 struct hostent
*result_buf
,
456 struct hostent
**result
,
457 int *h_errnop
) attribute_hidden
;
458 extern int __dns_lookup(const char *name
,
460 unsigned char **outpacket
,
461 struct resolv_answer
*a
) attribute_hidden
;
462 extern int __encode_dotted(const char *dotted
,
464 int maxlen
) attribute_hidden
;
465 extern int __decode_dotted(const unsigned char *packet
,
469 int dest_len
) attribute_hidden
;
470 extern int __encode_header(struct resolv_header
*h
,
472 int maxlen
) attribute_hidden
;
473 extern void __decode_header(unsigned char *data
,
474 struct resolv_header
*h
) attribute_hidden
;
475 extern int __encode_question(const struct resolv_question
*q
,
477 int maxlen
) attribute_hidden
;
478 extern int __encode_answer(struct resolv_answer
*a
,
480 int maxlen
) attribute_hidden
;
481 extern void __open_nameservers(void) attribute_hidden
;
482 extern void __close_nameservers(void) attribute_hidden
;
485 * Theory of operation.
487 * gethostbyname, getaddrinfo and friends end up here, and they sometimes
488 * need to talk to DNS servers. In order to do this, we need to read /etc/resolv.conf
489 * and determine servers' addresses and the like. resolv.conf format:
491 * nameserver <IP[v6]>
492 * Address of DNS server. Cumulative.
493 * If not specified, assumed to be on localhost.
494 * search <domain1>[ <domain2>]...
495 * Append these domains to unqualified names.
496 * See ndots:n option.
497 * $LOCALDOMAIN (space-separated list) overrides this.
499 * Effectively same as "search" with one domain.
500 * If no "domain" line is present, the domain is determined
501 * from the local host name returned by gethostname();
502 * the domain part is taken to be everything after the first dot.
503 * If there are no dots, there will be no "domain".
504 * The domain and search keywords are mutually exclusive.
505 * If more than one instance of these keywords is present,
506 * the last instance wins.
507 * sortlist 130.155.160.0[/255.255.240.0] 130.155.0.0
508 * Allows addresses returned by gethostbyname to be sorted.
510 * options option[ option]...
511 * (so far we support timeout:n and attempts:n)
512 * $RES_OPTIONS (space-separated list) is to be added to "options"
513 * debug sets RES_DEBUG in _res.options
514 * ndots:n how many dots there should be so that name will be tried
515 * first as an absolute name before any search list elements
516 * are appended to it. Default 1
517 * timeout:n how long to wait for response. Default 5
518 * (sun seems to have retrans:n synonym)
519 * attempts:n number of rounds to do before giving up and returning
520 * an error. Default 2
521 * (sun seems to have retry:n synonym)
522 * rotate sets RES_ROTATE in _res.options, round robin
523 * selection of nameservers. Otherwise try
524 * the first listed server first every time
526 * sets RES_NOCHECKNAME in _res.options, which disables
527 * checking of incoming host names for invalid characters
528 * such as underscore (_), non-ASCII, or control characters
529 * inet6 sets RES_USE_INET6 in _res.options. Try a AAAA query
530 * before an A query inside the gethostbyname(), and map
531 * IPv4 responses in IPv6 "tunnelled form" if no AAAA records
532 * are found but an A record set exists
533 * no_tld_query (FreeBSDism?)
534 * do not attempt to resolve names without dots
536 * We will read and analyze /etc/resolv.conf as needed before
537 * we do a DNS request. This happens in __dns_lookup.
538 * It is reread if its mtime is changed.
540 * BSD has res_init routine which is used to initialize resolver state
541 * which is held in global structure _res.
542 * Generally, programs call res_init, then fiddle with _res.XXX
543 * (_res.options and _res.nscount, _res.nsaddr_list[N]
544 * are popular targets of fiddling) and expect subsequent calls
545 * to gethostbyname, getaddrinfo, etc to use modified information.
547 * However, historical _res structure is quite awkward.
548 * Using it for storing /etc/resolv.conf info is not desirable,
549 * and __dns_lookup does not use it.
551 * We would like to avoid using it unless absolutely necessary.
552 * If user doesn't use res_init, we should arrange it so that
553 * _res structure doesn't even *get linked in* into user's application
554 * (imagine static uclibc build here).
556 * The solution is a __res_sync function pointer, which is normally NULL.
557 * But if res_init is called, it gets set and any subsequent gethostbyname
558 * et al "syncronizes" our internal structures with potentially
559 * modified _res.XXX stuff by calling __res_sync.
560 * The trick here is that if res_init is not used and not linked in,
561 * gethostbyname itself won't reference _res and _res won't be linked in
562 * either. Other possible methods like
563 * if (__res_sync_just_an_int_flag)
564 * __sync_me_with_res()
565 * would pull in __sync_me_with_res, which pulls in _res. Bad.
571 int __encode_header(struct resolv_header
*h
, unsigned char *dest
, int maxlen
)
573 if (maxlen
< HFIXEDSZ
)
576 dest
[0] = (h
->id
& 0xff00) >> 8;
577 dest
[1] = (h
->id
& 0x00ff) >> 0;
578 dest
[2] = (h
->qr
? 0x80 : 0) |
579 ((h
->opcode
& 0x0f) << 3) |
583 dest
[3] = (h
->ra
? 0x80 : 0) | (h
->rcode
& 0x0f);
584 dest
[4] = (h
->qdcount
& 0xff00) >> 8;
585 dest
[5] = (h
->qdcount
& 0x00ff) >> 0;
586 dest
[6] = (h
->ancount
& 0xff00) >> 8;
587 dest
[7] = (h
->ancount
& 0x00ff) >> 0;
588 dest
[8] = (h
->nscount
& 0xff00) >> 8;
589 dest
[9] = (h
->nscount
& 0x00ff) >> 0;
590 dest
[10] = (h
->arcount
& 0xff00) >> 8;
591 dest
[11] = (h
->arcount
& 0x00ff) >> 0;
595 #endif /* L_encodeh */
600 void __decode_header(unsigned char *data
,
601 struct resolv_header
*h
)
603 h
->id
= (data
[0] << 8) | data
[1];
604 h
->qr
= (data
[2] & 0x80) ? 1 : 0;
605 h
->opcode
= (data
[2] >> 3) & 0x0f;
606 h
->aa
= (data
[2] & 0x04) ? 1 : 0;
607 h
->tc
= (data
[2] & 0x02) ? 1 : 0;
608 h
->rd
= (data
[2] & 0x01) ? 1 : 0;
609 h
->ra
= (data
[3] & 0x80) ? 1 : 0;
610 h
->rcode
= data
[3] & 0x0f;
611 h
->qdcount
= (data
[4] << 8) | data
[5];
612 h
->ancount
= (data
[6] << 8) | data
[7];
613 h
->nscount
= (data
[8] << 8) | data
[9];
614 h
->arcount
= (data
[10] << 8) | data
[11];
616 #endif /* L_decodeh */
621 /* Encode a dotted string into nameserver transport-level encoding.
622 This routine is fairly dumb, and doesn't attempt to compress
624 int __encode_dotted(const char *dotted
, unsigned char *dest
, int maxlen
)
628 while (dotted
&& *dotted
) {
629 char *c
= strchr(dotted
, '.');
630 int l
= c
? c
- dotted
: strlen(dotted
);
632 /* two consecutive dots are not valid */
636 if (l
>= (maxlen
- used
- 1))
640 memcpy(dest
+ used
, dotted
, l
);
655 #endif /* L_encoded */
660 /* Decode a dotted string from nameserver transport-level encoding.
661 This routine understands compressed data. */
662 int __decode_dotted(const unsigned char *packet
,
677 if (offset
>= packet_len
)
679 b
= packet
[offset
++];
686 if ((b
& 0xc0) == 0xc0) {
687 if (offset
>= packet_len
)
691 /* compressed item, redirect */
692 offset
= ((b
& 0x3f) << 8) | packet
[offset
];
697 if (used
+ b
+ 1 >= dest_len
)
699 if (offset
+ b
>= packet_len
)
701 memcpy(dest
+ used
, packet
+ offset
, b
);
708 if (packet
[offset
] != 0)
714 /* The null byte must be counted too */
718 DPRINTF("Total decode len = %d\n", total
);
722 #endif /* L_decoded */
727 int __encode_question(const struct resolv_question
*q
,
733 i
= __encode_dotted(q
->dotted
, dest
, maxlen
);
743 dest
[0] = (q
->qtype
& 0xff00) >> 8;
744 dest
[1] = (q
->qtype
& 0x00ff) >> 0;
745 dest
[2] = (q
->qclass
& 0xff00) >> 8;
746 dest
[3] = (q
->qclass
& 0x00ff) >> 0;
750 #endif /* L_encodeq */
755 int __encode_answer(struct resolv_answer
*a
, unsigned char *dest
, int maxlen
)
759 i
= __encode_dotted(a
->dotted
, dest
, maxlen
);
766 if (maxlen
< (RRFIXEDSZ
+ a
->rdlength
))
769 *dest
++ = (a
->atype
& 0xff00) >> 8;
770 *dest
++ = (a
->atype
& 0x00ff) >> 0;
771 *dest
++ = (a
->aclass
& 0xff00) >> 8;
772 *dest
++ = (a
->aclass
& 0x00ff) >> 0;
773 *dest
++ = (a
->ttl
& 0xff000000) >> 24;
774 *dest
++ = (a
->ttl
& 0x00ff0000) >> 16;
775 *dest
++ = (a
->ttl
& 0x0000ff00) >> 8;
776 *dest
++ = (a
->ttl
& 0x000000ff) >> 0;
777 *dest
++ = (a
->rdlength
& 0xff00) >> 8;
778 *dest
++ = (a
->rdlength
& 0x00ff) >> 0;
779 memcpy(dest
, a
->rdata
, a
->rdlength
);
781 return i
+ RRFIXEDSZ
+ a
->rdlength
;
783 #endif /* L_encodea */
786 #ifdef CURRENTLY_UNUSED
789 int __encode_packet(struct resolv_header
*h
,
790 struct resolv_question
**q
,
791 struct resolv_answer
**an
,
792 struct resolv_answer
**ns
,
793 struct resolv_answer
**ar
,
794 unsigned char *dest
, int maxlen
) attribute_hidden
;
795 int __encode_packet(struct resolv_header
*h
,
796 struct resolv_question
**q
,
797 struct resolv_answer
**an
,
798 struct resolv_answer
**ns
,
799 struct resolv_answer
**ar
,
800 unsigned char *dest
, int maxlen
)
805 i
= __encode_header(h
, dest
, maxlen
);
813 for (j
= 0; j
< h
->qdcount
; j
++) {
814 i
= __encode_question(q
[j
], dest
, maxlen
);
822 for (j
= 0; j
< h
->ancount
; j
++) {
823 i
= __encode_answer(an
[j
], dest
, maxlen
);
830 for (j
= 0; j
< h
->nscount
; j
++) {
831 i
= __encode_answer(ns
[j
], dest
, maxlen
);
838 for (j
= 0; j
< h
->arcount
; j
++) {
839 i
= __encode_answer(ar
[j
], dest
, maxlen
);
849 #endif /* L_encodep */
854 int __decode_packet(unsigned char *data
, struct resolv_header
*h
) attribute_hidden
;
855 int __decode_packet(unsigned char *data
, struct resolv_header
*h
)
857 __decode_header(data
, h
);
860 #endif /* L_decodep */
865 int __form_query(int id
,
868 unsigned char *packet
,
869 int maxlen
) attribute_hidden
;
870 int __form_query(int id
,
873 unsigned char *packet
,
876 struct resolv_header h
;
877 struct resolv_question q
;
880 memset(&h
, 0, sizeof(h
));
884 q
.dotted
= (char *) name
;
886 q
.qclass
= C_IN
; /* CLASS_IN */
888 i
= __encode_header(&h
, packet
, maxlen
);
892 j
= __encode_question(&q
, packet
+ i
, maxlen
- i
);
898 #endif /* L_formquery */
899 #endif /* CURRENTLY_UNUSED */
902 #ifdef L_opennameservers
904 # if __BYTE_ORDER == __LITTLE_ENDIAN
905 #define NAMESERVER_PORT_N (__bswap_constant_16(NAMESERVER_PORT))
907 #define NAMESERVER_PORT_N NAMESERVER_PORT
910 __UCLIBC_MUTEX_INIT(__resolv_lock
, PTHREAD_MUTEX_INITIALIZER
);
912 /* Protected by __resolv_lock */
913 void (*__res_sync
)(void);
914 /*uint32_t __resolv_opts; */
915 uint8_t __resolv_timeout
= RES_TIMEOUT
;
916 uint8_t __resolv_attempts
= RES_DFLRETRY
;
917 unsigned __nameservers
;
918 unsigned __searchdomains
;
919 sockaddr46_t
*__nameserver
;
920 char **__searchdomain
;
921 #ifdef __UCLIBC_HAS_IPV4__
922 const struct sockaddr_in __local_nameserver
= {
923 .sin_family
= AF_INET
,
924 .sin_port
= NAMESERVER_PORT_N
,
927 const struct sockaddr_in6 __local_nameserver
= {
928 .sin6_family
= AF_INET6
,
929 .sin6_port
= NAMESERVER_PORT_N
,
933 /* Helpers. Both stop on EOL, if it's '\n', it is converted to NUL first */
934 static char *skip_nospace(char *p
)
936 while (*p
!= '\0' && !isspace(*p
)) {
945 static char *skip_and_NUL_space(char *p
)
947 /* NB: '\n' is not isspace! */
950 if (c
== '\0' || !isspace(c
))
953 if (c
== '\n' || c
== '#')
960 /* Must be called under __resolv_lock. */
961 void __open_nameservers(void)
963 static uint32_t resolv_conf_mtime
;
965 char szBuffer
[MAXLEN_searchdomain
];
971 /* Reread /etc/resolv.conf if it was modified. */
973 if (stat("/etc/resolv.conf", &sb
) != 0)
975 if (resolv_conf_mtime
!= (uint32_t)sb
.st_mtime
) {
976 resolv_conf_mtime
= sb
.st_mtime
;
977 __close_nameservers(); /* force config reread */
984 __resolv_timeout
= RES_TIMEOUT
;
985 __resolv_attempts
= RES_DFLRETRY
;
987 fp
= fopen("/etc/resolv.conf", "r");
988 #ifdef FALLBACK_TO_CONFIG_RESOLVCONF
990 /* If we do not have a pre-populated /etc/resolv.conf then
991 try to use the one from /etc/config which exists on numerous
992 systems ranging from some uClinux to IRIX installations and
993 may be the only /etc dir that was mounted rw. */
994 fp
= fopen("/etc/config/resolv.conf", "r");
999 while (fgets(szBuffer
, sizeof(szBuffer
), fp
) != NULL
) {
1003 keyword
= p
= skip_and_NUL_space(szBuffer
);
1005 p
= skip_nospace(p
);
1006 /* find next word */
1007 p
= skip_and_NUL_space(p
);
1009 if (strcmp(keyword
, "nameserver") == 0) {
1010 /* terminate IP addr */
1011 *skip_nospace(p
) = '\0';
1012 memset(&sa
, 0, sizeof(sa
));
1013 if (0) /* nothing */;
1014 #ifdef __UCLIBC_HAS_IPV6__
1015 else if (inet_pton(AF_INET6
, p
, &sa
.sa6
.sin6_addr
) > 0) {
1016 sa
.sa6
.sin6_family
= AF_INET6
;
1017 sa
.sa6
.sin6_port
= htons(NAMESERVER_PORT
);
1020 #ifdef __UCLIBC_HAS_IPV4__
1021 else if (inet_pton(AF_INET
, p
, &sa
.sa4
.sin_addr
) > 0) {
1022 sa
.sa4
.sin_family
= AF_INET
;
1023 sa
.sa4
.sin_port
= htons(NAMESERVER_PORT
);
1027 continue; /* garbage on this line */
1028 ptr
= realloc(__nameserver
, (__nameservers
+ 1) * sizeof(__nameserver
[0]));
1032 __nameserver
[__nameservers
++] = sa
; /* struct copy */
1035 if (strcmp(keyword
, "domain") == 0 || strcmp(keyword
, "search") == 0) {
1038 /* free old domains ("last 'domain' or 'search' wins" rule) */
1039 while (__searchdomains
)
1040 free(__searchdomain
[--__searchdomains
]);
1041 /*free(__searchdomain);*/
1042 /*__searchdomain = NULL; - not necessary */
1044 /* terminate current word */
1045 p1
= skip_nospace(p
);
1046 /* find next word (maybe) */
1047 p1
= skip_and_NUL_space(p1
);
1049 ptr
= realloc(__searchdomain
, (__searchdomains
+ 1) * sizeof(__searchdomain
[0]));
1052 __searchdomain
= ptr
;
1053 /* NB: strlen(p) <= MAXLEN_searchdomain) because szBuffer[] is smaller */
1057 DPRINTF("adding search %s\n", (char*)ptr
);
1058 __searchdomain
[__searchdomains
++] = (char*)ptr
;
1064 /* if (strcmp(keyword, "sortlist") == 0)... */
1065 if (strcmp(keyword
, "options") == 0) {
1069 if (p
== NULL
|| (p1
= strchr(p
, ':')) == NULL
)
1072 if (strcmp(p
, "timeout") == 0)
1073 what
= &__resolv_timeout
;
1074 else if (strcmp(p
, "attempts") == 0)
1075 what
= &__resolv_attempts
;
1079 DPRINTF("option %s:%d\n", p
, *what
);
1084 if (__nameservers
== 0) {
1085 /* Have to handle malloc failure! What a mess...
1086 * And it's not only here, we need to be careful
1087 * to never write into __nameserver[0] if it points
1088 * to constant __local_nameserver, or free it. */
1089 __nameserver
= malloc(sizeof(__nameserver
[0]));
1091 memcpy(__nameserver
, &__local_nameserver
, sizeof(__local_nameserver
));
1093 __nameserver
= (void*) &__local_nameserver
;
1096 if (__searchdomains
== 0) {
1099 i
= gethostname(buf
, sizeof(buf
) - 1);
1100 buf
[sizeof(buf
) - 1] = '\0';
1101 if (i
== 0 && (p
= strchr(buf
, '.')) != NULL
&& p
[1]) {
1105 __searchdomain
= malloc(sizeof(__searchdomain
[0]));
1106 if (!__searchdomain
) {
1110 __searchdomain
[0] = p
;
1115 DPRINTF("nameservers = %d\n", __nameservers
);
1121 #endif /* L_opennameservers */
1124 #ifdef L_closenameservers
1126 /* Must be called under __resolv_lock. */
1127 void __close_nameservers(void)
1129 if (__nameserver
!= (void*) &__local_nameserver
)
1131 __nameserver
= NULL
;
1133 while (__searchdomains
)
1134 free(__searchdomain
[--__searchdomains
]);
1135 free(__searchdomain
);
1136 __searchdomain
= NULL
;
1137 /*__searchdomains = 0; - already is */
1139 #endif /* L_closenameservers */
1145 static int __length_question(const unsigned char *data
, int maxlen
)
1147 const unsigned char *start
;
1160 if ((b
& 0xc0) == 0xc0) {
1161 /* It's a "compressed" name. */
1162 data
++; /* skip lsb of redirected offset */
1167 maxlen
-= (b
+ 1); /* account for data++ above */
1169 /* Up to here we were skipping encoded name */
1171 /* Account for QTYPE and QCLASS fields */
1174 return data
- start
+ 2 + 2;
1177 static int __decode_answer(const unsigned char *message
, /* packet */
1179 int len
, /* total packet len */
1180 struct resolv_answer
*a
)
1185 DPRINTF("decode_answer(start): off %d, len %d\n", offset
, len
);
1186 i
= __decode_dotted(message
, offset
, len
, temp
, sizeof(temp
));
1190 message
+= offset
+ i
;
1191 len
-= i
+ RRFIXEDSZ
+ offset
;
1193 DPRINTF("decode_answer: off %d, len %d, i %d\n", offset
, len
, i
);
1197 /* TODO: what if strdup fails? */
1198 a
->dotted
= strdup(temp
);
1199 a
->atype
= (message
[0] << 8) | message
[1];
1201 a
->aclass
= (message
[0] << 8) | message
[1];
1203 a
->ttl
= (message
[0] << 24) |
1204 (message
[1] << 16) | (message
[2] << 8) | (message
[3] << 0);
1206 a
->rdlength
= (message
[0] << 8) | message
[1];
1209 a
->rdoffset
= offset
+ i
+ RRFIXEDSZ
;
1211 DPRINTF("i=%d,rdlength=%d\n", i
, a
->rdlength
);
1213 if (len
< a
->rdlength
)
1215 return i
+ RRFIXEDSZ
+ a
->rdlength
;
1219 * a.buf(len) = auxiliary buffer for IP addresses after first one
1220 * a.add_count = how many additional addresses are there already
1221 * outpacket = where to save ptr to raw packet? can be NULL
1223 * ret < 0: error, all other data is not valid
1224 * ret >= 0: length of reply packet
1225 * a.add_count & a.buf: updated
1226 * a.rdlength: length of addresses (4 bytes for IPv4)
1227 * *outpacket: updated (packet is malloced, you need to free it)
1228 * a.rdata: points into *outpacket to 1st IP addr
1229 * NB: don't pass outpacket == NULL if you need to use a.rdata!
1230 * a.atype: type of query?
1231 * a.dotted: which name we _actually_ used. May contain search domains
1232 * appended. (why the filed is called "dotted" I have no idea)
1233 * This is a malloced string. May be NULL because strdup failed.
1235 int __dns_lookup(const char *name
,
1237 unsigned char **outpacket
,
1238 struct resolv_answer
*a
)
1240 /* Protected by __resolv_lock: */
1241 static int last_ns_num
= 0;
1242 static uint16_t last_id
= 1;
1253 struct resolv_header h
;
1254 struct resolv_question q
;
1255 struct resolv_answer ma
;
1256 bool first_answer
= 1;
1258 unsigned char *packet
= malloc(PACKETSZ
);
1260 int variant
= -1; /* search domain to append, -1: none */
1261 int local_ns_num
= -1; /* Nth server to use */
1262 int local_id
= local_id
; /* for compiler */
1269 name_len
= strlen(name
);
1270 if ((unsigned)name_len
>= MAXDNAME
- MAXLEN_searchdomain
- 2)
1271 goto fail
; /* paranoia */
1272 lookup
= malloc(name_len
+ 1/*for '.'*/ + MAXLEN_searchdomain
+ 1);
1273 if (!packet
|| !lookup
|| !name
[0])
1275 ends_with_dot
= (name
[name_len
- 1] == '.');
1276 /* no strcpy! paranoia, user might change name[] under us */
1277 memcpy(lookup
, name
, name_len
);
1279 DPRINTF("Looking up type %d answer for '%s'\n", type
, name
);
1280 retries_left
= 0; /* for compiler */
1283 unsigned reply_timeout
;
1290 /* Mess with globals while under lock */
1291 /* NB: even data *pointed to* by globals may vanish
1292 * outside the locks. We should assume any and all
1293 * globals can completely change between locked
1294 * code regions. OTOH, this is rare, so we don't need
1295 * to handle it "nicely" (do not skip servers,
1296 * search domains, etc), we only need to ensure
1297 * we do not SEGV, use freed+overwritten data
1298 * or do other Really Bad Things. */
1299 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
1300 __open_nameservers();
1301 sdomains
= __searchdomains
;
1302 lookup
[name_len
] = '\0';
1303 if ((unsigned)variant
< sdomains
) {
1304 /* lookup is name_len + 1 + MAXLEN_searchdomain + 1 long */
1305 /* __searchdomain[] is not bigger than MAXLEN_searchdomain */
1306 lookup
[name_len
] = '.';
1307 strcpy(&lookup
[name_len
+ 1], __searchdomain
[variant
]);
1309 /* first time? pick starting server etc */
1310 if (local_ns_num
< 0) {
1312 /*TODO: implement /etc/resolv.conf's "options rotate"
1313 (a.k.a. RES_ROTATE bit in _res.options)
1315 if (_res.options & RES_ROTATE) */
1316 local_ns_num
= last_ns_num
;
1317 retries_left
= __nameservers
* __resolv_attempts
;
1320 if (local_ns_num
>= __nameservers
)
1324 /* write new values back while still under lock */
1326 last_ns_num
= local_ns_num
;
1328 /* can't just take a pointer, __nameserver[x]
1329 * is not safe to use outside of locks */
1330 sa
= __nameserver
[local_ns_num
];
1331 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
1333 memset(packet
, 0, PACKETSZ
);
1334 memset(&h
, 0, sizeof(h
));
1340 DPRINTF("encoding header\n", h
.rd
);
1341 i
= __encode_header(&h
, packet
, PACKETSZ
);
1345 /* encode question */
1346 DPRINTF("lookup name: %s\n", lookup
);
1349 q
.qclass
= C_IN
; /* CLASS_IN */
1350 j
= __encode_question(&q
, packet
+i
, PACKETSZ
-i
);
1358 const socklen_t plen
= sa
.sa
.sa_family
== AF_INET
? INET_ADDRSTRLEN
: INET6_ADDRSTRLEN
;
1359 char *pbuf
= malloc(plen
);
1360 if (pbuf
== NULL
) ;/* nothing */
1361 #ifdef __UCLIBC_HAS_IPV6__
1362 else if (sa
.sa
.sa_family
== AF_INET6
)
1363 pbuf
= (char*)inet_ntop(AF_INET6
, &sa
.sa6
.sin6_addr
, pbuf
, plen
);
1365 #ifdef __UCLIBC_HAS_IPV4__
1366 else if (sa
.sa
.sa_family
== AF_INET
)
1367 pbuf
= (char*)inet_ntop(AF_INET
, &sa
.sa4
.sin_addr
, pbuf
, plen
);
1369 DPRINTF("On try %d, sending query to %s, port %d\n",
1370 retries_left
, pbuf
, NAMESERVER_PORT
);
1374 fd
= socket(sa
.sa
.sa_family
, SOCK_DGRAM
, IPPROTO_UDP
);
1375 if (fd
< 0) /* paranoia */
1376 goto try_next_server
;
1377 rc
= connect(fd
, &sa
.sa
, sizeof(sa
));
1379 /*if (errno == ENETUNREACH) { */
1380 /* routing error, presume not transient */
1381 goto try_next_server
;
1383 /*For example, what transient error this can be? Can't think of any */
1387 DPRINTF("Xmit packet len:%d id:%d qr:%d\n", packet_len
, h
.id
, h
.qr
);
1388 /* no error check - if it fails, we time out on recv */
1389 send(fd
, packet
, packet_len
, 0);
1392 reply_timeout
= __resolv_timeout
;
1396 tv
.tv_sec
= reply_timeout
;
1398 if (select(fd
+ 1, &fds
, NULL
, NULL
, &tv
) <= 0) {
1399 DPRINTF("Timeout\n");
1400 /* timed out, so retry send and receive
1401 * to next nameserver */
1402 goto try_next_server
;
1405 #else /* !USE_SELECT */
1406 reply_timeout
= __resolv_timeout
* 1000;
1409 fds
.events
= POLLIN
;
1410 if (poll(&fds
, 1, reply_timeout
) <= 0) {
1411 DPRINTF("Timeout\n");
1412 /* timed out, so retry send and receive
1413 * to next nameserver */
1414 goto try_next_server
;
1416 if (fds
.revents
& (POLLERR
| POLLHUP
| POLLNVAL
)) {
1417 DPRINTF("Bad event\n");
1418 goto try_next_server
;
1420 /*TODO: better timeout accounting?*/
1421 reply_timeout
-= 1000;
1422 #endif /* USE_SELECT */
1424 /* vda: a bogus response seen in real world (caused SEGV in uclibc):
1425 * "ping www.google.com" sending AAAA query and getting
1426 * response with one answer... with answer part missing!
1427 * Fixed by thorough checks for not going past the packet's end.
1431 static const char test_query
[32] = "\0\2\1\0\0\1\0\0\0\0\0\0\3www\6google\3com\0\0\34\0\1";
1432 static const char test_respn
[32] = "\0\2\201\200\0\1\0\1\0\0\0\0\3www\6google\3com\0\0\34\0\1";
1433 pos
= memcmp(packet
+ 2, test_query
+ 2, 30);
1434 packet_len
= recv(fd
, packet
, PACKETSZ
, MSG_DONTWAIT
);
1437 memcpy(packet
+ 2, test_respn
+ 2, 30);
1441 packet_len
= recv(fd
, packet
, PACKETSZ
, MSG_DONTWAIT
);
1444 if (packet_len
< HFIXEDSZ
) {
1446 * If the peer did shutdown then retry later,
1447 * try next peer on error.
1448 * it's just a bogus packet from somewhere */
1450 if (packet_len
>= 0 && reply_timeout
)
1452 goto try_next_server
;
1454 __decode_header(packet
, &h
);
1455 DPRINTF("len:%d id:%d qr:%d\n", packet_len
, h
.id
, h
.qr
);
1456 if (h
.id
!= local_id
|| !h
.qr
) {
1461 DPRINTF("Got response (i think)!\n");
1462 DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n",
1463 h
.qdcount
, h
.ancount
, h
.nscount
, h
.arcount
);
1464 DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n",
1465 h
.opcode
, h
.aa
, h
.tc
, h
.rd
, h
.ra
, h
.rcode
);
1467 /* bug 660 says we treat negative response as an error
1468 * and retry, which is, eh, an error. :)
1469 * We were incurring long delays because of this. */
1470 if (h
.rcode
== NXDOMAIN
|| h
.rcode
== SERVFAIL
) {
1471 /* if possible, try next search domain */
1472 if (!ends_with_dot
) {
1473 DPRINTF("variant:%d sdomains:%d\n", variant
, sdomains
);
1474 if (variant
< sdomains
- 1) {
1475 /* next search domain */
1479 /* no more search domains to try */
1481 if (h
.rcode
!= SERVFAIL
) {
1482 /* dont loop, this is "no such host" situation */
1483 h_errno
= HOST_NOT_FOUND
;
1487 /* Insert other non-fatal errors here, which do not warrant
1488 * switching to next nameserver */
1490 /* Strange error, assuming this nameserver is feeling bad */
1492 goto try_next_server
;
1494 /* Code below won't work correctly with h.ancount == 0, so... */
1495 if (h
.ancount
<= 0) {
1496 h_errno
= NO_DATA
; /* [is this correct code to check for?] */
1500 for (j
= 0; j
< h
.qdcount
; j
++) {
1501 DPRINTF("Skipping question %d at %d\n", j
, pos
);
1502 i
= __length_question(packet
+ pos
, packet_len
- pos
);
1504 DPRINTF("Packet'question section "
1505 "is truncated, trying next server\n");
1506 goto try_next_server
;
1509 DPRINTF("Length of question %d is %d\n", j
, i
);
1511 DPRINTF("Decoding answer at pos %d\n", pos
);
1515 for (j
= 0; j
< h
.ancount
; j
++) {
1516 i
= __decode_answer(packet
, pos
, packet_len
, &ma
);
1518 DPRINTF("failed decode %d\n", i
);
1519 /* If the message was truncated but we have
1520 * decoded some answers, pretend it's OK */
1523 goto try_next_server
;
1529 ma
.buflen
= a
->buflen
;
1530 ma
.add_count
= a
->add_count
;
1532 memcpy(a
, &ma
, sizeof(ma
));
1533 if (a
->atype
!= T_SIG
&& (NULL
== a
->buf
|| (type
!= T_A
&& type
!= T_AAAA
)))
1535 if (a
->atype
!= type
)
1537 a
->add_count
= h
.ancount
- j
- 1;
1538 if ((a
->rdlength
+ sizeof(struct in_addr
*)) * a
->add_count
> a
->buflen
)
1544 if (ma
.atype
!= type
)
1546 if (a
->rdlength
!= ma
.rdlength
) {
1548 DPRINTF("Answer address len(%u) differs from original(%u)\n",
1549 ma
.rdlength
, a
->rdlength
);
1550 goto try_next_server
;
1552 memcpy(a
->buf
+ (a
->add_count
* ma
.rdlength
), ma
.rdata
, ma
.rdlength
);
1558 DPRINTF("Answer name = |%s|\n", a
->dotted
);
1559 DPRINTF("Answer type = |%d|\n", a
->atype
);
1563 *outpacket
= packet
;
1570 /* Try next nameserver */
1573 } while (retries_left
> 0);
1576 h_errno
= NETDB_INTERNAL
;
1584 #endif /* L_dnslookup */
1587 #ifdef L_read_etc_hosts_r
1589 parser_t
* __open_etc_hosts(void)
1592 parser
= config_open("/etc/hosts");
1593 #ifdef FALLBACK_TO_CONFIG_RESOLVCONF
1595 parser
= config_open("/etc/config/hosts");
1600 #define MINTOKENS 2 /* ip address + canonical name */
1601 #define MAXTOKENS (MINTOKENS + MAXALIASES)
1602 #define HALISTOFF (sizeof(char*) * (MAXTOKENS + 1)) /* reserve space for list terminator */
1603 #define INADDROFF (HALISTOFF + 2 * sizeof(char*))
1605 int __read_etc_hosts_r(
1609 enum etc_hosts_action action
,
1610 struct hostent
*result_buf
,
1611 char *buf
, size_t buflen
,
1612 struct hostent
**result
,
1616 struct in_addr
*h_addr0
= NULL
;
1617 const size_t aliaslen
= INADDROFF
+
1618 #ifdef __UCLIBC_HAS_IPV6__
1619 sizeof(struct in6_addr
)
1621 sizeof(struct in_addr
)
1624 int ret
= HOST_NOT_FOUND
;
1625 /* make sure pointer is aligned */
1626 int i
= ALIGN_BUFFER_OFFSET(buf
);
1630 *h_errnop
= NETDB_INTERNAL
;
1631 if (/* (ssize_t)buflen < 0 || */ buflen
< aliaslen
1632 || (buflen
- aliaslen
) < BUFSZ
+ 1)
1635 parser
= __open_etc_hosts();
1636 if (parser
== NULL
) {
1641 * char *alias[MAXTOKENS] = {address, name, aliases...}
1642 * char **h_addr_list[1] = {*in[6]_addr, NULL}
1644 * char line_buffer[BUFSZ+];
1647 parser
->data_len
= aliaslen
;
1648 parser
->line_len
= buflen
- aliaslen
;
1649 *h_errnop
= HOST_NOT_FOUND
;
1650 /* <ip>[[:space:]][<aliases>] */
1651 while (config_read(parser
, &tok
, MAXTOKENS
, MINTOKENS
, "# \t", PARSE_NORMAL
)) {
1652 result_buf
->h_aliases
= tok
+1;
1653 if (action
== GETHOSTENT
) {
1654 /* Return whatever the next entry happens to be. */
1656 } else if (action
== GET_HOSTS_BYADDR
) {
1657 if (strcmp(name
, *tok
) != 0)
1659 } else { /* GET_HOSTS_BYNAME */
1661 char **alias
= tok
+ 1;
1662 while (aliases
< MAXALIASES
) {
1663 char *tmp
= *(alias
+aliases
++);
1664 if (tmp
&& strcasecmp(name
, tmp
) == 0)
1670 result_buf
->h_name
= *(result_buf
->h_aliases
++);
1671 result_buf
->h_addr_list
= (char**)(buf
+ HALISTOFF
);
1672 *(result_buf
->h_addr_list
+ 1) = '\0';
1673 h_addr0
= (struct in_addr
*)(buf
+ INADDROFF
);
1674 result_buf
->h_addr
= (char*)h_addr0
;
1675 if (0) /* nothing */;
1676 #ifdef __UCLIBC_HAS_IPV4__
1677 else if (type
== AF_INET
1678 && inet_pton(AF_INET
, *tok
, h_addr0
) > 0) {
1679 DPRINTF("Found INET\n");
1680 result_buf
->h_addrtype
= AF_INET
;
1681 result_buf
->h_length
= sizeof(struct in_addr
);
1682 *result
= result_buf
;
1683 ret
= NETDB_SUCCESS
;
1686 #ifdef __UCLIBC_HAS_IPV6__
1687 #define in6 ((struct in6_addr *)buf)
1688 else if (type
== AF_INET6
1689 && inet_pton(AF_INET6
, *tok
, h_addr0
) > 0) {
1690 DPRINTF("Found INET6\n");
1691 result_buf
->h_addrtype
= AF_INET6
;
1692 result_buf
->h_length
= sizeof(struct in6_addr
);
1693 *result
= result_buf
;
1694 ret
= NETDB_SUCCESS
;
1698 /* continue parsing in the hope the user has multiple
1699 * host types listed in the database like so:
1702 * If looking for an IPv6 addr, don't bail when we got the IPv4
1704 DPRINTF("Error: Found host but different address family\n");
1705 /* NB: gethostbyname2_r depends on this feature
1706 * to avoid looking for IPv6 addr of "localhost" etc */
1712 if (action
!= GETHOSTENT
)
1713 config_close(parser
);
1717 #endif /* L_read_etc_hosts_r */
1720 #ifdef L_get_hosts_byname_r
1722 int __get_hosts_byname_r(const char *name
,
1724 struct hostent
*result_buf
,
1727 struct hostent
**result
,
1730 return __read_etc_hosts_r(NULL
, name
, type
, GET_HOSTS_BYNAME
,
1731 result_buf
, buf
, buflen
, result
, h_errnop
);
1733 #endif /* L_get_hosts_byname_r */
1736 #ifdef L_get_hosts_byaddr_r
1738 int __get_hosts_byaddr_r(const char *addr
,
1741 struct hostent
*result_buf
,
1744 struct hostent
**result
,
1747 #ifndef __UCLIBC_HAS_IPV6__
1748 char ipaddr
[INET_ADDRSTRLEN
];
1750 char ipaddr
[INET6_ADDRSTRLEN
];
1754 #ifdef __UCLIBC_HAS_IPV4__
1756 if (len
!= sizeof(struct in_addr
))
1760 #ifdef __UCLIBC_HAS_IPV6__
1762 if (len
!= sizeof(struct in6_addr
))
1770 inet_ntop(type
, addr
, ipaddr
, sizeof(ipaddr
));
1772 return __read_etc_hosts_r(NULL
, ipaddr
, type
, GET_HOSTS_BYADDR
,
1773 result_buf
, buf
, buflen
, result
, h_errnop
);
1775 #endif /* L_get_hosts_byaddr_r */
1778 #ifdef L_getnameinfo
1780 int getnameinfo(const struct sockaddr
*sa
,
1790 struct hostent
*hoste
= NULL
;
1793 if (flags
& ~(NI_NUMERICHOST
|NI_NUMERICSERV
|NI_NOFQDN
|NI_NAMEREQD
|NI_DGRAM
))
1794 return EAI_BADFLAGS
;
1796 if (sa
== NULL
|| addrlen
< sizeof(sa_family_t
))
1799 if (sa
->sa_family
== AF_LOCAL
) /* valid */;
1800 #ifdef __UCLIBC_HAS_IPV4__
1801 else if (sa
->sa_family
== AF_INET
) {
1802 if (addrlen
< sizeof(struct sockaddr_in
))
1806 #ifdef __UCLIBC_HAS_IPV6__
1807 else if (sa
->sa_family
== AF_INET6
) {
1808 if (addrlen
< sizeof(struct sockaddr_in6
))
1815 if (host
!= NULL
&& hostlen
> 0)
1816 switch (sa
->sa_family
) {
1818 #ifdef __UCLIBC_HAS_IPV6__
1821 if (!(flags
& NI_NUMERICHOST
)) {
1822 if (0) /* nothing */;
1823 #ifdef __UCLIBC_HAS_IPV6__
1824 else if (sa
->sa_family
== AF_INET6
)
1825 hoste
= gethostbyaddr((const void *)
1826 &(((const struct sockaddr_in6
*) sa
)->sin6_addr
),
1827 sizeof(struct in6_addr
), AF_INET6
);
1829 #ifdef __UCLIBC_HAS_IPV4__
1831 hoste
= gethostbyaddr((const void *)
1832 &(((const struct sockaddr_in
*)sa
)->sin_addr
),
1833 sizeof(struct in_addr
), AF_INET
);
1838 if ((flags
& NI_NOFQDN
)
1839 && (getdomainname(domain
, sizeof(domain
)) == 0)
1840 && (c
= strstr(hoste
->h_name
, domain
)) != NULL
1841 && (c
!= hoste
->h_name
) && (*(--c
) == '.')
1843 strncpy(host
, hoste
->h_name
,
1844 MIN(hostlen
, (size_t) (c
- hoste
->h_name
)));
1845 host
[MIN(hostlen
- 1, (size_t) (c
- hoste
->h_name
))] = '\0';
1847 strncpy(host
, hoste
->h_name
, hostlen
);
1854 const char *c
= NULL
;
1856 if (flags
& NI_NAMEREQD
) {
1860 if (0) /* nothing */;
1861 #ifdef __UCLIBC_HAS_IPV6__
1862 else if (sa
->sa_family
== AF_INET6
) {
1863 const struct sockaddr_in6
*sin6p
;
1865 sin6p
= (const struct sockaddr_in6
*) sa
;
1866 c
= inet_ntop(AF_INET6
,
1867 (const void *) &sin6p
->sin6_addr
,
1870 /* Does scope id need to be supported? */
1872 scopeid
= sin6p
->sin6_scope_id
;
1874 /* Buffer is >= IFNAMSIZ+1. */
1875 char scopebuf
[IFNAMSIZ
+ 1];
1877 int ni_numericscope
= 0;
1878 size_t real_hostlen
= strnlen(host
, hostlen
);
1879 size_t scopelen
= 0;
1881 scopebuf
[0] = SCOPE_DELIMITER
;
1883 scopeptr
= &scopebuf
[1];
1885 if (IN6_IS_ADDR_LINKLOCAL(&sin6p
->sin6_addr
)
1886 || IN6_IS_ADDR_MC_LINKLOCAL(&sin6p
->sin6_addr
)) {
1887 if (if_indextoname(scopeid
, scopeptr
) == NULL
)
1890 scopelen
= strlen(scopebuf
);
1895 if (ni_numericscope
)
1896 scopelen
= 1 + snprintf(scopeptr
,
1902 if (real_hostlen
+ scopelen
+ 1 > hostlen
)
1904 memcpy(host
+ real_hostlen
, scopebuf
, scopelen
+ 1);
1908 #endif /* __UCLIBC_HAS_IPV6__ */
1909 #if defined __UCLIBC_HAS_IPV4__
1911 c
= inet_ntop(AF_INET
, (const void *)
1912 &(((const struct sockaddr_in
*) sa
)->sin_addr
),
1925 if (!(flags
& NI_NUMERICHOST
)) {
1926 struct utsname utsname
;
1928 if (!uname(&utsname
)) {
1929 strncpy(host
, utsname
.nodename
, hostlen
);
1934 if (flags
& NI_NAMEREQD
) {
1939 strncpy(host
, "localhost", hostlen
);
1941 /* Already checked above
1947 if (serv
&& (servlen
> 0)) {
1948 if (sa
->sa_family
== AF_LOCAL
) {
1949 strncpy(serv
, ((const struct sockaddr_un
*) sa
)->sun_path
, servlen
);
1950 } else { /* AF_INET || AF_INET6 */
1951 if (!(flags
& NI_NUMERICSERV
)) {
1953 s
= getservbyport(((const struct sockaddr_in
*) sa
)->sin_port
,
1954 ((flags
& NI_DGRAM
) ? "udp" : "tcp"));
1956 strncpy(serv
, s
->s_name
, servlen
);
1960 snprintf(serv
, servlen
, "%d",
1961 ntohs(((const struct sockaddr_in
*) sa
)->sin_port
));
1965 if (host
&& (hostlen
> 0))
1966 host
[hostlen
-1] = 0;
1967 if (serv
&& (servlen
> 0))
1968 serv
[servlen
-1] = 0;
1972 libc_hidden_def(getnameinfo
)
1973 #endif /* L_getnameinfo */
1976 #ifdef L_gethostbyname_r
1979 * "uClibc resolver's gethostbyname does not return the requested name
1980 * as an alias, but instead returns the canonical name. glibc's
1981 * gethostbyname has a similar bug where it returns the requested name
1982 * with the search domain name appended (to make a FQDN) as an alias,
1983 * but not the original name itself. Both contradict POSIX, which says
1984 * that the name argument passed to gethostbyname must be in the alias list"
1985 * This is fixed now, and we differ from glibc:
1987 * $ ./gethostbyname_uclibc wer.google.com
1988 * h_name:'c13-ss-2-lb.cnet.com'
1990 * h_addrtype:2 AF_INET
1991 * alias:'wer.google.com' <===
1992 * addr: 0x4174efd8 '216.239.116.65'
1994 * $ ./gethostbyname_glibc wer.google.com
1995 * h_name:'c13-ss-2-lb.cnet.com'
1997 * h_addrtype:2 AF_INET
1998 * alias:'wer.google.com.com' <===
1999 * addr:'216.239.116.65'
2001 * When examples were run, /etc/resolv.conf contained "search com" line.
2003 int gethostbyname_r(const char *name
,
2004 struct hostent
*result_buf
,
2007 struct hostent
**result
,
2010 struct in_addr
**addr_list
;
2013 unsigned char *packet
;
2014 struct resolv_answer a
;
2023 /* do /etc/hosts first */
2025 int old_errno
= errno
; /* save the old errno and reset errno */
2026 __set_errno(0); /* to check for missing /etc/hosts. */
2027 i
= __get_hosts_byname_r(name
, AF_INET
, result_buf
,
2028 buf
, buflen
, result
, h_errnop
);
2029 if (i
== NETDB_SUCCESS
) {
2030 __set_errno(old_errno
);
2033 switch (*h_errnop
) {
2034 case HOST_NOT_FOUND
:
2035 wrong_af
= (i
== TRY_AGAIN
);
2038 case NETDB_INTERNAL
:
2039 if (errno
== ENOENT
) {
2042 /* else fall through */
2046 __set_errno(old_errno
);
2049 DPRINTF("Nothing found in /etc/hosts\n");
2051 *h_errnop
= NETDB_INTERNAL
;
2053 /* prepare future h_aliases[0] */
2054 i
= strlen(name
) + 1;
2055 if ((ssize_t
)buflen
<= i
)
2057 memcpy(buf
, name
, i
); /* paranoia: name might change */
2061 /* make sure pointer is aligned */
2062 i
= ALIGN_BUFFER_OFFSET(buf
);
2067 * struct in_addr* addr_list[NN+1];
2068 * struct in_addr* in[NN];
2070 alias
= (char **)buf
;
2071 buf
+= sizeof(alias
[0]) * 2;
2072 buflen
-= sizeof(alias
[0]) * 2;
2073 addr_list
= (struct in_addr
**)buf
;
2074 /* buflen may be < 0, must do signed compare */
2075 if ((ssize_t
)buflen
< 256)
2078 /* we store only one "alias" - the name itself */
2079 #ifdef __UCLIBC_MJN3_ONLY__
2080 #warning TODO -- generate the full list
2085 /* maybe it is already an address? */
2087 struct in_addr
*in
= (struct in_addr
*)(buf
+ sizeof(addr_list
[0]) * 2);
2088 if (inet_aton(name
, in
)) {
2090 addr_list
[1] = NULL
;
2091 result_buf
->h_name
= alias0
;
2092 result_buf
->h_aliases
= alias
;
2093 result_buf
->h_addrtype
= AF_INET
;
2094 result_buf
->h_length
= sizeof(struct in_addr
);
2095 result_buf
->h_addr_list
= (char **) addr_list
;
2096 *result
= result_buf
;
2097 *h_errnop
= NETDB_SUCCESS
;
2098 return NETDB_SUCCESS
;
2102 /* what if /etc/hosts has it but it's not IPv4?
2103 * F.e. "::1 localhost6". We don't do DNS query for such hosts -
2104 * "ping localhost6" should be fast even if DNS server is down! */
2106 *h_errnop
= HOST_NOT_FOUND
;
2110 /* talk to DNS servers */
2112 /* take into account that at least one address will be there,
2113 * we'll need space for one in_addr + two addr_list[] elems */
2114 a
.buflen
= buflen
- ((sizeof(addr_list
[0]) * 2 + sizeof(struct in_addr
)));
2116 packet_len
= __dns_lookup(name
, T_A
, &packet
, &a
);
2117 if (packet_len
< 0) {
2118 *h_errnop
= HOST_NOT_FOUND
;
2119 DPRINTF("__dns_lookup returned < 0\n");
2123 if (a
.atype
== T_A
) { /* ADDRESS */
2124 /* we need space for addr_list[] and one IPv4 address */
2125 /* + 1 accounting for 1st addr (it's in a.rdata),
2126 * another + 1 for NULL in last addr_list[]: */
2127 int need_bytes
= sizeof(addr_list
[0]) * (a
.add_count
+ 1 + 1)
2128 /* for 1st addr (it's in a.rdata): */
2129 + sizeof(struct in_addr
);
2130 /* how many bytes will 2nd and following addresses take? */
2131 int ips_len
= a
.add_count
* a
.rdlength
;
2133 buflen
-= (need_bytes
+ ips_len
);
2134 if ((ssize_t
)buflen
< 0) {
2135 DPRINTF("buffer too small for all addresses\n");
2136 /* *h_errnop = NETDB_INTERNAL; - already is */
2141 /* if there are additional addresses in buf,
2142 * move them forward so that they are not destroyed */
2143 DPRINTF("a.add_count:%d a.rdlength:%d a.rdata:%p\n", a
.add_count
, a
.rdlength
, a
.rdata
);
2144 memmove(buf
+ need_bytes
, buf
, ips_len
);
2146 /* 1st address is in a.rdata, insert it */
2147 buf
+= need_bytes
- sizeof(struct in_addr
);
2148 memcpy(buf
, a
.rdata
, sizeof(struct in_addr
));
2150 /* fill addr_list[] */
2151 for (i
= 0; i
<= a
.add_count
; i
++) {
2152 addr_list
[i
] = (struct in_addr
*)buf
;
2153 buf
+= sizeof(struct in_addr
);
2155 addr_list
[i
] = NULL
;
2157 /* if we have enough space, we can report "better" name
2158 * (it may contain search domains attached by __dns_lookup,
2159 * or CNAME of the host if it is different from the name
2160 * we used to find it) */
2161 if (a
.dotted
&& buflen
> strlen(a
.dotted
)) {
2162 strcpy(buf
, a
.dotted
);
2166 result_buf
->h_name
= alias0
;
2167 result_buf
->h_aliases
= alias
;
2168 result_buf
->h_addrtype
= AF_INET
;
2169 result_buf
->h_length
= sizeof(struct in_addr
);
2170 result_buf
->h_addr_list
= (char **) addr_list
;
2171 *result
= result_buf
;
2172 *h_errnop
= NETDB_SUCCESS
;
2177 *h_errnop
= HOST_NOT_FOUND
;
2178 __set_h_errno(HOST_NOT_FOUND
);
2186 libc_hidden_def(gethostbyname_r
)
2187 #endif /* L_gethostbyname_r */
2190 #ifdef L_gethostbyname2_r
2192 int gethostbyname2_r(const char *name
,
2194 struct hostent
*result_buf
,
2197 struct hostent
**result
,
2200 #ifndef __UCLIBC_HAS_IPV6__
2201 return family
== (AF_INET
)
2202 ? gethostbyname_r(name
, result_buf
, buf
, buflen
, result
, h_errnop
)
2205 struct in6_addr
**addr_list
;
2208 unsigned char *packet
;
2209 struct resolv_answer a
;
2214 if (family
== AF_INET
)
2215 return gethostbyname_r(name
, result_buf
, buf
, buflen
, result
, h_errnop
);
2218 if (family
!= AF_INET6
)
2224 /* do /etc/hosts first */
2226 int old_errno
= errno
; /* save the old errno and reset errno */
2227 __set_errno(0); /* to check for missing /etc/hosts. */
2228 i
= __get_hosts_byname_r(name
, AF_INET6
/*family*/, result_buf
,
2229 buf
, buflen
, result
, h_errnop
);
2230 if (i
== NETDB_SUCCESS
) {
2231 __set_errno(old_errno
);
2234 switch (*h_errnop
) {
2235 case HOST_NOT_FOUND
:
2236 wrong_af
= (i
== TRY_AGAIN
);
2239 case NETDB_INTERNAL
:
2240 if (errno
== ENOENT
) {
2243 /* else fall through */
2247 __set_errno(old_errno
);
2250 DPRINTF("Nothing found in /etc/hosts\n");
2252 *h_errnop
= NETDB_INTERNAL
;
2254 /* prepare future h_aliases[0] */
2255 i
= strlen(name
) + 1;
2256 if ((ssize_t
)buflen
<= i
)
2258 memcpy(buf
, name
, i
); /* paranoia: name might change */
2262 /* make sure pointer is aligned */
2263 i
= ALIGN_BUFFER_OFFSET(buf
);
2268 * struct in6_addr* addr_list[NN+1];
2269 * struct in6_addr* in[NN];
2271 alias
= (char **)buf
;
2272 buf
+= sizeof(alias
[0]) * 2;
2273 buflen
-= sizeof(alias
[0]) * 2;
2274 addr_list
= (struct in6_addr
**)buf
;
2275 /* buflen may be < 0, must do signed compare */
2276 if ((ssize_t
)buflen
< 256)
2279 /* we store only one "alias" - the name itself */
2280 #ifdef __UCLIBC_MJN3_ONLY__
2281 #warning TODO -- generate the full list
2286 /* maybe it is already an address? */
2288 struct in6_addr
*in
= (struct in6_addr
*)(buf
+ sizeof(addr_list
[0]) * 2);
2289 if (inet_pton(AF_INET6
, name
, in
)) {
2291 addr_list
[1] = NULL
;
2292 result_buf
->h_name
= alias0
;
2293 result_buf
->h_aliases
= alias
;
2294 result_buf
->h_addrtype
= AF_INET6
;
2295 result_buf
->h_length
= sizeof(struct in6_addr
);
2296 result_buf
->h_addr_list
= (char **) addr_list
;
2297 *result
= result_buf
;
2298 *h_errnop
= NETDB_SUCCESS
;
2299 return NETDB_SUCCESS
;
2303 /* what if /etc/hosts has it but it's not IPv6?
2304 * F.e. "127.0.0.1 localhost". We don't do DNS query for such hosts -
2305 * "ping localhost" should be fast even if DNS server is down! */
2307 *h_errnop
= HOST_NOT_FOUND
;
2311 /* talk to DNS servers */
2313 /* take into account that at least one address will be there,
2314 * we'll need space of one in6_addr + two addr_list[] elems */
2315 a
.buflen
= buflen
- ((sizeof(addr_list
[0]) * 2 + sizeof(struct in6_addr
)));
2317 packet_len
= __dns_lookup(name
, T_AAAA
, &packet
, &a
);
2318 if (packet_len
< 0) {
2319 *h_errnop
= HOST_NOT_FOUND
;
2320 DPRINTF("__dns_lookup returned < 0\n");
2324 if (a
.atype
== T_AAAA
) { /* ADDRESS */
2325 /* we need space for addr_list[] and one IPv6 address */
2326 /* + 1 accounting for 1st addr (it's in a.rdata),
2327 * another + 1 for NULL in last addr_list[]: */
2328 int need_bytes
= sizeof(addr_list
[0]) * (a
.add_count
+ 1 + 1)
2329 /* for 1st addr (it's in a.rdata): */
2330 + sizeof(struct in6_addr
);
2331 /* how many bytes will 2nd and following addresses take? */
2332 int ips_len
= a
.add_count
* a
.rdlength
;
2334 buflen
-= (need_bytes
+ ips_len
);
2335 if ((ssize_t
)buflen
< 0) {
2336 DPRINTF("buffer too small for all addresses\n");
2337 /* *h_errnop = NETDB_INTERNAL; - already is */
2342 /* if there are additional addresses in buf,
2343 * move them forward so that they are not destroyed */
2344 DPRINTF("a.add_count:%d a.rdlength:%d a.rdata:%p\n", a
.add_count
, a
.rdlength
, a
.rdata
);
2345 memmove(buf
+ need_bytes
, buf
, ips_len
);
2347 /* 1st address is in a.rdata, insert it */
2348 buf
+= need_bytes
- sizeof(struct in6_addr
);
2349 memcpy(buf
, a
.rdata
, sizeof(struct in6_addr
));
2351 /* fill addr_list[] */
2352 for (i
= 0; i
<= a
.add_count
; i
++) {
2353 addr_list
[i
] = (struct in6_addr
*)buf
;
2354 buf
+= sizeof(struct in6_addr
);
2356 addr_list
[i
] = NULL
;
2358 /* if we have enough space, we can report "better" name
2359 * (it may contain search domains attached by __dns_lookup,
2360 * or CNAME of the host if it is different from the name
2361 * we used to find it) */
2362 if (a
.dotted
&& buflen
> strlen(a
.dotted
)) {
2363 strcpy(buf
, a
.dotted
);
2367 result_buf
->h_name
= alias0
;
2368 result_buf
->h_aliases
= alias
;
2369 result_buf
->h_addrtype
= AF_INET6
;
2370 result_buf
->h_length
= sizeof(struct in6_addr
);
2371 result_buf
->h_addr_list
= (char **) addr_list
;
2372 *result
= result_buf
;
2373 *h_errnop
= NETDB_SUCCESS
;
2378 *h_errnop
= HOST_NOT_FOUND
;
2379 __set_h_errno(HOST_NOT_FOUND
);
2386 #endif /* __UCLIBC_HAS_IPV6__ */
2388 libc_hidden_def(gethostbyname2_r
)
2389 #endif /* L_gethostbyname2_r */
2392 #ifdef L_gethostbyaddr_r
2394 int gethostbyaddr_r(const void *addr
, socklen_t addrlen
,
2396 struct hostent
*result_buf
,
2397 char *buf
, size_t buflen
,
2398 struct hostent
**result
,
2403 struct in_addr
**addr_list
;
2405 unsigned char *packet
;
2406 struct resolv_answer a
;
2416 #ifdef __UCLIBC_HAS_IPV4__
2418 if (addrlen
!= sizeof(struct in_addr
))
2422 #ifdef __UCLIBC_HAS_IPV6__
2424 if (addrlen
!= sizeof(struct in6_addr
))
2432 /* do /etc/hosts first */
2433 i
= __get_hosts_byaddr_r(addr
, addrlen
, type
, result_buf
,
2434 buf
, buflen
, result
, h_errnop
);
2437 switch (*h_errnop
) {
2438 case HOST_NOT_FOUND
:
2445 *h_errnop
= NETDB_INTERNAL
;
2447 /* make sure pointer is aligned */
2448 i
= ALIGN_BUFFER_OFFSET(buf
);
2452 * char *alias[ALIAS_DIM];
2453 * struct in[6]_addr* addr_list[2];
2454 * struct in[6]_addr in;
2455 * char scratch_buffer[256+];
2457 #define in6 ((struct in6_addr *)in)
2458 alias
= (char **)buf
;
2459 addr_list
= (struct in_addr
**)buf
;
2460 buf
+= sizeof(*addr_list
) * 2;
2461 buflen
-= sizeof(*addr_list
) * 2;
2462 in
= (struct in_addr
*)buf
;
2463 #ifndef __UCLIBC_HAS_IPV6__
2465 buflen
-= sizeof(*in
);
2466 if (addrlen
> sizeof(*in
))
2469 buf
+= sizeof(*in6
);
2470 buflen
-= sizeof(*in6
);
2471 if (addrlen
> sizeof(*in6
))
2474 if ((ssize_t
)buflen
< 256)
2479 addr_list
[1] = NULL
;
2480 memcpy(in
, addr
, addrlen
);
2482 if (0) /* nothing */;
2483 #ifdef __UCLIBC_HAS_IPV4__
2484 else IF_HAS_BOTH(if (type
== AF_INET
)) {
2485 unsigned char *tp
= (unsigned char *)addr
;
2486 sprintf(buf
, "%u.%u.%u.%u.in-addr.arpa",
2487 tp
[3], tp
[2], tp
[1], tp
[0]);
2490 #ifdef __UCLIBC_HAS_IPV6__
2493 unsigned char *tp
= (unsigned char *)addr
+ addrlen
- 1;
2495 dst
+= sprintf(dst
, "%x.%x.", tp
[0] & 0xf, tp
[0] >> 4);
2497 } while (tp
>= (unsigned char *)addr
);
2498 strcpy(dst
, "ip6.arpa");
2502 memset(&a
, '\0', sizeof(a
));
2504 /* Hmm why we memset(a) to zeros only once? */
2505 packet_len
= __dns_lookup(buf
, T_PTR
, &packet
, &a
);
2506 if (packet_len
< 0) {
2507 *h_errnop
= HOST_NOT_FOUND
;
2511 strncpy(buf
, a
.dotted
, buflen
);
2513 if (a
.atype
!= T_CNAME
)
2516 DPRINTF("Got a CNAME in gethostbyaddr()\n");
2517 if (++nest
> MAX_RECURSE
) {
2518 *h_errnop
= NO_RECOVERY
;
2521 /* Decode CNAME into buf, feed it to __dns_lookup() again */
2522 i
= __decode_dotted(packet
, a
.rdoffset
, packet_len
, buf
, buflen
);
2525 *h_errnop
= NO_RECOVERY
;
2530 if (a
.atype
== T_PTR
) { /* ADDRESS */
2531 i
= __decode_dotted(packet
, a
.rdoffset
, packet_len
, buf
, buflen
);
2533 result_buf
->h_name
= buf
;
2534 result_buf
->h_addrtype
= type
;
2535 result_buf
->h_length
= addrlen
;
2536 result_buf
->h_addr_list
= (char **) addr_list
;
2537 result_buf
->h_aliases
= alias
;
2538 *result
= result_buf
;
2539 *h_errnop
= NETDB_SUCCESS
;
2540 return NETDB_SUCCESS
;
2544 *h_errnop
= NO_ADDRESS
;
2548 libc_hidden_def(gethostbyaddr_r
)
2549 #endif /* L_gethostbyaddr_r */
2552 #ifdef L_gethostent_r
2554 __UCLIBC_MUTEX_STATIC(mylock
, PTHREAD_MUTEX_INITIALIZER
);
2556 static parser_t
*hostp
= NULL
;
2557 static smallint host_stayopen
;
2559 void endhostent_unlocked(void)
2562 config_close(hostp
);
2567 void endhostent(void)
2569 __UCLIBC_MUTEX_LOCK(mylock
);
2570 endhostent_unlocked();
2571 __UCLIBC_MUTEX_UNLOCK(mylock
);
2574 void sethostent(int stay_open
)
2576 __UCLIBC_MUTEX_LOCK(mylock
);
2579 __UCLIBC_MUTEX_UNLOCK(mylock
);
2582 int gethostent_r(struct hostent
*result_buf
, char *buf
, size_t buflen
,
2583 struct hostent
**result
, int *h_errnop
)
2587 __UCLIBC_MUTEX_LOCK(mylock
);
2588 if (hostp
== NULL
) {
2589 hostp
= __open_etc_hosts();
2590 if (hostp
== NULL
) {
2597 ret
= __read_etc_hosts_r(hostp
, NULL
, AF_INET
, GETHOSTENT
,
2598 result_buf
, buf
, buflen
, result
, h_errnop
);
2600 endhostent_unlocked();
2602 __UCLIBC_MUTEX_UNLOCK(mylock
);
2605 libc_hidden_def(gethostent_r
)
2606 #endif /* L_gethostent_r */
2609 #ifndef __UCLIBC_HAS_IPV6__
2610 #define GETXX_BUFSZ (sizeof(struct in_addr) + sizeof(struct in_addr *) * 2 + \
2611 /*sizeof(char *)*ALIAS_DIM */+ 384/*namebuffer*/ + 32/* margin */)
2613 #define GETXX_BUFSZ (sizeof(struct in6_addr) + sizeof(struct in6_addr *) * 2 + \
2614 /*sizeof(char *)*ALIAS_DIM */+ 384/*namebuffer*/ + 32/* margin */)
2615 #endif /* __UCLIBC_HAS_IPV6__ */
2617 #define __INIT_GETXX_BUF(sz) \
2619 buf = (char *)__uc_malloc((sz));
2623 struct hostent
*gethostent(void)
2625 static struct hostent hoste
;
2626 static char *buf
= NULL
;
2627 struct hostent
*host
= NULL
;
2628 #ifndef __UCLIBC_HAS_IPV6__
2629 #define HOSTENT_BUFSZ (sizeof(struct in_addr) + sizeof(struct in_addr *) * 2 + \
2630 sizeof(char *)*ALIAS_DIM + BUFSZ /*namebuffer*/ + 2 /* margin */)
2632 #define HOSTENT_BUFSZ (sizeof(struct in6_addr) + sizeof(struct in6_addr *) * 2 + \
2633 sizeof(char *)*ALIAS_DIM + BUFSZ /*namebuffer*/ + 2 /* margin */)
2634 #endif /* __UCLIBC_HAS_IPV6__ */
2636 __INIT_GETXX_BUF(HOSTENT_BUFSZ
);
2637 gethostent_r(&hoste
, buf
, HOSTENT_BUFSZ
, &host
, &h_errno
);
2640 #undef HOSTENT_BUFSZ
2641 #endif /* L_gethostent */
2644 #ifdef L_gethostbyname2
2646 struct hostent
*gethostbyname2(const char *name
, int family
)
2648 static struct hostent hoste
;
2649 static char *buf
= NULL
;
2652 __INIT_GETXX_BUF(GETXX_BUFSZ
);
2653 #ifndef __UCLIBC_HAS_IPV6__
2654 if (family
!= AF_INET
)
2655 return (struct hostent
*)NULL
;
2656 gethostbyname_r(name
, &hoste
, buf
, GETXX_BUFSZ
, &hp
, &h_errno
);
2658 gethostbyname2_r(name
, family
, &hoste
, buf
, GETXX_BUFSZ
, &hp
, &h_errno
);
2659 #endif /* __UCLIBC_HAS_IPV6__ */
2663 libc_hidden_def(gethostbyname2
)
2664 #endif /* L_gethostbyname2 */
2667 #ifdef L_gethostbyname
2669 struct hostent
*gethostbyname(const char *name
)
2671 return gethostbyname2(name
, AF_INET
);
2673 libc_hidden_def(gethostbyname
)
2674 #endif /* L_gethostbyname */
2677 #ifdef L_gethostbyaddr
2679 struct hostent
*gethostbyaddr(const void *addr
, socklen_t len
, int type
)
2681 static struct hostent hoste
;
2682 static char *buf
= NULL
;
2685 __INIT_GETXX_BUF(GETXX_BUFSZ
);
2686 gethostbyaddr_r(addr
, len
, type
, &hoste
, buf
, GETXX_BUFSZ
, &hp
, &h_errno
);
2689 libc_hidden_def(gethostbyaddr
)
2690 #endif /* L_gethostbyaddr */
2696 * Expand compressed domain name 'comp_dn' to full domain name.
2697 * 'msg' is a pointer to the begining of the message,
2698 * 'eomorig' points to the first location after the message,
2699 * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
2700 * Return size of compressed name or -1 if there was an error.
2702 int dn_expand(const u_char
*msg
, const u_char
*eom
, const u_char
*src
,
2703 char *dst
, int dstsiz
)
2705 int n
= ns_name_uncompress(msg
, eom
, src
, dst
, (size_t)dstsiz
);
2707 if (n
> 0 && dst
[0] == '.')
2711 libc_hidden_def(dn_expand
)
2714 * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
2715 * Return the size of the compressed name or -1.
2716 * 'length' is the size of the array pointed to by 'comp_dn'.
2719 dn_comp(const char *src
, u_char
*dst
, int dstsiz
,
2720 u_char
**dnptrs
, u_char
**lastdnptr
)
2722 return ns_name_compress(src
, dst
, (size_t) dstsiz
,
2723 (const u_char
**) dnptrs
,
2724 (const u_char
**) lastdnptr
);
2726 libc_hidden_def(dn_comp
)
2727 #endif /* L_res_comp */
2732 /* Thinking in noninternationalized USASCII (per the DNS spec),
2733 * is this character visible and not a space when printed ?
2735 static int printable(int ch
)
2737 return (ch
> 0x20 && ch
< 0x7f);
2739 /* Thinking in noninternationalized USASCII (per the DNS spec),
2740 * is this characted special ("in need of quoting") ?
2742 static int special(int ch
)
2745 case 0x22: /* '"' */
2746 case 0x2E: /* '.' */
2747 case 0x3B: /* ';' */
2748 case 0x5C: /* '\\' */
2749 /* Special modifiers in zone files. */
2750 case 0x40: /* '@' */
2751 case 0x24: /* '$' */
2759 * ns_name_uncompress(msg, eom, src, dst, dstsiz)
2760 * Expand compressed domain name to presentation format.
2762 * Number of bytes read out of `src', or -1 (with errno set).
2764 * Root domain returns as "." not "".
2766 int ns_name_uncompress(const u_char
*msg
, const u_char
*eom
,
2767 const u_char
*src
, char *dst
, size_t dstsiz
)
2769 u_char tmp
[NS_MAXCDNAME
];
2772 n
= ns_name_unpack(msg
, eom
, src
, tmp
, sizeof tmp
);
2775 if (ns_name_ntop(tmp
, dst
, dstsiz
) == -1)
2779 libc_hidden_def(ns_name_uncompress
)
2782 * ns_name_ntop(src, dst, dstsiz)
2783 * Convert an encoded domain name to printable ascii as per RFC1035.
2785 * Number of bytes written to buffer, or -1 (with errno set)
2787 * The root is returned as "."
2788 * All other domains are returned in non absolute form
2790 int ns_name_ntop(const u_char
*src
, char *dst
, size_t dstsiz
)
2801 while ((n
= *cp
++) != 0) {
2802 if ((n
& NS_CMPRSFLGS
) != 0) {
2803 /* Some kind of compression pointer. */
2804 __set_errno(EMSGSIZE
);
2809 __set_errno(EMSGSIZE
);
2814 if (dn
+ n
>= eom
) {
2815 __set_errno(EMSGSIZE
);
2818 for (; n
> 0; n
--) {
2821 if (dn
+ 1 >= eom
) {
2822 __set_errno(EMSGSIZE
);
2827 } else if (!printable(c
)) {
2828 if (dn
+ 3 >= eom
) {
2829 __set_errno(EMSGSIZE
);
2833 *dn
++ = "0123456789"[c
/ 100];
2835 *dn
++ = "0123456789"[c
/ 10];
2836 *dn
++ = "0123456789"[c
% 10];
2839 __set_errno(EMSGSIZE
);
2848 __set_errno(EMSGSIZE
);
2854 __set_errno(EMSGSIZE
);
2860 libc_hidden_def(ns_name_ntop
)
2862 static int encode_bitstring(const char **bp
, const char *end
,
2863 unsigned char **labelp
,
2864 unsigned char ** dst
,
2865 unsigned const char *eom
)
2868 const char *cp
= *bp
;
2870 const char *beg_blen
;
2871 int value
= 0, count
= 0, tbcount
= 0, blen
= 0;
2875 /* a bitstring must contain at least 2 characters */
2879 /* XXX: currently, only hex strings are supported */
2882 if (!isxdigit((unsigned char) *cp
)) /*%< reject '\[x/BLEN]' */
2885 for (tp
= *dst
+ 1; cp
< end
&& tp
< eom
; cp
++) {
2886 unsigned char c
= *cp
;
2889 case ']': /*%< end of the bitstring */
2892 if (beg_blen
== NULL
)
2894 blen
= (int)strtol(beg_blen
, &end_blen
, 10);
2895 if (*end_blen
!= ']')
2899 *tp
++ = ((value
<< 4) & 0xff);
2900 cp
++; /*%< skip ']' */
2907 if (!__isdigit_char(c
))
2909 if (beg_blen
== NULL
) {
2911 /* blen never begings with 0 */
2917 if (!__isdigit_char(c
)) {
2918 c
= c
| 0x20; /* lowercase */
2920 if (c
> 5) /* not a-f? */
2939 if (cp
>= end
|| tp
>= eom
)
2943 * bit length validation:
2944 * If a <length> is present, the number of digits in the <bit-data>
2945 * MUST be just sufficient to contain the number of bits specified
2946 * by the <length>. If there are insignificant bits in a final
2947 * hexadecimal or octal digit, they MUST be zero.
2948 * RFC2673, Section 3.2.
2953 if (((blen
+ 3) & ~3) != tbcount
)
2955 traillen
= tbcount
- blen
; /*%< between 0 and 3 */
2956 if (((value
<< (8 - traillen
)) & 0xff) != 0)
2964 /* encode the type and the significant bit fields */
2965 **labelp
= DNS_LABELTYPE_BITSTRING
;
2974 int ns_name_pton(const char *src
, u_char
*dst
, size_t dstsiz
)
2976 static const char digits
[] = "0123456789";
2977 u_char
*label
, *bp
, *eom
;
2978 int c
, n
, escaped
, e
= 0;
2986 while ((c
= *src
++) != 0) {
2988 if (c
== '[') { /*%< start a bit string label */
2989 cp
= strchr(src
, ']');
2991 errno
= EINVAL
; /*%< ??? */
2994 e
= encode_bitstring(&src
, cp
+ 2,
3011 cp
= strchr(digits
, c
);
3013 n
= (cp
- digits
) * 100;
3017 cp
= strchr(digits
, c
);
3020 n
+= (cp
- digits
) * 10;
3024 cp
= strchr(digits
, c
);
3033 } else if (c
== '\\') {
3036 } else if (c
== '.') {
3037 c
= (bp
- label
- 1);
3038 if ((c
& NS_CMPRSFLGS
) != 0) { /*%< Label too big. */
3045 /* Fully qualified ? */
3053 if ((bp
- dst
) > MAXCDNAME
) {
3059 if (c
== 0 || *src
== '.') {
3070 c
= (bp
- label
- 1);
3071 if ((c
& NS_CMPRSFLGS
) != 0) { /*%< Label too big. */
3085 if ((bp
- dst
) > MAXCDNAME
) { /*%< src too big */
3095 libc_hidden_def(ns_name_pton
)
3098 * ns_name_unpack(msg, eom, src, dst, dstsiz)
3099 * Unpack a domain name from a message, source may be compressed.
3101 * -1 if it fails, or consumed octets if it succeeds.
3103 int ns_name_unpack(const u_char
*msg
, const u_char
*eom
, const u_char
*src
,
3104 u_char
*dst
, size_t dstsiz
)
3106 const u_char
*srcp
, *dstlim
;
3108 int n
, len
, checked
;
3114 dstlim
= dst
+ dstsiz
;
3115 if (srcp
< msg
|| srcp
>= eom
) {
3116 __set_errno(EMSGSIZE
);
3119 /* Fetch next label in domain name. */
3120 while ((n
= *srcp
++) != 0) {
3121 /* Check for indirection. */
3122 switch (n
& NS_CMPRSFLGS
) {
3125 if (dstp
+ n
+ 1 >= dstlim
|| srcp
+ n
>= eom
) {
3126 __set_errno(EMSGSIZE
);
3131 memcpy(dstp
, srcp
, n
);
3138 __set_errno(EMSGSIZE
);
3142 len
= srcp
- src
+ 1;
3143 srcp
= msg
+ (((n
& 0x3f) << 8) | (*srcp
& 0xff));
3144 if (srcp
< msg
|| srcp
>= eom
) { /* Out of range. */
3145 __set_errno(EMSGSIZE
);
3150 * Check for loops in the compressed name;
3151 * if we've looked at the whole message,
3152 * there must be a loop.
3154 if (checked
>= eom
- msg
) {
3155 __set_errno(EMSGSIZE
);
3161 __set_errno(EMSGSIZE
);
3162 return -1; /* flag error */
3170 libc_hidden_def(ns_name_unpack
)
3172 static int labellen(const unsigned char *lp
)
3175 unsigned char l
= *lp
;
3177 if ((l
& NS_CMPRSFLGS
) == NS_CMPRSFLGS
) {
3178 /* should be avoided by the caller */
3182 if ((l
& NS_CMPRSFLGS
) == NS_TYPE_ELT
) {
3183 if (l
== DNS_LABELTYPE_BITSTRING
) {
3187 return ((bitlen
+ 7 ) / 8 + 1);
3190 return -1; /*%< unknwon ELT */
3196 static int mklower(int ch
)
3198 if (ch
>= 0x41 && ch
<= 0x5A)
3204 static int dn_find(const unsigned char *domain
,
3205 const unsigned char *msg
,
3206 const unsigned char * const *dnptrs
,
3207 const unsigned char * const *lastdnptr
)
3209 const unsigned char *dn
, *cp
, *sp
;
3210 const unsigned char * const *cpp
;
3213 for (cpp
= dnptrs
; cpp
< lastdnptr
; cpp
++) {
3216 * terminate search on:
3218 * compression pointer
3221 while (*sp
!= 0 && (*sp
& NS_CMPRSFLGS
) == 0 &&
3222 (sp
- msg
) < 0x4000) {
3226 while ((n
= *cp
++) != 0) {
3228 * check for indirection
3230 switch (n
& NS_CMPRSFLGS
) {
3231 case 0: /*%< normal case, n == len */
3232 n
= labellen(cp
- 1); /*%< XXX */
3237 if (mklower(*dn
++) !=
3240 /* Is next root for both ? */
3241 if (*dn
== '\0' && *cp
== '\0')
3246 case NS_CMPRSFLGS
: /*%< indirection */
3247 cp
= msg
+ (((n
& 0x3f) << 8) | *cp
);
3250 default: /*%< illegal type */
3264 int ns_name_pack(const unsigned char *src
,
3265 unsigned char *dst
, int dstsiz
,
3266 const unsigned char **dnptrs
,
3267 const unsigned char **lastdnptr
)
3269 unsigned char *dstp
;
3270 const unsigned char **cpp
, **lpp
, *eob
, *msg
;
3271 const unsigned char *srcp
;
3272 int n
, l
, first
= 1;
3276 eob
= dstp
+ dstsiz
;
3279 if (dnptrs
!= NULL
) {
3282 for (cpp
= dnptrs
; *cpp
!= NULL
; cpp
++)
3285 lpp
= cpp
; /*%< end of list to search */
3291 /* make sure the domain we are about to add is legal */
3297 if ((n
& NS_CMPRSFLGS
) == NS_CMPRSFLGS
) {
3302 l0
= labellen(srcp
);
3309 if (l
> MAXCDNAME
) {
3317 /* from here on we need to reset compression pointer array on error */
3321 /* Look to see if we can use pointers. */
3324 if (n
!= 0 && msg
!= NULL
) {
3325 l
= dn_find(srcp
, msg
, (const unsigned char * const *) dnptrs
,
3326 (const unsigned char * const *) lpp
);
3328 if (dstp
+ 1 >= eob
) {
3332 *dstp
++ = ((u_int32_t
)l
>> 8) | NS_CMPRSFLGS
;
3334 return (dstp
- dst
);
3337 /* Not found, save it. */
3338 if (lastdnptr
!= NULL
&& cpp
< lastdnptr
- 1 &&
3339 (dstp
- msg
) < 0x4000 && first
) {
3346 /* copy label to buffer */
3347 if ((n
& NS_CMPRSFLGS
) == NS_CMPRSFLGS
) {
3348 /* Should not happen. */
3353 if (dstp
+ 1 + n
>= eob
) {
3357 memcpy(dstp
, srcp
, (size_t)(n
+ 1));
3373 libc_hidden_def(ns_name_pack
)
3375 int ns_name_compress(const char *src
,
3376 unsigned char *dst
, size_t dstsiz
,
3377 const unsigned char **dnptrs
,
3378 const unsigned char **lastdnptr
)
3380 unsigned char tmp
[NS_MAXCDNAME
];
3382 if (ns_name_pton(src
, tmp
, sizeof(tmp
)) == -1)
3385 return ns_name_pack(tmp
, dst
, dstsiz
, dnptrs
, lastdnptr
);
3387 libc_hidden_def(ns_name_compress
)
3389 int ns_name_skip(const unsigned char **ptrptr
,
3390 const unsigned char *eom
)
3392 const unsigned char *cp
;
3397 while (cp
< eom
&& (n
= *cp
++) != 0) {
3398 /* Check for indirection. */
3399 switch (n
& NS_CMPRSFLGS
) {
3400 case 0: /*%< normal case, n == len */
3403 case NS_TYPE_ELT
: /*%< EDNS0 extended label */
3404 l
= labellen(cp
- 1);
3406 errno
= EMSGSIZE
; /*%< XXX */
3411 case NS_CMPRSFLGS
: /*%< indirection */
3414 default: /*%< illegal type */
3431 libc_hidden_def(ns_name_skip
)
3433 int dn_skipname(const unsigned char *ptr
, const unsigned char *eom
)
3435 const unsigned char *saveptr
= ptr
;
3437 if (ns_name_skip(&ptr
, eom
) == -1)
3440 return ptr
- saveptr
;
3442 libc_hidden_def(dn_skipname
)
3443 #endif /* L_ns_name */
3448 /* Will be called under __resolv_lock. */
3449 static void res_sync_func(void)
3451 struct __res_state
*rp
= &(_res
);
3454 /* If we didn't get malloc failure earlier... */
3455 if (__nameserver
!= (void*) &__local_nameserver
) {
3457 * if (__nameservers < rp->nscount) - try to grow __nameserver[]?
3459 #ifdef __UCLIBC_HAS_IPV6__
3460 if (__nameservers
> rp
->_u
._ext
.nscount
)
3461 __nameservers
= rp
->_u
._ext
.nscount
;
3464 __nameserver
[n
].sa6
= *rp
->_u
._ext
.nsaddrs
[n
]; /* struct copy */
3465 #else /* IPv4 only */
3466 if (__nameservers
> rp
->nscount
)
3467 __nameservers
= rp
->nscount
;
3470 __nameserver
[n
].sa4
= rp
->nsaddr_list
[n
]; /* struct copy */
3473 __resolv_timeout
= rp
->retrans
? : RES_TIMEOUT
;
3474 __resolv_attempts
= rp
->retry
? : RES_DFLRETRY
;
3475 /* Extend and comment what program is known
3476 * to use which _res.XXX member(s).
3478 __resolv_opts = rp->options;
3483 /* has to be called under __resolv_lock */
3485 __res_vinit(res_state rp
, int preinit
)
3487 int i
, n
, options
, retrans
, retry
, ndots
;
3488 #ifdef __UCLIBC_HAS_IPV6__
3492 __close_nameservers();
3493 __open_nameservers();
3496 options
= rp
->options
;
3497 retrans
= rp
->retrans
;
3502 memset(rp
, 0, sizeof(*rp
));
3505 rp
->options
= RES_DEFAULT
;
3506 rp
->retrans
= RES_TIMEOUT
;
3507 rp
->retry
= RES_DFLRETRY
;
3510 rp
->options
= options
;
3511 rp
->retrans
= retrans
;
3516 #ifdef __UCLIBC_HAS_COMPAT_RES_STATE__
3517 /* Was: "rp->id = random();" but:
3518 * - random() pulls in largish static buffers
3519 * - isn't actually random unless, say, srandom(time(NULL)) was called
3520 * - is not used by uclibc anyway :)
3522 /* rp->id = 0; - memset did it */
3524 #ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__
3528 n
= __searchdomains
;
3529 if (n
> ARRAY_SIZE(rp
->dnsrch
))
3530 n
= ARRAY_SIZE(rp
->dnsrch
);
3531 for (i
= 0; i
< n
; i
++)
3532 rp
->dnsrch
[i
] = __searchdomain
[i
];
3534 /* copy nameservers' addresses */
3536 #ifdef __UCLIBC_HAS_IPV4__
3538 while (n
< ARRAY_SIZE(rp
->nsaddr_list
) && i
< __nameservers
) {
3539 if (__nameserver
[i
].sa
.sa_family
== AF_INET
) {
3540 rp
->nsaddr_list
[n
] = __nameserver
[i
].sa4
; /* struct copy */
3541 #ifdef __UCLIBC_HAS_IPV6__
3542 if (m
< ARRAY_SIZE(rp
->_u
._ext
.nsaddrs
)) {
3543 rp
->_u
._ext
.nsaddrs
[m
] = (void*) &rp
->nsaddr_list
[n
];
3549 #ifdef __UCLIBC_HAS_IPV6__
3550 if (__nameserver
[i
].sa
.sa_family
== AF_INET6
3551 && m
< ARRAY_SIZE(rp
->_u
._ext
.nsaddrs
)
3553 struct sockaddr_in6
*sa6
= malloc(sizeof(*sa6
));
3555 *sa6
= __nameserver
[i
].sa6
; /* struct copy */
3556 rp
->_u
._ext
.nsaddrs
[m
] = sa6
;
3564 #ifdef __UCLIBC_HAS_IPV6__
3565 rp
->_u
._ext
.nscount
= m
;
3568 #else /* IPv6 only */
3569 while (m
< ARRAY_SIZE(rp
->_u
._ext
.nsaddrs
) && i
< __nameservers
) {
3570 struct sockaddr_in6
*sa6
= malloc(sizeof(*sa6
));
3572 *sa6
= __nameserver
[i
].sa6
; /* struct copy */
3573 rp
->_u
._ext
.nsaddrs
[m
] = sa6
;
3578 rp
->_u
._ext
.nscount
= m
;
3581 rp
->options
|= RES_INIT
;
3589 return 0xffff & getpid();
3592 /* Our res_init never fails (always returns 0) */
3597 * These three fields used to be statically initialized. This made
3598 * it hard to use this code in a shared library. It is necessary,
3599 * now that we're doing dynamic initialization here, that we preserve
3600 * the old semantics: if an application modifies one of these three
3601 * fields of _res before res_init() is called, res_init() will not
3602 * alter them. Of course, if an application is setting them to
3603 * _zero_ before calling res_init(), hoping to override what used
3604 * to be the static default, we can't detect it and unexpected results
3605 * will follow. Zero for any of these fields would make no sense,
3606 * so one can safely assume that the applications were already getting
3607 * unexpected results.
3609 * _res.options is tricky since some apps were known to diddle the bits
3610 * before res_init() was first called. We can't replicate that semantic
3611 * with dynamic initialization (they may have turned bits off that are
3612 * set in RES_DEFAULT). Our solution is to declare such applications
3613 * "broken". They could fool us by setting RES_INIT but none do (yet).
3616 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
3619 _res
.retrans
= RES_TIMEOUT
;
3622 if (!(_res
.options
& RES_INIT
))
3623 _res
.options
= RES_DEFAULT
;
3626 * This one used to initialize implicitly to zero, so unless the app
3627 * has set it to something in particular, we can randomize it now.
3630 _res
.id
= res_randomid();
3633 __res_vinit(&_res
, 1);
3634 __res_sync
= res_sync_func
;
3636 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
3640 libc_hidden_def(res_init
)
3643 __res_iclose(res_state statp
)
3645 struct __res_state
* rp
= statp
;
3646 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
3649 __close_nameservers();
3651 #ifdef __UCLIBC_HAS_IPV6__
3653 char *p1
= (char*) &(rp
->nsaddr_list
[0]);
3655 /* free nsaddrs[m] if they do not point to nsaddr_list[x] */
3656 while (m
< ARRAY_SIZE(rp
->_u
._ext
.nsaddrs
)) {
3657 char *p2
= (char*)(rp
->_u
._ext
.nsaddrs
[m
++]);
3658 if (p2
< p1
|| (p2
- p1
) > (signed)sizeof(rp
->nsaddr_list
))
3663 memset(rp
, 0, sizeof(struct __res_state
));
3664 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
3668 * This routine is for closing the socket if a virtual circuit is used and
3669 * the program wants to close it. This provides support for endhostent()
3670 * which expects to close the socket.
3672 * This routine is not expected to be user visible.
3676 res_nclose(res_state statp
)
3678 __res_iclose(statp
);
3681 #ifdef __UCLIBC_HAS_BSD_RES_CLOSE__
3682 void res_close(void)
3688 /* This needs to be after the use of _res in res_init, above. */
3691 #ifndef __UCLIBC_HAS_THREADS__
3692 /* The resolver state for use by single-threaded programs.
3693 This differs from plain `struct __res_state _res;' in that it doesn't
3694 create a common definition, but a plain symbol that resides in .bss,
3695 which can have an alias. */
3696 struct __res_state _res
__attribute__((section (".bss")));
3697 struct __res_state
*__resp
= &_res
;
3698 #else /* __UCLIBC_HAS_THREADS__ */
3699 struct __res_state _res
__attribute__((section (".bss"))) attribute_hidden
;
3701 # if defined __UCLIBC_HAS_TLS__
3703 __thread
struct __res_state
*__resp
= &_res
;
3704 extern __thread
struct __res_state
*__libc_resp
3705 __attribute__ ((alias ("__resp"))) attribute_hidden attribute_tls_model_ie
;
3708 struct __res_state
*__resp
= &_res
;
3710 #endif /* !__UCLIBC_HAS_THREADS__ */
3713 * Set up default settings. If the configuration file exist, the values
3714 * there will have precedence. Otherwise, the server address is set to
3715 * INADDR_ANY and the default domain name comes from the gethostname().
3717 * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
3718 * rather than INADDR_ANY ("0.0.0.0") as the default name server address
3719 * since it was noted that INADDR_ANY actually meant ``the first interface
3720 * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
3721 * it had to be "up" in order for you to reach your own name server. It
3722 * was later decided that since the recommended practice is to always
3723 * install local static routes through 127.0.0.1 for all your network
3724 * interfaces, that we could solve this problem without a code change.
3726 * The configuration file should always be used, since it is the only way
3727 * to specify a default domain. If you are running a server on your local
3728 * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
3729 * in the configuration file.
3731 * Return 0 if completes successfully, -1 on error
3734 res_ninit(res_state statp
)
3737 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
3738 ret
= __res_vinit(statp
, 0);
3739 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
3743 #endif /* L_res_init */
3746 # if defined __UCLIBC_HAS_TLS__
3747 struct __res_state
*
3754 extern struct __res_state _res
;
3756 /* When threaded, _res may be a per-thread variable. */
3757 struct __res_state
*
3765 #endif /* L_res_state */
3770 int res_query(const char *dname
, int class, int type
,
3771 unsigned char *answer
, int anslen
)
3774 unsigned char *packet
= NULL
;
3775 struct resolv_answer a
;
3777 if (!dname
|| class != 1 /* CLASS_IN */) {
3778 h_errno
= NO_RECOVERY
;
3782 memset(&a
, '\0', sizeof(a
));
3783 i
= __dns_lookup(dname
, type
, &packet
, &a
);
3786 if (!h_errno
) /* TODO: can this ever happen? */
3787 h_errno
= TRY_AGAIN
;
3795 memcpy(answer
, packet
, i
);
3800 libc_hidden_def(res_query
)
3803 * Formulate a normal query, send, and retrieve answer in supplied buffer.
3804 * Return the size of the response on success, -1 on error.
3805 * If enabled, implement search rules until answer or unrecoverable failure
3806 * is detected. Error code, if any, is left in h_errno.
3808 #define __TRAILING_DOT (1<<0)
3809 #define __GOT_NODATA (1<<1)
3810 #define __GOT_SERVFAIL (1<<2)
3811 #define __TRIED_AS_IS (1<<3)
3812 int res_search(const char *name
, int class, int type
, u_char
*answer
,
3817 HEADER
*hp
= (HEADER
*)(void *)answer
;
3820 int ret
, saved_herrno
;
3821 uint32_t _res_options
;
3822 unsigned _res_ndots
;
3825 if (!name
|| !answer
) {
3826 h_errno
= NETDB_INTERNAL
;
3831 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
3832 _res_options
= _res
.options
;
3833 _res_ndots
= _res
.ndots
;
3834 _res_dnsrch
= _res
.dnsrch
;
3835 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
3836 if (!(_res_options
& RES_INIT
)) {
3837 res_init(); /* our res_init never fails */
3843 h_errno
= HOST_NOT_FOUND
; /* default, if we never query */
3845 for (cp
= name
; *cp
; cp
++)
3846 dots
+= (*cp
== '.');
3848 if (cp
> name
&& *--cp
== '.')
3849 state
|= __TRAILING_DOT
;
3852 * If there are dots in the name already, let's just give it a try
3853 * 'as is'. The threshold can be set with the "ndots" option.
3856 if (dots
>= _res_ndots
) {
3857 ret
= res_querydomain(name
, NULL
, class, type
, answer
, anslen
);
3860 saved_herrno
= h_errno
;
3861 state
|= __TRIED_AS_IS
;
3865 * We do at least one level of search if
3866 * - there is no dot and RES_DEFNAME is set, or
3867 * - there is at least one dot, there is no trailing dot,
3868 * and RES_DNSRCH is set.
3870 if ((!dots
&& (_res_options
& RES_DEFNAMES
))
3871 || (dots
&& !(state
& __TRAILING_DOT
) && (_res_options
& RES_DNSRCH
))
3875 for (domain
= _res_dnsrch
; *domain
&& !done
; domain
++) {
3877 ret
= res_querydomain(name
, *domain
, class, type
,
3883 * If no server present, give up.
3884 * If name isn't found in this domain,
3885 * keep trying higher domains in the search list
3886 * (if that's enabled).
3887 * On a NO_DATA error, keep trying, otherwise
3888 * a wildcard entry of another type could keep us
3889 * from finding this entry higher in the domain.
3890 * If we get some other error (negative answer or
3891 * server failure), then stop searching up,
3892 * but try the input name below in case it's
3895 if (errno
== ECONNREFUSED
) {
3896 h_errno
= TRY_AGAIN
;
3902 state
|= __GOT_NODATA
;
3904 case HOST_NOT_FOUND
:
3908 if (hp
->rcode
== SERVFAIL
) {
3909 /* try next search element, if any */
3910 state
|= __GOT_SERVFAIL
;
3915 /* anything else implies that we're done */
3919 * if we got here for some reason other than DNSRCH,
3920 * we only wanted one iteration of the loop, so stop.
3922 if (!(_res_options
& RES_DNSRCH
))
3928 * if we have not already tried the name "as is", do that now.
3929 * note that we do this regardless of how many dots were in the
3930 * name or whether it ends with a dot.
3932 if (!(state
& __TRIED_AS_IS
)) {
3933 ret
= res_querydomain(name
, NULL
, class, type
, answer
, anslen
);
3939 * if we got here, we didn't satisfy the search.
3940 * if we did an initial full query, return that query's h_errno
3941 * (note that we wouldn't be here if that query had succeeded).
3942 * else if we ever got a nodata, send that back as the reason.
3943 * else send back meaningless h_errno, that being the one from
3944 * the last DNSRCH we did.
3946 if (saved_herrno
!= -1)
3947 h_errno
= saved_herrno
;
3948 else if (state
& __GOT_NODATA
)
3950 else if (state
& __GOT_SERVFAIL
)
3951 h_errno
= TRY_AGAIN
;
3954 #undef __TRAILING_DOT
3956 #undef __GOT_SERVFAIL
3957 #undef __TRIED_AS_IS
3959 * Perform a call on res_query on the concatenation of name and domain,
3960 * removing a trailing dot from name if domain is NULL.
3962 int res_querydomain(const char *name
, const char *domain
, int class, int type
,
3963 u_char
*answer
, int anslen
)
3965 char nbuf
[MAXDNAME
];
3966 const char *longname
= nbuf
;
3969 uint32_t _res_options
;
3972 if (!name
|| !answer
) {
3973 h_errno
= NETDB_INTERNAL
;
3979 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
3980 _res_options
= _res
.options
;
3981 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
3982 if (!(_res_options
& RES_INIT
)) {
3983 res_init(); /* our res_init never fails */
3986 if (_res_options
& RES_DEBUG
)
3987 printf(";; res_querydomain(%s, %s, %d, %d)\n",
3988 name
, (domain
? domain
: "<Nil>"), class, type
);
3990 if (domain
== NULL
) {
3992 * Check for trailing '.';
3993 * copy without '.' if present.
3996 if (n
+ 1 > sizeof(nbuf
)) {
3997 h_errno
= NO_RECOVERY
;
4000 if (n
> 0 && name
[--n
] == '.') {
4001 strncpy(nbuf
, name
, n
);
4008 if (n
+ 1 + d
+ 1 > sizeof(nbuf
)) {
4009 h_errno
= NO_RECOVERY
;
4012 snprintf(nbuf
, sizeof(nbuf
), "%s.%s", name
, domain
);
4014 return res_query(longname
, class, type
, answer
, anslen
);
4016 libc_hidden_def(res_querydomain
)
4017 #endif /* L_res_query */
4020 unsigned int ns_get16(const unsigned char *src
)
4027 unsigned long ns_get32(const unsigned char *src
)
4034 void ns_put16(unsigned int src
, unsigned char *dst
)
4039 void ns_put32(unsigned long src
, unsigned char *dst
)
4043 #endif /* L_ns_netint */
4046 /* These need to be in the same order as the nres.h:ns_flag enum. */
4047 struct _ns_flagdata
{ unsigned short mask
, shift
; };
4048 static const struct _ns_flagdata _ns_flagdata
[16] = {
4049 { 0x8000, 15 }, /*%< qr. */
4050 { 0x7800, 11 }, /*%< opcode. */
4051 { 0x0400, 10 }, /*%< aa. */
4052 { 0x0200, 9 }, /*%< tc. */
4053 { 0x0100, 8 }, /*%< rd. */
4054 { 0x0080, 7 }, /*%< ra. */
4055 { 0x0040, 6 }, /*%< z. */
4056 { 0x0020, 5 }, /*%< ad. */
4057 { 0x0010, 4 }, /*%< cd. */
4058 { 0x000f, 0 }, /*%< rcode. */
4059 { 0x0000, 0 }, /*%< expansion (1/6). */
4060 { 0x0000, 0 }, /*%< expansion (2/6). */
4061 { 0x0000, 0 }, /*%< expansion (3/6). */
4062 { 0x0000, 0 }, /*%< expansion (4/6). */
4063 { 0x0000, 0 }, /*%< expansion (5/6). */
4064 { 0x0000, 0 }, /*%< expansion (6/6). */
4067 static void setsection(ns_msg
*msg
, ns_sect sect
)
4070 if (sect
== ns_s_max
) {
4075 msg
->_ptr
= msg
->_sections
[(int)sect
];
4079 int ns_skiprr(const unsigned char *ptr
,
4080 const unsigned char *eom
,
4081 ns_sect section
, int count
)
4083 const u_char
*optr
= ptr
;
4085 for (; count
> 0; count
--) {
4088 b
= dn_skipname(ptr
, eom
);
4094 ptr
+= b
/*Name*/ + NS_INT16SZ
/*Type*/ + NS_INT16SZ
/*Class*/;
4095 if (section
!= ns_s_qd
) {
4096 if (ptr
+ NS_INT32SZ
+ NS_INT16SZ
> eom
) {
4101 ptr
+= NS_INT32SZ
/*TTL*/;
4102 NS_GET16(rdlength
, ptr
);
4103 ptr
+= rdlength
/*RData*/;
4114 libc_hidden_def(ns_skiprr
)
4117 ns_initparse(const unsigned char *msg
, int msglen
, ns_msg
*handle
)
4119 const u_char
*eom
= msg
+ msglen
;
4124 if (msg
+ NS_INT16SZ
> eom
) {
4129 NS_GET16(handle
->_id
, msg
);
4130 if (msg
+ NS_INT16SZ
> eom
) {
4135 NS_GET16(handle
->_flags
, msg
);
4136 for (i
= 0; i
< ns_s_max
; i
++) {
4137 if (msg
+ NS_INT16SZ
> eom
) {
4142 NS_GET16(handle
->_counts
[i
], msg
);
4144 for (i
= 0; i
< ns_s_max
; i
++)
4145 if (handle
->_counts
[i
] == 0)
4146 handle
->_sections
[i
] = NULL
;
4148 int b
= ns_skiprr(msg
, eom
, (ns_sect
)i
,
4149 handle
->_counts
[i
]);
4153 handle
->_sections
[i
] = msg
;
4162 setsection(handle
, ns_s_max
);
4167 ns_parserr(ns_msg
*handle
, ns_sect section
, int rrnum
, ns_rr
*rr
)
4172 /* Make section right. */
4174 if (tmp
< 0 || section
>= ns_s_max
) {
4179 if (section
!= handle
->_sect
)
4180 setsection(handle
, section
);
4182 /* Make rrnum right. */
4184 rrnum
= handle
->_rrnum
;
4185 if (rrnum
< 0 || rrnum
>= handle
->_counts
[(int)section
]) {
4189 if (rrnum
< handle
->_rrnum
)
4190 setsection(handle
, section
);
4191 if (rrnum
> handle
->_rrnum
) {
4192 b
= ns_skiprr(handle
->_ptr
, handle
->_eom
, section
,
4193 rrnum
- handle
->_rrnum
);
4198 handle
->_rrnum
= rrnum
;
4202 b
= dn_expand(handle
->_msg
, handle
->_eom
,
4203 handle
->_ptr
, rr
->name
, NS_MAXDNAME
);
4207 if (handle
->_ptr
+ NS_INT16SZ
+ NS_INT16SZ
> handle
->_eom
) {
4211 NS_GET16(rr
->type
, handle
->_ptr
);
4212 NS_GET16(rr
->rr_class
, handle
->_ptr
);
4213 if (section
== ns_s_qd
) {
4218 if (handle
->_ptr
+ NS_INT32SZ
+ NS_INT16SZ
> handle
->_eom
) {
4222 NS_GET32(rr
->ttl
, handle
->_ptr
);
4223 NS_GET16(rr
->rdlength
, handle
->_ptr
);
4224 if (handle
->_ptr
+ rr
->rdlength
> handle
->_eom
) {
4228 rr
->rdata
= handle
->_ptr
;
4229 handle
->_ptr
+= rr
->rdlength
;
4231 if (++handle
->_rrnum
> handle
->_counts
[(int)section
])
4232 setsection(handle
, (ns_sect
)((int)section
+ 1));
4237 int ns_msg_getflag(ns_msg handle
, int flag
)
4239 return ((handle
)._flags
& _ns_flagdata
[flag
].mask
) >> _ns_flagdata
[flag
].shift
;
4241 #endif /* L_ns_parse */
4244 int res_mkquery(int op
, const char *dname
, int class, int type
,
4245 const unsigned char *data
, int datalen
,
4246 const unsigned char *newrr_in
,
4247 unsigned char *buf
, int buflen
)
4250 unsigned char *cp
, *ep
;
4251 unsigned char *dnptrs
[20], **dpp
, **lastdnptr
;
4252 uint32_t _res_options
;
4255 if (!buf
|| buflen
< HFIXEDSZ
) {
4256 h_errno
= NETDB_INTERNAL
;
4261 __UCLIBC_MUTEX_LOCK(__resolv_lock
);
4262 _res_options
= _res
.options
;
4263 __UCLIBC_MUTEX_UNLOCK(__resolv_lock
);
4264 if (!(_res_options
& RES_INIT
)) {
4265 res_init(); /* our res_init never fails */
4270 if (_res_options
& RES_DEBUG
)
4271 printf(";; res_mkquery(%d, %s, %d, %d)\n",
4272 op
, dname
&& *dname
? dname
: "<null>", class, type
);
4275 memset(buf
, 0, HFIXEDSZ
);
4276 hp
= (HEADER
*) buf
;
4277 hp
->id
= getpid() & 0xffff;
4279 hp
->rd
= (_res_options
& RES_RECURSE
) != 0U;
4280 hp
->rcode
= NOERROR
;
4282 cp
= buf
+ HFIXEDSZ
;
4287 lastdnptr
= dnptrs
+ sizeof dnptrs
/ sizeof dnptrs
[0];
4290 * perform opcode specific processing
4295 if (ep
- cp
< QFIXEDSZ
)
4298 n
= dn_comp(dname
, cp
, ep
- cp
- QFIXEDSZ
, dnptrs
, lastdnptr
);
4304 NS_PUT16(class, cp
);
4305 hp
->qdcount
= htons(1);
4307 if (op
== QUERY
|| data
== NULL
)
4311 * Make an additional record for completion domain.
4313 if ((ep
- cp
) < RRFIXEDSZ
)
4316 n
= dn_comp((const char *)data
, cp
, ep
- cp
- RRFIXEDSZ
,
4322 NS_PUT16(T_NULL
, cp
);
4323 NS_PUT16(class, cp
);
4326 hp
->arcount
= htons(1);
4332 * Initialize answer section
4334 if (ep
- cp
< 1 + RRFIXEDSZ
+ datalen
)
4337 *cp
++ = '\0'; /*%< no domain name */
4339 NS_PUT16(class, cp
);
4341 NS_PUT16(datalen
, cp
);
4344 memcpy(cp
, data
, (size_t)datalen
);
4348 hp
->ancount
= htons(1);
4357 #endif /* L_res_data */
4359 /* Unimplemented: */