summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2007-02-02 01:28:36 (GMT)
committer Eric Andersen <andersen@codepoet.org>2007-02-02 01:28:36 (GMT)
commit08b4b5e281451daf3b5e3c896b19e1187886f7e3 (patch)
tree498780f4d1055291570b22a967d03668a87990b4
parent62a7782180447b91312ab2fdffc04ac19a5d58ab (diff)
downloaduClibc-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.c4
-rw-r--r--libc/inet/hostid.c14
-rw-r--r--libc/inet/resolv.c47
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