]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-server: support rapid commit (RFC4039)
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Nov 2023 16:27:46 +0000 (01:27 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 7 Nov 2023 17:39:59 +0000 (02:39 +0900)
https://datatracker.ietf.org/doc/html/rfc4039

src/libsystemd-network/dhcp-server-internal.h
src/libsystemd-network/sd-dhcp-server.c
src/systemd/sd-dhcp-server.h

index 1879b5b159f81c69bd95d89ec42ee2b3fc086505..8db517293f891722262fef228e4659916e744c12 100644 (file)
@@ -84,6 +84,7 @@ struct sd_dhcp_server {
         usec_t max_lease_time;
         usec_t default_lease_time;
         usec_t ipv6_only_preferred_usec;
+        bool rapid_commit;
 
         sd_dhcp_server_callback_t callback;
         void *callback_userdata;
@@ -108,6 +109,7 @@ typedef struct DHCPRequest {
         char *hostname;
         const uint8_t *parameter_request_list;
         size_t parameter_request_list_len;
+        bool rapid_commit;
 } DHCPRequest;
 
 extern const struct hash_ops dhcp_lease_hash_ops;
index 54a659766d38541f87a259c1c48ce25a70ef571f..437028800d0eff7f121435a0f2feb25e555a2691 100644 (file)
@@ -211,6 +211,7 @@ int sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
                 .bind_to_interface = true,
                 .default_lease_time = DHCP_DEFAULT_LEASE_TIME_USEC,
                 .max_lease_time = DHCP_MAX_LEASE_TIME_USEC,
+                .rapid_commit = true,
         };
 
         *ret = TAKE_PTR(server);
@@ -692,6 +693,15 @@ static int server_send_offer_or_ack(
                         return r;
         }
 
+        if (server->rapid_commit && req->rapid_commit && type == DHCP_ACK) {
+                r = dhcp_option_append(
+                                &packet->dhcp, req->max_optlen, &offset, 0,
+                                SD_DHCP_OPTION_RAPID_COMMIT,
+                                0, NULL);
+                if (r < 0)
+                        return r;
+        }
+
         return dhcp_server_send_packet(server, req, packet, type, offset);
 }
 
@@ -810,6 +820,10 @@ static int parse_request(uint8_t code, uint8_t len, const void *option, void *us
                 req->parameter_request_list = option;
                 req->parameter_request_list_len = len;
                 break;
+
+        case SD_DHCP_OPTION_RAPID_COMMIT:
+                req->rapid_commit = true;
+                break;
         }
 
         return 0;
@@ -1210,6 +1224,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
                         /* no free addresses left */
                         return 0;
 
+                if (server->rapid_commit && req->rapid_commit)
+                        return server_ack_request(server, req, existing_lease, address);
+
                 r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
                 if (r < 0)
                         /* this only fails on critical errors */
@@ -1274,6 +1291,9 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz
                         address = req->message->ciaddr;
                 }
 
+                /* Silently ignore Rapid Commit option in REQUEST message. */
+                req->rapid_commit = false;
+
                 /* disallow our own address */
                 if (address == server->address)
                         return 0;
@@ -1545,6 +1565,13 @@ int sd_dhcp_server_set_ipv6_only_preferred_usec(sd_dhcp_server *server, uint64_t
         return 0;
 }
 
+int sd_dhcp_server_set_rapid_commit(sd_dhcp_server *server, int enabled) {
+        assert_return(server, -EINVAL);
+
+        server->rapid_commit = enabled;
+        return 0;
+}
+
 int sd_dhcp_server_set_servers(
                 sd_dhcp_server *server,
                 sd_dhcp_lease_server_type_t what,
index 1256076b833bf746d599472d8c0dc528f55d325a..feafa5d1fc69eab866d84fbefb62c29d3b295aed 100644 (file)
@@ -85,6 +85,7 @@ int sd_dhcp_server_set_static_lease(sd_dhcp_server *server, const struct in_addr
 int sd_dhcp_server_set_max_lease_time(sd_dhcp_server *server, uint64_t t);
 int sd_dhcp_server_set_default_lease_time(sd_dhcp_server *server, uint64_t t);
 int sd_dhcp_server_set_ipv6_only_preferred_usec(sd_dhcp_server *server, uint64_t t);
+int sd_dhcp_server_set_rapid_commit(sd_dhcp_server *server, int enabled);
 
 int sd_dhcp_server_forcerenew(sd_dhcp_server *server);