summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
b77acbc)
client->secs wasn't getting set in the REBOOT state, causing
an assertion. REBOOT should work the same way as INIT, per
RFC 2131:
secs 2 Filled in by client, seconds elapsed since client
began address acquisition or renewal process.
REBOOT is necessary because some DHCP servers (eg on
home routers) do not hand back the same IP address unless the
'ciaddr' field is filled with that address, which DISCOVER
cannot do per the RFCs. This leads to multiple leases
on machine reboot or DHCP client restart.
uint32_t mtu;
uint32_t xid;
usec_t start_time;
uint32_t mtu;
uint32_t xid;
usec_t start_time;
unsigned int attempt;
usec_t request_sent;
sd_event_source *timeout_t1;
unsigned int attempt;
usec_t request_sent;
sd_event_source *timeout_t1;
_cleanup_free_ DHCPPacket *packet;
size_t optlen, optoffset, size;
be16_t max_size;
_cleanup_free_ DHCPPacket *packet;
size_t optlen, optoffset, size;
be16_t max_size;
+ usec_t time_now;
+ uint16_t secs;
+ assert(client->start_time);
assert(ret);
assert(_optlen);
assert(_optoffset);
assert(ret);
assert(_optlen);
assert(_optoffset);
/* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
refuse to issue an DHCP lease if 'secs' is set to zero */
/* Although 'secs' field is a SHOULD in RFC 2131, certain DHCP servers
refuse to issue an DHCP lease if 'secs' is set to zero */
- packet->dhcp.secs = htobe16(client->secs);
+ r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0)
+ return r;
+ assert(time_now >= client->start_time);
+
+ /* seconds between sending first and last DISCOVER
+ * must always be strictly positive to deal with broken servers */
+ secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
+ packet->dhcp.secs = htobe16(secs);
/* RFC2132 section 4.1
A client that cannot receive unicast IP datagrams until its protocol
/* RFC2132 section 4.1
A client that cannot receive unicast IP datagrams until its protocol
static int client_send_discover(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *discover = NULL;
size_t optoffset, optlen;
static int client_send_discover(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *discover = NULL;
size_t optoffset, optlen;
int r;
assert(client);
assert(client->state == DHCP_STATE_INIT ||
client->state == DHCP_STATE_SELECTING);
int r;
assert(client);
assert(client->state == DHCP_STATE_INIT ||
client->state == DHCP_STATE_SELECTING);
- /* See RFC2131 section 4.4.1 */
-
- r = sd_event_now(client->event, clock_boottime_or_monotonic(), &time_now);
- if (r < 0)
- return r;
- assert(time_now >= client->start_time);
-
- /* seconds between sending first and last DISCOVER
- * must always be strictly positive to deal with broken servers */
- client->secs = ((time_now - client->start_time) / USEC_PER_SEC) ? : 1;
-
r = client_message_init(client, &discover, DHCP_DISCOVER,
&optlen, &optoffset);
if (r < 0)
r = client_message_init(client, &discover, DHCP_DISCOVER,
&optlen, &optoffset);
if (r < 0)
- if (client->state == DHCP_STATE_INIT) {
+ if (client->state == DHCP_STATE_INIT || client->state == DHCP_STATE_INIT_REBOOT)
client->start_time = now(clock_boottime_or_monotonic());
client->start_time = now(clock_boottime_or_monotonic());
return client_initialize_events(client, client_receive_message_raw);
}
return client_initialize_events(client, client_receive_message_raw);
}