chiark / gitweb /
sd-dhcp-client: allow the max dhcp message size to be set to the MTU of the link
authorTom Gundersen <teg@jklm.no>
Fri, 1 Aug 2014 14:10:13 +0000 (16:10 +0200)
committerTom Gundersen <teg@jklm.no>
Fri, 1 Aug 2014 14:34:50 +0000 (16:34 +0200)
src/libsystemd-network/dhcp-protocol.h
src/libsystemd-network/sd-dhcp-client.c
src/systemd/sd-dhcp-client.h

index f5119a7..abca942 100644 (file)
@@ -60,7 +60,8 @@ typedef struct DHCPPacket DHCPPacket;
 #define DHCP_IP_SIZE            (int32_t)(sizeof(struct iphdr))
 #define DHCP_IP_UDP_SIZE        (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
 #define DHCP_MESSAGE_SIZE       (int32_t)(sizeof(DHCPMessage))
-#define DHCP_MIN_OPTIONS_SIZE   308 /* spec says 312, but that includes the magic cookie */
+#define DHCP_DEFAULT_MIN_SIZE   576 /* the minimum internet hosts must be able to receive */
+#define DHCP_MIN_OPTIONS_SIZE   DHCP_DEFAULT_MIN_SIZE - DHCP_IP_UDP_SIZE - DHCP_MESSAGE_SIZE
 #define DHCP_MAGIC_COOKIE       (uint32_t)(0x63825363)
 
 enum {
index 8205ad0..f5910d9 100644 (file)
@@ -59,6 +59,7 @@ struct sd_dhcp_client {
         } _packed_ client_id;
         char *hostname;
         char *vendor_class_identifier;
+        uint32_t mtu;
         uint32_t xid;
         usec_t start_time;
         uint16_t secs;
@@ -227,6 +228,15 @@ int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client,
         return 0;
 }
 
+int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
+        assert_return(client, -EINVAL);
+        assert_return(mtu >= DHCP_DEFAULT_MIN_SIZE, -ERANGE);
+
+        client->mtu = mtu;
+
+        return 0;
+}
+
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
         assert_return(client, -EINVAL);
         assert_return(ret, -EINVAL);
@@ -366,9 +376,23 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
            Note (from ConnMan): Some DHCP servers will send bigger DHCP packets
            than the defined default size unless the Maximum Messge Size option
            is explicitely set
+
+           RFC3442 "Requirements to Avoid Sizing Constraints":
+           Because a full routing table can be quite large, the standard 576
+           octet maximum size for a DHCP message may be too short to contain
+           some legitimate Classless Static Route options.  Because of this,
+           clients implementing the Classless Static Route option SHOULD send a
+           Maximum DHCP Message Size [4] option if the DHCP client's TCP/IP
+           stack is capable of receiving larger IP datagrams.  In this case, the
+           client SHOULD set the value of this option to at least the MTU of the
+           interface that the client is configuring.  The client MAY set the
+           value of this option higher, up to the size of the largest UDP packet
+           it is prepared to accept.  (Note that the value specified in the
+           Maximum DHCP Message Size option is the total maximum packet size,
+           including IP and UDP headers.)
          */
         max_size = htobe16(size);
-        r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
+        r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
                                DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
                                2, &max_size);
         if (r < 0)
@@ -1505,6 +1529,7 @@ int sd_dhcp_client_new(sd_dhcp_client **ret) {
         client->index = -1;
         client->fd = -1;
         client->attempt = 1;
+        client->mtu = DHCP_DEFAULT_MIN_SIZE;
 
         client->req_opts_size = ELEMENTSOF(default_req_opts);
 
index 36b8710..98c6782 100644 (file)
@@ -51,6 +51,7 @@ int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
 int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
 int sd_dhcp_client_set_mac(sd_dhcp_client *client,
                            const struct ether_addr *addr);
+int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
 int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
 int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
 int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret);