summaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2007-02-02 01:29:10 +0000
committerEric Andersen <andersen@codepoet.org>2007-02-02 01:29:10 +0000
commit83b530eb6b7111486156fc5286a7f40742aeb2d0 (patch)
tree7aab0c2f107cbda453942a89f1a8eaed5a3ed48f /libc
parentf21e442f635260e070527637c04574a4fe95fb4b (diff)
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.
Diffstat (limited to 'libc')
-rw-r--r--libc/inet/addr.c4
-rw-r--r--libc/inet/hostid.c14
-rw-r--r--libc/inet/resolv.c46
3 files changed, 53 insertions, 11 deletions
diff --git a/libc/inet/addr.c b/libc/inet/addr.c
index ba2a022d6..94fa3aab7 100644
--- a/libc/inet/addr.c
+++ b/libc/inet/addr.c
@@ -55,6 +55,10 @@ int inet_aton(const char *cp, struct in_addr *addrptr)
int value;
int part;
+ if (cp == NULL) { /* check for NULL arg */
+ return 0;
+ }
+
addr = 0;
for (part = 1; part <= 4; part++) {
diff --git a/libc/inet/hostid.c b/libc/inet/hostid.c
index 716bffaf3..58dc13aec 100644
--- a/libc/inet/hostid.c
+++ b/libc/inet/hostid.c
@@ -73,7 +73,19 @@ long int gethostid(void)
struct hostent *hp;
struct in_addr in;
- if ((hp = gethostbyname(host)) == (struct hostent *)NULL)
+ /* replace gethostbyname() with gethostbyname_r() - ron@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
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index 59819819e..973b787ec 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -1018,12 +1018,14 @@ int attribute_hidden __dns_lookup(const char *name, int type, int nscount, char
#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 @@ struct hostent *gethostbyname2(const char *name, int family)
#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 @@ int res_init(void)
/** 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 @@ int res_search(name, class, type, answer, anslen)
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 @@ int res_search(name, class, type, answer, anslen)
* '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 @@ int res_search(name, class, type, answer, anslen)
* - 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 @@ int res_search(name, class, type, answer, anslen)
* 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 @@ int res_querydomain(name, domain, class, type, answer, anslen)
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