diff options
Diffstat (limited to 'libc/netbsd/net')
-rw-r--r-- | libc/netbsd/net/base64.c | 340 | ||||
-rw-r--r-- | libc/netbsd/net/getaddrinfo.c | 1792 | ||||
-rw-r--r-- | libc/netbsd/net/getnameinfo.c | 519 | ||||
-rw-r--r-- | libc/netbsd/net/getservbyname.c | 54 | ||||
-rw-r--r-- | libc/netbsd/net/getservbyname_r.c | 76 | ||||
-rw-r--r-- | libc/netbsd/net/getservbyport.c | 53 | ||||
-rw-r--r-- | libc/netbsd/net/getservbyport_r.c | 65 | ||||
-rw-r--r-- | libc/netbsd/net/getservent.c | 124 | ||||
-rw-r--r-- | libc/netbsd/net/getservent_r.c | 151 | ||||
-rw-r--r-- | libc/netbsd/net/nsdispatch.c | 152 | ||||
-rw-r--r-- | libc/netbsd/net/reentrant.h | 268 | ||||
-rw-r--r-- | libc/netbsd/net/servent.h | 44 | ||||
-rw-r--r-- | libc/netbsd/net/services.h | 480 |
13 files changed, 4118 insertions, 0 deletions
diff --git a/libc/netbsd/net/base64.c b/libc/netbsd/net/base64.c new file mode 100644 index 0000000..70caaf7 --- /dev/null +++ b/libc/netbsd/net/base64.c @@ -0,0 +1,340 @@ +/* $NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $ */ + +/* + * Copyright (c) 1996 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: base64.c,v 1.8 2002/11/11 01:15:17 thorpej Exp $"); +#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 <assert.h> +#include <ctype.h> +#ifdef ANDROID_CHANGES +#include "resolv_private.h" +#else +#include <resolv.h> +#endif +#include <stdio.h> + +#include <stdlib.h> +#include <string.h> + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(src, srclength, target, targsize) + u_char const *src; + size_t srclength; + char *target; + size_t targsize; +{ + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + assert(src != NULL); + assert(target != NULL); + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = (u_int32_t)input[0] >> 2; + output[1] = ((u_int32_t)(input[0] & 0x03) << 4) + + ((u_int32_t)input[1] >> 4); + output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) + + ((u_int32_t)input[2] >> 6); + output[3] = input[2] & 0x3f; + assert(output[0] < 64); + assert(output[1] < 64); + assert(output[2] < 64); + assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = (u_int32_t)input[0] >> 2; + output[1] = ((u_int32_t)(input[0] & 0x03) << 4) + + ((u_int32_t)input[1] >> 4); + output[2] = ((u_int32_t)(input[1] & 0x0f) << 2) + + ((u_int32_t)input[2] >> 6); + assert(output[0] < 64); + assert(output[1] < 64); + assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton(src, target, targsize) + char const *src; + u_char *target; + size_t targsize; +{ + size_t tarindex; + int state, ch; + char *pos; + + assert(src != NULL); + assert(target != NULL); + + state = 0; + tarindex = 0; + + while ((ch = (u_char) *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= + (u_int32_t)(pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if (tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= + (u_int32_t)(pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if (tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for (; ch != '\0'; ch = (u_char) *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for (; ch != '\0'; ch = (u_char) *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c new file mode 100644 index 0000000..2dd3d97 --- /dev/null +++ b/libc/netbsd/net/getaddrinfo.c @@ -0,0 +1,1792 @@ +/* $NetBSD: getaddrinfo.c,v 1.82 2006/03/25 12:09:40 rpaulo Exp $ */ +/* $KAME: getaddrinfo.c,v 1.29 2000/08/31 17:26:57 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE 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: + * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked. + * - Return values. There are nonstandard return values defined and used + * in the source code. This is because RFC2553 is silent about which error + * code must be returned for which situation. + * - IPv4 classful (shortened) form. RFC2553 is silent about it. XNET 5.2 + * says to use inet_aton() to convert IPv4 numeric to binary (alows + * classful form as a result). + * current code - disallow classful form for IPv4 (due to use of inet_pton). + * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is + * invalid. + * current code - SEGV on freeaddrinfo(NULL) + * Note: + * - We use getipnodebyname() just for thread-safeness. There's no intent + * to let it do PF_UNSPEC (actually we never pass PF_UNSPEC to + * getipnodebyname(). + * - The code filters out AFs that are not supported by the kernel, + * when globbing NULL hostname (to loopback, or wildcard). Is it the right + * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG + * in ai_flags? + * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague. + * (1) what should we do against numeric hostname (2) what should we do + * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready? + * non-loopback address configured? global address configured? + * - To avoid search order issue, we have a big amount of code duplicate + * from gethnamaddr.c and some other places. The issues that there's no + * lower layer function to lookup "IPv4 or IPv6" record. Calling + * gethostbyname2 from getaddrinfo will end up in wrong search order, as + * follows: + * - The code makes use of following calls when asked to resolver with + * ai_family = PF_UNSPEC: + * getipnodebyname(host, AF_INET6); + * getipnodebyname(host, AF_INET); + * This will result in the following queries if the node is configure to + * prefer /etc/hosts than DNS: + * lookup /etc/hosts for IPv6 address + * lookup DNS for IPv6 address + * lookup /etc/hosts for IPv4 address + * lookup DNS for IPv4 address + * which may not meet people's requirement. + * The right thing to happen is to have underlying layer which does + * PF_UNSPEC lookup (lookup both) and return chain of addrinfos. + * This would result in a bit of code duplicate with _dns_ghbyname() and + * friends. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "arpa_nameser.h" +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include "resolv_private.h" +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <syslog.h> +#include <stdarg.h> +#include "nsswitch.h" + +#define SUCCESS 0 +#define ANY 0 +#define YES 1 +#define NO 0 + +static const char in_addrany[] = { 0, 0, 0, 0 }; +static const char in_loopback[] = { 127, 0, 0, 1 }; +#ifdef INET6 +static const char in6_addrany[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +static const char in6_loopback[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; +#endif + +static const struct afd { + int a_af; + int a_addrlen; + int a_socklen; + int a_off; + const char *a_addrany; + const char *a_loopback; + int a_scoped; +} afdl [] = { +#ifdef INET6 + {PF_INET6, sizeof(struct in6_addr), + sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr), + in6_addrany, in6_loopback, 1}, +#endif + {PF_INET, sizeof(struct in_addr), + sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr), + in_addrany, in_loopback, 0}, + {0, 0, 0, 0, NULL, NULL, 0}, +}; + +struct explore { + int e_af; + int e_socktype; + int e_protocol; + const char *e_protostr; + int e_wild; +#define WILD_AF(ex) ((ex)->e_wild & 0x01) +#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02) +#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04) +}; + +static const struct explore explore[] = { +#if 0 + { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 }, +#endif +#ifdef INET6 + { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 }, +#endif + { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_INET, SOCK_RAW, ANY, NULL, 0x05 }, + { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 }, + { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 }, + { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 }, + { -1, 0, 0, NULL, 0 }, +}; + +#ifdef INET6 +#define PTON_MAX 16 +#else +#define PTON_MAX 4 +#endif + +static const ns_src default_dns_files[] = { + { NSSRC_FILES, NS_SUCCESS }, + { NSSRC_DNS, NS_SUCCESS }, + { 0, 0 } +}; + +#define MAXPACKET (64*1024) + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +struct res_target { + struct res_target *next; + const char *name; /* domain name */ + int qclass, qtype; /* class and type of query */ + u_char *answer; /* buffer to put answer */ + int anslen; /* size of answer buffer */ + int n; /* result length */ +}; + +static int str2number(const char *); +static int explore_fqdn(const struct addrinfo *, const char *, + const char *, struct addrinfo **); +static int explore_null(const struct addrinfo *, + const char *, struct addrinfo **); +static int explore_numeric(const struct addrinfo *, const char *, + const char *, struct addrinfo **, const char *); +static int explore_numeric_scope(const struct addrinfo *, const char *, + const char *, struct addrinfo **); +static int get_canonname(const struct addrinfo *, + struct addrinfo *, const char *); +static struct addrinfo *get_ai(const struct addrinfo *, + const struct afd *, const char *); +static int get_portmatch(const struct addrinfo *, const char *); +static int get_port(const struct addrinfo *, const char *, int); +static const struct afd *find_afd(int); +#ifdef INET6 +static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *); +#endif + +static struct addrinfo *getanswer(const querybuf *, int, const char *, int, + const struct addrinfo *); +static void aisort(struct addrinfo *s, res_state res); +static int _dns_getaddrinfo(void *, void *, va_list); +static void _sethtent(FILE **); +static void _endhtent(FILE **); +static struct addrinfo *_gethtent(FILE **, const char *, + const struct addrinfo *); +static int _files_getaddrinfo(void *, void *, va_list); + +static int res_queryN(const char *, struct res_target *, res_state); +static int res_searchN(const char *, struct res_target *, res_state); +static int res_querydomainN(const char *, const char *, + struct res_target *, res_state); + +static const char * const ai_errlist[] = { + "Success", + "Address family for hostname not supported", /* EAI_ADDRFAMILY */ + "Temporary failure in name resolution", /* EAI_AGAIN */ + "Invalid value for ai_flags", /* EAI_BADFLAGS */ + "Non-recoverable failure in name resolution", /* EAI_FAIL */ + "ai_family not supported", /* EAI_FAMILY */ + "Memory allocation failure", /* EAI_MEMORY */ + "No address associated with hostname", /* EAI_NODATA */ + "hostname nor servname provided, or not known", /* EAI_NONAME */ + "servname not supported for ai_socktype", /* EAI_SERVICE */ + "ai_socktype not supported", /* EAI_SOCKTYPE */ + "System error returned in errno", /* EAI_SYSTEM */ + "Invalid value for hints", /* EAI_BADHINTS */ + "Resolved protocol is unknown", /* EAI_PROTOCOL */ + "Argument buffer overflow", /* EAI_OVERFLOW */ + "Unknown error", /* EAI_MAX */ +}; + +/* XXX macros that make external reference is BAD. */ + +#define GET_AI(ai, afd, addr) \ +do { \ + /* external reference: pai, error, and label free */ \ + (ai) = get_ai(pai, (afd), (addr)); \ + if ((ai) == NULL) { \ + error = EAI_MEMORY; \ + goto free; \ + } \ +} while (/*CONSTCOND*/0) + +#define GET_PORT(ai, serv) \ +do { \ + /* external reference: error and label free */ \ + error = get_port((ai), (serv), 0); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define GET_CANONNAME(ai, str) \ +do { \ + /* external reference: pai, error and label free */ \ + error = get_canonname(pai, (ai), (str)); \ + if (error != 0) \ + goto free; \ +} while (/*CONSTCOND*/0) + +#define ERR(err) \ +do { \ + /* external reference: error, and label bad */ \ + error = (err); \ + goto bad; \ + /*NOTREACHED*/ \ +} while (/*CONSTCOND*/0) + +#define MATCH_FAMILY(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || \ + (y) == PF_UNSPEC))) +#define MATCH(x, y, w) \ + ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY))) + +const char * +gai_strerror(int ecode) +{ + if (ecode < 0 || ecode > EAI_MAX) + ecode = EAI_MAX; + return ai_errlist[ecode]; +} + +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *next; + + assert(ai != NULL); + + do { + next = ai->ai_next; + if (ai->ai_canonname) + free(ai->ai_canonname); + /* no need to free(ai->ai_addr) */ + free(ai); + ai = next; + } while (ai); +} + +static int +str2number(const char *p) +{ + char *ep; + unsigned long v; + + assert(p != NULL); + + if (*p == '\0') + return -1; + ep = NULL; + errno = 0; + v = strtoul(p, &ep, 10); + if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) + return v; + else + return -1; +} + +int +getaddrinfo(const char *hostname, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) +{ + struct addrinfo sentinel; + struct addrinfo *cur; + int error = 0; + struct addrinfo ai; + struct addrinfo ai0; + struct addrinfo *pai; + const struct explore *ex; + + /* hostname is allowed to be NULL */ + /* servname is allowed to be NULL */ + /* hints is allowed to be NULL */ + assert(res != NULL); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + pai = &ai; + pai->ai_flags = 0; + pai->ai_family = PF_UNSPEC; + pai->ai_socktype = ANY; + pai->ai_protocol = ANY; + pai->ai_addrlen = 0; + pai->ai_canonname = NULL; + pai->ai_addr = NULL; + pai->ai_next = NULL; + + if (hostname == NULL && servname == NULL) + return EAI_NONAME; + if (hints) { + /* error check for hints */ + if (hints->ai_addrlen || hints->ai_canonname || + hints->ai_addr || hints->ai_next) + ERR(EAI_BADHINTS); /* xxx */ + if (hints->ai_flags & ~AI_MASK) + ERR(EAI_BADFLAGS); + switch (hints->ai_family) { + case PF_UNSPEC: + case PF_INET: +#ifdef INET6 + case PF_INET6: +#endif + break; + default: + ERR(EAI_FAMILY); + } + memcpy(pai, hints, sizeof(*pai)); + + /* + * if both socktype/protocol are specified, check if they + * are meaningful combination. + */ + if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) { + for (ex = explore; ex->e_af >= 0; ex++) { + if (pai->ai_family != ex->e_af) + continue; + if (ex->e_socktype == ANY) + continue; + if (ex->e_protocol == ANY) + continue; + if (pai->ai_socktype == ex->e_socktype + && pai->ai_protocol != ex->e_protocol) { + ERR(EAI_BADHINTS); + } + } + } + } + + /* + * check for special cases. (1) numeric servname is disallowed if + * socktype/protocol are left unspecified. (2) servname is disallowed + * for raw and other inet{,6} sockets. + */ + if (MATCH_FAMILY(pai->ai_family, PF_INET, 1) +#ifdef PF_INET6 + || MATCH_FAMILY(pai->ai_family, PF_INET6, 1) +#endif + ) { + ai0 = *pai; /* backup *pai */ + + if (pai->ai_family == PF_UNSPEC) { +#ifdef PF_INET6 + pai->ai_family = PF_INET6; +#else + pai->ai_family = PF_INET; +#endif + } + error = get_portmatch(pai, servname); + if (error) + ERR(error); + + *pai = ai0; + } + + ai0 = *pai; + + /* NULL hostname, or numeric hostname */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + /* PF_UNSPEC entries are prepared for DNS queries only */ + if (ex->e_af == PF_UNSPEC) + continue; + + if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex))) + continue; + if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex))) + continue; + if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex))) + continue; + + if (pai->ai_family == PF_UNSPEC) + pai->ai_family = ex->e_af; + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + if (hostname == NULL) + error = explore_null(pai, servname, &cur->ai_next); + else + error = explore_numeric_scope(pai, hostname, servname, + &cur->ai_next); + + if (error) + goto free; + + while (cur->ai_next) + cur = cur->ai_next; + } + + /* + * XXX + * If numeric representation of AF1 can be interpreted as FQDN + * representation of AF2, we need to think again about the code below. + */ + if (sentinel.ai_next) + goto good; + + if (hostname == NULL) + ERR(EAI_NODATA); + if (pai->ai_flags & AI_NUMERICHOST) + ERR(EAI_NONAME); + + /* + * hostname as alphabetical name. + * we would like to prefer AF_INET6 than AF_INET, so we'll make a + * outer loop by AFs. + */ + for (ex = explore; ex->e_af >= 0; ex++) { + *pai = ai0; + + /* require exact match for family field */ + if (pai->ai_family != ex->e_af) + continue; + + if (!MATCH(pai->ai_socktype, ex->e_socktype, + WILD_SOCKTYPE(ex))) { + continue; + } + if (!MATCH(pai->ai_protocol, ex->e_protocol, + WILD_PROTOCOL(ex))) { + continue; + } + + if (pai->ai_socktype == ANY && ex->e_socktype != ANY) + pai->ai_socktype = ex->e_socktype; + if (pai->ai_protocol == ANY && ex->e_protocol != ANY) + pai->ai_protocol = ex->e_protocol; + + error = explore_fqdn(pai, hostname, servname, + &cur->ai_next); + + while (cur && cur->ai_next) + cur = cur->ai_next; + } + + /* XXX */ + if (sentinel.ai_next) + error = 0; + + if (error) + goto free; + if (error == 0) { + if (sentinel.ai_next) { + good: + *res = sentinel.ai_next; + return SUCCESS; + } else + error = EAI_FAIL; + } + free: + bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + *res = NULL; + return error; +} + +/* + * FQDN hostname, DNS lookup + */ +static int +explore_fqdn(const struct addrinfo *pai, const char *hostname, + const char *servname, struct addrinfo **res) +{ + struct addrinfo *result; + struct addrinfo *cur; + int error = 0; + static const ns_dtab dtab[] = { + NS_FILES_CB(_files_getaddrinfo, NULL) + { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */ + NS_NIS_CB(_yp_getaddrinfo, NULL) + { 0, 0, 0 } + }; + + assert(pai != NULL); + /* hostname may be NULL */ + /* servname may be NULL */ + assert(res != NULL); + + result = NULL; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return 0; + + switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo", + default_dns_files, hostname, pai)) { + case NS_TRYAGAIN: + error = EAI_AGAIN; + goto free; + case NS_UNAVAIL: + error = EAI_FAIL; + goto free; + case NS_NOTFOUND: + error = EAI_NODATA; + goto free; + case NS_SUCCESS: + error = 0; + for (cur = result; cur; cur = cur->ai_next) { + GET_PORT(cur, servname); + /* canonname should be filled already */ + } + break; + } + + *res = result; + + return 0; + +free: + if (result) + freeaddrinfo(result); + return error; +} + +/* + * hostname == NULL. + * passive socket -> anyaddr (0.0.0.0 or ::) + * non-passive socket -> localhost (127.0.0.1 or ::1) + */ +static int +explore_null(const struct addrinfo *pai, const char *servname, + struct addrinfo **res) +{ + int s; + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + + assert(pai != NULL); + /* servname may be NULL */ + assert(res != NULL); + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + /* + * filter out AFs that are not supported by the kernel + * XXX errno? + */ + s = socket(pai->ai_family, SOCK_DGRAM, 0); + if (s < 0) { + if (errno != EMFILE) + return 0; + } else + close(s); + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return 0; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (pai->ai_flags & AI_PASSIVE) { + GET_AI(cur->ai_next, afd, afd->a_addrany); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "anyaddr"); + */ + GET_PORT(cur->ai_next, servname); + } else { + GET_AI(cur->ai_next, afd, afd->a_loopback); + /* xxx meaningless? + * GET_CANONNAME(cur->ai_next, "localhost"); + */ + GET_PORT(cur->ai_next, servname); + } + cur = cur->ai_next; + + *res = sentinel.ai_next; + return 0; + +free: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname + */ +static int +explore_numeric(const struct addrinfo *pai, const char *hostname, + const char *servname, struct addrinfo **res, const char *canonname) +{ + const struct afd *afd; + struct addrinfo *cur; + struct addrinfo sentinel; + int error; + char pton[PTON_MAX]; + + assert(pai != NULL); + /* hostname may be NULL */ + /* servname may be NULL */ + assert(res != NULL); + + *res = NULL; + sentinel.ai_next = NULL; + cur = &sentinel; + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return 0; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + switch (afd->a_af) { +#if 0 /*X/Open spec*/ + case AF_INET: + if (inet_aton(hostname, (struct in_addr *)pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + if ((pai->ai_flags & AI_CANONNAME)) { + /* + * Set the numeric address itself as + * the canonical name, based on a + * clarification in rfc2553bis-03. + */ + GET_CANONNAME(cur->ai_next, canonname); + } + while (cur && cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; +#endif + default: + if (inet_pton(afd->a_af, hostname, pton) == 1) { + if (pai->ai_family == afd->a_af || + pai->ai_family == PF_UNSPEC /*?*/) { + GET_AI(cur->ai_next, afd, pton); + GET_PORT(cur->ai_next, servname); + if ((pai->ai_flags & AI_CANONNAME)) { + /* + * Set the numeric address itself as + * the canonical name, based on a + * clarification in rfc2553bis-03. + */ + GET_CANONNAME(cur->ai_next, canonname); + } + while (cur->ai_next) + cur = cur->ai_next; + } else + ERR(EAI_FAMILY); /*xxx*/ + } + break; + } + + *res = sentinel.ai_next; + return 0; + +free: +bad: + if (sentinel.ai_next) + freeaddrinfo(sentinel.ai_next); + return error; +} + +/* + * numeric hostname with scope + */ +static int +explore_numeric_scope(const struct addrinfo *pai, const char *hostname, + const char *servname, struct addrinfo **res) +{ +#if !defined(SCOPE_DELIMITER) || !defined(INET6) + return explore_numeric(pai, hostname, servname, res, hostname); +#else + const struct afd *afd; + struct addrinfo *cur; + int error; + char *cp, *hostname2 = NULL, *scope, *addr; + struct sockaddr_in6 *sin6; + + assert(pai != NULL); + /* hostname may be NULL */ + /* servname may be NULL */ + assert(res != NULL); + + /* + * if the servname does not match socktype/protocol, ignore it. + */ + if (get_portmatch(pai, servname) != 0) + return 0; + + afd = find_afd(pai->ai_family); + if (afd == NULL) + return 0; + + if (!afd->a_scoped) + return explore_numeric(pai, hostname, servname, res, hostname); + + cp = strchr(hostname, SCOPE_DELIMITER); + if (cp == NULL) + return explore_numeric(pai, hostname, servname, res, hostname); + + /* + * Handle special case of <scoped_address><delimiter><scope id> + */ + hostname2 = strdup(hostname); + if (hostname2 == NULL) + return EAI_MEMORY; + /* terminate at the delimiter */ + hostname2[cp - hostname] = '\0'; + addr = hostname2; + scope = cp + 1; + + error = explore_numeric(pai, addr, servname, res, hostname); + if (error == 0) { + u_int32_t scopeid; + + for (cur = *res; cur; cur = cur->ai_next) { + if (cur->ai_family != AF_INET6) + continue; + sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr; + if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) { + free(hostname2); + return(EAI_NODATA); /* XXX: is return OK? */ + } + sin6->sin6_scope_id = scopeid; + } + } + + free(hostname2); + + return error; +#endif +} + +static int +get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str) +{ + + assert(pai != NULL); + assert(ai != NULL); + assert(str != NULL); + + if ((pai->ai_flags & AI_CANONNAME) != 0) { + ai->ai_canonname = strdup(str); + if (ai->ai_canonname == NULL) + return EAI_MEMORY; + } + return 0; +} + +static struct addrinfo * +get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) +{ + char *p; + struct addrinfo *ai; + + assert(pai != NULL); + assert(afd != NULL); + assert(addr != NULL); + + ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + + (afd->a_socklen)); + if (ai == NULL) + return NULL; + + memcpy(ai, pai, sizeof(struct addrinfo)); + ai->ai_addr = (struct sockaddr *)(void *)(ai + 1); + memset(ai->ai_addr, 0, (size_t)afd->a_socklen); + +#ifdef HAVE_SA_LEN + ai->ai_addr->sa_len = afd->a_socklen; +#endif + + ai->ai_addrlen = afd->a_socklen; +#if defined (__alpha__) || (defined(__i386__) && defined(_LP64)) || defined(__sparc64__) + ai->__ai_pad0 = 0; +#endif + ai->ai_addr->sa_family = ai->ai_family = afd->a_af; + p = (char *)(void *)(ai->ai_addr); + memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); + return ai; +} + +static int +get_portmatch(const struct addrinfo *ai, const char *servname) +{ + + assert(ai != NULL); + /* servname may be NULL */ + + return get_port(ai, servname, 1); +} + +static int +get_port(const struct addrinfo *ai, const char *servname, int matchonly) +{ + const char *proto; + struct servent *sp; + int port; + int allownumeric; + + assert(ai != NULL); + /* servname may be NULL */ + + if (servname == NULL) + return 0; + switch (ai->ai_family) { + case AF_INET: +#ifdef AF_INET6 + case AF_INET6: +#endif + break; + default: + return 0; + } + + switch (ai->ai_socktype) { + case SOCK_RAW: + return EAI_SERVICE; + case SOCK_DGRAM: + case SOCK_STREAM: + allownumeric = 1; + break; + case ANY: + allownumeric = 0; + break; + default: + return EAI_SOCKTYPE; + } + + port = str2number(servname); + if (port >= 0) { + if (!allownumeric) + return EAI_SERVICE; + if (port < 0 || port > 65535) + return EAI_SERVICE; + port = htons(port); + } else { + if (ai->ai_flags & AI_NUMERICSERV) + return EAI_NONAME; + + switch (ai->ai_socktype) { + case SOCK_DGRAM: + proto = "udp"; + break; + case SOCK_STREAM: + proto = "tcp"; + break; + default: + proto = NULL; + break; + } + + if ((sp = getservbyname(servname, proto)) == NULL) + return EAI_SERVICE; + port = sp->s_port; + } + + if (!matchonly) { + switch (ai->ai_family) { + case AF_INET: + ((struct sockaddr_in *)(void *) + ai->ai_addr)->sin_port = port; + break; +#ifdef INET6 + case AF_INET6: + ((struct sockaddr_in6 *)(void *) + ai->ai_addr)->sin6_port = port; + break; +#endif + } + } + + return 0; +} + +static const struct afd * +find_afd(int af) +{ + const struct afd *afd; + + if (af == PF_UNSPEC) + return NULL; + for (afd = afdl; afd->a_af; afd++) { + if (afd->a_af == af) + return afd; + } + return NULL; +} + +#ifdef INET6 +/* convert a string to a scope identifier. XXX: IPv6 specific */ +static int +ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid) +{ + u_long lscopeid; + struct in6_addr *a6; + char *ep; + + assert(scope != NULL); + assert(sin6 != NULL); + assert(scopeid != NULL); + + a6 = &sin6->sin6_addr; + + /* empty scopeid portion is invalid */ + if (*scope == '\0') + return -1; + + if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) { + /* + * We currently assume a one-to-one mapping between links + * and interfaces, so we simply use interface indices for + * like-local scopes. + */ + *scopeid = if_nametoindex(scope); + if (*scopeid == 0) + goto trynumeric; + return 0; + } + + /* still unclear about literal, allow numeric only - placeholder */ + if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) + goto trynumeric; + if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) + goto trynumeric; + else + goto trynumeric; /* global */ + + /* try to convert to a numeric id as a last resort */ + trynumeric: + errno = 0; + lscopeid = strtoul(scope, &ep, 10); + *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL); + if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid) + return 0; + else + return -1; +} +#endif + +/* code duplicate with gethnamaddr.c */ + +static const char AskedForGot[] = + "gethostby*.getanswer: asked for \"%s\", got \"%s\""; + +static struct addrinfo * +getanswer(const querybuf *answer, int anslen, const char *qname, int qtype, + const struct addrinfo *pai) +{ + struct addrinfo sentinel, *cur; + struct addrinfo ai; + const struct afd *afd; + char *canonname; + const HEADER *hp; + const u_char *cp; + int n; + const u_char *eom; + char *bp, *ep; + int type, class, ancount, qdcount; + int haveanswer, had_error; + char tbuf[MAXDNAME]; + int (*name_ok) (const char *); + char hostbuf[8*1024]; + + assert(answer != NULL); + assert(qname != NULL); + assert(pai != NULL); + + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + canonname = NULL; + eom = answer->buf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: + case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/ + name_ok = res_hnok; + break; + default: + return NULL; /* XXX should be abort(); */ + } + /* + * find first satisfactory answer + */ + hp = &answer->hdr; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = hostbuf; + ep = hostbuf + sizeof hostbuf; + cp = answer->buf + HFIXEDSZ; + if (qdcount != 1) { + h_errno = NO_RECOVERY; + return (NULL); + } + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); + if ((n < 0) || !(*name_ok)(bp)) { + h_errno = NO_RECOVERY; + return (NULL); + } + cp += n + QFIXEDSZ; + if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) { + h_errno = NO_RECOVERY; + return (NULL); + } + canonname = bp; + bp += n; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = canonname; + } + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(answer->buf, eom, cp, bp, ep - bp); + if ((n < 0) || !(*name_ok)(bp)) { + had_error++; + continue; + } + cp += n; /* name */ + type = _getshort(cp); + cp += INT16SZ; /* type */ + class = _getshort(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = _getshort(cp); + cp += INT16SZ; /* len */ + if (class != C_IN) { + /* XXX - debug? syslog? */ + cp += n; + continue; /* XXX - had_error++ ? */ + } + if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) && + type == T_CNAME) { + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if ((n < 0) || !(*name_ok)(tbuf)) { + had_error++; + continue; + } + cp += n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > ep - bp || n >= MAXHOSTNAMELEN) { + had_error++; + continue; + } + strlcpy(bp, tbuf, (size_t)(ep - bp)); + canonname = bp; + bp += n; + continue; + } + if (qtype == T_ANY) { + if (!(type == T_A || type == T_AAAA)) { + cp += n; + continue; + } + } else if (type != qtype) { + if (type != T_KEY && type != T_SIG) + syslog(LOG_NOTICE|LOG_AUTH, + "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", + qname, p_class(C_IN), p_type(qtype), + p_type(type)); + cp += n; + continue; /* XXX - had_error++ ? */ + } + switch (type) { + case T_A: + case T_AAAA: + if (strcasecmp(canonname, bp) != 0) { + syslog(LOG_NOTICE|LOG_AUTH, + AskedForGot, canonname, bp); + cp += n; + continue; /* XXX - had_error++ ? */ + } + if (type == T_A && n != INADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA && n != IN6ADDRSZ) { + cp += n; + continue; + } + if (type == T_AAAA) { + struct in6_addr in6; + memcpy(&in6, cp, IN6ADDRSZ); + if (IN6_IS_ADDR_V4MAPPED(&in6)) { + cp += n; + continue; + } + } + if (!haveanswer) { + int nn; + + canonname = bp; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + } + + /* don't overwrite pai */ + ai = *pai; + ai.ai_family = (type == T_A) ? AF_INET : AF_INET6; + afd = find_afd(ai.ai_family); + if (afd == NULL) { + cp += n; + continue; + } + cur->ai_next = get_ai(&ai, afd, (const char *)cp); + if (cur->ai_next == NULL) + had_error++; + while (cur && cur->ai_next) + cur = cur->ai_next; + cp += n; + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + if (!canonname) + (void)get_canonname(pai, sentinel.ai_next, qname); + else + (void)get_canonname(pai, sentinel.ai_next, canonname); + h_errno = NETDB_SUCCESS; + return sentinel.ai_next; + } + + h_errno = NO_RECOVERY; + return NULL; +} + +#define SORTEDADDR(p) (((struct sockaddr_in *)(void *)(p->ai_next->ai_addr))->sin_addr.s_addr) +#define SORTMATCH(p, s) ((SORTEDADDR(p) & (s).mask) == (s).addr.s_addr) + +static void +aisort(struct addrinfo *s, res_state res) +{ + struct addrinfo head, *t, *p; + int i; + + head.ai_next = NULL; + t = &head; + + for (i = 0; i < res->nsort; i++) { + p = s; + while (p->ai_next) { + if ((p->ai_next->ai_family != AF_INET) + || SORTMATCH(p, res->sort_list[i])) { + t->ai_next = p->ai_next; + t = t->ai_next; + p->ai_next = p->ai_next->ai_next; + } else { + p = p->ai_next; + } + } + } + + /* add rest of list and reset s to the new list*/ + t->ai_next = s->ai_next; + s->ai_next = head.ai_next; +} + +/*ARGSUSED*/ +static int +_dns_getaddrinfo(void *rv, void *cb_data, va_list ap) +{ + struct addrinfo *ai; + querybuf *buf, *buf2; + const char *name; + const struct addrinfo *pai; + struct addrinfo sentinel, *cur; + struct res_target q, q2; + res_state res; + + name = va_arg(ap, char *); + pai = va_arg(ap, const struct addrinfo *); + + fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name); + + memset(&q, 0, sizeof(q)); + memset(&q2, 0, sizeof(q2)); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + buf = malloc(sizeof(*buf)); + if (buf == NULL) { + h_errno = NETDB_INTERNAL; + return NS_NOTFOUND; + } + buf2 = malloc(sizeof(*buf2)); + if (buf2 == NULL) { + free(buf); + h_errno = NETDB_INTERNAL; + return NS_NOTFOUND; + } + + switch (pai->ai_family) { + case AF_UNSPEC: + /* prefer IPv6 */ + q.name = name; + q.qclass = C_IN; + q.qtype = T_AAAA; + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); + q.next = &q2; + q2.name = name; + q2.qclass = C_IN; + q2.qtype = T_A; + q2.answer = buf2->buf; + q2.anslen = sizeof(buf2->buf); + break; + case AF_INET: + q.name = name; + q.qclass = C_IN; + q.qtype = T_A; + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); + break; + case AF_INET6: + q.name = name; + q.qclass = C_IN; + q.qtype = T_AAAA; + q.answer = buf->buf; + q.anslen = sizeof(buf->buf); + break; + default: + free(buf); + free(buf2); + return NS_UNAVAIL; + } + + res = __res_get_state(); + if (res == NULL) { + free(buf); + free(buf2); + return NS_NOTFOUND; + } + + if (res_searchN(name, &q, res) < 0) { + __res_put_state(res); + free(buf); + free(buf2); + return NS_NOTFOUND; + } + ai = getanswer(buf, q.n, q.name, q.qtype, pai); + if (ai) { + cur->ai_next = ai; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + if (q.next) { + ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai); + if (ai) + cur->ai_next = ai; + } + free(buf); + free(buf2); + if (sentinel.ai_next == NULL) { + __res_put_state(res); + switch (h_errno) { + case HOST_NOT_FOUND: + return NS_NOTFOUND; + case TRY_AGAIN: + return NS_TRYAGAIN; + default: + return NS_UNAVAIL; + } + } + + if (res->nsort) + aisort(&sentinel, res); + + __res_put_state(res); + + *((struct addrinfo **)rv) = sentinel.ai_next; + return NS_SUCCESS; +} + +static void +_sethtent(FILE **hostf) +{ + + if (!*hostf) + *hostf = fopen(_PATH_HOSTS, "r" ); + else + rewind(*hostf); +} + +static void +_endhtent(FILE **hostf) +{ + + if (*hostf) { + (void) fclose(*hostf); + *hostf = NULL; + } +} + +static struct addrinfo * +_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai) +{ + char *p; + char *cp, *tname, *cname; + struct addrinfo hints, *res0, *res; + int error; + const char *addr; + char hostbuf[8*1024]; + +// fprintf(stderr, "_gethtent() name = '%s'\n", name); + assert(name != NULL); + assert(pai != NULL); + + if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r" ))) + return (NULL); + again: + if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf))) + return (NULL); + if (*p == '#') + goto again; + if (!(cp = strpbrk(p, "#\n"))) + goto again; + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + addr = p; + /* if this is not something we're looking for, skip it. */ + cname = NULL; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (!cname) + cname = cp; + tname = cp; + if ((cp = strpbrk(cp, " \t")) != NULL) + *cp++ = '\0'; +// fprintf(stderr, "\ttname = '%s'", tname); + if (strcasecmp(name, tname) == 0) + goto found; + } + goto again; + +found: + hints = *pai; + hints.ai_flags = AI_NUMERICHOST; + error = getaddrinfo(addr, NULL, &hints, &res0); + if (error) + goto again; + for (res = res0; res; res = res->ai_next) { + /* cover it up */ + res->ai_flags = pai->ai_flags; + + if (pai->ai_flags & AI_CANONNAME) { + if (get_canonname(pai, res, cname) != 0) { + freeaddrinfo(res0); + goto again; + } + } + } + return res0; +} + +/*ARGSUSED*/ +static int +_files_getaddrinfo(void *rv, void *cb_data, va_list ap) +{ + const char *name; + const struct addrinfo *pai; + struct addrinfo sentinel, *cur; + struct addrinfo *p; + FILE *hostf = NULL; + + name = va_arg(ap, char *); + pai = va_arg(ap, struct addrinfo *); + +// fprintf(stderr, "_files_getaddrinfo() name = '%s'\n", name); + memset(&sentinel, 0, sizeof(sentinel)); + cur = &sentinel; + + _sethtent(&hostf); + while ((p = _gethtent(&hostf, name, pai)) != NULL) { + cur->ai_next = p; + while (cur && cur->ai_next) + cur = cur->ai_next; + } + _endhtent(&hostf); + + *((struct addrinfo **)rv) = sentinel.ai_next; + if (sentinel.ai_next == NULL) + return NS_NOTFOUND; + return NS_SUCCESS; +} + +/* resolver logic */ + +/* + * 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. + */ +static int +res_queryN(const char *name, /* domain name */ struct res_target *target, + res_state res) +{ + u_char buf[MAXPACKET]; + HEADER *hp; + int n; + struct res_target *t; + int rcode; + int ancount; + + assert(name != NULL); + /* XXX: target may be NULL??? */ + + rcode = NOERROR; + ancount = 0; + + for (t = target; t; t = t->next) { + int class, type; + u_char *answer; + int anslen; + + hp = (HEADER *)(void *)t->answer; + hp->rcode = NOERROR; /* default */ + + /* make it easier... */ + class = t->qclass; + type = t->qtype; + answer = t->answer; + anslen = t->anslen; +#ifdef DEBUG + if (res->options & RES_DEBUG) + printf(";; res_nquery(%s, %d, %d)\n", name, class, type); +#endif + + n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL, + buf, sizeof(buf)); +#ifdef RES_USE_EDNS0 + if (n > 0 && (res->options & RES_USE_EDNS0) != 0) + n = res_nopt(res, n, buf, sizeof(buf), anslen); +#endif + if (n <= 0) { +#ifdef DEBUG + if (res->options & RES_DEBUG) + printf(";; res_nquery: mkquery failed\n"); +#endif + h_errno = NO_RECOVERY; + return n; + } + n = res_nsend(res, buf, n, answer, anslen); +#if 0 + if (n < 0) { +#ifdef DEBUG + if (res->options & RES_DEBUG) + printf(";; res_query: send error\n"); +#endif + h_errno = TRY_AGAIN; + return n; + } +#endif + + if (n < 0 || hp->rcode != NOERROR || ntohs(hp->ancount) == 0) { + rcode = hp->rcode; /* record most recent error */ +#ifdef DEBUG + if (res->options & RES_DEBUG) + printf(";; rcode = %u, ancount=%u\n", hp->rcode, + ntohs(hp->ancount)); +#endif + continue; + } + + ancount += ntohs(hp->ancount); + + t->n = n; + } + + if (ancount == 0) { + switch (rcode) { + case NXDOMAIN: + h_errno = HOST_NOT_FOUND; + break; + case SERVFAIL: + h_errno = TRY_AGAIN; + break; + case NOERROR: + h_errno = NO_DATA; + break; + case FORMERR: + case NOTIMP: + case REFUSED: + default: + h_errno = NO_RECOVERY; + break; + } + return -1; + } + return ancount; +} + +/* + * 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. + */ +static int +res_searchN(const char *name, struct res_target *target, res_state res) +{ + const char *cp, * const *domain; + HEADER *hp; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, tried_as_is = 0; + + assert(name != NULL); + assert(target != NULL); + + hp = (HEADER *)(void *)target->answer; /*XXX*/ + + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + trailing_dot++; + + +fprintf(stderr, "res_searchN() name = '%s'\n", name); + + /* + * if there aren't any dots, it could be a user-level alias + */ + if (!dots && (cp = __hostalias(name)) != NULL) { + ret = res_queryN(cp, target, res); + return ret; + } + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + if (dots >= res->ndots) { + ret = res_querydomainN(name, NULL, target, res); + if (ret > 0) + return (ret); + saved_herrno = 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 && (res->options & RES_DEFNAMES)) || + (dots && !trailing_dot && (res->options & RES_DNSRCH))) { + int done = 0; + + for (domain = (const char * const *)res->dnsrch; + *domain && !done; + domain++) { + + ret = res_querydomainN(name, *domain, target, res); + 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) { + h_errno = TRY_AGAIN; + return -1; + } + + switch (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 (!(res->options & RES_DNSRCH)) + done++; + } + } + + /* + * if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!tried_as_is) { + ret = res_querydomainN(name, NULL, target, res); + 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) + h_errno = saved_herrno; + else if (got_nodata) + h_errno = NO_DATA; + else if (got_servfail) + h_errno = 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. + */ +static int +res_querydomainN(const char *name, const char *domain, + struct res_target *target, res_state res) +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + size_t n, d; + + assert(name != NULL); + /* XXX: target may be NULL??? */ + +#ifdef DEBUG + if (res->options & RES_DEBUG) + printf(";; res_querydomain(%s, %s)\n", + name, domain?domain:"<Nil>"); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + if (n > 0 && name[--n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + 1 + d + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); + } + return res_queryN(longname, target, res); +} diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c new file mode 100644 index 0000000..db04fbf --- /dev/null +++ b/libc/netbsd/net/getnameinfo.c @@ -0,0 +1,519 @@ +/* $NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $ */ +/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */ + +/* + * Copyright (c) 2000 Ben Harris. + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE 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: + * 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. Neither the name of the project 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 PROJECT 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 PROJECT 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. + */ + +/* + * Issues to be discussed: + * - Thread safe-ness must be checked + * - RFC2553 says that we should raise error on short buffer. X/Open says + * we need to truncate the result. We obey RFC2553 (and X/Open should be + * modified). ipngwg rough consensus seems to follow RFC2553. + * - What is "local" in NI_FQDN? + * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other. + * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if + * sin6_scope_id is filled - standardization status? + * XXX breaks backward compat for code that expects no scopeid. + * beware on merge. + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/if_ieee1394.h> +#include <net/if_types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include "arpa_nameser.h" +#include <assert.h> +#include <limits.h> +#include <netdb.h> +#ifdef ANDROID_CHANGES +#include "resolv_private.h" +#else +#include <resolv.h> +#endif +#include <stddef.h> +#include <string.h> + +static const struct afd { + int a_af; + socklen_t a_addrlen; + socklen_t a_socklen; + int a_off; +} afdl [] = { +#ifdef INET6 + {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), + offsetof(struct sockaddr_in6, sin6_addr)}, +#endif + {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), + offsetof(struct sockaddr_in, sin_addr)}, + {0, 0, 0, 0}, +}; + +struct sockinet { + u_char si_len; + u_char si_family; + u_short si_port; +}; + +static int getnameinfo_inet __P((const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, int)); +#ifdef INET6 +static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *, + socklen_t, int)); +static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t, + int)); +#endif +static int getnameinfo_link __P((const struct sockaddr *, socklen_t, char *, + socklen_t, char *, socklen_t, int)); +static int hexname __P((const u_int8_t *, size_t, char *, socklen_t)); + +/* + * Top-level getnameinfo() code. Look at the address family, and pick an + * appropriate function to call. + */ +int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags) +{ + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: + return getnameinfo_inet(sa, salen, host, hostlen, + serv, servlen, flags); +#if 0 + case AF_LINK: + return getnameinfo_link(sa, salen, host, hostlen, + serv, servlen, flags); +#endif + default: + return EAI_FAMILY; + } +} + + +/* + * getnameinfo_inet(): + * Format an IPv4 or IPv6 sockaddr into a printable string. + */ +static int +getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags) + const struct sockaddr *sa; + socklen_t salen; + char *host; + socklen_t hostlen; + char *serv; + socklen_t servlen; + int flags; +{ + const struct afd *afd; + struct servent *sp; + struct hostent *hp; + u_short port; + int family, i; + const char *addr; + u_int32_t v4a; + char numserv[512]; + char numaddr[512]; + + /* sa is checked below */ + /* host may be NULL */ + /* serv may be NULL */ + + if (sa == NULL) + return EAI_FAIL; + +#ifdef BSD4_4 + if (sa->sa_len != salen) + return EAI_FAIL; +#endif + + family = sa->sa_family; + for (i = 0; afdl[i].a_af; i++) + if (afdl[i].a_af == family) { + afd = &afdl[i]; + goto found; + } + return EAI_FAMILY; + + found: + if (salen != afd->a_socklen) + return EAI_FAIL; + + /* network byte order */ + port = ((const struct sockinet *)(const void *)sa)->si_port; + addr = (const char *)(const void *)sa + afd->a_off; + + if (serv == NULL || servlen == 0) { + /* + * do nothing in this case. + * in case you are wondering if "&&" is more correct than + * "||" here: rfc2553bis-03 says that serv == NULL OR + * servlen == 0 means that the caller does not want the result. + */ + } else { + if (flags & NI_NUMERICSERV) + sp = NULL; + else { + sp = getservbyport(port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + } + if (sp) { + if (strlen(sp->s_name) + 1 > (size_t)servlen) + return EAI_MEMORY; + strlcpy(serv, sp->s_name, servlen); + } else { + snprintf(numserv, sizeof(numserv), "%u", ntohs(port)); + if (strlen(numserv) + 1 > (size_t)servlen) + return EAI_MEMORY; + strlcpy(serv, numserv, servlen); + } + } + + switch (sa->sa_family) { + case AF_INET: + v4a = (u_int32_t) + ntohl(((const struct sockaddr_in *) + (const void *)sa)->sin_addr.s_addr); + if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) + flags |= NI_NUMERICHOST; + v4a >>= IN_CLASSA_NSHIFT; + if (v4a == 0) + flags |= NI_NUMERICHOST; + break; +#ifdef INET6 + case AF_INET6: + { + const struct sockaddr_in6 *sin6; + sin6 = (const struct sockaddr_in6 *)(const void *)sa; + switch (sin6->sin6_addr.s6_addr[0]) { + case 0x00: + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + ; + else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr)) + ; + else + flags |= NI_NUMERICHOST; + break; + default: + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + flags |= NI_NUMERICHOST; + } + else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) + flags |= NI_NUMERICHOST; + break; + } + } + break; +#endif + } + if (host == NULL || hostlen == 0) { + /* + * do nothing in this case. + * in case you are wondering if "&&" is more correct than + * "||" here: rfc2553bis-03 says that host == NULL or + * hostlen == 0 means that the caller does not want the result. + */ + } else if (flags & NI_NUMERICHOST) { + size_t numaddrlen; + + /* NUMERICHOST and NAMEREQD conflicts with each other */ + if (flags & NI_NAMEREQD) + return EAI_NONAME; + + switch(afd->a_af) { +#ifdef INET6 + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, flags)) != 0) + return(error); + break; + } +#endif + default: + if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) + == NULL) + return EAI_SYSTEM; + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > (size_t)hostlen) /* don't forget terminator */ + return EAI_MEMORY; + strlcpy(host, numaddr, hostlen); + break; + } + } else { + hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); + + if (hp) { +#if 0 + /* + * commented out, since "for local host" is not + * implemented here - see RFC2553 p30 + */ + if (flags & NI_NOFQDN) { + char *p; + p = strchr(hp->h_name, '.'); + if (p) + *p = '\0'; + } +#endif + if (strlen(hp->h_name) + 1 > (size_t)hostlen) { + return EAI_MEMORY; + } + strlcpy(host, hp->h_name, hostlen); + } else { + if (flags & NI_NAMEREQD) + return EAI_NONAME; + switch(afd->a_af) { +#ifdef INET6 + case AF_INET6: + { + int error; + + if ((error = ip6_parsenumeric(sa, addr, host, + hostlen, + flags)) != 0) + return(error); + break; + } +#endif + default: + if (inet_ntop(afd->a_af, addr, host, + hostlen) == NULL) + return EAI_SYSTEM; + break; + } + } + } + return(0); +} + +#ifdef INET6 +static int +ip6_parsenumeric(sa, addr, host, hostlen, flags) + const struct sockaddr *sa; + const char *addr; + char *host; + socklen_t hostlen; + int flags; +{ + size_t numaddrlen; + char numaddr[512]; + + assert(sa != NULL); + assert(addr != NULL); + assert(host != NULL); + + if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL) + return EAI_SYSTEM; + + numaddrlen = strlen(numaddr); + if (numaddrlen + 1 > hostlen) /* don't forget terminator */ + return EAI_OVERFLOW; + strlcpy(host, numaddr, hostlen); + + if (((const struct sockaddr_in6 *)(const void *)sa)->sin6_scope_id) { + char zonebuf[MAXHOSTNAMELEN]; + int zonelen; + + zonelen = ip6_sa2str( + (const struct sockaddr_in6 *)(const void *)sa, + zonebuf, sizeof(zonebuf), flags); + if (zonelen < 0) + return EAI_OVERFLOW; + if ((size_t) zonelen + 1 + numaddrlen + 1 > hostlen) + return EAI_OVERFLOW; + /* construct <numeric-addr><delim><zoneid> */ + memcpy(host + numaddrlen + 1, zonebuf, + (size_t)zonelen); + host[numaddrlen] = SCOPE_DELIMITER; + host[numaddrlen + 1 + zonelen] = '\0'; + } + + return 0; +} + +/* ARGSUSED */ +static int +ip6_sa2str(sa6, buf, bufsiz, flags) + const struct sockaddr_in6 *sa6; + char *buf; + size_t bufsiz; + int flags; +{ + unsigned int ifindex; + const struct in6_addr *a6; + int n; + + assert(sa6 != NULL); + assert(buf != NULL); + + ifindex = (unsigned int)sa6->sin6_scope_id; + a6 = &sa6->sin6_addr; + +#ifdef NI_NUMERICSCOPE + if ((flags & NI_NUMERICSCOPE) != 0) { + n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); + if (n < 0 || n >= bufsiz) + return -1; + else + return n; + } +#endif + + /* if_indextoname() does not take buffer size. not a good api... */ + if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && + bufsiz >= IF_NAMESIZE) { + char *p = if_indextoname(ifindex, buf); + if (p) { + return(strlen(p)); + } + } + + /* last resort */ + n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); + if (n < 0 || (size_t) n >= bufsiz) + return -1; + else + return n; +} +#endif /* INET6 */ + + +/* + * getnameinfo_link(): + * Format a link-layer address into a printable format, paying attention to + * the interface type. + */ +/* ARGSUSED */ +static int +getnameinfo_link(const struct sockaddr *sa, socklen_t salen, + char *host, socklen_t hostlen, char *serv, socklen_t servlen, + int flags) +{ + const struct sockaddr_dl *sdl = + (const struct sockaddr_dl *)(const void *)sa; + const struct ieee1394_hwaddr *iha; + int n; + + if (serv != NULL && servlen > 0) + *serv = '\0'; + + if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { + n = snprintf(host, hostlen, "link#%u", sdl->sdl_index); + if (n < 0 || (socklen_t) n > hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + return 0; + } + + switch (sdl->sdl_type) { +#ifdef IFT_ECONET + case IFT_ECONET: + if (sdl->sdl_alen < 2) + return EAI_FAMILY; + if (CLLADDR(sdl)[1] == 0) + n = snprintf(host, hostlen, "%u", CLLADDR(sdl)[0]); + else + n = snprintf(host, hostlen, "%u.%u", + CLLADDR(sdl)[1], CLLADDR(sdl)[0]); + if (n < 0 || (socklen_t) n >= hostlen) { + *host = '\0'; + return EAI_MEMORY; + } else + return 0; +#endif + case IFT_IEEE1394: + if (sdl->sdl_alen < sizeof(iha->iha_uid)) + return EAI_FAMILY; + iha = + (const struct ieee1394_hwaddr *)(const void *)CLLADDR(sdl); + return hexname(iha->iha_uid, sizeof(iha->iha_uid), + host, hostlen); + /* + * The following have zero-length addresses. + * IFT_ATM (net/if_atmsubr.c) + * IFT_FAITH (net/if_faith.c) + * IFT_GIF (net/if_gif.c) + * IFT_LOOP (net/if_loop.c) + * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c) + * IFT_SLIP (net/if_sl.c, net/if_strip.c) + * IFT_STF (net/if_stf.c) + * IFT_L2VLAN (net/if_vlan.c) + * IFT_PROPVIRTUAL (net/if_bridge.h> + */ + /* + * The following use IPv4 addresses as link-layer addresses: + * IFT_OTHER (net/if_gre.c) + */ + case IFT_ARCNET: /* default below is believed correct for all these. */ + case IFT_ETHER: + case IFT_FDDI: + case IFT_HIPPI: + case IFT_ISO88025: + default: + return hexname((const u_int8_t *)CLLADDR(sdl), + (size_t)sdl->sdl_alen, host, hostlen); + } +} + +static int +hexname(cp, len, host, hostlen) + const u_int8_t *cp; + char *host; + size_t len; + socklen_t hostlen; +{ + int n; + size_t i; + char *outp = host; + + *outp = '\0'; + for (i = 0; i < len; i++) { + n = snprintf(outp, hostlen, "%s%02x", + i ? ":" : "", cp[i]); + if (n < 0 || (socklen_t) n >= hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + outp += n; + hostlen -= n; + } + return 0; +} diff --git a/libc/netbsd/net/getservbyname.c b/libc/netbsd/net/getservbyname.c new file mode 100644 index 0000000..5ea528e --- /dev/null +++ b/libc/netbsd/net/getservbyname.c @@ -0,0 +1,54 @@ +/* + * 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 <netdb.h> +#include "servent.h" + +struct servent * +getservbyname(const char *name, const char *proto) +{ + res_static rs = __res_get_static(); + struct servent* s; + + if (rs == NULL || proto == NULL || name == NULL) { + errno = EINVAL; + return NULL; + } + + rs->servent_ptr = NULL; + while (1) { + struct servent* s = getservent_r(rs); + if (s == NULL) + break; + if ( !strcmp( s->s_name, name ) && !strcmp( s->s_proto, proto ) ) + return s; + } + + return NULL; +} diff --git a/libc/netbsd/net/getservbyname_r.c b/libc/netbsd/net/getservbyname_r.c new file mode 100644 index 0000000..fb6dc52 --- /dev/null +++ b/libc/netbsd/net/getservbyname_r.c @@ -0,0 +1,76 @@ +/* $NetBSD: getservbyname_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $ */ + +/* + * Copyright (c) 1983, 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. 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. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)getservbyname.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: getservbyname_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include <assert.h> +#include <netdb.h> +#include <string.h> + +#include "servent.h" + +struct servent * +getservbyname_r(const char *name, const char *proto, struct servent *sp, + struct servent_data *sd) +{ + struct servent *s; + char **cp; + + assert(name != NULL); + /* proto may be NULL */ + + setservent_r(sd->stayopen, sd); + while ((s = getservent_r(sp, sd)) != NULL) { + if (strcmp(name, s->s_name) == 0) + goto gotname; + for (cp = s->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; +gotname: + if (proto == NULL || strcmp(s->s_proto, proto) == 0) + break; + } + if (!sd->stayopen) + if (sd->fp != NULL) { + (void)fclose(sd->fp); + sd->fp = NULL; + } + return s; +} diff --git a/libc/netbsd/net/getservbyport.c b/libc/netbsd/net/getservbyport.c new file mode 100644 index 0000000..fad7e23 --- /dev/null +++ b/libc/netbsd/net/getservbyport.c @@ -0,0 +1,53 @@ +/* + * 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 <netdb.h> +#include "servent.h" + +struct servent * +getservbyport(int port, const char *proto) +{ + res_static rs = __res_get_static(); + struct servent* s; + + if (rs == NULL || proto == NULL) { + errno = EINVAL; + return NULL; + } + + rs->servent_ptr = NULL; + while (1) { + struct servent* s = getservent_r(rs); + if (s == NULL) + break; + if ( s->s_port == port && !strcmp( s->s_proto, proto ) ) + return s; + } + + return NULL; +} diff --git a/libc/netbsd/net/getservbyport_r.c b/libc/netbsd/net/getservbyport_r.c new file mode 100644 index 0000000..6fe4293 --- /dev/null +++ b/libc/netbsd/net/getservbyport_r.c @@ -0,0 +1,65 @@ +/* $NetBSD: getservbyport_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $ */ + +/* + * Copyright (c) 1983, 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. 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. + */ + +#include <sys/cdefs.h> +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)getservbyport.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: getservbyport_r.c,v 1.3 2005/04/18 19:39:45 kleink Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include <netdb.h> +#include <string.h> + +#include "servent.h" + +struct servent * +getservbyport_r(int port, const char *proto, struct servent *sp, + struct servent_data *sd) +{ + struct servent *s; + + setservent_r(sd->stayopen, sd); + while ((s = getservent_r(sp, sd)) != NULL) { + if (s->s_port != port) + continue; + if (proto == NULL || strcmp(s->s_proto, proto) == 0) + break; + } + if (!sd->stayopen) + if (sd->fp != NULL) { + (void)fclose(sd->fp); + sd->fp = NULL; + } + return s; +} diff --git a/libc/netbsd/net/getservent.c b/libc/netbsd/net/getservent.c new file mode 100644 index 0000000..45207df --- /dev/null +++ b/libc/netbsd/net/getservent.c @@ -0,0 +1,124 @@ +/* + * 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 <netdb.h> +#include "servent.h" +#include "services.h" + +void +setservent(int f) +{ + res_static rs = __res_get_static(); + if (rs) { + rs->servent_ptr = NULL; + } +} + +void +endservent(void) +{ + /* nothing to do */ +} + +struct servent * +getservent_r( res_static rs ) +{ + const char* p; + const char* q; + int namelen; + int nn,count; + int total = 0; + char* p2; + + p = rs->servent_ptr; + if (p == NULL) + p = _services; + else if (p[0] == 0) + return NULL; + + /* first compute the total size */ + namelen = p[0]; + total += namelen + 1; + q = p + 1 + namelen + 3; /* skip name + port + proto */ + count = q[0]; /* get aliascount */ + q += 1; + + total += (count+1)*sizeof(char*); + for (nn = 0; nn < count; nn++) { + int len2 = q[0]; + total += 1 + len2; + q += 1 + len2; + } + + /* reallocate the thread-specific servent struct */ + p2 = realloc( (char*)rs->servent.s_aliases, total ); + if (p2 == NULL) + return NULL; + + /* now write to it */ + rs->servent.s_aliases = (char**) p2; + p2 += (count+1)*sizeof(char*); + rs->servent.s_name = p2; + p2 += namelen + 1; + rs->servent.s_proto = p2; + + /* copy name + port + setup protocol */ + memcpy( rs->servent.s_name, p+1, namelen ); + rs->servent.s_name[namelen] = 0; + p += 1 + namelen; + rs->servent.s_port = ((((unsigned char*)p)[0] << 8) | + ((unsigned char*)p)[1]); + + rs->servent.s_proto = p[2] == 't' ? "tcp" : "udp"; + p += 4; /* skip port(2) + proto(1) + aliascount(1) */ + + for (nn = 0; nn < count; nn++) { + int len2 = p[0]; + rs->servent.s_aliases[nn] = p2; + memcpy( p2, p+1, len2 ); + p2[len2] = 0; + p2 += len2 + 1; + p += len2 + 1; + } + rs->servent.s_aliases[nn] = NULL; + + rs->servent_ptr = p; + + return &rs->servent; +} + +struct servent * +getservent(void) +{ + res_static rs = __res_get_static(); + + if (rs == NULL) return NULL; + + return getservent_r(rs); +} diff --git a/libc/netbsd/net/getservent_r.c b/libc/netbsd/net/getservent_r.c new file mode 100644 index 0000000..1668759 --- /dev/null +++ b/libc/netbsd/net/getservent_r.c @@ -0,0 +1,151 @@ +/* $NetBSD: getservent_r.c,v 1.5 2005/04/18 19:39:45 kleink Exp $ */ + +/* + * Copyright (c) 1983, 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. 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. + */ + +#include <sys/cdefs.h> +#include <sys/types.h> + +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: getservent_r.c,v 1.5 2005/04/18 19:39:45 kleink Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +#include <netdb.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> + +#include "servent.h" + +void +setservent_r(int f, struct servent_data *sd) +{ + if (sd->fp == NULL) + sd->fp = fopen(_PATH_SERVICES, "r"); + else + rewind(sd->fp); + sd->stayopen |= f; +} + +void +endservent_r(struct servent_data *sd) +{ + if (sd->fp) { + (void)fclose(sd->fp); + sd->fp = NULL; + } + if (sd->aliases) { + free(sd->aliases); + sd->aliases = NULL; + sd->maxaliases = 0; + } + if (sd->line) { + free(sd->line); + sd->line = NULL; + } + sd->stayopen = 0; +} + +struct servent * +getservent_r(struct servent *sp, struct servent_data *sd) +{ + char *p, *cp, **q; + size_t i = 0; + int oerrno; + + if (sd->fp == NULL && (sd->fp = fopen(_PATH_SERVICES, "r")) == NULL) + return NULL; + + for (;;) { + if (sd->line) + free(sd->line); +// sd->line = fparseln(sd->fp, NULL, NULL, NULL, FPARSELN_UNESCALL); + fprintf(stderr, "*** FIX ME! getservent_r() is going to fail!!!\n"); + sd->line = NULL; + if (sd->line == NULL) + return NULL; + sp->s_name = p = sd->line; + p = strpbrk(p, " \t"); + if (p == NULL) + continue; + *p++ = '\0'; + while (*p == ' ' || *p == '\t') + p++; + cp = strpbrk(p, ",/"); + if (cp == NULL) + continue; + *cp++ = '\0'; + sp->s_port = htons((u_short)atoi(p)); + sp->s_proto = cp; + if (sd->aliases == NULL) { + sd->maxaliases = 10; + sd->aliases = malloc(sd->maxaliases * sizeof(char *)); + if (sd->aliases == NULL) { + oerrno = errno; + endservent_r(sd); + errno = oerrno; + return NULL; + } + } + q = sp->s_aliases = sd->aliases; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (i == sd->maxaliases - 2) { + sd->maxaliases *= 2; + q = realloc(q, + sd->maxaliases * sizeof(char *)); + if (q == NULL) { + oerrno = errno; + endservent_r(sd); + errno = oerrno; + return NULL; + } + sp->s_aliases = sd->aliases = q; + } + q[i++] = cp; + cp = strpbrk(cp, " \t"); + if (cp != NULL) + *cp++ = '\0'; + } + q[i] = NULL; + return sp; + } +} diff --git a/libc/netbsd/net/nsdispatch.c b/libc/netbsd/net/nsdispatch.c new file mode 100644 index 0000000..fa99366 --- /dev/null +++ b/libc/netbsd/net/nsdispatch.c @@ -0,0 +1,152 @@ +/* $NetBSD: nsdispatch.c,v 1.30 2005/11/29 03:11:59 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Luke Mewburn; and by Jason R. Thorpe. + * + * 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. + */ + +/*- + * Copyright (c) 2003 Networks Associates Technology, Inc. + * All rights reserved. + * + * Portions of this software were developed for the FreeBSD Project by + * Jacques A. Vidrine, Safeport Network Services, and Network + * Associates Laboratories, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * 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 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 AUTHOR 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 <sys/param.h> +#include <sys/stat.h> + +#include <assert.h> +#ifdef __ELF__ +#include <dlfcn.h> +#endif /* __ELF__ */ +#include <fcntl.h> +#define _NS_PRIVATE +#include <nsswitch.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static nss_method +_nsmethod(const char *source, const char *database, const char *method, + const ns_dtab disp_tab[], void **cb_data) +{ + int curdisp; + + if (disp_tab != NULL) { + for (curdisp = 0; disp_tab[curdisp].src != NULL; curdisp++) { + if (strcasecmp(source, disp_tab[curdisp].src) == 0) { + *cb_data = disp_tab[curdisp].cb_data; + return (disp_tab[curdisp].callback); + } + } + } + + *cb_data = NULL; + return (NULL); +} + +int +/*ARGSUSED*/ +nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database, + const char *method, const ns_src defaults[], ...) +{ + va_list ap; + int i, result; + const ns_src *srclist; + int srclistsize; + nss_method cb; + void *cb_data; + + /* retval may be NULL */ + /* disp_tab may be NULL */ + assert(database != NULL); + assert(method != NULL); + assert(defaults != NULL); + if (database == NULL || method == NULL || defaults == NULL) + return (NS_UNAVAIL); + + srclist = defaults; + srclistsize = 0; + while (srclist[srclistsize].name != NULL) + srclistsize++; + + result = 0; + + for (i = 0; i < srclistsize; i++) { + cb = _nsmethod(srclist[i].name, database, method, + disp_tab, &cb_data); + result = 0; + if (cb != NULL) { + va_start(ap, defaults); + result = (*cb)(retval, cb_data, ap); + va_end(ap); + if (defaults[0].flags & NS_FORCEALL) + continue; + if (result & srclist[i].flags) + break; + } + } + result &= NS_STATUSMASK; /* clear private flags in result */ + + return (result ? result : NS_NOTFOUND); +} diff --git a/libc/netbsd/net/reentrant.h b/libc/netbsd/net/reentrant.h new file mode 100644 index 0000000..15507eb --- /dev/null +++ b/libc/netbsd/net/reentrant.h @@ -0,0 +1,268 @@ +/* $NetBSD: reentrant.h,v 1.10 2004/12/14 00:23:19 nathanw Exp $ */ + +/*- + * Copyright (c) 1997, 1998, 2003 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin, by Nathan J. Williams, and by Jason R. Thorpe. + * + * 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. + */ + +/* + * Requirements: + * + * 1. The thread safe mechanism should be lightweight so the library can + * be used by non-threaded applications without unreasonable overhead. + * + * 2. There should be no dependency on a thread engine for non-threaded + * applications. + * + * 3. There should be no dependency on any particular thread engine. + * + * 4. The library should be able to be compiled without support for thread + * safety. + * + * + * Rationale: + * + * One approach for thread safety is to provide discrete versions of the + * library: one thread safe, the other not. The disadvantage of this is + * that libc is rather large, and two copies of a library which are 99%+ + * identical is not an efficent use of resources. + * + * Another approach is to provide a single thread safe library. However, + * it should not add significant run time or code size overhead to non- + * threaded applications. + * + * Since the NetBSD C library is used in other projects, it should be + * easy to replace the mutual exclusion primitives with ones provided by + * another system. Similarly, it should also be easy to remove all + * support for thread safety completely if the target environment does + * not support threads. + * + * + * Implementation Details: + * + * The thread primitives used by the library (mutex_t, mutex_lock, etc.) + * are macros which expand to the cooresponding primitives provided by + * the thread engine or to nothing. The latter is used so that code is + * not unreasonably cluttered with #ifdefs when all thread safe support + * is removed. + * + * The thread macros can be directly mapped to the mutex primitives from + * pthreads, however it should be reasonably easy to wrap another mutex + * implementation so it presents a similar interface. + * + * The thread functions operate by dispatching to symbols which are, by + * default, weak-aliased to no-op functions in thread-stub/thread-stub.c + * (some uses of thread operations are conditional on __isthreaded, but + * not all of them are). + * + * When the thread library is linked in, it provides strong-alias versions + * of those symbols which dispatch to its own real thread operations. + * + */ + +#ifdef _REENTRANT + +/* + * Abtract thread interface for thread-safe libraries. These routines + * will use stubs in libc if the application is not linked against the + * pthread library, and the real function in the pthread library if it + * is. + */ + +#include <pthread.h> +#include <signal.h> + +#define mutex_t pthread_mutex_t +#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER + +#define mutexattr_t pthread_mutexattr_t + +#define MUTEX_TYPE_NORMAL PTHREAD_MUTEX_NORMAL +#define MUTEX_TYPE_ERRORCHECK PTHREAD_MUTEX_ERRORCHECK +#define MUTEX_TYPE_RECURSIVE PTHREAD_MUTEX_RECURSIVE + +#define cond_t pthread_cond_t +#define COND_INITIALIZER PTHREAD_COND_INITIALIZER + +#define condattr_t pthread_condattr_t + +#define rwlock_t pthread_rwlock_t +#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER + +#define rwlockattr_t pthread_rwlockattr_t + +#define thread_key_t pthread_key_t + +#define thr_t pthread_t + +#define thrattr_t pthread_attr_t + +#define once_t pthread_once_t +#define ONCE_INITIALIZER PTHREAD_ONCE_INIT + +#ifndef __LIBC_THREAD_STUBS + +__BEGIN_DECLS +int __libc_mutex_init(mutex_t *, const mutexattr_t *); +int __libc_mutex_lock(mutex_t *); +int __libc_mutex_trylock(mutex_t *); +int __libc_mutex_unlock(mutex_t *); +int __libc_mutex_destroy(mutex_t *); + +int __libc_mutexattr_init(mutexattr_t *); +int __libc_mutexattr_settype(mutexattr_t *, int); +int __libc_mutexattr_destroy(mutexattr_t *); +__END_DECLS + +#define mutex_init(m, a) __libc_mutex_init((m), (a)) +#define mutex_lock(m) __libc_mutex_lock((m)) +#define mutex_trylock(m) __libc_mutex_trylock((m)) +#define mutex_unlock(m) __libc_mutex_unlock((m)) +#define mutex_destroy(m) __libc_mutex_destroy((m)) + +#define mutexattr_init(ma) __libc_mutexattr_init((ma)) +#define mutexattr_settype(ma, t) __libc_mutexattr_settype((ma), (t)) +#define mutexattr_destroy(ma) __libc_mutexattr_destroy((ma)) + +__BEGIN_DECLS +int __libc_cond_init(cond_t *, const condattr_t *); +int __libc_cond_signal(cond_t *); +int __libc_cond_broadcast(cond_t *); +int __libc_cond_wait(cond_t *, mutex_t *); +int __libc_cond_timedwait(cond_t *, mutex_t *, const struct timespec *); +int __libc_cond_destroy(cond_t *); +__END_DECLS + +#define cond_init(c, t, a) __libc_cond_init((c), (a)) +#define cond_signal(c) __libc_cond_signal((c)) +#define cond_broadcast(c) __libc_cond_broadcast((c)) +#define cond_wait(c, m) __libc_cond_wait((c), (m)) +#define cond_timedwait(c, m, t) __libc_cond_timedwait((c), (m), (t)) +#define cond_destroy(c) __libc_cond_destroy((c)) + +__BEGIN_DECLS +int __libc_rwlock_init(rwlock_t *, const rwlockattr_t *); +int __libc_rwlock_rdlock(rwlock_t *); +int __libc_rwlock_wrlock(rwlock_t *); +int __libc_rwlock_tryrdlock(rwlock_t *); +int __libc_rwlock_trywrlock(rwlock_t *); +int __libc_rwlock_unlock(rwlock_t *); +int __libc_rwlock_destroy(rwlock_t *); +__END_DECLS + +#define rwlock_init(l, a) __libc_rwlock_init((l), (a)) +#define rwlock_rdlock(l) __libc_rwlock_rdlock((l)) +#define rwlock_wrlock(l) __libc_rwlock_wrlock((l)) +#define rwlock_tryrdlock(l) __libc_rwlock_tryrdlock((l)) +#define rwlock_trywrlock(l) __libc_rwlock_trywrlock((l)) +#define rwlock_unlock(l) __libc_rwlock_unlock((l)) +#define rwlock_destroy(l) __libc_rwlock_destroy((l)) + +__BEGIN_DECLS +int __libc_thr_keycreate(thread_key_t *, void (*)(void *)); +int __libc_thr_setspecific(thread_key_t, const void *); +void *__libc_thr_getspecific(thread_key_t); +int __libc_thr_keydelete(thread_key_t); +__END_DECLS + +#define thr_keycreate(k, d) __libc_thr_keycreate((k), (d)) +#define thr_setspecific(k, p) __libc_thr_setspecific((k), (p)) +#define thr_getspecific(k) __libc_thr_getspecific((k)) +#define thr_keydelete(k) __libc_thr_keydelete((k)) + +__BEGIN_DECLS +int __libc_thr_once(once_t *, void (*)(void)); +int __libc_thr_sigsetmask(int, const sigset_t *, sigset_t *); +thr_t __libc_thr_self(void); +int __libc_thr_yield(void); +void __libc_thr_create(thr_t *, const thrattr_t *, + void *(*)(void *), void *); +void __libc_thr_exit(void *) __attribute__((__noreturn__)); +int *__libc_thr_errno(void); +int __libc_thr_setcancelstate(int, int *); + +extern int __isthreaded; +__END_DECLS + +#define thr_once(o, f) __libc_thr_once((o), (f)) +#define thr_sigsetmask(f, n, o) __libc_thr_sigsetmask((f), (n), (o)) +#define thr_self() __libc_thr_self() +#define thr_yield() __libc_thr_yield() +#define thr_create(tp, ta, f, a) __libc_thr_create((tp), (ta), (f), (a)) +#define thr_exit(v) __libc_thr_exit((v)) +#define thr_errno() __libc_thr_errno() +#define thr_enabled() (__isthreaded) +#define thr_setcancelstate(n, o) __libc_thr_setcancelstate((n),(o)) +#endif /* __LIBC_THREAD_STUBS */ + +#define FLOCKFILE(fp) __flockfile_internal(fp, 1) +#define FUNLOCKFILE(fp) __funlockfile_internal(fp, 1) + +#else /* _REENTRANT */ + +#define mutex_init(m, a) +#define mutex_lock(m) +#define mutex_trylock(m) +#define mutex_unlock(m) +#define mutex_destroy(m) + +#define cond_init(c, t, a) +#define cond_signal(c) +#define cond_broadcast(c) +#define cond_wait(c, m) +#define cond_timedwait(c, m, t) +#define cond_destroy(c) + +#define rwlock_init(l, a) +#define rwlock_rdlock(l) +#define rwlock_wrlock(l) +#define rwlock_tryrdlock(l) +#define rwlock_trywrlock(l) +#define rwlock_unlock(l) +#define rwlock_destroy(l) + +#define thr_keycreate(k, d) +#define thr_setspecific(k, p) +#define thr_getspecific(k) +#define thr_keydelete(k) + +#define thr_once(o, f) +#define thr_sigsetmask(f, n, o) +#define thr_self() +#define thr_errno() + +#define FLOCKFILE(fp) +#define FUNLOCKFILE(fp) + +#endif /* _REENTRANT */ diff --git a/libc/netbsd/net/servent.h b/libc/netbsd/net/servent.h new file mode 100644 index 0000000..822b375 --- /dev/null +++ b/libc/netbsd/net/servent.h @@ -0,0 +1,44 @@ +/* $NetBSD: servent.h,v 1.1 2005/04/18 19:39:45 kleink 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 <stdio.h> +#include <errno.h> +#include <string.h> +#include "resolv_static.h" + +struct servent* getservent_r(res_static rs); diff --git a/libc/netbsd/net/services.h b/libc/netbsd/net/services.h new file mode 100644 index 0000000..fa199d0 --- /dev/null +++ b/libc/netbsd/net/services.h @@ -0,0 +1,480 @@ +/* generated by genserv.py - do not edit */ +static const char _services[] = "\ +\6tcpmux\0\1t\0\ +\4echo\0\7t\0\ +\4echo\0\7u\0\ +\7discard\0\11t\2\4sink\4null\ +\7discard\0\11u\2\4sink\4null\ +\6systat\0\13t\1\5users\ +\7daytime\0\15t\0\ +\7daytime\0\15u\0\ +\7netstat\0\17t\0\ +\4qotd\0\21t\1\5quote\ +\3msp\0\22t\0\ +\3msp\0\22u\0\ +\7chargen\0\23t\2\6ttytst\6source\ +\7chargen\0\23u\2\6ttytst\6source\ +\10ftp-data\0\24t\0\ +\3ftp\0\25t\0\ +\3fsp\0\25u\1\4fspd\ +\3ssh\0\26t\0\ +\3ssh\0\26u\0\ +\6telnet\0\27t\0\ +\4smtp\0\31t\1\4mail\ +\4time\0\45t\1\11timserver\ +\4time\0\45u\1\11timserver\ +\3rlp\0\47u\1\10resource\ +\12nameserver\0\52t\1\4name\ +\5whois\0\53t\1\7nicname\ +\6tacacs\0\61t\0\ +\6tacacs\0\61u\0\ +\12re-mail-ck\0\62t\0\ +\12re-mail-ck\0\62u\0\ +\6domain\0\65t\1\12nameserver\ +\6domain\0\65u\1\12nameserver\ +\3mtp\0\71t\0\ +\11tacacs-ds\0\101t\0\ +\11tacacs-ds\0\101u\0\ +\6bootps\0\103t\0\ +\6bootps\0\103u\0\ +\6bootpc\0\104t\0\ +\6bootpc\0\104u\0\ +\4tftp\0\105u\0\ +\6gopher\0\106t\0\ +\6gopher\0\106u\0\ +\3rje\0\115t\1\6netrjs\ +\6finger\0\117t\0\ +\3www\0\120t\1\4http\ +\3www\0\120u\0\ +\4link\0\127t\1\7ttylink\ +\10kerberos\0\130t\3\11kerberos5\4krb5\14kerberos-sec\ +\10kerberos\0\130u\3\11kerberos5\4krb5\14kerberos-sec\ +\6supdup\0\137t\0\ +\11hostnames\0\145t\1\10hostname\ +\10iso-tsap\0\146t\1\4tsap\ +\10acr-nema\0\150t\1\5dicom\ +\10acr-nema\0\150u\1\5dicom\ +\10csnet-ns\0\151t\1\6cso-ns\ +\10csnet-ns\0\151u\1\6cso-ns\ +\7rtelnet\0\153t\0\ +\7rtelnet\0\153u\0\ +\4pop2\0\155t\2\12postoffice\5pop-2\ +\4pop2\0\155u\1\5pop-2\ +\4pop3\0\156t\1\5pop-3\ +\4pop3\0\156u\1\5pop-3\ +\6sunrpc\0\157t\1\12portmapper\ +\6sunrpc\0\157u\1\12portmapper\ +\4auth\0\161t\3\16authentication\3tap\5ident\ +\4sftp\0\163t\0\ +\11uucp-path\0\165t\0\ +\4nntp\0\167t\2\10readnews\4untp\ +\3ntp\0\173t\0\ +\3ntp\0\173u\0\ +\6pwdgen\0\201t\0\ +\6pwdgen\0\201u\0\ +\7loc-srv\0\207t\1\5epmap\ +\7loc-srv\0\207u\1\5epmap\ +\12netbios-ns\0\211t\0\ +\12netbios-ns\0\211u\0\ +\13netbios-dgm\0\212t\0\ +\13netbios-dgm\0\212u\0\ +\13netbios-ssn\0\213t\0\ +\13netbios-ssn\0\213u\0\ +\5imap2\0\217t\1\4imap\ +\5imap2\0\217u\1\4imap\ +\4snmp\0\241t\0\ +\4snmp\0\241u\0\ +\11snmp-trap\0\242t\1\10snmptrap\ +\11snmp-trap\0\242u\1\10snmptrap\ +\10cmip-man\0\243t\0\ +\10cmip-man\0\243u\0\ +\12cmip-agent\0\244t\0\ +\12cmip-agent\0\244u\0\ +\5mailq\0\256t\0\ +\5mailq\0\256u\0\ +\5xdmcp\0\261t\0\ +\5xdmcp\0\261u\0\ +\10nextstep\0\262t\2\10NeXTStep\10NextStep\ +\10nextstep\0\262u\2\10NeXTStep\10NextStep\ +\3bgp\0\263t\0\ +\3bgp\0\263u\0\ +\10prospero\0\277t\0\ +\10prospero\0\277u\0\ +\3irc\0\302t\0\ +\3irc\0\302u\0\ +\4smux\0\307t\0\ +\4smux\0\307u\0\ +\7at-rtmp\0\311t\0\ +\7at-rtmp\0\311u\0\ +\6at-nbp\0\312t\0\ +\6at-nbp\0\312u\0\ +\7at-echo\0\314t\0\ +\7at-echo\0\314u\0\ +\6at-zis\0\316t\0\ +\6at-zis\0\316u\0\ +\4qmtp\0\321t\0\ +\4qmtp\0\321u\0\ +\5z3950\0\322t\1\4wais\ +\5z3950\0\322u\1\4wais\ +\3ipx\0\325t\0\ +\3ipx\0\325u\0\ +\5imap3\0\334t\0\ +\5imap3\0\334u\0\ +\7pawserv\1\131t\0\ +\7pawserv\1\131u\0\ +\5zserv\1\132t\0\ +\5zserv\1\132u\0\ +\7fatserv\1\133t\0\ +\7fatserv\1\133u\0\ +\13rpc2portmap\1\161t\0\ +\13rpc2portmap\1\161u\0\ +\11codaauth2\1\162t\0\ +\11codaauth2\1\162u\0\ +\11clearcase\1\163t\1\11Clearcase\ +\11clearcase\1\163u\1\11Clearcase\ +\11ulistserv\1\164t\0\ +\11ulistserv\1\164u\0\ +\4ldap\1\205t\0\ +\4ldap\1\205u\0\ +\4imsp\1\226t\0\ +\4imsp\1\226u\0\ +\5https\1\273t\0\ +\5https\1\273u\0\ +\4snpp\1\274t\0\ +\4snpp\1\274u\0\ +\14microsoft-ds\1\275t\0\ +\14microsoft-ds\1\275u\0\ +\4saft\1\347t\0\ +\4saft\1\347u\0\ +\6isakmp\1\364t\0\ +\6isakmp\1\364u\0\ +\4rtsp\2\52t\0\ +\4rtsp\2\52u\0\ +\3nqs\2\137t\0\ +\3nqs\2\137u\0\ +\12npmp-local\2\142t\1\16dqs313_qmaster\ +\12npmp-local\2\142u\1\16dqs313_qmaster\ +\10npmp-gui\2\143t\1\14dqs313_execd\ +\10npmp-gui\2\143u\1\14dqs313_execd\ +\10hmmp-ind\2\144t\1\20dqs313_intercell\ +\10hmmp-ind\2\144u\1\20dqs313_intercell\ +\3ipp\2\167t\0\ +\3ipp\2\167u\0\ +\4exec\2\0t\0\ +\4biff\2\0u\1\6comsat\ +\5login\2\1t\0\ +\3who\2\1u\1\4whod\ +\5shell\2\2t\1\3cmd\ +\6syslog\2\2u\0\ +\7printer\2\3t\1\7spooler\ +\4talk\2\5u\0\ +\5ntalk\2\6u\0\ +\5route\2\10u\2\6router\6routed\ +\5timed\2\15u\1\12timeserver\ +\5tempo\2\16t\1\7newdate\ +\7courier\2\22t\1\3rpc\ +\12conference\2\23t\1\4chat\ +\7netnews\2\24t\1\10readnews\ +\7netwall\2\25u\0\ +\6gdomap\2\32t\0\ +\6gdomap\2\32u\0\ +\4uucp\2\34t\1\5uucpd\ +\6klogin\2\37t\0\ +\6kshell\2\40t\1\5krcmd\ +\12afpovertcp\2\44t\0\ +\12afpovertcp\2\44u\0\ +\10remotefs\2\54t\2\12rfs_server\3rfs\ +\5nntps\2\63t\1\5snntp\ +\5nntps\2\63u\1\5snntp\ +\12submission\2\113t\0\ +\12submission\2\113u\0\ +\5ldaps\2\174t\0\ +\5ldaps\2\174u\0\ +\4tinc\2\217t\0\ +\4tinc\2\217u\0\ +\4silc\2\302t\0\ +\4silc\2\302u\0\ +\14kerberos-adm\2\355t\0\ +\7webster\2\375t\0\ +\7webster\2\375u\0\ +\5rsync\3\151t\0\ +\5rsync\3\151u\0\ +\11ftps-data\3\335t\0\ +\4ftps\3\336t\0\ +\7telnets\3\340t\0\ +\7telnets\3\340u\0\ +\5imaps\3\341t\0\ +\5imaps\3\341u\0\ +\4ircs\3\342t\0\ +\4ircs\3\342u\0\ +\5pop3s\3\343t\0\ +\5pop3s\3\343u\0\ +\5socks\4\70t\0\ +\5socks\4\70u\0\ +\6proofd\4\105t\0\ +\6proofd\4\105u\0\ +\5rootd\4\106t\0\ +\5rootd\4\106u\0\ +\7openvpn\4\252t\0\ +\7openvpn\4\252u\0\ +\13rmiregistry\4\113t\0\ +\13rmiregistry\4\113u\0\ +\5kazaa\4\276t\0\ +\5kazaa\4\276u\0\ +\6nessus\4\331t\0\ +\6nessus\4\331u\0\ +\11lotusnote\5\110t\1\12lotusnotes\ +\11lotusnote\5\110u\1\12lotusnotes\ +\10ms-sql-s\5\231t\0\ +\10ms-sql-s\5\231u\0\ +\10ms-sql-m\5\232t\0\ +\10ms-sql-m\5\232u\0\ +\12ingreslock\5\364t\0\ +\12ingreslock\5\364u\0\ +\13prospero-np\5\365t\0\ +\13prospero-np\5\365u\0\ +\13datametrics\6\155t\1\12old-radius\ +\13datametrics\6\155u\1\12old-radius\ +\13sa-msg-port\6\156t\1\13old-radacct\ +\13sa-msg-port\6\156u\1\13old-radacct\ +\6kermit\6\161t\0\ +\6kermit\6\161u\0\ +\3l2f\6\245t\1\4l2tp\ +\3l2f\6\245u\1\4l2tp\ +\6radius\7\24t\0\ +\6radius\7\24u\0\ +\13radius-acct\7\25t\1\7radacct\ +\13radius-acct\7\25u\1\7radacct\ +\13unix-status\7\245t\0\ +\12log-server\7\246t\0\ +\12remoteping\7\247t\0\ +\3nfs\10\1t\0\ +\3nfs\10\1u\0\ +\12rtcm-sc104\10\65t\0\ +\12rtcm-sc104\10\65u\0\ +\12cvspserver\11\141t\0\ +\12cvspserver\11\141u\0\ +\5venus\11\176t\0\ +\5venus\11\176u\0\ +\10venus-se\11\177t\0\ +\10venus-se\11\177u\0\ +\7codasrv\11\200t\0\ +\7codasrv\11\200u\0\ +\12codasrv-se\11\201t\0\ +\12codasrv-se\11\201u\0\ +\3mon\12\27t\0\ +\3mon\12\27u\0\ +\4dict\12\104t\0\ +\4dict\12\104u\0\ +\4gpsd\13\203t\0\ +\4gpsd\13\203u\0\ +\6gds_db\13\352t\0\ +\6gds_db\13\352u\0\ +\5icpv2\14\72t\1\3icp\ +\5icpv2\14\72u\1\3icp\ +\5mysql\14\352t\0\ +\5mysql\14\352u\0\ +\3nut\15\245t\0\ +\3nut\15\245u\0\ +\6distcc\16\60t\0\ +\6distcc\16\60u\0\ +\4daap\16\151t\0\ +\4daap\16\151u\0\ +\3svn\16\152t\1\12subversion\ +\3svn\16\152u\1\12subversion\ +\3iax\21\331t\0\ +\3iax\21\331u\0\ +\13radmin-port\23\43t\0\ +\13radmin-port\23\43u\0\ +\3rfe\23\212u\0\ +\3rfe\23\212t\0\ +\3sip\23\304t\0\ +\3sip\23\304u\0\ +\7sip-tls\23\305t\0\ +\7sip-tls\23\305u\0\ +\13xmpp-client\24\146t\1\15jabber-client\ +\13xmpp-client\24\146u\1\15jabber-client\ +\13xmpp-server\24\225t\1\15jabber-server\ +\13xmpp-server\24\225u\1\15jabber-server\ +\10cfengine\24\274t\0\ +\10cfengine\24\274u\0\ +\12postgresql\25\70t\1\10postgres\ +\12postgresql\25\70u\1\10postgres\ +\3x11\27\160t\1\5x11-0\ +\3x11\27\160u\1\5x11-0\ +\5x11-1\27\161t\0\ +\5x11-1\27\161u\0\ +\5x11-2\27\162t\0\ +\5x11-2\27\162u\0\ +\5x11-3\27\163t\0\ +\5x11-3\27\163u\0\ +\5x11-4\27\164t\0\ +\5x11-4\27\164u\0\ +\5x11-5\27\165t\0\ +\5x11-5\27\165u\0\ +\5x11-6\27\166t\0\ +\5x11-6\27\166u\0\ +\5x11-7\27\167t\0\ +\5x11-7\27\167u\0\ +\14gnutella-svc\30\312t\0\ +\14gnutella-svc\30\312u\0\ +\14gnutella-rtr\30\313t\0\ +\14gnutella-rtr\30\313u\0\ +\17afs3-fileserver\33\130t\1\3bbs\ +\17afs3-fileserver\33\130u\1\3bbs\ +\15afs3-callback\33\131t\0\ +\15afs3-callback\33\131u\0\ +\15afs3-prserver\33\132t\0\ +\15afs3-prserver\33\132u\0\ +\15afs3-vlserver\33\133t\0\ +\15afs3-vlserver\33\133u\0\ +\15afs3-kaserver\33\134t\0\ +\15afs3-kaserver\33\134u\0\ +\13afs3-volser\33\135t\0\ +\13afs3-volser\33\135u\0\ +\13afs3-errors\33\136t\0\ +\13afs3-errors\33\136u\0\ +\10afs3-bos\33\137t\0\ +\10afs3-bos\33\137u\0\ +\13afs3-update\33\140t\0\ +\13afs3-update\33\140u\0\ +\13afs3-rmtsys\33\141t\0\ +\13afs3-rmtsys\33\141u\0\ +\14font-service\33\274t\1\3xfs\ +\14font-service\33\274u\1\3xfs\ +\12bacula-dir\43\215t\0\ +\12bacula-dir\43\215u\0\ +\11bacula-fd\43\216t\0\ +\11bacula-fd\43\216u\0\ +\11bacula-sd\43\217t\0\ +\11bacula-sd\43\217u\0\ +\6amanda\47\140t\0\ +\6amanda\47\140u\0\ +\3hkp\54\153t\0\ +\3hkp\54\153u\0\ +\4bprd\65\230t\0\ +\4bprd\65\230u\0\ +\5bpdbm\65\231t\0\ +\5bpdbm\65\231u\0\ +\13bpjava-msvc\65\232t\0\ +\13bpjava-msvc\65\232u\0\ +\5vnetd\65\234t\0\ +\5vnetd\65\234u\0\ +\4bpcd\65\326t\0\ +\4bpcd\65\326u\0\ +\6vopied\65\327t\0\ +\6vopied\65\327u\0\ +\4wnn6\127\1t\0\ +\4wnn6\127\1u\0\ +\11kerberos4\2\356u\2\13kerberos-iv\3kdc\ +\11kerberos4\2\356t\2\13kerberos-iv\3kdc\ +\17kerberos_master\2\357u\0\ +\17kerberos_master\2\357t\0\ +\15passwd_server\2\360u\0\ +\10krb_prop\2\362t\2\11krb5_prop\5hprop\ +\11krbupdate\2\370t\1\4kreg\ +\7kpasswd\2\371t\1\4kpwd\ +\4swat\3\205t\0\ +\4kpop\4\125t\0\ +\5knetd\10\5t\0\ +\12zephyr-srv\10\66u\0\ +\12zephyr-clt\10\67u\0\ +\11zephyr-hm\10\70u\0\ +\7eklogin\10\71t\0\ +\2kx\10\77t\0\ +\5iprop\10\111t\0\ +\12supfilesrv\3\147t\0\ +\12supfiledbg\4\147t\0\ +\11linuxconf\0\142t\0\ +\10poppassd\0\152t\0\ +\10poppassd\0\152u\0\ +\5ssmtp\1\321t\1\5smtps\ +\10moira_db\3\7t\0\ +\14moira_update\3\11t\0\ +\12moira_ureg\3\13u\0\ +\5spamd\3\17t\0\ +\5omirr\3\50t\1\6omirrd\ +\5omirr\3\50u\1\6omirrd\ +\7customs\3\351t\0\ +\7customs\3\351u\0\ +\7skkserv\4\232t\0\ +\7predict\4\272u\0\ +\6rmtcfg\4\324t\0\ +\5wipld\5\24t\0\ +\4xtel\5\41t\0\ +\5xtelw\5\42t\0\ +\7support\5\371t\0\ +\5sieve\7\320t\0\ +\7cfinger\7\323t\0\ +\4ndtp\7\332t\0\ +\4frox\10\111t\0\ +\10ninstall\10\146t\0\ +\10ninstall\10\146u\0\ +\10zebrasrv\12\50t\0\ +\5zebra\12\51t\0\ +\4ripd\12\52t\0\ +\6ripngd\12\53t\0\ +\5ospfd\12\54t\0\ +\4bgpd\12\55t\0\ +\6ospf6d\12\56t\0\ +\7ospfapi\12\57t\0\ +\5isisd\12\60t\0\ +\10afbackup\13\254t\0\ +\10afbackup\13\254u\0\ +\11afmbackup\13\255t\0\ +\11afmbackup\13\255u\0\ +\5xtell\20\200t\0\ +\3fax\21\315t\0\ +\7hylafax\21\317t\0\ +\7distmp3\21\370t\0\ +\5munin\23\125t\1\4lrrd\ +\13enbd-cstatd\23\273t\0\ +\13enbd-sstatd\23\274t\0\ +\4pcrd\24\37t\0\ +\6noclog\24\352t\0\ +\6noclog\24\352u\0\ +\7hostmon\24\353t\0\ +\7hostmon\24\353u\0\ +\5rplay\25\263u\0\ +\5rplay\25\263t\0\ +\4rptp\25\264u\0\ +\4rptp\25\264t\0\ +\4nsca\26\43t\0\ +\4mrtd\26\52t\0\ +\6bgpsim\26\53t\0\ +\5canna\26\60t\0\ +\11sane-port\31\246t\2\4sane\5saned\ +\4ircd\32\13t\0\ +\10zope-ftp\37\125t\0\ +\10webcache\37\220t\0\ +\6tproxy\37\221t\0\ +\7omniorb\37\230t\0\ +\7omniorb\37\230u\0\ +\20clc-build-daemon\43\36t\0\ +\6xinetd\43\212t\0\ +\13mandelspawn\44\217u\1\12mandelbrot\ +\4zope\45\311t\0\ +\7kamanda\47\141t\0\ +\7kamanda\47\141u\0\ +\11amandaidx\47\142t\0\ +\11amidxtape\47\143t\0\ +\5smsqp\53\301t\0\ +\5smsqp\53\301u\0\ +\6xpilot\73\361t\0\ +\6xpilot\73\361u\0\ +\10sgi-cmsd\102\151u\0\ +\10sgi-crsd\102\152u\0\ +\7sgi-gcd\102\153u\0\ +\7sgi-cad\102\154t\0\ +\7isdnlog\116\53t\0\ +\7isdnlog\116\53u\0\ +\5vboxd\116\54t\0\ +\5vboxd\116\54u\0\ +\5binkp\137\352t\0\ +\3asp\152\356t\0\ +\3asp\152\356u\0\ +\11dircproxy\336\250t\0\ +\5tfido\353\21t\0\ +\4fido\353\23t\0\ +\0"; + |