aboutsummaryrefslogtreecommitdiff
path: root/stand
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2018-02-14 15:40:13 +0000
committerKyle Evans <kevans@FreeBSD.org>2018-02-14 15:40:13 +0000
commit502b7cf99bea531fa3cf59d72cf89fcbb9311b8c (patch)
tree000ec315309a3c6619826bb786ac75c3430486cc /stand
parentd793587fe2e4c758a2995ac373e6e0df6a1a3bae (diff)
downloadsrc-502b7cf99bea531fa3cf59d72cf89fcbb9311b8c.tar.gz
src-502b7cf99bea531fa3cf59d72cf89fcbb9311b8c.zip
libsa: Fix IP recv timeout
readip() doesn't, at the moment, properly indicate to callers that it has timed out. One can tell that it's timed out if errno == EAGAIN when it returns, but this is not ideal. Restructure it a little bit to explicitly set errno to ETIMEDOUT if we've exhausted tleft. I found two places that care about where it timed out or not: sendrecv in net.c and sendrecv_tftp. Both are structured to pass smaller timeout values to readip while tracking a larger timeout. Neither of them were able to do this properly with readip not indicating ETIMEDOUT, so fix it. While here, straighten out the time (t/t1) usage in sendrecv_tftp. This would have manifested itself in periodic failures to NFS/TFTP boot for no apparent reason because MINTMO/MAXTMO were not actually being respected properly. Problems were not reported with NFS, only TFTP. Reported by: sbruno Reviewed by: sbruno, tsoome MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D14350
Notes
Notes: svn path=/head/; revision=329264
Diffstat (limited to 'stand')
-rw-r--r--stand/libsa/ip.c9
-rw-r--r--stand/libsa/net.c2
-rw-r--r--stand/libsa/tftp.c8
3 files changed, 15 insertions, 4 deletions
diff --git a/stand/libsa/ip.c b/stand/libsa/ip.c
index f2293b3cd3f9..ea8213770432 100644
--- a/stand/libsa/ip.c
+++ b/stand/libsa/ip.c
@@ -416,8 +416,13 @@ readip(struct iodesc *d, void **pkt, void **payload, time_t tleft,
while ((getsecs() - t) < tleft) {
errno = 0;
ret = readipv4(d, pkt, payload, tleft, proto);
+ if (ret >= 0)
+ return (ret);
+ /* Bubble up the error if it wasn't successful */
if (errno != EAGAIN)
- break;
+ return (-1);
}
- return (ret);
+ /* We've exhausted tleft; timeout */
+ errno = ETIMEDOUT;
+ return (-1);
}
diff --git a/stand/libsa/net.c b/stand/libsa/net.c
index ae6e74511e12..5e13c5344327 100644
--- a/stand/libsa/net.c
+++ b/stand/libsa/net.c
@@ -118,7 +118,7 @@ sendrecv(struct iodesc *d,
/* Try to get a packet and process it. */
cc = (*rproc)(d, pkt, payload, tleft);
/* Return on data, EOF or real error. */
- if (cc != -1 || errno != 0)
+ if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
return (cc);
/* Timed out or didn't get the packet we're waiting for */
diff --git a/stand/libsa/tftp.c b/stand/libsa/tftp.c
index 9bef4643d25f..da85b9842785 100644
--- a/stand/libsa/tftp.c
+++ b/stand/libsa/tftp.c
@@ -638,14 +638,20 @@ sendrecv_tftp(struct tftp_handle *h,
if (cc == -1) {
/* Error on transmit; wait before retrying */
while ((getsecs() - t1) < tleft);
+ t1 = getsecs();
continue;
}
+ t = t1 = getsecs();
recvnext:
+ if ((getsecs() - t) > MAXTMO) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
/* Try to get a packet and process it. */
cc = (*rproc)(h, pkt, payload, tleft, rtype);
/* Return on data, EOF or real error. */
- if (cc != -1 || errno != 0)
+ if (cc != -1 || (errno != 0 && errno != ETIMEDOUT))
return (cc);
if ((getsecs() - t1) < tleft) {
goto recvnext;