summaryrefslogtreecommitdiff
path: root/resolv/res_send.c
diff options
context:
space:
mode:
Diffstat (limited to 'resolv/res_send.c')
-rw-r--r--resolv/res_send.c264
1 files changed, 127 insertions, 137 deletions
diff --git a/resolv/res_send.c b/resolv/res_send.c
index ca3e630868..18e54dbcda 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -73,6 +73,7 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi
* Send query to name server and wait for reply.
*/
+#include <assert.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
@@ -808,7 +809,7 @@ send_dg(res_state statp,
int ptimeout;
struct sockaddr_in6 from;
static int socket_pf = 0;
- int fromlen, resplen, seconds, n, s;
+ int fromlen, resplen, seconds, n;
if (EXT(statp).nssocks[ns] == -1) {
/* only try IPv6 if IPv6 NS and if not failed before */
@@ -854,7 +855,7 @@ send_dg(res_state statp,
Dprint(statp->options & RES_DEBUG,
(stdout, ";; new DG socket\n"))
}
- s = EXT(statp).nssocks[ns];
+
/*
* Compute time for the total operation.
*/
@@ -867,13 +868,25 @@ send_dg(res_state statp,
evConsTime(&timeout, seconds, 0);
evAddTime(&finish, &now, &timeout);
int need_recompute = 0;
- resend:
+ int nwritten = 0;
+ pfd[0].fd = EXT(statp).nssocks[ns];
+ pfd[0].events = POLLOUT;
+ wait:
+ if (need_recompute) {
+ evNowTime(&now);
+ if (evCmpTime(finish, now) <= 0) {
+ Perror(statp, stderr, "select", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ evSubTime(&timeout, &finish, &now);
+ }
/* Convert struct timespec in milliseconds. */
ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
- pfd[0].fd = s;
- pfd[0].events = POLLOUT;
- n = __poll (pfd, 1, 0);
+ n = 0;
+ if (nwritten == 0)
+ n = __poll (pfd, 1, 0);
if (__builtin_expect (n == 0, 0)) {
n = __poll (pfd, 1, ptimeout);
need_recompute = 1;
@@ -890,7 +903,7 @@ send_dg(res_state statp,
evNowTime(&now);
if (evCmpTime(finish, now) > 0) {
evSubTime(&timeout, &finish, &now);
- goto resend;
+ goto wait;
}
}
Perror(statp, stderr, "select", errno);
@@ -898,149 +911,126 @@ send_dg(res_state statp,
return (0);
}
__set_errno (0);
- if (send(s, (char*)buf, buflen, 0) != buflen) {
- if (errno == EINTR || errno == EAGAIN)
- goto recompute_resend;
- Perror(statp, stderr, "send", errno);
- res_nclose(statp);
- return (0);
- }
-
- wait:
- if (need_recompute) {
- evNowTime(&now);
- if (evCmpTime(finish, now) <= 0) {
- err_return:
- Perror(statp, stderr, "select", errno);
+ if (pfd[0].revents & POLLOUT) {
+ if (send(pfd[0].fd, (char*)buf, buflen, 0) != buflen) {
+ if (errno == EINTR || errno == EAGAIN)
+ goto recompute_resend;
+ Perror(statp, stderr, "send", errno);
res_nclose(statp);
return (0);
}
- evSubTime(&timeout, &finish, &now);
- }
- /* Convert struct timespec in milliseconds. */
- ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
+ pfd[0].events = POLLIN;
+ ++nwritten;
+ goto wait;
+ } else {
+ assert(pfd[0].revents & POLLIN);
- pfd[0].events = POLLIN;
- n = __poll (pfd, 1, ptimeout);
- if (n == 0) {
- Dprint(statp->options & RES_DEBUG, (stdout,
- ";; timeout receiving\n"));
+ fromlen = sizeof(struct sockaddr_in6);
+ if (anssiz < MAXPACKET
+ && anscp
+ && (ioctl (pfd[0].fd, FIONREAD, &resplen) < 0
+ || anssiz < resplen)) {
+ ans = malloc (MAXPACKET);
+ if (ans == NULL)
+ ans = *ansp;
+ else {
+ anssiz = MAXPACKET;
+ *anssizp = MAXPACKET;
+ *ansp = ans;
+ *anscp = ans;
+ anhp = (HEADER *) ans;
+ }
+ }
+ resplen = recvfrom(pfd[0].fd, (char*)ans, anssiz,0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ if (errno == EINTR || errno == EAGAIN) {
+ need_recompute = 1;
+ goto wait;
+ }
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
+ return (0);
+ }
*gotsomewhere = 1;
- return (0);
- }
- if (n < 0) {
- if (errno == EINTR) {
- need_recompute = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
goto wait;
}
- goto err_return;
- }
- __set_errno (0);
- fromlen = sizeof(struct sockaddr_in6);
- if (anssiz < MAXPACKET
- && anscp
- && (ioctl (s, FIONREAD, &resplen) < 0
- || anssiz < resplen)) {
- ans = malloc (MAXPACKET);
- if (ans == NULL)
- ans = *ansp;
- else {
- anssiz = MAXPACKET;
- *anssizp = MAXPACKET;
- *ansp = ans;
- *anscp = ans;
- anhp = (HEADER *) ans;
+ if (!(statp->options & RES_INSECURE1) &&
+ !res_ourserver_p(statp, &from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
}
- }
- resplen = recvfrom(s, (char*)ans, anssiz,0,
- (struct sockaddr *)&from, &fromlen);
- if (resplen <= 0) {
- if (errno == EINTR || errno == EAGAIN) {
- need_recompute = 1;
+ if (!(statp->options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
goto wait;
}
- Perror(statp, stderr, "recvfrom", errno);
- res_nclose(statp);
- return (0);
- }
- *gotsomewhere = 1;
- if (resplen < HFIXEDSZ) {
- /*
- * Undersized message.
- */
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; undersized: %d\n",
- resplen));
- *terrno = EMSGSIZE;
- res_nclose(statp);
- return (0);
- }
- if (hp->id != anhp->id) {
- /*
- * response from old query, ignore it.
- * XXX - potential security hazard could
- * be detected here.
- */
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; old answer:\n"),
- ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
- }
- if (!(statp->options & RES_INSECURE1) &&
- !res_ourserver_p(statp, &from)) {
- /*
- * response from wrong server? ignore it.
- * XXX - potential security hazard could
- * be detected here.
- */
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; not our server:\n"),
- ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
- }
- if (!(statp->options & RES_INSECURE2) &&
- !res_queriesmatch(buf, buf + buflen,
- ans, ans + anssiz)) {
- /*
- * response contains wrong query? ignore it.
- * XXX - potential security hazard could
- * be detected here.
- */
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; wrong query name:\n"),
- ans, (resplen > anssiz) ? anssiz : resplen);
- goto wait;
- }
- if (anhp->rcode == SERVFAIL ||
- anhp->rcode == NOTIMP ||
- anhp->rcode == REFUSED) {
- DprintQ(statp->options & RES_DEBUG,
- (stdout, "server rejected query:\n"),
- ans, (resplen > anssiz) ? anssiz : resplen);
- res_nclose(statp);
- /* don't retry if called from dig */
- if (!statp->pfcode)
- return (0);
- }
- if (!(statp->options & RES_IGNTC) && anhp->tc) {
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ res_nclose(statp);
+ /* don't retry if called from dig */
+ if (!statp->pfcode)
+ return (0);
+ }
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
+ /*
+ * To get the rest of answer,
+ * use TCP with same server.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ *v_circuit = 1;
+ res_nclose(statp);
+ return (1);
+ }
/*
- * To get the rest of answer,
- * use TCP with same server.
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
*/
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; truncated answer\n"));
- *v_circuit = 1;
- res_nclose(statp);
- return (1);
+ return (resplen);
}
- /*
- * All is well, or the error is fatal. Signal that the
- * next nameserver ought not be tried.
- */
- return (resplen);
}
#ifdef DEBUG