diff options
Diffstat (limited to 'mit-pthreads/net/res_internal.c')
-rw-r--r-- | mit-pthreads/net/res_internal.c | 576 |
1 files changed, 0 insertions, 576 deletions
diff --git a/mit-pthreads/net/res_internal.c b/mit-pthreads/net/res_internal.c deleted file mode 100644 index 4eab65bf5aa..00000000000 --- a/mit-pthreads/net/res_internal.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Copyright (c) 1985 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)res_internal.c 6.22 (Berkeley) 3/19/91";*/ -static char *rcsid = "$Id$"; -#endif /* LIBC_SCCS and not lint */ - -#include <pthread.h> -#include <stdio.h> -#include <stdlib.h> -#include <resolv.h> -#include <netdb.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <string.h> -#include <errno.h> -#include "res_internal.h" - -#define DEFAULT_RETRIES 4 - -pthread_mutex_t host_iterate_lock = PTHREAD_MUTEX_INITIALIZER; -static pthread_once_t init_once = PTHREAD_ONCE_INIT; -static pthread_key_t key; -static int init_status; - -static void _res_init_global(void); -static void set_options(const char *options, const char *source); -static pthread_ipaddr_type net_mask(struct in_addr in); -static int qcomp(const void *arg1, const void *arg2); - -static struct __res_state start; -/* We want to define _res for partial binary compatibility with libraries. */ -#undef _res -struct __res_state _res = { - RES_TIMEOUT, /* retransmition time interval */ - 4, /* number of times to retransmit */ - RES_DEFAULT, /* options flags */ - 1, /* number of name servers */ -}; - -struct hostent *_res_parse_answer(querybuf *answer, int anslen, int iquery, - struct hostent *result, char *buf, - int bufsize, int *errval) -{ - struct res_data *data = _res_init(); - register HEADER *hp; - register u_char *cp; - register int n; - u_char *eom; - char *aliases[__NETDB_MAXALIASES], *addrs[__NETDB_MAXADDRS]; - char *bp = buf, **ap = aliases, **hap = addrs; - int type, class, ancount, qdcount, getclass = C_ANY, iquery_done = 0; - - eom = answer->buf + anslen; - /* - * find first satisfactory answer - */ - hp = &answer->hdr; - ancount = ntohs(hp->ancount); - qdcount = ntohs(hp->qdcount); - bp = buf; - cp = answer->buf + sizeof(HEADER); - - /* Read in the hostname if this is an address lookup. */ - if (qdcount) { - if (iquery) { - if ((n = dn_expand((u_char *) answer->buf, - (u_char *) eom, (u_char *) cp, (u_char *) bp, - bufsize - (bp - buf))) < 0) { - *errval = NO_RECOVERY; - return ((struct hostent *) NULL); - } - cp += n + QFIXEDSZ; - result->h_name = bp; - bp += strlen(bp) + 1; - } else { - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - } - while (--qdcount > 0) - cp += __dn_skipname(cp, eom) + QFIXEDSZ; - } else if (iquery) { - *errval = (hp->aa) ? HOST_NOT_FOUND : TRY_AGAIN; - return ((struct hostent *) NULL); - } - - /* Read in the answers. */ - *ap = NULL; - *hap = NULL; - while (--ancount >= 0 && cp < eom) { - if ((n = dn_expand((u_char *) answer->buf, (u_char *) eom, - (u_char *) cp, (u_char *) bp, - bufsize - (bp - buf))) < 0) - break; - cp += n; - type = _getshort(cp); - cp += sizeof(u_short); - class = _getshort(cp); - cp += sizeof(u_short) + sizeof(pthread_ipaddr_type); - n = _getshort(cp); - cp += sizeof(u_short); - if (type == T_CNAME) { - cp += n; - if (ap >= aliases + __NETDB_MAXALIASES - 1) - continue; - *ap++ = bp; - bp += strlen(bp) + 1; - continue; - } - if (iquery && type == T_PTR) { - if ((n = dn_expand((u_char *) answer->buf, (u_char *) eom, - (u_char *) cp, (u_char *) bp, - bufsize - (bp - buf))) < 0) - break; - cp += n; - result->h_name = bp; - bp += strlen(bp) + 1; - iquery_done = 1; - break; - } - if (iquery || type != T_A) { -#ifdef DEBUG_RESOLVER - if (data->state.options & RES_DEBUG) - printf("unexpected answer type %d, size %d\n", - type, n); -#endif - cp += n; - continue; - } - if (hap > addrs) { - if (n != result->h_length) { - cp += n; - continue; - } - if (class != getclass) { - cp += n; - continue; - } - } else { - result->h_length = n; - getclass = class; - result->h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC; - if (!iquery) { - result->h_name = bp; - bp += strlen(bp) + 1; - } - } - bp = ALIGN(bp, pthread_ipaddr_type); - if (bp + n >= buf + bufsize) { - errno = ERANGE; - return NULL; - } - memcpy(bp, cp, n); - cp += n; - if (hap >= addrs + __NETDB_MAXADDRS - 1) - continue; - *hap++ = bp; - bp += n; - cp += n; - } - - if (hap > addrs || iquery_done) { - *ap++ = NULL; - *hap++ = NULL; - if (data->state.nsort) - qsort(addrs, hap - addrs, sizeof(struct in_addr), qcomp); - if (SP(bp, char *, (hap - addrs) + (ap - aliases)) > buf + bufsize) { - errno = ERANGE; - return NULL; - } - result->h_addr_list = (char **) ALIGN(bp, char *); - memcpy(result->h_addr_list, addrs, (hap - addrs) * sizeof(char *)); - result->h_aliases = result->h_addr_list + (hap - addrs); - memcpy(result->h_aliases, aliases, (ap - aliases) * sizeof(char *)); - return result; - } else { - *errval = TRY_AGAIN; - return NULL; - } -} - -/* Performs global initialization. */ -struct res_data *_res_init() -{ - struct res_data *data; - - /* Make sure the global initializations have been done. */ - pthread_once(&init_once, _res_init_global); - if (init_status < 0) - return NULL; - - /* Initialize thread-specific data for this thread if it hasn't - * been done already. */ - data = (struct res_data *) pthread_getspecific(key); - if (!data) { - data = (struct res_data *) malloc(sizeof(struct res_data)); - if (data == NULL) - return NULL; - if (pthread_setspecific(key, data) < 0) { - free(data); - return NULL; - } - data->buf = NULL; - data->state = start; - data->errval = NO_RECOVERY; - data->sock = -1; - } - return data; -} - -static void _res_init_global() -{ - int result; - char line[BUFSIZ], buf[BUFSIZ], *domain, *p, *net; - int i, localdomain_set = 0, num_servers = 0, num_sorts = 0; - FILE *fp; - struct in_addr addr; - - /* Assume an error state until we finish. */ - init_status = -1; - - /* Initialize the key for thread-specific data. */ - result = pthread_key_create(&key, free); - if (result < 0) - return; - - /* Initialize starting state. */ - start.retrans = RES_TIMEOUT; - start.retry = DEFAULT_RETRIES; - start.options = RES_DEFAULT; - start.id = 0; - start.nscount = 1; - start.nsaddr.sin_addr.s_addr = INADDR_ANY; - start.nsaddr.sin_family = AF_INET; - start.nsaddr.sin_port = htons(NAMESERVER_PORT); - start.nscount = 1; - start.ndots = 1; - start.pfcode = 0; - strncpy(start.lookups, "f", sizeof(start.lookups)); - - /* Look for a LOCALDOMAIN definition. */ - domain = getenv("LOCALDOMAIN"); - if (domain != NULL) { - strncpy(start.defdname, domain, sizeof(start.defdname)); - domain = start.defdname; - localdomain_set = 1; - - /* Construct a search path from the LOCALDOMAIN value, which is - * a space-separated list of strings. For backwards-compatibility, - * a newline terminates the list. */ - i = 0; - while (*domain && i < MAXDNSRCH) { - start.dnsrch[i] = domain; - while (*domain && !isspace(*domain)) - domain++; - if (!*domain || *domain == '\n') { - *domain = 0; - break; - } - *domain++ = 0; - while (isspace(*domain)) - domain++; - i++; - } - } - - /* Look for a config file and read it in. */ - fp = fopen(_PATH_RESCONF, "r"); - if (fp != NULL) { - strncpy(start.lookups, "bf", sizeof(start.lookups)); - - /* Read in the configuration file. */ - while (fgets(line, sizeof(line), fp)) { - - /* Ignore blank lines and comments. */ - if (*line == ';' || *line == '#' || !*line) - continue; - - if (strncmp(line, "domain", 6) == 0) { - - /* Read in the default domain, and initialize a one- - * element search path. Skip the domain line if we - * already got one from the LOCALDOMAIN environment - * variable. */ - if (localdomain_set) - continue; - - /* Look for the next word in the line. */ - p = line + 6; - while (*p == ' ' || *p == '\t') - p++; - if (!*p || *p == '\n') - continue; - - /* Copy in the domain, and null-terminate it at the - * first tab or newline. */ - strncpy(start.defdname, p, sizeof(start.defdname) - 1); - p = strpbrk(start.defdname, "\t\n"); - if (p) - *p = 0; - - start.dnsrch[0] = start.defdname; - start.dnsrch[1] = NULL; - - } else if (strncmp(line, "lookup", 6) == 0) { - - /* Get a list of lookup types. */ - memset(start.lookups, 0, sizeof(start.lookups)); - - /* Find the next word in the line. */ - p = line + 6; - while (isspace(*p)) - p++; - - i = 0; - while (*p && i < MAXDNSLUS) { - /* Add a lookup type. */ - if (*p == 'y' || *p == 'b' || *p == 'f') - start.lookups[i++] = *p; - - /* Find the next word. */ - while (*p && !isspace(*p)) - p++; - while (isspace(*p)) - p++; - } - - } else if (strncmp(line, "search", 6) == 0) { - - /* Read in a space-separated list of domains to search - * when a name is not fully-qualified. Skip this line - * if the LOCALDOMAIN environment variable was set. */ - if (localdomain_set) - continue; - - /* Look for the next word on the line. */ - p = line + 6; - while (*p == ' ' || *p == '\t') - p++; - if (!*p || *p == '\n') - continue; - - /* Copy the rest of the line into start.defdname. */ - strncpy(start.defdname, p, sizeof(start.defdname) - 1); - domain = start.defdname; - p = strchr(domain, '\n'); - if (*p) - *p = 0; - - /* Construct a search path from the line, which is a - * space-separated list of strings. */ - i = 0; - while (*domain && i < MAXDNSRCH) { - start.dnsrch[i] = domain; - while (*domain && !isspace(*domain)) - domain++; - if (!*domain || *domain == '\n') { - *domain = 0; - break; - } - *domain++ = 0; - while (isspace(*domain)) - domain++; - i++; - } - - } else if (strncmp(line, "nameserver", 10) == 0) { - - /* Add an address to the list of name servers we can - * connect to. */ - - /* Look for the next word in the line. */ - p = line + 10; - while (*p == ' ' || *p == '\t') - p++; - if (*p && *p != '\n' && inet_aton(p, &addr)) { - start.nsaddr_list[num_servers].sin_addr = addr; - start.nsaddr_list[num_servers].sin_family = AF_INET; - start.nsaddr_list[num_servers].sin_port = - htons(NAMESERVER_PORT); - if (++num_servers >= MAXNS) - break; - } - - } else if (strncmp(line, "sortlist", 8) == 0) { - - p = line + 8; - while (num_sorts < MAXRESOLVSORT) { - - /* Find the next word in the line. */ - p = line + 8; - while (*p == ' ' || *p == '\t') - p++; - - /* Read in an IP address and netmask. */ - if (sscanf(p, "%[0-9./]s", buf) != 1) - break; - net = strchr(buf, '/'); - if (net) - *net = 0; - - /* Translate the address into an IP address - * and netmask. */ - if (inet_aton(buf, &addr)) { - start.sort_list[num_sorts].addr = addr; - if (net && inet_aton(net + 1, &addr)) { - start.sort_list[num_sorts].mask = addr.s_addr; - } else { - start.sort_list[num_sorts].mask = - net_mask(start.sort_list[num_sorts].addr); - } - num_sorts++; - } - - /* Skip past this word. */ - if (net) - *net = '/'; - p += strlen(buf); - } - - } - } - fclose(fp); - } - - /* If we don't have a default domain, strip off the first - * component of this machine's domain name, and make a one- - * element search path consisting of the default domain. */ - if (*start.defdname == 0) { - if (gethostname(buf, sizeof(start.defdname) - 1) == 0) { - p = strchr(buf, '.'); - if (p) - strcpy(start.defdname, p + 1); - } - start.dnsrch[0] = start.defdname; - start.dnsrch[1] = NULL; - } - - p = getenv("RES_OPTIONS"); - if (p) - set_options(p, "env"); - - start.options |= RES_INIT; - _res = start; - init_status = 0; -} - -static void set_options(const char *options, const char *source) -{ - const char *p = options; - int i; - - while (*p) { - - /* Skip leading and inner runs of spaces. */ - while (*p == ' ' || *p == '\t') - p++; - - /* Search for and process individual options. */ - if (strncmp(p, "ndots:", 6) == 0) { - i = atoi(p + 6); - start.ndots = (i <= RES_MAXNDOTS) ? i : RES_MAXNDOTS; - } else if (!strncmp(p, "debug", 5)) - start.options |= RES_DEBUG; - else if (!strncmp(p, "usevc", 5)) - start.options |= RES_USEVC; - else if (!strncmp(p, "stayopen", 8)) - start.options |= RES_STAYOPEN; - - /* Skip to next run of spaces */ - while (*p && *p != ' ' && *p != '\t') - p++; - } -} - -static pthread_ipaddr_type net_mask(struct in_addr in) -{ - pthread_ipaddr_type i = ntohl(in.s_addr); - - if (IN_CLASSA(i)) - return htonl(IN_CLASSA_NET); - if (IN_CLASSB(i)) - return htonl(IN_CLASSB_NET); - return htonl(IN_CLASSC_NET); -} - -/* Get the error value for this thread, or NO_RECOVERY if none has been - * successfully set. The screw case to worry about here is if - * __res_init() fails for a resolver routine because it can't allocate - * or set the thread-specific data, and then __res_init() succeeds here. - * Because __res_init() sets errval to NO_RECOVERY after a successful - * initialization, we return NO_RECOVERY in that case, which is correct. */ -int _res_get_error() -{ - struct res_data *data; - - data = _res_init(); - return (data) ? data->errval : NO_RECOVERY; -} - -struct __res_state *_res_status() -{ - struct res_data *data; - - data = _res_init(); - return (data) ? &data->state : NULL; -} - -static int qcomp(const void *arg1, const void *arg2) -{ - const struct in_addr **a1 = (const struct in_addr **) arg1; - const struct in_addr **a2 = (const struct in_addr **) arg2; - struct __res_state *state = _res_status(); - - int pos1, pos2; - - for (pos1 = 0; pos1 < state->nsort; pos1++) { - if (state->sort_list[pos1].addr.s_addr == - ((*a1)->s_addr & state->sort_list[pos1].mask)) - break; - } - for (pos2 = 0; pos2 < state->nsort; pos2++) { - if (state->sort_list[pos2].addr.s_addr == - ((*a2)->s_addr & state->sort_list[pos2].mask)) - break; - } - return pos1 - pos2; -} - -/* - * This routine is for closing the socket if a virtual circuit is used and - * the program wants to close it. We don't use this routine, but libc - * might reference it. - * - * This routine is not expected to be user visible. - */ -void _res_close() -{ - struct res_data *data; - - data = _res_init(); - if (data && data->sock != -1) { - (void) close(data->sock); - data->sock = -1; - } -} |