From owner-freebsd-bugs Thu Aug 9 13:11:44 2001 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id EE5BB37B40D for ; Thu, 9 Aug 2001 13:10:21 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.4/8.11.4) id f79KAKu92083; Thu, 9 Aug 2001 13:10:20 -0700 (PDT) (envelope-from gnats) Received: from smtp03.mrf.mail.rcn.net (smtp03.mrf.mail.rcn.net [207.172.4.62]) by hub.freebsd.org (Postfix) with ESMTP id C60D537B406 for ; Thu, 9 Aug 2001 13:02:37 -0700 (PDT) (envelope-from archer@whichever.org) Received: from 207-172-201-120.s57.as2.xnb.nj.dialup.rcn.com ([207.172.201.120] helo=unknown.whichever.org) by smtp03.mrf.mail.rcn.net with esmtp (Exim 3.32 #2) id 15Uw0h-00020C-00 for FreeBSD-gnats-submit@freebsd.org; Thu, 09 Aug 2001 16:02:27 -0400 Received: (from archer@localhost) by unknown.whichever.org (8.11.5/8.11.1) id f79K2OT19276; Thu, 9 Aug 2001 16:02:24 -0400 (EDT) (envelope-from archer) Message-Id: <200108092002.f79K2OT19276@unknown.whichever.org> Date: Thu, 9 Aug 2001 16:02:24 -0400 (EDT) From: "Alexander Litvin"@FreeBSD.ORG, archer@whichever.org Reply-To: Alexander Litvin To: FreeBSD-gnats-submit@FreeBSD.ORG X-Send-Pr-Version: 3.113 Subject: bin/29581: proposed gethostbyXXXX_r() implementation Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 29581 >Category: bin >Synopsis: proposed gethostbyXXXX_r() implementation >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Aug 09 13:10:19 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Alexander Litvin >Release: FreeBSD 5.0-CURRENT i386 >Organization: unknown >Environment: System: FreeBSD unknown.whichever.org 5.0-CURRENT FreeBSD 5.0-CURRENT #2: Wed Aug 8 09:20:55 EDT 2001 root@unknown.whichever.org:/var/src/sys/i386/compile/UNKNOWN i386 >Description: Below is a patch, which adds implementation of gethostbyname_r() and gethostbyaddr_r() reentrant functions to FreeBSD libc. Notes: * Patch essentially eliminates usage of static buffers when gethostbyXXXX_r are called. * Also, global _res and h_errno are replaced by function calls (similar to errno) and for threaded applications are stored in thread-specific data * Although all static variables relevant to gethostbyXXXX() and resolver library were eliminated, to clame that this implementation is thread-safe it is necessary to check all possible code paths. * Patch implements reentrant functions only for dns/files configuration. In case of nis implementation is not reentrant. This can be easily done (it looks easier then to modify dns/files code) , but I chose to omit this, because I have no environment to test it. * Code was not tested on non-i386 hardware. >How-To-Repeat: >Fix: ---------------------------- *** src/include/netdb.h.orig Sun Jul 22 14:10:08 2001 --- src/include/netdb.h Wed Aug 8 23:26:57 2001 *************** *** 77,83 **** #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" ! extern int h_errno; /* * Structures returned by network data base library. All addresses are --- 77,86 ---- #define _PATH_PROTOCOLS "/etc/protocols" #define _PATH_SERVICES "/etc/services" ! __BEGIN_DECLS ! int * __h_errno_accessor __P((void)); ! __END_DECLS ! #define h_errno (* __h_errno_accessor()) /* * Structures returned by network data base library. All addresses are *************** *** 244,249 **** --- 247,263 ---- char *gai_strerror __P((int)); void setnetgrent __P((const char *)); void setservent __P((int)); + + struct hostent *gethostbyaddr_r __P((const char *, int, int, struct hostent *, + char *, int, int *)); + struct hostent *gethostbyname_r __P((const char *, struct hostent *, + char *, int, int *)); + struct hostent *gethostbyname2_r __P((const char *, int, struct hostent *, + char *, int, int *)); + struct hostent *gethostent_r __P((struct hostent *, char *, int)); + + #define CAST_ALIGN(ptr, type) \ + (char*)(type)ptr<(char*)ptr?((type)ptr)+1:(type)ptr /* * PRIVATE functions specific to the FreeBSD implementation *** src/include/resolv.h.orig Sun Jun 10 16:25:21 2001 --- src/include/resolv.h Wed Aug 8 23:26:57 2001 *************** *** 198,206 **** 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[]; --- 198,206 ---- 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,229 **** --- 224,230 ---- #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,278 **** --- 274,280 ---- void fp_query __P((const u_char *, FILE *)); void fp_nquery __P((const u_char *, int, FILE *)); const char * hostalias __P((const char *)); + const char * hostalias_r __P((const char *, char *, int)); void putlong __P((u_int32_t, u_char *)); void putshort __P((u_int16_t, u_char *)); const char * p_class __P((int)); *************** *** 316,320 **** --- 318,344 ---- void res_freeupdrec __P((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 + struct __res_data * __res_data_accessor __P((void)); + struct __res_state * __res_accessor __P((void)); + __END_DECLS + #define _res_data (* __res_data_accessor()) + #define _res (* __res_accessor()) + #define _res_ext (* (__res_data_accessor()->res_ext)) #endif /* !_RESOLV_H_ */ *** src/lib/libc/net/getaddrinfo.c.orig Sun Jun 10 16:25:23 2001 --- src/lib/libc/net/getaddrinfo.c Wed Aug 8 23:26:57 2001 *************** *** 1668,1674 **** /* resolver logic */ extern const char *__hostalias __P((const char *)); - extern int h_errno; /* * Formulate a normal query, send, and await answer. --- 1668,1673 ---- *** src/lib/libc/net/gethostbydns.c.orig Wed Sep 6 14:16:40 2000 --- src/lib/libc/net/gethostbydns.c Wed Aug 8 23:26:57 2001 *************** *** 88,98 **** "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 __P((char **, int)); --- 88,98 ---- "gethostby*.gethostanswer: asked for \"%s\", got \"%s\""; 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 }; ! ! static char hostbuf_s[8*1024]; ! static u_char host_addr_s[16]; /* IPv4 or IPv6 */ #ifdef RESOLVSORT static void addrsort __P((char **, int)); *************** *** 114,120 **** char ac; } align; - extern int h_errno; int _dns_ttl_; #ifdef DEBUG --- 114,119 ---- *************** *** 152,162 **** } while (0) static struct hostent * ! gethostanswer(answer, anslen, qname, qtype) const querybuf *answer; int anslen; const char *qname; int qtype; { register const HEADER *hp; register const u_char *cp; --- 151,164 ---- } while (0) static struct hostent * ! 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; { register const HEADER *hp; register const u_char *cp; *************** *** 171,177 **** int (*name_ok) __P((const char *)); tname = qname; ! host.h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: --- 173,179 ---- int (*name_ok) __P((const char *)); tname = qname; ! host->h_name = NULL; eom = answer->buf + anslen; switch (qtype) { case T_A: *************** *** 192,198 **** ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; ! buflen = sizeof hostbuf; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { --- 194,200 ---- ancount = ntohs(hp->ancount); qdcount = ntohs(hp->qdcount); bp = hostbuf; ! buflen = hostbuflen; cp = answer->buf; BOUNDED_INCR(HFIXEDSZ); if (qdcount != 1) { *************** *** 215,232 **** h_errno = NO_RECOVERY; return (NULL); } ! host.h_name = bp; bp += n; buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ ! qname = host.h_name; } ! ap = host_aliases; *ap = NULL; ! host.h_aliases = host_aliases; ! hap = h_addr_ptrs; *hap = NULL; - host.h_addr_list = h_addr_ptrs; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; --- 217,232 ---- h_errno = NO_RECOVERY; return (NULL); } ! host->h_name = bp; bp += n; buflen -= n; /* The qname can be abbreviated, but h_name is now absolute. */ ! qname = host->h_name; } ! ap = host->h_aliases; *ap = NULL; ! hap = host->h_addr_list; *hap = NULL; haveanswer = 0; had_error = 0; _dns_ttl_ = -1; *************** *** 255,261 **** continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { ! if (ap >= &host_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { --- 255,261 ---- continue; /* XXX - had_error++ ? */ } if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { ! if (ap >= &host->h_aliases[MAXALIASES-1]) continue; n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); if ((n < 0) || !(*name_ok)(tbuf)) { *************** *** 283,289 **** continue; } strcpy(bp, tbuf); ! host.h_name = bp; bp += n; buflen -= n; continue; --- 283,289 ---- continue; } strcpy(bp, tbuf); ! host->h_name = bp; bp += n; buflen -= n; continue; *************** *** 340,347 **** return (NULL); } if (!haveanswer) ! host.h_name = bp; ! else if (ap < &host_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; --- 340,347 ---- return (NULL); } if (!haveanswer) ! host->h_name = bp; ! else if (ap < &host->h_aliases[MAXALIASES-1]) *ap++ = bp; else n = -1; *************** *** 356,362 **** } break; #else ! host.h_name = bp; if (_res.options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { --- 356,362 ---- } break; #else ! host->h_name = bp; if (_res.options & RES_USE_INET6) { n = strlen(bp) + 1; /* for the \0 */ if (n >= MAXHOSTNAMELEN) { *************** *** 365,391 **** } bp += n; buflen -= n; ! _map_v4v6_hostent(&host, &bp, &buflen); } h_errno = NETDB_SUCCESS; ! return (&host); #endif case T_A: case T_AAAA: ! if (strcasecmp(host.h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, ! AskedForGot, host.h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } ! if (n != host.h_length) { cp += n; continue; } if (!haveanswer) { register int nn; ! host.h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; --- 365,391 ---- } bp += n; buflen -= n; ! _map_v4v6_hostent(host, &bp, &buflen); } h_errno = NETDB_SUCCESS; ! return (host); #endif case T_A: case T_AAAA: ! if (strcasecmp(host->h_name, bp) != 0) { syslog(LOG_NOTICE|LOG_AUTH, ! AskedForGot, host->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } ! if (n != host->h_length) { cp += n; continue; } if (!haveanswer) { register int nn; ! host->h_name = bp; nn = strlen(bp) + 1; /* for the \0 */ bp += nn; buflen -= nn; *************** *** 393,404 **** bp += sizeof(align) - ((u_long)bp % sizeof(align)); ! if (bp + n >= &hostbuf[sizeof hostbuf]) { dprintf("size (%d) too big\n", n); had_error++; continue; } ! if (hap >= &h_addr_ptrs[MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", MAXADDRS); --- 393,404 ---- bp += sizeof(align) - ((u_long)bp % sizeof(align)); ! if (bp + n >= &hostbuf[hostbuflen]) { dprintf("size (%d) too big\n", n); had_error++; continue; } ! if (hap >= &host->h_addr_list[MAXADDRS-1]) { if (!toobig++) dprintf("Too many addresses (%d)\n", MAXADDRS); *************** *** 433,453 **** * address in that case, not some random one */ if (_res.nsort && haveanswer > 1 && qtype == T_A) ! addrsort(h_addr_ptrs, haveanswer); # endif /*RESOLVSORT*/ ! if (!host.h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); ! host.h_name = bp; bp += n; buflen -= n; } if (_res.options & RES_USE_INET6) ! _map_v4v6_hostent(&host, &bp, &buflen); h_errno = NETDB_SUCCESS; ! return (&host); } no_recovery: h_errno = NO_RECOVERY; --- 433,453 ---- * address in that case, not some random one */ if (_res.nsort && haveanswer > 1 && qtype == T_A) ! addrsort(host->h_addr_list, haveanswer); # endif /*RESOLVSORT*/ ! if (!host->h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) goto no_recovery; strcpy(bp, qname); ! host->h_name = bp; bp += n; buflen -= n; } if (_res.options & RES_USE_INET6) ! _map_v4v6_hostent(host, &bp, &buflen); h_errno = NETDB_SUCCESS; ! return (host); } no_recovery: h_errno = NO_RECOVERY; *************** *** 461,479 **** 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 --- 461,484 ---- const char *qname; int qtype; { + struct hostent *host = &host_s; + char *hostbuf = hostbuf_s; + int hostbuflen = sizeof hostbuf_s; + 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, ! host, hostbuf, hostbuflen)); } int *************** *** 481,495 **** --- 486,543 ---- { const char *name; int af; + struct hostent *host; + char *hostbuf; + int hostbuflen; + u_char *host_addr; querybuf buf; register const char *cp; char *bp; 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; + /* XXX */ + printf("gethostbyname %s\n",name); + + if(hostbuflen!=0 && hostbuf != NULL && host != 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; + 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; + 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; + return NS_UNAVAIL; + } + } else { + host = &host_s; + 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; *************** *** 510,524 **** return NS_UNAVAIL; } ! 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))) name = cp; /* --- 558,572 ---- return NS_UNAVAIL; } ! 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_r(name, abuf, sizeof abuf))) name = cp; /* *************** *** 542,558 **** 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; if (_res.options & RES_USE_INET6) ! _map_v4v6_hostent(&host, &bp, &len); h_errno = NETDB_SUCCESS; ! *(struct hostent **)rval = &host; return NS_SUCCESS; } if (!isdigit((unsigned char)*cp) && *cp != '.') --- 590,604 ---- strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; ! 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; if (_res.options & RES_USE_INET6) ! _map_v4v6_hostent(host, &bp, &len); h_errno = NETDB_SUCCESS; ! *(struct hostent **)rval = host; return NS_SUCCESS; } if (!isdigit((unsigned char)*cp) && *cp != '.') *************** *** 576,590 **** 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; h_errno = NETDB_SUCCESS; ! *(struct hostent **)rval = &host; return NS_SUCCESS; } if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') --- 622,634 ---- strncpy(hostbuf, name, MAXDNAME); hostbuf[MAXDNAME] = '\0'; bp = hostbuf + MAXDNAME; ! 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; return NS_SUCCESS; } if (!isxdigit((unsigned char)*cp) && *cp != ':' && *cp != '.') *************** *** 595,601 **** dprintf("res_search failed (%d)\n", n); return NS_UNAVAIL; } ! *(struct hostent **)rval = gethostanswer(&buf, n, name, type); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } --- 639,646 ---- dprintf("res_search failed (%d)\n", n); return NS_UNAVAIL; } ! *(struct hostent **)rval = gethostanswer(&buf, n, name, type, ! host, hostbuf, hostbuflen); return (*(struct hostent **)rval != NULL) ? NS_SUCCESS : NS_NOTFOUND; } *************** *** 604,609 **** --- 649,658 ---- { 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 }; *************** *** 617,630 **** u_long old_options; char hname2[MAXDNAME+1]; #endif /*SUNSECURITY*/ addr = va_arg(ap, const char *); 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; --- 666,713 ---- u_long old_options; char hname2[MAXDNAME+1]; #endif /*SUNSECURITY*/ + u_char *host_addr = host_addr_s; addr = va_arg(ap, const char *); 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 != 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; + 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; + 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; + return NS_UNAVAIL; + } + } else { + host = &host_s; + hostbuf = hostbuf_s; + hostbuflen = sizeof hostbuf_s; + } + if ((_res.options & RES_INIT) == 0 && res_init() == -1) { h_errno = NETDB_INTERNAL; return NS_UNAVAIL; *************** *** 684,690 **** dprintf("static buffer is too small (%d)\n", n); return NS_UNAVAIL; } ! if (!(hp = gethostanswer(&buf, n, qbuf, T_PTR))) return NS_NOTFOUND; /* h_errno was set by gethostanswer() */ #ifdef SUNSECURITY if (af == AF_INET) { --- 767,773 ---- dprintf("static buffer is too small (%d)\n", n); return NS_UNAVAIL; } ! 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) { *************** *** 721,728 **** 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; if (af == AF_INET && (_res.options & RES_USE_INET6)) { _map_v4v6_address((char*)host_addr, (char*)host_addr); hp->h_addrtype = AF_INET6; --- 804,811 ---- hp->h_addrtype = af; hp->h_length = len; bcopy(addr, host_addr, len); ! 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; *** src/lib/libc/net/gethostbyht.c.orig Wed Jan 24 08:00:26 2001 --- src/lib/libc/net/gethostbyht.c Wed Aug 8 23:26:57 2001 *************** *** 71,117 **** #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" ); else ! rewind(hostf); ! stayopen = f; } void _endhosthtent() { ! if (hostf && !stayopen) { ! (void) fclose(hostf); ! hostf = NULL; } } struct hostent * gethostent() { char *p; register char *cp, **q; int af, len; ! if (!hostf && !(hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } again: ! if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); } --- 71,122 ---- #define MAXALIASES 35 static char *h_addr_ptrs[2]; ! 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 (!_res_data.hostf) ! _res_data.hostf = fopen(_PATH_HOSTS, "r" ); else ! rewind(_res_data.hostf); ! _res_data.stayopen = f; } void _endhosthtent() { ! 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; register char *cp, **q; int af, len; ! if (!_res_data.hostf && !(_res_data.hostf = fopen(_PATH_HOSTS, "r" ))) { h_errno = NETDB_INTERNAL; return (NULL); } again: ! if (!(p = fgets(hostbuf, hostbuflen, _res_data.hostf))) { h_errno = HOST_NOT_FOUND; return (NULL); } *************** *** 123,134 **** if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\0'; ! if (inet_pton(AF_INET6, p, host_addr) > 0) { af = AF_INET6; len = IN6ADDRSZ; ! } else if (inet_pton(AF_INET, p, host_addr) > 0) { if (_res.options & RES_USE_INET6) { ! _map_v4v6_address((char*)host_addr, (char*)host_addr); af = AF_INET6; len = IN6ADDRSZ; } else { --- 128,139 ---- if (!(cp = strpbrk(p, " \t"))) goto again; *cp++ = '\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->h_addr_list[0]) > 0) { if (_res.options & RES_USE_INET6) { ! _map_v4v6_address(host->h_addr_list[0], host->h_addr_list[0]); af = AF_INET6; len = IN6ADDRSZ; } else { *************** *** 138,152 **** } 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; while (*cp == ' ' || *cp == '\t') cp++; ! host.h_name = cp; ! q = host.h_aliases = host_aliases; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; while (cp && *cp) { --- 143,154 ---- } else { goto again; } ! host->h_length = len; ! host->h_addrtype = af; while (*cp == ' ' || *cp == '\t') cp++; ! host->h_name = cp; ! q = host->h_aliases; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; while (cp && *cp) { *************** *** 154,167 **** cp++; continue; } ! if (q < &host_aliases[MAXALIASES - 1]) *q++ = cp; if ((cp = strpbrk(cp, " \t")) != NULL) *cp++ = '\0'; } *q = NULL; h_errno = NETDB_SUCCESS; ! return (&host); } int --- 156,169 ---- cp++; continue; } ! 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); } int *************** *** 169,182 **** { const char *name; int af; register struct hostent *p; register char **cp; name = va_arg(ap, const char *); af = va_arg(ap, int); sethostent(0); ! while ((p = gethostent()) != NULL) { if (p->h_addrtype != af) continue; if (strcasecmp(p->h_name, name) == 0) --- 171,226 ---- { const char *name; int af; + struct hostent *host; + char *hostbuf, *bp; + int hostbuflen; + u_int32_t *host_addr; register struct hostent *p; register 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 != 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; + 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; + 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; + return NS_UNAVAIL; + } + } else { + host = &host_s; + 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_r(host, hostbuf, hostbuflen)) != NULL) { if (p->h_addrtype != af) continue; if (strcasecmp(p->h_name, name) == 0) *************** *** 197,210 **** { const char *addr; int len, af; register struct hostent *p; addr = va_arg(ap, const char *); len = va_arg(ap, int); af = va_arg(ap, int); sethostent(0); ! while ((p = gethostent()) != NULL) if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; endhostent(); --- 241,296 ---- { const char *addr; int len, af; + struct hostent *host; + char *hostbuf, *bp; + int hostbuflen; + u_int32_t *host_addr; register 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 != 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; + 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; + 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; + return NS_UNAVAIL; + } + } else { + host = &host_s; + 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_r(host,hostbuf,hostbuflen)) != NULL) if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) break; endhostent(); *** src/lib/libc/net/gethostnamadr.c.orig Wed Jan 24 08:00:26 2001 --- src/lib/libc/net/gethostnamadr.c Wed Aug 8 23:26:57 2001 *************** *** 56,79 **** }; struct hostent * ! gethostbyname(const char *name) { struct hostent *hp; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { ! h_errno = NETDB_INTERNAL; return (NULL); } if (_res.options & RES_USE_INET6) { /* XXX */ ! hp = gethostbyname2(name, AF_INET6); /* XXX */ if (hp) /* XXX */ return (hp); /* XXX */ } /* XXX */ ! return (gethostbyname2(name, AF_INET)); } struct hostent * ! gethostbyname2(const char *name, int type) { struct hostent *hp = 0; int rval; --- 56,89 ---- }; struct hostent * ! gethostbyname_r(const char *name, struct hostent *resp, ! char *buffer, int buflen, int *h_errnop) { struct hostent *hp; if ((_res.options & RES_INIT) == 0 && res_init() == -1) { ! *h_errnop = NETDB_INTERNAL; return (NULL); } if (_res.options & RES_USE_INET6) { /* XXX */ ! hp = gethostbyname2_r(name, AF_INET6, resp, ! buffer, buflen, h_errnop); /* XXX */ if (hp) /* XXX */ return (hp); /* XXX */ } /* XXX */ ! return (gethostbyname2_r(name, AF_INET, resp, ! buffer, buflen, h_errnop)); } struct hostent * ! gethostbyname(const char *name) ! { ! return (gethostbyname_r(name, NULL, NULL, 0, &h_errno)); ! } ! ! struct hostent * ! gethostbyname2_r(const char *name, int type, struct hostent *resp, ! char *buffer, int buflen, int *h_errnop) { struct hostent *hp = 0; int rval; *************** *** 86,92 **** }; rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", ! default_src, name, type); if (rval != NS_SUCCESS) return NULL; --- 96,104 ---- }; rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyname", ! default_src, name, type, resp, buffer, buflen); ! ! *h_errnop = h_errno; if (rval != NS_SUCCESS) return NULL; *************** *** 95,101 **** } struct hostent * ! gethostbyaddr(const char *addr, int len, int type) { struct hostent *hp = 0; int rval; --- 107,120 ---- } struct hostent * ! gethostbyname2(const char *name, int type) ! { ! return (gethostbyname2_r(name, type, NULL, NULL, 0, &h_errno)); ! } ! ! struct hostent * ! 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; *************** *** 108,114 **** }; rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr", ! default_src, addr, len, type); if (rval != NS_SUCCESS) return NULL; --- 127,135 ---- }; rval = nsdispatch((void *)&hp, dtab, NSDB_HOSTS, "gethostbyaddr", ! default_src, addr, len, type, resp, buffer, buflen); ! ! *h_errnop = h_errno; if (rval != NS_SUCCESS) return NULL; *************** *** 116,126 **** 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) { --- 137,152 ---- return hp; } + struct hostent * + gethostbyaddr(const char *addr, int len, int type) + { + return (gethostbyaddr_r(addr, len, type, NULL, NULL, 0, &h_errno)); + } + 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) { *************** *** 134,139 **** --- 160,166 ---- } return(ret); } + */ void sethostent(stayopen) *** src/lib/libc/net/getnetbydns.c.orig Wed Jan 24 08:00:26 2001 --- src/lib/libc/net/getnetbydns.c Wed Aug 8 23:26:57 2001 *************** *** 81,88 **** #include "res_config.h" - extern int h_errno; - #define BYADDR 0 #define BYNAME 1 #define MAXALIASES 35 --- 81,86 ---- *** src/lib/libc/net/herror.c.orig Wed Jan 24 08:00:26 2001 --- src/lib/libc/net/herror.c Wed Aug 8 23:26:57 2001 *************** *** 70,77 **** }; int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; - int h_errno; - /* * herror -- * print the error indicated by the h_errno value. --- 70,75 ---- *************** *** 109,111 **** --- 107,125 ---- 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; + } + *** src/lib/libc/net/res_init.c.orig Sun Jun 10 16:25:23 2001 --- src/lib/libc/net/res_init.c Wed Aug 8 23:26:57 2001 *************** *** 103,119 **** # 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 --- 103,108 ---- *************** *** 153,158 **** --- 142,150 ---- #ifndef RFC1535 int dots; #endif + + if(&_res_data==NULL) + return -1; /* * These three fields used to be statically initialized. This made *************** *** 574,576 **** --- 566,605 ---- */ #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; + } *** src/lib/libc/net/res_query.c.orig Sun Jun 10 16:25:23 2001 --- src/lib/libc/net/res_query.c Wed Aug 8 23:26:57 2001 *************** *** 373,383 **** hostalias(name) const char *name; { register char *cp1, *cp2; FILE *fp; char *file; char buf[BUFSIZ]; - static char abuf[MAXDNAME]; if (_res.options & RES_NOALIASES) return (NULL); --- 373,392 ---- 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; + { register char *cp1, *cp2; FILE *fp; char *file; char buf[BUFSIZ]; if (_res.options & RES_NOALIASES) return (NULL); *************** *** 401,408 **** break; for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2) ; ! abuf[sizeof(abuf) - 1] = *cp2 = '\0'; ! strncpy(abuf, cp1, sizeof(abuf) - 1); fclose(fp); return (abuf); } --- 410,417 ---- break; for (cp2 = cp1 + 1; *cp2 && !isspace((unsigned char)*cp2); ++cp2) ; ! abuf[len - 1] = *cp2 = '\0'; ! strncpy(abuf, cp1, len - 1); fclose(fp); return (abuf); } *** src/lib/libc/net/res_send.c.orig Sat Jun 23 02:54:28 2001 --- src/lib/libc/net/res_send.c Wed Aug 8 23:26:57 2001 *************** *** 101,113 **** #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 --- 101,106 ---- *************** *** 169,175 **** res_send_qhook hook; { ! Qhook = hook; } void --- 162,168 ---- res_send_qhook hook; { ! _res_data.Qhook = hook; } void *************** *** 177,183 **** res_send_rhook hook; { ! Rhook = hook; } static struct sockaddr * get_nsaddr __P((size_t)); --- 170,176 ---- res_send_rhook hook; { ! _res_data.Rhook = hook; } static struct sockaddr * get_nsaddr __P((size_t)); *************** *** 405,417 **** goto next_ns; } ! if (Qhook) { int done = 0, loops = 0; do { res_sendhookact act; ! act = (*Qhook)((struct sockaddr_in **)&nsap, &buf, &buflen, ans, anssiz, &resplen); switch (act) { --- 398,410 ---- goto next_ns; } ! if (_res_data.Qhook) { int done = 0, loops = 0; do { res_sendhookact act; ! act = (*_res_data.Qhook)((struct sockaddr_in **)&nsap, &buf, &buflen, ans, anssiz, &resplen); switch (act) { *************** *** 456,469 **** */ try = _res.retry; truncated = 0; ! if (s < 0 || !vc || hp->opcode == ns_o_update || ! af != nsap->sa_family) { ! if (s >= 0) res_close(); ! af = nsap->sa_family; ! s = _socket(af, SOCK_STREAM, 0); ! if (s < 0) { terrno = errno; Perror(stderr, "socket(vc)", errno); badns |= (1 << ns); --- 449,462 ---- */ try = _res.retry; truncated = 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(); ! _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); *************** *** 471,477 **** goto next_ns; } errno = 0; ! if (_connect(s, nsap, salen) < 0) { terrno = errno; Aerror(stderr, "connect/vc", errno, nsap); --- 464,470 ---- goto next_ns; } errno = 0; ! if (_connect(_res_data.s, nsap, salen) < 0) { terrno = errno; Aerror(stderr, "connect/vc", errno, nsap); *************** *** 479,485 **** res_close(); goto next_ns; } ! vc = 1; } /* * Send length & message --- 472,478 ---- res_close(); goto next_ns; } ! _res_data.vc = 1; } /* * Send length & message *************** *** 489,495 **** iov[0].iov_len = INT16SZ; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; ! if (_writev(s, iov, 2) != (INT16SZ + buflen)) { terrno = errno; Perror(stderr, "write failed", errno); badns |= (1 << ns); --- 482,488 ---- iov[0].iov_len = INT16SZ; iov[1].iov_base = (caddr_t)buf; iov[1].iov_len = buflen; ! if (_writev(_res_data.s, iov, 2) != (INT16SZ + buflen)) { terrno = errno; Perror(stderr, "write failed", errno); badns |= (1 << ns); *************** *** 502,508 **** read_len: cp = ans; len = INT16SZ; ! while ((n = _read(s, (char *)cp, (int)len)) > 0) { cp += n; if ((len -= n) <= 0) break; --- 495,501 ---- read_len: cp = ans; len = INT16SZ; ! while ((n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; if ((len -= n) <= 0) break; *************** *** 550,556 **** } cp = ans; while (len != 0 && ! (n = _read(s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } --- 543,549 ---- } cp = ans; while (len != 0 && ! (n = _read(_res_data.s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } *************** *** 573,579 **** n = (len > sizeof(junk) ? sizeof(junk) : len); ! if ((n = _read(s, junk, n)) > 0) len -= n; else break; --- 566,572 ---- n = (len > sizeof(junk) ? sizeof(junk) : len); ! if ((n = _read(_res_data.s, junk, n)) > 0) len -= n; else break; *************** *** 603,614 **** struct sockaddr_storage from; int fromlen; ! if (s < 0 || vc || af != nsap->sa_family) { ! if (vc) ! res_close(); ! af = nsap->sa_family; ! s = _socket(af, SOCK_DGRAM, 0); ! if (s < 0) { #ifndef CAN_RECONNECT bad_dg_sock: #endif --- 596,608 ---- struct sockaddr_storage from; int fromlen; ! if (_res_data.s < 0 || _res_data.vc || ! _res_data.af != nsap->sa_family) { ! if (_res_data.vc) ! res_close(); ! _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 *************** *** 618,624 **** res_close(); goto next_ns; } ! connected = 0; } #ifndef CANNOT_CONNECT_DGRAM /* --- 612,618 ---- res_close(); goto next_ns; } ! _res_data.connected = 0; } #ifndef CANNOT_CONNECT_DGRAM /* *************** *** 641,648 **** * Connect only if we are sure we won't * receive a response from another server. */ ! if (!connected) { ! if (_connect(s, nsap, salen) < 0) { Aerror(stderr, "connect(dg)", errno, nsap); --- 635,642 ---- * Connect only if we are sure we won't * receive a response from another server. */ ! if (!_res_data.connected) { ! if (_connect(_res_data.s, nsap, salen) < 0) { Aerror(stderr, "connect(dg)", errno, nsap); *************** *** 650,658 **** res_close(); goto next_ns; } ! connected = 1; } ! if (send(s, (char*)buf, buflen, 0) != buflen) { Perror(stderr, "send", errno); badns |= (1 << ns); res_close(); --- 644,652 ---- res_close(); goto next_ns; } ! _res_data.connected = 1; } ! if (send(_res_data.s, (char*)buf, buflen, 0) != buflen) { Perror(stderr, "send", errno); badns |= (1 << ns); res_close(); *************** *** 663,669 **** * Disconnect if we want to listen * for responses from more than one server. */ ! if (connected) { #ifdef CAN_RECONNECT /* XXX: any errornous address */ struct sockaddr_in no_addr; --- 657,663 ---- * Disconnect if we want to listen * for responses from more than one server. */ ! if (_res_data.connected) { #ifdef CAN_RECONNECT /* XXX: any errornous address */ struct sockaddr_in no_addr; *************** *** 671,694 **** no_addr.sin_family = AF_INET; no_addr.sin_addr.s_addr = INADDR_ANY; no_addr.sin_port = 0; ! (void) _connect(s, (struct sockaddr *) &no_addr, sizeof no_addr); #else ! int s1 = _socket(af, SOCK_DGRAM,0); if (s1 < 0) goto bad_dg_sock; ! (void)_dup2(s1, s); (void)_close(s1); Dprint(_res.options & RES_DEBUG, (stdout, ";; new DG socket\n")) #endif /* CAN_RECONNECT */ ! connected = 0; errno = 0; } #endif /* !CANNOT_CONNECT_DGRAM */ ! if (_sendto(s, (char*)buf, buflen, 0, nsap, salen) != buflen) { Aerror(stderr, "sendto", errno, nsap); badns |= (1 << ns); --- 665,688 ---- no_addr.sin_family = AF_INET; no_addr.sin_addr.s_addr = INADDR_ANY; no_addr.sin_port = 0; ! (void) _connect(_res_data.s, (struct sockaddr *) &no_addr, sizeof no_addr); #else ! int s1 = _socket(_res_data.af, SOCK_DGRAM,0); if (s1 < 0) goto bad_dg_sock; ! (void)_dup2(s1, _res_data.s); (void)_close(s1); Dprint(_res.options & RES_DEBUG, (stdout, ";; new DG socket\n")) #endif /* CAN_RECONNECT */ ! _res_data.connected = 0; errno = 0; } #endif /* !CANNOT_CONNECT_DGRAM */ ! if (_sendto(_res_data.s, (char*)buf, buflen, 0, nsap, salen) != buflen) { Aerror(stderr, "sendto", errno, nsap); badns |= (1 << ns); *************** *** 713,725 **** (void) gettimeofday(&ctv, NULL); timeradd(&timeout, &ctv, &timeout); wait: ! if (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); n = _kevent(kq, &kv, 1, &kv, 1, &ts); if (n < 0) { --- 707,719 ---- (void) gettimeofday(&ctv, NULL); timeradd(&timeout, &ctv, &timeout); wait: ! if (_res_data.s < 0) { Perror(stderr, "s out-of-bounds", EMFILE); res_close(); goto next_ns; } ! 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) { *************** *** 749,755 **** } errno = 0; fromlen = sizeof(from); ! resplen = _recvfrom(s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); --- 743,749 ---- } errno = 0; fromlen = sizeof(from); ! resplen = _recvfrom(_res_data.s, (char*)ans, anssiz, 0, (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); *************** *** 854,866 **** !(_res.options & RES_STAYOPEN)) { res_close(); } ! if (Rhook) { int done = 0, loops = 0; do { res_sendhookact act; ! act = (*Rhook)((struct sockaddr_in *)nsap, buf, buflen, ans, anssiz, &resplen); switch (act) { --- 848,860 ---- !(_res.options & RES_STAYOPEN)) { res_close(); } ! if (_res_data.Rhook) { int done = 0, loops = 0; do { res_sendhookact act; ! act = (*_res_data.Rhook)((struct sockaddr_in *)nsap, buf, buflen, ans, anssiz, &resplen); switch (act) { *************** *** 912,923 **** void res_close() { ! if (s >= 0) { ! (void)_close(s); ! s = -1; ! connected = 0; ! vc = 0; ! af = 0; } } --- 906,917 ---- void res_close() { ! 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; } } *** src/lib/libc_r/sys/Makefile.inc.orig Wed Aug 8 23:25:32 2001 --- src/lib/libc_r/sys/Makefile.inc Wed Aug 8 23:26:13 2001 *************** *** 2,6 **** .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} ! SRCS+= uthread_error.c _atomic_lock.S --- 2,6 ---- .PATH: ${.CURDIR}/sys ${.CURDIR}/arch/${MACHINE_ARCH} ! SRCS+= uthread_error.c uthread_resolv.c _atomic_lock.S *** src/lib/libc_r/sys/uthread_resolv.c.orig Wed Aug 8 23:24:38 2001 --- src/lib/libc_r/sys/uthread_resolv.c Thu Aug 9 15:49:45 2001 *************** *** 0 **** --- 1,142 ---- + /*- + * Copyright (c) 2001 Alexandr Litvin + * 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. + * + */ + + #ifdef _THREAD_SAFE + #include + #include + #include + #include + #include + #include + #include + #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); + } + + #endif + >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message