From 324f818781a250b60f2fcfa74ff1c9101d2d1315 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Fri, 1 Aug 2014 16:10:13 +0200 Subject: [PATCH] sd-dhcp-client: allow the max dhcp message size to be set to the MTU of the link --- src/libsystemd-network/dhcp-protocol.h | 3 ++- src/libsystemd-network/sd-dhcp-client.c | 27 ++++++++++++++++++++++++- src/systemd/sd-dhcp-client.h | 1 + 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h index f5119a7a5..abca9422c 100644 --- a/src/libsystemd-network/dhcp-protocol.h +++ b/src/libsystemd-network/dhcp-protocol.h @@ -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 { diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 8205ad0e1..f5910d9e0 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -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); diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 36b871049..98c67829b 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -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); -- 2.30.2