svn commit: trunk/uClibc/libc/inet

andersen at uclibc.org andersen at uclibc.org
Fri Feb 2 01:29:10 UTC 2007


Author: andersen
Date: 2007-02-01 17:29:10 -0800 (Thu, 01 Feb 2007)
New Revision: 17714

Log:
Ronald Maeder writes:
I have successfully made gethostbyname_r(), res_init(), and gethostid() fully
reentrant.  In addition, I have added a NULL check to inet_aton().  This is
where SEG FAULTs were coming from when gethostbyname_r() was called.


Modified:
   trunk/uClibc/libc/inet/addr.c
   trunk/uClibc/libc/inet/hostid.c
   trunk/uClibc/libc/inet/resolv.c


Changeset:
Modified: trunk/uClibc/libc/inet/addr.c
===================================================================
--- trunk/uClibc/libc/inet/addr.c	2007-02-02 01:28:36 UTC (rev 17713)
+++ trunk/uClibc/libc/inet/addr.c	2007-02-02 01:29:10 UTC (rev 17714)
@@ -55,6 +55,10 @@
 	int value;
 	int part;
 
+	if (cp == NULL) {	/* check for NULL arg */
+	    return 0;
+	}
+
 	addr = 0;
 	for (part = 1; part <= 4; part++) {
 

Modified: trunk/uClibc/libc/inet/hostid.c
===================================================================
--- trunk/uClibc/libc/inet/hostid.c	2007-02-02 01:28:36 UTC (rev 17713)
+++ trunk/uClibc/libc/inet/hostid.c	2007-02-02 01:29:10 UTC (rev 17714)
@@ -73,7 +73,19 @@
 		struct hostent *hp;
 		struct in_addr in;
 
-		if ((hp = gethostbyname(host)) == (struct hostent *)NULL)
+		/* replace gethostbyname() with gethostbyname_r() - ron at zing.net */
+		/*if ((hp = gethostbyname(host)) == (struct hostent *)NULL)*/
+		{
+		    struct hostent ghbn_h;
+		    char ghbn_buf[sizeof(struct in_addr) +
+				  sizeof(struct in_addr *)*2 +
+				  sizeof(char *)*((2 + 5/*MAX_ALIASES*/ +
+						   1)/*ALIAS_DIM*/) +
+				  256/*namebuffer*/ + 32/* margin */];
+		    int ghbn_errno;
+		    gethostbyname_r(host, &ghbn_h, ghbn_buf, sizeof(ghbn_buf), &hp, &ghbn_errno);
+		}
+		if (hp == (struct hostent *)NULL)
 
 		/* This is not a error if we get here, as all it means is that
 		 * this host is not on a network and/or they have not

Modified: trunk/uClibc/libc/inet/resolv.c
===================================================================
--- trunk/uClibc/libc/inet/resolv.c	2007-02-02 01:28:36 UTC (rev 17713)
+++ trunk/uClibc/libc/inet/resolv.c	2007-02-02 01:29:10 UTC (rev 17714)
@@ -1018,12 +1018,14 @@
 
 #ifdef L_opennameservers
 
+/* We use __resolv_lock to guard access to the
+ * '__nameservers' and __searchdomains globals */
 int __nameservers;
 char * __nameserver[MAX_SERVERS];
 int __searchdomains;
 char * __searchdomain[MAX_SEARCH];
 
-__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER);
+__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP);
 
 /*
  *	we currently read formats not quite the same as that on normal
@@ -1155,12 +1157,14 @@
 
 
 #ifdef L_res_init
+/* We use __resolv_lock to guard access to global '_res' */
 struct __res_state _res;
 
 int res_init(void)
 {
 	struct __res_state *rp = &(_res);
 
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);	/* must be a recursive lock! */
 	__close_nameservers();
 	__open_nameservers();
 	rp->retrans = RES_TIMEOUT;
@@ -1178,7 +1182,6 @@
 	/** rp->rhook = NULL; **/
 	/** rp->_u._ext.nsinit = 0; **/
 
-	__UCLIBC_MUTEX_LOCK(__resolv_lock);
 	if(__searchdomains) {
 		int i;
 		for(i=0; i<__searchdomains; i++) {
@@ -1278,8 +1281,14 @@
 	u_int dots;
 	int trailing_dot, ret, saved_herrno;
 	int got_nodata = 0, got_servfail = 0, tried_as_is = 0;
+	u_long _res_options;
+	unsigned _res_ndots;
+	char **_res_dnsrch;
 
-	if ((!name || !answer) || ((_res.options & RES_INIT) == 0 && res_init() == -1)) {
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_options = _res.options;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) {
 		h_errno = NETDB_INTERNAL;
 		return (-1);
 	}
@@ -1298,7 +1307,10 @@
 	 * 'as is'.  The threshold can be set with the "ndots" option.
 	 */
 	saved_herrno = -1;
-	if (dots >= _res.ndots) {
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_ndots = _res.ndots;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if (dots >= _res_ndots) {
 		ret = res_querydomain(name, NULL, class, type, answer, anslen);
 		if (ret > 0)
 			return (ret);
@@ -1312,11 +1324,15 @@
 	 *	- there is at least one dot, there is no trailing dot,
 	 *	  and RES_DNSRCH is set.
 	 */
-	if ((!dots && (_res.options & RES_DEFNAMES)) ||
-	    (dots && !trailing_dot && (_res.options & RES_DNSRCH))) {
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_options = _res.options;
+	_res_dnsrch = _res.dnsrch;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if ((!dots && (_res_options & RES_DEFNAMES)) ||
+	    (dots && !trailing_dot && (_res_options & RES_DNSRCH))) {
 		int done = 0;
 
-		for (domain = (const char * const *)_res.dnsrch;
+		for (domain = (const char * const *)_res_dnsrch;
 			 *domain && !done;
 			 domain++) {
 
@@ -1365,7 +1381,10 @@
 			 * if we got here for some reason other than DNSRCH,
 			 * we only wanted one iteration of the loop, so stop.
 			 */
-			if (!(_res.options & RES_DNSRCH))
+			__UCLIBC_MUTEX_LOCK(__resolv_lock);
+			_res_options = _res.options;
+			__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+			if (!(_res_options & RES_DNSRCH))
 				done++;
 		}
 	}
@@ -1411,14 +1430,21 @@
 	char nbuf[MAXDNAME];
 	const char *longname = nbuf;
 	size_t n, d;
+	u_long _res_options;
 
-	if ((!name || !answer) || ((_res.options & RES_INIT) == 0 && res_init() == -1)) {
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_options = _res.options;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if ((!name || !answer) || ((_res_options & RES_INIT) == 0 && res_init() == -1)) {
 		h_errno = NETDB_INTERNAL;
 		return (-1);
 	}
 
 #ifdef DEBUG
-	if (_res.options & RES_DEBUG)
+	__UCLIBC_MUTEX_LOCK(__resolv_lock);
+	_res_options = _res.options;
+	__UCLIBC_MUTEX_UNLOCK(__resolv_lock);
+	if (_res_options & RES_DEBUG)
 		printf(";; res_querydomain(%s, %s, %d, %d)\n",
 			   name, domain?domain:"<Nil>", class, type);
 #endif




More information about the uClibc-cvs mailing list