dhcp: Increase maximum size of client identification option
authorTobias Brunner <tobias@strongswan.org>
Tue, 10 Apr 2018 16:45:16 +0000 (18:45 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 18 May 2018 16:04:01 +0000 (18:04 +0200)
This increases the chances that subject DNs that might have been cut
off with the arbitrary previous limit of 64 bytes might now be sent
successfully.

The REQUEST message has the most static overhead in terms of other
options (17 bytes) as compared to DISCOVER (5) and RELEASE (7).
Added to that are 3 bytes for the DHCP message type, which means we have
288 bytes left for the two options based on the client identity (host
name and client identification).  Since both contain the same value, a
FQDN identity, which causes a host name option to get added, may be
142 bytes long, other identities like subject DNs may be 255 bytes
long (the maximum for a DHCP option).

src/libcharon/plugins/dhcp/dhcp_socket.c

index 7b64380..320b17b 100644 (file)
@@ -202,7 +202,7 @@ static int prepare_dhcp(private_dhcp_socket_t *this,
        chunk_t chunk;
        identification_t *identity;
        dhcp_option_t *option;
-       int optlen = 0;
+       int optlen = 0, remaining;
        host_t *src;
        uint32_t id;
 
@@ -254,21 +254,28 @@ static int prepare_dhcp(private_dhcp_socket_t *this,
        option->data[0] = type;
        optlen += sizeof(dhcp_option_t) + option->len;
 
+       /* the REQUEST message has the most static overhead in the 'options' field
+        * with 17 bytes */
+       remaining = sizeof(dhcp->options) - optlen - 17;
+
        if (identity->get_type(identity) == ID_FQDN)
        {
                option = (dhcp_option_t*)&dhcp->options[optlen];
                option->type = DHCP_HOST_NAME;
-               option->len = min(chunk.len, 64);
+               option->len = min(min(chunk.len, remaining-sizeof(dhcp_option_t)), 255);
                memcpy(option->data, chunk.ptr, option->len);
                optlen += sizeof(dhcp_option_t) + option->len;
+               remaining -= sizeof(dhcp_option_t) + option->len;
        }
 
-       option = (dhcp_option_t*)&dhcp->options[optlen];
-       option->type = DHCP_CLIENT_ID;
-       option->len = min(chunk.len, 64);
-       memcpy(option->data, chunk.ptr, option->len);
-       optlen += sizeof(dhcp_option_t) + option->len;
-
+       if (remaining >= sizeof(dhcp_option_t) + 2)
+       {
+               option = (dhcp_option_t*)&dhcp->options[optlen];
+               option->type = DHCP_CLIENT_ID;
+               option->len = min(min(chunk.len, remaining-sizeof(dhcp_option_t)), 255);
+               memcpy(option->data, chunk.ptr, option->len);
+               optlen += sizeof(dhcp_option_t) + option->len;
+       }
        return optlen;
 }