diff options
| author | Eric Andersen <andersen@codepoet.org> | 2007-02-02 01:28:36 (GMT) |
|---|---|---|
| committer | Eric Andersen <andersen@codepoet.org> | 2007-02-02 01:28:36 (GMT) |
| commit | 08b4b5e281451daf3b5e3c896b19e1187886f7e3 (patch) | |
| tree | 498780f4d1055291570b22a967d03668a87990b4 | |
| parent | 62a7782180447b91312ab2fdffc04ac19a5d58ab (diff) | |
| download | uClibc-08b4b5e281451daf3b5e3c896b19e1187886f7e3.tar.gz uClibc-08b4b5e281451daf3b5e3c896b19e1187886f7e3.tar.bz2 | |
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.
| -rw-r--r-- | libc/inet/addr.c | 4 | ||||
| -rw-r--r-- | libc/inet/hostid.c | 14 | ||||
| -rw-r--r-- | libc/inet/resolv.c | 47 |
3 files changed, 54 insertions, 11 deletions
diff --git a/libc/inet/addr.c b/libc/inet/addr.c index 5c4005a..db835e3 100644 --- a/libc/inet/addr.c +++ b/libc/inet/addr.c @@ -52,6 +52,10 @@ 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 e90cf25..efeedc9 100644 --- a/libc/inet/hostid.c +++ b/libc/inet/hostid.c @@ -56,7 +56,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 e1f274d..314ef57 100644 --- a/libc/inet/resolv.c +++ b/libc/inet/resolv.c @@ -180,6 +180,9 @@ __UCLIBC_MUTEX_EXTERN(__resolv_lock); /* Global stuff (stuff needing to be locked to be thread safe)... */ + +/* We use __resolv_lock to guard access to the + * '__nameservers' and __searchdomains globals */ extern int __nameservers; extern char * __nameserver[MAX_SERVERS]; extern int __searchdomains; @@ -965,7 +968,7 @@ 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 @@ -1096,12 +1099,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; @@ -1119,7 +1124,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++) { @@ -1217,8 +1221,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); } @@ -1237,7 +1247,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); @@ -1251,11 +1264,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++) { @@ -1304,7 +1321,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++; } } @@ -1350,14 +1370,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 |
