chiark / gitweb /
sd-dhcp6-client: Implement Rapid Commit
authorPatrik Flykt <patrik.flykt@linux.intel.com>
Wed, 25 Jun 2014 13:54:30 +0000 (16:54 +0300)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Thu, 26 Jun 2014 13:10:47 +0000 (16:10 +0300)
Add a Rapid Commit option to Solicit messages and expect a Reply to
be received instead of an Advertise. When receiving a DHCPv6 message
from the server in state Solicit, continue testing whether the
message is a Reply. Ease up the message type checking, it's not fatal
if the message is of a wrong type.

Add helper functions to set/get the rapid commit of a lease. See
RFC 3315, sections 17., 17.1.2., 17.1.4. and 18.1.8.

src/libsystemd-network/dhcp6-lease-internal.h
src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/sd-dhcp6-client.c
src/libsystemd-network/sd-dhcp6-lease.c

index 62c16c5b6d284e30d872f7d0d238e0f180c1bbdd..109e0f4f21ec577e897a9df256c6b1d1e9128b22 100644 (file)
@@ -35,6 +35,7 @@ struct sd_dhcp6_lease {
         uint8_t *serverid;
         size_t serverid_len;
         uint8_t preference;
+        bool rapid_commit;
 
         DHCP6IA ia;
 
@@ -50,6 +51,9 @@ int dhcp6_lease_set_serverid(sd_dhcp6_lease *lease, const uint8_t *id,
 int dhcp6_lease_get_serverid(sd_dhcp6_lease *lease, uint8_t **id, size_t *len);
 int dhcp6_lease_set_preference(sd_dhcp6_lease *lease, uint8_t preference);
 int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference);
+int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease);
+int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit);
+
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid);
 
 int dhcp6_lease_new(sd_dhcp6_lease **ret);
index f488832cf919ca4406c3a192ee124b9b05cb8323..e9b382c17070c1266d213e11fe084703b3c68fcd 100644 (file)
@@ -58,13 +58,14 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
                         size_t optlen, const void *optval) {
         int r;
 
-        assert_return(optval, -EINVAL);
+        assert_return(optval || optlen == 0, -EINVAL);
 
         r = option_append_hdr(buf, buflen, code, optlen);
         if (r < 0)
                 return r;
 
-        memcpy(*buf, optval, optlen);
+        if (optval)
+                memcpy(*buf, optval, optlen);
 
         *buf += optlen;
         *buflen -= optlen;
index 60d502fcbe8225b40b73c1e57e30a292c81b6007..2d5bedcb8bced12993244b225f83dffbe4d1e429 100644 (file)
@@ -252,6 +252,9 @@ static int client_send_message(sd_dhcp6_client *client) {
         case DHCP6_STATE_SOLICITATION:
                 message->type = DHCP6_SOLICIT;
 
+                r = dhcp6_option_append(&opt, &optlen,
+                                        DHCP6_OPTION_RAPID_COMMIT, 0, NULL);
+
                 r = dhcp6_option_append_ia(&opt, &optlen, &client->ia_na);
                 if (r < 0)
                         return r;
@@ -658,6 +661,13 @@ static int client_parse_message(sd_dhcp6_client *client,
                         }
 
                         break;
+
+                case DHCP6_OPTION_RAPID_COMMIT:
+                        r = dhcp6_lease_set_rapid_commit(lease);
+                        if (r < 0)
+                                return r;
+
+                        break;
                 }
         }
 
@@ -680,9 +690,10 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
 {
         int r;
         _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
+        bool rapid_commit;
 
         if (reply->type != DHCP6_REPLY)
-                return -EINVAL;
+                return 0;
 
         r = dhcp6_lease_new(&lease);
         if (r < 0)
@@ -692,6 +703,15 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply,
         if (r < 0)
                 return r;
 
+        if (client->state == DHCP6_STATE_SOLICITATION) {
+                r = dhcp6_lease_get_rapid_commit(lease, &rapid_commit);
+                if (r < 0)
+                        return r;
+
+                if (!rapid_commit)
+                        return 0;
+        }
+
         dhcp6_lease_clear_timers(&client->lease->ia);
 
         client->lease = sd_dhcp6_lease_unref(client->lease);
@@ -708,7 +728,7 @@ static int client_receive_advertise(sd_dhcp6_client *client,
         uint8_t pref_advertise = 0, pref_lease = 0;
 
         if (advertise->type != DHCP6_ADVERTISE)
-                return -EINVAL;
+                return 0;
 
         r = dhcp6_lease_new(&lease);
         if (r < 0)
@@ -793,11 +813,13 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
         case DHCP6_STATE_SOLICITATION:
                 r = client_receive_advertise(client, message, len);
 
-                if (r == DHCP6_STATE_REQUEST)
+                if (r == DHCP6_STATE_REQUEST) {
                         client_start(client, r);
 
-                break;
+                        break;
+                }
 
+                /* fall through for Soliciation Rapid Commit option check */
         case DHCP6_STATE_REQUEST:
         case DHCP6_STATE_RENEW:
         case DHCP6_STATE_REBIND:
index 17a4b64063160fd1ee6ca754b3eddd9c1a773a62..b9d0503642517708637dd857704db74c55cb8e8f 100644 (file)
@@ -118,6 +118,23 @@ int dhcp6_lease_get_preference(sd_dhcp6_lease *lease, uint8_t *preference) {
         return 0;
 }
 
+int dhcp6_lease_set_rapid_commit(sd_dhcp6_lease *lease) {
+        assert_return(lease, -EINVAL);
+
+        lease->rapid_commit = true;
+
+        return 0;
+}
+
+int dhcp6_lease_get_rapid_commit(sd_dhcp6_lease *lease, bool *rapid_commit) {
+        assert_return(lease, -EINVAL);
+        assert_return(rapid_commit, -EINVAL);
+
+        *rapid_commit = lease->rapid_commit;
+
+        return 0;
+}
+
 int dhcp6_lease_get_iaid(sd_dhcp6_lease *lease, be32_t *iaid) {
         assert_return(lease, -EINVAL);
         assert_return(iaid, -EINVAL);