diff options
-rw-r--r-- | libdhcp/dhcp_client.c | 38 |
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); |