Page MenuHomeFreeBSD

D61477.1794623729.diff
No OneTemporary

Authored By
Unknown
Size
2 KB
Referenced Files
None
Subscribers
None

D61477.1794623729.diff

diff --git a/stand/libsa/bootp.c b/stand/libsa/bootp.c
--- a/stand/libsa/bootp.c
+++ b/stand/libsa/bootp.c
@@ -83,6 +83,15 @@
#ifdef SUPPORT_DHCP
static char expected_dhcpmsgtype = -1, dhcp_ok;
+static bool dhcp_nak;
+
+/*
+ * How long to wait for the server to confirm a cached lease before giving up
+ * and running a full DISCOVER. A server that does not recognise the client
+ * may stay silent (RFC 2131 § 4.3.2), so this has to be far shorter than
+ * sendrecv()'s MAXWAIT, which is as long as the UEFI boot watchdog.
+ */
+#define DHCP_INIT_REBOOT_WAIT 10 /* seconds */
struct in_addr dhcp_serverip;
#endif
struct bootp *bootp_response;
@@ -181,6 +190,9 @@
} wbuf;
struct bootp *rbootp;
bool init_reboot = false;
+#ifdef SUPPORT_DHCP
+ time_t deadline;
+#endif
DEBUG_PRINTF(1, ("bootp: socket=%d\n", sock));
if (!bot)
@@ -301,6 +313,7 @@
bootp_fill_request(&bp->bp_vend[off]);
expected_dhcpmsgtype = DHCPACK;
+ deadline = getsecs() + DHCP_INIT_REBOOT_WAIT;
if (pkt != NULL) {
free(pkt);
@@ -308,10 +321,12 @@
}
if (sendrecv(d,
bootpsend, bp, sizeof(*bp),
- bootprecv, &pkt, (void **)&rbootp, NULL) == -1) {
+ bootprecv, &pkt, (void **)&rbootp,
+ init_reboot ? &deadline : NULL) == -1) {
if (init_reboot) {
- printf("bootp: INIT-REBOOT failed, "
- "falling back to DISCOVER\n");
+ printf("bootp: INIT-REBOOT %s, "
+ "falling back to DISCOVER\n",
+ dhcp_nak ? "refused" : "timed out");
free(bootp_response);
bootp_response = NULL;
bootp_response_size = 0;
@@ -388,11 +403,15 @@
{
ssize_t n;
struct bootp *bp;
+ time_t *deadline = extra;
void *ptr;
DEBUG_PRINTF(1,("bootp_recvoffer: called\n"));
ptr = NULL;
+#ifdef SUPPORT_DHCP
+ dhcp_nak = false;
+#endif
n = readudp(d, &ptr, (void **)&bp, tleft);
if (n == -1 || n < sizeof(struct bootp) - BOOTP_VENDSIZE)
goto bad;
@@ -437,7 +456,19 @@
return (n);
bad:
free(ptr);
+ /*
+ * A zero errno has sendrecv() keep waiting and retransmitting. A NAK
+ * is the server's final answer, and the caller may have bounded the
+ * wait, so report those as errors to end the exchange.
+ */
errno = 0;
+#ifdef SUPPORT_DHCP
+ if (dhcp_nak)
+ errno = ECONNREFUSED;
+ else
+#endif
+ if (deadline != NULL && getsecs() >= *deadline)
+ errno = EHOSTDOWN;
return (-1);
}
@@ -510,8 +541,12 @@
vend_vivso(cp, size);
#ifdef SUPPORT_DHCP
if (tag == TAG_DHCP_MSGTYPE) {
- if(*cp != expected_dhcpmsgtype)
- return(-1);
+ if (*cp != expected_dhcpmsgtype) {
+ if (*cp == DHCPNAK &&
+ expected_dhcpmsgtype == DHCPACK)
+ dhcp_nak = true;
+ return (-1);
+ }
dhcp_ok = 1;
}
if (tag == TAG_SERVERID) {

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 14, 2:35 AM (10 m, 49 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41708436
Default Alt Text
D61477.1794623729.diff (2 KB)

Event Timeline