diff options
Diffstat (limited to 'libc/netbsd/resolv')
-rw-r--r-- | libc/netbsd/resolv/__dn_comp.c | 38 | ||||
-rw-r--r-- | libc/netbsd/resolv/__res_close.c | 33 | ||||
-rw-r--r-- | libc/netbsd/resolv/__res_send.c | 37 | ||||
-rw-r--r-- | libc/netbsd/resolv/herror.c | 133 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_cache.c | 1461 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_comp.c | 259 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_compat.c | 87 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_data.c | 332 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_debug.c | 1174 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_debug.h | 36 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_init.c | 863 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_mkquery.c | 276 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_private.h | 22 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_query.c | 415 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_random.c | 275 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_send.c | 1168 | ||||
-rw-r--r-- | libc/netbsd/resolv/res_state.c | 185 |
17 files changed, 0 insertions, 6794 deletions
diff --git a/libc/netbsd/resolv/__dn_comp.c b/libc/netbsd/resolv/__dn_comp.c deleted file mode 100644 index 93d3f19..0000000 --- a/libc/netbsd/resolv/__dn_comp.c +++ /dev/null @@ -1,38 +0,0 @@ -/* $NetBSD: __dn_comp.c,v 1.4 2005/09/13 01:44:10 christos Exp $ */ - -/* - * written by matthew green, 22/04/97. - * public domain. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: __dn_comp.c,v 1.4 2005/09/13 01:44:10 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#if defined(__indr_reference) -__indr_reference(__dn_comp,dn_comp) -#else - -#include <sys/types.h> -#include <netinet/in.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif - -/* XXX THIS IS A MESS! SEE <resolv.h> XXX */ - -#undef dn_comp -int dn_comp(const char *, u_char *, int, u_char **, u_char **); - -int -dn_comp(const char *exp_dn, u_char *comp_dn, u_char **dnptrs, - u_char **lastdnptr, int length) -{ - - return __dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr); -} - -#endif diff --git a/libc/netbsd/resolv/__res_close.c b/libc/netbsd/resolv/__res_close.c deleted file mode 100644 index 3af50b0..0000000 --- a/libc/netbsd/resolv/__res_close.c +++ /dev/null @@ -1,33 +0,0 @@ -/* $NetBSD: __res_close.c,v 1.4 2005/09/13 01:44:10 christos Exp $ */ - -/* - * written by matthew green, 22/04/97. - * public domain. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: __res_close.c,v 1.4 2005/09/13 01:44:10 christos Exp $"); -#endif /* LIBC_SCCS and not lint */ - -#if defined(__indr_reference) -__indr_reference(__res_close, res_close) -#else - -#include <sys/types.h> -#include <netinet/in.h> -#include "resolv_private.h" - -/* XXX THIS IS A MESS! SEE <resolv.h> XXX */ - -#undef res_close -void res_close(void); - -void -res_close(void) -{ - - __res_close(); -} - -#endif diff --git a/libc/netbsd/resolv/__res_send.c b/libc/netbsd/resolv/__res_send.c deleted file mode 100644 index 198b05c..0000000 --- a/libc/netbsd/resolv/__res_send.c +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: __res_send.c,v 1.4 2005/09/13 01:44:10 christos Exp $ */ - -/* - * written by matthew green, 22/04/97. - * public domain. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: __res_send.c,v 1.4 2005/09/13 01:44:10 christos Exp $"); -#endif - -#if defined(__indr_reference) -__indr_reference(__res_send, res_send) -#else - -#include <sys/types.h> -#include <netinet/in.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif - -/* XXX THIS IS A MESS! SEE <resolv.h> XXX */ - -#undef res_send -int res_send(const u_char *, int, u_char *, int); - -int -res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) -{ - - return __res_send(buf, buflen, ans, anssiz); -} - -#endif diff --git a/libc/netbsd/resolv/herror.c b/libc/netbsd/resolv/herror.c deleted file mode 100644 index e90e641..0000000 --- a/libc/netbsd/resolv/herror.c +++ /dev/null @@ -1,133 +0,0 @@ -/* $NetBSD: herror.c,v 1.4 2004/05/23 05:09:52 christos Exp $ */ - -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: herror.c,v 1.2.206.1 2004/03/09 08:33:54 marka Exp"; -#else -__RCSID("$NetBSD: herror.c,v 1.4 2004/05/23 05:09:52 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/uio.h> - -#include <netinet/in.h> -#include "arpa_nameser.h" - -#include <netdb.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif -#include <string.h> -#include <unistd.h> - -#ifndef DE_CONST -#define DE_CONST(c,v) v = ((c) ? \ - strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL) -#endif - -const char * const h_errlist[] = { - "Resolver Error 0 (no error)", - "Unknown host", /* 1 HOST_NOT_FOUND */ - "Host name lookup failure", /* 2 TRY_AGAIN */ - "Unknown server error", /* 3 NO_RECOVERY */ - "No address associated with name", /* 4 NO_ADDRESS */ -}; -const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; - -/* - * herror -- - * print the error indicated by the h_errno value. - */ -void -herror(const char *s) { - struct iovec iov[4], *v = iov; - char *t; - - if (s != NULL && *s != '\0') { - DE_CONST(s, t); - v->iov_base = t; - v->iov_len = strlen(t); - v++; - DE_CONST(": ", t); - v->iov_base = t; - v->iov_len = 2; - v++; - } - DE_CONST(hstrerror(h_errno), t); - v->iov_base = t; - v->iov_len = strlen(v->iov_base); - v++; - DE_CONST("\n", t); - v->iov_base = t; - v->iov_len = 1; - writev(STDERR_FILENO, iov, (v - iov) + 1); -} - -/* - * hstrerror -- - * return the string associated with a given "host" errno value. - */ -const char * -hstrerror(int err) { - if (err < 0) - return ("Resolver internal error"); - else if (err < h_nerr) - return (h_errlist[err]); - return ("Unknown resolver error"); -} diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c deleted file mode 100644 index 2c912de..0000000 --- a/libc/netbsd/resolv/res_cache.c +++ /dev/null @@ -1,1461 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "resolv_cache.h" -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include "pthread.h" - -/* This code implements a small and *simple* DNS resolver cache. - * - * It is only used to cache DNS answers for a maximum of CONFIG_SECONDS seconds - * in order to reduce DNS traffic. It is not supposed to be a full DNS cache, - * since we plan to implement that in the future in a dedicated process running - * on the system. - * - * Note that its design is kept simple very intentionally, i.e.: - * - * - it takes raw DNS query packet data as input, and returns raw DNS - * answer packet data as output - * - * (this means that two similar queries that encode the DNS name - * differently will be treated distinctly). - * - * - the TTLs of answer RRs are ignored. our DNS resolver library does not use - * them anyway, but it means that records with a TTL smaller than - * CONFIG_SECONDS will be kept in the cache anyway. - * - * this is bad, but we absolutely want to avoid parsing the answer packets - * (and should be solved by the later full DNS cache process). - * - * - the implementation is just a (query-data) => (answer-data) hash table - * with a trivial least-recently-used expiration policy. - * - * Doing this keeps the code simple and avoids to deal with a lot of things - * that a full DNS cache is expected to do. - * - * The API is also very simple: - * - * - the client calls _resolv_cache_get() to obtain a handle to the cache. - * this will initialize the cache on first usage. the result can be NULL - * if the cache is disabled. - * - * - the client calls _resolv_cache_lookup() before performing a query - * - * if the function returns RESOLV_CACHE_FOUND, a copy of the answer data - * has been copied into the client-provided answer buffer. - * - * if the function returns RESOLV_CACHE_NOTFOUND, the client should perform - * a request normally, *then* call _resolv_cache_add() to add the received - * answer to the cache. - * - * if the function returns RESOLV_CACHE_UNSUPPORTED, the client should - * perform a request normally, and *not* call _resolv_cache_add() - * - * note that RESOLV_CACHE_UNSUPPORTED is also returned if the answer buffer - * is too short to accomodate the cached result. - * - * - when network settings change, the cache must be flushed since the list - * of DNS servers probably changed. this is done by calling - * _resolv_cache_reset() - * - * the parameter to this function must be an ever-increasing generation - * number corresponding to the current network settings state. - * - * This is done because several threads could detect the same network - * settings change (but at different times) and will all end up calling the - * same function. Comparing with the last used generation number ensures - * that the cache is only flushed once per network change. - */ - -/* the name of an environment variable that will be checked the first time - * this code is called if its value is "0", then the resolver cache is - * disabled. - */ -#define CONFIG_ENV "BIONIC_DNSCACHE" - -/* entries older than CONFIG_SECONDS seconds are always discarded. - */ -#define CONFIG_SECONDS (60*10) /* 10 minutes */ - -/* maximum number of entries kept in the cache. This value has been - * determined by browsing through various sites and counting the number - * of corresponding requests. Keep in mind that our framework is currently - * performing two requests per name lookup (one for IPv4, the other for IPv6) - * - * www.google.com 4 - * www.ysearch.com 6 - * www.amazon.com 8 - * www.nytimes.com 22 - * www.espn.com 28 - * www.msn.com 28 - * www.lemonde.fr 35 - * - * (determined in 2009-2-17 from Paris, France, results may vary depending - * on location) - * - * most high-level websites use lots of media/ad servers with different names - * but these are generally reused when browsing through the site. - * - * As such, a valud of 64 should be relatively conformtable at the moment. - */ -#define CONFIG_MAX_ENTRIES 64 - -/****************************************************************************/ -/****************************************************************************/ -/***** *****/ -/***** *****/ -/***** *****/ -/****************************************************************************/ -/****************************************************************************/ - -/* set to 1 to debug cache operations */ -#define DEBUG 0 - -/* set to 1 to debug query data */ -#define DEBUG_DATA 0 - -#if DEBUG -# include <logd.h> -# define XLOG(...) \ - __libc_android_log_print(ANDROID_LOG_DEBUG,"libc",__VA_ARGS__) - -#include <stdio.h> -#include <stdarg.h> - -/** BOUNDED BUFFER FORMATTING - **/ - -/* technical note: - * - * the following debugging routines are used to append data to a bounded - * buffer they take two parameters that are: - * - * - p : a pointer to the current cursor position in the buffer - * this value is initially set to the buffer's address. - * - * - end : the address of the buffer's limit, i.e. of the first byte - * after the buffer. this address should never be touched. - * - * IMPORTANT: it is assumed that end > buffer_address, i.e. - * that the buffer is at least one byte. - * - * the _bprint_() functions return the new value of 'p' after the data - * has been appended, and also ensure the following: - * - * - the returned value will never be strictly greater than 'end' - * - * - a return value equal to 'end' means that truncation occured - * (in which case, end[-1] will be set to 0) - * - * - after returning from a _bprint_() function, the content of the buffer - * is always 0-terminated, even in the event of truncation. - * - * these conventions allow you to call _bprint_ functions multiple times and - * only check for truncation at the end of the sequence, as in: - * - * char buff[1000], *p = buff, *end = p + sizeof(buff); - * - * p = _bprint_c(p, end, '"'); - * p = _bprint_s(p, end, my_string); - * p = _bprint_c(p, end, '"'); - * - * if (p >= end) { - * // buffer was too small - * } - * - * printf( "%s", buff ); - */ - -/* add a char to a bounded buffer */ -static char* -_bprint_c( char* p, char* end, int c ) -{ - if (p < end) { - if (p+1 == end) - *p++ = 0; - else { - *p++ = (char) c; - *p = 0; - } - } - return p; -} - -/* add a sequence of bytes to a bounded buffer */ -static char* -_bprint_b( char* p, char* end, const char* buf, int len ) -{ - int avail = end - p; - - if (avail <= 0 || len <= 0) - return p; - - if (avail > len) - avail = len; - - memcpy( p, buf, avail ); - p += avail; - - if (p < end) - p[0] = 0; - else - end[-1] = 0; - - return p; -} - -/* add a string to a bounded buffer */ -static char* -_bprint_s( char* p, char* end, const char* str ) -{ - return _bprint_b(p, end, str, strlen(str)); -} - -/* add a formatted string to a bounded buffer */ -static char* -_bprint( char* p, char* end, const char* format, ... ) -{ - int avail, n; - va_list args; - - avail = end - p; - - if (avail <= 0) - return p; - - va_start(args, format); - n = snprintf( p, avail, format, args); - va_end(args); - - /* certain C libraries return -1 in case of truncation */ - if (n < 0 || n > avail) - n = avail; - - p += n; - /* certain C libraries do not zero-terminate in case of truncation */ - if (p == end) - p[-1] = 0; - - return p; -} - -/* add a hex value to a bounded buffer, up to 8 digits */ -static char* -_bprint_hex( char* p, char* end, unsigned value, int numDigits ) -{ - char text[sizeof(unsigned)*2]; - int nn = 0; - - while (numDigits-- > 0) { - text[nn++] = "0123456789abcdef"[(value >> (numDigits*4)) & 15]; - } - return _bprint_b(p, end, text, nn); -} - -/* add the hexadecimal dump of some memory area to a bounded buffer */ -static char* -_bprint_hexdump( char* p, char* end, const uint8_t* data, int datalen ) -{ - int lineSize = 16; - - while (datalen > 0) { - int avail = datalen; - int nn; - - if (avail > lineSize) - avail = lineSize; - - for (nn = 0; nn < avail; nn++) { - if (nn > 0) - p = _bprint_c(p, end, ' '); - p = _bprint_hex(p, end, data[nn], 2); - } - for ( ; nn < lineSize; nn++ ) { - p = _bprint_s(p, end, " "); - } - p = _bprint_s(p, end, " "); - - for (nn = 0; nn < avail; nn++) { - int c = data[nn]; - - if (c < 32 || c > 127) - c = '.'; - - p = _bprint_c(p, end, c); - } - p = _bprint_c(p, end, '\n'); - - data += avail; - datalen -= avail; - } - return p; -} - -/* dump the content of a query of packet to the log */ -static void -XLOG_BYTES( const void* base, int len ) -{ - char buff[1024]; - char* p = buff, *end = p + sizeof(buff); - - p = _bprint_hexdump(p, end, base, len); - XLOG("%s",buff); -} - -#else /* !DEBUG */ -# define XLOG(...) ((void)0) -# define XLOG_BYTES(a,b) ((void)0) -#endif - -static time_t -_time_now( void ) -{ - struct timeval tv; - - gettimeofday( &tv, NULL ); - return tv.tv_sec; -} - -/* reminder: the general format of a DNS packet is the following: - * - * HEADER (12 bytes) - * QUESTION (variable) - * ANSWER (variable) - * AUTHORITY (variable) - * ADDITIONNAL (variable) - * - * the HEADER is made of: - * - * ID : 16 : 16-bit unique query identification field - * - * QR : 1 : set to 0 for queries, and 1 for responses - * Opcode : 4 : set to 0 for queries - * AA : 1 : set to 0 for queries - * TC : 1 : truncation flag, will be set to 0 in queries - * RD : 1 : recursion desired - * - * RA : 1 : recursion available (0 in queries) - * Z : 3 : three reserved zero bits - * RCODE : 4 : response code (always 0=NOERROR in queries) - * - * QDCount: 16 : question count - * ANCount: 16 : Answer count (0 in queries) - * NSCount: 16: Authority Record count (0 in queries) - * ARCount: 16: Additionnal Record count (0 in queries) - * - * the QUESTION is made of QDCount Question Record (QRs) - * the ANSWER is made of ANCount RRs - * the AUTHORITY is made of NSCount RRs - * the ADDITIONNAL is made of ARCount RRs - * - * Each Question Record (QR) is made of: - * - * QNAME : variable : Query DNS NAME - * TYPE : 16 : type of query (A=1, PTR=12, MX=15, AAAA=28, ALL=255) - * CLASS : 16 : class of query (IN=1) - * - * Each Resource Record (RR) is made of: - * - * NAME : variable : DNS NAME - * TYPE : 16 : type of query (A=1, PTR=12, MX=15, AAAA=28, ALL=255) - * CLASS : 16 : class of query (IN=1) - * TTL : 32 : seconds to cache this RR (0=none) - * RDLENGTH: 16 : size of RDDATA in bytes - * RDDATA : variable : RR data (depends on TYPE) - * - * Each QNAME contains a domain name encoded as a sequence of 'labels' - * terminated by a zero. Each label has the following format: - * - * LEN : 8 : lenght of label (MUST be < 64) - * NAME : 8*LEN : label length (must exclude dots) - * - * A value of 0 in the encoding is interpreted as the 'root' domain and - * terminates the encoding. So 'www.android.com' will be encoded as: - * - * <3>www<7>android<3>com<0> - * - * Where <n> represents the byte with value 'n' - * - * Each NAME reflects the QNAME of the question, but has a slightly more - * complex encoding in order to provide message compression. This is achieved - * by using a 2-byte pointer, with format: - * - * TYPE : 2 : 0b11 to indicate a pointer, 0b01 and 0b10 are reserved - * OFFSET : 14 : offset to another part of the DNS packet - * - * The offset is relative to the start of the DNS packet and must point - * A pointer terminates the encoding. - * - * The NAME can be encoded in one of the following formats: - * - * - a sequence of simple labels terminated by 0 (like QNAMEs) - * - a single pointer - * - a sequence of simple labels terminated by a pointer - * - * A pointer shall always point to either a pointer of a sequence of - * labels (which can themselves be terminated by either a 0 or a pointer) - * - * The expanded length of a given domain name should not exceed 255 bytes. - * - * NOTE: we don't parse the answer packets, so don't need to deal with NAME - * records, only QNAMEs. - */ - -#define DNS_HEADER_SIZE 12 - -#define DNS_TYPE_A "\00\01" /* big-endian decimal 1 */ -#define DNS_TYPE_PTR "\00\014" /* big-endian decimal 12 */ -#define DNS_TYPE_MX "\00\017" /* big-endian decimal 15 */ -#define DNS_TYPE_AAAA "\00\034" /* big-endian decimal 28 */ -#define DNS_TYPE_ALL "\00\0377" /* big-endian decimal 255 */ - -#define DNS_CLASS_IN "\00\01" /* big-endian decimal 1 */ - -typedef struct { - const uint8_t* base; - const uint8_t* end; - const uint8_t* cursor; -} DnsPacket; - -static void -_dnsPacket_init( DnsPacket* packet, const uint8_t* buff, int bufflen ) -{ - packet->base = buff; - packet->end = buff + bufflen; - packet->cursor = buff; -} - -static void -_dnsPacket_rewind( DnsPacket* packet ) -{ - packet->cursor = packet->base; -} - -static void -_dnsPacket_skip( DnsPacket* packet, int count ) -{ - const uint8_t* p = packet->cursor + count; - - if (p > packet->end) - p = packet->end; - - packet->cursor = p; -} - -static int -_dnsPacket_readInt16( DnsPacket* packet ) -{ - const uint8_t* p = packet->cursor; - - if (p+2 > packet->end) - return -1; - - packet->cursor = p+2; - return (p[0]<< 8) | p[1]; -} - -/** QUERY CHECKING - **/ - -/* check bytes in a dns packet. returns 1 on success, 0 on failure. - * the cursor is only advanced in the case of success - */ -static int -_dnsPacket_checkBytes( DnsPacket* packet, int numBytes, const void* bytes ) -{ - const uint8_t* p = packet->cursor; - - if (p + numBytes > packet->end) - return 0; - - if (memcmp(p, bytes, numBytes) != 0) - return 0; - - packet->cursor = p + numBytes; - return 1; -} - -/* parse and skip a given QNAME stored in a query packet, - * from the current cursor position. returns 1 on success, - * or 0 for malformed data. - */ -static int -_dnsPacket_checkQName( DnsPacket* packet ) -{ - const uint8_t* p = packet->cursor; - const uint8_t* end = packet->end; - - for (;;) { - int c; - - if (p >= end) - break; - - c = *p++; - - if (c == 0) { - packet->cursor = p; - return 1; - } - - /* we don't expect label compression in QNAMEs */ - if (c >= 64) - break; - - p += c; - /* we rely on the bound check at the start - * of the loop here */ - } - /* malformed data */ - XLOG("malformed QNAME"); - return 0; -} - -/* parse and skip a given QR stored in a packet. - * returns 1 on success, and 0 on failure - */ -static int -_dnsPacket_checkQR( DnsPacket* packet ) -{ - int len; - - if (!_dnsPacket_checkQName(packet)) - return 0; - - /* TYPE must be one of the things we support */ - if (!_dnsPacket_checkBytes(packet, 2, DNS_TYPE_A) && - !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_PTR) && - !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_MX) && - !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_AAAA) && - !_dnsPacket_checkBytes(packet, 2, DNS_TYPE_ALL)) - { - XLOG("unsupported TYPE"); - return 0; - } - /* CLASS must be IN */ - if (!_dnsPacket_checkBytes(packet, 2, DNS_CLASS_IN)) { - XLOG("unsupported CLASS"); - return 0; - } - - return 1; -} - -/* check the header of a DNS Query packet, return 1 if it is one - * type of query we can cache, or 0 otherwise - */ -static int -_dnsPacket_checkQuery( DnsPacket* packet ) -{ - const uint8_t* p = packet->base; - int qdCount, anCount, dnCount, arCount; - - if (p + DNS_HEADER_SIZE > packet->end) { - XLOG("query packet too small"); - return 0; - } - - /* QR must be set to 0, opcode must be 0 and AA must be 0 */ - /* RA, Z, and RCODE must be 0 */ - if ((p[2] & 0xFC) != 0 || p[3] != 0) { - XLOG("query packet flags unsupported"); - return 0; - } - - /* Note that we ignore the TC and RD bits here for the - * following reasons: - * - * - there is no point for a query packet sent to a server - * to have the TC bit set, but the implementation might - * set the bit in the query buffer for its own needs - * between a _resolv_cache_lookup and a - * _resolv_cache_add. We should not freak out if this - * is the case. - * - * - we consider that the result from a RD=0 or a RD=1 - * query might be different, hence that the RD bit - * should be used to differentiate cached result. - * - * this implies that RD is checked when hashing or - * comparing query packets, but not TC - */ - - /* ANCOUNT, DNCOUNT and ARCOUNT must be 0 */ - qdCount = (p[4] << 8) | p[5]; - anCount = (p[6] << 8) | p[7]; - dnCount = (p[8] << 8) | p[9]; - arCount = (p[10]<< 8) | p[11]; - - if (anCount != 0 || dnCount != 0 || arCount != 0) { - XLOG("query packet contains non-query records"); - return 0; - } - - if (qdCount == 0) { - XLOG("query packet doesn't contain query record"); - return 0; - } - - /* Check QDCOUNT QRs */ - packet->cursor = p + DNS_HEADER_SIZE; - - for (;qdCount > 0; qdCount--) - if (!_dnsPacket_checkQR(packet)) - return 0; - - return 1; -} - -/** QUERY DEBUGGING - **/ -#if DEBUG -static char* -_dnsPacket_bprintQName(DnsPacket* packet, char* bp, char* bend) -{ - const uint8_t* p = packet->cursor; - const uint8_t* end = packet->end; - int first = 1; - - for (;;) { - int c; - - if (p >= end) - break; - - c = *p++; - - if (c == 0) { - packet->cursor = p; - return bp; - } - - /* we don't expect label compression in QNAMEs */ - if (c >= 64) - break; - - if (first) - first = 0; - else - bp = _bprint_c(bp, bend, '.'); - - bp = _bprint_b(bp, bend, (const char*)p, c); - - p += c; - /* we rely on the bound check at the start - * of the loop here */ - } - /* malformed data */ - bp = _bprint_s(bp, bend, "<MALFORMED>"); - return bp; -} - -static char* -_dnsPacket_bprintQR(DnsPacket* packet, char* p, char* end) -{ -#define QQ(x) { DNS_TYPE_##x, #x } - static const struct { - const char* typeBytes; - const char* typeString; - } qTypes[] = - { - QQ(A), QQ(PTR), QQ(MX), QQ(AAAA), QQ(ALL), - { NULL, NULL } - }; - int nn; - const char* typeString = NULL; - - /* dump QNAME */ - p = _dnsPacket_bprintQName(packet, p, end); - - /* dump TYPE */ - p = _bprint_s(p, end, " ("); - - for (nn = 0; qTypes[nn].typeBytes != NULL; nn++) { - if (_dnsPacket_checkBytes(packet, 2, qTypes[nn].typeBytes)) { - typeString = qTypes[nn].typeString; - break; - } - } - - if (typeString != NULL) - p = _bprint_s(p, end, typeString); - else { - int typeCode = _dnsPacket_readInt16(packet); - p = _bprint(p, end, "UNKNOWN-%d", typeCode); - } - - p = _bprint_c(p, end, ')'); - - /* skip CLASS */ - _dnsPacket_skip(packet, 2); - return p; -} - -/* this function assumes the packet has already been checked */ -static char* -_dnsPacket_bprintQuery( DnsPacket* packet, char* p, char* end ) -{ - int qdCount; - - if (packet->base[2] & 0x1) { - p = _bprint_s(p, end, "RECURSIVE "); - } - - _dnsPacket_skip(packet, 4); - qdCount = _dnsPacket_readInt16(packet); - _dnsPacket_skip(packet, 6); - - for ( ; qdCount > 0; qdCount-- ) { - p = _dnsPacket_bprintQR(packet, p, end); - } - return p; -} -#endif - - -/** QUERY HASHING SUPPORT - ** - ** THE FOLLOWING CODE ASSUMES THAT THE INPUT PACKET HAS ALREADY - ** BEEN SUCCESFULLY CHECKED. - **/ - -/* use 32-bit FNV hash function */ -#define FNV_MULT 16777619U -#define FNV_BASIS 2166136261U - -static unsigned -_dnsPacket_hashBytes( DnsPacket* packet, int numBytes, unsigned hash ) -{ - const uint8_t* p = packet->cursor; - const uint8_t* end = packet->end; - - while (numBytes > 0 && p < end) { - hash = hash*FNV_MULT ^ *p++; - } - packet->cursor = p; - return hash; -} - - -static unsigned -_dnsPacket_hashQName( DnsPacket* packet, unsigned hash ) -{ - const uint8_t* p = packet->cursor; - const uint8_t* end = packet->end; - - for (;;) { - int c; - - if (p >= end) { /* should not happen */ - XLOG("%s: INTERNAL_ERROR: read-overflow !!\n", __FUNCTION__); - break; - } - - c = *p++; - - if (c == 0) - break; - - if (c >= 64) { - XLOG("%s: INTERNAL_ERROR: malformed domain !!\n", __FUNCTION__); - break; - } - if (p + c >= end) { - XLOG("%s: INTERNAL_ERROR: simple label read-overflow !!\n", - __FUNCTION__); - break; - } - while (c > 0) { - hash = hash*FNV_MULT ^ *p++; - c -= 1; - } - } - packet->cursor = p; - return hash; -} - -static unsigned -_dnsPacket_hashQR( DnsPacket* packet, unsigned hash ) -{ - int len; - - hash = _dnsPacket_hashQName(packet, hash); - hash = _dnsPacket_hashBytes(packet, 4, hash); /* TYPE and CLASS */ - return hash; -} - -static unsigned -_dnsPacket_hashQuery( DnsPacket* packet ) -{ - unsigned hash = FNV_BASIS; - int count; - _dnsPacket_rewind(packet); - - /* we ignore the TC bit for reasons explained in - * _dnsPacket_checkQuery(). - * - * however we hash the RD bit to differentiate - * between answers for recursive and non-recursive - * queries. - */ - hash = hash*FNV_MULT ^ (packet->base[2] & 1); - - /* assume: other flags are 0 */ - _dnsPacket_skip(packet, 4); - - /* read QDCOUNT */ - count = _dnsPacket_readInt16(packet); - - /* assume: ANcount, NScount, ARcount are 0 */ - _dnsPacket_skip(packet, 6); - - /* hash QDCOUNT QRs */ - for ( ; count > 0; count-- ) - hash = _dnsPacket_hashQR(packet, hash); - - return hash; -} - - -/** QUERY COMPARISON - ** - ** THE FOLLOWING CODE ASSUMES THAT THE INPUT PACKETS HAVE ALREADY - ** BEEN SUCCESFULLY CHECKED. - **/ - -static int -_dnsPacket_isEqualDomainName( DnsPacket* pack1, DnsPacket* pack2 ) -{ - const uint8_t* p1 = pack1->cursor; - const uint8_t* end1 = pack1->end; - const uint8_t* p2 = pack2->cursor; - const uint8_t* end2 = pack2->end; - - for (;;) { - int c1, c2; - - if (p1 >= end1 || p2 >= end2) { - XLOG("%s: INTERNAL_ERROR: read-overflow !!\n", __FUNCTION__); - break; - } - c1 = *p1++; - c2 = *p2++; - if (c1 != c2) - break; - - if (c1 == 0) { - pack1->cursor = p1; - pack2->cursor = p2; - return 1; - } - if (c1 >= 64) { - XLOG("%s: INTERNAL_ERROR: malformed domain !!\n", __FUNCTION__); - break; - } - if ((p1+c1 > end1) || (p2+c1 > end2)) { - XLOG("%s: INTERNAL_ERROR: simple label read-overflow !!\n", - __FUNCTION__); - break; - } - if (memcmp(p1, p2, c1) != 0) - break; - p1 += c1; - p2 += c1; - /* we rely on the bound checks at the start of the loop */ - } - /* not the same, or one is malformed */ - XLOG("different DN"); - return 0; -} - -static int -_dnsPacket_isEqualBytes( DnsPacket* pack1, DnsPacket* pack2, int numBytes ) -{ - const uint8_t* p1 = pack1->cursor; - const uint8_t* p2 = pack2->cursor; - - if ( p1 + numBytes > pack1->end || p2 + numBytes > pack2->end ) - return 0; - - if ( memcmp(p1, p2, numBytes) != 0 ) - return 0; - - pack1->cursor += numBytes; - pack2->cursor += numBytes; - return 1; -} - -static int -_dnsPacket_isEqualQR( DnsPacket* pack1, DnsPacket* pack2 ) -{ - /* compare domain name encoding + TYPE + CLASS */ - if ( !_dnsPacket_isEqualDomainName(pack1, pack2) || - !_dnsPacket_isEqualBytes(pack1, pack2, 2+2) ) - return 0; - - return 1; -} - -static int -_dnsPacket_isEqualQuery( DnsPacket* pack1, DnsPacket* pack2 ) -{ - int count1, count2; - - /* compare the headers, ignore most fields */ - _dnsPacket_rewind(pack1); - _dnsPacket_rewind(pack2); - - /* compare RD, ignore TC, see comment in _dnsPacket_checkQuery */ - if ((pack1->base[2] & 1) != (pack2->base[2] & 1)) { - XLOG("different RD"); - return 0; - } - - /* assume: other flags are all 0 */ - _dnsPacket_skip(pack1, 4); - _dnsPacket_skip(pack2, 4); - - /* compare QDCOUNT */ - count1 = _dnsPacket_readInt16(pack1); - count2 = _dnsPacket_readInt16(pack2); - if (count1 != count2 || count1 < 0) { - XLOG("different QDCOUNT"); - return 0; - } - - /* assume: ANcount, NScount and ARcount are all 0 */ - _dnsPacket_skip(pack1, 6); - _dnsPacket_skip(pack2, 6); - - /* compare the QDCOUNT QRs */ - for ( ; count1 > 0; count1-- ) { - if (!_dnsPacket_isEqualQR(pack1, pack2)) { - XLOG("different QR"); - return 0; - } - } - return 1; -} - -/****************************************************************************/ -/****************************************************************************/ -/***** *****/ -/***** *****/ -/***** *****/ -/****************************************************************************/ -/****************************************************************************/ - -/* cache entry. for simplicity, 'hash' and 'hlink' are inlined in this - * structure though they are conceptually part of the hash table. - * - * similarly, mru_next and mru_prev are part of the global MRU list - */ -typedef struct Entry { - unsigned int hash; /* hash value */ - struct Entry* hlink; /* next in collision chain */ - struct Entry* mru_prev; - struct Entry* mru_next; - - const uint8_t* query; - int querylen; - const uint8_t* answer; - int answerlen; - time_t when; /* time_t when entry was added to table */ - int id; /* for debugging purpose */ -} Entry; - - -static void -entry_free( Entry* e ) -{ - /* everything is allocated in a single memory block */ - if (e) { - free(e); - } -} - -static __inline__ void -entry_mru_remove( Entry* e ) -{ - e->mru_prev->mru_next = e->mru_next; - e->mru_next->mru_prev = e->mru_prev; -} - -static __inline__ void -entry_mru_add( Entry* e, Entry* list ) -{ - Entry* first = list->mru_next; - - e->mru_next = first; - e->mru_prev = list; - - list->mru_next = e; - first->mru_prev = e; -} - -/* compute the hash of a given entry, this is a hash of most - * data in the query (key) */ -static unsigned -entry_hash( const Entry* e ) -{ - DnsPacket pack[1]; - - _dnsPacket_init(pack, e->query, e->querylen); - return _dnsPacket_hashQuery(pack); -} - -/* initialize an Entry as a search key, this also checks the input query packet - * returns 1 on success, or 0 in case of unsupported/malformed data */ -static int -entry_init_key( Entry* e, const void* query, int querylen ) -{ - DnsPacket pack[1]; - - memset(e, 0, sizeof(*e)); - - e->query = query; - e->querylen = querylen; - e->hash = entry_hash(e); - - _dnsPacket_init(pack, query, querylen); - - return _dnsPacket_checkQuery(pack); -} - -/* allocate a new entry as a cache node */ -static Entry* -entry_alloc( const Entry* init, const void* answer, int answerlen ) -{ - Entry* e; - int size; - - size = sizeof(*e) + init->querylen + answerlen; - e = calloc(size, 1); - if (e == NULL) - return e; - - e->hash = init->hash; - e->query = (const uint8_t*)(e+1); - e->querylen = init->querylen; - - memcpy( (char*)e->query, init->query, e->querylen ); - - e->answer = e->query + e->querylen; - e->answerlen = answerlen; - - memcpy( (char*)e->answer, answer, e->answerlen ); - - e->when = _time_now(); - - return e; -} - -static int -entry_equals( const Entry* e1, const Entry* e2 ) -{ - DnsPacket pack1[1], pack2[1]; - - if (e1->querylen != e2->querylen) { - return 0; - } - _dnsPacket_init(pack1, e1->query, e1->querylen); - _dnsPacket_init(pack2, e2->query, e2->querylen); - - return _dnsPacket_isEqualQuery(pack1, pack2); -} - -/****************************************************************************/ -/****************************************************************************/ -/***** *****/ -/***** *****/ -/***** *****/ -/****************************************************************************/ -/****************************************************************************/ - -/* We use a simple hash table with external collision lists - * for simplicity, the hash-table fields 'hash' and 'hlink' are - * inlined in the Entry structure. - */ -#define MAX_HASH_ENTRIES (2*CONFIG_MAX_ENTRIES) - -typedef struct resolv_cache { - int num_entries; - Entry mru_list; - pthread_mutex_t lock; - unsigned generation; - int last_id; - Entry* entries[ MAX_HASH_ENTRIES ]; -} Cache; - - -#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED) - -static void -_cache_flush_locked( Cache* cache ) -{ - int nn; - time_t now = _time_now(); - - for (nn = 0; nn < MAX_HASH_ENTRIES; nn++) - { - Entry** pnode = &cache->entries[nn]; - - while (*pnode != NULL) { - Entry* node = *pnode; - *pnode = node->hlink; - entry_free(node); - } - } - - cache->mru_list.mru_next = cache->mru_list.mru_prev = &cache->mru_list; - cache->num_entries = 0; - cache->last_id = 0; - - XLOG("*************************\n" - "*** DNS CACHE FLUSHED ***\n" - "*************************"); -} - -struct resolv_cache* -_resolv_cache_create( void ) -{ - struct resolv_cache* cache; - - cache = calloc(sizeof(*cache), 1); - if (cache) { - cache->generation = ~0U; - pthread_mutex_init( &cache->lock, NULL ); - cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list; - XLOG("%s: cache created\n", __FUNCTION__); - } - return cache; -} - - -#if DEBUG -static void -_dump_query( const uint8_t* query, int querylen ) -{ - char temp[256], *p=temp, *end=p+sizeof(temp); - DnsPacket pack[1]; - - _dnsPacket_init(pack, query, querylen); - p = _dnsPacket_bprintQuery(pack, p, end); - XLOG("QUERY: %s", temp); -} - -static void -_cache_dump_mru( Cache* cache ) -{ - char temp[512], *p=temp, *end=p+sizeof(temp); - Entry* e; - - p = _bprint(temp, end, "MRU LIST (%2d): ", cache->num_entries); - for (e = cache->mru_list.mru_next; e != &cache->mru_list; e = e->mru_next) - p = _bprint(p, end, " %d", e->id); - - XLOG("%s", temp); -} -#endif - -#if DEBUG -# define XLOG_QUERY(q,len) _dump_query((q), (len)) -#else -# define XLOG_QUERY(q,len) ((void)0) -#endif - -/* This function tries to find a key within the hash table - * In case of success, it will return a *pointer* to the hashed key. - * In case of failure, it will return a *pointer* to NULL - * - * So, the caller must check '*result' to check for success/failure. - * - * The main idea is that the result can later be used directly in - * calls to _resolv_cache_add or _resolv_cache_remove as the 'lookup' - * parameter. This makes the code simpler and avoids re-searching - * for the key position in the htable. - * - * The result of a lookup_p is only valid until you alter the hash - * table. - */ -static Entry** -_cache_lookup_p( Cache* cache, - Entry* key ) -{ - int index = key->hash % MAX_HASH_ENTRIES; - Entry** pnode = &cache->entries[ key->hash % MAX_HASH_ENTRIES ]; - - while (*pnode != NULL) { - Entry* node = *pnode; - - if (node == NULL) - break; - - if (node->hash == key->hash && entry_equals(node, key)) - break; - - pnode = &node->hlink; - } - return pnode; -} - -/* Add a new entry to the hash table. 'lookup' must be the - * result of an immediate previous failed _lookup_p() call - * (i.e. with *lookup == NULL), and 'e' is the pointer to the - * newly created entry - */ -static void -_cache_add_p( Cache* cache, - Entry** lookup, - Entry* e ) -{ - *lookup = e; - e->id = ++cache->last_id; - entry_mru_add(e, &cache->mru_list); - cache->num_entries += 1; - - XLOG("%s: entry %d added (count=%d)", __FUNCTION__, - e->id, cache->num_entries); -} - -/* Remove an existing entry from the hash table, - * 'lookup' must be the result of an immediate previous - * and succesful _lookup_p() call. - */ -static void -_cache_remove_p( Cache* cache, - Entry** lookup ) -{ - Entry* e = *lookup; - - XLOG("%s: entry %d removed (count=%d)", __FUNCTION__, - e->id, cache->num_entries-1); - - entry_mru_remove(e); - *lookup = e->hlink; - entry_free(e); - cache->num_entries -= 1; -} - -/* Remove the oldest entry from the hash table. - */ -static void -_cache_remove_oldest( Cache* cache ) -{ - Entry* oldest = cache->mru_list.mru_prev; - Entry** lookup = _cache_lookup_p(cache, oldest); - - if (*lookup == NULL) { /* should not happen */ - XLOG("%s: OLDEST NOT IN HTABLE ?", __FUNCTION__); - return; - } - _cache_remove_p(cache, lookup); -} - - -ResolvCacheStatus -_resolv_cache_lookup( struct resolv_cache* cache, - const void* query, - int querylen, - void* answer, - int answersize, - int *answerlen ) -{ - DnsPacket pack[1]; - Entry key[1]; - int index; - Entry** lookup; - Entry* e; - time_t now; - - ResolvCacheStatus result = RESOLV_CACHE_NOTFOUND; - - XLOG("%s: lookup", __FUNCTION__); - XLOG_QUERY(query, querylen); - - /* we don't cache malformed queries */ - if (!entry_init_key(key, query, querylen)) { - XLOG("%s: unsupported query", __FUNCTION__); - return RESOLV_CACHE_UNSUPPORTED; - } - /* lookup cache */ - pthread_mutex_lock( &cache->lock ); - - /* see the description of _lookup_p to understand this. - * the function always return a non-NULL pointer. - */ - lookup = _cache_lookup_p(cache, key); - e = *lookup; - - if (e == NULL) { - XLOG( "NOT IN CACHE"); - goto Exit; - } - - now = _time_now(); - - /* remove stale entries here */ - if ( (unsigned)(now - e->when) >= CONFIG_SECONDS ) { - XLOG( " NOT IN CACHE (STALE ENTRY %p DISCARDED)", *lookup ); - _cache_remove_p(cache, lookup); - goto Exit; - } - - *answerlen = e->answerlen; - if (e->answerlen > answersize) { - /* NOTE: we return UNSUPPORTED if the answer buffer is too short */ - result = RESOLV_CACHE_UNSUPPORTED; - XLOG(" ANSWER TOO LONG"); - goto Exit; - } - - memcpy( answer, e->answer, e->answerlen ); - - /* bump up this entry to the top of the MRU list */ - if (e != cache->mru_list.mru_next) { - entry_mru_remove( e ); - entry_mru_add( e, &cache->mru_list ); - } - - XLOG( "FOUND IN CACHE entry=%p", e ); - result = RESOLV_CACHE_FOUND; - -Exit: - pthread_mutex_unlock( &cache->lock ); - return result; -} - - -void -_resolv_cache_add( struct resolv_cache* cache, - const void* query, - int querylen, - const void* answer, - int answerlen ) -{ - Entry key[1]; - Entry* e; - Entry** lookup; - - /* don't assume that the query has already been cached - */ - if (!entry_init_key( key, query, querylen )) { - XLOG( "%s: passed invalid query ?", __FUNCTION__); - return; - } - - pthread_mutex_lock( &cache->lock ); - - XLOG( "%s: query:", __FUNCTION__ ); - XLOG_QUERY(query,querylen); -#if DEBUG_DATA - XLOG( "answer:"); - XLOG_BYTES(answer,answerlen); -#endif - - lookup = _cache_lookup_p(cache, key); - e = *lookup; - - if (e != NULL) { /* should not happen */ - XLOG("%s: ALREADY IN CACHE (%p) ? IGNORING ADD", - __FUNCTION__, e); - goto Exit; - } - - if (cache->num_entries >= CONFIG_MAX_ENTRIES) { - _cache_remove_oldest(cache); - /* need to lookup again */ - lookup = _cache_lookup_p(cache, key); - e = *lookup; - if (e != NULL) { - XLOG("%s: ALREADY IN CACHE (%p) ? IGNORING ADD", - __FUNCTION__, e); - goto Exit; - } - } - - e = entry_alloc( key, answer, answerlen ); - if (e != NULL) { - _cache_add_p(cache, lookup, e); - } -#if DEBUG - _cache_dump_mru(cache); -#endif -Exit: - pthread_mutex_unlock( &cache->lock ); -} - -/****************************************************************************/ -/****************************************************************************/ -/***** *****/ -/***** *****/ -/***** *****/ -/****************************************************************************/ -/****************************************************************************/ - -static struct resolv_cache* _res_cache; -static pthread_once_t _res_cache_once; - -static void -_res_cache_init( void ) -{ - const char* env = getenv(CONFIG_ENV); - - if (env && atoi(env) == 0) { - /* the cache is disabled */ - return; - } - - _res_cache = _resolv_cache_create(); -} - - -struct resolv_cache* -__get_res_cache( void ) -{ - pthread_once( &_res_cache_once, _res_cache_init ); - return _res_cache; -} - -void -_resolv_cache_reset( unsigned generation ) -{ - XLOG("%s: generation=%d", __FUNCTION__, generation); - - if (_res_cache == NULL) - return; - - pthread_mutex_lock( &_res_cache->lock ); - if (_res_cache->generation != generation) { - _cache_flush_locked(_res_cache); - _res_cache->generation = generation; - } - pthread_mutex_unlock( &_res_cache->lock ); -} diff --git a/libc/netbsd/resolv/res_comp.c b/libc/netbsd/resolv/res_comp.c deleted file mode 100644 index 6991e8b..0000000 --- a/libc/netbsd/resolv/res_comp.c +++ /dev/null @@ -1,259 +0,0 @@ -/* $NetBSD: res_comp.c,v 1.6 2004/05/22 23:47:09 christos Exp $ */ - -/* - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: res_comp.c,v 1.1.2.1.4.1 2004/03/09 08:33:54 marka Exp"; -#else -__RCSID("$NetBSD: res_comp.c,v 1.6 2004/05/22 23:47:09 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/param.h> -#include <netinet/in.h> -#include "arpa_nameser.h" -#include <ctype.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif -#include <stdio.h> -#include <string.h> -#include <unistd.h> - -/* - * Expand compressed domain name 'src' to full domain name. - * 'msg' is a pointer to the begining of the message, - * 'eom' points to the first location after the message, - * 'dst' is a pointer to a buffer of size 'dstsiz' for the result. - * Return size of compressed name or -1 if there was an error. - */ -int -dn_expand(const u_char *msg, const u_char *eom, const u_char *src, - char *dst, int dstsiz) -{ - int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); - - if (n > 0 && dst[0] == '.') - dst[0] = '\0'; - return (n); -} - -/* - * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. - * Return the size of the compressed name or -1. - * 'length' is the size of the array pointed to by 'comp_dn'. - */ -int -dn_comp(const char *src, u_char *dst, int dstsiz, - u_char **dnptrs, u_char **lastdnptr) -{ - return (ns_name_compress(src, dst, (size_t)dstsiz, - (const u_char **)dnptrs, - (const u_char **)lastdnptr)); -} - -/* - * Skip over a compressed domain name. Return the size or -1. - */ -int -dn_skipname(const u_char *ptr, const u_char *eom) { - const u_char *saveptr = ptr; - - if (ns_name_skip(&ptr, eom) == -1) - return (-1); - return (ptr - saveptr); -} - -/* - * Verify that a domain name uses an acceptable character set. - */ - -/* - * Note the conspicuous absence of ctype macros in these definitions. On - * non-ASCII hosts, we can't depend on string literals or ctype macros to - * tell us anything about network-format data. The rest of the BIND system - * is not careful about this, but for some reason, we're doing it right here. - */ -#define PERIOD 0x2e -#define hyphenchar(c) ((c) == 0x2d) -#define bslashchar(c) ((c) == 0x5c) -#define periodchar(c) ((c) == PERIOD) -#define asterchar(c) ((c) == 0x2a) -#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ - || ((c) >= 0x61 && (c) <= 0x7a)) -#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) - -#define borderchar(c) (alphachar(c) || digitchar(c)) -#define middlechar(c) (borderchar(c) || hyphenchar(c)) -#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) - -int -res_hnok(const char *dn) { - int pch = PERIOD, ch = *dn++; - - while (ch != '\0') { - int nch = *dn++; - - if (periodchar(ch)) { - ; - } else if (periodchar(pch)) { - if (!borderchar(ch)) - return (0); - } else if (periodchar(nch) || nch == '\0') { - if (!borderchar(ch)) - return (0); - } else { - if (!middlechar(ch)) - return (0); - } - pch = ch, ch = nch; - } - return (1); -} - -/* - * hostname-like (A, MX, WKS) owners can have "*" as their first label - * but must otherwise be as a host name. - */ -int -res_ownok(const char *dn) { - if (asterchar(dn[0])) { - if (periodchar(dn[1])) - return (res_hnok(dn+2)); - if (dn[1] == '\0') - return (1); - } - return (res_hnok(dn)); -} - -/* - * SOA RNAMEs and RP RNAMEs can have any printable character in their first - * label, but the rest of the name has to look like a host name. - */ -int -res_mailok(const char *dn) { - int ch, escaped = 0; - - /* "." is a valid missing representation */ - if (*dn == '\0') - return (1); - - /* otherwise <label>.<hostname> */ - while ((ch = *dn++) != '\0') { - if (!domainchar(ch)) - return (0); - if (!escaped && periodchar(ch)) - break; - if (escaped) - escaped = 0; - else if (bslashchar(ch)) - escaped = 1; - } - if (periodchar(ch)) - return (res_hnok(dn)); - return (0); -} - -/* - * This function is quite liberal, since RFC 1034's character sets are only - * recommendations. - */ -int -res_dnok(const char *dn) { - int ch; - - while ((ch = *dn++) != '\0') - if (!domainchar(ch)) - return (0); - return (1); -} - -#ifdef BIND_4_COMPAT -/* - * This module must export the following externally-visible symbols: - * ___putlong - * ___putshort - * __getlong - * __getshort - * Note that one _ comes from C and the others come from us. - */ -void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } -void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } -#ifndef __ultrix__ -u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } -u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } -#endif /*__ultrix__*/ -#endif /*BIND_4_COMPAT*/ diff --git a/libc/netbsd/resolv/res_compat.c b/libc/netbsd/resolv/res_compat.c deleted file mode 100644 index 19a1d5f..0000000 --- a/libc/netbsd/resolv/res_compat.c +++ /dev/null @@ -1,87 +0,0 @@ -/* $NetBSD: res_compat.c,v 1.1 2004/06/09 18:07:03 christos Exp $ */ - -/*- - * Copyright (c) 2004 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: res_compat.c,v 1.1 2004/06/09 18:07:03 christos Exp $"); -#endif - -#include <sys/types.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" -#include <netdb.h> -#include <string.h> -#define __OLD_RES_STATE -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include "resolv.h" -#endif - -#undef _res - -/* - * Binary Compatibility; this symbol does not appear in a header file - * Most userland programs use this to set res_options before res_init() - * is called. There are hooks to res_init() to consult the data in this - * structure. The hooks are provided indirectly by the two functions below. - * We depend on the fact the the first 440 [32 bit machines] bytes are - * shared between the two structures. - */ -#ifndef __BIND_NOSTATIC -struct __res_state _res -#if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif -; - -void *__res_get_old_state(void); -void __res_put_old_state(void *); - -void * -__res_get_old_state(void) -{ - return &_res; -} - -void -__res_put_old_state(void *res) -{ - (void)memcpy(&_res, res, sizeof(_res)); -} -#endif diff --git a/libc/netbsd/resolv/res_data.c b/libc/netbsd/resolv/res_data.c deleted file mode 100644 index e60ecfd..0000000 --- a/libc/netbsd/resolv/res_data.c +++ /dev/null @@ -1,332 +0,0 @@ -/* $NetBSD: res_data.c,v 1.8 2004/06/09 18:07:03 christos Exp $ */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char rcsid[] = "Id: res_data.c,v 1.1.206.2 2004/03/16 12:34:18 marka Exp"; -#else -__RCSID("$NetBSD: res_data.c,v 1.8 2004/06/09 18:07:03 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - - - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" - -#include <ctype.h> -#include <netdb.h> -#include "resolv_private.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - - -const char * const _res_opcodes[] = { - "QUERY", - "IQUERY", - "CQUERYM", - "CQUERYU", /* experimental */ - "NOTIFY", /* experimental */ - "UPDATE", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "ZONEINIT", - "ZONEREF", -}; - -#ifdef BIND_UPDATE -const char * const _res_sectioncodes[] = { - "ZONE", - "PREREQUISITES", - "UPDATE", - "ADDITIONAL", -}; -#endif - -#ifndef __BIND_NOSTATIC -extern struct __res_state _nres; - -/* Proto. */ - -int res_ourserver_p(const res_state, const struct sockaddr *); - -#ifdef ANDROID_CHANGES -int res_need_init() { - return ((_nres.options & RES_INIT) == 0U) || res_get_dns_changed(); -} -#else -#define res_need_init() ((_nres.options & RES_INIT) == 0U) -#endif - -int -res_init(void) { - int rv; - extern int __res_vinit(res_state, int); -#ifdef COMPAT__RES - /* - * Compatibility with program that were accessing _res directly - * to set options. We keep another struct res that is the same - * size as the original res structure, and then copy fields to - * it so that we achieve the same initialization - */ - extern void *__res_get_old_state(void); - extern void __res_put_old_state(void *); - res_state ores = __res_get_old_state(); - - if (ores->options != 0) - _nres.options = ores->options; - if (ores->retrans != 0) - _nres.retrans = ores->retrans; - if (ores->retry != 0) - _nres.retry = ores->retry; -#endif - - /* - * These three fields used to be statically initialized. This made - * it hard to use this code in a shared library. It is necessary, - * now that we're doing dynamic initialization here, that we preserve - * the old semantics: if an application modifies one of these three - * fields of _res before res_init() is called, res_init() will not - * alter them. Of course, if an application is setting them to - * _zero_ before calling res_init(), hoping to override what used - * to be the static default, we can't detect it and unexpected results - * will follow. Zero for any of these fields would make no sense, - * so one can safely assume that the applications were already getting - * unexpected results. - * - * _nres.options is tricky since some apps were known to diddle the bits - * before res_init() was first called. We can't replicate that semantic - * with dynamic initialization (they may have turned bits off that are - * set in RES_DEFAULT). Our solution is to declare such applications - * "broken". They could fool us by setting RES_INIT but none do (yet). - */ - if (!_nres.retrans) - _nres.retrans = RES_TIMEOUT; - if (!_nres.retry) - _nres.retry = 4; - if (!(_nres.options & RES_INIT)) - _nres.options = RES_DEFAULT; - - /* - * This one used to initialize implicitly to zero, so unless the app - * has set it to something in particular, we can randomize it now. - */ - if (!_nres.id) - _nres.id = res_randomid(); - - rv = __res_vinit(&_nres, 1); -#ifdef COMPAT__RES - __res_put_old_state(&_nres); -#endif - return rv; -} - -void -p_query(const u_char *msg) { - fp_query(msg, stdout); -} - -void -fp_query(const u_char *msg, FILE *file) { - fp_nquery(msg, PACKETSZ, file); -} - -void -fp_nquery(const u_char *msg, int len, FILE *file) { - if (res_need_init() && res_init() == -1) - return; - - res_pquery(&_nres, msg, len, file); -} - -int -res_mkquery(int op, /* opcode of query */ - const char *dname, /* domain name */ - int class, int type, /* class and type of query */ - const u_char *data, /* resource record data */ - int datalen, /* length of data */ - const u_char *newrr_in, /* new rr for modify or append */ - u_char *buf, /* buffer to put query */ - int buflen) /* size of buffer */ -{ - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - return (res_nmkquery(&_nres, op, dname, class, type, - data, datalen, - newrr_in, buf, buflen)); -} - -#ifdef _LIBRESOLV -int -res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - - return (res_nmkupdate(&_nres, rrecp_in, buf, buflen)); -} -#endif - -int -res_query(const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer buffer */ -{ - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - return (res_nquery(&_nres, name, class, type, answer, anslen)); -} - -void -res_send_setqhook(res_send_qhook hook) { - _nres.qhook = hook; -} - -void -res_send_setrhook(res_send_rhook hook) { - _nres.rhook = hook; -} - -int -res_isourserver(const struct sockaddr_in *inp) { - return (res_ourserver_p(&_nres, (const struct sockaddr *)(const void *)inp)); -} - -int -res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { - if (res_need_init() && res_init() == -1) { - /* errno should have been set by res_init() in this case. */ - return (-1); - } - - return (res_nsend(&_nres, buf, buflen, ans, anssiz)); -} - -#ifdef _LIBRESOLV -int -res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, - u_char *ans, int anssiz) -{ - if (res_need_init() && res_init() == -1) { - /* errno should have been set by res_init() in this case. */ - return (-1); - } - - return (res_nsendsigned(&_nres, buf, buflen, key, ans, anssiz)); -} -#endif - -void -res_close(void) { - res_nclose(&_nres); -} - -#ifdef _LIBRESOLV -int -res_update(ns_updrec *rrecp_in) { - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - - return (res_nupdate(&_nres, rrecp_in, NULL)); -} -#endif - -int -res_search(const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - - return (res_nsearch(&_nres, name, class, type, answer, anslen)); -} - -int -res_querydomain(const char *name, - const char *domain, - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - if (res_need_init() && res_init() == -1) { - RES_SET_H_ERRNO(&_nres, NETDB_INTERNAL); - return (-1); - } - - return (res_nquerydomain(&_nres, name, domain, - class, type, - answer, anslen)); -} - -int -res_opt(int a, u_char *b, int c, int d) -{ - return res_nopt(&_nres, a, b, c, d); -} - -const char * -hostalias(const char *name) { - return NULL; -} - -#ifdef ultrix -int -local_hostname_length(const char *hostname) { - int len_host, len_domain; - - if (!*_nres.defdname) - res_init(); - len_host = strlen(hostname); - len_domain = strlen(_nres.defdname); - if (len_host > len_domain && - !strcasecmp(hostname + len_host - len_domain, _nres.defdname) && - hostname[len_host - len_domain - 1] == '.') - return (len_host - len_domain - 1); - return (0); -} -#endif /*ultrix*/ - -#endif diff --git a/libc/netbsd/resolv/res_debug.c b/libc/netbsd/resolv/res_debug.c deleted file mode 100644 index 84c6afc..0000000 --- a/libc/netbsd/resolv/res_debug.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* $NetBSD: res_debug.c,v 1.7 2004/11/07 02:25:01 christos Exp $ */ - -/* - * Copyright (c) 1985 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: res_debug.c,v 1.3.2.5.4.5 2004/07/28 20:16:46 marka Exp"; -#else -__RCSID("$NetBSD: res_debug.c,v 1.7 2004/11/07 02:25:01 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - - - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" - -#include <ctype.h> -#include <errno.h> -#include <math.h> -#include <netdb.h> -#include "resolv_private.h" -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - - - -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) sprintf x -#endif - -static const char *precsize_ntoa(u_int32_t); - -extern const char * const _res_opcodes[]; -extern const char * const _res_sectioncodes[]; - -#ifndef _LIBC -/* - * Print the current options. - */ -void -fp_resstat(const res_state statp, FILE *file) { - u_long mask; - - fprintf(file, ";; res options:"); - for (mask = 1; mask != 0U; mask <<= 1) - if (statp->options & mask) - fprintf(file, " %s", p_option(mask)); - putc('\n', file); -} -#endif - -static void -do_section(const res_state statp, - ns_msg *handle, ns_sect section, - int pflag, FILE *file) -{ - int n, sflag, rrnum; - int buflen = 2048; - char *buf; - ns_opcode opcode; - ns_rr rr; - - /* - * Print answer records. - */ - sflag = (statp->pfcode & pflag); - if (statp->pfcode && !sflag) - return; - - buf = malloc((size_t)buflen); - if (buf == NULL) { - fprintf(file, ";; memory allocation failure\n"); - return; - } - - opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); - rrnum = 0; - for (;;) { - if (ns_parserr(handle, section, rrnum, &rr)) { - if (errno != ENODEV) - fprintf(file, ";; ns_parserr: %s\n", - strerror(errno)); - else if (rrnum > 0 && sflag != 0 && - (statp->pfcode & RES_PRF_HEAD1)) - putc('\n', file); - goto cleanup; - } - if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) - fprintf(file, ";; %s SECTION:\n", - p_section(section, opcode)); - if (section == ns_s_qd) - fprintf(file, ";;\t%s, type = %s, class = %s\n", - ns_rr_name(rr), - p_type(ns_rr_type(rr)), - p_class(ns_rr_class(rr))); - else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) { - u_int32_t ttl = ns_rr_ttl(rr); - fprintf(file, - "; EDNS: version: %u, udp=%u, flags=%04x\n", - (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff); - } else { - n = ns_sprintrr(handle, &rr, NULL, NULL, - buf, (u_int)buflen); - if (n < 0) { - if (errno == ENOSPC) { - free(buf); - buf = NULL; - if (buflen < 131072) - buf = malloc((size_t)(buflen += 1024)); - if (buf == NULL) { - fprintf(file, - ";; memory allocation failure\n"); - return; - } - continue; - } - fprintf(file, ";; ns_sprintrr: %s\n", - strerror(errno)); - goto cleanup; - } - fputs(buf, file); - fputc('\n', file); - } - rrnum++; - } - cleanup: - if (buf != NULL) - free(buf); -} - -/* - * Print the contents of a query. - * This is intended to be primarily a debugging routine. - */ -void -res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { - ns_msg handle; - int qdcount, ancount, nscount, arcount; - u_int opcode, rcode, id; - - if (ns_initparse(msg, len, &handle) < 0) { - fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); - return; - } - opcode = ns_msg_getflag(handle, ns_f_opcode); - rcode = ns_msg_getflag(handle, ns_f_rcode); - id = ns_msg_id(handle); - qdcount = ns_msg_count(handle, ns_s_qd); - ancount = ns_msg_count(handle, ns_s_an); - nscount = ns_msg_count(handle, ns_s_ns); - arcount = ns_msg_count(handle, ns_s_ar); - - /* - * Print header fields. - */ - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) - fprintf(file, - ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", - _res_opcodes[opcode], p_rcode((int)rcode), id); - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) - putc(';', file); - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { - fprintf(file, "; flags:"); - if (ns_msg_getflag(handle, ns_f_qr)) - fprintf(file, " qr"); - if (ns_msg_getflag(handle, ns_f_aa)) - fprintf(file, " aa"); - if (ns_msg_getflag(handle, ns_f_tc)) - fprintf(file, " tc"); - if (ns_msg_getflag(handle, ns_f_rd)) - fprintf(file, " rd"); - if (ns_msg_getflag(handle, ns_f_ra)) - fprintf(file, " ra"); - if (ns_msg_getflag(handle, ns_f_z)) - fprintf(file, " ??"); - if (ns_msg_getflag(handle, ns_f_ad)) - fprintf(file, " ad"); - if (ns_msg_getflag(handle, ns_f_cd)) - fprintf(file, " cd"); - } - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { - fprintf(file, "; %s: %d", - p_section(ns_s_qd, (int)opcode), qdcount); - fprintf(file, ", %s: %d", - p_section(ns_s_an, (int)opcode), ancount); - fprintf(file, ", %s: %d", - p_section(ns_s_ns, (int)opcode), nscount); - fprintf(file, ", %s: %d", - p_section(ns_s_ar, (int)opcode), arcount); - } - if ((!statp->pfcode) || (statp->pfcode & - (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { - putc('\n',file); - } - /* - * Print the various sections. - */ - do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); - do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); - do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); - do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); - if (qdcount == 0 && ancount == 0 && - nscount == 0 && arcount == 0) - putc('\n', file); -} - -const u_char * -p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { - char name[MAXDNAME]; - int n; - - if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) - return (NULL); - if (name[0] == '\0') - putc('.', file); - else - fputs(name, file); - return (cp + n); -} - -const u_char * -p_cdname(const u_char *cp, const u_char *msg, FILE *file) { - return (p_cdnname(cp, msg, PACKETSZ, file)); -} - -/* Return a fully-qualified domain name from a compressed name (with - length supplied). */ - -const u_char * -p_fqnname(cp, msg, msglen, name, namelen) - const u_char *cp, *msg; - int msglen; - char *name; - int namelen; -{ - int n, newlen; - - if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) - return (NULL); - newlen = strlen(name); - if (newlen == 0 || name[newlen - 1] != '.') { - if (newlen + 1 >= namelen) /* Lack space for final dot */ - return (NULL); - else - strcpy(name + newlen, "."); - } - return (cp + n); -} - -/* XXX: the rest of these functions need to become length-limited, too. */ - -const u_char * -p_fqname(const u_char *cp, const u_char *msg, FILE *file) { - char name[MAXDNAME]; - const u_char *n; - - n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); - if (n == NULL) - return (NULL); - fputs(name, file); - return (n); -} - -/* - * Names of RR classes and qclasses. Classes and qclasses are the same, except - * that C_ANY is a qclass but not a class. (You can ask for records of class - * C_ANY, but you can't have any records of that class in the database.) - */ -const struct res_sym __p_class_syms[] = { - {C_IN, "IN", (char *)0}, - {C_CHAOS, "CH", (char *)0}, - {C_CHAOS, "CHAOS", (char *)0}, - {C_HS, "HS", (char *)0}, - {C_HS, "HESIOD", (char *)0}, - {C_ANY, "ANY", (char *)0}, - {C_NONE, "NONE", (char *)0}, - {C_IN, (char *)0, (char *)0} -}; - -/* - * Names of message sections. - */ -const struct res_sym __p_default_section_syms[] = { - {ns_s_qd, "QUERY", (char *)0}, - {ns_s_an, "ANSWER", (char *)0}, - {ns_s_ns, "AUTHORITY", (char *)0}, - {ns_s_ar, "ADDITIONAL", (char *)0}, - {0, (char *)0, (char *)0} -}; - -const struct res_sym __p_update_section_syms[] = { - {S_ZONE, "ZONE", (char *)0}, - {S_PREREQ, "PREREQUISITE", (char *)0}, - {S_UPDATE, "UPDATE", (char *)0}, - {S_ADDT, "ADDITIONAL", (char *)0}, - {0, (char *)0, (char *)0} -}; - -const struct res_sym __p_key_syms[] = { - {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, - {NS_ALG_DH, "DH", "Diffie Hellman"}, - {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, - {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, - {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, - {0, NULL, NULL} -}; - -const struct res_sym __p_cert_syms[] = { - {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, - {cert_t_spki, "SPKI", "SPKI certificate"}, - {cert_t_pgp, "PGP", "PGP certificate"}, - {cert_t_url, "URL", "URL Private"}, - {cert_t_oid, "OID", "OID Private"}, - {0, NULL, NULL} -}; - -/* - * Names of RR types and qtypes. Types and qtypes are the same, except - * that T_ANY is a qtype but not a type. (You can ask for records of type - * T_ANY, but you can't have any records of that type in the database.) - */ -const struct res_sym __p_type_syms[] = { - {ns_t_a, "A", "address"}, - {ns_t_ns, "NS", "name server"}, - {ns_t_md, "MD", "mail destination (deprecated)"}, - {ns_t_mf, "MF", "mail forwarder (deprecated)"}, - {ns_t_cname, "CNAME", "canonical name"}, - {ns_t_soa, "SOA", "start of authority"}, - {ns_t_mb, "MB", "mailbox"}, - {ns_t_mg, "MG", "mail group member"}, - {ns_t_mr, "MR", "mail rename"}, - {ns_t_null, "NULL", "null"}, - {ns_t_wks, "WKS", "well-known service (deprecated)"}, - {ns_t_ptr, "PTR", "domain name pointer"}, - {ns_t_hinfo, "HINFO", "host information"}, - {ns_t_minfo, "MINFO", "mailbox information"}, - {ns_t_mx, "MX", "mail exchanger"}, - {ns_t_txt, "TXT", "text"}, - {ns_t_rp, "RP", "responsible person"}, - {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, - {ns_t_x25, "X25", "X25 address"}, - {ns_t_isdn, "ISDN", "ISDN address"}, - {ns_t_rt, "RT", "router"}, - {ns_t_nsap, "NSAP", "nsap address"}, - {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, - {ns_t_sig, "SIG", "signature"}, - {ns_t_key, "KEY", "key"}, - {ns_t_px, "PX", "mapping information"}, - {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, - {ns_t_aaaa, "AAAA", "IPv6 address"}, - {ns_t_loc, "LOC", "location"}, - {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, - {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, - {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, - {ns_t_srv, "SRV", "server selection"}, - {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, - {ns_t_tkey, "TKEY", "tkey"}, - {ns_t_tsig, "TSIG", "transaction signature"}, - {ns_t_ixfr, "IXFR", "incremental zone transfer"}, - {ns_t_axfr, "AXFR", "zone transfer"}, - {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, - {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, - {ns_t_maila, "MAILA", "mail agent (deprecated)"}, - {ns_t_naptr, "NAPTR", "URN Naming Authority"}, - {ns_t_kx, "KX", "Key Exchange"}, - {ns_t_cert, "CERT", "Certificate"}, - {ns_t_a6, "A6", "IPv6 Address"}, - {ns_t_dname, "DNAME", "dname"}, - {ns_t_sink, "SINK", "Kitchen Sink (experimental)"}, - {ns_t_opt, "OPT", "EDNS Options"}, - {ns_t_any, "ANY", "\"any\""}, - {0, NULL, NULL} -}; - -/* - * Names of DNS rcodes. - */ -const struct res_sym __p_rcode_syms[] = { - {ns_r_noerror, "NOERROR", "no error"}, - {ns_r_formerr, "FORMERR", "format error"}, - {ns_r_servfail, "SERVFAIL", "server failed"}, - {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, - {ns_r_notimpl, "NOTIMP", "not implemented"}, - {ns_r_refused, "REFUSED", "refused"}, - {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, - {ns_r_yxrrset, "YXRRSET", "rrset exists"}, - {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, - {ns_r_notauth, "NOTAUTH", "not authoritative"}, - {ns_r_notzone, "NOTZONE", "Not in zone"}, - {ns_r_max, "", ""}, - {ns_r_badsig, "BADSIG", "bad signature"}, - {ns_r_badkey, "BADKEY", "bad key"}, - {ns_r_badtime, "BADTIME", "bad time"}, - {0, NULL, NULL} -}; - -int -sym_ston(const struct res_sym *syms, const char *name, int *success) { - for (; syms->name != 0; syms++) { - if (strcasecmp (name, syms->name) == 0) { - if (success) - *success = 1; - return (syms->number); - } - } - if (success) - *success = 0; - return (syms->number); /* The default value. */ -} - -const char * -sym_ntos(const struct res_sym *syms, int number, int *success) { - static char unname[20]; - - for (; syms->name != 0; syms++) { - if (number == syms->number) { - if (success) - *success = 1; - return (syms->name); - } - } - - sprintf(unname, "%d", number); /* XXX nonreentrant */ - if (success) - *success = 0; - return (unname); -} - -const char * -sym_ntop(const struct res_sym *syms, int number, int *success) { - static char unname[20]; - - for (; syms->name != 0; syms++) { - if (number == syms->number) { - if (success) - *success = 1; - return (syms->humanname); - } - } - sprintf(unname, "%d", number); /* XXX nonreentrant */ - if (success) - *success = 0; - return (unname); -} - -/* - * Return a string for the type. - */ -const char * -p_type(int type) { - int success; - const char *result; - static char typebuf[20]; - - result = sym_ntos(__p_type_syms, type, &success); - if (success) - return (result); - if (type < 0 || type > 0xffff) - return ("BADTYPE"); - sprintf(typebuf, "TYPE%d", type); - return (typebuf); -} - -/* - * Return a string for the type. - */ -const char * -p_section(int section, int opcode) { - const struct res_sym *symbols; - - switch (opcode) { - case ns_o_update: - symbols = __p_update_section_syms; - break; - default: - symbols = __p_default_section_syms; - break; - } - return (sym_ntos(symbols, section, (int *)0)); -} - -/* - * Return a mnemonic for class. - */ -const char * -p_class(int class) { - int success; - const char *result; - static char classbuf[20]; - - result = sym_ntos(__p_class_syms, class, &success); - if (success) - return (result); - if (class < 0 || class > 0xffff) - return ("BADCLASS"); - sprintf(classbuf, "CLASS%d", class); - return (classbuf); -} - -/* - * Return a mnemonic for an option - */ -const char * -p_option(u_long option) { - static char nbuf[40]; - - switch (option) { - case RES_INIT: return "init"; - case RES_DEBUG: return "debug"; - case RES_AAONLY: return "aaonly(unimpl)"; - case RES_USEVC: return "usevc"; - case RES_PRIMARY: return "primry(unimpl)"; - case RES_IGNTC: return "igntc"; - case RES_RECURSE: return "recurs"; - case RES_DEFNAMES: return "defnam"; - case RES_STAYOPEN: return "styopn"; - case RES_DNSRCH: return "dnsrch"; - case RES_INSECURE1: return "insecure1"; - case RES_INSECURE2: return "insecure2"; - case RES_NOALIASES: return "noaliases"; - case RES_USE_INET6: return "inet6"; -#ifdef RES_USE_EDNS0 /* KAME extension */ - case RES_USE_EDNS0: return "edns0"; -#endif -#ifdef RES_USE_DNAME - case RES_USE_DNAME: return "dname"; -#endif -#ifdef RES_USE_DNSSEC - case RES_USE_DNSSEC: return "dnssec"; -#endif -#ifdef RES_NOTLDQUERY - case RES_NOTLDQUERY: return "no-tld-query"; -#endif -#ifdef RES_NO_NIBBLE2 - case RES_NO_NIBBLE2: return "no-nibble2"; -#endif - /* XXX nonreentrant */ - default: sprintf(nbuf, "?0x%lx?", (u_long)option); - return (nbuf); - } -} - -/* - * Return a mnemonic for a time to live. - */ -const char * -p_time(u_int32_t value) { - static char nbuf[40]; /* XXX nonreentrant */ - - if (ns_format_ttl((u_long)value, nbuf, sizeof nbuf) < 0) - sprintf(nbuf, "%u", value); - return (nbuf); -} - -/* - * Return a string for the rcode. - */ -const char * -p_rcode(int rcode) { - return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); -} - -/* - * Return a string for a res_sockaddr_union. - */ -const char * -p_sockun(union res_sockaddr_union u, char *buf, size_t size) { - char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"]; - - switch (u.sin.sin_family) { - case AF_INET: - inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret); - break; -#ifdef HAS_INET6_STRUCTS - case AF_INET6: - inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret); - break; -#endif - default: - sprintf(ret, "[af%d]", u.sin.sin_family); - break; - } - if (size > 0U) { - strncpy(buf, ret, size - 1); - buf[size - 1] = '0'; - } - return (buf); -} - -/* - * routines to convert between on-the-wire RR format and zone file format. - * Does not contain conversion to/from decimal degrees; divide or multiply - * by 60*60*1000 for that. - */ - -static const unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, - 1000000,10000000,100000000,1000000000}; - -/* takes an XeY precision/size value, returns a string representation. */ -static const char * -precsize_ntoa(prec) - u_int32_t prec; -{ - static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */ - unsigned long val; - int mantissa, exponent; - - mantissa = (int)((prec >> 4) & 0x0f) % 10; - exponent = (int)((prec >> 0) & 0x0f) % 10; - - val = mantissa * poweroften[exponent]; - - (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100); - return (retbuf); -} - -/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ -static u_int8_t -precsize_aton(const char **strptr) { - unsigned int mval = 0, cmval = 0; - u_int8_t retval = 0; - const char *cp; - int exponent; - int mantissa; - - cp = *strptr; - - while (isdigit((unsigned char)*cp)) - mval = mval * 10 + (*cp++ - '0'); - - if (*cp == '.') { /* centimeters */ - cp++; - if (isdigit((unsigned char)*cp)) { - cmval = (*cp++ - '0') * 10; - if (isdigit((unsigned char)*cp)) { - cmval += (*cp++ - '0'); - } - } - } - cmval = (mval * 100) + cmval; - - for (exponent = 0; exponent < 9; exponent++) - if (cmval < poweroften[exponent+1]) - break; - - mantissa = cmval / poweroften[exponent]; - if (mantissa > 9) - mantissa = 9; - - retval = (mantissa << 4) | exponent; - - *strptr = cp; - - return (retval); -} - -/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ -static u_int32_t -latlon2ul(const char **latlonstrptr, int *which) { - const char *cp; - u_int32_t retval; - int deg = 0, min = 0, secs = 0, secsfrac = 0; - - cp = *latlonstrptr; - - while (isdigit((unsigned char)*cp)) - deg = deg * 10 + (*cp++ - '0'); - - while (isspace((unsigned char)*cp)) - cp++; - - if (!(isdigit((unsigned char)*cp))) - goto fndhemi; - - while (isdigit((unsigned char)*cp)) - min = min * 10 + (*cp++ - '0'); - - while (isspace((unsigned char)*cp)) - cp++; - - if (!(isdigit((unsigned char)*cp))) - goto fndhemi; - - while (isdigit((unsigned char)*cp)) - secs = secs * 10 + (*cp++ - '0'); - - if (*cp == '.') { /* decimal seconds */ - cp++; - if (isdigit((unsigned char)*cp)) { - secsfrac = (*cp++ - '0') * 100; - if (isdigit((unsigned char)*cp)) { - secsfrac += (*cp++ - '0') * 10; - if (isdigit((unsigned char)*cp)) { - secsfrac += (*cp++ - '0'); - } - } - } - } - - while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ - cp++; - - while (isspace((unsigned char)*cp)) - cp++; - - fndhemi: - switch (*cp) { - case 'N': case 'n': - case 'E': case 'e': - retval = ((unsigned)1<<31) - + (((((deg * 60) + min) * 60) + secs) * 1000) - + secsfrac; - break; - case 'S': case 's': - case 'W': case 'w': - retval = ((unsigned)1<<31) - - (((((deg * 60) + min) * 60) + secs) * 1000) - - secsfrac; - break; - default: - retval = 0; /* invalid value -- indicates error */ - break; - } - - switch (*cp) { - case 'N': case 'n': - case 'S': case 's': - *which = 1; /* latitude */ - break; - case 'E': case 'e': - case 'W': case 'w': - *which = 2; /* longitude */ - break; - default: - *which = 0; /* error */ - break; - } - - cp++; /* skip the hemisphere */ - - while (!isspace((unsigned char)*cp)) /* if any trailing garbage */ - cp++; - - while (isspace((unsigned char)*cp)) /* move to next field */ - cp++; - - *latlonstrptr = cp; - - return (retval); -} - -/* converts a zone file representation in a string to an RDATA on-the-wire - * representation. */ -int -loc_aton(ascii, binary) - const char *ascii; - u_char *binary; -{ - const char *cp, *maxcp; - u_char *bcp; - - u_int32_t latit = 0, longit = 0, alt = 0; - u_int32_t lltemp1 = 0, lltemp2 = 0; - int altmeters = 0, altfrac = 0, altsign = 1; - u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ - u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ - u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ - int which1 = 0, which2 = 0; - - cp = ascii; - maxcp = cp + strlen(ascii); - - lltemp1 = latlon2ul(&cp, &which1); - - lltemp2 = latlon2ul(&cp, &which2); - - switch (which1 + which2) { - case 3: /* 1 + 2, the only valid combination */ - if ((which1 == 1) && (which2 == 2)) { /* normal case */ - latit = lltemp1; - longit = lltemp2; - } else if ((which1 == 2) && (which2 == 1)) { /* reversed */ - longit = lltemp1; - latit = lltemp2; - } else { /* some kind of brokenness */ - return (0); - } - break; - default: /* we didn't get one of each */ - return (0); - } - - /* altitude */ - if (*cp == '-') { - altsign = -1; - cp++; - } - - if (*cp == '+') - cp++; - - while (isdigit((unsigned char)*cp)) - altmeters = altmeters * 10 + (*cp++ - '0'); - - if (*cp == '.') { /* decimal meters */ - cp++; - if (isdigit((unsigned char)*cp)) { - altfrac = (*cp++ - '0') * 10; - if (isdigit((unsigned char)*cp)) { - altfrac += (*cp++ - '0'); - } - } - } - - alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); - - while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ - cp++; - - while (isspace((unsigned char)*cp) && (cp < maxcp)) - cp++; - - if (cp >= maxcp) - goto defaults; - - siz = precsize_aton(&cp); - - while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ - cp++; - - while (isspace((unsigned char)*cp) && (cp < maxcp)) - cp++; - - if (cp >= maxcp) - goto defaults; - - hp = precsize_aton(&cp); - - while (!isspace((unsigned char)*cp) && (cp < maxcp)) /* if trailing garbage or m */ - cp++; - - while (isspace((unsigned char)*cp) && (cp < maxcp)) - cp++; - - if (cp >= maxcp) - goto defaults; - - vp = precsize_aton(&cp); - - defaults: - - bcp = binary; - *bcp++ = (u_int8_t) 0; /* version byte */ - *bcp++ = siz; - *bcp++ = hp; - *bcp++ = vp; - PUTLONG(latit,bcp); - PUTLONG(longit,bcp); - PUTLONG(alt,bcp); - - return (16); /* size of RR in octets */ -} - -/* takes an on-the-wire LOC RR and formats it in a human readable format. */ -const char * -loc_ntoa(binary, ascii) - const u_char *binary; - char *ascii; -{ - static const char *error = "?"; - static char tmpbuf[sizeof -"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; - const u_char *cp = binary; - - int latdeg, latmin, latsec, latsecfrac; - int longdeg, longmin, longsec, longsecfrac; - char northsouth, eastwest; - const char *altsign; - int altmeters, altfrac; - - const u_int32_t referencealt = 100000 * 100; - - int32_t latval, longval, altval; - u_int32_t templ; - u_int8_t sizeval, hpval, vpval, versionval; - - char *sizestr, *hpstr, *vpstr; - - versionval = *cp++; - - if (ascii == NULL) - ascii = tmpbuf; - - if (versionval) { - (void) sprintf(ascii, "; error: unknown LOC RR version"); - return (ascii); - } - - sizeval = *cp++; - - hpval = *cp++; - vpval = *cp++; - - GETLONG(templ, cp); - latval = (templ - ((unsigned)1<<31)); - - GETLONG(templ, cp); - longval = (templ - ((unsigned)1<<31)); - - GETLONG(templ, cp); - if (templ < referencealt) { /* below WGS 84 spheroid */ - altval = referencealt - templ; - altsign = "-"; - } else { - altval = templ - referencealt; - altsign = ""; - } - - if (latval < 0) { - northsouth = 'S'; - latval = -latval; - } else - northsouth = 'N'; - - latsecfrac = latval % 1000; - latval = latval / 1000; - latsec = latval % 60; - latval = latval / 60; - latmin = latval % 60; - latval = latval / 60; - latdeg = latval; - - if (longval < 0) { - eastwest = 'W'; - longval = -longval; - } else - eastwest = 'E'; - - longsecfrac = longval % 1000; - longval = longval / 1000; - longsec = longval % 60; - longval = longval / 60; - longmin = longval % 60; - longval = longval / 60; - longdeg = longval; - - altfrac = altval % 100; - altmeters = (altval / 100); - - sizestr = strdup(precsize_ntoa((u_int32_t)sizeval)); - hpstr = strdup(precsize_ntoa((u_int32_t)hpval)); - vpstr = strdup(precsize_ntoa((u_int32_t)vpval)); - - sprintf(ascii, - "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm", - latdeg, latmin, latsec, latsecfrac, northsouth, - longdeg, longmin, longsec, longsecfrac, eastwest, - altsign, altmeters, altfrac, - (sizestr != NULL) ? sizestr : error, - (hpstr != NULL) ? hpstr : error, - (vpstr != NULL) ? vpstr : error); - - if (sizestr != NULL) - free(sizestr); - if (hpstr != NULL) - free(hpstr); - if (vpstr != NULL) - free(vpstr); - - return (ascii); -} - - -/* Return the number of DNS hierarchy levels in the name. */ -int -dn_count_labels(const char *name) { - int i, len, count; - - len = strlen(name); - for (i = 0, count = 0; i < len; i++) { - /* XXX need to check for \. or use named's nlabels(). */ - if (name[i] == '.') - count++; - } - - /* don't count initial wildcard */ - if (name[0] == '*') - if (count) - count--; - - /* don't count the null label for root. */ - /* if terminating '.' not found, must adjust */ - /* count to include last label */ - if (len > 0 && name[len-1] != '.') - count++; - return (count); -} - - -/* - * Make dates expressed in seconds-since-Jan-1-1970 easy to read. - * SIG records are required to be printed like this, by the Secure DNS RFC. - */ -char * -p_secstodate (u_long secs) { - /* XXX nonreentrant */ - static char output[15]; /* YYYYMMDDHHMMSS and null */ - time_t myclock = secs; - struct tm *mytime; -#ifdef HAVE_TIME_R - struct tm res; - - mytime = gmtime_r(&myclock, &res); -#else - mytime = gmtime(&myclock); -#endif - mytime->tm_year += 1900; - mytime->tm_mon += 1; - sprintf(output, "%04d%02d%02d%02d%02d%02d", - mytime->tm_year, mytime->tm_mon, mytime->tm_mday, - mytime->tm_hour, mytime->tm_min, mytime->tm_sec); - return (output); -} - -u_int16_t -res_nametoclass(const char *buf, int *successp) { - unsigned long result; - char *endptr; - int success; - - result = sym_ston(__p_class_syms, buf, &success); - if (success) - goto done; - - if (strncasecmp(buf, "CLASS", 5) != 0 || - !isdigit((unsigned char)buf[5])) - goto done; - errno = 0; - result = strtoul(buf + 5, &endptr, 10); - if (errno == 0 && *endptr == '\0' && result <= 0xffffU) - success = 1; - done: - if (successp) - *successp = success; - return (u_int16_t)(result); -} - -u_int16_t -res_nametotype(const char *buf, int *successp) { - unsigned long result; - char *endptr; - int success; - - result = sym_ston(__p_type_syms, buf, &success); - if (success) - goto done; - - if (strncasecmp(buf, "type", 4) != 0 || - !isdigit((unsigned char)buf[4])) - goto done; - errno = 0; - result = strtoul(buf + 4, &endptr, 10); - if (errno == 0 && *endptr == '\0' && result <= 0xffffU) - success = 1; - done: - if (successp) - *successp = success; - return (u_int16_t)(result); -} diff --git a/libc/netbsd/resolv/res_debug.h b/libc/netbsd/resolv/res_debug.h deleted file mode 100644 index 4341c5a..0000000 --- a/libc/netbsd/resolv/res_debug.h +++ /dev/null @@ -1,36 +0,0 @@ -/* $NetBSD: res_debug.h,v 1.1.1.1 2004/05/20 17:18:55 christos Exp $ */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _RES_DEBUG_H_ -#define _RES_DEBUG_H_ - -#ifndef DEBUG -# define Dprint(cond, args) /*empty*/ -# define DprintQ(cond, args, query, size) /*empty*/ -# define Aerror(statp, file, string, error, address) /*empty*/ -# define Perror(statp, file, string, error) /*empty*/ -#else -# define Dprint(cond, args) if (cond) {fprintf args;} else {} -# define DprintQ(cond, args, query, size) if (cond) {\ - fprintf args;\ - res_pquery(statp, query, size, stdout);\ - } else {} -#endif - -#endif /* _RES_DEBUG_H_ */ diff --git a/libc/netbsd/resolv/res_init.c b/libc/netbsd/resolv/res_init.c deleted file mode 100644 index fc0272c..0000000 --- a/libc/netbsd/resolv/res_init.c +++ /dev/null @@ -1,863 +0,0 @@ -/* $NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $ */ - -/* - * Copyright (c) 1985, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static const char rcsid[] = "Id: res_init.c,v 1.9.2.5.4.2 2004/03/16 12:34:18 marka Exp"; -#else -__RCSID("$NetBSD: res_init.c,v 1.8 2006/03/19 03:10:08 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - - - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" - -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <netdb.h> - -#ifdef ANDROID_CHANGES -#include <sys/system_properties.h> -#endif /* ANDROID_CHANGES */ - -#ifndef MIN -#define MIN(x,y) ((x)<(y)?(x):(y)) -#endif - -/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#define MAX_DNS_PROPERTIES 8 -#define DNS_PROP_NAME_PREFIX "net.dns" -#define DNS_CHANGE_PROP_NAME "net.dnschange" -const prop_info *dns_change_prop; -int dns_last_change_counter; -static int _get_dns_change_count(); -#else -#include <resolv.h> -#endif - -#include "res_private.h" - -/* Options. Should all be left alone. */ -#ifndef DEBUG -#define DEBUG -#endif - -static void res_setoptions __P((res_state, const char *, const char *)); - -static const char sort_mask[] = "/&"; -#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) -static u_int32_t net_mask __P((struct in_addr)); - -#if !defined(isascii) /* XXX - could be a function */ -# define isascii(c) (!(c & 0200)) -#endif - -/* - * Resolver state default settings. - */ - -/* - * Set up default settings. If the configuration file exist, the values - * there will have precedence. Otherwise, the server address is set to - * INADDR_ANY and the default domain name comes from the gethostname(). - * - * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 - * rather than INADDR_ANY ("0.0.0.0") as the default name server address - * since it was noted that INADDR_ANY actually meant ``the first interface - * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, - * it had to be "up" in order for you to reach your own name server. It - * was later decided that since the recommended practice is to always - * install local static routes through 127.0.0.1 for all your network - * interfaces, that we could solve this problem without a code change. - * - * The configuration file should always be used, since it is the only way - * to specify a default domain. If you are running a server on your local - * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" - * in the configuration file. - * - * Return 0 if completes successfully, -1 on error - */ -int -res_ninit(res_state statp) { - extern int __res_vinit(res_state, int); - - return (__res_vinit(statp, 0)); -} - -/* This function has to be reachable by res_data.c but not publicly. */ -int -__res_vinit(res_state statp, int preinit) { - register FILE *fp; - register char *cp, **pp; - register int n; - char buf[BUFSIZ]; - int nserv = 0; /* number of nameserver records read from file */ - int haveenv = 0; - int havesearch = 0; - int nsort = 0; - char *net; - int dots; - union res_sockaddr_union u[2]; -#ifdef ANDROID_CHANGES - pid_t mypid = getpid(); - int use_proc_props = 0; - int found_prop; - char dnsProperty[PROP_VALUE_MAX]; -#endif - - if (!preinit) { - statp->retrans = RES_TIMEOUT; - statp->retry = RES_DFLRETRY; - statp->options = RES_DEFAULT; - statp->id = res_randomid(); - } - - if ((statp->options & RES_INIT) != 0U) - res_ndestroy(statp); - - memset(u, 0, sizeof(u)); -#ifdef USELOOPBACK - u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); -#else - u[nserv].sin.sin_addr.s_addr = INADDR_ANY; -#endif - u[nserv].sin.sin_family = AF_INET; - u[nserv].sin.sin_port = htons(NAMESERVER_PORT); -#ifdef HAVE_SA_LEN - u[nserv].sin.sin_len = sizeof(struct sockaddr_in); -#endif - nserv++; -#ifdef HAS_INET6_STRUCTS -#ifdef USELOOPBACK - u[nserv].sin6.sin6_addr = in6addr_loopback; -#else - u[nserv].sin6.sin6_addr = in6addr_any; -#endif - u[nserv].sin6.sin6_family = AF_INET6; - u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT); -#ifdef HAVE_SA_LEN - u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6); -#endif - nserv++; -#endif - statp->nscount = 0; - statp->ndots = 1; - statp->pfcode = 0; - statp->_vcsock = -1; - statp->_flags = 0; - statp->qhook = NULL; - statp->rhook = NULL; - statp->_u._ext.nscount = 0; - statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext)); - if (statp->_u._ext.ext != NULL) { - memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext)); - statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr; - strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); - strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); - } - statp->nsort = 0; - res_setservers(statp, u, nserv); - -#if 0 /* IGNORE THE ENVIRONMENT */ - /* Allow user to override the local domain definition */ - if ((cp = getenv("LOCALDOMAIN")) != NULL) { - (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - haveenv++; - - /* - * Set search list to be blank-separated strings - * from rest of env value. Permits users of LOCALDOMAIN - * to still have a search list, and anyone to set the - * one that they want to use as an individual (even more - * important now that the rfc1535 stuff restricts searches) - */ - cp = statp->defdname; - pp = statp->dnsrch; - *pp++ = cp; - for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { - if (*cp == '\n') /* silly backwards compat */ - break; - else if (*cp == ' ' || *cp == '\t') { - *cp = 0; - n = 1; - } else if (n) { - *pp++ = cp; - n = 0; - havesearch = 1; - } - } - /* null terminate last domain if there are excess */ - while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') - cp++; - *cp = '\0'; - *pp++ = 0; - } - if (nserv > 0) - statp->nscount = nserv; -#endif -#ifdef ANDROID_CHANGES /* READ FROM SYSTEM PROPERTIES */ - dns_last_change_counter = _get_dns_change_count(); - - nserv = 0; - for(n = 1; n <= MAX_DNS_PROPERTIES && nserv < MAXNS; n++) { - char propname[PROP_NAME_MAX]; - char propvalue[PROP_VALUE_MAX]; - - struct addrinfo hints, *ai; - char sbuf[NI_MAXSERV]; - const size_t minsiz = sizeof(statp->_u._ext.ext->nsaddrs[0]); - - /* - * Check first for process-specific properties, and if those don't - * exist, try the generic properties. - */ - found_prop = 0; - if (n == 1 || use_proc_props) { - snprintf(propname, sizeof(propname), "%s%d.%d", DNS_PROP_NAME_PREFIX, n, mypid); - if(__system_property_get(propname, propvalue) < 1) { - if (use_proc_props) { - break; - } - } else { - found_prop = 1; - use_proc_props = 1; - } - } - if (!found_prop) { - snprintf(propname, sizeof(propname), "%s%d", DNS_PROP_NAME_PREFIX, n); - if(__system_property_get(propname, propvalue) < 1) { - break; - } - } - - cp = propvalue; - - while (*cp == ' ' || *cp == '\t') - cp++; - cp[strcspn(cp, ";# \t\n")] = '\0'; - if ((*cp != '\0') && (*cp != '\n')) { - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - sprintf(sbuf, "%u", NAMESERVER_PORT); - if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && - (size_t)ai->ai_addrlen <= minsiz) { - if (statp->_u._ext.ext != NULL) { - memcpy(&statp->_u._ext.ext->nsaddrs[nserv], - ai->ai_addr, ai->ai_addrlen); - } - if ((size_t)ai->ai_addrlen <= - sizeof(statp->nsaddr_list[nserv])) { - memcpy(&statp->nsaddr_list[nserv], - ai->ai_addr, ai->ai_addrlen); - } else { - statp->nsaddr_list[nserv].sin_family = 0; - } - freeaddrinfo(ai); - nserv++; - } - } - } -#else /* IGNORE resolv.conf */ -#define MATCH(line, name) \ - (!strncmp(line, name, sizeof(name) - 1) && \ - (line[sizeof(name) - 1] == ' ' || \ - line[sizeof(name) - 1] == '\t')) - - nserv = 0; - if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { - /* read the config file */ - while (fgets(buf, sizeof(buf), fp) != NULL) { - /* skip comments */ - if (*buf == ';' || *buf == '#') - continue; - /* read default domain name */ - if (MATCH(buf, "domain")) { - if (haveenv) /* skip if have from environ */ - continue; - cp = buf + sizeof("domain") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - if ((*cp == '\0') || (*cp == '\n')) - continue; - strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) - *cp = '\0'; - havesearch = 0; - continue; - } - /* set search list */ - if (MATCH(buf, "search")) { - if (haveenv) /* skip if have from environ */ - continue; - cp = buf + sizeof("search") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - if ((*cp == '\0') || (*cp == '\n')) - continue; - strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - if ((cp = strchr(statp->defdname, '\n')) != NULL) - *cp = '\0'; - /* - * Set search list to be blank-separated strings - * on rest of line. - */ - cp = statp->defdname; - pp = statp->dnsrch; - *pp++ = cp; - for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { - if (*cp == ' ' || *cp == '\t') { - *cp = 0; - n = 1; - } else if (n) { - *pp++ = cp; - n = 0; - } - } - /* null terminate last domain if there are excess */ - while (*cp != '\0' && *cp != ' ' && *cp != '\t') - cp++; - *cp = '\0'; - *pp++ = 0; - havesearch = 1; - continue; - } - /* read nameservers to query */ - if (MATCH(buf, "nameserver") && nserv < MAXNS) { - struct addrinfo hints, *ai; - char sbuf[NI_MAXSERV]; - const size_t minsiz = - sizeof(statp->_u._ext.ext->nsaddrs[0]); - - cp = buf + sizeof("nameserver") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - cp[strcspn(cp, ";# \t\n")] = '\0'; - if ((*cp != '\0') && (*cp != '\n')) { - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - sprintf(sbuf, "%u", NAMESERVER_PORT); - if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 && - ai->ai_addrlen <= minsiz) { - if (statp->_u._ext.ext != NULL) { - memcpy(&statp->_u._ext.ext->nsaddrs[nserv], - ai->ai_addr, ai->ai_addrlen); - } - if (ai->ai_addrlen <= - sizeof(statp->nsaddr_list[nserv])) { - memcpy(&statp->nsaddr_list[nserv], - ai->ai_addr, ai->ai_addrlen); - } else - statp->nsaddr_list[nserv].sin_family = 0; - freeaddrinfo(ai); - nserv++; - } - } - continue; - } - if (MATCH(buf, "sortlist")) { - struct in_addr a; - - cp = buf + sizeof("sortlist") - 1; - while (nsort < MAXRESOLVSORT) { - while (*cp == ' ' || *cp == '\t') - cp++; - if (*cp == '\0' || *cp == '\n' || *cp == ';') - break; - net = cp; - while (*cp && !ISSORTMASK(*cp) && *cp != ';' && - isascii(*cp) && !isspace((unsigned char)*cp)) - cp++; - n = *cp; - *cp = 0; - if (inet_aton(net, &a)) { - statp->sort_list[nsort].addr = a; - if (ISSORTMASK(n)) { - *cp++ = n; - net = cp; - while (*cp && *cp != ';' && - isascii(*cp) && - !isspace((unsigned char)*cp)) - cp++; - n = *cp; - *cp = 0; - if (inet_aton(net, &a)) { - statp->sort_list[nsort].mask = a.s_addr; - } else { - statp->sort_list[nsort].mask = - net_mask(statp->sort_list[nsort].addr); - } - } else { - statp->sort_list[nsort].mask = - net_mask(statp->sort_list[nsort].addr); - } - nsort++; - } - *cp = n; - } - continue; - } - if (MATCH(buf, "options")) { - res_setoptions(statp, buf + sizeof("options") - 1, "conf"); - continue; - } - } - if (nserv > 0) - statp->nscount = nserv; - statp->nsort = nsort; - (void) fclose(fp); - } -#endif /* ANDROID_CHANGES */ -/* - * Last chance to get a nameserver. This should not normally - * be necessary - */ -#ifdef NO_RESOLV_CONF - if(nserv == 0) - nserv = get_nameservers(statp); -#endif - - if (statp->defdname[0] == 0 && - gethostname(buf, sizeof(statp->defdname) - 1) == 0 && - (cp = strchr(buf, '.')) != NULL) - strcpy(statp->defdname, cp + 1); - - /* find components of local domain that might be searched */ - if (havesearch == 0) { - pp = statp->dnsrch; - *pp++ = statp->defdname; - *pp = NULL; - - dots = 0; - for (cp = statp->defdname; *cp; cp++) - dots += (*cp == '.'); - - cp = statp->defdname; - while (pp < statp->dnsrch + MAXDFLSRCH) { - if (dots < LOCALDOMAINPARTS) - break; - cp = strchr(cp, '.') + 1; /* we know there is one */ - *pp++ = cp; - dots--; - } - *pp = NULL; -#ifdef DEBUG - if (statp->options & RES_DEBUG) { - printf(";; res_init()... default dnsrch list:\n"); - for (pp = statp->dnsrch; *pp; pp++) - printf(";;\t%s\n", *pp); - printf(";;\t..END..\n"); - } -#endif - } - - if ((cp = getenv("RES_OPTIONS")) != NULL) - res_setoptions(statp, cp, "env"); - if (nserv > 0) { - statp->nscount = nserv; - statp->options |= RES_INIT; - } - return (0); -} - -static void -res_setoptions(res_state statp, const char *options, const char *source) -{ - const char *cp = options; - int i; - struct __res_state_ext *ext = statp->_u._ext.ext; - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_setoptions(\"%s\", \"%s\")...\n", - options, source); -#endif - while (*cp) { - /* skip leading and inner runs of spaces */ - while (*cp == ' ' || *cp == '\t') - cp++; - /* search for and process individual options */ - if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { - i = atoi(cp + sizeof("ndots:") - 1); - if (i <= RES_MAXNDOTS) - statp->ndots = i; - else - statp->ndots = RES_MAXNDOTS; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";;\tndots=%d\n", statp->ndots); -#endif - } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { - i = atoi(cp + sizeof("timeout:") - 1); - if (i <= RES_MAXRETRANS) - statp->retrans = i; - else - statp->retrans = RES_MAXRETRANS; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";;\ttimeout=%d\n", statp->retrans); -#endif - } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ - i = atoi(cp + sizeof("attempts:") - 1); - if (i <= RES_MAXRETRY) - statp->retry = i; - else - statp->retry = RES_MAXRETRY; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";;\tattempts=%d\n", statp->retry); -#endif - } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { -#ifdef DEBUG - if (!(statp->options & RES_DEBUG)) { - printf(";; res_setoptions(\"%s\", \"%s\")..\n", - options, source); - statp->options |= RES_DEBUG; - } - printf(";;\tdebug\n"); -#endif - } else if (!strncmp(cp, "no_tld_query", - sizeof("no_tld_query") - 1) || - !strncmp(cp, "no-tld-query", - sizeof("no-tld-query") - 1)) { - statp->options |= RES_NOTLDQUERY; - } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { - statp->options |= RES_USE_INET6; - } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { - statp->options |= RES_ROTATE; - } else if (!strncmp(cp, "no-check-names", - sizeof("no-check-names") - 1)) { - statp->options |= RES_NOCHECKNAME; - } -#ifdef RES_USE_EDNS0 - else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { - statp->options |= RES_USE_EDNS0; - } -#endif - else if (!strncmp(cp, "dname", sizeof("dname") - 1)) { - statp->options |= RES_USE_DNAME; - } - else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) { - if (ext == NULL) - goto skip; - cp += sizeof("nibble:") - 1; - i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1); - strncpy(ext->nsuffix, cp, (size_t)i); - ext->nsuffix[i] = '\0'; - } - else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) { - if (ext == NULL) - goto skip; - cp += sizeof("nibble2:") - 1; - i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1); - strncpy(ext->nsuffix2, cp, (size_t)i); - ext->nsuffix2[i] = '\0'; - } - else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) { - cp += sizeof("v6revmode:") - 1; - /* "nibble" and "bitstring" used to be valid */ - if (!strncmp(cp, "single", sizeof("single") - 1)) { - statp->options |= RES_NO_NIBBLE2; - } else if (!strncmp(cp, "both", sizeof("both") - 1)) { - statp->options &= - ~RES_NO_NIBBLE2; - } - } - else { - /* XXX - print a warning here? */ - } - skip: - /* skip to next run of spaces */ - while (*cp && *cp != ' ' && *cp != '\t') - cp++; - } -} - -/* XXX - should really support CIDR which means explicit masks always. */ -static u_int32_t -net_mask(in) /* XXX - should really use system's version of this */ - struct in_addr in; -{ - register u_int32_t i = ntohl(in.s_addr); - - if (IN_CLASSA(i)) - return (htonl(IN_CLASSA_NET)); - else if (IN_CLASSB(i)) - return (htonl(IN_CLASSB_NET)); - return (htonl(IN_CLASSC_NET)); -} - -u_int -res_randomid(void) { - struct timeval now; - - gettimeofday(&now, NULL); - return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid())); -} - -/* - * This routine is for closing the socket if a virtual circuit is used and - * the program wants to close it. This provides support for endhostent() - * which expects to close the socket. - * - * This routine is not expected to be user visible. - */ -void -res_nclose(res_state statp) { - int ns; - - if (statp->_vcsock >= 0) { - (void) close(statp->_vcsock); - statp->_vcsock = -1; - statp->_flags &= ~(RES_F_VC | RES_F_CONN); - } - for (ns = 0; ns < statp->_u._ext.nscount; ns++) { - if (statp->_u._ext.nssocks[ns] != -1) { - (void) close(statp->_u._ext.nssocks[ns]); - statp->_u._ext.nssocks[ns] = -1; - } - } -} - -void -res_ndestroy(res_state statp) { - res_nclose(statp); - if (statp->_u._ext.ext != NULL) - free(statp->_u._ext.ext); - statp->options &= ~RES_INIT; - statp->_u._ext.ext = NULL; -} - -const char * -res_get_nibblesuffix(res_state statp) { - if (statp->_u._ext.ext) - return (statp->_u._ext.ext->nsuffix); - return ("ip6.arpa"); -} - -const char * -res_get_nibblesuffix2(res_state statp) { - if (statp->_u._ext.ext) - return (statp->_u._ext.ext->nsuffix2); - return ("ip6.int"); -} - -void -res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) { - int i, nserv; - size_t size; - - /* close open servers */ - res_nclose(statp); - - /* cause rtt times to be forgotten */ - statp->_u._ext.nscount = 0; - - nserv = 0; - for (i = 0; i < cnt && nserv < MAXNS; i++) { - switch (set->sin.sin_family) { - case AF_INET: - size = sizeof(set->sin); - if (statp->_u._ext.ext) - memcpy(&statp->_u._ext.ext->nsaddrs[nserv], - &set->sin, size); - if (size <= sizeof(statp->nsaddr_list[nserv])) - memcpy(&statp->nsaddr_list[nserv], - &set->sin, size); -#ifdef notdef - else - statp->nsaddr_list[nserv].sin_family = 0; -#endif - nserv++; - break; - -#ifdef HAS_INET6_STRUCTS - case AF_INET6: - size = sizeof(set->sin6); - if (statp->_u._ext.ext) - memcpy(&statp->_u._ext.ext->nsaddrs[nserv], - &set->sin6, size); - if (size <= sizeof(statp->nsaddr_list[nserv])) - memcpy(&statp->nsaddr_list[nserv], - &set->sin6, size); - else - statp->nsaddr_list[nserv].sin_family = 0; - nserv++; - break; -#endif - - default: - break; - } - set++; - } - statp->nscount = nserv; - -} - -int -res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) { - int i; - size_t size; - u_int16_t family; - - for (i = 0; i < statp->nscount && i < cnt; i++) { - if (statp->_u._ext.ext) - family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family; - else - family = statp->nsaddr_list[i].sin_family; - - switch (family) { - case AF_INET: - size = sizeof(set->sin); - if (statp->_u._ext.ext) - memcpy(&set->sin, - &statp->_u._ext.ext->nsaddrs[i], - size); - else - memcpy(&set->sin, &statp->nsaddr_list[i], - size); - break; - -#ifdef HAS_INET6_STRUCTS - case AF_INET6: - size = sizeof(set->sin6); - if (statp->_u._ext.ext) - memcpy(&set->sin6, - &statp->_u._ext.ext->nsaddrs[i], - size); - else - memcpy(&set->sin6, &statp->nsaddr_list[i], - size); - break; -#endif - - default: - set->sin.sin_family = 0; - break; - } - set++; - } - return (statp->nscount); -} - -#ifdef ANDROID_CHANGES -static int _get_dns_change_count() -{ - if (dns_change_prop == NULL) { - dns_change_prop = __system_property_find(DNS_CHANGE_PROP_NAME); - } - if (dns_change_prop != NULL) { - char propvalue[PROP_VALUE_MAX]; - if (__system_property_read(dns_change_prop, NULL, propvalue) >= 1) { - return atoi(propvalue); - } - } - return -1; -} - -int res_get_dns_changed() -{ - int change_count; - - change_count = _get_dns_change_count(); - if (change_count != dns_last_change_counter) { - if (change_count != -1) { - dns_last_change_counter = change_count; - } - return 1; - } else { - return 0; - } -} -#endif /* ANDROID_CHANGES */ diff --git a/libc/netbsd/resolv/res_mkquery.c b/libc/netbsd/resolv/res_mkquery.c deleted file mode 100644 index fb4de7f..0000000 --- a/libc/netbsd/resolv/res_mkquery.c +++ /dev/null @@ -1,276 +0,0 @@ -/* $NetBSD: res_mkquery.c,v 1.6 2006/01/24 17:40:32 christos Exp $ */ - -/* - * Copyright (c) 2008 Android Open Source Project (query id randomization) - * Copyright (c) 1985, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: res_mkquery.c,v 1.1.2.2.4.2 2004/03/16 12:34:18 marka Exp"; -#else -__RCSID("$NetBSD: res_mkquery.c,v 1.6 2006/01/24 17:40:32 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - - - -#include <sys/types.h> -#include <sys/param.h> -#include <netinet/in.h> -#include "arpa_nameser.h" -#include <netdb.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif -#include <stdio.h> -#include <string.h> - -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif - -#ifndef lint -#define UNUSED(a) (void)&a -#else -#define UNUSED(a) a = a -#endif - -extern const char *_res_opcodes[]; - -/* - * Form all types of queries. - * Returns the size of the result or -1. - */ -int -res_nmkquery(res_state statp, - int op, /* opcode of query */ - const char *dname, /* domain name */ - int class, int type, /* class and type of query */ - const u_char *data, /* resource record data */ - int datalen, /* length of data */ - const u_char *newrr_in, /* new rr for modify or append */ - u_char *buf, /* buffer to put query */ - int buflen) /* size of buffer */ -{ - register HEADER *hp; - register u_char *cp, *ep; - register int n; - u_char *dnptrs[20], **dpp, **lastdnptr; - - UNUSED(newrr_in); - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_nmkquery(%s, %s, %s, %s)\n", - _res_opcodes[op], dname, p_class(class), p_type(type)); -#endif - /* - * Initialize header fields. - */ - if ((buf == NULL) || (buflen < HFIXEDSZ)) - return (-1); - memset(buf, 0, HFIXEDSZ); - hp = (HEADER *)(void *)buf; - hp->id = htons(res_randomid()); - hp->opcode = op; - hp->rd = (statp->options & RES_RECURSE) != 0U; - hp->rcode = NOERROR; - cp = buf + HFIXEDSZ; - ep = buf + buflen; - dpp = dnptrs; - *dpp++ = buf; - *dpp++ = NULL; - lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; - /* - * perform opcode specific processing - */ - switch (op) { - case QUERY: /*FALLTHROUGH*/ - case NS_NOTIFY_OP: - if (ep - cp < QFIXEDSZ) - return (-1); - if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs, - lastdnptr)) < 0) - return (-1); - cp += n; - ns_put16(type, cp); - cp += INT16SZ; - ns_put16(class, cp); - cp += INT16SZ; - hp->qdcount = htons(1); - if (op == QUERY || data == NULL) - break; - /* - * Make an additional record for completion domain. - */ - if ((ep - cp) < RRFIXEDSZ) - return (-1); - n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ, - dnptrs, lastdnptr); - if (n < 0) - return (-1); - cp += n; - ns_put16(T_NULL, cp); - cp += INT16SZ; - ns_put16(class, cp); - cp += INT16SZ; - ns_put32(0, cp); - cp += INT32SZ; - ns_put16(0, cp); - cp += INT16SZ; - hp->arcount = htons(1); - break; - - case IQUERY: - /* - * Initialize answer section - */ - if (ep - cp < 1 + RRFIXEDSZ + datalen) - return (-1); - *cp++ = '\0'; /* no domain name */ - ns_put16(type, cp); - cp += INT16SZ; - ns_put16(class, cp); - cp += INT16SZ; - ns_put32(0, cp); - cp += INT32SZ; - ns_put16(datalen, cp); - cp += INT16SZ; - if (datalen) { - memcpy(cp, data, (size_t)datalen); - cp += datalen; - } - hp->ancount = htons(1); - break; - - default: - return (-1); - } - return (cp - buf); -} - -#ifdef RES_USE_EDNS0 -/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ -#ifndef T_OPT -#define T_OPT 41 -#endif - -int -res_nopt(res_state statp, - int n0, /* current offset in buffer */ - u_char *buf, /* buffer to put query */ - int buflen, /* size of buffer */ - int anslen) /* UDP answer buffer size */ -{ - register HEADER *hp; - register u_char *cp, *ep; - u_int16_t flags = 0; - -#ifdef DEBUG - if ((statp->options & RES_DEBUG) != 0U) - printf(";; res_nopt()\n"); -#endif - - hp = (HEADER *)(void *)buf; - cp = buf + n0; - ep = buf + buflen; - - if ((ep - cp) < 1 + RRFIXEDSZ) - return (-1); - - *cp++ = 0; /* "." */ - - ns_put16(T_OPT, cp); /* TYPE */ - cp += INT16SZ; - ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */ - cp += INT16SZ; - *cp++ = NOERROR; /* extended RCODE */ - *cp++ = 0; /* EDNS version */ - if (statp->options & RES_USE_DNSSEC) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_opt()... ENDS0 DNSSEC\n"); -#endif - flags |= NS_OPT_DNSSEC_OK; - } - ns_put16(flags, cp); - cp += INT16SZ; - ns_put16(0, cp); /* RDLEN */ - cp += INT16SZ; - hp->arcount = htons(ntohs(hp->arcount) + 1); - - return (cp - buf); -} -#endif diff --git a/libc/netbsd/resolv/res_private.h b/libc/netbsd/resolv/res_private.h deleted file mode 100644 index 8341913..0000000 --- a/libc/netbsd/resolv/res_private.h +++ /dev/null @@ -1,22 +0,0 @@ -/* $NetBSD: res_private.h,v 1.1.1.1 2004/05/20 17:18:54 christos Exp $ */ - -#ifndef res_private_h -#define res_private_h - -struct __res_state_ext { - union res_sockaddr_union nsaddrs[MAXNS]; - struct sort_list { - int af; - union { - struct in_addr ina; - struct in6_addr in6a; - } addr, mask; - } sort_list[MAXRESOLVSORT]; - char nsuffix[64]; - char nsuffix2[64]; -}; - -extern int -res_ourserver_p(const res_state statp, const struct sockaddr *sa); - -#endif diff --git a/libc/netbsd/resolv/res_query.c b/libc/netbsd/resolv/res_query.c deleted file mode 100644 index 8e1321e..0000000 --- a/libc/netbsd/resolv/res_query.c +++ /dev/null @@ -1,415 +0,0 @@ -/* $NetBSD: res_query.c,v 1.7 2006/01/24 17:41:25 christos Exp $ */ - -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: res_query.c,v 1.2.2.3.4.2 2004/03/16 12:34:19 marka Exp"; -#else -__RCSID("$NetBSD: res_query.c,v 1.7 2006/01/24 17:41:25 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - - - -#include <sys/types.h> -#include <sys/param.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#define DISABLE_HOST_ALIAS 1 - -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif - -#if PACKETSZ > 1024 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 1024 -#endif - -/* - * Formulate a normal query, send, and await answer. - * Returned answer is placed in supplied buffer "answer". - * Perform preliminary check of answer, returning success only - * if no error is indicated and the answer count is nonzero. - * Return the size of the response on success, -1 on error. - * Error number is left in H_ERRNO. - * - * Caller must parse answer and determine whether it answers the question. - */ -int -res_nquery(res_state statp, - const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer buffer */ -{ - u_char buf[MAXPACKET]; - HEADER *hp = (HEADER *)(void *)answer; - int n; - u_int oflags; - - oflags = statp->_flags; - -again: - hp->rcode = NOERROR; /* default */ - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query(%s, %d, %d)\n", name, class, type); -#endif - - n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, - buf, sizeof(buf)); -#ifdef RES_USE_EDNS0 - if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 && - (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U) - n = res_nopt(statp, n, buf, sizeof(buf), anslen); -#endif - if (n <= 0) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query: mkquery failed\n"); -#endif - RES_SET_H_ERRNO(statp, NO_RECOVERY); - return (n); - } - n = res_nsend(statp, buf, n, answer, anslen); - if (n < 0) { -#ifdef RES_USE_EDNS0 - /* if the query choked with EDNS0, retry without EDNS0 */ - if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U && - ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { - statp->_flags |= RES_F_EDNS0ERR; - if (statp->options & RES_DEBUG) - printf(";; res_nquery: retry without EDNS0\n"); - goto again; - } -#endif -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query: send error\n"); -#endif - RES_SET_H_ERRNO(statp, TRY_AGAIN); - return (n); - } - - if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n", - p_rcode(hp->rcode), - ntohs(hp->ancount), - ntohs(hp->nscount), - ntohs(hp->arcount)); -#endif - switch (hp->rcode) { - case NXDOMAIN: - RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); - break; - case SERVFAIL: - RES_SET_H_ERRNO(statp, TRY_AGAIN); - break; - case NOERROR: - RES_SET_H_ERRNO(statp, NO_DATA); - break; - case FORMERR: - case NOTIMP: - case REFUSED: - default: - RES_SET_H_ERRNO(statp, NO_RECOVERY); - break; - } - return (-1); - } - return (n); -} - -/* - * Formulate a normal query, send, and retrieve answer in supplied buffer. - * Return the size of the response on success, -1 on error. - * If enabled, implement search rules until answer or unrecoverable failure - * is detected. Error code, if any, is left in H_ERRNO. - */ -int -res_nsearch(res_state statp, - const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - const char *cp, * const *domain; - HEADER *hp = (HEADER *)(void *)answer; - char tmp[NS_MAXDNAME]; - u_int dots; - int trailing_dot, ret, saved_herrno; - int got_nodata = 0, got_servfail = 0, root_on_list = 0; - int tried_as_is = 0; - int searched = 0; - - errno = 0; - RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ - - dots = 0; - for (cp = name; *cp != '\0'; cp++) - dots += (*cp == '.'); - trailing_dot = 0; - if (cp > name && *--cp == '.') - trailing_dot++; - - /* If there aren't any dots, it could be a user-level alias. */ - if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) - return (res_nquery(statp, cp, class, type, answer, anslen)); - - /* - * If there are enough dots in the name, let's just give it a - * try 'as is'. The threshold can be set with the "ndots" option. - * Also, query 'as is', if there is a trailing dot in the name. - */ - saved_herrno = -1; - if (dots >= statp->ndots || trailing_dot) { - ret = res_nquerydomain(statp, name, NULL, class, type, - answer, anslen); - if (ret > 0 || trailing_dot) - return (ret); - saved_herrno = statp->res_h_errno; - tried_as_is++; - } - - /* - * We do at least one level of search if - * - there is no dot and RES_DEFNAME is set, or - * - there is at least one dot, there is no trailing dot, - * and RES_DNSRCH is set. - */ - if ((!dots && (statp->options & RES_DEFNAMES) != 0U) || - (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) { - int done = 0; - - for (domain = (const char * const *)statp->dnsrch; - *domain && !done; - domain++) { - searched = 1; - - if (domain[0][0] == '\0' || - (domain[0][0] == '.' && domain[0][1] == '\0')) - root_on_list++; - - ret = res_nquerydomain(statp, name, *domain, - class, type, - answer, anslen); - if (ret > 0) - return (ret); - - /* - * If no server present, give up. - * If name isn't found in this domain, - * keep trying higher domains in the search list - * (if that's enabled). - * On a NO_DATA error, keep trying, otherwise - * a wildcard entry of another type could keep us - * from finding this entry higher in the domain. - * If we get some other error (negative answer or - * server failure), then stop searching up, - * but try the input name below in case it's - * fully-qualified. - */ - if (errno == ECONNREFUSED) { - RES_SET_H_ERRNO(statp, TRY_AGAIN); - return (-1); - } - - switch (statp->res_h_errno) { - case NO_DATA: - got_nodata++; - /* FALLTHROUGH */ - case HOST_NOT_FOUND: - /* keep trying */ - break; - case TRY_AGAIN: - if (hp->rcode == SERVFAIL) { - /* try next search element, if any */ - got_servfail++; - break; - } - /* FALLTHROUGH */ - default: - /* anything else implies that we're done */ - done++; - } - - /* if we got here for some reason other than DNSRCH, - * we only wanted one iteration of the loop, so stop. - */ - if ((statp->options & RES_DNSRCH) == 0U) - done++; - } - } - - /* - * If the query has not already been tried as is then try it - * unless RES_NOTLDQUERY is set and there were no dots. - */ - if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) && - !(tried_as_is || root_on_list)) { - ret = res_nquerydomain(statp, name, NULL, class, type, - answer, anslen); - if (ret > 0) - return (ret); - } - - /* if we got here, we didn't satisfy the search. - * if we did an initial full query, return that query's H_ERRNO - * (note that we wouldn't be here if that query had succeeded). - * else if we ever got a nodata, send that back as the reason. - * else send back meaningless H_ERRNO, that being the one from - * the last DNSRCH we did. - */ - if (saved_herrno != -1) - RES_SET_H_ERRNO(statp, saved_herrno); - else if (got_nodata) - RES_SET_H_ERRNO(statp, NO_DATA); - else if (got_servfail) - RES_SET_H_ERRNO(statp, TRY_AGAIN); - return (-1); -} - -/* - * Perform a call on res_query on the concatenation of name and domain, - * removing a trailing dot from name if domain is NULL. - */ -int -res_nquerydomain(res_state statp, - const char *name, - const char *domain, - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - char nbuf[MAXDNAME]; - const char *longname = nbuf; - int n, d; - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_nquerydomain(%s, %s, %d, %d)\n", - name, domain?domain:"<Nil>", class, type); -#endif - if (domain == NULL) { - /* - * Check for trailing '.'; - * copy without '.' if present. - */ - n = strlen(name); - if (n >= MAXDNAME) { - RES_SET_H_ERRNO(statp, NO_RECOVERY); - return (-1); - } - n--; - if (n >= 0 && name[n] == '.') { - strncpy(nbuf, name, (size_t)n); - nbuf[n] = '\0'; - } else - longname = name; - } else { - n = strlen(name); - d = strlen(domain); - if (n + d + 1 >= MAXDNAME) { - RES_SET_H_ERRNO(statp, NO_RECOVERY); - return (-1); - } - sprintf(nbuf, "%s.%s", name, domain); - } - return (res_nquery(statp, longname, class, type, answer, anslen)); -} - -const char * -res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { - return (NULL); -} diff --git a/libc/netbsd/resolv/res_random.c b/libc/netbsd/resolv/res_random.c deleted file mode 100644 index 4570c4f..0000000 --- a/libc/netbsd/resolv/res_random.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $OpenBSD: res_random.c,v 1.17 2008/04/13 00:28:35 djm Exp $ */ - -/* - * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de> - * Copyright 2008 Damien Miller <djm@openbsd.org> - * Copyright 2008 Android Open Source Project (thread-safety) - * All rights reserved. - * - * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using - * such a mathematical system to generate more random (yet non-repeating) - * ids to solve the resolver/named problem. But Niels designed the - * actual system based on the constraints. - * - * Later modified by Damien Miller to wrap the LCG output in a 15-bit - * permutation generator based on a Luby-Rackoff block cipher. This - * ensures the output is non-repeating and preserves the MSB twiddle - * trick, but makes it more resistant to LCG prediction. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * seed = random 15bit - * n = prime, g0 = generator to n, - * j = random so that gcd(j,n-1) == 1 - * g = g0^j mod n will be a generator again. - * - * X[0] = random seed. - * X[n] = a*X[n-1]+b mod m is a Linear Congruential Generator - * with a = 7^(even random) mod m, - * b = random with gcd(b,m) == 1 - * m = 31104 and a maximal period of m-1. - * - * The transaction id is determined by: - * id[n] = seed xor (g^X[n] mod n) - * - * Effectivly the id is restricted to the lower 15 bits, thus - * yielding two different cycles by toggling the msb on and off. - * This avoids reuse issues caused by reseeding. - * - * The output of this generator is then randomly permuted though a - * custom 15 bit Luby-Rackoff block cipher. - */ - -#include <sys/types.h> -#include <netinet/in.h> -#include <sys/time.h> -#include "resolv_private.h" - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> - -/* BIONIC-BEGIN */ -static pthread_mutex_t _res_random_lock = PTHREAD_MUTEX_INITIALIZER; -#define _RES_RANDOM_LOCK() pthread_mutex_lock(&_res_random_lock) -#define _RES_RANDOM_UNLOCK() pthread_mutex_unlock(&_res_random_lock) -/* BIONIC-END */ - -#define RU_OUT 180 /* Time after wich will be reseeded */ -#define RU_MAX 30000 /* Uniq cycle, avoid blackjack prediction */ -#define RU_GEN 2 /* Starting generator */ -#define RU_N 32749 /* RU_N-1 = 2*2*3*2729 */ -#define RU_AGEN 7 /* determine ru_a as RU_AGEN^(2*rand) */ -#define RU_M 31104 /* RU_M = 2^7*3^5 - don't change */ -#define RU_ROUNDS 11 /* Number of rounds for permute (odd) */ - -struct prf_ctx { - /* PRF lookup table for odd rounds (7 bits input to 8 bits output) */ - u_char prf7[(RU_ROUNDS / 2) * (1 << 7)]; - - /* PRF lookup table for even rounds (8 bits input to 7 bits output) */ - u_char prf8[((RU_ROUNDS + 1) / 2) * (1 << 8)]; -}; - -#define PFAC_N 3 -const static u_int16_t pfacts[PFAC_N] = { - 2, - 3, - 2729 -}; - -static u_int16_t ru_x; -static u_int16_t ru_seed, ru_seed2; -static u_int16_t ru_a, ru_b; -static u_int16_t ru_g; -static u_int16_t ru_counter = 0; -static u_int16_t ru_msb = 0; -static struct prf_ctx *ru_prf = NULL; -static long ru_reseed; - -static u_int16_t pmod(u_int16_t, u_int16_t, u_int16_t); -static void res_initid(void); - -/* - * Do a fast modular exponation, returned value will be in the range - * of 0 - (mod-1) - */ -static u_int16_t -pmod(u_int16_t gen, u_int16_t exp, u_int16_t mod) -{ - u_int16_t s, t, u; - - s = 1; - t = gen; - u = exp; - - while (u) { - if (u & 1) - s = (s * t) % mod; - u >>= 1; - t = (t * t) % mod; - } - return (s); -} - -/* - * 15-bit permutation based on Luby-Rackoff block cipher - */ -u_int -permute15(u_int in) -{ - int i; - u_int left, right, tmp; - - if (ru_prf == NULL) - return in; - - left = (in >> 8) & 0x7f; - right = in & 0xff; - - /* - * Each round swaps the width of left and right. Even rounds have - * a 7-bit left, odd rounds have an 8-bit left. Since this uses an - * odd number of rounds, left is always 8 bits wide at the end. - */ - for (i = 0; i < RU_ROUNDS; i++) { - if ((i & 1) == 0) - tmp = ru_prf->prf8[(i << (8 - 1)) | right] & 0x7f; - else - tmp = ru_prf->prf7[((i - 1) << (7 - 1)) | right]; - tmp ^= left; - left = right; - right = tmp; - } - - return (right << 8) | left; -} - -/* - * Initializes the seed and chooses a suitable generator. Also toggles - * the msb flag. The msb flag is used to generate two distinct - * cycles of random numbers and thus avoiding reuse of ids. - * - * This function is called from res_randomid() when needed, an - * application does not have to worry about it. - */ -static void -res_initid(void) -{ - u_int16_t j, i; - u_int32_t tmp; - int noprime = 1; - struct timeval tv; - - ru_x = arc4random_uniform(RU_M); - - /* 15 bits of random seed */ - tmp = arc4random(); - ru_seed = (tmp >> 16) & 0x7FFF; - ru_seed2 = tmp & 0x7FFF; - - /* Determine the LCG we use */ - tmp = arc4random(); - ru_b = (tmp & 0xfffe) | 1; - ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M); - while (ru_b % 3 == 0) - ru_b += 2; - - j = arc4random_uniform(RU_N); - - /* - * Do a fast gcd(j,RU_N-1), so we can find a j with - * gcd(j, RU_N-1) == 1, giving a new generator for - * RU_GEN^j mod RU_N - */ - - while (noprime) { - for (i = 0; i < PFAC_N; i++) - if (j % pfacts[i] == 0) - break; - - if (i >= PFAC_N) - noprime = 0; - else - j = (j + 1) % RU_N; - } - - ru_g = pmod(RU_GEN, j, RU_N); - ru_counter = 0; - - /* Initialise PRF for Luby-Rackoff permutation */ - if (ru_prf == NULL) - ru_prf = malloc(sizeof(*ru_prf)); - if (ru_prf != NULL) - arc4random_buf(ru_prf, sizeof(*ru_prf)); - - gettimeofday(&tv, NULL); - ru_reseed = tv.tv_sec + RU_OUT; - ru_msb = ru_msb == 0x8000 ? 0 : 0x8000; -} - -u_int -res_randomid(void) -{ - struct timeval tv; - u_int result; - - _RES_RANDOM_LOCK() - gettimeofday(&tv, NULL); - if (ru_counter >= RU_MAX || tv.tv_sec > ru_reseed) - res_initid(); - - /* Linear Congruential Generator */ - ru_x = (ru_a * ru_x + ru_b) % RU_M; - ru_counter++; - - result = permute15(ru_seed ^ pmod(ru_g, ru_seed2 + ru_x, RU_N)) | ru_msb; - _RES_RANDOM_UNLOCK() - return result; -} - -#if 0 -int -main(int argc, char **argv) -{ - int i, n; - u_int16_t wert; - - res_initid(); - - printf("Generator: %u\n", ru_g); - printf("Seed: %u\n", ru_seed); - printf("Reseed at %ld\n", ru_reseed); - printf("Ru_X: %u\n", ru_x); - printf("Ru_A: %u\n", ru_a); - printf("Ru_B: %u\n", ru_b); - - n = argc > 1 ? atoi(argv[1]) : 60001; - for (i=0;i<n;i++) { - wert = res_randomid(); - printf("%u\n", wert); - } - return 0; -} -#endif - diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c deleted file mode 100644 index 3aca760..0000000 --- a/libc/netbsd/resolv/res_send.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* $NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $ */ - -/* - * Copyright 2008 Android Open Source Project (source port randomization) - * Copyright (c) 1985, 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Portions Copyright (c) 1993 by Digital Equipment Corporation. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies, and that - * the name of Digital Equipment Corporation not be used in advertising or - * publicity pertaining to distribution of the document or software without - * specific, written prior permission. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT - * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Portions Copyright (c) 1996-1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/cdefs.h> -#if defined(LIBC_SCCS) && !defined(lint) -#ifdef notdef -static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "Id: res_send.c,v 1.5.2.2.4.5 2004/08/10 02:19:56 marka Exp"; -#else -__RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - -/* set to 1 to use our small/simple/limited DNS cache */ -#define USE_RESOLV_CACHE 1 - -/* - * Send query to name server and wait for reply. - */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/uio.h> - -#include <netinet/in.h> -#include <netinet/in6.h> -#include "arpa_nameser.h" -#include <arpa/inet.h> - -#include <errno.h> -#include <netdb.h> -#ifdef ANDROID_CHANGES -#include "resolv_private.h" -#else -#include <resolv.h> -#endif -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <isc/eventlib.h> - -#if USE_RESOLV_CACHE -# include <resolv_cache.h> -#endif - -#ifndef DE_CONST -#define DE_CONST(c,v) v = ((c) ? \ - strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL) -#endif - -/* Options. Leave them on. */ -#ifndef DEBUG -#define DEBUG -#endif -#include "res_debug.h" -#include "res_private.h" - -#define EXT(res) ((res)->_u._ext) - -static const int highestFD = FD_SETSIZE - 1; - -/* Forward. */ - -static int get_salen __P((const struct sockaddr *)); -static struct sockaddr * get_nsaddr __P((res_state, size_t)); -static int send_vc(res_state, const u_char *, int, - u_char *, int, int *, int); -static int send_dg(res_state, const u_char *, int, - u_char *, int, int *, int, - int *, int *); -static void Aerror(const res_state, FILE *, const char *, int, - const struct sockaddr *, int); -static void Perror(const res_state, FILE *, const char *, int); -static int sock_eq(struct sockaddr *, struct sockaddr *); -#ifdef NEED_PSELECT -static int pselect(int, void *, void *, void *, - struct timespec *, - const sigset_t *); -#endif -void res_pquery(const res_state, const u_char *, int, FILE *); - - -/* BIONIC-BEGIN: implement source port randomization */ -typedef union { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_in6 sin6; -} _sockaddr_union; - -static int -random_bind( int s, int family ) -{ - _sockaddr_union u; - int j; - socklen_t slen; - - /* clear all, this also sets the IP4/6 address to 'any' */ - memset( &u, 0, sizeof u ); - - switch (family) { - case AF_INET: - u.sin.sin_family = family; - slen = sizeof u.sin; - break; - case AF_INET6: - u.sin6.sin6_family = family; - slen = sizeof u.sin6; - break; - default: - errno = EPROTO; - return -1; - } - - /* first try to bind to a random source port a few times */ - for (j = 0; j < 10; j++) { - /* find a random port between 1025 .. 65534 */ - int port = 1025 + (res_randomid() % (65535-1025)); - if (family == AF_INET) - u.sin.sin_port = htons(port); - else - u.sin6.sin6_port = htons(port); - - if ( !bind( s, &u.sa, slen ) ) - return 0; - } - - /* nothing after 10 tries, our network table is probably busy */ - /* let the system decide which port is best */ - if (family == AF_INET) - u.sin.sin_port = 0; - else - u.sin6.sin6_port = 0; - - return bind( s, &u.sa, slen ); -} -/* BIONIC-END */ - -static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; - -/* Public. */ - -/* int - * res_isourserver(ina) - * looks up "ina" in _res.ns_addr_list[] - * returns: - * 0 : not found - * >0 : found - * author: - * paul vixie, 29may94 - */ -int -res_ourserver_p(const res_state statp, const struct sockaddr *sa) { - const struct sockaddr_in *inp, *srv; - const struct sockaddr_in6 *in6p, *srv6; - int ns; - - switch (sa->sa_family) { - case AF_INET: - inp = (const struct sockaddr_in *)(const void *)sa; - for (ns = 0; ns < statp->nscount; ns++) { - srv = (struct sockaddr_in *)(void *)get_nsaddr(statp, (size_t)ns); - if (srv->sin_family == inp->sin_family && - srv->sin_port == inp->sin_port && - (srv->sin_addr.s_addr == INADDR_ANY || - srv->sin_addr.s_addr == inp->sin_addr.s_addr)) - return (1); - } - break; - case AF_INET6: - if (EXT(statp).ext == NULL) - break; - in6p = (const struct sockaddr_in6 *)(const void *)sa; - for (ns = 0; ns < statp->nscount; ns++) { - srv6 = (struct sockaddr_in6 *)(void *)get_nsaddr(statp, (size_t)ns); - if (srv6->sin6_family == in6p->sin6_family && - srv6->sin6_port == in6p->sin6_port && -#ifdef HAVE_SIN6_SCOPE_ID - (srv6->sin6_scope_id == 0 || - srv6->sin6_scope_id == in6p->sin6_scope_id) && -#endif - (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) || - IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr))) - return (1); - } - break; - default: - break; - } - return (0); -} - -/* int - * res_nameinquery(name, type, class, buf, eom) - * look for (name,type,class) in the query section of packet (buf,eom) - * requires: - * buf + HFIXEDSZ <= eom - * returns: - * -1 : format error - * 0 : not found - * >0 : found - * author: - * paul vixie, 29may94 - */ -int -res_nameinquery(const char *name, int type, int class, - const u_char *buf, const u_char *eom) -{ - const u_char *cp = buf + HFIXEDSZ; - int qdcount = ntohs(((const HEADER*)(const void *)buf)->qdcount); - - while (qdcount-- > 0) { - char tname[MAXDNAME+1]; - int n, ttype, tclass; - - n = dn_expand(buf, eom, cp, tname, sizeof tname); - if (n < 0) - return (-1); - cp += n; - if (cp + 2 * INT16SZ > eom) - return (-1); - ttype = ns_get16(cp); cp += INT16SZ; - tclass = ns_get16(cp); cp += INT16SZ; - if (ttype == type && tclass == class && - ns_samename(tname, name) == 1) - return (1); - } - return (0); -} - -/* int - * res_queriesmatch(buf1, eom1, buf2, eom2) - * is there a 1:1 mapping of (name,type,class) - * in (buf1,eom1) and (buf2,eom2)? - * returns: - * -1 : format error - * 0 : not a 1:1 mapping - * >0 : is a 1:1 mapping - * author: - * paul vixie, 29may94 - */ -int -res_queriesmatch(const u_char *buf1, const u_char *eom1, - const u_char *buf2, const u_char *eom2) -{ - const u_char *cp = buf1 + HFIXEDSZ; - int qdcount = ntohs(((const HEADER*)(const void *)buf1)->qdcount); - - if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) - return (-1); - - /* - * Only header section present in replies to - * dynamic update packets. - */ - if ((((const HEADER *)(const void *)buf1)->opcode == ns_o_update) && - (((const HEADER *)(const void *)buf2)->opcode == ns_o_update)) - return (1); - - if (qdcount != ntohs(((const HEADER*)(const void *)buf2)->qdcount)) - return (0); - while (qdcount-- > 0) { - char tname[MAXDNAME+1]; - int n, ttype, tclass; - - n = dn_expand(buf1, eom1, cp, tname, sizeof tname); - if (n < 0) - return (-1); - cp += n; - if (cp + 2 * INT16SZ > eom1) - return (-1); - ttype = ns_get16(cp); cp += INT16SZ; - tclass = ns_get16(cp); cp += INT16SZ; - if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) - return (0); - } - return (1); -} - - -int -res_nsend(res_state statp, - const u_char *buf, int buflen, u_char *ans, int anssiz) -{ - int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; - char abuf[NI_MAXHOST]; -#if USE_RESOLV_CACHE - struct resolv_cache* cache; - ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED; -#endif - - if (statp->nscount == 0) { - errno = ESRCH; - return (-1); - } - if (anssiz < HFIXEDSZ) { - errno = EINVAL; - return (-1); - } - DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), - (stdout, ";; res_send()\n"), buf, buflen); - v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ; - gotsomewhere = 0; - terrno = ETIMEDOUT; - -#if USE_RESOLV_CACHE - cache = __get_res_cache(); - if (cache != NULL) { - int anslen = 0; - cache_status = _resolv_cache_lookup( - cache, buf, buflen, - ans, anssiz, &anslen); - - if (cache_status == RESOLV_CACHE_FOUND) { - return anslen; - } - } -#endif - - /* - * If the ns_addr_list in the resolver context has changed, then - * invalidate our cached copy and the associated timing data. - */ - if (EXT(statp).nscount != 0) { - int needclose = 0; - struct sockaddr_storage peer; - socklen_t peerlen; - - if (EXT(statp).nscount != statp->nscount) - needclose++; - else - for (ns = 0; ns < statp->nscount; ns++) { - if (statp->nsaddr_list[ns].sin_family && - !sock_eq((struct sockaddr *)(void *)&statp->nsaddr_list[ns], - (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[ns])) { - needclose++; - break; - } - - if (EXT(statp).nssocks[ns] == -1) - continue; - peerlen = sizeof(peer); - if (getsockname(EXT(statp).nssocks[ns], - (struct sockaddr *)(void *)&peer, &peerlen) < 0) { - needclose++; - break; - } - if (!sock_eq((struct sockaddr *)(void *)&peer, - get_nsaddr(statp, (size_t)ns))) { - needclose++; - break; - } - } - if (needclose) { - res_nclose(statp); - EXT(statp).nscount = 0; - } - } - - /* - * Maybe initialize our private copy of the ns_addr_list. - */ - if (EXT(statp).nscount == 0) { - for (ns = 0; ns < statp->nscount; ns++) { - EXT(statp).nstimes[ns] = RES_MAXTIME; - EXT(statp).nssocks[ns] = -1; - if (!statp->nsaddr_list[ns].sin_family) - continue; - EXT(statp).ext->nsaddrs[ns].sin = - statp->nsaddr_list[ns]; - } - EXT(statp).nscount = statp->nscount; - } - - /* - * Some resolvers want to even out the load on their nameservers. - * Note that RES_BLAST overrides RES_ROTATE. - */ - if ((statp->options & RES_ROTATE) != 0U && - (statp->options & RES_BLAST) == 0U) { - union res_sockaddr_union inu; - struct sockaddr_in ina; - int lastns = statp->nscount - 1; - int fd; - u_int16_t nstime; - - if (EXT(statp).ext != NULL) - inu = EXT(statp).ext->nsaddrs[0]; - ina = statp->nsaddr_list[0]; - fd = EXT(statp).nssocks[0]; - nstime = EXT(statp).nstimes[0]; - for (ns = 0; ns < lastns; ns++) { - if (EXT(statp).ext != NULL) - EXT(statp).ext->nsaddrs[ns] = - EXT(statp).ext->nsaddrs[ns + 1]; - statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; - EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; - EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1]; - } - if (EXT(statp).ext != NULL) - EXT(statp).ext->nsaddrs[lastns] = inu; - statp->nsaddr_list[lastns] = ina; - EXT(statp).nssocks[lastns] = fd; - EXT(statp).nstimes[lastns] = nstime; - } - - /* - * Send request, RETRY times, or until successful. - */ - for (try = 0; try < statp->retry; try++) { - for (ns = 0; ns < statp->nscount; ns++) { - struct sockaddr *nsap; - int nsaplen; - nsap = get_nsaddr(statp, (size_t)ns); - nsaplen = get_salen(nsap); - statp->_flags &= ~RES_F_LASTMASK; - statp->_flags |= (ns << RES_F_LASTSHIFT); - same_ns: - if (statp->qhook) { - int done = 0, loops = 0; - - do { - res_sendhookact act; - - act = (*statp->qhook)(&nsap, &buf, &buflen, - ans, anssiz, &resplen); - switch (act) { - case res_goahead: - done = 1; - break; - case res_nextns: - res_nclose(statp); - goto next_ns; - case res_done: - return (resplen); - case res_modified: - /* give the hook another try */ - if (++loops < 42) /*doug adams*/ - break; - /*FALLTHROUGH*/ - case res_error: - /*FALLTHROUGH*/ - default: - goto fail; - } - } while (!done); - } - - Dprint(((statp->options & RES_DEBUG) && - getnameinfo(nsap, (socklen_t)nsaplen, abuf, sizeof(abuf), - NULL, 0, niflags) == 0), - (stdout, ";; Querying server (# %d) address = %s\n", - ns + 1, abuf)); - - - if (v_circuit) { - /* Use VC; at most one attempt per server. */ - try = statp->retry; - n = send_vc(statp, buf, buflen, ans, anssiz, &terrno, - ns); - if (n < 0) - goto fail; - if (n == 0) - goto next_ns; - resplen = n; - } else { - /* Use datagrams. */ - n = send_dg(statp, buf, buflen, ans, anssiz, &terrno, - ns, &v_circuit, &gotsomewhere); - if (n < 0) - goto fail; - if (n == 0) - goto next_ns; - if (v_circuit) - goto same_ns; - resplen = n; - } - - Dprint((statp->options & RES_DEBUG) || - ((statp->pfcode & RES_PRF_REPLY) && - (statp->pfcode & RES_PRF_HEAD1)), - (stdout, ";; got answer:\n")); - - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, "%s", ""), - ans, (resplen > anssiz) ? anssiz : resplen); - -#if USE_RESOLV_CACHE - if (cache_status == RESOLV_CACHE_NOTFOUND) { - _resolv_cache_add(cache, buf, buflen, - ans, resplen); - } -#endif - /* - * If we have temporarily opened a virtual circuit, - * or if we haven't been asked to keep a socket open, - * close the socket. - */ - if ((v_circuit && (statp->options & RES_USEVC) == 0U) || - (statp->options & RES_STAYOPEN) == 0U) { - res_nclose(statp); - } - if (statp->rhook) { - int done = 0, loops = 0; - - do { - res_sendhookact act; - - act = (*statp->rhook)(nsap, buf, buflen, - ans, anssiz, &resplen); - switch (act) { - case res_goahead: - case res_done: - done = 1; - break; - case res_nextns: - res_nclose(statp); - goto next_ns; - case res_modified: - /* give the hook another try */ - if (++loops < 42) /*doug adams*/ - break; - /*FALLTHROUGH*/ - case res_error: - /*FALLTHROUGH*/ - default: - goto fail; - } - } while (!done); - - } - return (resplen); - next_ns: ; - } /*foreach ns*/ - } /*foreach retry*/ - res_nclose(statp); - if (!v_circuit) { - if (!gotsomewhere) - errno = ECONNREFUSED; /* no nameservers found */ - else - errno = ETIMEDOUT; /* no answer obtained */ - } else - errno = terrno; - return (-1); - fail: - res_nclose(statp); - return (-1); -} - -/* Private */ - -static int -get_salen(sa) - const struct sockaddr *sa; -{ - -#ifdef HAVE_SA_LEN - /* There are people do not set sa_len. Be forgiving to them. */ - if (sa->sa_len) - return (sa->sa_len); -#endif - - if (sa->sa_family == AF_INET) - return (sizeof(struct sockaddr_in)); - else if (sa->sa_family == AF_INET6) - return (sizeof(struct sockaddr_in6)); - else - return (0); /* unknown, die on connect */ -} - -/* - * pick appropriate nsaddr_list for use. see res_init() for initialization. - */ -static struct sockaddr * -get_nsaddr(statp, n) - res_state statp; - size_t n; -{ - - if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) { - /* - * - EXT(statp).ext->nsaddrs[n] holds an address that is larger - * than struct sockaddr, and - * - user code did not update statp->nsaddr_list[n]. - */ - return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n]; - } else { - /* - * - user code updated statp->nsaddr_list[n], or - * - statp->nsaddr_list[n] has the same content as - * EXT(statp).ext->nsaddrs[n]. - */ - return (struct sockaddr *)(void *)&statp->nsaddr_list[n]; - } -} - -static int -send_vc(res_state statp, - const u_char *buf, int buflen, u_char *ans, int anssiz, - int *terrno, int ns) -{ - const HEADER *hp = (const HEADER *)(const void *)buf; - HEADER *anhp = (HEADER *)(void *)ans; - struct sockaddr *nsap; - int nsaplen; - int truncating, connreset, resplen, n; - struct iovec iov[2]; - u_short len; - u_char *cp; - void *tmp; - - nsap = get_nsaddr(statp, (size_t)ns); - nsaplen = get_salen(nsap); - - connreset = 0; - same_ns: - truncating = 0; - - /* Are we still talking to whom we want to talk to? */ - if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { - struct sockaddr_storage peer; - socklen_t size = sizeof peer; - - if (getpeername(statp->_vcsock, - (struct sockaddr *)(void *)&peer, &size) < 0 || - !sock_eq((struct sockaddr *)(void *)&peer, nsap)) { - res_nclose(statp); - statp->_flags &= ~RES_F_VC; - } - } - - if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { - if (statp->_vcsock >= 0) - res_nclose(statp); - - statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); - if (statp->_vcsock > highestFD) { - res_nclose(statp); - errno = ENOTSOCK; - } - if (statp->_vcsock < 0) { - switch (errno) { - case EPROTONOSUPPORT: -#ifdef EPFNOSUPPORT - case EPFNOSUPPORT: -#endif - case EAFNOSUPPORT: - Perror(statp, stderr, "socket(vc)", errno); - return (0); - default: - *terrno = errno; - Perror(statp, stderr, "socket(vc)", errno); - return (-1); - } - } - errno = 0; - if (random_bind(statp->_vcsock,nsap->sa_family) < 0) { - *terrno = errno; - Aerror(statp, stderr, "bind/vc", errno, nsap, - nsaplen); - res_nclose(statp); - return (0); - } - if (connect(statp->_vcsock, nsap, (socklen_t)nsaplen) < 0) { - *terrno = errno; - Aerror(statp, stderr, "connect/vc", errno, nsap, - nsaplen); - res_nclose(statp); - return (0); - } - statp->_flags |= RES_F_VC; - } - - /* - * Send length & message - */ - ns_put16((u_short)buflen, (u_char*)(void *)&len); - iov[0] = evConsIovec(&len, INT16SZ); - DE_CONST(buf, tmp); - iov[1] = evConsIovec(tmp, (size_t)buflen); - if (writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) { - *terrno = errno; - Perror(statp, stderr, "write failed", errno); - res_nclose(statp); - return (0); - } - /* - * Receive length & response - */ - read_len: - cp = ans; - len = INT16SZ; - while ((n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0) { - cp += n; - if ((len -= n) == 0) - break; - } - if (n <= 0) { - *terrno = errno; - Perror(statp, stderr, "read failed", errno); - res_nclose(statp); - /* - * A long running process might get its TCP - * connection reset if the remote server was - * restarted. Requery the server instead of - * trying a new one. When there is only one - * server, this means that a query might work - * instead of failing. We only allow one reset - * per query to prevent looping. - */ - if (*terrno == ECONNRESET && !connreset) { - connreset = 1; - res_nclose(statp); - goto same_ns; - } - res_nclose(statp); - return (0); - } - resplen = ns_get16(ans); - if (resplen > anssiz) { - Dprint(statp->options & RES_DEBUG, - (stdout, ";; response truncated\n") - ); - truncating = 1; - len = anssiz; - } else - len = resplen; - if (len < HFIXEDSZ) { - /* - * Undersized message. - */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; undersized: %d\n", len)); - *terrno = EMSGSIZE; - res_nclose(statp); - return (0); - } - cp = ans; - while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (size_t)len)) > 0){ - cp += n; - len -= n; - } - if (n <= 0) { - *terrno = errno; - Perror(statp, stderr, "read(vc)", errno); - res_nclose(statp); - return (0); - } - if (truncating) { - /* - * Flush rest of answer so connection stays in synch. - */ - anhp->tc = 1; - len = resplen - anssiz; - while (len != 0) { - char junk[PACKETSZ]; - - n = read(statp->_vcsock, junk, - (len > sizeof junk) ? sizeof junk : len); - if (n > 0) - len -= n; - else - break; - } - } - /* - * If the calling applicating has bailed out of - * a previous call and failed to arrange to have - * the circuit closed or the server has got - * itself confused, then drop the packet and - * wait for the correct one. - */ - if (hp->id != anhp->id) { - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; old answer (unexpected):\n"), - ans, (resplen > anssiz) ? anssiz: resplen); - goto read_len; - } - - /* - * All is well, or the error is fatal. Signal that the - * next nameserver ought not be tried. - */ - return (resplen); -} - -static int -send_dg(res_state statp, - const u_char *buf, int buflen, u_char *ans, int anssiz, - int *terrno, int ns, int *v_circuit, int *gotsomewhere) -{ - const HEADER *hp = (const HEADER *)(const void *)buf; - HEADER *anhp = (HEADER *)(void *)ans; - const struct sockaddr *nsap; - int nsaplen; - struct timespec now, timeout, finish; - fd_set dsmask; - struct sockaddr_storage from; - socklen_t fromlen; - int resplen, seconds, n, s; - - nsap = get_nsaddr(statp, (size_t)ns); - nsaplen = get_salen(nsap); - if (EXT(statp).nssocks[ns] == -1) { - EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM, 0); - if (EXT(statp).nssocks[ns] > highestFD) { - res_nclose(statp); - errno = ENOTSOCK; - } - if (EXT(statp).nssocks[ns] < 0) { - switch (errno) { - case EPROTONOSUPPORT: -#ifdef EPFNOSUPPORT - case EPFNOSUPPORT: -#endif - case EAFNOSUPPORT: - Perror(statp, stderr, "socket(dg)", errno); - return (0); - default: - *terrno = errno; - Perror(statp, stderr, "socket(dg)", errno); - return (-1); - } - } -#ifndef CANNOT_CONNECT_DGRAM - /* - * On a 4.3BSD+ machine (client and server, - * actually), sending to a nameserver datagram - * port with no nameserver will cause an - * ICMP port unreachable message to be returned. - * If our datagram socket is "connected" to the - * server, we get an ECONNREFUSED error on the next - * socket operation, and select returns if the - * error message is received. We can thus detect - * the absence of a nameserver without timing out. - */ - if (random_bind(EXT(statp).nssocks[ns], nsap->sa_family) < 0) { - Aerror(statp, stderr, "bind(dg)", errno, nsap, - nsaplen); - res_nclose(statp); - return (0); - } - if (connect(EXT(statp).nssocks[ns], nsap, (socklen_t)nsaplen) < 0) { - Aerror(statp, stderr, "connect(dg)", errno, nsap, - nsaplen); - res_nclose(statp); - return (0); - } -#endif /* !CANNOT_CONNECT_DGRAM */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; new DG socket\n")) - } - s = EXT(statp).nssocks[ns]; -#ifndef CANNOT_CONNECT_DGRAM - if (send(s, (const char*)buf, (size_t)buflen, 0) != buflen) { - Perror(statp, stderr, "send", errno); - res_nclose(statp); - return (0); - } -#else /* !CANNOT_CONNECT_DGRAM */ - if (sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) - { - Aerror(statp, stderr, "sendto", errno, nsap, nsaplen); - res_nclose(statp); - return (0); - } -#endif /* !CANNOT_CONNECT_DGRAM */ - - /* - * Wait for reply. - */ - seconds = (statp->retrans << ns); - if (ns > 0) - seconds /= statp->nscount; - if (seconds <= 0) - seconds = 1; - now = evNowTime(); - timeout = evConsTime((long)seconds, 0L); - finish = evAddTime(now, timeout); - goto nonow; - wait: - now = evNowTime(); - nonow: - FD_ZERO(&dsmask); - FD_SET(s, &dsmask); - if (evCmpTime(finish, now) > 0) - timeout = evSubTime(finish, now); - else - timeout = evConsTime(0L, 0L); - n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL); - if (n == 0) { - Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); - *gotsomewhere = 1; - return (0); - } - if (n < 0) { - if (errno == EINTR) - goto wait; - Perror(statp, stderr, "select", errno); - res_nclose(statp); - return (0); - } - errno = 0; - fromlen = sizeof(from); - resplen = recvfrom(s, (char*)ans, (size_t)anssiz,0, - (struct sockaddr *)(void *)&from, &fromlen); - if (resplen <= 0) { - Perror(statp, stderr, "recvfrom", errno); - res_nclose(statp); - return (0); - } - *gotsomewhere = 1; - if (resplen < HFIXEDSZ) { - /* - * Undersized message. - */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; undersized: %d\n", - resplen)); - *terrno = EMSGSIZE; - res_nclose(statp); - return (0); - } - if (hp->id != anhp->id) { - /* - * response from old query, ignore it. - * XXX - potential security hazard could - * be detected here. - */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; old answer:\n"), - ans, (resplen > anssiz) ? anssiz : resplen); - goto wait; - } - if (!(statp->options & RES_INSECURE1) && - !res_ourserver_p(statp, (struct sockaddr *)(void *)&from)) { - /* - * response from wrong server? ignore it. - * XXX - potential security hazard could - * be detected here. - */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; not our server:\n"), - ans, (resplen > anssiz) ? anssiz : resplen); - goto wait; - } -#ifdef RES_USE_EDNS0 - if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) { - /* - * Do not retry if the server do not understand EDNS0. - * The case has to be captured here, as FORMERR packet do not - * carry query section, hence res_queriesmatch() returns 0. - */ - DprintQ(statp->options & RES_DEBUG, - (stdout, "server rejected query with EDNS0:\n"), - ans, (resplen > anssiz) ? anssiz : resplen); - /* record the error */ - statp->_flags |= RES_F_EDNS0ERR; - res_nclose(statp); - return (0); - } -#endif - if (!(statp->options & RES_INSECURE2) && - !res_queriesmatch(buf, buf + buflen, - ans, ans + anssiz)) { - /* - * response contains wrong query? ignore it. - * XXX - potential security hazard could - * be detected here. - */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; wrong query name:\n"), - ans, (resplen > anssiz) ? anssiz : resplen); - goto wait; - } - if (anhp->rcode == SERVFAIL || - anhp->rcode == NOTIMP || - anhp->rcode == REFUSED) { - DprintQ(statp->options & RES_DEBUG, - (stdout, "server rejected query:\n"), - ans, (resplen > anssiz) ? anssiz : resplen); - res_nclose(statp); - /* don't retry if called from dig */ - if (!statp->pfcode) - return (0); - } - if (!(statp->options & RES_IGNTC) && anhp->tc) { - /* - * To get the rest of answer, - * use TCP with same server. - */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; truncated answer\n")); - *v_circuit = 1; - res_nclose(statp); - return (1); - } - /* - * All is well, or the error is fatal. Signal that the - * next nameserver ought not be tried. - */ - return (resplen); -} - -static void -Aerror(const res_state statp, FILE *file, const char *string, int error, - const struct sockaddr *address, int alen) -{ - int save = errno; - char hbuf[NI_MAXHOST]; - char sbuf[NI_MAXSERV]; - - alen = alen; - - if ((statp->options & RES_DEBUG) != 0U) { - if (getnameinfo(address, (socklen_t)alen, hbuf, sizeof(hbuf), - sbuf, sizeof(sbuf), niflags)) { - strncpy(hbuf, "?", sizeof(hbuf) - 1); - hbuf[sizeof(hbuf) - 1] = '\0'; - strncpy(sbuf, "?", sizeof(sbuf) - 1); - sbuf[sizeof(sbuf) - 1] = '\0'; - } - fprintf(file, "res_send: %s ([%s].%s): %s\n", - string, hbuf, sbuf, strerror(error)); - } - errno = save; -} - -static void -Perror(const res_state statp, FILE *file, const char *string, int error) { - int save = errno; - - if ((statp->options & RES_DEBUG) != 0U) - fprintf(file, "res_send: %s: %s\n", - string, strerror(error)); - errno = save; -} - -static int -sock_eq(struct sockaddr *a, struct sockaddr *b) { - struct sockaddr_in *a4, *b4; - struct sockaddr_in6 *a6, *b6; - - if (a->sa_family != b->sa_family) - return 0; - switch (a->sa_family) { - case AF_INET: - a4 = (struct sockaddr_in *)(void *)a; - b4 = (struct sockaddr_in *)(void *)b; - return a4->sin_port == b4->sin_port && - a4->sin_addr.s_addr == b4->sin_addr.s_addr; - case AF_INET6: - a6 = (struct sockaddr_in6 *)(void *)a; - b6 = (struct sockaddr_in6 *)(void *)b; - return a6->sin6_port == b6->sin6_port && -#ifdef HAVE_SIN6_SCOPE_ID - a6->sin6_scope_id == b6->sin6_scope_id && -#endif - IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr); - default: - return 0; - } -} - -#ifdef NEED_PSELECT -/* XXX needs to move to the porting library. */ -static int -pselect(int nfds, void *rfds, void *wfds, void *efds, - struct timespec *tsp, const sigset_t *sigmask) -{ - struct timeval tv, *tvp; - sigset_t sigs; - int n; - - if (tsp) { - tvp = &tv; - tv = evTimeVal(*tsp); - } else - tvp = NULL; - if (sigmask) - sigprocmask(SIG_SETMASK, sigmask, &sigs); - n = select(nfds, rfds, wfds, efds, tvp); - if (sigmask) - sigprocmask(SIG_SETMASK, &sigs, NULL); - if (tsp) - *tsp = evTimeSpec(tv); - return (n); -} -#endif diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c deleted file mode 100644 index 3a2301d..0000000 --- a/libc/netbsd/resolv/res_state.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include <sys/cdefs.h> -#include <sys/types.h> -#include <arpa/inet.h> -#include "arpa_nameser.h" -#include <netdb.h> -#include "resolv_private.h" -#include "resolv_cache.h" -#include <pthread.h> -#include <stdlib.h> - -#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ -#include <sys/_system_properties.h> - -static pthread_key_t _res_key; -static pthread_once_t _res_once; - -typedef struct { - int _h_errno; - struct __res_state _nres[1]; - unsigned _serial; - struct prop_info* _pi; - struct res_static _rstatic[1]; -} _res_thread; - -static _res_thread* -_res_thread_alloc(void) -{ - _res_thread* rt = malloc(sizeof(*rt)); - - if (rt) { - rt->_h_errno = 0; - /* Special system property which tracks any changes to 'net.*'. */ - rt->_serial = 0; - rt->_pi = (struct prop_info*) __system_property_find("net.change"); - if (rt->_pi) { - rt->_serial = rt->_pi->serial; - } - if ( res_ninit( rt->_nres ) < 0 ) { - free(rt); - rt = NULL; - } else { - memset(rt->_rstatic, 0, sizeof rt->_rstatic); - } - } - return rt; -} - -static void -_res_static_done( res_static rs ) -{ - /* fortunately, there is nothing to do here, since the - * points in h_addr_ptrs and host_aliases should all - * point to 'hostbuf' - */ - if (rs->hostf) { /* should not happen in theory, but just be safe */ - fclose(rs->hostf); - rs->hostf = NULL; - } - free(rs->servent.s_aliases); -} - -static void -_res_thread_free( void* _rt ) -{ - _res_thread* rt = _rt; - - _res_static_done(rt->_rstatic); - res_ndestroy(rt->_nres); - free(rt); -} - -static void -_res_init_key( void ) -{ - pthread_key_create( &_res_key, _res_thread_free ); -} - -static _res_thread* -_res_thread_get(void) -{ - _res_thread* rt; - pthread_once( &_res_once, _res_init_key ); - rt = pthread_getspecific( _res_key ); - if (rt == NULL) { - if ((rt = _res_thread_alloc()) == NULL) { - return NULL; - } - rt->_h_errno = 0; - rt->_serial = 0; - pthread_setspecific( _res_key, rt ); - } - /* Check the serial value for any chanes to net.* properties. */ - if (rt->_pi == NULL) { - rt->_pi = (struct prop_info*) __system_property_find("net.change"); - } - if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) { - return rt; - } - rt->_serial = rt->_pi->serial; - /* Reload from system properties. */ - if ( res_ninit( rt->_nres ) < 0 ) { - free(rt); - rt = NULL; - pthread_setspecific( _res_key, rt ); - } - _resolv_cache_reset(rt->_serial); - return rt; -} - -struct __res_state _nres; - -#if 0 -struct resolv_cache* -__get_res_cache(void) -{ - _res_thread* rt = _res_thread_get(); - - if (!rt) - return NULL; - - if (!rt->_cache) { - rt->_cache = _resolv_cache_create(); - } - return rt->_cache; -} -#endif - -int* -__get_h_errno(void) -{ - _res_thread* rt = _res_thread_get(); - static int panic = NETDB_INTERNAL; - - return rt ? &rt->_h_errno : &panic; -} - -res_state -__res_get_state(void) -{ - _res_thread* rt = _res_thread_get(); - - return rt ? rt->_nres : NULL; -} - -void -__res_put_state(res_state res) -{ - /* nothing to do */ - res=res; -} - -res_static -__res_get_static(void) -{ - _res_thread* rt = _res_thread_get(); - - return rt ? rt->_rstatic : NULL; -} |