Date: Mon, 12 Aug 2002 13:14:49 +0300 From: Maxim Sobolev <sobomax@FreeBSD.org> To: hackers@FreeBSD.org, audit@FreeBSD.org, Alexander Litvin <archer@whichever.org>, Andriy Gapon <agapon@excite.com> Subject: Thread-safe resolver [patches for review] Message-ID: <3D578A99.F0821712@FreeBSD.org>
next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------051496A982500B2DDF1E4FCD Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 7bit Folks, Attched please find two patches based on bin/29581 PR to make FreeBSD resolver thread-safe. They represent two approaches to reach this goal - the first is to introduce reentrant versions of the standard gethostbyXXX(3) APIs, similar to ones existing in other unices, and the second one is to make gethostbyXXX(3) returning data placed into per-thread storage when linked with libc_r. I like the latter approach more, since it doesn't introduce new non-standard APIs. I would like to hear any comments and suggestions on the proposed patches, as well as to opinions about which path to chose. Thanks! -Maxim --------------051496A982500B2DDF1E4FCD Content-Type: text/plain; charset=koi8-r; name="resolv_r-1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="resolv_r-1.diff" Index: src/include/netdb.h =================================================================== RCS file: /home/ncvs/src/include/netdb.h,v retrieving revision 1.24 diff -d -u -r1.24 netdb.h --- src/include/netdb.h 26 Jun 2002 08:18:42 -0000 1.24 +++ src/include/netdb.h 10 Aug 2002 10:03:43 -0000 @@ -82,7 +82,10 @@ #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" -extern int h_errno; +__BEGIN_DECLS +int * __h_errno_accessor(void); +__END_DECLS +#define h_errno (* __h_errno_accessor()) /* * Structures returned by network data base library. All addresses are @@ -240,6 +243,15 @@ char *gai_strerror(int); void setnetgrent(const char *); void setservent(int); + +int gethostbyaddr_r(const char *, int, int, struct hostent *, + char *, int, int *); +int gethostbyname_r(const char *, struct hostent *, + char *, int, int *); +int gethostbyname2_r(const char *, int, struct hostent *, + char *, int, int *); +struct hostent *gethostent_r(struct hostent *, char *, int); + /* * PRIVATE functions specific to the FreeBSD implementation Index: src/include/resolv.h =================================================================== RCS file: /home/ncvs/src/include/resolv.h,v retrieving revision 1.21 diff -d -u -r1.21 resolv.h --- src/include/resolv.h 23 Mar 2002 17:24:53 -0000 1.21 +++ src/include/resolv.h 10 Aug 2002 10:03:43 -0000 @@ -90,11 +90,16 @@ #define MAXDFLSRCH 3 /* # default domain levels to try */ #define MAXDNSRCH 6 /* max # domains in search path */ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ +#define MAXALIASES 35 /* max # of aliases to return */ +#define MAXADDRS 35 /* max # of addresses to return */ #define RES_TIMEOUT 5 /* min. seconds between retries */ #define MAXRESOLVSORT 10 /* number of net to sort on */ #define RES_MAXNDOTS 15 /* should reflect bit field size */ +#define CAST_ALIGN(ptr, type) \ + (char*)(type)ptr < (char*)ptr ? ((type)ptr) + 1 : (type)ptr + struct __res_state { int retrans; /* retransmition time interval */ int retry; /* number of times to retransmit */ @@ -198,10 +203,6 @@ char * humanname; /* Its fun name, like "mail exchanger" */ }; -extern struct __res_state _res; -/* for INET6 */ -extern struct __res_state_ext _res_ext; - extern const struct res_sym __p_class_syms[]; extern const struct res_sym __p_type_syms[]; @@ -224,6 +225,7 @@ #define fp_query __fp_query #define fp_nquery __fp_nquery #define hostalias __hostalias +#define hostalias_r __hostalias_r #define putlong __putlong #define putshort __putshort #define p_class __p_class @@ -273,6 +275,7 @@ void fp_query(const u_char *, FILE *); void fp_nquery(const u_char *, int, FILE *); const char * hostalias(const char *); +const char * hostalias_r(const char *, char *, int); void putlong(u_int32_t, u_char *); void putshort(u_int16_t, u_char *); const char * p_class(int); @@ -315,5 +318,30 @@ void res_freeupdrec(ns_updrec *); #endif __END_DECLS + +struct __res_data { + int h_errno_res; + int s; /* socket used for communications */ + int connected : 1; /* is the socket connected */ + int vc : 1; /* is the socket a virtual circuit? */ + int af; /* address family of socket */ + res_send_qhook Qhook; + res_send_rhook Rhook; + FILE* hostf; + int stayopen; + struct __res_state *res; + struct __res_state_ext *res_ext; +}; + +__BEGIN_DECLS +u_int16_t _getshort(const u_char *); +u_int32_t _getlong(const u_char *); +struct __res_data * __res_data_accessor(void); +struct __res_state * __res_accessor(void); +__END_DECLS +#define _res_data (* __res_data_accessor()) +#define _res (* __res_accessor()) +/* for INET6 */ +#define _res_ext (* (__res_data_accessor()->res_ext)) #endif /* !_RESOLV_H_ */ Index: src/lib/libc/net/getaddrinfo.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getaddrinfo.c,v retrieving revision 1.28 diff -d -u -r1.28 getaddrinfo.c --- src/lib/libc/net/getaddrinfo.c 2 Aug 2002 11:58:48 -0000 1.28 +++ src/lib/libc/net/getaddrinfo.c 10 Aug 2002 10:03:49 -0000 @@ -1673,7 +1673,6 @@ /* resolver logic */ extern const char *__hostalias(const char *); -extern int h_errno; /* * Formulate a normal query, send, and await answer. Index: src/lib/libc/net/gethostbydns.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbydns.c,v retrieving revision 1.36 diff -d -u -r1.36 gethostbydns.c --- src/lib/libc/net/gethostbydns.c 26 Jun 2002 14:18:36 -0000 1.36 +++ src/lib/libc/net/gethostbydns.c 10 Aug 2002 10:03:49 -0000 @@ -68,6 +68,7 @@ #include <arpa/nameser.h> #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #include <string.h> #include <netdb.h> @@ -82,18 +83,11 @@ #define SPRINTF(x) ((size_t)sprintf x) -#define MAXALIASES 35 -#define MAXADDRS 35 - static const char AskedForGot[] = "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; -static char *h_addr_ptrs[MAXADDRS + 1]; - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[8*1024]; -static u_char host_addr[16]; /* IPv4 or IPv6 */ +static char hostbuf_s[8*1024]; +static u_char host_addr_s[16]; /* IPv4 or IPv6 */ #ifdef RESOLVSORT static void addrsort(char **, int); @@ -119,7 +113,6 @@ char ac; } align; -extern int h_errno; int _dns_ttl_; #ifdef DEBUG @@ -157,11 +150,14 @@ } while (0) static struct hostent * -gethostanswer(answer, anslen, qname, qtype) +gethostanswer(answer, anslen, qname, qtype, host, hostbuf, hostbuflen) const querybuf *answer; int anslen; const char *qname; int qtype; + struct hostent *host; + char *hostbuf; + int hostbuflen; { const HEADER *hp; const u_char *cp; @@ -176,7 +172,7 @@ int (*name_ok)(const char *); tname = qname; - host.h_name = NULL; + host->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: @@ -197,7 +193,7 @@ ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - ep = hostbuf + sizeof hostbuf; + ep = hostbuf + hostbuflen; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { @@ -220,17 +216,15 @@ h_errno = NO_RECOVERY; return (NULL); } - host.h_name = bp; + host->h_name = bp; bp += n; /* The qname can be abbreviated, but h_name is now absolute. */ - qname = host.h_name; + qname = host->h_name; } - ap = host_aliases; + ap = host->h_aliases; *ap = NULL; - host.h_aliases = host_aliases; - hap = h_addr_ptrs; + hap = host->h_addr_list; *hap = NULL; - host.h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; @@ -259,7 +253,7 @@ continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) + if (ap >= &host->h_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { @@ -286,7 +280,7 @@ continue; } strcpy(bp, tbuf); - host.h_name = bp; + host->h_name = bp; bp += n; continue; } @@ -341,8 +335,8 @@ return (NULL); } if (!haveanswer) - host.h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) + host->h_name = bp; + else if (ap < &host->h_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; @@ -356,7 +350,7 @@ } break; #else - host.h_name = bp; + host->h_name = bp; if (_res.options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { @@ -364,27 +358,27 @@ break; } bp += n; - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); } h_errno = NETDB_SUCCESS; - return (&host); + return (host); #endif case T_A: case T_AAAA: - if (strcasecmp(host.h_name, bp) != 0) { + if (strcasecmp(host->h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); + AskedForGot, host->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } - if (n != host.h_length) { + if (n != host->h_length) { cp += n; continue; } if (!haveanswer) { int nn; - host.h_name = bp; + host->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; } @@ -396,7 +390,7 @@ had_error++; continue; } - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (hap >= &host->h_addr_list[MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", MAXADDRS); @@ -430,62 +424,82 @@ * address in that case, not some random one */ if (_res.nsort && haveanswer > 1 && qtype == T_A) - addrsort(h_addr_ptrs, haveanswer); + addrsort(host->h_addr_list, haveanswer); # endif /*RESOLVSORT*/ - if (!host.h_name) { + if (!host->h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); - host.h_name = bp; + host->h_name = bp; bp += n; } if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); h_errno = NETDB_SUCCESS; - return (&host); + return (host); } no_recovery: h_errno = NO_RECOVERY; return (NULL); } -struct hostent * -__dns_getanswer(answer, anslen, qname, qtype) - const char *answer; - int anslen; - const char *qname; - int qtype; -{ - switch(qtype) { - case T_AAAA: - host.h_addrtype = AF_INET6; - host.h_length = IN6ADDRSZ; - break; - case T_A: - default: - host.h_addrtype = AF_INET; - host.h_length = INADDRSZ; - break; - } - - return(gethostanswer((const querybuf *)answer, anslen, qname, qtype)); -} - int _dns_gethostbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; + u_char *host_addr; querybuf buf; const char *cp; char *bp, *ep; int n, size, type, len; + char abuf[MAXDNAME]; name = va_arg(ap, const char *); af = va_arg(ap, int); + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char *); + hostbuflen = va_arg(ap, int); *(struct hostent **)rval = NULL; + if(hostbuflen != 0 && hostbuf != NULL) { + host->h_aliases = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host->h_addr_list = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_addr_list + sizeof(char *[MAXADDRS + 1]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host_addr = hostbuf; + bp = (char *)host_addr + sizeof(u_char[16]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < MAXDNAME+1) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + } else { + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + host_addr = host_addr_s; + } + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return NS_UNAVAIL; @@ -506,15 +520,15 @@ return NS_UNAVAIL; } - host.h_addrtype = af; - host.h_length = size; + host->h_addrtype = af; + host->h_length = size; /* * if there aren't any dots, it could be a user-level alias. * this is also done in res_query() since we are not the only * function that looks up host names. */ - if (!strchr(name, '.') && (cp = __hostalias(name))) + if (!strchr(name, '.') && (cp = __hostalias_r(name, abuf, sizeof abuf))) name = cp; /* @@ -538,17 +552,15 @@ strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; - ep = hostbuf + sizeof hostbuf; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; + ep = hostbuf + hostbuflen; + host->h_name = hostbuf; + host->h_aliases[0] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; + *(struct hostent **)rval = host; return NS_SUCCESS; } if (!isdigit((unsigned char)*cp) && *cp != '.') @@ -572,15 +584,13 @@ strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; - len = sizeof hostbuf - MAXDNAME; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; + len = hostbuflen - MAXDNAME; + host->h_name = hostbuf; + host->h_aliases[0] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; + *(struct hostent **)rval = host; return NS_SUCCESS; } if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') @@ -591,7 +601,8 @@ dprintf("res_search failed (%d)\n", n); return NS_UNAVAIL; } - *(struct hostent **)rval = gethostanswer(&buf, n, name, type); + *(struct hostent **)rval = gethostanswer(&buf, n, name, type, + host, hostbuf, hostbuflen); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } @@ -600,6 +611,10 @@ { const char *addr; /* XXX should have been def'd as u_char! */ int len, af; + struct hostent *host; + char *hostbuf; + int hostbuflen; + char *bp; const u_char *uaddr; static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; @@ -607,6 +622,7 @@ querybuf buf; struct hostent *hp; char qbuf[MAXDNAME+1], *qp; + u_char *host_addr; #ifdef SUNSECURITY struct hostent *rhp; char **haddr; @@ -618,9 +634,45 @@ uaddr = (const u_char *)addr; len = va_arg(ap, int); af = va_arg(ap, int); - + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char*); + hostbuflen = va_arg(ap, int); *(struct hostent **)rval = NULL; + if(hostbuflen != 0 && hostbuf != NULL) { + host->h_aliases = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host->h_addr_list = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_addr_list + sizeof(char *[MAXADDRS + 1]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host_addr = hostbuf; + bp = (char *)host_addr + sizeof(u_char[16]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < MAXDNAME+1) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + } else { + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + host_addr = host_addr_s; + } + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return NS_UNAVAIL; @@ -680,7 +732,7 @@ dprintf("static buffer is too small (%d)\n", n); return NS_UNAVAIL; } - if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR))) + if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR, host, hostbuf, hostbuflen))) return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ #ifdef SUNSECURITY if (af == AF_INET) { @@ -717,8 +769,8 @@ hp->h_addrtype = af; hp->h_length = len; bcopy(addr, host_addr, len); - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; if (af == AF_INET && (_res.options & RES_USE_INET6)) { _map_v4v6_address((char*)host_addr, (char*)host_addr); hp->h_addrtype = AF_INET6; Index: src/lib/libc/net/gethostbyht.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbyht.c,v retrieving revision 1.16 diff -d -u -r1.16 gethostbyht.c --- src/lib/libc/net/gethostbyht.c 22 Mar 2002 21:52:29 -0000 1.16 +++ src/lib/libc/net/gethostbyht.c 10 Aug 2002 10:03:52 -0000 @@ -62,6 +62,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <errno.h> #include <stdio.h> #include <ctype.h> #include <string.h> @@ -70,49 +71,53 @@ #include <arpa/nameser.h> /* XXX */ #include <resolv.h> /* XXX */ -#define MAXALIASES 35 - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[BUFSIZ+1]; -static FILE *hostf = NULL; -static u_int32_t host_addr[4]; /* IPv4 or IPv6 */ static char *h_addr_ptrs[2]; -static int stayopen = 0; +static char *host_aliases[MAXALIASES]; +static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs }; + +static char hostbuf_s[BUFSIZ+1]; +static u_int32_t host_addr_s[4]; /* IPv4 or IPv6 */ void _sethosthtent(f) int f; { - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); + if (!_res_data.hostf) + _res_data.hostf = fopen(_PATH_HOSTS, "r" ); else - rewind(hostf); - stayopen = f; + rewind(_res_data.hostf); + _res_data.stayopen = f; } void _endhosthtent() { - if (hostf && !stayopen) { - (void) fclose(hostf); - hostf = NULL; + if (_res_data.hostf && !_res_data.stayopen) { + (void) fclose(_res_data.hostf); + _res_data.hostf = NULL; } } struct hostent * gethostent() { + + return (gethostent_r(&host_s, hostbuf_s, sizeof hostbuf_s)); +} + +struct hostent * +gethostent_r(struct hostent *host, char *hostbuf, int hostbuflen) +{ char *p; char *cp, **q; int af, len; - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { + if (!_res_data.hostf && !(_res_data.hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } again: - if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { + if (!(p = fgets(hostbuf, hostbuflen, _res_data.hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); } @@ -124,12 +129,12 @@ if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - if (inet_pton(AF_INET6, p, host_addr) > 0) { + if (inet_pton(AF_INET6, p, host->h_addr_list[0]) > 0) { af = AF_INET6; len = IN6ADDRSZ; - } else if (inet_pton(AF_INET, p, host_addr) > 0) { + } else if (inet_pton(AF_INET, p, host->h_addr_list[0]) > 0) { if (_res.options & RES_USE_INET6) { - _map_v4v6_address((char*)host_addr, (char*)host_addr); + _map_v4v6_address(host->h_addr_list[0], host->h_addr_list[0]); af = AF_INET6; len = IN6ADDRSZ; } else { @@ -139,15 +144,12 @@ } else { goto again; } - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - host.h_length = len; - host.h_addrtype = af; + host->h_length = len; + host->h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; - host.h_name = cp; - q = host.h_aliases = host_aliases; + host->h_name = cp; + q = host->h_aliases; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; while (cp && *cp) { @@ -155,14 +157,14 @@ cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) + if (q < &host->h_aliases[MAXALIASES - 1]) *q++ = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } *q = NULL; h_errno = NETDB_SUCCESS; - return (&host); + return (host); } int @@ -170,14 +172,58 @@ { const char *name; int af; + struct hostent *host; + char *hostbuf, *bp; + int hostbuflen; + u_int32_t *host_addr; struct hostent *p; char **cp; name = va_arg(ap, const char *); af = va_arg(ap, int); + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char*); + hostbuflen = va_arg(ap, int); + if(hostbuflen != 0 && hostbuf != NULL) { + host->h_aliases = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host->h_addr_list = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_addr_list + sizeof(char *[2]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host_addr = CAST_ALIGN(hostbuf, u_int32_t *); + bp = (char *)host_addr + sizeof(u_int32_t[4]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < BUFSIZ+1) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + } else { + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + host_addr = host_addr_s; + } + + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; + sethostent(0); - while ((p = gethostent()) != NULL) { + while ((p = gethostent_r(host, hostbuf, hostbuflen)) != NULL) { if (p->h_addrtype != af) continue; if (strcasecmp(p->h_name, name) == 0) @@ -198,14 +244,58 @@ { const char *addr; int len, af; + struct hostent *host; + char *hostbuf, *bp; + int hostbuflen; + u_int32_t *host_addr; struct hostent *p; addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char*); + hostbuflen = va_arg(ap, int); + + if(hostbuflen != 0 && hostbuf != NULL) { + host->h_aliases = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host->h_addr_list = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_addr_list + sizeof(char *[2]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + host_addr = CAST_ALIGN(hostbuf, u_int32_t *); + bp = (char *)host_addr + sizeof(u_int32_t[4]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < BUFSIZ+1) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NS_UNAVAIL); + } + } else { + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + host_addr = host_addr_s; + } + + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; sethostent(0); - while ((p = gethostent()) != NULL) + while ((p = gethostent_r(host, hostbuf, hostbuflen)) != NULL) if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; endhostent(); Index: src/lib/libc/net/gethostbynis.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbynis.c,v retrieving revision 1.15 diff -d -u -r1.15 gethostbynis.c --- src/lib/libc/net/gethostbynis.c 22 Mar 2002 21:52:29 -0000 1.15 +++ src/lib/libc/net/gethostbynis.c 10 Aug 2002 10:03:52 -0000 @@ -44,29 +44,63 @@ #include <rpcsvc/yp_prot.h> #include <rpcsvc/ypclnt.h> #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 - -extern int h_errno; +#include <resolv.h> #ifdef YP +static char hostbuf_s[8*1024]; +static u_char host_addr_s[16]; + +static char *h_addr_ptrs[2]; static char *host_aliases[MAXALIASES]; -static char hostaddr[MAXADDRS]; -static char *host_addrs[2]; +static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs }; static struct hostent * -_gethostbynis(name, map, af) +_gethostbynis(name, map, af, host, hostbuf, hostbuflen) const char *name; char *map; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; { - char *cp, **q; + char *bp, *cp, **q; char *result; int resultlen,size; - static struct hostent h; static char *domain = (char *)NULL; - static char ypbuf[YPMAXRECORD + 2]; + + if(hostbuflen != 0 && hostbuf != NULL) { + host->h_aliases = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_aliases + sizeof(char *[MAXALIASES]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NULL); + } + host->h_addr_list = CAST_ALIGN(hostbuf, char **); + bp = (char *)host->h_addr_list + sizeof(char *[2]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NULL); + } + host->h_addr_list[0] = hostbuf; + bp = (char *)host->h_addr_list[0] + sizeof(u_char[16]); + hostbuflen -= (bp - hostbuf); + hostbuf = bp; + if(hostbuflen < 0) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NULL); + } + } else { + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + host->h_addr_list[0] = host_addr_s; + } switch(af) { case AF_INET: @@ -90,27 +124,29 @@ h_errno = HOST_NOT_FOUND; return ((struct hostent *)NULL); } - - /* avoid potential memory leak */ - bcopy((char *)result, (char *)&ypbuf, resultlen); - ypbuf[resultlen] = '\0'; + if (resultlen > hostbuflen) { + h_errno = NO_RECOVERY; + errno = ERANGE; + return (NULL); + } + result[resultlen] = '\0'; + bcopy((char *)result, hostbuf, resultlen); free(result); - result = (char *)&ypbuf; + result = hostbuf; if ((cp = index(result, '\n'))) *cp = '\0'; cp = strpbrk(result, " \t"); *cp++ = '\0'; - h.h_addr_list = host_addrs; - h.h_addr = hostaddr; - *((u_long *)h.h_addr) = inet_addr(result); - h.h_length = size; - h.h_addrtype = AF_INET; + *((u_long *)host->h_addr_list[0]) = inet_addr(result); + host->h_addr_list[1] = NULL; + host->h_length = size; + host->h_addrtype = AF_INET; while (*cp == ' ' || *cp == '\t') cp++; - h.h_name = cp; - q = h.h_aliases = host_aliases; + host->h_name = cp; + q = host->h_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -119,14 +155,14 @@ cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) + if (q < &host->h_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; - return (&h); + return (host); } #endif /* YP */ @@ -135,7 +171,7 @@ _gethostbynisname(const char *name, int af) { #ifdef YP - return _gethostbynis(name, "hosts.byname", af); + return _gethostbynis(name, "hosts.byname", af, &host_s, NULL, 0); #else return NULL; #endif @@ -146,7 +182,7 @@ { #ifdef YP return _gethostbynis(inet_ntoa(*(struct in_addr *)addr), - "hosts.byaddr", af); + "hosts.byaddr", af, &host_s, NULL, 0); #else return NULL; #endif @@ -159,11 +195,18 @@ #ifdef YP const char *name; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; name = va_arg(ap, const char *); af = va_arg(ap, int); + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char *); + hostbuflen = va_arg(ap, int); - *(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af); + *(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af, + host, hostbuf, hostbuflen); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; #else return NS_UNAVAIL; @@ -177,12 +220,19 @@ const char *addr; int len; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); - - *(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af); + host = va_arg(ap, struct hostent *); + hostbuf = va_arg(ap, char *); + hostbuflen = va_arg(ap, int); + + *(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr), + "hosts.byaddr", af, host, hostbuf, hostbuflen); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; #else return NS_UNAVAIL; Index: src/lib/libc/net/gethostnamadr.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostnamadr.c,v retrieving revision 1.20 diff -d -u -r1.20 gethostnamadr.c --- src/lib/libc/net/gethostnamadr.c 22 Mar 2002 21:52:29 -0000 1.20 +++ src/lib/libc/net/gethostnamadr.c 10 Aug 2002 10:03:52 -0000 @@ -31,6 +31,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <errno.h> #include <stdio.h> #include <ctype.h> #include <string.h> @@ -46,6 +47,10 @@ extern int _dns_gethostbyaddr(void *, void *, va_list); extern int _nis_gethostbyaddr(void *, void *, va_list); +static char *h_addr_ptrs[MAXADDRS + 1]; +static char *host_aliases[MAXALIASES]; +static struct hostent host_s = { NULL, host_aliases, 0, 0, h_addr_ptrs }; + /* Host lookup order if nsswitch.conf is broken or nonexistant */ static const ns_src default_src[] = { { NSSRC_FILES, NS_SUCCESS }, @@ -53,25 +58,38 @@ { 0 } }; -struct hostent * -gethostbyname(const char *name) +int +gethostbyname_r(const char *name, struct hostent *resp, + char *buffer, int buflen, int *h_errnop) { - struct hostent *hp; + int rval; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - h_errno = NETDB_INTERNAL; - return (NULL); + *h_errnop = NO_RECOVERY; + return (NETDB_INTERNAL); } if (_res.options & RES_USE_INET6) { /* XXX */ - hp = gethostbyname2(name, AF_INET6); /* XXX */ - if (hp) /* XXX */ - return (hp); /* XXX */ + rval = gethostbyname2_r(name, AF_INET6, resp, + buffer, buflen, h_errnop); /* XXX */ + if (rval == 0) /* XXX */ + return (0); /* XXX */ } /* XXX */ - return (gethostbyname2(name, AF_INET)); + return (gethostbyname2_r(name, AF_INET, resp, + buffer, buflen, h_errnop)); } struct hostent * -gethostbyname2(const char *name, int type) +gethostbyname(const char *name) +{ + int rval; + + rval = gethostbyname_r(name, &host_s, NULL, 0, &h_errno); + return (rval == 0 ? &host_s : NULL); +} + +int +gethostbyname2_r(const char *name, int type, struct hostent *resp, + char *buffer, int buflen, int *h_errnop) { struct hostent *hp = 0; int rval; @@ -82,18 +100,29 @@ NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ { 0 } }; - + rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", - default_src, name, type); + default_src, name, type, resp, buffer, buflen); + *h_errnop = h_errno; if (rval != NS_SUCCESS) - return NULL; + return ((errno == 0) ? -1 : errno); /* Be paranoid */ else - return hp; + return (0); } struct hostent * -gethostbyaddr(const char *addr, int len, int type) +gethostbyname2(const char *name, int type) +{ + int rval; + + rval = gethostbyname2_r(name, type, &host_s, NULL, 0, &h_errno); + return (rval == 0 ? &host_s : NULL); +} + +int +gethostbyaddr_r(const char *addr, int len, int type, struct hostent *resp, + char *buffer, int buflen, int *h_errnop) { struct hostent *hp = 0; int rval; @@ -106,37 +135,28 @@ }; rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr", - default_src, addr, len, type); + default_src, addr, len, type, resp, buffer, buflen); + *h_errnop = h_errno; if (rval != NS_SUCCESS) - return NULL; + return ((errno == 0) ? -1 : errno); /* Be paranoid */ else - return hp; + return (0); } -struct hostent_data; - -/* - * Temporary function (not thread safe) - */ -int gethostbyaddr_r(const char *addr, int len, int type, - struct hostent *result, struct hostent_data *buffer) +struct hostent * +gethostbyaddr(const char *addr, int len, int type) { - struct hostent *hp; - int ret; - if ((hp = gethostbyaddr(addr, len, type)) == NULL) { - ret = -1; - } else { - memcpy(result, hp, sizeof(struct hostent)); - ret = 0; - } - return(ret); + int rval; + + rval = gethostbyaddr_r(addr, len, type, NULL, NULL, 0, &h_errno); + return (rval == 0 ? &host_s : NULL); } void -sethostent(stayopen) - int stayopen; +sethostent(int stayopen) { + _sethosthtent(stayopen); _sethostdnsent(stayopen); } @@ -144,6 +164,7 @@ void endhostent() { + _endhosthtent(); _endhostdnsent(); } Index: src/lib/libc/net/getnetbydns.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbydns.c,v retrieving revision 1.21 diff -d -u -r1.21 getnetbydns.c --- src/lib/libc/net/getnetbydns.c 26 Jun 2002 14:18:36 -0000 1.21 +++ src/lib/libc/net/getnetbydns.c 10 Aug 2002 10:03:52 -0000 @@ -82,11 +82,8 @@ #include "res_config.h" -extern int h_errno; - #define BYADDR 0 #define BYNAME 1 -#define MAXALIASES 35 #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ Index: src/lib/libc/net/getnetbyht.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbyht.c,v retrieving revision 1.10 diff -d -u -r1.10 getnetbyht.c --- src/lib/libc/net/getnetbyht.c 22 Mar 2002 21:52:29 -0000 1.10 +++ src/lib/libc/net/getnetbyht.c 10 Aug 2002 10:03:52 -0000 @@ -58,8 +58,7 @@ #include <string.h> #include <stdarg.h> #include <nsswitch.h> - -#define MAXALIASES 35 +#include <resolv.h> static FILE *netf; static char line[BUFSIZ+1]; Index: src/lib/libc/net/getnetbynis.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbynis.c,v retrieving revision 1.15 diff -d -u -r1.15 getnetbynis.c --- src/lib/libc/net/getnetbynis.c 22 Mar 2002 21:52:29 -0000 1.15 +++ src/lib/libc/net/getnetbynis.c 10 Aug 2002 10:03:52 -0000 @@ -44,9 +44,7 @@ #include <rpcsvc/yp_prot.h> #include <rpcsvc/ypclnt.h> #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 +#include <resolv.h> #ifdef YP static char *host_aliases[MAXALIASES]; Index: src/lib/libc/net/herror.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/herror.c,v retrieving revision 1.11 diff -d -u -r1.11 herror.c --- src/lib/libc/net/herror.c 22 Mar 2002 21:52:29 -0000 1.11 +++ src/lib/libc/net/herror.c 10 Aug 2002 10:03:52 -0000 @@ -71,8 +71,6 @@ }; int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; -int h_errno; - /* * herror -- * print the error indicated by the h_errno value. @@ -110,3 +108,19 @@ return (h_errlist[err]); return ("Unknown resolver error"); } + +#undef h_errno +int h_errno; + +/* + * Declare a weak reference in case the application is not linked + * with libpthread. + */ +__weak_reference(__h_errno_accessor_unthreaded, __h_errno_accessor); + +int * +__h_errno_accessor_unthreaded() +{ + return &h_errno; +} + Index: src/lib/libc/net/res_init.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_init.c,v retrieving revision 1.29 diff -d -u -r1.29 res_init.c --- src/lib/libc/net/res_init.c 22 Mar 2002 21:52:30 -0000 1.29 +++ src/lib/libc/net/res_init.c 10 Aug 2002 10:03:55 -0000 @@ -104,17 +104,6 @@ # define isascii(c) (!(c & 0200)) #endif -/* - * Resolver state default settings. - */ - -struct __res_state _res -# if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif - ; - -struct __res_state_ext _res_ext; /* * Set up default settings. If the configuration file exist, the values @@ -154,6 +143,9 @@ #ifndef RFC1535 int dots; #endif + + if(&_res_data==NULL) + return -1; /* * These three fields used to be statically initialized. This made @@ -582,3 +574,43 @@ */ #undef res_init __weak_reference(__res_init, res_init); + +/* + * Resolver state default settings. + */ + +#undef _res +#undef _res_ext +#undef _res_data + +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /* Motorola, et al. */ +# endif + ; + +struct __res_state_ext _res_ext; + +struct __res_data _res_data = { 0, -1, 0, 0, 0, NULL, NULL, NULL, 0, &_res, + &_res_ext }; + +/* + * Declare a weak reference in case the application is not linked + * with libpthread. + */ +__weak_reference(__res_data_accessor_unthreaded, __res_data_accessor); +__weak_reference(__res_accessor_unthreaded, __res_accessor); + +struct __res_data * +__res_data_accessor_unthreaded() +{ + + return &_res_data; +} + +struct __res_state * +__res_accessor_unthreaded() +{ + + return _res_data.res; +} Index: src/lib/libc/net/res_query.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_query.c,v retrieving revision 1.23 diff -d -u -r1.23 res_query.c --- src/lib/libc/net/res_query.c 7 Jul 2002 11:28:28 -0000 1.23 +++ src/lib/libc/net/res_query.c 10 Aug 2002 10:03:55 -0000 @@ -87,6 +87,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "res_config.h" @@ -374,11 +375,20 @@ hostalias(name) const char *name; { + static char abuf[MAXDNAME]; + return (hostalias_r(name, abuf, sizeof abuf)); +} + +const char * +hostalias_r(name, abuf, len) + const char *name; + char *abuf; + int len; +{ char *cp1, *cp2; FILE *fp; char *file; char buf[BUFSIZ]; - static char abuf[MAXDNAME]; if (_res.options & RES_NOALIASES) return (NULL); @@ -402,8 +412,8 @@ break; for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2) ; - abuf[sizeof(abuf) - 1] = *cp2 = '\0'; - strncpy(abuf, cp1, sizeof(abuf) - 1); + abuf[len - 1] = *cp2 = '\0'; + strncpy(abuf, cp1, len - 1); fclose(fp); return (abuf); } Index: src/lib/libc/net/res_send.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_send.c,v retrieving revision 1.45 diff -d -u -r1.45 res_send.c --- src/lib/libc/net/res_send.c 1 Apr 2002 16:09:45 -0000 1.45 +++ src/lib/libc/net/res_send.c 10 Aug 2002 10:03:56 -0000 @@ -102,13 +102,6 @@ #include "res_config.h" -static int s = -1; /* socket used for communications */ -static int connected = 0; /* is the socket connected */ -static int vc = 0; /* is the socket a virtual circuit? */ -static int af = 0; /* address family of socket */ -static res_send_qhook Qhook = NULL; -static res_send_rhook Rhook = NULL; - #define CAN_RECONNECT 1 @@ -170,7 +163,7 @@ res_send_qhook hook; { - Qhook = hook; + _res_data.Qhook = hook; } void @@ -178,7 +171,7 @@ res_send_rhook hook; { - Rhook = hook; + _res_data.Rhook = hook; } static struct sockaddr * get_nsaddr(size_t); @@ -406,13 +399,13 @@ goto next_ns; } - if (Qhook) { + if (_res_data.Qhook) { int done = 0, loops = 0; do { res_sendhookact act; - act = (*Qhook)((struct sockaddr_in **)&nsap, + act = (*_res_data.Qhook)((struct sockaddr_in **)&nsap, &buf, &buflen, ans, anssiz, &resplen); switch (act) { @@ -457,14 +450,14 @@ */ try = _res.retry; truncated = 0; - if (s < 0 || !vc || hp->opcode == ns_o_update || - af != nsap->sa_family) { - if (s >= 0) + if (_res_data.s < 0 || !_res_data.vc || hp->opcode == ns_o_update || + _res_data.af != nsap->sa_family) { + if (_res_data.s >= 0) res_close(); - af = nsap->sa_family; - s = _socket(af, SOCK_STREAM, 0); - if (s < 0) { + _res_data.af = nsap->sa_family; + _res_data.s = _socket(_res_data.af, SOCK_STREAM, 0); + if (_res_data.s < 0) { terrno = errno; Perror(stderr, "socket(vc)", errno); badns |= (1 << ns); @@ -472,7 +465,7 @@ goto next_ns; } errno = 0; - if (_connect(s, nsap, salen) < 0) { + if (_connect(_res_data.s, nsap, salen) < 0) { terrno = errno; Aerror(stderr, "connect/vc", errno, nsap); @@ -480,7 +473,7 @@ res_close(); goto next_ns; } - vc = 1; + _res_data.vc = 1; } /* * Send length & message @@ -490,7 +483,7 @@ iov[0].iov_len = INT16SZ; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; - if (_writev(s, iov, 2) != (INT16SZ + buflen)) { + if (_writev(_res_data.s, iov, 2) != (INT16SZ + buflen)) { terrno = errno; Perror(stderr, "write failed", errno); badns |= (1 << ns); @@ -503,7 +496,7 @@ read_len: cp = ans; len = INT16SZ; - while ((n = _read(s, (char *)cp, (int)len)) > 0) { + while ((n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; if ((len -= n) <= 0) break; @@ -551,7 +544,7 @@ } cp = ans; while (len != 0 && - (n = _read(s, (char *)cp, (int)len)) > 0) { + (n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } @@ -574,7 +567,7 @@ n = (len > sizeof(junk) ? sizeof(junk) : len); - if ((n = _read(s, junk, n)) > 0) + if ((n = _read(_res_data.s, junk, n)) > 0) len -= n; else break; @@ -604,12 +597,13 @@ struct sockaddr_storage from; int fromlen; - if (s < 0 || vc || af != nsap->sa_family) { - if (vc) + if (_res_data.s < 0 || _res_data.vc || + _res_data.af != nsap->sa_family) { + if (_res_data.vc) res_close(); - af = nsap->sa_family; - s = _socket(af, SOCK_DGRAM, 0); - if (s < 0) { + _res_data.af = nsap->sa_family; + _res_data.s = _socket(_res_data.af, SOCK_DGRAM, 0); + if (_res_data.s < 0) { #ifndef CAN_RECONNECT bad_dg_sock: #endif @@ -619,7 +613,7 @@ res_close(); goto next_ns; } - connected = 0; + _res_data.connected = 0; } #ifndef CANNOT_CONNECT_DGRAM /* @@ -650,8 +644,8 @@ * Connect only if we are sure we won't * receive a response from another server. */ - if (!connected) { - if (_connect(s, nsap, salen) < 0) { + if (!_res_data.connected) { + if (_connect(_res_data.s, nsap, salen) < 0) { Aerror(stderr, "connect(dg)", errno, nsap); @@ -659,9 +653,9 @@ res_close(); goto next_ns; } - connected = 1; + _res_data.connected = 1; } - if (send(s, (char*)buf, buflen, 0) != buflen) { + if (send(_res_data.s, (char*)buf, buflen, 0) != buflen) { Perror(stderr, "send", errno); badns |= (1 << ns); res_close(); @@ -672,7 +666,7 @@ * Disconnect if we want to listen * for responses from more than one server. */ - if (connected) { + if (_res_data.connected) { #ifdef CAN_RECONNECT /* XXX: any errornous address */ struct sockaddr_in no_addr; @@ -680,24 +674,24 @@ no_addr.sin_family = AF_INET; no_addr.sin_addr.s_addr = INADDR_ANY; no_addr.sin_port = 0; - (void) _connect(s, + (void) _connect(_res_data.s, (struct sockaddr *) &no_addr, sizeof no_addr); #else - int s1 = _socket(af, SOCK_DGRAM,0); + int s1 = _socket(_res_data.af, SOCK_DGRAM,0); if (s1 < 0) goto bad_dg_sock; - (void)_dup2(s1, s); + (void)_dup2(s1, _res_data.s); (void)_close(s1); Dprint(_res.options & RES_DEBUG, (stdout, ";; new DG socket\n")) #endif /* CAN_RECONNECT */ - connected = 0; + _res_data.connected = 0; errno = 0; } #endif /* !CANNOT_CONNECT_DGRAM */ - if (_sendto(s, (char*)buf, buflen, 0, + if (_sendto(_res_data.s, (char*)buf, buflen, 0, nsap, salen) != buflen) { Aerror(stderr, "sendto", errno, nsap); badns |= (1 << ns); @@ -722,13 +716,13 @@ (void) gettimeofday(&ctv, NULL); timeradd(&timeout, &ctv, &timeout); wait: - if (s < 0) { + if (_res_data.s < 0) { Perror(stderr, "s out-of-bounds", EMFILE); res_close(); goto next_ns; } - EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0); + EV_SET(&kv, _res_data.s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0); n = _kevent(kq, &kv, 1, &kv, 1, &ts); if (n < 0) { @@ -757,7 +751,7 @@ } errno = 0; fromlen = sizeof(from); - resplen = _recvfrom(s, (char*)ans, anssiz, 0, + resplen = _recvfrom(_res_data.s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); @@ -862,13 +856,13 @@ !(_res.options & RES_STAYOPEN)) { res_close(); } - if (Rhook) { + if (_res_data.Rhook) { int done = 0, loops = 0; do { res_sendhookact act; - act = (*Rhook)((struct sockaddr_in *)nsap, + act = (*_res_data.Rhook)((struct sockaddr_in *)nsap, buf, buflen, ans, anssiz, &resplen); switch (act) { @@ -920,12 +914,12 @@ void res_close() { - if (s >= 0) { - (void)_close(s); - s = -1; - connected = 0; - vc = 0; - af = 0; + if (_res_data.s >= 0) { + (void)_close(_res_data.s); + _res_data.s = -1; + _res_data.connected = 0; + _res_data.vc = 0; + _res_data.af = 0; } } Index: src/lib/libc_r/sys/Makefile.inc =================================================================== RCS file: /home/ncvs/src/lib/libc_r/sys/Makefile.inc,v retrieving revision 1.10 diff -d -u -r1.10 Makefile.inc --- src/lib/libc_r/sys/Makefile.inc 28 Aug 1999 00:03:13 -0000 1.10 +++ src/lib/libc_r/sys/Makefile.inc 10 Aug 2002 10:03:56 -0000 @@ -2,5 +2,5 @@ .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS+= uthread_error.c _atomic_lock.S +SRCS+= uthread_error.c uthread_resolv.c _atomic_lock.S Index: src/lib/libc_r/sys/uthread_resolv.c =================================================================== RCS file: src/lib/libc_r/sys/uthread_resolv.c diff -N src/lib/libc_r/sys/uthread_resolv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/lib/libc_r/sys/uthread_resolv.c 10 Aug 2002 10:03:56 -0000 @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2001 Alexandr Litvin <archer@whichever.org> + * 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. + * + * 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. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <netdb.h> +#include <stdlib.h> +#include <pthread.h> +#include "pthread_private.h" + +#undef h_errno +#undef _res +#undef _res_ext +#undef _res_data + +extern int h_errno; +extern struct __res_data _res_data; + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_key_t key; + + +static void +__res_data_destroy(void *p) +{ + struct __res_data *_res_datap = (struct __res_data *)p; + + if(_res_datap->res) + free(_res_datap->res); + if(_res_datap->res_ext) + free(_res_datap->res_ext); + if(_res_datap->s >= 0) + close(_res_datap->s); + if(_res_datap->hostf) + fclose(_res_datap->hostf); + free(_res_datap); +} + +static void +__res_data_init() +{ + + pthread_key_create(&key, __res_data_destroy); +} + +struct __res_data * +__res_data_accessor() +{ + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + _res_datap = &_res_data; + } else { + pthread_once(&once, __res_data_init); + _res_datap = (struct __res_data *)pthread_getspecific(key); + if(_res_datap==NULL) { + _res_datap = malloc(sizeof(struct __res_data)); + if(_res_datap==NULL) + return (NULL); + bzero(_res_datap, sizeof(struct __res_data)); + _res_datap->res = malloc(sizeof(struct __res_state)); + if(_res_datap->res == NULL) { + free(_res_datap); + return (NULL); + } + bzero(_res_datap->res, sizeof(struct __res_state)); + _res_datap->res_ext = + malloc(sizeof(struct __res_state_ext)); + if(_res_datap->res_ext == NULL) { + free(_res_datap->res); + free(_res_datap); + return (NULL); + } + bzero(_res_datap->res_ext, + sizeof(struct __res_state_ext)); + _res_datap->s = -1; + pthread_setspecific(key, _res_datap); + } + } + return (_res_datap); +} + +static struct __res_state dummy_res; +static int dummy_h_errno; + +struct __res_state * +__res_accessor() +{ + struct __res_state *resp; + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + resp = _res_data.res; + } else { + _res_datap = __res_data_accessor(); + if(_res_datap) { + resp = _res_datap->res; + } else { + dummy_res.options = RES_DEFAULT; + resp = &dummy_res; + } + } + return (resp); +} + +int * +__h_errno_accessor() +{ + int *h_errnop; + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + h_errnop = &h_errno; + } else { + _res_datap = __res_data_accessor(); + if(_res_datap) { + h_errnop = &_res_datap->h_errno_res; + } else { + dummy_h_errno = NETDB_INTERNAL; + h_errnop = &dummy_h_errno; + } + } + return (h_errnop); +} --------------051496A982500B2DDF1E4FCD Content-Type: text/plain; charset=koi8-r; name="resolv_r-2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="resolv_r-2.diff" Index: src/include/netdb.h =================================================================== RCS file: /home/ncvs/src/include/netdb.h,v retrieving revision 1.24 diff -d -u -r1.24 netdb.h --- src/include/netdb.h 26 Jun 2002 08:18:42 -0000 1.24 +++ src/include/netdb.h 12 Aug 2002 09:48:11 -0000 @@ -82,7 +82,10 @@ #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" -extern int h_errno; +__BEGIN_DECLS +int * __h_errno_accessor(void); +__END_DECLS +#define h_errno (* __h_errno_accessor()) /* * Structures returned by network data base library. All addresses are Index: src/include/resolv.h =================================================================== RCS file: /home/ncvs/src/include/resolv.h,v retrieving revision 1.21 diff -d -u -r1.21 resolv.h --- src/include/resolv.h 23 Mar 2002 17:24:53 -0000 1.21 +++ src/include/resolv.h 12 Aug 2002 09:48:11 -0000 @@ -62,6 +62,7 @@ #include <sys/cdefs.h> #include <sys/socket.h> #include <stdio.h> +#include <netdb.h> /* * Revision information. This is the release date in YYYYMMDD format. @@ -90,6 +91,8 @@ #define MAXDFLSRCH 3 /* # default domain levels to try */ #define MAXDNSRCH 6 /* max # domains in search path */ #define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ +#define MAXALIASES 35 /* max # of aliases to return */ +#define MAXADDRS 35 /* max # of addresses to return */ #define RES_TIMEOUT 5 /* min. seconds between retries */ #define MAXRESOLVSORT 10 /* number of net to sort on */ @@ -198,10 +201,6 @@ char * humanname; /* Its fun name, like "mail exchanger" */ }; -extern struct __res_state _res; -/* for INET6 */ -extern struct __res_state_ext _res_ext; - extern const struct res_sym __p_class_syms[]; extern const struct res_sym __p_type_syms[]; @@ -224,6 +223,7 @@ #define fp_query __fp_query #define fp_nquery __fp_nquery #define hostalias __hostalias +#define hostalias_r __hostalias_r #define putlong __putlong #define putshort __putshort #define p_class __p_class @@ -273,6 +273,7 @@ void fp_query(const u_char *, FILE *); void fp_nquery(const u_char *, int, FILE *); const char * hostalias(const char *); +const char * hostalias_r(const char *, char *, int); void putlong(u_int32_t, u_char *); void putshort(u_int16_t, u_char *); const char * p_class(int); @@ -315,5 +316,35 @@ void res_freeupdrec(ns_updrec *); #endif __END_DECLS + +struct __res_data { + int h_errno_res; + int s; /* socket used for communications */ + int connected : 1; /* is the socket connected */ + int vc : 1; /* is the socket a virtual circuit? */ + int af; /* address family of socket */ + res_send_qhook Qhook; + res_send_rhook Rhook; + FILE* hostf; + int stayopen; + struct hostent host; + char *hostbuf; + int hostbuflen; + u_char *host_addr; + int host_addrlen; + struct __res_state *res; + struct __res_state_ext *res_ext; +}; + +__BEGIN_DECLS +u_int16_t _getshort(const u_char *); +u_int32_t _getlong(const u_char *); +struct __res_data * __res_data_accessor(void); +struct __res_state * __res_accessor(void); +__END_DECLS +#define _res_data (* __res_data_accessor()) +#define _res (* __res_accessor()) +/* for INET6 */ +#define _res_ext (* (__res_data_accessor()->res_ext)) #endif /* !_RESOLV_H_ */ Index: src/lib/libc/net/getaddrinfo.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getaddrinfo.c,v retrieving revision 1.28 diff -d -u -r1.28 getaddrinfo.c --- src/lib/libc/net/getaddrinfo.c 2 Aug 2002 11:58:48 -0000 1.28 +++ src/lib/libc/net/getaddrinfo.c 12 Aug 2002 09:48:17 -0000 @@ -1673,7 +1673,6 @@ /* resolver logic */ extern const char *__hostalias(const char *); -extern int h_errno; /* * Formulate a normal query, send, and await answer. Index: src/lib/libc/net/gethostbydns.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbydns.c,v retrieving revision 1.36 diff -d -u -r1.36 gethostbydns.c --- src/lib/libc/net/gethostbydns.c 26 Jun 2002 14:18:36 -0000 1.36 +++ src/lib/libc/net/gethostbydns.c 12 Aug 2002 09:48:17 -0000 @@ -68,6 +68,7 @@ #include <arpa/nameser.h> #include <stdio.h> +#include <stdlib.h> #include <unistd.h> #include <string.h> #include <netdb.h> @@ -82,19 +83,9 @@ #define SPRINTF(x) ((size_t)sprintf x) -#define MAXALIASES 35 -#define MAXADDRS 35 - static const char AskedForGot[] = "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; -static char *h_addr_ptrs[MAXADDRS + 1]; - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[8*1024]; -static u_char host_addr[16]; /* IPv4 or IPv6 */ - #ifdef RESOLVSORT static void addrsort(char **, int); #endif @@ -119,7 +110,6 @@ char ac; } align; -extern int h_errno; int _dns_ttl_; #ifdef DEBUG @@ -157,11 +147,14 @@ } while (0) static struct hostent * -gethostanswer(answer, anslen, qname, qtype) +gethostanswer(answer, anslen, qname, qtype, host, hostbuf, hostbuflen) const querybuf *answer; int anslen; const char *qname; int qtype; + struct hostent *host; + char *hostbuf; + int hostbuflen; { const HEADER *hp; const u_char *cp; @@ -176,7 +169,7 @@ int (*name_ok)(const char *); tname = qname; - host.h_name = NULL; + host->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: @@ -197,7 +190,7 @@ ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; - ep = hostbuf + sizeof hostbuf; + ep = hostbuf + hostbuflen; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { @@ -220,17 +213,15 @@ h_errno = NO_RECOVERY; return (NULL); } - host.h_name = bp; + host->h_name = bp; bp += n; /* The qname can be abbreviated, but h_name is now absolute. */ - qname = host.h_name; + qname = host->h_name; } - ap = host_aliases; + ap = host->h_aliases; *ap = NULL; - host.h_aliases = host_aliases; - hap = h_addr_ptrs; + hap = host->h_addr_list; *hap = NULL; - host.h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; @@ -259,7 +250,7 @@ continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { - if (ap >= &host_aliases[MAXALIASES-1]) + if (ap >= &host->h_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { @@ -286,7 +277,7 @@ continue; } strcpy(bp, tbuf); - host.h_name = bp; + host->h_name = bp; bp += n; continue; } @@ -341,8 +332,8 @@ return (NULL); } if (!haveanswer) - host.h_name = bp; - else if (ap < &host_aliases[MAXALIASES-1]) + host->h_name = bp; + else if (ap < &host->h_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; @@ -356,7 +347,7 @@ } break; #else - host.h_name = bp; + host->h_name = bp; if (_res.options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { @@ -364,27 +355,27 @@ break; } bp += n; - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); } h_errno = NETDB_SUCCESS; - return (&host); + return (host); #endif case T_A: case T_AAAA: - if (strcasecmp(host.h_name, bp) != 0) { + if (strcasecmp(host->h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); + AskedForGot, host->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } - if (n != host.h_length) { + if (n != host->h_length) { cp += n; continue; } if (!haveanswer) { int nn; - host.h_name = bp; + host->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; } @@ -396,7 +387,7 @@ had_error++; continue; } - if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (hap >= &host->h_addr_list[MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", MAXADDRS); @@ -430,57 +421,40 @@ * address in that case, not some random one */ if (_res.nsort && haveanswer > 1 && qtype == T_A) - addrsort(h_addr_ptrs, haveanswer); + addrsort(host->h_addr_list, haveanswer); # endif /*RESOLVSORT*/ - if (!host.h_name) { + if (!host->h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > ep - bp || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); - host.h_name = bp; + host->h_name = bp; bp += n; } if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); h_errno = NETDB_SUCCESS; - return (&host); + return (host); } no_recovery: h_errno = NO_RECOVERY; return (NULL); } -struct hostent * -__dns_getanswer(answer, anslen, qname, qtype) - const char *answer; - int anslen; - const char *qname; - int qtype; -{ - switch(qtype) { - case T_AAAA: - host.h_addrtype = AF_INET6; - host.h_length = IN6ADDRSZ; - break; - case T_A: - default: - host.h_addrtype = AF_INET; - host.h_length = INADDRSZ; - break; - } - - return(gethostanswer((const querybuf *)answer, anslen, qname, qtype)); -} - int _dns_gethostbyname(void *rval, void *cb_data, va_list ap) { const char *name; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; + u_char *host_addr; querybuf buf; const char *cp; char *bp, *ep; int n, size, type, len; + char abuf[MAXDNAME]; name = va_arg(ap, const char *); af = va_arg(ap, int); @@ -491,6 +465,11 @@ return NS_UNAVAIL; } + host = &_res_data.host; + hostbuf = _res_data.hostbuf; + hostbuflen = _res_data.hostbuflen; + host_addr = _res_data.host_addr; + switch (af) { case AF_INET: size = INADDRSZ; @@ -506,15 +485,15 @@ return NS_UNAVAIL; } - host.h_addrtype = af; - host.h_length = size; + host->h_addrtype = af; + host->h_length = size; /* * if there aren't any dots, it could be a user-level alias. * this is also done in res_query() since we are not the only * function that looks up host names. */ - if (!strchr(name, '.') && (cp = __hostalias(name))) + if (!strchr(name, '.') && (cp = __hostalias_r(name, abuf, sizeof abuf))) name = cp; /* @@ -538,17 +517,15 @@ strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; - ep = hostbuf + sizeof hostbuf; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; + ep = hostbuf + hostbuflen; + host->h_name = hostbuf; + host->h_aliases[0] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; if (_res.options & RES_USE_INET6) - _map_v4v6_hostent(&host, &bp, &ep); + _map_v4v6_hostent(host, &bp, &ep); h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; + *(struct hostent **)rval = host; return NS_SUCCESS; } if (!isdigit((unsigned char)*cp) && *cp != '.') @@ -572,15 +549,13 @@ strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; - len = sizeof hostbuf - MAXDNAME; - host.h_name = hostbuf; - host.h_aliases = host_aliases; - host_aliases[0] = NULL; - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; + len = hostbuflen - MAXDNAME; + host->h_name = hostbuf; + host->h_aliases[0] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; h_errno = NETDB_SUCCESS; - *(struct hostent **)rval = &host; + *(struct hostent **)rval = host; return NS_SUCCESS; } if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') @@ -591,7 +566,8 @@ dprintf("res_search failed (%d)\n", n); return NS_UNAVAIL; } - *(struct hostent **)rval = gethostanswer(&buf, n, name, type); + *(struct hostent **)rval = gethostanswer(&buf, n, name, type, + host, hostbuf, hostbuflen); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } @@ -600,6 +576,9 @@ { const char *addr; /* XXX should have been def'd as u_char! */ int len, af; + struct hostent *host; + char *hostbuf; + int hostbuflen; const u_char *uaddr; static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; @@ -607,6 +586,7 @@ querybuf buf; struct hostent *hp; char qbuf[MAXDNAME+1], *qp; + u_char *host_addr; #ifdef SUNSECURITY struct hostent *rhp; char **haddr; @@ -618,13 +598,19 @@ uaddr = (const u_char *)addr; len = va_arg(ap, int); af = va_arg(ap, int); - + *(struct hostent **)rval = NULL; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return NS_UNAVAIL; } + + host = &_res_data.host; + hostbuf = _res_data.hostbuf; + hostbuflen = _res_data.hostbuflen; + host_addr = _res_data.host_addr; + if (af == AF_INET6 && len == IN6ADDRSZ && (!bcmp(uaddr, mapped, sizeof mapped) || !bcmp(uaddr, tunnelled, sizeof tunnelled))) { @@ -680,7 +666,8 @@ dprintf("static buffer is too small (%d)\n", n); return NS_UNAVAIL; } - if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR))) + if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR, host, hostbuf, + hostbuflen))) return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ #ifdef SUNSECURITY if (af == AF_INET) { @@ -717,8 +704,8 @@ hp->h_addrtype = af; hp->h_length = len; bcopy(addr, host_addr, len); - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; + host->h_addr_list[0] = (char *)host_addr; + host->h_addr_list[1] = NULL; if (af == AF_INET && (_res.options & RES_USE_INET6)) { _map_v4v6_address((char*)host_addr, (char*)host_addr); hp->h_addrtype = AF_INET6; Index: src/lib/libc/net/gethostbyht.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbyht.c,v retrieving revision 1.16 diff -d -u -r1.16 gethostbyht.c --- src/lib/libc/net/gethostbyht.c 22 Mar 2002 21:52:29 -0000 1.16 +++ src/lib/libc/net/gethostbyht.c 12 Aug 2002 09:48:20 -0000 @@ -62,6 +62,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <errno.h> #include <stdio.h> #include <ctype.h> #include <string.h> @@ -70,33 +71,35 @@ #include <arpa/nameser.h> /* XXX */ #include <resolv.h> /* XXX */ -#define MAXALIASES 35 - -static struct hostent host; -static char *host_aliases[MAXALIASES]; -static char hostbuf[BUFSIZ+1]; -static FILE *hostf = NULL; -static u_int32_t host_addr[4]; /* IPv4 or IPv6 */ -static char *h_addr_ptrs[2]; -static int stayopen = 0; - void _sethosthtent(f) int f; { - if (!hostf) - hostf = fopen(_PATH_HOSTS, "r" ); + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return; + } + + if (!_res_data.hostf) + _res_data.hostf = fopen(_PATH_HOSTS, "r" ); else - rewind(hostf); - stayopen = f; + rewind(_res_data.hostf); + _res_data.stayopen = f; } void _endhosthtent() { - if (hostf && !stayopen) { - (void) fclose(hostf); - hostf = NULL; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return; + } + + if (_res_data.hostf && !_res_data.stayopen) { + (void) fclose(_res_data.hostf); + _res_data.hostf = NULL; } } @@ -106,13 +109,27 @@ char *p; char *cp, **q; int af, len; + struct hostent *host; + char *hostbuf; + int hostbuflen; - if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return NULL; + } + + host = &_res_data.host; + hostbuf = _res_data.hostbuf; + hostbuflen = _res_data.hostbuflen; + host->h_addr_list[0] = _res_data.host_addr; + host->h_addr_list[1] = NULL; + + if (!_res_data.hostf && !(_res_data.hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } again: - if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { + if (!(p = fgets(hostbuf, hostbuflen, _res_data.hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); } @@ -124,12 +141,12 @@ if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; - if (inet_pton(AF_INET6, p, host_addr) > 0) { + if (inet_pton(AF_INET6, p, host->h_addr_list[0]) > 0) { af = AF_INET6; len = IN6ADDRSZ; - } else if (inet_pton(AF_INET, p, host_addr) > 0) { + } else if (inet_pton(AF_INET, p, host->h_addr_list[0]) > 0) { if (_res.options & RES_USE_INET6) { - _map_v4v6_address((char*)host_addr, (char*)host_addr); + _map_v4v6_address(host->h_addr_list[0], host->h_addr_list[0]); af = AF_INET6; len = IN6ADDRSZ; } else { @@ -139,15 +156,12 @@ } else { goto again; } - h_addr_ptrs[0] = (char *)host_addr; - h_addr_ptrs[1] = NULL; - host.h_addr_list = h_addr_ptrs; - host.h_length = len; - host.h_addrtype = af; + host->h_length = len; + host->h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; - host.h_name = cp; - q = host.h_aliases = host_aliases; + host->h_name = cp; + q = host->h_aliases; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; while (cp && *cp) { @@ -155,14 +169,14 @@ cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) + if (q < &host->h_aliases[MAXALIASES - 1]) *q++ = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } *q = NULL; h_errno = NETDB_SUCCESS; - return (&host); + return (host); } int @@ -175,7 +189,7 @@ name = va_arg(ap, const char *); af = va_arg(ap, int); - + sethostent(0); while ((p = gethostent()) != NULL) { if (p->h_addrtype != af) Index: src/lib/libc/net/gethostbynis.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostbynis.c,v retrieving revision 1.15 diff -d -u -r1.15 gethostbynis.c --- src/lib/libc/net/gethostbynis.c 22 Mar 2002 21:52:29 -0000 1.15 +++ src/lib/libc/net/gethostbynis.c 12 Aug 2002 09:48:20 -0000 @@ -44,16 +44,9 @@ #include <rpcsvc/yp_prot.h> #include <rpcsvc/ypclnt.h> #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 - -extern int h_errno; +#include <resolv.h> #ifdef YP -static char *host_aliases[MAXALIASES]; -static char hostaddr[MAXADDRS]; -static char *host_addrs[2]; static struct hostent * _gethostbynis(name, map, af) @@ -64,9 +57,20 @@ char *cp, **q; char *result; int resultlen,size; - static struct hostent h; static char *domain = (char *)NULL; - static char ypbuf[YPMAXRECORD + 2]; + struct hostent *host; + char *hostbuf; + int hostbuflen; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return NULL; + } + + host = &_res_data.host; + hostbuf = _res_data.hostbuf; + hostbuflen = _res_data.hostbuflen; + host->h_addr_list[0] = _res_data.host_addr; switch(af) { case AF_INET: @@ -90,27 +94,29 @@ h_errno = HOST_NOT_FOUND; return ((struct hostent *)NULL); } - - /* avoid potential memory leak */ - bcopy((char *)result, (char *)&ypbuf, resultlen); - ypbuf[resultlen] = '\0'; + if (resultlen > hostbuflen) { + h_errno = NETDB_INTERNAL; + errno = ERANGE; + return (NULL); + } + result[resultlen] = '\0'; + bcopy((char *)result, hostbuf, resultlen); free(result); - result = (char *)&ypbuf; + result = hostbuf; if ((cp = index(result, '\n'))) *cp = '\0'; cp = strpbrk(result, " \t"); *cp++ = '\0'; - h.h_addr_list = host_addrs; - h.h_addr = hostaddr; - *((u_long *)h.h_addr) = inet_addr(result); - h.h_length = size; - h.h_addrtype = AF_INET; + *((u_long *)host->h_addr_list[0]) = inet_addr(result); + host->h_addr_list[1] = NULL; + host->h_length = size; + host->h_addrtype = AF_INET; while (*cp == ' ' || *cp == '\t') cp++; - h.h_name = cp; - q = h.h_aliases = host_aliases; + host->h_name = cp; + q = host->h_aliases; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; @@ -119,14 +125,14 @@ cp++; continue; } - if (q < &host_aliases[MAXALIASES - 1]) + if (q < &host->h_aliases[MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; - return (&h); + return (host); } #endif /* YP */ @@ -163,6 +169,11 @@ name = va_arg(ap, const char *); af = va_arg(ap, int); + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return NS_UNAVAIL; + } + *(struct hostent **)rval = _gethostbynis(name, "hosts.byname", af); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; #else @@ -181,8 +192,14 @@ addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); - - *(struct hostent **)rval =_gethostbynis(inet_ntoa(*(struct in_addr *)addr),"hosts.byaddr", af); + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + h_errno = NETDB_INTERNAL; + return NS_UNAVAIL; + } + + *(struct hostent **)rval = _gethostbynis( + inet_ntoa(*(struct in_addr *)addr), "hosts.byaddr", af); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; #else return NS_UNAVAIL; Index: src/lib/libc/net/gethostnamadr.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/gethostnamadr.c,v retrieving revision 1.20 diff -d -u -r1.20 gethostnamadr.c --- src/lib/libc/net/gethostnamadr.c 22 Mar 2002 21:52:29 -0000 1.20 +++ src/lib/libc/net/gethostnamadr.c 12 Aug 2002 09:48:20 -0000 @@ -31,6 +31,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> +#include <errno.h> #include <stdio.h> #include <ctype.h> #include <string.h> @@ -82,7 +83,7 @@ NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */ { 0 } }; - + rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", default_src, name, type); @@ -114,29 +115,10 @@ return hp; } -struct hostent_data; - -/* - * Temporary function (not thread safe) - */ -int gethostbyaddr_r(const char *addr, int len, int type, - struct hostent *result, struct hostent_data *buffer) -{ - struct hostent *hp; - int ret; - if ((hp = gethostbyaddr(addr, len, type)) == NULL) { - ret = -1; - } else { - memcpy(result, hp, sizeof(struct hostent)); - ret = 0; - } - return(ret); -} - void -sethostent(stayopen) - int stayopen; +sethostent(int stayopen) { + _sethosthtent(stayopen); _sethostdnsent(stayopen); } @@ -144,6 +126,7 @@ void endhostent() { + _endhosthtent(); _endhostdnsent(); } Index: src/lib/libc/net/getnetbydns.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbydns.c,v retrieving revision 1.21 diff -d -u -r1.21 getnetbydns.c --- src/lib/libc/net/getnetbydns.c 26 Jun 2002 14:18:36 -0000 1.21 +++ src/lib/libc/net/getnetbydns.c 12 Aug 2002 09:48:20 -0000 @@ -82,11 +82,8 @@ #include "res_config.h" -extern int h_errno; - #define BYADDR 0 #define BYNAME 1 -#define MAXALIASES 35 #if PACKETSZ > 1024 #define MAXPACKET PACKETSZ Index: src/lib/libc/net/getnetbyht.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbyht.c,v retrieving revision 1.10 diff -d -u -r1.10 getnetbyht.c --- src/lib/libc/net/getnetbyht.c 22 Mar 2002 21:52:29 -0000 1.10 +++ src/lib/libc/net/getnetbyht.c 12 Aug 2002 09:48:20 -0000 @@ -58,8 +58,7 @@ #include <string.h> #include <stdarg.h> #include <nsswitch.h> - -#define MAXALIASES 35 +#include <resolv.h> static FILE *netf; static char line[BUFSIZ+1]; Index: src/lib/libc/net/getnetbynis.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/getnetbynis.c,v retrieving revision 1.15 diff -d -u -r1.15 getnetbynis.c --- src/lib/libc/net/getnetbynis.c 22 Mar 2002 21:52:29 -0000 1.15 +++ src/lib/libc/net/getnetbynis.c 12 Aug 2002 09:48:20 -0000 @@ -44,9 +44,7 @@ #include <rpcsvc/yp_prot.h> #include <rpcsvc/ypclnt.h> #endif - -#define MAXALIASES 35 -#define MAXADDRS 35 +#include <resolv.h> #ifdef YP static char *host_aliases[MAXALIASES]; Index: src/lib/libc/net/herror.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/herror.c,v retrieving revision 1.11 diff -d -u -r1.11 herror.c --- src/lib/libc/net/herror.c 22 Mar 2002 21:52:29 -0000 1.11 +++ src/lib/libc/net/herror.c 12 Aug 2002 09:48:20 -0000 @@ -71,8 +71,6 @@ }; int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; -int h_errno; - /* * herror -- * print the error indicated by the h_errno value. @@ -104,9 +102,26 @@ hstrerror(err) int err; { + if (err < 0) return ("Resolver internal error"); else if (err < h_nerr) return (h_errlist[err]); return ("Unknown resolver error"); +} + +#undef h_errno +int h_errno; + +/* + * Declare a weak reference in case the application is not linked + * with libpthread. + */ +__weak_reference(__h_errno_accessor_unthreaded, __h_errno_accessor); + +int * +__h_errno_accessor_unthreaded() +{ + + return &h_errno; } Index: src/lib/libc/net/res_init.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_init.c,v retrieving revision 1.29 diff -d -u -r1.29 res_init.c --- src/lib/libc/net/res_init.c 22 Mar 2002 21:52:30 -0000 1.29 +++ src/lib/libc/net/res_init.c 12 Aug 2002 09:48:22 -0000 @@ -83,12 +83,12 @@ #include <arpa/inet.h> #include <arpa/nameser.h> #include <ctype.h> -#include <resolv.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netdb.h> +#include <resolv.h> #include "res_config.h" @@ -104,17 +104,6 @@ # define isascii(c) (!(c & 0200)) #endif -/* - * Resolver state default settings. - */ - -struct __res_state _res -# if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif - ; - -struct __res_state_ext _res_ext; /* * Set up default settings. If the configuration file exist, the values @@ -154,6 +143,10 @@ #ifndef RFC1535 int dots; #endif + + /* Ensure that _res_data is inited in the threaded case */ + if(&_res_data == NULL) + return -1; /* * These three fields used to be statically initialized. This made @@ -582,3 +575,49 @@ */ #undef res_init __weak_reference(__res_init, res_init); + +/* + * Resolver state default settings. + */ + +#undef _res +#undef _res_ext +#undef _res_data + +struct __res_state _res +# if defined(__BIND_RES_TEXT) + = { RES_TIMEOUT, } /* Motorola, et al. */ +# endif + ; + +struct __res_state_ext _res_ext; + +static char *host_aliases[MAXALIASES]; +static char *h_addr_ptrs[MAXADDRS + 1]; +static char hostbuf[8*1024]; +static u_char host_addr[16]; + +struct __res_data _res_data = { 0, -1, 0, 0, 0, NULL, NULL, NULL, 0, + { NULL, host_aliases, 0, 0, h_addr_ptrs }, hostbuf, sizeof hostbuf, + host_addr, sizeof host_addr, &_res, &_res_ext }; + +/* + * Declare a weak reference in case the application is not linked + * with libpthread. + */ +__weak_reference(__res_data_accessor_unthreaded, __res_data_accessor); +__weak_reference(__res_accessor_unthreaded, __res_accessor); + +struct __res_data * +__res_data_accessor_unthreaded() +{ + + return &_res_data; +} + +struct __res_state * +__res_accessor_unthreaded() +{ + + return _res_data.res; +} Index: src/lib/libc/net/res_query.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_query.c,v retrieving revision 1.23 diff -d -u -r1.23 res_query.c --- src/lib/libc/net/res_query.c 7 Jul 2002 11:28:28 -0000 1.23 +++ src/lib/libc/net/res_query.c 12 Aug 2002 09:48:22 -0000 @@ -87,6 +87,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "res_config.h" @@ -374,11 +375,21 @@ hostalias(name) const char *name; { + static char abuf[MAXDNAME]; + + return (hostalias_r(name, abuf, sizeof abuf)); +} + +const char * +hostalias_r(name, abuf, len) + const char *name; + char *abuf; + int len; +{ char *cp1, *cp2; FILE *fp; char *file; char buf[BUFSIZ]; - static char abuf[MAXDNAME]; if (_res.options & RES_NOALIASES) return (NULL); @@ -402,8 +413,8 @@ break; for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2) ; - abuf[sizeof(abuf) - 1] = *cp2 = '\0'; - strncpy(abuf, cp1, sizeof(abuf) - 1); + abuf[len - 1] = *cp2 = '\0'; + strncpy(abuf, cp1, len - 1); fclose(fp); return (abuf); } Index: src/lib/libc/net/res_send.c =================================================================== RCS file: /home/ncvs/src/lib/libc/net/res_send.c,v retrieving revision 1.45 diff -d -u -r1.45 res_send.c --- src/lib/libc/net/res_send.c 1 Apr 2002 16:09:45 -0000 1.45 +++ src/lib/libc/net/res_send.c 12 Aug 2002 09:48:23 -0000 @@ -102,13 +102,6 @@ #include "res_config.h" -static int s = -1; /* socket used for communications */ -static int connected = 0; /* is the socket connected */ -static int vc = 0; /* is the socket a virtual circuit? */ -static int af = 0; /* address family of socket */ -static res_send_qhook Qhook = NULL; -static res_send_rhook Rhook = NULL; - #define CAN_RECONNECT 1 @@ -170,7 +163,7 @@ res_send_qhook hook; { - Qhook = hook; + _res_data.Qhook = hook; } void @@ -178,7 +171,7 @@ res_send_rhook hook; { - Rhook = hook; + _res_data.Rhook = hook; } static struct sockaddr * get_nsaddr(size_t); @@ -406,13 +399,13 @@ goto next_ns; } - if (Qhook) { + if (_res_data.Qhook) { int done = 0, loops = 0; do { res_sendhookact act; - act = (*Qhook)((struct sockaddr_in **)&nsap, + act = (*_res_data.Qhook)((struct sockaddr_in **)&nsap, &buf, &buflen, ans, anssiz, &resplen); switch (act) { @@ -457,14 +450,16 @@ */ try = _res.retry; truncated = 0; - if (s < 0 || !vc || hp->opcode == ns_o_update || - af != nsap->sa_family) { - if (s >= 0) + if (_res_data.s < 0 || !_res_data.vc || + hp->opcode == ns_o_update || + _res_data.af != nsap->sa_family) { + if (_res_data.s >= 0) res_close(); - af = nsap->sa_family; - s = _socket(af, SOCK_STREAM, 0); - if (s < 0) { + _res_data.af = nsap->sa_family; + _res_data.s = _socket(_res_data.af, SOCK_STREAM, + 0); + if (_res_data.s < 0) { terrno = errno; Perror(stderr, "socket(vc)", errno); badns |= (1 << ns); @@ -472,7 +467,7 @@ goto next_ns; } errno = 0; - if (_connect(s, nsap, salen) < 0) { + if (_connect(_res_data.s, nsap, salen) < 0) { terrno = errno; Aerror(stderr, "connect/vc", errno, nsap); @@ -480,7 +475,7 @@ res_close(); goto next_ns; } - vc = 1; + _res_data.vc = 1; } /* * Send length & message @@ -490,7 +485,7 @@ iov[0].iov_len = INT16SZ; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; - if (_writev(s, iov, 2) != (INT16SZ + buflen)) { + if (_writev(_res_data.s, iov, 2) != (INT16SZ + buflen)) { terrno = errno; Perror(stderr, "write failed", errno); badns |= (1 << ns); @@ -503,7 +498,7 @@ read_len: cp = ans; len = INT16SZ; - while ((n = _read(s, (char *)cp, (int)len)) > 0) { + while ((n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; if ((len -= n) <= 0) break; @@ -551,7 +546,7 @@ } cp = ans; while (len != 0 && - (n = _read(s, (char *)cp, (int)len)) > 0) { + (n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } @@ -574,7 +569,7 @@ n = (len > sizeof(junk) ? sizeof(junk) : len); - if ((n = _read(s, junk, n)) > 0) + if ((n = _read(_res_data.s, junk, n)) > 0) len -= n; else break; @@ -604,12 +599,14 @@ struct sockaddr_storage from; int fromlen; - if (s < 0 || vc || af != nsap->sa_family) { - if (vc) + if (_res_data.s < 0 || _res_data.vc || + _res_data.af != nsap->sa_family) { + if (_res_data.vc) res_close(); - af = nsap->sa_family; - s = _socket(af, SOCK_DGRAM, 0); - if (s < 0) { + _res_data.af = nsap->sa_family; + _res_data.s = _socket(_res_data.af, SOCK_DGRAM, + 0); + if (_res_data.s < 0) { #ifndef CAN_RECONNECT bad_dg_sock: #endif @@ -619,7 +616,7 @@ res_close(); goto next_ns; } - connected = 0; + _res_data.connected = 0; } #ifndef CANNOT_CONNECT_DGRAM /* @@ -650,8 +647,9 @@ * Connect only if we are sure we won't * receive a response from another server. */ - if (!connected) { - if (_connect(s, nsap, salen) < 0) { + if (!_res_data.connected) { + if (_connect(_res_data.s, nsap, salen) < + 0) { Aerror(stderr, "connect(dg)", errno, nsap); @@ -659,9 +657,10 @@ res_close(); goto next_ns; } - connected = 1; + _res_data.connected = 1; } - if (send(s, (char*)buf, buflen, 0) != buflen) { + if (send(_res_data.s, (char*)buf, buflen, 0) != + buflen) { Perror(stderr, "send", errno); badns |= (1 << ns); res_close(); @@ -672,7 +671,7 @@ * Disconnect if we want to listen * for responses from more than one server. */ - if (connected) { + if (_res_data.connected) { #ifdef CAN_RECONNECT /* XXX: any errornous address */ struct sockaddr_in no_addr; @@ -680,24 +679,25 @@ no_addr.sin_family = AF_INET; no_addr.sin_addr.s_addr = INADDR_ANY; no_addr.sin_port = 0; - (void) _connect(s, + (void) _connect(_res_data.s, (struct sockaddr *) &no_addr, sizeof no_addr); #else - int s1 = _socket(af, SOCK_DGRAM,0); + int s1 = _socket(_res_data.af, + SOCK_DGRAM,0); if (s1 < 0) goto bad_dg_sock; - (void)_dup2(s1, s); + (void)_dup2(s1, _res_data.s); (void)_close(s1); Dprint(_res.options & RES_DEBUG, (stdout, ";; new DG socket\n")) #endif /* CAN_RECONNECT */ - connected = 0; + _res_data.connected = 0; errno = 0; } #endif /* !CANNOT_CONNECT_DGRAM */ - if (_sendto(s, (char*)buf, buflen, 0, + if (_sendto(_res_data.s, (char*)buf, buflen, 0, nsap, salen) != buflen) { Aerror(stderr, "sendto", errno, nsap); badns |= (1 << ns); @@ -722,13 +722,14 @@ (void) gettimeofday(&ctv, NULL); timeradd(&timeout, &ctv, &timeout); wait: - if (s < 0) { + if (_res_data.s < 0) { Perror(stderr, "s out-of-bounds", EMFILE); res_close(); goto next_ns; } - EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0,0,0); + EV_SET(&kv, _res_data.s, EVFILT_READ, + EV_ADD | EV_ONESHOT, 0,0,0); n = _kevent(kq, &kv, 1, &kv, 1, &ts); if (n < 0) { @@ -757,7 +758,7 @@ } errno = 0; fromlen = sizeof(from); - resplen = _recvfrom(s, (char*)ans, anssiz, 0, + resplen = _recvfrom(_res_data.s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); @@ -862,15 +863,15 @@ !(_res.options & RES_STAYOPEN)) { res_close(); } - if (Rhook) { + if (_res_data.Rhook) { int done = 0, loops = 0; do { res_sendhookact act; - act = (*Rhook)((struct sockaddr_in *)nsap, - buf, buflen, - ans, anssiz, &resplen); + act = (*_res_data.Rhook)( + (struct sockaddr_in *)nsap, buf, buflen, + ans, anssiz, &resplen); switch (act) { case res_goahead: case res_done: @@ -920,12 +921,12 @@ void res_close() { - if (s >= 0) { - (void)_close(s); - s = -1; - connected = 0; - vc = 0; - af = 0; + if (_res_data.s >= 0) { + (void)_close(_res_data.s); + _res_data.s = -1; + _res_data.connected = 0; + _res_data.vc = 0; + _res_data.af = 0; } } Index: src/lib/libc_r/sys/Makefile.inc =================================================================== RCS file: /home/ncvs/src/lib/libc_r/sys/Makefile.inc,v retrieving revision 1.10 diff -d -u -r1.10 Makefile.inc --- src/lib/libc_r/sys/Makefile.inc 28 Aug 1999 00:03:13 -0000 1.10 +++ src/lib/libc_r/sys/Makefile.inc 12 Aug 2002 09:48:23 -0000 @@ -2,5 +2,5 @@ .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} -SRCS+= uthread_error.c _atomic_lock.S +SRCS+= uthread_error.c uthread_resolv.c _atomic_lock.S Index: src/lib/libc_r/sys/uthread_resolv.c =================================================================== RCS file: src/lib/libc_r/sys/uthread_resolv.c diff -N src/lib/libc_r/sys/uthread_resolv.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/lib/libc_r/sys/uthread_resolv.c 12 Aug 2002 09:48:23 -0000 @@ -0,0 +1,186 @@ +/*- + * Copyright (c) 2001 Alexandr Litvin <archer@whichever.org> + * 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. + * + * 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. + * + * $FreeBSD$ + */ + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <pthread.h> +#include "pthread_private.h" + +#undef h_errno +#undef _res +#undef _res_ext +#undef _res_data + +extern int h_errno; +extern struct __res_data _res_data; + +static pthread_once_t once = PTHREAD_ONCE_INIT; +static pthread_key_t key; + + +static void +__res_data_destroy(void *p) +{ + struct __res_data *_res_datap = (struct __res_data *)p; + + if(_res_datap->res) + free(_res_datap->res); + if(_res_datap->res_ext) + free(_res_datap->res_ext); + if (_res_datap->host.h_aliases) + free(_res_datap->host.h_aliases); + if (_res_datap->host.h_addr_list) + free(_res_datap->host.h_addr_list); + if (_res_datap->hostbuf) + free(_res_datap->hostbuf); + if (_res_datap->host_addr) + free(_res_datap->host_addr); + if(_res_datap->s >= 0) + close(_res_datap->s); + if(_res_datap->hostf) + fclose(_res_datap->hostf); + free(_res_datap); +} + +static void +__res_data_init() +{ + + pthread_key_create(&key, __res_data_destroy); +} + +struct __res_data * +__res_data_accessor() +{ + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + _res_datap = &_res_data; + } else { + pthread_once(&once, __res_data_init); + _res_datap = (struct __res_data *)pthread_getspecific(key); + if(_res_datap==NULL) { + _res_datap = malloc(sizeof(struct __res_data)); + if(_res_datap==NULL) + return (NULL); + bzero(_res_datap, sizeof(struct __res_data)); + _res_datap->res = malloc(sizeof(struct __res_state)); + if(_res_datap->res == NULL) + goto e1; + bzero(_res_datap->res, sizeof(struct __res_state)); + _res_datap->res_ext = + malloc(sizeof(struct __res_state_ext)); + if(_res_datap->res_ext == NULL) + goto e2; + bzero(_res_datap->res_ext, + sizeof(struct __res_state_ext)); + _res_datap->s = -1; + _res_datap->host.h_name = NULL; + _res_datap->host.h_aliases = + malloc(sizeof(char *[MAXALIASES])); + if (_res_datap->host.h_aliases == NULL) + goto e3; + _res_datap->host.h_addrtype = 0; + _res_datap->host.h_length = 0; + _res_datap->host.h_addr_list = + malloc(sizeof(char *[MAXADDRS + 1])); + if (_res_datap->host.h_addr_list == NULL) + goto e4; + _res_datap->hostbuflen = sizeof(*_res_datap->hostbuf) * + 8 * 1024; + _res_datap->hostbuf = malloc(_res_datap->hostbuflen); + if (_res_datap->hostbuf == NULL) + goto e5; + _res_datap->host_addrlen = + sizeof(*_res_datap->host_addr) * 16; + _res_datap->host_addr = + malloc(_res_datap->host_addrlen); + if (_res_datap->host_addr == NULL) + goto e6; + pthread_setspecific(key, _res_datap); + } + } + return (_res_datap); + +e6: free(_res_datap->hostbuf); +e5: free(_res_datap->host.h_addr_list); +e4: free(_res_datap->host.h_aliases); +e3: free(_res_datap->res_ext); +e2: free(_res_datap->res); +e1: free(_res_datap); + return (NULL); +} + +static struct __res_state dummy_res; +static int dummy_h_errno; + +struct __res_state * +__res_accessor() +{ + struct __res_state *resp; + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + resp = _res_data.res; + } else { + _res_datap = __res_data_accessor(); + if(_res_datap) { + resp = _res_datap->res; + } else { + dummy_res.options = RES_DEFAULT; + resp = &dummy_res; + } + } + return (resp); +} + +int * +__h_errno_accessor() +{ + int *h_errnop; + struct __res_data *_res_datap; + + if (_thread_run == _thread_initial) { + h_errnop = &h_errno; + } else { + _res_datap = __res_data_accessor(); + if(_res_datap) { + h_errnop = &_res_datap->h_errno_res; + } else { + dummy_h_errno = NETDB_INTERNAL; + h_errnop = &dummy_h_errno; + } + } + return (h_errnop); +} --------------051496A982500B2DDF1E4FCD-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-audit" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3D578A99.F0821712>