[systemd-commits] 4 commits - src/libsystemd-network

Patrik Flykt pflykt at kemper.freedesktop.org
Wed Mar 19 02:01:36 PDT 2014


 src/libsystemd-network/dhcp-internal.h    |    2 
 src/libsystemd-network/dhcp-packet.c      |   10 +-
 src/libsystemd-network/sd-dhcp-client.c   |  129 +++++++++++++++++++++++-------
 src/libsystemd-network/test-dhcp-client.c |   46 ++++------
 4 files changed, 128 insertions(+), 59 deletions(-)

New commits:
commit 8b1243f72ed321bd11f0939405b6d0963ce5eea5
Author: Patrik Flykt <patrik.flykt at linux.intel.com>
Date:   Fri Jan 31 11:31:22 2014 +0200

    libsystemd-network: Add Init-Reboot support
    
    Init-Reboot is tried if a client IP address has been given when
    the DHCP client is started. In Init-Reboot, start by sending a
    broadcast DHCP Request including the supplied client IP address
    but without the server identifier. After sending the request,
    enter Reboot state.
    
    If a DHCP Ack is received, proceed to Bound state as usual. If a
    DHCP Nak is received or the first timeout triggers, start the
    address acquisition over from DHCP Init state.
    
    See RFC 2131, sections 4.3.2, 4.4, 4.4.1 and 4.4.2 for details.

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 792e4af..8411141 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -338,7 +338,17 @@ static int client_send_request(sd_dhcp_client *client, uint16_t secs) {
         if (err < 0)
                 return err;
 
-        if (client->state == DHCP_STATE_REQUESTING) {
+        switch (client->state) {
+
+        case DHCP_STATE_INIT_REBOOT:
+                err = dhcp_option_append(&opt, &optlen,
+                                         DHCP_OPTION_REQUESTED_IP_ADDRESS,
+                                         4, &client->last_addr);
+                if (err < 0)
+                        return err;
+                break;
+
+        case DHCP_STATE_REQUESTING:
                 err = dhcp_option_append(&opt, &optlen,
                                          DHCP_OPTION_REQUESTED_IP_ADDRESS,
                                          4, &client->lease->address);
@@ -350,6 +360,16 @@ static int client_send_request(sd_dhcp_client *client, uint16_t secs) {
                                          4, &client->lease->server_address);
                 if (err < 0)
                         return err;
+                break;
+
+        case DHCP_STATE_INIT:
+        case DHCP_STATE_SELECTING:
+        case DHCP_STATE_REBOOTING:
+        case DHCP_STATE_BOUND:
+        case DHCP_STATE_RENEWING:
+        case DHCP_STATE_REBINDING:
+
+                break;
         }
 
         err = dhcp_option_append(&opt, &optlen, DHCP_OPTION_END, 0, NULL);
@@ -416,9 +436,15 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 next_timeout = time_now + time_left * USEC_PER_SEC;
                 break;
 
+        case DHCP_STATE_REBOOTING:
+                /* start over as we did not receive a timely ack or nak */
+                client->state = DHCP_STATE_INIT;
+                client->attempt = 1;
+                client->xid = random_u32();
+
+                /* fall through */
         case DHCP_STATE_INIT:
         case DHCP_STATE_INIT_REBOOT:
-        case DHCP_STATE_REBOOTING:
         case DHCP_STATE_SELECTING:
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_BOUND:
@@ -473,6 +499,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
 
                 break;
 
+        case DHCP_STATE_INIT_REBOOT:
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_RENEWING:
         case DHCP_STATE_REBINDING:
@@ -480,11 +507,13 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                 if (r < 0 && client->attempt >= 64)
                          goto error;
 
+                if (client->state == DHCP_STATE_INIT_REBOOT)
+                        client->state = DHCP_STATE_REBOOTING;
+
                 client->request_sent = time_now;
 
                 break;
 
-        case DHCP_STATE_INIT_REBOOT:
         case DHCP_STATE_REBOOTING:
         case DHCP_STATE_BOUND:
 
@@ -853,20 +882,37 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                 break;
 
+        case DHCP_STATE_REBOOTING:
         case DHCP_STATE_REQUESTING:
         case DHCP_STATE_RENEWING:
         case DHCP_STATE_REBINDING:
 
                 r = client_handle_ack(client, message, len);
 
-                if (r == DHCP_EVENT_NO_LEASE)
+                if (r == DHCP_EVENT_NO_LEASE) {
+
+                        client->timeout_resend =
+                                sd_event_source_unref(client->timeout_resend);
+
+                        if (client->state == DHCP_STATE_REBOOTING) {
+                                r = client_initialize(client);
+                                if (r < 0)
+                                        goto error;
+
+                                r = client_start(client);
+                                if (r < 0)
+                                        goto error;
+                        }
+
                         goto error;
+                }
 
                 if (r >= 0) {
                         client->timeout_resend =
                                 sd_event_source_unref(client->timeout_resend);
 
-                        if (client->state == DHCP_STATE_REQUESTING)
+                        if (IN_SET(client->state, DHCP_STATE_REQUESTING,
+                                   DHCP_STATE_REBOOTING))
                                 notify_event = DHCP_EVENT_IP_ACQUIRE;
                         else if (r != DHCP_EVENT_IP_ACQUIRE)
                                 notify_event = r;
@@ -894,7 +940,6 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
         case DHCP_STATE_INIT:
         case DHCP_STATE_INIT_REBOOT:
-        case DHCP_STATE_REBOOTING:
         case DHCP_STATE_BOUND:
 
                 break;

commit 0f941add365638ad487ba94017cc2cf1f8d45195
Author: Patrik Flykt <patrik.flykt at linux.intel.com>
Date:   Wed Mar 12 11:46:40 2014 +0200

    libsystemd-network: Restart DHCP acquisition if the lease expires
    
    This causes the DHCP client struct initialization and DHCP client
    starting to be factored out into functions of their own.

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 2d3af2f..792e4af 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -178,7 +178,7 @@ static int client_notify(sd_dhcp_client *client, int event) {
         return 0;
 }
 
-static int client_stop(sd_dhcp_client *client, int error) {
+static int client_initialize(sd_dhcp_client *client) {
         assert_return(client, -EINVAL);
 
         client->receive_message =
@@ -194,15 +194,24 @@ static int client_stop(sd_dhcp_client *client, int error) {
 
         client->attempt = 1;
 
-        client_notify(client, error);
-
         client->start_time = 0;
         client->secs = 0;
         client->state = DHCP_STATE_INIT;
+        client->xid = 0;
 
         if (client->lease)
                 client->lease = sd_dhcp_lease_unref(client->lease);
 
+        return 0;
+}
+
+static int client_stop(sd_dhcp_client *client, int error) {
+        assert_return(client, -EINVAL);
+
+        client_notify(client, error);
+
+        client_initialize(client);
+
         log_dhcp_client(client, "STOPPED");
 
         return 0;
@@ -529,13 +538,46 @@ error:
 
 }
 
+static int client_start(sd_dhcp_client *client) {
+        int r;
+
+        assert_return(client, -EINVAL);
+        assert_return(client->event, -EINVAL);
+        assert_return(client->index > 0, -EINVAL);
+        assert_return(client->fd < 0, -EBUSY);
+        assert_return(client->xid == 0, -EINVAL);
+        assert_return(client->state == DHCP_STATE_INIT ||
+                      client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
+
+        client->xid = random_u32();
+
+        r = dhcp_network_bind_raw_socket(client->index, &client->link);
+
+        if (r < 0) {
+                client_stop(client, r);
+                return r;
+        }
+
+        client->fd = r;
+        client->start_time = now(CLOCK_MONOTONIC);
+        client->secs = 0;
+
+        log_dhcp_client(client, "STARTED");
+
+        return client_initialize_events(client, client_receive_message_raw);
+}
+
 static int client_timeout_expire(sd_event_source *s, uint64_t usec,
                                  void *userdata) {
         sd_dhcp_client *client = userdata;
 
         log_dhcp_client(client, "EXPIRED");
 
-        client_stop(client, DHCP_EVENT_EXPIRED);
+        client_notify(client, DHCP_EVENT_EXPIRED);
+
+        /* start over as the lease was lost */
+        client_initialize(client);
+        client_start(client);
 
         return 0;
 }
@@ -961,27 +1003,15 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
         int r;
 
         assert_return(client, -EINVAL);
-        assert_return(client->event, -EINVAL);
-        assert_return(client->index > 0, -EINVAL);
-        assert_return(client->state == DHCP_STATE_INIT ||
-                      client->state == DHCP_STATE_INIT_REBOOT, -EBUSY);
 
-        client->xid = random_u32();
-
-        r = dhcp_network_bind_raw_socket(client->index, &client->link);
-
-        if (r < 0) {
-                client_stop(client, r);
+        r = client_initialize(client);
+        if (r < 0)
                 return r;
-        }
 
-        client->fd = r;
-        client->start_time = now(CLOCK_MONOTONIC);
-        client->secs = 0;
+        if (client->last_addr)
+                client->state = DHCP_STATE_INIT_REBOOT;
 
-        log_dhcp_client(client, "STARTED");
-
-        return client_initialize_events(client, client_receive_message_raw);
+        return client_start(client);
 }
 
 int sd_dhcp_client_stop(sd_dhcp_client *client) {

commit 8fc8e3ab98104db40f5674984dd3edb54e62267f
Author: Patrik Flykt <patrik.flykt at linux.intel.com>
Date:   Wed Mar 12 12:52:00 2014 +0200

    libsystemd-network: Add hangcheck timer for DHCP client test

diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index cfc75ae..1eb4648 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -44,6 +44,15 @@ static bool verbose = false;
 static int test_fd[2];
 static test_callback_recv_t callback_recv;
 static be32_t xid;
+static sd_event_source *test_hangcheck;
+
+static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec,
+                               void *userdata)
+{
+        assert_not_reached("Test case should have completed in 2 seconds");
+
+        return 0;
+}
 
 static void test_request_basic(sd_event *e)
 {
@@ -419,6 +428,7 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover)
 
 static void test_addr_acq(sd_event *e)
 {
+        usec_t time_now = now(CLOCK_MONOTONIC);
         sd_dhcp_client *client;
         int res, r;
 
@@ -440,11 +450,17 @@ static void test_addr_acq(sd_event *e)
 
         callback_recv = test_addr_acq_recv_discover;
 
+        assert_se(sd_event_add_monotonic(e, &test_hangcheck,
+                                         time_now + 2 * USEC_PER_SEC, 0,
+                                         test_dhcp_hangcheck, NULL) >= 0);
+
         res = sd_dhcp_client_start(client);
         assert_se(res == 0 || res == -EINPROGRESS);
 
         sd_event_loop(e);
 
+        test_hangcheck = sd_event_source_unref(test_hangcheck);
+
         sd_dhcp_client_set_callback(client, NULL, NULL);
         sd_dhcp_client_stop(client);
         sd_dhcp_client_free(client);

commit a838c939a3a50b7318efac7b960392ca8d13bb1e
Author: Patrik Flykt <patrik.flykt at linux.intel.com>
Date:   Tue Feb 25 13:33:24 2014 +0200

    libsystemd-network: Export checksum function to test case
    
    Remove identical checksum function implementation from the test
    case code.

diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index 3c3e1f6..064b13b 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -48,6 +48,8 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
 int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
                       uint8_t **opt, size_t *optlen);
 
+uint16_t dhcp_packet_checksum(void *buf, int len);
+
 void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
                                    uint16_t source, be32_t destination_addr,
                                    uint16_t destination, uint16_t len);
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 418a977..bed942f 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -69,7 +69,7 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
         return 0;
 }
 
-static uint16_t dhcp_checksum(void *buf, int len) {
+uint16_t dhcp_packet_checksum(void *buf, int len) {
         uint32_t sum;
         uint16_t *check;
         int i;
@@ -109,11 +109,11 @@ void dhcp_packet_append_ip_headers(DHCPPacket *packet, be32_t source_addr,
         packet->udp.len = htobe16(len - DHCP_IP_SIZE);
 
         packet->ip.check = packet->udp.len;
-        packet->udp.check = dhcp_checksum(&packet->ip.ttl, len - 8);
+        packet->udp.check = dhcp_packet_checksum(&packet->ip.ttl, len - 8);
 
         packet->ip.ttl = IPDEFTTL;
         packet->ip.check = 0;
-        packet->ip.check = dhcp_checksum(&packet->ip, DHCP_IP_SIZE);
+        packet->ip.check = dhcp_packet_checksum(&packet->ip, DHCP_IP_SIZE);
 }
 
 int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
@@ -150,7 +150,7 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
                 return -EINVAL;
         }
 
-        if (dhcp_checksum(&packet->ip, hdrlen)) {
+        if (dhcp_packet_checksum(&packet->ip, hdrlen)) {
                 log_dhcp_client(client, "ignoring packet: invalid IP checksum");
                 return -EINVAL;
         }
@@ -175,7 +175,7 @@ int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum) {
                 packet->ip.check = packet->udp.len;
                 packet->ip.ttl = 0;
 
-                if (dhcp_checksum(&packet->ip.ttl,
+                if (dhcp_packet_checksum(&packet->ip.ttl,
                                   be16toh(packet->udp.len) + 12)) {
                         log_dhcp_client(client, "ignoring packet: invalid UDP checksum");
                         return -EINVAL;
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 8061e5f..cfc75ae 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -102,30 +102,6 @@ static void test_request_basic(sd_event *e)
         assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
 }
 
-static uint16_t client_checksum(void *buf, int len)
-{
-        uint32_t sum;
-        uint16_t *check;
-        int i;
-        uint8_t *odd;
-
-        sum = 0;
-        check = buf;
-
-        for (i = 0; i < len / 2 ; i++)
-                sum += check[i];
-
-        if (len & 0x01) {
-                odd = buf;
-                sum += odd[len - 1];
-        }
-
-        while (sum >> 16)
-                sum = (sum & 0xffff) + (sum >> 16);
-
-        return ~sum;
-}
-
 static void test_checksum(void)
 {
         uint8_t buf[20] = {
@@ -137,7 +113,7 @@ static void test_checksum(void)
         if (verbose)
                 printf("* %s\n", __FUNCTION__);
 
-        assert_se(client_checksum(&buf, 20) == be16toh(0x78ae));
+        assert_se(dhcp_packet_checksum(&buf, 20) == be16toh(0x78ae));
 }
 
 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
@@ -173,13 +149,13 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
         discover->ip.ttl = 0;
         discover->ip.check = discover->udp.len;
 
-        udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
+        udp_check = ~dhcp_packet_checksum(&discover->ip.ttl, len - 8);
         assert_se(udp_check == 0xffff);
 
         discover->ip.ttl = IPDEFTTL;
         discover->ip.check = ip_check;
 
-        ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
+        ip_check = ~dhcp_packet_checksum(&discover->ip, sizeof(discover->ip));
         assert_se(ip_check == 0xffff);
 
         assert_se(discover->dhcp.xid);



More information about the systemd-commits mailing list