]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dhcp6: Fix DHCPv6 client file descriptor and event handling (#7796)
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 4 Jan 2018 10:02:52 +0000 (12:02 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Jan 2018 10:02:52 +0000 (11:02 +0100)
Close DHCPv6 client socket file descriptor when
sd_dhcp6_client_stop() is called and not when client_reset() is
called. If left in client_reset(), any internal temporary stopping
of the DHCPv6 client with client_stop() will call client_reset()
after which the DHCPv6 client will not be able to receive any further
DHCPv6 messages.

Similarly, client_start() needs to enable events for the DHCPv6
socket file descriptor since a call to client_stop() will call
client_reset() which will remove it from the main loop. Events should
be turned off when no DHCPv6 messages are expected.

src/libsystemd-network/sd-dhcp6-client.c

index 1c12e5430f44867143b778548e8bb3d864d4a5ed..074a409cbff4699de979b6ff2ba5e982d7a979d8 100644 (file)
@@ -336,8 +336,6 @@ static int client_reset(sd_dhcp6_client *client) {
         client->receive_message =
                 sd_event_source_unref(client->receive_message);
 
-        client->fd = safe_close(client->fd);
-
         client->transaction_id = 0;
         client->transaction_start = 0;
 
@@ -1092,6 +1090,24 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
         if (r < 0)
                 return r;
 
+        if (!client->receive_message) {
+                r = sd_event_add_io(client->event, &client->receive_message,
+                                    client->fd, EPOLLIN, client_receive_message,
+                                    client);
+                if (r < 0)
+                        goto error;
+
+                r = sd_event_source_set_priority(client->receive_message,
+                                                 client->event_priority);
+                if (r < 0)
+                        goto error;
+
+                r = sd_event_source_set_description(client->receive_message,
+                                                    "dhcp6-receive-message");
+                if (r < 0)
+                        goto error;
+        }
+
         switch (state) {
         case DHCP6_STATE_STOPPED:
                 if (client->state == DHCP6_STATE_INFORMATION_REQUEST) {
@@ -1138,16 +1154,16 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
                                       10 * USEC_PER_SEC, client_timeout_t1,
                                       client);
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 r = sd_event_source_set_priority(client->lease->ia.timeout_t1,
                                                  client->event_priority);
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 r = sd_event_source_set_description(client->lease->ia.timeout_t1, "dhcp6-t1-timeout");
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
 
@@ -1160,16 +1176,16 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
                                       10 * USEC_PER_SEC, client_timeout_t2,
                                       client);
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 r = sd_event_source_set_priority(client->lease->ia.timeout_t2,
                                                  client->event_priority);
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 r = sd_event_source_set_description(client->lease->ia.timeout_t2, "dhcp6-t2-timeout");
                 if (r < 0)
-                        return r;
+                        goto error;
 
                 client->state = state;
 
@@ -1183,18 +1199,22 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
                               clock_boottime_or_monotonic(), 0, 0, client_timeout_resend,
                               client);
         if (r < 0)
-                return r;
+                goto error;
 
         r = sd_event_source_set_priority(client->timeout_resend,
                                          client->event_priority);
         if (r < 0)
-                return r;
+                goto error;
 
         r = sd_event_source_set_description(client->timeout_resend, "dhcp6-resend-timeout");
         if (r < 0)
-                return r;
+                goto error;
 
         return 0;
+
+ error:
+        client_reset(client);
+        return r;
 }
 
 int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
@@ -1202,6 +1222,8 @@ int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
 
         client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
 
+        client->fd = safe_close(client->fd);
+
         return 0;
 }
 
@@ -1246,22 +1268,6 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
 
         client->fd = r;
 
-        r = sd_event_add_io(client->event, &client->receive_message,
-                            client->fd, EPOLLIN, client_receive_message,
-                            client);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_priority(client->receive_message,
-                                         client->event_priority);
-        if (r < 0)
-                goto error;
-
-        r = sd_event_source_set_description(client->receive_message,
-                                            "dhcp6-receive-message");
-        if (r < 0)
-                goto error;
-
         if (client->information_request)
                 state = DHCP6_STATE_INFORMATION_REQUEST;
 
@@ -1270,10 +1276,6 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
                          "Managed");
 
         return client_start(client, state);
-
-error:
-        client_reset(client);
-        return r;
 }
 
 int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event, int64_t priority) {