On Wed, Nov 13, 2013 at 11:22:53PM +0200, Patrik Flykt wrote: > Compute the default T1 and T2 timer values if they were not set by > the DHCP server. Verify that the values are reasonable. > --- > src/dhcp/client.c | 123 > ++++++++++++++++++++++++++++++++++++++++++++++++++- > src/dhcp/protocol.h | 2 + > 2 files changed, 124 insertions(+), 1 deletion(-) > > diff --git a/src/dhcp/client.c b/src/dhcp/client.c > index 669804a..50008a9 100644 > --- a/src/dhcp/client.c > +++ b/src/dhcp/client.c > @@ -34,6 +34,8 @@ > > struct DHCPLease { > uint32_t lifetime; > + uint32_t t2; > + uint32_t t1; Can we have the order t1, t2 everywhere?
> struct in_addr address; > struct in_addr server_address; > struct in_addr subnet_mask; > @@ -57,6 +59,10 @@ struct DHCPClient { > uint32_t xid; > uint64_t start_time; > unsigned int attempt; > + uint64_t request_sent; > + sd_event_source *timeout_expire; > + sd_event_source *timeout_t1; > + sd_event_source *timeout_t2; > DHCPLease *lease; > }; > > @@ -177,6 +183,16 @@ static int client_stop(DHCPClient *client, int error) > client->timeout_resend = > sd_event_source_unref(client->timeout_resend); > > + if (client->timeout_expire) > + client->timeout_expire = > + sd_event_source_unref(client->timeout_expire); sd_event_source_unref accepts NULL, so those if's are not necessary. I think that this is not performance trical code, so it's better to simplify. > + if (client->timeout_t2) > + client->timeout_t2 = > + sd_event_source_unref(client->timeout_t2); > + if (client->timeout_t1) > + client->timeout_t1 = > + sd_event_source_unref(client->timeout_t1); > + > client->attempt = 1; > > switch (client->state) { > @@ -184,6 +200,7 @@ static int client_stop(DHCPClient *client, int error) > case DHCP_STATE_INIT: > case DHCP_STATE_SELECTING: > case DHCP_STATE_REQUESTING: > + case DHCP_STATE_BOUND: > > client->start_time = 0; > client->state = DHCP_STATE_INIT; > @@ -191,7 +208,6 @@ static int client_stop(DHCPClient *client, int error) > > case DHCP_STATE_INIT_REBOOT: > case DHCP_STATE_REBOOTING: > - case DHCP_STATE_BOUND: > case DHCP_STATE_RENEWING: > case DHCP_STATE_REBINDING: > > @@ -447,6 +463,8 @@ static int client_timeout_resend(sd_event_source *s, > uint64_t usec, > if (err < 0 && client->attempt >= 64) > goto error; > > + client->request_sent = usec; > + > break; > > case DHCP_STATE_INIT_REBOOT: > @@ -466,6 +484,22 @@ error: > return 0; > } > > +static int client_timeout_expire(sd_event_source *s, uint64_t usec, > + void *userdata) > +{ > + return 0; > +} > + > +static int client_timeout_t2(sd_event_source *s, uint64_t usec, void > *userdata) > +{ > + return 0; > +} > + > +static int client_timeout_t1(sd_event_source *s, uint64_t usec, void > *userdata) > +{ > + return 0; > +} > + > static int client_parse_offer(uint8_t code, uint8_t len, uint8_t *option, > void *user_data) > { > @@ -499,6 +533,22 @@ static int client_parse_offer(uint8_t code, uint8_t len, > uint8_t *option, > memcpy(&lease->router.s_addr, option, 4); > > break; > + > + case DHCP_OPTION_RENEWAL_T1_TIME: > + if (len == 4) { > + memcpy(&val, option, 4); > + lease->t1 = ntohl(val); > + } > + > + break; > + > + case DHCP_OPTION_REBINDING_T2_TIME: > + if (len == 4) { > + memcpy(&val, option, 4); > + lease->t2 = ntohl(val); > + } > + > + break; > } > > return 0; > @@ -635,6 +685,72 @@ error: > return err; > } > > +static uint64_t client_compute_timeout(uint64_t request_sent, > + uint32_t lifetime) > +{ > + return request_sent + (lifetime - 3) * USEC_PER_SEC + > + + (random_u() & 0x1fffff); > +} > + > +static int client_set_lease_timeouts(DHCPClient *client, uint64_t usec) > +{ > + int err; > + uint64_t next_timeout; > + > + if (client->lease->lifetime < 10) > + return -EINVAL; > + > + if (!client->lease->t1) > + client->lease->t1 = client->lease->lifetime / 2; > + > + next_timeout = client_compute_timeout(client->request_sent, > + client->lease->t1); > + if (next_timeout < usec) > + return -EINVAL; > + > + err = sd_event_add_monotonic(client->event, next_timeout, > + 10 * USEC_PER_MSEC, > + client_timeout_t1, client, > + &client->timeout_t1); > + if (err < 0) > + return err; > + > + if (!client->lease->t2) > + client->lease->t2 = client->lease->lifetime * 7 / 8; > + > + if (client->lease->t2 < client->lease->t1) > + return -EINVAL; > + > + if (client->lease->lifetime < client->lease->t2) > + return -EINVAL; > + > + next_timeout = client_compute_timeout(client->request_sent, > + client->lease->t2); > + if (next_timeout < usec) > + return -EINVAL; > + > + err = sd_event_add_monotonic(client->event, next_timeout, > + 10 * USEC_PER_MSEC, > + client_timeout_t2, client, > + &client->timeout_t2); > + if (err < 0) > + return err; > + > + next_timeout = client_compute_timeout(client->request_sent, > + client->lease->lifetime); > + if (next_timeout < usec) > + return -EINVAL; > + > + err = sd_event_add_monotonic(client->event, next_timeout, > + 10 * USEC_PER_MSEC, > + client_timeout_expire, client, > + &client->timeout_expire); > + if (err < 0) > + return err; > + > + return 0; > +} > + > static int client_receive_raw_message(sd_event_source *s, int fd, > uint32_t revents, void *userdata) > { > @@ -697,6 +813,11 @@ static int client_receive_raw_message(sd_event_source > *s, int fd, > client->last_addr->s_addr = > client->lease->address.s_addr; > > + err = client_set_lease_timeouts(client, > + > now(CLOCK_MONOTONIC)); > + if (err < 0 ) > + goto error; > + > client_notify(client, DHCP_EVENT_IP_ACQUIRE); > > close(client->fd); > diff --git a/src/dhcp/protocol.h b/src/dhcp/protocol.h > index 6503931..773c29c 100644 > --- a/src/dhcp/protocol.h > +++ b/src/dhcp/protocol.h > @@ -100,5 +100,7 @@ typedef enum DHCPState DHCPState; > #define DHCP_OPTION_SERVER_IDENTIFIER 54 > #define DHCP_OPTION_PARAMETER_REQUEST_LIST 55 > #define DHCP_OPTION_MAXIMUM_MESSAGE_SIZE 57 > +#define DHCP_OPTION_RENEWAL_T1_TIME 58 > +#define DHCP_OPTION_REBINDING_T2_TIME 59 > #define DHCP_OPTION_CLIENT_IDENTIFIER 61 > #define DHCP_OPTION_END 255 Zbyszek _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel