Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Aug 2001 16:02:24 -0400 (EDT)
From:      "Alexander Litvin"@FreeBSD.ORG, archer@whichever.org
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/29581: proposed gethostbyXXXX_r() implementation
Message-ID:  <200108092002.f79K2OT19276@unknown.whichever.org>

next in thread | raw e-mail | index | archive | help

>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 <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.
+  *
+  */
+ 
+ #ifdef _THREAD_SAFE
+ #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);
+ }
+ 
+ #endif
+ 
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108092002.f79K2OT19276>