summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--NEWS3
-rw-r--r--resolv/res_send.c63
3 files changed, 51 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 0be4a594d7..fb777de266 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2016-04-22 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #19791]
+ * resolv/res_send.c (close_and_return_error): New function.
+ (send_dg): Initialize *resplen2 after reopen failure. Call
+ close_and_return_error for error returns. On error paths without
+ __res_iclose, initialze *resplen2 explicitly. Update comment for
+ successful return.
+
2016-04-22 Andreas Schwab <schwab@suse.de>
[BZ #15946]
diff --git a/NEWS b/NEWS
index 94bcc4e54b..67a29f8f27 100644
--- a/NEWS
+++ b/NEWS
@@ -10,7 +10,8 @@ Version 2.18.1
* The following bugs are resolved with this release:
15073, 15128, 15909, 15946, 15996, 16009, 16150, 16169, 16387, 16510,
- 16885, 16916, 16943, 16958, 17269, 18032, 18665, 18928, 19018.
+ 16885, 16916, 16943, 16958, 17269, 18032, 18665, 18928, 19018, 19791.
+
* The LD_POINTER_GUARD environment variable can no longer be used to
disable the pointer guard feature. It is always enabled.
diff --git a/resolv/res_send.c b/resolv/res_send.c
index e8b1809eab..9a10ef4bd5 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -671,6 +671,18 @@ libresolv_hidden_def (res_nsend)
/* Private */
+/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
+ is not NULL, and return zero. */
+static int
+__attribute__ ((warn_unused_result))
+close_and_return_error (res_state statp, int *resplen2)
+{
+ __res_iclose(statp, false);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
+}
+
/* The send_vc function is responsible for sending a DNS query over TCP
to the nameserver numbered NS from the res_state STATP i.e.
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
@@ -1156,7 +1168,11 @@ send_dg(res_state statp,
retry_reopen:
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
retry:
evNowTime(&now);
evConsTime(&timeout, seconds, 0);
@@ -1169,8 +1185,6 @@ send_dg(res_state statp,
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
- if (resplen2 != NULL)
- *resplen2 = 0;
wait:
if (need_recompute) {
recompute_resend:
@@ -1178,9 +1192,7 @@ send_dg(res_state statp,
if (evCmpTime(finish, now) <= 0) {
poll_err_out:
Perror(statp, stderr, "poll", errno);
- err_out:
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
evSubTime(&timeout, &finish, &now);
need_recompute = 0;
@@ -1227,7 +1239,9 @@ send_dg(res_state statp,
}
*gotsomewhere = 1;
- return (0);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
}
if (n < 0) {
if (errno == EINTR)
@@ -1295,7 +1309,7 @@ send_dg(res_state statp,
fail_sendmmsg:
Perror(statp, stderr, "sendmmsg", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
}
else
@@ -1313,7 +1327,7 @@ send_dg(res_state statp,
if (errno == EINTR || errno == EAGAIN)
goto recompute_resend;
Perror(statp, stderr, "send", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
just_one:
if (nwritten != 0 || buf2 == NULL || single_request)
@@ -1389,7 +1403,7 @@ send_dg(res_state statp,
goto wait;
}
Perror(statp, stderr, "recvfrom", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
*gotsomewhere = 1;
if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
@@ -1400,7 +1414,7 @@ send_dg(res_state statp,
(stdout, ";; undersized: %d\n",
*thisresplenp));
*terrno = EMSGSIZE;
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
if ((recvresp1 || hp->id != anhp->id)
&& (recvresp2 || hp2->id != anhp->id)) {
@@ -1449,7 +1463,7 @@ send_dg(res_state statp,
? *thisanssizp : *thisresplenp);
/* record the error */
statp->_flags |= RES_F_EDNS0ERR;
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
#endif
if (!(statp->options & RES_INSECURE2)
@@ -1501,10 +1515,10 @@ send_dg(res_state statp,
}
next_ns:
- __res_iclose(statp, false);
/* don't retry if called from dig */
if (!statp->pfcode)
- return (0);
+ return close_and_return_error (statp, resplen2);
+ __res_iclose(statp, false);
}
if (anhp->rcode == NOERROR && anhp->ancount == 0
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
@@ -1526,6 +1540,8 @@ send_dg(res_state statp,
__res_iclose(statp, false);
// XXX if we have received one reply we could
// XXX use it and not repeat it over TCP...
+ if (resplen2 != NULL)
+ *resplen2 = 0;
return (1);
}
/* Mark which reply we received. */
@@ -1541,21 +1557,22 @@ send_dg(res_state statp,
__res_iclose (statp, false);
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
pfd[0].fd = EXT(statp).nssocks[ns];
}
}
goto wait;
}
- /*
- * All is well, or the error is fatal. Signal that the
- * next nameserver ought not be tried.
- */
+ /* All is well. We have received both responses (if
+ two responses were requested). */
return (resplen);
- } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- /* Something went wrong. We can stop trying. */
- goto err_out;
- }
+ } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+ /* Something went wrong. We can stop trying. */
+ return close_and_return_error (statp, resplen2);
else {
/* poll should not have returned > 0 in this case. */
abort ();