From 547ebab319b228b064cf5dcb3ff0ae1bf23d24a2 Mon Sep 17 00:00:00 2001 From: marc <> Date: Tue, 28 Jan 2003 04:58:00 +0000 Subject: 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@ --- src/lib/libc/net/res_send.c | 109 ++++++++++++++++++++++++-------------------- 1 file changed, 59 insertions(+), 50 deletions(-) (limited to 'src/lib/libc/net/res_send.c') diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c index b043e7c9fb..282675a533 100644 --- a/src/lib/libc/net/res_send.c +++ b/src/lib/libc/net/res_send.c @@ -1,4 +1,4 @@ -/* $OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $ */ +/* $OpenBSD: res_send.c,v 1.13 2003/01/28 04:58:00 marc Exp $ */ /* * ++Copyright++ 1985, 1989, 1993 @@ -64,7 +64,7 @@ static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $"; #else -static char rcsid[] = "$OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: res_send.c,v 1.13 2003/01/28 04:58:00 marc Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -96,6 +96,8 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt E #include #include +#include "thread_private.h" + static int s = -1; /* socket used for communications */ static int connected = 0; /* is the socket connected */ static int vc = 0; /* is the socket a virtual ciruit? */ @@ -136,9 +138,10 @@ static void Perror(FILE *, char *, int); int error; struct sockaddr *address; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); int save = errno; - if (_res.options & RES_DEBUG) { + if (_resp->options & RES_DEBUG) { if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf), pbuf, sizeof(pbuf), NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) { @@ -156,9 +159,10 @@ static void Perror(FILE *, char *, int); char *string; int error; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); int save = errno; - if (_res.options & RES_DEBUG) { + if (_resp->options & RES_DEBUG) { fprintf(file, "res_send: %s: %s\n", string, strerror(error)); } @@ -195,30 +199,33 @@ static struct sockaddr * get_nsaddr(n) size_t n; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); + struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext, + &_res_ext); - if (!_res.nsaddr_list[n].sin_family) { + if (!_resp->nsaddr_list[n].sin_family) { /* - * - _res_ext.nsaddr_list[n] holds an address that is larger + * - _res_extp->nsaddr_list[n] holds an address that is larger * than struct sockaddr, and - * - user code did not update _res.nsaddr_list[n]. + * - user code did not update _resp->nsaddr_list[n]. */ - return (struct sockaddr *)&_res_ext.nsaddr_list[n]; + return (struct sockaddr *)&_res_extp->nsaddr_list[n]; } else { /* * - user code updated _res.nsaddr_list[n], or - * - _res.nsaddr_list[n] has the same content as - * _res_ext.nsaddr_list[n]. + * - _resp->nsaddr_list[n] has the same content as + * _res_extp->nsaddr_list[n]. */ - return (struct sockaddr *)&_res.nsaddr_list[n]; + return (struct sockaddr *)&_resp->nsaddr_list[n]; } } #else -#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)]) +#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)]) #endif /* int * res_isourserver(ina) - * looks up "ina" in _res.ns_addr_list[] + * looks up "ina" in _resp->ns_addr_list[] * returns: * 0 : not found * >0 : found @@ -229,6 +236,7 @@ int res_isourserver(inp) const struct sockaddr_in *inp; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); #ifdef INET6 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp; const struct sockaddr_in6 *srv6; @@ -240,7 +248,7 @@ res_isourserver(inp) switch (inp->sin_family) { #ifdef INET6 case AF_INET6: - for (ns = 0; ns < _res.nscount; ns++) { + for (ns = 0; ns < _resp->nscount; ns++) { srv6 = (struct sockaddr_in6 *)get_nsaddr(ns); if (srv6->sin6_family == in6p->sin6_family && srv6->sin6_port == in6p->sin6_port && @@ -255,7 +263,7 @@ res_isourserver(inp) break; #endif case AF_INET: - for (ns = 0; ns < _res.nscount; ns++) { + for (ns = 0; ns < _resp->nscount; ns++) { srv = (struct sockaddr_in *)get_nsaddr(ns); if (srv->sin_family == inp->sin_family && srv->sin_port == inp->sin_port && @@ -351,19 +359,20 @@ res_send(buf, buflen, ans, anssiz) u_char *ans; int anssiz; { + struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res); HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) ans; int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; register int n; u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if ((_resp->options & RES_INIT) == 0 && res_init() == -1) { /* errno should have been set by res_init() in this case. */ return (-1); } - DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), + DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY), (stdout, ";; res_send()\n"), buf, buflen); - v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; + v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ; gotsomewhere = 0; connreset = 0; terrno = ETIMEDOUT; @@ -372,8 +381,8 @@ res_send(buf, buflen, ans, anssiz) /* * Send request, RETRY times, or until successful */ - for (try = 0; try < _res.retry; try++) { - for (ns = 0; ns < _res.nscount; ns++) { + for (try = 0; try < _resp->retry; try++) { + for (ns = 0; ns < _resp->nscount; ns++) { struct sockaddr *nsap = get_nsaddr(ns); socklen_t salen; @@ -425,7 +434,7 @@ res_send(buf, buflen, ans, anssiz) } while (!done); } - Dprint((_res.options & RES_DEBUG) && + Dprint((_resp->options & RES_DEBUG) && getnameinfo(nsap, salen, abuf, sizeof(abuf), NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0, (stdout, ";; Querying server (# %d) address = %s\n", @@ -441,7 +450,7 @@ res_send(buf, buflen, ans, anssiz) * Use virtual circuit; * at most one attempt per server. */ - try = _res.retry; + try = _resp->retry; truncated = 0; if ((s < 0) || (!vc) || (af != nsap->sa_family)) { if (s >= 0) @@ -520,7 +529,7 @@ read_len: } resplen = _getshort(ans); if (resplen > anssiz) { - Dprint(_res.options & RES_DEBUG, + Dprint(_resp->options & RES_DEBUG, (stdout, ";; response truncated\n") ); truncated = 1; @@ -566,8 +575,8 @@ read_len: * wait for the correct one. */ if (hp->id != anhp->id) { - DprintQ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY), + DprintQ((_resp->options & RES_DEBUG) || + (_resp->pfcode & RES_PRF_REPLY), (stdout, ";; old answer (unexpected):\n"), ans, (resplen>anssiz)?anssiz:resplen); goto read_len; @@ -625,8 +634,8 @@ read_len: * as we wish to receive answers from the first * server to respond. */ - if (!(_res.options & RES_INSECURE1) && - (_res.nscount == 1 || (try == 0 && ns == 0))) { + if (!(_resp->options & RES_INSECURE1) && + (_resp->nscount == 1 || (try == 0 && ns == 0))) { /* * Connect only if we are sure we won't * receive a response from another server. @@ -673,7 +682,7 @@ read_len: goto bad_dg_sock; (void) dup2(s1, s); (void) close(s1); - Dprint(_res.options & RES_DEBUG, + Dprint(_resp->options & RES_DEBUG, (stdout, ";; new DG socket\n")) #endif #ifdef IPV6_MINMTU @@ -699,9 +708,9 @@ read_len: /* * Wait for reply */ - timeout.tv_sec = (_res.retrans << try); + timeout.tv_sec = (_resp->retrans << try); if (try > 0) - timeout.tv_sec /= _res.nscount; + timeout.tv_sec /= _resp->nscount; if ((long) timeout.tv_sec <= 0) timeout.tv_sec = 1; timeout.tv_usec = 0; @@ -727,7 +736,7 @@ read_len: /* * timeout */ - Dprint(_res.options & RES_DEBUG, + Dprint(_resp->options & RES_DEBUG, (stdout, ";; timeout\n")); gotsomewhere = 1; res_close(); @@ -749,28 +758,28 @@ read_len: * XXX - potential security hazard could * be detected here. */ - DprintQ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY), + DprintQ((_resp->options & RES_DEBUG) || + (_resp->pfcode & RES_PRF_REPLY), (stdout, ";; old answer:\n"), ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #if CHECK_SRVR_ADDR - if (!(_res.options & RES_INSECURE1) && + if (!(_resp->options & RES_INSECURE1) && !res_isourserver((struct sockaddr_in *)&from)) { /* * response from wrong server? ignore it. * XXX - potential security hazard could * be detected here. */ - DprintQ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY), + DprintQ((_resp->options & RES_DEBUG) || + (_resp->pfcode & RES_PRF_REPLY), (stdout, ";; not our server:\n"), ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #endif - if (!(_res.options & RES_INSECURE2) && + if (!(_resp->options & RES_INSECURE2) && !res_queriesmatch(buf, buf + buflen, ans, ans + anssiz)) { /* @@ -778,8 +787,8 @@ read_len: * XXX - potential security hazard could * be detected here. */ - DprintQ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY), + DprintQ((_resp->options & RES_DEBUG) || + (_resp->pfcode & RES_PRF_REPLY), (stdout, ";; wrong query name:\n"), ans, (resplen>anssiz)?anssiz:resplen); goto wait; @@ -787,33 +796,33 @@ read_len: if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) { - DprintQ(_res.options & RES_DEBUG, + DprintQ(_resp->options & RES_DEBUG, (stdout, "server rejected query:\n"), ans, (resplen>anssiz)?anssiz:resplen); badns |= (1 << ns); res_close(); /* don't retry if called from dig */ - if (!_res.pfcode) + if (!_resp->pfcode) goto next_ns; } - if (!(_res.options & RES_IGNTC) && anhp->tc) { + if (!(_resp->options & RES_IGNTC) && anhp->tc) { /* * get rest of answer; * use TCP with same server. */ - Dprint(_res.options & RES_DEBUG, + Dprint(_resp->options & RES_DEBUG, (stdout, ";; truncated answer\n")); v_circuit = 1; res_close(); goto same_ns; } } /*if vc/dg*/ - Dprint((_res.options & RES_DEBUG) || - ((_res.pfcode & RES_PRF_REPLY) && - (_res.pfcode & RES_PRF_HEAD1)), + Dprint((_resp->options & RES_DEBUG) || + ((_resp->pfcode & RES_PRF_REPLY) && + (_resp->pfcode & RES_PRF_HEAD1)), (stdout, ";; got answer:\n")); - DprintQ((_res.options & RES_DEBUG) || - (_res.pfcode & RES_PRF_REPLY), + DprintQ((_resp->options & RES_DEBUG) || + (_resp->pfcode & RES_PRF_REPLY), (stdout, "%s", ""), ans, (resplen>anssiz)?anssiz:resplen); /* @@ -824,8 +833,8 @@ read_len: * or if we haven't been asked to keep a socket open, * close the socket. */ - if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || - !(_res.options & RES_STAYOPEN)) { + if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) || + !(_resp->options & RES_STAYOPEN)) { res_close(); } if (Rhook) { -- cgit v1.2.3-55-g6feb