diff options
author | Marco S Hyman <marc@cvs.openbsd.org> | 2003-01-28 04:58:01 +0000 |
---|---|---|
committer | Marco S Hyman <marc@cvs.openbsd.org> | 2003-01-28 04:58:01 +0000 |
commit | 93357d25160373499d1be166f2df69454a23b5ce (patch) | |
tree | a7f3c3fa5b4bd253c97080e2afa6b65819c90383 /lib/libc/net/res_init.c | |
parent | 06732d397fb40c90813f9782585e8d1d9fa1c367 (diff) |
thread safer libc (note: safer, not safe)
Access to the global _res structure replaced by pointers to a
per thread instance. If unthreaded the pointer is to the
global structure.
Also replaced a 64k stack array with malloc-ed memory so
threaded aps (with a default 64k stack) have a chance at working.
ok deraadt@
Diffstat (limited to 'lib/libc/net/res_init.c')
-rw-r--r-- | lib/libc/net/res_init.c | 187 |
1 files changed, 101 insertions, 86 deletions
diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index c55c7763a4e..a1d69f57b5e 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: res_init.c,v 1.27 2002/07/25 21:13:45 deraadt Exp $ */ +/* $OpenBSD: res_init.c,v 1.28 2003/01/28 04:58:00 marc Exp $ */ /* * ++Copyright++ 1985, 1989, 1993 @@ -64,7 +64,7 @@ static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; static char rcsid[] = "$From: res_init.c,v 8.7 1996/09/28 06:51:07 vixie Exp $"; #else -static char rcsid[] = "$OpenBSD: res_init.c,v 1.27 2002/07/25 21:13:45 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: res_init.c,v 1.28 2003/01/28 04:58:00 marc Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -86,6 +86,8 @@ static char rcsid[] = "$OpenBSD: res_init.c,v 1.27 2002/07/25 21:13:45 deraadt E #include <netdb.h> #endif /* INET6 */ +#include "thread_private.h" + /*-------------------------------------- info about "sortlist" -------------- * Marc Majka 1994/04/16 * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) @@ -120,6 +122,9 @@ static u_int32_t net_mask(struct in_addr); /* * Resolver state default settings. */ +volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res) = { + PTHREAD_ONCE_INIT, 0 +}; struct __res_state _res # if defined(__BIND_RES_TEXT) @@ -127,6 +132,10 @@ struct __res_state _res # endif ; #ifdef INET6 +volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext) = { + PTHREAD_ONCE_INIT, 0 +}; + struct __res_state_ext _res_ext; #endif /* INET6 */ @@ -154,6 +163,11 @@ struct __res_state_ext _res_ext; int res_init() { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); +#ifdef INET6 + struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext, + &_res_ext); +#endif register FILE *fp; register char *cp, **pp; register int n; @@ -189,33 +203,33 @@ res_init() * set in RES_DEFAULT). Our solution is to declare such applications * "broken". They could fool us by setting RES_INIT but none do (yet). */ - if (!_res.retrans) - _res.retrans = RES_TIMEOUT; - if (!_res.retry) - _res.retry = 4; - if (!(_res.options & RES_INIT)) - _res.options = RES_DEFAULT; + if (!_resp->retrans) + _resp->retrans = RES_TIMEOUT; + if (!_resp->retry) + _resp->retry = 4; + if (!(_resp->options & RES_INIT)) + _resp->options = RES_DEFAULT; #ifdef USELOOPBACK - _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); + _resp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); #else - _res.nsaddr.sin_addr.s_addr = INADDR_ANY; + _resp->nsaddr.sin_addr.s_addr = INADDR_ANY; #endif - _res.nsaddr.sin_family = AF_INET; - _res.nsaddr.sin_port = htons(NAMESERVER_PORT); - _res.nsaddr.sin_len = sizeof(struct sockaddr_in); + _resp->nsaddr.sin_family = AF_INET; + _resp->nsaddr.sin_port = htons(NAMESERVER_PORT); + _resp->nsaddr.sin_len = sizeof(struct sockaddr_in); #ifdef INET6 - if (sizeof(_res_ext.nsaddr) >= _res.nsaddr.sin_len) - memcpy(&_res_ext.nsaddr, &_res.nsaddr, _res.nsaddr.sin_len); + if (sizeof(_res_extp->nsaddr) >= _resp->nsaddr.sin_len) + memcpy(&_res_extp->nsaddr, &_resp->nsaddr, _resp->nsaddr.sin_len); #endif - _res.nscount = 1; - _res.ndots = 1; - _res.pfcode = 0; - strlcpy(_res.lookups, "f", sizeof _res.lookups); + _resp->nscount = 1; + _resp->ndots = 1; + _resp->pfcode = 0; + strlcpy(_resp->lookups, "f", sizeof _resp->lookups); /* Allow user to override the local domain definition */ if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) { - strlcpy(_res.defdname, cp, sizeof(_res.defdname)); + strlcpy(_resp->defdname, cp, sizeof(_resp->defdname)); haveenv++; /* @@ -225,10 +239,10 @@ res_init() * one that they want to use as an individual (even more * important now that the rfc1535 stuff restricts searches) */ - cp = _res.defdname; - pp = _res.dnsrch; + cp = _resp->defdname; + pp = _resp->dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) { if (*cp == '\n') /* silly backwards compat */ break; else if (*cp == ' ' || *cp == '\t') { @@ -253,7 +267,7 @@ res_init() line[sizeof(name) - 1] == '\t')) if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { - strlcpy(_res.lookups, "bf", sizeof _res.lookups); + strlcpy(_resp->lookups, "bf", sizeof _resp->lookups); /* read the config file */ buf[0] = '\0'; @@ -277,8 +291,8 @@ res_init() cp++; if ((*cp == '\0') || (*cp == '\n')) continue; - strlcpy(_res.defdname, cp, sizeof(_res.defdname)); - if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) + strlcpy(_resp->defdname, cp, sizeof(_resp->defdname)); + if ((cp = strpbrk(_resp->defdname, " \t\n")) != NULL) *cp = '\0'; havesearch = 0; continue; @@ -287,7 +301,7 @@ res_init() if (MATCH(buf, "lookup")) { char *sp = NULL; - bzero(_res.lookups, sizeof _res.lookups); + bzero(_resp->lookups, sizeof _resp->lookups); cp = buf + sizeof("lookup") - 1; for (n = 0;; cp++) { if (n == MAXDNSLUS) @@ -295,14 +309,14 @@ res_init() if ((*cp == '\0') || (*cp == '\n')) { if (sp) { if (*sp=='y' || *sp=='b' || *sp=='f') - _res.lookups[n++] = *sp; + _resp->lookups[n++] = *sp; sp = NULL; } break; } else if ((*cp == ' ') || (*cp == '\t') || (*cp == ',')) { if (sp) { if (*sp=='y' || *sp=='b' || *sp=='f') - _res.lookups[n++] = *sp; + _resp->lookups[n++] = *sp; sp = NULL; } } else if (sp == NULL) @@ -319,17 +333,17 @@ res_init() cp++; if ((*cp == '\0') || (*cp == '\n')) continue; - strlcpy(_res.defdname, cp, sizeof(_res.defdname)); - if ((cp = strchr(_res.defdname, '\n')) != NULL) + strlcpy(_resp->defdname, cp, sizeof(_resp->defdname)); + if ((cp = strchr(_resp->defdname, '\n')) != NULL) *cp = '\0'; /* * Set search list to be blank-separated strings * on rest of line. */ - cp = _res.defdname; - pp = _res.dnsrch; + cp = _resp->defdname; + pp = _resp->dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; *cp && pp < _resp->dnsrch + MAXDNSRCH; cp++) { if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; @@ -375,19 +389,19 @@ res_init() res = NULL; if (getaddrinfo(cp, pbuf, &hints, &res) == 0 && res->ai_next == NULL) { - if (res->ai_addrlen <= sizeof(_res_ext.nsaddr_list[nserv])) { - memcpy(&_res_ext.nsaddr_list[nserv], res->ai_addr, + if (res->ai_addrlen <= sizeof(_res_extp->nsaddr_list[nserv])) { + memcpy(&_res_extp->nsaddr_list[nserv], res->ai_addr, res->ai_addrlen); } else { - memset(&_res_ext.nsaddr_list[nserv], 0, - sizeof(_res_ext.nsaddr_list[nserv])); + memset(&_res_extp->nsaddr_list[nserv], 0, + sizeof(_res_extp->nsaddr_list[nserv])); } - if (res->ai_addrlen <= sizeof(_res.nsaddr_list[nserv])) { - memcpy(&_res.nsaddr_list[nserv], res->ai_addr, + if (res->ai_addrlen <= sizeof(_resp->nsaddr_list[nserv])) { + memcpy(&_resp->nsaddr_list[nserv], res->ai_addr, res->ai_addrlen); } else { - memset(&_res.nsaddr_list[nserv], 0, - sizeof(_res.nsaddr_list[nserv])); + memset(&_resp->nsaddr_list[nserv], 0, + sizeof(_resp->nsaddr_list[nserv])); } nserv++; } @@ -395,11 +409,11 @@ res_init() freeaddrinfo(res); #else /* INET6 */ if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { - _res.nsaddr_list[nserv].sin_addr = a; - _res.nsaddr_list[nserv].sin_family = AF_INET; - _res.nsaddr_list[nserv].sin_port = + _resp->nsaddr_list[nserv].sin_addr = a; + _resp->nsaddr_list[nserv].sin_family = AF_INET; + _resp->nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT); - _res.nsaddr_list[nserv].sin_len = + _resp->nsaddr_list[nserv].sin_len = sizeof(struct sockaddr_in); nserv++; } @@ -428,7 +442,7 @@ res_init() n = *cp; *cp = 0; if (inet_aton(net, &a)) { - _res.sort_list[nsort].addr = a; + _resp->sort_list[nsort].addr = a; if (ISSORTMASK(n)) { *cp++ = n; net = cp; @@ -438,29 +452,29 @@ res_init() n = *cp; *cp = 0; if (inet_aton(net, &a)) { - _res.sort_list[nsort].mask = a.s_addr; + _resp->sort_list[nsort].mask = a.s_addr; } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); + _resp->sort_list[nsort].mask = + net_mask(_resp->sort_list[nsort].addr); } } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); + _resp->sort_list[nsort].mask = + net_mask(_resp->sort_list[nsort].addr); } #ifdef INET6 - _res_ext.sort_list[nsort].af = AF_INET; - _res_ext.sort_list[nsort].addr.ina = - _res.sort_list[nsort].addr; - _res_ext.sort_list[nsort].mask.ina.s_addr = - _res.sort_list[nsort].mask; + _res_extp->sort_list[nsort].af = AF_INET; + _res_extp->sort_list[nsort].addr.ina = + _resp->sort_list[nsort].addr; + _res_extp->sort_list[nsort].mask.ina.s_addr = + _resp->sort_list[nsort].mask; #endif /* INET6 */ nsort++; } #ifdef INET6 else if (inet_pton(AF_INET6, net, &a6) == 1) { - _res_ext.sort_list[nsort].af = AF_INET6; - _res_ext.sort_list[nsort].addr.in6a = a6; - u = (u_char *)&_res_ext.sort_list[nsort].mask.in6a; + _res_extp->sort_list[nsort].af = AF_INET6; + _res_extp->sort_list[nsort].addr.in6a = a6; + u = (u_char *)&_res_extp->sort_list[nsort].mask.in6a; *cp++ = n; net = cp; while (*cp && *cp != ';' && @@ -510,33 +524,33 @@ res_init() } } if (nserv > 1) - _res.nscount = nserv; + _resp->nscount = nserv; #ifdef RESOLVSORT - _res.nsort = nsort; + _resp->nsort = nsort; #endif (void) fclose(fp); } - if (_res.defdname[0] == 0 && - gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + if (_resp->defdname[0] == 0 && + gethostname(buf, sizeof(_resp->defdname) - 1) == 0 && (cp = strchr(buf, '.')) != NULL) { - strlcpy(_res.defdname, cp + 1, - sizeof(_res.defdname)); + strlcpy(_resp->defdname, cp + 1, + sizeof(_resp->defdname)); } /* find components of local domain that might be searched */ if (havesearch == 0) { - pp = _res.dnsrch; - *pp++ = _res.defdname; + pp = _resp->dnsrch; + *pp++ = _resp->defdname; *pp = NULL; #ifndef RFC1535 dots = 0; - for (cp = _res.defdname; *cp; cp++) + for (cp = _resp->defdname; *cp; cp++) dots += (*cp == '.'); - cp = _res.defdname; - while (pp < _res.dnsrch + MAXDFLSRCH) { + cp = _resp->defdname; + while (pp < _resp->dnsrch + MAXDFLSRCH) { if (dots < LOCALDOMAINPARTS) break; cp = strchr(cp, '.') + 1; /* we know there is one */ @@ -545,9 +559,9 @@ res_init() } *pp = NULL; #ifdef DEBUG - if (_res.options & RES_DEBUG) { + if (_resp->options & RES_DEBUG) { printf(";; res_init()... default dnsrch list:\n"); - for (pp = _res.dnsrch; *pp; pp++) + for (pp = _resp->dnsrch; *pp; pp++) printf(";;\t%s\n", *pp); printf(";;\t..END..\n"); } @@ -556,10 +570,10 @@ res_init() } if (issetugid()) - _res.options |= RES_NOALIASES; + _resp->options |= RES_NOALIASES; else if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(cp, "env"); - _res.options |= RES_INIT; + _resp->options |= RES_INIT; return (0); } @@ -568,12 +582,13 @@ static void res_setoptions(options, source) char *options, *source; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); char *cp = options; char *endp; long l; #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (_resp->options & RES_DEBUG) printf(";; res_setoptions(\"%s\", \"%s\")...\n", options, source); #endif @@ -588,31 +603,31 @@ res_setoptions(options, source) if (l >= 0 && endp != p && (*endp = '\0' || isspace(*endp))) { if (l <= RES_MAXNDOTS) - _res.ndots = l; + _resp->ndots = l; else - _res.ndots = RES_MAXNDOTS; + _resp->ndots = RES_MAXNDOTS; #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";;\tndots=%u\n", _res.ndots); + if (_resp->options & RES_DEBUG) + printf(";;\tndots=%u\n", _resp->ndots); #endif } } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { #ifdef DEBUG - if (!(_res.options & RES_DEBUG)) { + if (!(_resp->options & RES_DEBUG)) { printf(";; res_setoptions(\"%s\", \"%s\")..\n", options, source); - _res.options |= RES_DEBUG; + _resp->options |= RES_DEBUG; } printf(";;\tdebug\n"); #endif } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { - _res.options |= RES_USE_INET6; + _resp->options |= RES_USE_INET6; } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) { - _res.options |= RES_INSECURE1; + _resp->options |= RES_INSECURE1; } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) { - _res.options |= RES_INSECURE2; + _resp->options |= RES_INSECURE2; } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) { - _res.options |= RES_USE_EDNS0; + _resp->options |= RES_USE_EDNS0; } else { /* XXX - print a warning here? */ } |