summaryrefslogtreecommitdiff
path: root/src/lib/libc/net/res_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libc/net/res_send.c')
-rw-r--r--src/lib/libc/net/res_send.c109
1 files changed, 59 insertions, 50 deletions
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 @@
1/* $OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $ */ 1/* $OpenBSD: res_send.c,v 1.13 2003/01/28 04:58:00 marc Exp $ */
2 2
3/* 3/*
4 * ++Copyright++ 1985, 1989, 1993 4 * ++Copyright++ 1985, 1989, 1993
@@ -64,7 +64,7 @@
64static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; 64static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
65static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $"; 65static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
66#else 66#else
67static char rcsid[] = "$OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt Exp $"; 67static char rcsid[] = "$OpenBSD: res_send.c,v 1.13 2003/01/28 04:58:00 marc Exp $";
68#endif 68#endif
69#endif /* LIBC_SCCS and not lint */ 69#endif /* LIBC_SCCS and not lint */
70 70
@@ -96,6 +96,8 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.12 2002/09/06 18:35:12 deraadt E
96#include <string.h> 96#include <string.h>
97#include <unistd.h> 97#include <unistd.h>
98 98
99#include "thread_private.h"
100
99static int s = -1; /* socket used for communications */ 101static int s = -1; /* socket used for communications */
100static int connected = 0; /* is the socket connected */ 102static int connected = 0; /* is the socket connected */
101static int vc = 0; /* is the socket a virtual ciruit? */ 103static int vc = 0; /* is the socket a virtual ciruit? */
@@ -136,9 +138,10 @@ static void Perror(FILE *, char *, int);
136 int error; 138 int error;
137 struct sockaddr *address; 139 struct sockaddr *address;
138 { 140 {
141 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
139 int save = errno; 142 int save = errno;
140 143
141 if (_res.options & RES_DEBUG) { 144 if (_resp->options & RES_DEBUG) {
142 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf), 145 if (getnameinfo(address, address->sa_len, abuf, sizeof(abuf),
143 pbuf, sizeof(pbuf), 146 pbuf, sizeof(pbuf),
144 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) { 147 NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID) != 0) {
@@ -156,9 +159,10 @@ static void Perror(FILE *, char *, int);
156 char *string; 159 char *string;
157 int error; 160 int error;
158 { 161 {
162 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
159 int save = errno; 163 int save = errno;
160 164
161 if (_res.options & RES_DEBUG) { 165 if (_resp->options & RES_DEBUG) {
162 fprintf(file, "res_send: %s: %s\n", 166 fprintf(file, "res_send: %s: %s\n",
163 string, strerror(error)); 167 string, strerror(error));
164 } 168 }
@@ -195,30 +199,33 @@ static struct sockaddr *
195get_nsaddr(n) 199get_nsaddr(n)
196 size_t n; 200 size_t n;
197{ 201{
202 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
203 struct __res_state_ext *_res_extp = _THREAD_PRIVATE(_res_ext, _res_ext,
204 &_res_ext);
198 205
199 if (!_res.nsaddr_list[n].sin_family) { 206 if (!_resp->nsaddr_list[n].sin_family) {
200 /* 207 /*
201 * - _res_ext.nsaddr_list[n] holds an address that is larger 208 * - _res_extp->nsaddr_list[n] holds an address that is larger
202 * than struct sockaddr, and 209 * than struct sockaddr, and
203 * - user code did not update _res.nsaddr_list[n]. 210 * - user code did not update _resp->nsaddr_list[n].
204 */ 211 */
205 return (struct sockaddr *)&_res_ext.nsaddr_list[n]; 212 return (struct sockaddr *)&_res_extp->nsaddr_list[n];
206 } else { 213 } else {
207 /* 214 /*
208 * - user code updated _res.nsaddr_list[n], or 215 * - user code updated _res.nsaddr_list[n], or
209 * - _res.nsaddr_list[n] has the same content as 216 * - _resp->nsaddr_list[n] has the same content as
210 * _res_ext.nsaddr_list[n]. 217 * _res_extp->nsaddr_list[n].
211 */ 218 */
212 return (struct sockaddr *)&_res.nsaddr_list[n]; 219 return (struct sockaddr *)&_resp->nsaddr_list[n];
213 } 220 }
214} 221}
215#else 222#else
216#define get_nsaddr(n) ((struct sockaddr *)&_res.nsaddr_list[(n)]) 223#define get_nsaddr(n) ((struct sockaddr *)&_resp->nsaddr_list[(n)])
217#endif 224#endif
218 225
219/* int 226/* int
220 * res_isourserver(ina) 227 * res_isourserver(ina)
221 * looks up "ina" in _res.ns_addr_list[] 228 * looks up "ina" in _resp->ns_addr_list[]
222 * returns: 229 * returns:
223 * 0 : not found 230 * 0 : not found
224 * >0 : found 231 * >0 : found
@@ -229,6 +236,7 @@ int
229res_isourserver(inp) 236res_isourserver(inp)
230 const struct sockaddr_in *inp; 237 const struct sockaddr_in *inp;
231{ 238{
239 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
232#ifdef INET6 240#ifdef INET6
233 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp; 241 const struct sockaddr_in6 *in6p = (const struct sockaddr_in6 *)inp;
234 const struct sockaddr_in6 *srv6; 242 const struct sockaddr_in6 *srv6;
@@ -240,7 +248,7 @@ res_isourserver(inp)
240 switch (inp->sin_family) { 248 switch (inp->sin_family) {
241#ifdef INET6 249#ifdef INET6
242 case AF_INET6: 250 case AF_INET6:
243 for (ns = 0; ns < _res.nscount; ns++) { 251 for (ns = 0; ns < _resp->nscount; ns++) {
244 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns); 252 srv6 = (struct sockaddr_in6 *)get_nsaddr(ns);
245 if (srv6->sin6_family == in6p->sin6_family && 253 if (srv6->sin6_family == in6p->sin6_family &&
246 srv6->sin6_port == in6p->sin6_port && 254 srv6->sin6_port == in6p->sin6_port &&
@@ -255,7 +263,7 @@ res_isourserver(inp)
255 break; 263 break;
256#endif 264#endif
257 case AF_INET: 265 case AF_INET:
258 for (ns = 0; ns < _res.nscount; ns++) { 266 for (ns = 0; ns < _resp->nscount; ns++) {
259 srv = (struct sockaddr_in *)get_nsaddr(ns); 267 srv = (struct sockaddr_in *)get_nsaddr(ns);
260 if (srv->sin_family == inp->sin_family && 268 if (srv->sin_family == inp->sin_family &&
261 srv->sin_port == inp->sin_port && 269 srv->sin_port == inp->sin_port &&
@@ -351,19 +359,20 @@ res_send(buf, buflen, ans, anssiz)
351 u_char *ans; 359 u_char *ans;
352 int anssiz; 360 int anssiz;
353{ 361{
362 struct __res_state *_resp = _THREAD_PRIVATE(_res, _res, &_res);
354 HEADER *hp = (HEADER *) buf; 363 HEADER *hp = (HEADER *) buf;
355 HEADER *anhp = (HEADER *) ans; 364 HEADER *anhp = (HEADER *) ans;
356 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns; 365 int gotsomewhere, connreset, terrno, try, v_circuit, resplen, ns;
357 register int n; 366 register int n;
358 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */ 367 u_int badns; /* XXX NSMAX can't exceed #/bits in this var */
359 368
360 if ((_res.options & RES_INIT) == 0 && res_init() == -1) { 369 if ((_resp->options & RES_INIT) == 0 && res_init() == -1) {
361 /* errno should have been set by res_init() in this case. */ 370 /* errno should have been set by res_init() in this case. */
362 return (-1); 371 return (-1);
363 } 372 }
364 DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_QUERY), 373 DprintQ((_resp->options & RES_DEBUG) || (_resp->pfcode & RES_PRF_QUERY),
365 (stdout, ";; res_send()\n"), buf, buflen); 374 (stdout, ";; res_send()\n"), buf, buflen);
366 v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; 375 v_circuit = (_resp->options & RES_USEVC) || buflen > PACKETSZ;
367 gotsomewhere = 0; 376 gotsomewhere = 0;
368 connreset = 0; 377 connreset = 0;
369 terrno = ETIMEDOUT; 378 terrno = ETIMEDOUT;
@@ -372,8 +381,8 @@ res_send(buf, buflen, ans, anssiz)
372 /* 381 /*
373 * Send request, RETRY times, or until successful 382 * Send request, RETRY times, or until successful
374 */ 383 */
375 for (try = 0; try < _res.retry; try++) { 384 for (try = 0; try < _resp->retry; try++) {
376 for (ns = 0; ns < _res.nscount; ns++) { 385 for (ns = 0; ns < _resp->nscount; ns++) {
377 struct sockaddr *nsap = get_nsaddr(ns); 386 struct sockaddr *nsap = get_nsaddr(ns);
378 socklen_t salen; 387 socklen_t salen;
379 388
@@ -425,7 +434,7 @@ res_send(buf, buflen, ans, anssiz)
425 } while (!done); 434 } while (!done);
426 } 435 }
427 436
428 Dprint((_res.options & RES_DEBUG) && 437 Dprint((_resp->options & RES_DEBUG) &&
429 getnameinfo(nsap, salen, abuf, sizeof(abuf), 438 getnameinfo(nsap, salen, abuf, sizeof(abuf),
430 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0, 439 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) == 0,
431 (stdout, ";; Querying server (# %d) address = %s\n", 440 (stdout, ";; Querying server (# %d) address = %s\n",
@@ -441,7 +450,7 @@ res_send(buf, buflen, ans, anssiz)
441 * Use virtual circuit; 450 * Use virtual circuit;
442 * at most one attempt per server. 451 * at most one attempt per server.
443 */ 452 */
444 try = _res.retry; 453 try = _resp->retry;
445 truncated = 0; 454 truncated = 0;
446 if ((s < 0) || (!vc) || (af != nsap->sa_family)) { 455 if ((s < 0) || (!vc) || (af != nsap->sa_family)) {
447 if (s >= 0) 456 if (s >= 0)
@@ -520,7 +529,7 @@ read_len:
520 } 529 }
521 resplen = _getshort(ans); 530 resplen = _getshort(ans);
522 if (resplen > anssiz) { 531 if (resplen > anssiz) {
523 Dprint(_res.options & RES_DEBUG, 532 Dprint(_resp->options & RES_DEBUG,
524 (stdout, ";; response truncated\n") 533 (stdout, ";; response truncated\n")
525 ); 534 );
526 truncated = 1; 535 truncated = 1;
@@ -566,8 +575,8 @@ read_len:
566 * wait for the correct one. 575 * wait for the correct one.
567 */ 576 */
568 if (hp->id != anhp->id) { 577 if (hp->id != anhp->id) {
569 DprintQ((_res.options & RES_DEBUG) || 578 DprintQ((_resp->options & RES_DEBUG) ||
570 (_res.pfcode & RES_PRF_REPLY), 579 (_resp->pfcode & RES_PRF_REPLY),
571 (stdout, ";; old answer (unexpected):\n"), 580 (stdout, ";; old answer (unexpected):\n"),
572 ans, (resplen>anssiz)?anssiz:resplen); 581 ans, (resplen>anssiz)?anssiz:resplen);
573 goto read_len; 582 goto read_len;
@@ -625,8 +634,8 @@ read_len:
625 * as we wish to receive answers from the first 634 * as we wish to receive answers from the first
626 * server to respond. 635 * server to respond.
627 */ 636 */
628 if (!(_res.options & RES_INSECURE1) && 637 if (!(_resp->options & RES_INSECURE1) &&
629 (_res.nscount == 1 || (try == 0 && ns == 0))) { 638 (_resp->nscount == 1 || (try == 0 && ns == 0))) {
630 /* 639 /*
631 * Connect only if we are sure we won't 640 * Connect only if we are sure we won't
632 * receive a response from another server. 641 * receive a response from another server.
@@ -673,7 +682,7 @@ read_len:
673 goto bad_dg_sock; 682 goto bad_dg_sock;
674 (void) dup2(s1, s); 683 (void) dup2(s1, s);
675 (void) close(s1); 684 (void) close(s1);
676 Dprint(_res.options & RES_DEBUG, 685 Dprint(_resp->options & RES_DEBUG,
677 (stdout, ";; new DG socket\n")) 686 (stdout, ";; new DG socket\n"))
678#endif 687#endif
679#ifdef IPV6_MINMTU 688#ifdef IPV6_MINMTU
@@ -699,9 +708,9 @@ read_len:
699 /* 708 /*
700 * Wait for reply 709 * Wait for reply
701 */ 710 */
702 timeout.tv_sec = (_res.retrans << try); 711 timeout.tv_sec = (_resp->retrans << try);
703 if (try > 0) 712 if (try > 0)
704 timeout.tv_sec /= _res.nscount; 713 timeout.tv_sec /= _resp->nscount;
705 if ((long) timeout.tv_sec <= 0) 714 if ((long) timeout.tv_sec <= 0)
706 timeout.tv_sec = 1; 715 timeout.tv_sec = 1;
707 timeout.tv_usec = 0; 716 timeout.tv_usec = 0;
@@ -727,7 +736,7 @@ read_len:
727 /* 736 /*
728 * timeout 737 * timeout
729 */ 738 */
730 Dprint(_res.options & RES_DEBUG, 739 Dprint(_resp->options & RES_DEBUG,
731 (stdout, ";; timeout\n")); 740 (stdout, ";; timeout\n"));
732 gotsomewhere = 1; 741 gotsomewhere = 1;
733 res_close(); 742 res_close();
@@ -749,28 +758,28 @@ read_len:
749 * XXX - potential security hazard could 758 * XXX - potential security hazard could
750 * be detected here. 759 * be detected here.
751 */ 760 */
752 DprintQ((_res.options & RES_DEBUG) || 761 DprintQ((_resp->options & RES_DEBUG) ||
753 (_res.pfcode & RES_PRF_REPLY), 762 (_resp->pfcode & RES_PRF_REPLY),
754 (stdout, ";; old answer:\n"), 763 (stdout, ";; old answer:\n"),
755 ans, (resplen>anssiz)?anssiz:resplen); 764 ans, (resplen>anssiz)?anssiz:resplen);
756 goto wait; 765 goto wait;
757 } 766 }
758#if CHECK_SRVR_ADDR 767#if CHECK_SRVR_ADDR
759 if (!(_res.options & RES_INSECURE1) && 768 if (!(_resp->options & RES_INSECURE1) &&
760 !res_isourserver((struct sockaddr_in *)&from)) { 769 !res_isourserver((struct sockaddr_in *)&from)) {
761 /* 770 /*
762 * response from wrong server? ignore it. 771 * response from wrong server? ignore it.
763 * XXX - potential security hazard could 772 * XXX - potential security hazard could
764 * be detected here. 773 * be detected here.
765 */ 774 */
766 DprintQ((_res.options & RES_DEBUG) || 775 DprintQ((_resp->options & RES_DEBUG) ||
767 (_res.pfcode & RES_PRF_REPLY), 776 (_resp->pfcode & RES_PRF_REPLY),
768 (stdout, ";; not our server:\n"), 777 (stdout, ";; not our server:\n"),
769 ans, (resplen>anssiz)?anssiz:resplen); 778 ans, (resplen>anssiz)?anssiz:resplen);
770 goto wait; 779 goto wait;
771 } 780 }
772#endif 781#endif
773 if (!(_res.options & RES_INSECURE2) && 782 if (!(_resp->options & RES_INSECURE2) &&
774 !res_queriesmatch(buf, buf + buflen, 783 !res_queriesmatch(buf, buf + buflen,
775 ans, ans + anssiz)) { 784 ans, ans + anssiz)) {
776 /* 785 /*
@@ -778,8 +787,8 @@ read_len:
778 * XXX - potential security hazard could 787 * XXX - potential security hazard could
779 * be detected here. 788 * be detected here.
780 */ 789 */
781 DprintQ((_res.options & RES_DEBUG) || 790 DprintQ((_resp->options & RES_DEBUG) ||
782 (_res.pfcode & RES_PRF_REPLY), 791 (_resp->pfcode & RES_PRF_REPLY),
783 (stdout, ";; wrong query name:\n"), 792 (stdout, ";; wrong query name:\n"),
784 ans, (resplen>anssiz)?anssiz:resplen); 793 ans, (resplen>anssiz)?anssiz:resplen);
785 goto wait; 794 goto wait;
@@ -787,33 +796,33 @@ read_len:
787 if (anhp->rcode == SERVFAIL || 796 if (anhp->rcode == SERVFAIL ||
788 anhp->rcode == NOTIMP || 797 anhp->rcode == NOTIMP ||
789 anhp->rcode == REFUSED) { 798 anhp->rcode == REFUSED) {
790 DprintQ(_res.options & RES_DEBUG, 799 DprintQ(_resp->options & RES_DEBUG,
791 (stdout, "server rejected query:\n"), 800 (stdout, "server rejected query:\n"),
792 ans, (resplen>anssiz)?anssiz:resplen); 801 ans, (resplen>anssiz)?anssiz:resplen);
793 badns |= (1 << ns); 802 badns |= (1 << ns);
794 res_close(); 803 res_close();
795 /* don't retry if called from dig */ 804 /* don't retry if called from dig */
796 if (!_res.pfcode) 805 if (!_resp->pfcode)
797 goto next_ns; 806 goto next_ns;
798 } 807 }
799 if (!(_res.options & RES_IGNTC) && anhp->tc) { 808 if (!(_resp->options & RES_IGNTC) && anhp->tc) {
800 /* 809 /*
801 * get rest of answer; 810 * get rest of answer;
802 * use TCP with same server. 811 * use TCP with same server.
803 */ 812 */
804 Dprint(_res.options & RES_DEBUG, 813 Dprint(_resp->options & RES_DEBUG,
805 (stdout, ";; truncated answer\n")); 814 (stdout, ";; truncated answer\n"));
806 v_circuit = 1; 815 v_circuit = 1;
807 res_close(); 816 res_close();
808 goto same_ns; 817 goto same_ns;
809 } 818 }
810 } /*if vc/dg*/ 819 } /*if vc/dg*/
811 Dprint((_res.options & RES_DEBUG) || 820 Dprint((_resp->options & RES_DEBUG) ||
812 ((_res.pfcode & RES_PRF_REPLY) && 821 ((_resp->pfcode & RES_PRF_REPLY) &&
813 (_res.pfcode & RES_PRF_HEAD1)), 822 (_resp->pfcode & RES_PRF_HEAD1)),
814 (stdout, ";; got answer:\n")); 823 (stdout, ";; got answer:\n"));
815 DprintQ((_res.options & RES_DEBUG) || 824 DprintQ((_resp->options & RES_DEBUG) ||
816 (_res.pfcode & RES_PRF_REPLY), 825 (_resp->pfcode & RES_PRF_REPLY),
817 (stdout, "%s", ""), 826 (stdout, "%s", ""),
818 ans, (resplen>anssiz)?anssiz:resplen); 827 ans, (resplen>anssiz)?anssiz:resplen);
819 /* 828 /*
@@ -824,8 +833,8 @@ read_len:
824 * or if we haven't been asked to keep a socket open, 833 * or if we haven't been asked to keep a socket open,
825 * close the socket. 834 * close the socket.
826 */ 835 */
827 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || 836 if ((v_circuit && (!(_resp->options & RES_USEVC) || ns != 0)) ||
828 !(_res.options & RES_STAYOPEN)) { 837 !(_resp->options & RES_STAYOPEN)) {
829 res_close(); 838 res_close();
830 } 839 }
831 if (Rhook) { 840 if (Rhook) {