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.c111
1 files changed, 69 insertions, 42 deletions
diff --git a/src/lib/libc/net/res_send.c b/src/lib/libc/net/res_send.c
index 1efd17df2b..bfc01f9b6a 100644
--- a/src/lib/libc/net/res_send.c
+++ b/src/lib/libc/net/res_send.c
@@ -1,4 +1,8 @@
1/*- 1/* $OpenBSD: res_send.c,v 1.4 1997/03/13 19:07:41 downsj Exp $ */
2
3/*
4 * ++Copyright++ 1985, 1989, 1993
5 * -
2 * Copyright (c) 1985, 1989, 1993 6 * Copyright (c) 1985, 1989, 1993
3 * The Regents of the University of California. All rights reserved. 7 * The Regents of the University of California. All rights reserved.
4 * 8 *
@@ -52,7 +56,12 @@
52 */ 56 */
53 57
54#if defined(LIBC_SCCS) && !defined(lint) 58#if defined(LIBC_SCCS) && !defined(lint)
55static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp $"; 59#if 0
60static char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
61static char rcsid[] = "$From: res_send.c,v 8.12 1996/10/08 04:51:06 vixie Exp $";
62#else
63static char rcsid[] = "$OpenBSD: res_send.c,v 1.4 1997/03/13 19:07:41 downsj Exp $";
64#endif
56#endif /* LIBC_SCCS and not lint */ 65#endif /* LIBC_SCCS and not lint */
57 66
58 /* change this to "0" 67 /* change this to "0"
@@ -66,6 +75,7 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp
66 * Send query to name server and wait for reply. 75 * Send query to name server and wait for reply.
67 */ 76 */
68 77
78#include <sys/types.h>
69#include <sys/param.h> 79#include <sys/param.h>
70#include <sys/time.h> 80#include <sys/time.h>
71#include <sys/socket.h> 81#include <sys/socket.h>
@@ -78,24 +88,24 @@ static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp
78#include <netdb.h> 88#include <netdb.h>
79#include <errno.h> 89#include <errno.h>
80#include <resolv.h> 90#include <resolv.h>
81#if defined(BSD) && (BSD >= 199306) 91#include <stdlib.h>
82# include <stdlib.h> 92#include <string.h>
83# include <string.h> 93#include <unistd.h>
84# include <unistd.h>
85#else
86# include "../conf/portability.h"
87#endif
88
89#if defined(USE_OPTIONS_H)
90# include <../conf/options.h>
91#endif
92
93void _res_close __P((void));
94 94
95static int s = -1; /* socket used for communications */ 95static int s = -1; /* socket used for communications */
96static int connected = 0; /* is the socket connected */ 96static int connected = 0; /* is the socket connected */
97static int vc = 0; /* is the socket a virtual ciruit? */ 97static int vc = 0; /* is the socket a virtual ciruit? */
98 98
99#ifndef FD_SET
100/* XXX - should be in portability.h */
101#define NFDBITS 32
102#define FD_SETSIZE 32
103#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
104#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
105#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
106#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
107#endif
108
99#define CAN_RECONNECT 1 109#define CAN_RECONNECT 1
100 110
101#ifndef DEBUG 111#ifndef DEBUG
@@ -301,7 +311,7 @@ res_send(buf, buflen, ans, anssiz)
301 struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; 311 struct sockaddr_in *nsap = &_res.nsaddr_list[ns];
302 same_ns: 312 same_ns:
303 if (badns & (1 << ns)) { 313 if (badns & (1 << ns)) {
304 _res_close(); 314 res_close();
305 goto next_ns; 315 goto next_ns;
306 } 316 }
307 317
@@ -318,7 +328,7 @@ res_send(buf, buflen, ans, anssiz)
318 done = 1; 328 done = 1;
319 break; 329 break;
320 case res_nextns: 330 case res_nextns:
321 _res_close(); 331 res_close();
322 goto next_ns; 332 goto next_ns;
323 case res_done: 333 case res_done:
324 return (resplen); 334 return (resplen);
@@ -353,7 +363,7 @@ res_send(buf, buflen, ans, anssiz)
353 truncated = 0; 363 truncated = 0;
354 if ((s < 0) || (!vc)) { 364 if ((s < 0) || (!vc)) {
355 if (s >= 0) 365 if (s >= 0)
356 _res_close(); 366 res_close();
357 367
358 s = socket(PF_INET, SOCK_STREAM, 0); 368 s = socket(PF_INET, SOCK_STREAM, 0);
359 if (s < 0) { 369 if (s < 0) {
@@ -368,7 +378,7 @@ res_send(buf, buflen, ans, anssiz)
368 Aerror(stderr, "connect/vc", 378 Aerror(stderr, "connect/vc",
369 errno, *nsap); 379 errno, *nsap);
370 badns |= (1 << ns); 380 badns |= (1 << ns);
371 _res_close(); 381 res_close();
372 goto next_ns; 382 goto next_ns;
373 } 383 }
374 vc = 1; 384 vc = 1;
@@ -385,12 +395,13 @@ res_send(buf, buflen, ans, anssiz)
385 terrno = errno; 395 terrno = errno;
386 Perror(stderr, "write failed", errno); 396 Perror(stderr, "write failed", errno);
387 badns |= (1 << ns); 397 badns |= (1 << ns);
388 _res_close(); 398 res_close();
389 goto next_ns; 399 goto next_ns;
390 } 400 }
391 /* 401 /*
392 * Receive length & response 402 * Receive length & response
393 */ 403 */
404read_len:
394 cp = ans; 405 cp = ans;
395 len = INT16SZ; 406 len = INT16SZ;
396 while ((n = read(s, (char *)cp, (int)len)) > 0) { 407 while ((n = read(s, (char *)cp, (int)len)) > 0) {
@@ -401,7 +412,7 @@ res_send(buf, buflen, ans, anssiz)
401 if (n <= 0) { 412 if (n <= 0) {
402 terrno = errno; 413 terrno = errno;
403 Perror(stderr, "read failed", errno); 414 Perror(stderr, "read failed", errno);
404 _res_close(); 415 res_close();
405 /* 416 /*
406 * A long running process might get its TCP 417 * A long running process might get its TCP
407 * connection reset if the remote server was 418 * connection reset if the remote server was
@@ -413,10 +424,10 @@ res_send(buf, buflen, ans, anssiz)
413 */ 424 */
414 if (terrno == ECONNRESET && !connreset) { 425 if (terrno == ECONNRESET && !connreset) {
415 connreset = 1; 426 connreset = 1;
416 _res_close(); 427 res_close();
417 goto same_ns; 428 goto same_ns;
418 } 429 }
419 _res_close(); 430 res_close();
420 goto next_ns; 431 goto next_ns;
421 } 432 }
422 resplen = _getshort(ans); 433 resplen = _getshort(ans);
@@ -437,7 +448,7 @@ res_send(buf, buflen, ans, anssiz)
437 if (n <= 0) { 448 if (n <= 0) {
438 terrno = errno; 449 terrno = errno;
439 Perror(stderr, "read(vc)", errno); 450 Perror(stderr, "read(vc)", errno);
440 _res_close(); 451 res_close();
441 goto next_ns; 452 goto next_ns;
442 } 453 }
443 if (truncated) { 454 if (truncated) {
@@ -459,6 +470,20 @@ res_send(buf, buflen, ans, anssiz)
459 break; 470 break;
460 } 471 }
461 } 472 }
473 /*
474 * The calling applicating has bailed out of
475 * a previous call and failed to arrange to have
476 * the circuit closed or the server has got
477 * itself confused. Anyway drop the packet and
478 * wait for the correct one.
479 */
480 if (hp->id != anhp->id) {
481 DprintQ((_res.options & RES_DEBUG) ||
482 (_res.pfcode & RES_PRF_REPLY),
483 (stdout, ";; old answer (unexpected):\n"),
484 ans, (resplen>anssiz)?anssiz:resplen);
485 goto read_len;
486 }
462 } else { 487 } else {
463 /* 488 /*
464 * Use datagrams. 489 * Use datagrams.
@@ -470,7 +495,7 @@ res_send(buf, buflen, ans, anssiz)
470 495
471 if ((s < 0) || vc) { 496 if ((s < 0) || vc) {
472 if (vc) 497 if (vc)
473 _res_close(); 498 res_close();
474 s = socket(PF_INET, SOCK_DGRAM, 0); 499 s = socket(PF_INET, SOCK_DGRAM, 0);
475 if (s < 0) { 500 if (s < 0) {
476#if !CAN_RECONNECT 501#if !CAN_RECONNECT
@@ -510,7 +535,7 @@ res_send(buf, buflen, ans, anssiz)
510 "connect(dg)", 535 "connect(dg)",
511 errno, *nsap); 536 errno, *nsap);
512 badns |= (1 << ns); 537 badns |= (1 << ns);
513 _res_close(); 538 res_close();
514 goto next_ns; 539 goto next_ns;
515 } 540 }
516 connected = 1; 541 connected = 1;
@@ -518,7 +543,7 @@ res_send(buf, buflen, ans, anssiz)
518 if (send(s, (char*)buf, buflen, 0) != buflen) { 543 if (send(s, (char*)buf, buflen, 0) != buflen) {
519 Perror(stderr, "send", errno); 544 Perror(stderr, "send", errno);
520 badns |= (1 << ns); 545 badns |= (1 << ns);
521 _res_close(); 546 res_close();
522 goto next_ns; 547 goto next_ns;
523 } 548 }
524 } else { 549 } else {
@@ -555,7 +580,7 @@ res_send(buf, buflen, ans, anssiz)
555 != buflen) { 580 != buflen) {
556 Aerror(stderr, "sendto", errno, *nsap); 581 Aerror(stderr, "sendto", errno, *nsap);
557 badns |= (1 << ns); 582 badns |= (1 << ns);
558 _res_close(); 583 res_close();
559 goto next_ns; 584 goto next_ns;
560 } 585 }
561 } 586 }
@@ -575,8 +600,10 @@ res_send(buf, buflen, ans, anssiz)
575 n = select(s+1, &dsmask, (fd_set *)NULL, 600 n = select(s+1, &dsmask, (fd_set *)NULL,
576 (fd_set *)NULL, &timeout); 601 (fd_set *)NULL, &timeout);
577 if (n < 0) { 602 if (n < 0) {
603 if (errno == EINTR)
604 goto wait;
578 Perror(stderr, "select", errno); 605 Perror(stderr, "select", errno);
579 _res_close(); 606 res_close();
580 goto next_ns; 607 goto next_ns;
581 } 608 }
582 if (n == 0) { 609 if (n == 0) {
@@ -586,7 +613,7 @@ res_send(buf, buflen, ans, anssiz)
586 Dprint(_res.options & RES_DEBUG, 613 Dprint(_res.options & RES_DEBUG,
587 (stdout, ";; timeout\n")); 614 (stdout, ";; timeout\n"));
588 gotsomewhere = 1; 615 gotsomewhere = 1;
589 _res_close(); 616 res_close();
590 goto next_ns; 617 goto next_ns;
591 } 618 }
592 errno = 0; 619 errno = 0;
@@ -595,7 +622,7 @@ res_send(buf, buflen, ans, anssiz)
595 (struct sockaddr *)&from, &fromlen); 622 (struct sockaddr *)&from, &fromlen);
596 if (resplen <= 0) { 623 if (resplen <= 0) {
597 Perror(stderr, "recvfrom", errno); 624 Perror(stderr, "recvfrom", errno);
598 _res_close(); 625 res_close();
599 goto next_ns; 626 goto next_ns;
600 } 627 }
601 gotsomewhere = 1; 628 gotsomewhere = 1;
@@ -608,7 +635,7 @@ res_send(buf, buflen, ans, anssiz)
608 DprintQ((_res.options & RES_DEBUG) || 635 DprintQ((_res.options & RES_DEBUG) ||
609 (_res.pfcode & RES_PRF_REPLY), 636 (_res.pfcode & RES_PRF_REPLY),
610 (stdout, ";; old answer:\n"), 637 (stdout, ";; old answer:\n"),
611 ans, resplen); 638 ans, (resplen>anssiz)?anssiz:resplen);
612 goto wait; 639 goto wait;
613 } 640 }
614#if CHECK_SRVR_ADDR 641#if CHECK_SRVR_ADDR
@@ -622,7 +649,7 @@ res_send(buf, buflen, ans, anssiz)
622 DprintQ((_res.options & RES_DEBUG) || 649 DprintQ((_res.options & RES_DEBUG) ||
623 (_res.pfcode & RES_PRF_REPLY), 650 (_res.pfcode & RES_PRF_REPLY),
624 (stdout, ";; not our server:\n"), 651 (stdout, ";; not our server:\n"),
625 ans, resplen); 652 ans, (resplen>anssiz)?anssiz:resplen);
626 goto wait; 653 goto wait;
627 } 654 }
628#endif 655#endif
@@ -637,7 +664,7 @@ res_send(buf, buflen, ans, anssiz)
637 DprintQ((_res.options & RES_DEBUG) || 664 DprintQ((_res.options & RES_DEBUG) ||
638 (_res.pfcode & RES_PRF_REPLY), 665 (_res.pfcode & RES_PRF_REPLY),
639 (stdout, ";; wrong query name:\n"), 666 (stdout, ";; wrong query name:\n"),
640 ans, resplen); 667 ans, (resplen>anssiz)?anssiz:resplen);
641 goto wait; 668 goto wait;
642 } 669 }
643 if (anhp->rcode == SERVFAIL || 670 if (anhp->rcode == SERVFAIL ||
@@ -645,9 +672,9 @@ res_send(buf, buflen, ans, anssiz)
645 anhp->rcode == REFUSED) { 672 anhp->rcode == REFUSED) {
646 DprintQ(_res.options & RES_DEBUG, 673 DprintQ(_res.options & RES_DEBUG,
647 (stdout, "server rejected query:\n"), 674 (stdout, "server rejected query:\n"),
648 ans, resplen); 675 ans, (resplen>anssiz)?anssiz:resplen);
649 badns |= (1 << ns); 676 badns |= (1 << ns);
650 _res_close(); 677 res_close();
651 /* don't retry if called from dig */ 678 /* don't retry if called from dig */
652 if (!_res.pfcode) 679 if (!_res.pfcode)
653 goto next_ns; 680 goto next_ns;
@@ -660,7 +687,7 @@ res_send(buf, buflen, ans, anssiz)
660 Dprint(_res.options & RES_DEBUG, 687 Dprint(_res.options & RES_DEBUG,
661 (stdout, ";; truncated answer\n")); 688 (stdout, ";; truncated answer\n"));
662 v_circuit = 1; 689 v_circuit = 1;
663 _res_close(); 690 res_close();
664 goto same_ns; 691 goto same_ns;
665 } 692 }
666 } /*if vc/dg*/ 693 } /*if vc/dg*/
@@ -671,7 +698,7 @@ res_send(buf, buflen, ans, anssiz)
671 DprintQ((_res.options & RES_DEBUG) || 698 DprintQ((_res.options & RES_DEBUG) ||
672 (_res.pfcode & RES_PRF_REPLY), 699 (_res.pfcode & RES_PRF_REPLY),
673 (stdout, ""), 700 (stdout, ""),
674 ans, resplen); 701 ans, (resplen>anssiz)?anssiz:resplen);
675 /* 702 /*
676 * If using virtual circuits, we assume that the first server 703 * If using virtual circuits, we assume that the first server
677 * is preferred over the rest (i.e. it is on the local 704 * is preferred over the rest (i.e. it is on the local
@@ -682,7 +709,7 @@ res_send(buf, buflen, ans, anssiz)
682 */ 709 */
683 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || 710 if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) ||
684 !(_res.options & RES_STAYOPEN)) { 711 !(_res.options & RES_STAYOPEN)) {
685 _res_close(); 712 res_close();
686 } 713 }
687 if (Rhook) { 714 if (Rhook) {
688 int done = 0, loops = 0; 715 int done = 0, loops = 0;
@@ -698,7 +725,7 @@ res_send(buf, buflen, ans, anssiz)
698 done = 1; 725 done = 1;
699 break; 726 break;
700 case res_nextns: 727 case res_nextns:
701 _res_close(); 728 res_close();
702 goto next_ns; 729 goto next_ns;
703 case res_modified: 730 case res_modified:
704 /* give the hook another try */ 731 /* give the hook another try */
@@ -717,7 +744,7 @@ res_send(buf, buflen, ans, anssiz)
717 next_ns: ; 744 next_ns: ;
718 } /*foreach ns*/ 745 } /*foreach ns*/
719 } /*foreach retry*/ 746 } /*foreach retry*/
720 _res_close(); 747 res_close();
721 if (!v_circuit) 748 if (!v_circuit)
722 if (!gotsomewhere) 749 if (!gotsomewhere)
723 errno = ECONNREFUSED; /* no nameservers found */ 750 errno = ECONNREFUSED; /* no nameservers found */
@@ -736,7 +763,7 @@ res_send(buf, buflen, ans, anssiz)
736 * This routine is not expected to be user visible. 763 * This routine is not expected to be user visible.
737 */ 764 */
738void 765void
739_res_close() 766res_close()
740{ 767{
741 if (s >= 0) { 768 if (s >= 0) {
742 (void) close(s); 769 (void) close(s);