chiark / gitweb /
sd-dhcp-client: make sure timers fire immediately
[elogind.git] / src / libsystemd-network / sd-dhcp-client.c
index b6810a9efed8ad40422d707f4da0ddea9cf777c9..5374db74cb9b00e38c360f40a9ca2e2ca5f7371d 100644 (file)
@@ -143,6 +143,15 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client,
         assert_return(client, -EINVAL);
         assert_return(client->state == DHCP_STATE_INIT, -EBUSY);
 
+        log_dhcp_client(client, "set MAC address to "
+                        "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+                        addr->ether_addr_octet[0],
+                        addr->ether_addr_octet[1],
+                        addr->ether_addr_octet[2],
+                        addr->ether_addr_octet[3],
+                        addr->ether_addr_octet[4],
+                        addr->ether_addr_octet[5]);
+
         memcpy(&client->mac_addr, addr, ETH_ALEN);
 
         return 0;
@@ -176,7 +185,7 @@ static int client_stop(sd_dhcp_client *client, int error) {
                 sd_event_source_unref(client->receive_message);
 
         if (client->fd >= 0)
-                close(client->fd);
+                close_nointr_nofail(client->fd);
         client->fd = -1;
 
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
@@ -255,6 +264,15 @@ static int client_message_init(sd_dhcp_client *client, DHCPMessage *message,
         return 0;
 }
 
+static int dhcp_client_send_raw(sd_dhcp_client *client, DHCPPacket *packet,
+                                size_t len) {
+        dhcp_packet_append_ip_headers(packet, INADDR_ANY, DHCP_PORT_CLIENT,
+                                      INADDR_BROADCAST, DHCP_PORT_SERVER, len);
+
+        return dhcp_network_send_raw_socket(client->fd, &client->link,
+                                            packet, len);
+}
+
 static int client_send_discover(sd_dhcp_client *client, uint16_t secs) {
         int err = 0;
         _cleanup_free_ DHCPPacket *discover;
@@ -286,14 +304,13 @@ static int client_send_discover(sd_dhcp_client *client, uint16_t secs) {
         if (err < 0)
                 return err;
 
-        dhcp_packet_append_ip_headers(discover, len);
-
-        err = dhcp_network_send_raw_socket(client->fd, &client->link,
-                                           discover, len);
+        err = dhcp_client_send_raw(client, discover, len);
+        if (err < 0)
+                return err;
 
         log_dhcp_client(client, "DISCOVER");
 
-        return err;
+        return 0;
 }
 
 static int client_send_request(sd_dhcp_client *client, uint16_t secs) {
@@ -339,15 +356,14 @@ static int client_send_request(sd_dhcp_client *client, uint16_t secs) {
                                                    &request->dhcp,
                                                    len - DHCP_IP_UDP_SIZE);
         } else {
-                dhcp_packet_append_ip_headers(request, len);
-
-                err = dhcp_network_send_raw_socket(client->fd, &client->link,
-                                                   request, len);
+                err = dhcp_client_send_raw(client, request, len);
         }
+        if (err < 0)
+                return err;
 
         log_dhcp_client(client, "REQUEST");
 
-        return err;
+        return 0;
 }
 
 static uint16_t client_update_secs(sd_dhcp_client *client, usec_t time_now)
@@ -361,13 +377,18 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                                  void *userdata) {
         sd_dhcp_client *client = userdata;
         usec_t next_timeout = 0;
+        uint64_t time_now;
         uint32_t time_left;
-        int r = 0;
+        int r;
 
         assert(s);
         assert(client);
         assert(client->event);
 
+        r = sd_event_get_now_monotonic(client->event, &time_now);
+        if (r < 0)
+                goto error;
+
         switch (client->state) {
         case DHCP_STATE_RENEWING:
 
@@ -375,7 +396,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 if (time_left < 60)
                         time_left = 60;
 
-                next_timeout = usec + time_left * USEC_PER_SEC;
+                next_timeout = time_now + time_left * USEC_PER_SEC;
 
                 break;
 
@@ -385,7 +406,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 if (time_left < 60)
                         time_left = 60;
 
-                next_timeout = usec + time_left * USEC_PER_SEC;
+                next_timeout = time_now + time_left * USEC_PER_SEC;
                 break;
 
         case DHCP_STATE_INIT:
@@ -398,7 +419,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 if (client->attempt < 64)
                         client->attempt *= 2;
 
-                next_timeout = usec + (client->attempt - 1) * USEC_PER_SEC;
+                next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
 
                 break;
         }
@@ -423,7 +444,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
         switch (client->state) {
         case DHCP_STATE_INIT:
 
-                client_update_secs(client, usec);
+                client_update_secs(client, time_now);
 
                 r = client_send_discover(client, client->secs);
                 if (r >= 0) {
@@ -437,7 +458,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 break;
 
         case DHCP_STATE_SELECTING:
-                client_update_secs(client, usec);
+                client_update_secs(client, time_now);
 
                 r = client_send_discover(client, client->secs);
                 if (r < 0 && client->attempt >= 64)
@@ -452,7 +473,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 if (r < 0 && client->attempt >= 64)
                          goto error;
 
-                client->request_sent = usec;
+                client->request_sent = time_now;
 
                 break;
 
@@ -474,8 +495,7 @@ error:
 }
 
 static int client_initialize_events(sd_dhcp_client *client,
-                                    sd_event_io_handler_t io_callback,
-                                    usec_t usec) {
+                                    sd_event_io_handler_t io_callback) {
         int r;
 
         assert(client);
@@ -495,8 +515,7 @@ static int client_initialize_events(sd_dhcp_client *client,
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
         r = sd_event_add_monotonic(client->event,
-                                   &client->timeout_resend,
-                                   usec, 0,
+                                   &client->timeout_resend, 0, 0,
                                    client_timeout_resend, client);
         if (r < 0)
                 goto error;
@@ -530,7 +549,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         if (client->fd >= 0) {
                 client->receive_message =
                         sd_event_source_unref(client->receive_message);
-                close(client->fd);
+                close_nointr_nofail(client->fd);
                 client->fd = -1;
         }
 
@@ -547,8 +566,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
 
         log_dhcp_client(client, "TIMEOUT T2");
 
-        return client_initialize_events(client, client_receive_message_raw,
-                                        usec);
+        return client_initialize_events(client, client_receive_message_raw);
 }
 
 static int client_timeout_t1(sd_event_source *s, uint64_t usec,
@@ -571,7 +589,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
 
         log_dhcp_client(client, "TIMEOUT T1");
 
-        return client_initialize_events(client, client_receive_message_udp, usec);
+        return client_initialize_events(client, client_receive_message_udp);
 }
 
 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
@@ -680,10 +698,10 @@ static int client_set_lease_timeouts(sd_dhcp_client *client, uint64_t usec) {
                 return -EINVAL;
 
         r = sd_event_add_monotonic(client->event,
-                                     &client->timeout_t1,
-                                     next_timeout,
-                                     10 * USEC_PER_MSEC,
-                                     client_timeout_t1, client);
+                                   &client->timeout_t1,
+                                   next_timeout,
+                                   10 * USEC_PER_MSEC,
+                                   client_timeout_t1, client);
         if (r < 0)
                 return r;
 
@@ -707,10 +725,10 @@ static int client_set_lease_timeouts(sd_dhcp_client *client, uint64_t usec) {
                 return -EINVAL;
 
         r = sd_event_add_monotonic(client->event,
-                                     &client->timeout_t2,
-                                     next_timeout,
-                                     10 * USEC_PER_MSEC,
-                                     client_timeout_t2, client);
+                                   &client->timeout_t2,
+                                   next_timeout,
+                                   10 * USEC_PER_MSEC,
+                                   client_timeout_t2, client);
         if (r < 0)
                 return r;
 
@@ -725,9 +743,9 @@ static int client_set_lease_timeouts(sd_dhcp_client *client, uint64_t usec) {
                 return -EINVAL;
 
         r = sd_event_add_monotonic(client->event,
-                                     &client->timeout_expire, next_timeout,
-                                     10 * USEC_PER_MSEC,
-                                     client_timeout_expire, client);
+                                   &client->timeout_expire, next_timeout,
+                                   10 * USEC_PER_MSEC,
+                                   client_timeout_expire, client);
         if (r < 0)
                 return r;
 
@@ -785,9 +803,8 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                         client->attempt = 1;
 
                         r = sd_event_add_monotonic(client->event,
-                                                   &client->timeout_resend,
-                                                   time_now, 0,
-                                                   client_timeout_resend,
+                                                   &client->timeout_resend, 0,
+                                                   0, client_timeout_resend,
                                                    client);
                         if (r < 0)
                                 goto error;
@@ -832,7 +849,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                         client->receive_message =
                                 sd_event_source_unref(client->receive_message);
-                        close(client->fd);
+                        close_nointr_nofail(client->fd);
                         client->fd = -1;
                 }
 
@@ -971,8 +988,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
 
         log_dhcp_client(client, "STARTED");
 
-        return client_initialize_events(client, client_receive_message_raw,
-                                        client->start_time);
+        return client_initialize_events(client, client_receive_message_raw);
 }
 
 int sd_dhcp_client_stop(sd_dhcp_client *client) {