diff options
| author | Roy Marples <roy@marples.name> | 2016-05-11 14:17:15 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2016-05-11 14:17:15 +0000 |
| commit | 3ce1402fdc06ba79429831d7ff8c150bec9aee9c (patch) | |
| tree | f682449578c5830fd3045eb6888125bebcc06960 /dhcp.c | |
| parent | 945c2f21f9ae5e57e13f4349fbb57d3e8abb8045 (diff) | |
| download | dhcpcd-3ce1402fdc06ba79429831d7ff8c150bec9aee9c.tar.xz | |
Handle truncated DHCP messages, provided only the BOOTP vendor area is
truncated. Fixes [3f10c9b871].
Diffstat (limited to 'dhcp.c')
| -rw-r--r-- | dhcp.c | 25 |
1 files changed, 20 insertions, 5 deletions
@@ -1084,9 +1084,12 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type) *p++ = DHO_END; len = (size_t)(p - (uint8_t *)bootp); - /* Pad out to the BOOTP minimum message length. - * Some DHCP servers incorrectly require this. */ - while (len < BOOTP_MESSAGE_LENTH_MIN) { + /* Pad out to the BOOTP message length. + * Even if we send a DHCP packet with a variable length vendor area, + * some servers / relay agents don't like packets smaller than + * a BOOTP message which is fine because that's stipulated + * in RFC1542 section 2.1. */ + while (len < sizeof(*bootp)) { *p++ = DHO_PAD; len++; } @@ -3136,14 +3139,26 @@ dhcp_handlepacket(void *arg) "%s: server %s is not destination", ifp->name, inet_ntoa(from)); } - + /* + * DHCP has a variable option area rather than a fixed + * vendor area. + * Because DHCP uses the BOOTP protocol it should + * still send BOOTP sized packets to be RFC compliant. + * However some servers send a truncated vendor area. + * dhcpcd can work fine without the vendor area being sent. + */ bytes = get_udp_data(&bootp, buf); - if (bytes < sizeof(struct bootp)) { + if (bytes < offsetof(struct bootp, vend)) { logger(ifp->ctx, LOG_ERR, "%s: truncated packet (%zu) from %s", ifp->name, bytes, inet_ntoa(from)); continue; } + /* But to make our IS_DHCP macro easy, ensure the vendor + * area has at least 4 octets. */ + while (bytes < offsetof(struct bootp, vend) + 4) + bootp[bytes++] = '\0'; + dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from); if (state->raw_fd == -1) break; |
