diff options
| -rw-r--r-- | lib/libc/net/getnameinfo.c | 26 | 
1 files changed, 24 insertions, 2 deletions
| diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index cee07f6e0fe73..9f60ae30910cd 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -46,6 +46,7 @@  #include <sys/cdefs.h>  __FBSDID("$FreeBSD$"); +#include "namespace.h"  #include <sys/types.h>  #include <sys/socket.h>  #include <net/if.h> @@ -53,10 +54,12 @@ __FBSDID("$FreeBSD$");  #include <arpa/inet.h>  #include <arpa/nameser.h>  #include <netdb.h> +#include <pthread.h>  #include <resolv.h>  #include <string.h>  #include <stddef.h>  #include <errno.h> +#include "un-namespace.h"  static const struct afd {  	int a_af; @@ -85,6 +88,19 @@ static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,  static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);  #endif +/* + * XXX: Many dependencies are not thread-safe.  So, we share lock between + * getaddrinfo() and getipnodeby*().  Still, we cannot use + * getaddrinfo() and getipnodeby*() in conjunction with other + * functions which call them. + */ +#include "libc_private.h" +extern pthread_mutex_t __getaddrinfo_thread_lock; +#define THREAD_LOCK() \ +	if (__isthreaded) _pthread_mutex_lock(&__getaddrinfo_thread_lock); +#define THREAD_UNLOCK() \ +	if (__isthreaded) _pthread_mutex_unlock(&__getaddrinfo_thread_lock); +  int  getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)  	const struct sockaddr *sa; @@ -136,6 +152,7 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)  		 * servlen == 0 means that the caller does not want the result.  		 */  	} else { +		THREAD_LOCK();  		if (flags & NI_NUMERICSERV)  			sp = NULL;  		else { @@ -143,15 +160,20 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)  				(flags & NI_DGRAM) ? "udp" : "tcp");  		}  		if (sp) { -			if (strlen(sp->s_name) + 1 > servlen) +			if (strlen(sp->s_name) + 1 > servlen) { +				THREAD_UNLOCK();  				return EAI_MEMORY; +			}  			strlcpy(serv, sp->s_name, servlen);  		} else {  			snprintf(numserv, sizeof(numserv), "%u", ntohs(port)); -			if (strlen(numserv) + 1 > servlen) +			if (strlen(numserv) + 1 > servlen) { +				THREAD_UNLOCK();  				return EAI_MEMORY; +			}  			strlcpy(serv, numserv, servlen);  		} +		THREAD_UNLOCK();  	}  	switch (sa->sa_family) { | 
