summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdhcp/dhcp_client.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/libdhcp/dhcp_client.c b/libdhcp/dhcp_client.c
index b0a2868..4ab456c 100644
--- a/libdhcp/dhcp_client.c
+++ b/libdhcp/dhcp_client.c
@@ -149,6 +149,7 @@ struct dhcp_client {
STATE_REBOOTING,
} state;
uint8_t last_sent_msgtyp;
+ uint16_t last_discover_secs;
/* Lifetime of xid:
* 1. initial : [INIT]->DHCPDISCOVER->DHCPOFFER->DHCPREQUEST-+->DHCPNAK-------------->[INIT]
* |->DHCPACK->DHCPDECLINE->[INIT]
@@ -242,10 +243,39 @@ static bool dhcp_client_send(struct dhcp_client *client, uint8_t msgtyp, const c
msg.hlen = sizeof(client->self_eth_addr);
msg.hops = 0; /* relays increment this when they forward it along */
msg.xid = uint32be_marshal(client->xid);
- /* systemd's sd-dhcp-client.c asserts that some servers are
- * broken and require .secs to be non-zero, even though RFC
- * 2131 explicitly says that this is valid. */
- msg.secs = uint16be_marshal( ((VCALL(bootclock, get_time_ns) - client->time_ns_init)/NS_PER_S) ?: 1);
+ msg.secs = uint16be_marshal( ({
+ uint16_t secs;
+ switch (msgtyp) {
+ case DHCP_MSGTYP_DISCOVER: case DHCP_MSGTYP_INFORM:
+ case DHCP_MSGTYP_REQUEST:
+ secs = (VCALL(bootclock, get_time_ns) - client->time_ns_init)/NS_PER_S;
+ if (!secs)
+ /* systemd's sd-dhcp-client.c asserts that some
+ * servers are broken and require .secs to be
+ * non-zero, even though RFC 2131 explicitly
+ * says that zero is valid. */
+ secs = 1;
+ if (msgtyp == DHCP_MSGTYP_REQUEST &&
+ client->state == STATE_SELECTING)
+ /* "The DHCPREQUEST message MUST use the same
+ * value in the DHCP message header's 'secs'
+ * field ... as the original DHCPDISCOVER
+ * message" -- RFC 2131
+ */
+ secs = client->last_discover_secs;
+ if (msgtyp == DHCP_MSGTYP_DISCOVER)
+ /* Record the value to make the above
+ * possible. */
+ client->last_discover_secs = secs;
+ break;
+ case DHCP_MSGTYP_DECLINE: case DHCP_MSGTYP_RELEASE:
+ secs = 0;
+ break;
+ default:
+ assert_notreached("invalid message type for client to send");
+ }
+ secs;
+ }) );
switch (msgtyp) {
case DHCP_MSGTYP_DISCOVER: case DHCP_MSGTYP_INFORM: case DHCP_MSGTYP_REQUEST:
msg.flags = uint16be_marshal(server_broadcasts ? DHCP_FLAG_BROADCAST : 0);