summaryrefslogtreecommitdiff
path: root/lib/libc/net/res_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/net/res_send.c')
-rw-r--r--lib/libc/net/res_send.c111
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);