diff options
Diffstat (limited to 'lib/libc/net/res_send.c')
-rw-r--r-- | lib/libc/net/res_send.c | 111 |
1 files changed, 69 insertions, 42 deletions
diff --git a/lib/libc/net/res_send.c b/lib/libc/net/res_send.c index 1efd17df2b8..bfc01f9b6af 100644 --- a/lib/libc/net/res_send.c +++ b/lib/libc/net/res_send.c @@ -1,4 +1,8 @@ -/*- +/* $OpenBSD: res_send.c,v 1.4 1997/03/13 19:07:41 downsj Exp $ */ + +/* + * ++Copyright++ 1985, 1989, 1993 + * - * Copyright (c) 1985, 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -52,7 +56,12 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: res_send.c,v 1.3 1996/08/19 08:29:49 tholo Exp $"; +#if 0 +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.4 1997/03/13 19:07:41 downsj Exp $"; +#endif #endif /* LIBC_SCCS and not lint */ /* 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 * Send query to name server and wait for reply. */ +#include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #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 #include <netdb.h> #include <errno.h> #include <resolv.h> -#if defined(BSD) && (BSD >= 199306) -# include <stdlib.h> -# include <string.h> -# include <unistd.h> -#else -# include "../conf/portability.h" -#endif - -#if defined(USE_OPTIONS_H) -# include <../conf/options.h> -#endif - -void _res_close __P((void)); +#include <stdlib.h> +#include <string.h> +#include <unistd.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? */ +#ifndef FD_SET +/* XXX - should be in portability.h */ +#define NFDBITS 32 +#define FD_SETSIZE 32 +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + #define CAN_RECONNECT 1 #ifndef DEBUG @@ -301,7 +311,7 @@ res_send(buf, buflen, ans, anssiz) struct sockaddr_in *nsap = &_res.nsaddr_list[ns]; same_ns: if (badns & (1 << ns)) { - _res_close(); + res_close(); goto next_ns; } @@ -318,7 +328,7 @@ res_send(buf, buflen, ans, anssiz) done = 1; break; case res_nextns: - _res_close(); + res_close(); goto next_ns; case res_done: return (resplen); @@ -353,7 +363,7 @@ res_send(buf, buflen, ans, anssiz) truncated = 0; if ((s < 0) || (!vc)) { if (s >= 0) - _res_close(); + res_close(); s = socket(PF_INET, SOCK_STREAM, 0); if (s < 0) { @@ -368,7 +378,7 @@ res_send(buf, buflen, ans, anssiz) Aerror(stderr, "connect/vc", errno, *nsap); badns |= (1 << ns); - _res_close(); + res_close(); goto next_ns; } vc = 1; @@ -385,12 +395,13 @@ res_send(buf, buflen, ans, anssiz) terrno = errno; Perror(stderr, "write failed", errno); badns |= (1 << ns); - _res_close(); + res_close(); goto next_ns; } /* * Receive length & response */ +read_len: cp = ans; len = INT16SZ; while ((n = read(s, (char *)cp, (int)len)) > 0) { @@ -401,7 +412,7 @@ res_send(buf, buflen, ans, anssiz) if (n <= 0) { terrno = errno; Perror(stderr, "read failed", errno); - _res_close(); + res_close(); /* * A long running process might get its TCP * connection reset if the remote server was @@ -413,10 +424,10 @@ res_send(buf, buflen, ans, anssiz) */ if (terrno == ECONNRESET && !connreset) { connreset = 1; - _res_close(); + res_close(); goto same_ns; } - _res_close(); + res_close(); goto next_ns; } resplen = _getshort(ans); @@ -437,7 +448,7 @@ res_send(buf, buflen, ans, anssiz) if (n <= 0) { terrno = errno; Perror(stderr, "read(vc)", errno); - _res_close(); + res_close(); goto next_ns; } if (truncated) { @@ -459,6 +470,20 @@ res_send(buf, buflen, ans, anssiz) break; } } + /* + * The calling applicating has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused. Anyway drop the packet and + * wait for the correct one. + */ + if (hp->id != anhp->id) { + DprintQ((_res.options & RES_DEBUG) || + (_res.pfcode & RES_PRF_REPLY), + (stdout, ";; old answer (unexpected):\n"), + ans, (resplen>anssiz)?anssiz:resplen); + goto read_len; + } } else { /* * Use datagrams. @@ -470,7 +495,7 @@ res_send(buf, buflen, ans, anssiz) if ((s < 0) || vc) { if (vc) - _res_close(); + res_close(); s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) { #if !CAN_RECONNECT @@ -510,7 +535,7 @@ res_send(buf, buflen, ans, anssiz) "connect(dg)", errno, *nsap); badns |= (1 << ns); - _res_close(); + res_close(); goto next_ns; } connected = 1; @@ -518,7 +543,7 @@ res_send(buf, buflen, ans, anssiz) if (send(s, (char*)buf, buflen, 0) != buflen) { Perror(stderr, "send", errno); badns |= (1 << ns); - _res_close(); + res_close(); goto next_ns; } } else { @@ -555,7 +580,7 @@ res_send(buf, buflen, ans, anssiz) != buflen) { Aerror(stderr, "sendto", errno, *nsap); badns |= (1 << ns); - _res_close(); + res_close(); goto next_ns; } } @@ -575,8 +600,10 @@ res_send(buf, buflen, ans, anssiz) n = select(s+1, &dsmask, (fd_set *)NULL, (fd_set *)NULL, &timeout); if (n < 0) { + if (errno == EINTR) + goto wait; Perror(stderr, "select", errno); - _res_close(); + res_close(); goto next_ns; } if (n == 0) { @@ -586,7 +613,7 @@ res_send(buf, buflen, ans, anssiz) Dprint(_res.options & RES_DEBUG, (stdout, ";; timeout\n")); gotsomewhere = 1; - _res_close(); + res_close(); goto next_ns; } errno = 0; @@ -595,7 +622,7 @@ res_send(buf, buflen, ans, anssiz) (struct sockaddr *)&from, &fromlen); if (resplen <= 0) { Perror(stderr, "recvfrom", errno); - _res_close(); + res_close(); goto next_ns; } gotsomewhere = 1; @@ -608,7 +635,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; old answer:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #if CHECK_SRVR_ADDR @@ -622,7 +649,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; not our server:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } #endif @@ -637,7 +664,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ";; wrong query name:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); goto wait; } if (anhp->rcode == SERVFAIL || @@ -645,9 +672,9 @@ res_send(buf, buflen, ans, anssiz) anhp->rcode == REFUSED) { DprintQ(_res.options & RES_DEBUG, (stdout, "server rejected query:\n"), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); badns |= (1 << ns); - _res_close(); + res_close(); /* don't retry if called from dig */ if (!_res.pfcode) goto next_ns; @@ -660,7 +687,7 @@ res_send(buf, buflen, ans, anssiz) Dprint(_res.options & RES_DEBUG, (stdout, ";; truncated answer\n")); v_circuit = 1; - _res_close(); + res_close(); goto same_ns; } } /*if vc/dg*/ @@ -671,7 +698,7 @@ res_send(buf, buflen, ans, anssiz) DprintQ((_res.options & RES_DEBUG) || (_res.pfcode & RES_PRF_REPLY), (stdout, ""), - ans, resplen); + ans, (resplen>anssiz)?anssiz:resplen); /* * If using virtual circuits, we assume that the first server * is preferred over the rest (i.e. it is on the local @@ -682,7 +709,7 @@ res_send(buf, buflen, ans, anssiz) */ if ((v_circuit && (!(_res.options & RES_USEVC) || ns != 0)) || !(_res.options & RES_STAYOPEN)) { - _res_close(); + res_close(); } if (Rhook) { int done = 0, loops = 0; @@ -698,7 +725,7 @@ res_send(buf, buflen, ans, anssiz) done = 1; break; case res_nextns: - _res_close(); + res_close(); goto next_ns; case res_modified: /* give the hook another try */ @@ -717,7 +744,7 @@ res_send(buf, buflen, ans, anssiz) next_ns: ; } /*foreach ns*/ } /*foreach retry*/ - _res_close(); + res_close(); if (!v_circuit) if (!gotsomewhere) errno = ECONNREFUSED; /* no nameservers found */ @@ -736,7 +763,7 @@ res_send(buf, buflen, ans, anssiz) * This routine is not expected to be user visible. */ void -_res_close() +res_close() { if (s >= 0) { (void) close(s); |