udhcpc: make DHCP packets to have at least 300 DHCP bytes
authorJohannes Stezenbach <js@sig21.net>
Mon, 28 Oct 2013 22:27:37 +0000 (23:27 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 28 Oct 2013 22:27:37 +0000 (23:27 +0100)
Commit b8b72f02 removed all padding from DHCP packets
to fix operation with buggy servers which can't handle
maximum sized packets.  But it introduced a regression
with buggy routers which drop DHCP packets smaller
than 300 bytes (i.e. 342 byte ethernet packets).
Add back some padding to work around.

function                                             old     new   delta
udhcp_send_kernel_packet                             268     292     +24
udhcp_send_raw_packet                                462     473     +11
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 35/0)               Total: 35 bytes

Signed-off-by: Johannes Stezenbach <js@sig21.net>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/udhcp/packet.c

index 33c9585cfc6cebb7830927fa48f2824ebb474aca..148f52551a129e179ea8fe031ddb36a81eaa09a2 100644 (file)
@@ -143,8 +143,15 @@ int FAST_FUNC udhcp_send_raw_packet(struct dhcp_packet *dhcp_pkt,
         *
         * In order to work with those buggy servers,
         * we truncate packets after end option byte.
+        *
+        * However, RFC 1542 says "The IP Total Length and UDP Length
+        * must be large enough to contain the minimal BOOTP header of 300 octets".
+        * Thus, we retain enough padding to not go below 300 BOOTP bytes.
+        * Some devices have filters which drop DHCP packets shorter than that.
         */
        padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(packet.data.options);
+       if (padding > DHCP_SIZE - 300)
+               padding = DHCP_SIZE - 300;
 
        packet.ip.protocol = IPPROTO_UDP;
        packet.ip.saddr = source_nip;
@@ -215,6 +222,8 @@ int FAST_FUNC udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt,
 
        udhcp_dump_packet(dhcp_pkt);
        padding = DHCP_OPTIONS_BUFSIZE - 1 - udhcp_end_option(dhcp_pkt->options);
+       if (padding > DHCP_SIZE - 300)
+               padding = DHCP_SIZE - 300;
        result = safe_write(fd, dhcp_pkt, DHCP_SIZE - padding);
        msg = "write";
  ret_close: