diff options
author | Hans Dedecker <dedeckeh@gmail.com> | 2019-04-26 14:15:55 +0200 |
---|---|---|
committer | Hans Dedecker <dedeckeh@gmail.com> | 2019-04-26 14:23:50 +0200 |
commit | 09e5eca32c1872c1676c25dfd3f240b10bc85d55 (patch) | |
tree | 23a5b9cdd19e8cfa71e13f47e695add0a5ec4356 /src | |
parent | 3cd48765b74e498f06397f4b90b64cafe3a82dd1 (diff) |
dhcpv4: fix DHCP packet size
Calculate the DHCP packet size based on the number of DHCP options in the
message. Make sure the DHCP packet size does not go lower than 300 bytes
as some clients ignore DHCP messages smaller than 300 bytes.
Based on a patch by Dainis Jonitis <dainis.jonitis@ubnt.com>
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/dhcpv4.c | 18 | ||||
-rw-r--r-- | src/dhcpv4.h | 3 |
2 files changed, 16 insertions, 5 deletions
diff --git a/src/dhcpv4.c b/src/dhcpv4.c index 7058b83..3fb5988 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -35,6 +35,9 @@ #include "dhcpv4.h" #include "dhcpv6.h" +#define PACKET_SIZE(start, end) (((uint8_t *)end - (uint8_t *)start) < DHCPV4_MIN_PACKET_SIZE ? \ + DHCPV4_MIN_PACKET_SIZE : (uint8_t *)end - (uint8_t *)start) + static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info); static int setup_dhcpv4_addresses(struct interface *iface); static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr); @@ -429,15 +432,20 @@ static void dhcpv4_put(struct dhcpv4_message *msg, uint8_t **cookie, { uint8_t *c = *cookie; uint8_t *end = (uint8_t *)msg + sizeof(*msg); + bool tag_only = type == DHCPV4_OPT_PAD || type == DHCPV4_OPT_END; + int total_len = tag_only ? 1 : 2 + len; - if (*cookie + 2 + len > end) + if (*cookie + total_len > end) return; + *cookie += total_len; *c++ = type; + + if (tag_only) + return; + *c++ = len; memcpy(c, data, len); - - *cookie = c + len; } static void dhcpv4_fr_send(struct dhcp_assignment *a) @@ -518,7 +526,7 @@ static void dhcpv4_fr_send(struct dhcp_assignment *a) dest.sin_port = htons(DHCPV4_CLIENT_PORT); dest.sin_addr.s_addr = a->addr; - if (sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, sizeof(fr_msg), + if (sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, PACKET_SIZE(&fr_msg, cookie), MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0) syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(msg), odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr)); @@ -861,7 +869,7 @@ static void handle_dhcpv4(void *addr, void *data, size_t len, syslog(LOG_ERR, "ioctl(SIOCSARP): %m"); } - if (sendto(sock, &reply, sizeof(reply), MSG_DONTWAIT, + if (sendto(sock, &reply, PACKET_SIZE(&reply, cookie), MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0) syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(msg), diff --git a/src/dhcpv4.h b/src/dhcpv4.h index 96bd068..505346f 100644 --- a/src/dhcpv4.h +++ b/src/dhcpv4.h @@ -19,6 +19,8 @@ #define DHCPV4_FLAG_BROADCAST 0x8000 +#define DHCPV4_MIN_PACKET_SIZE 300 + enum dhcpv4_op { DHCPV4_BOOTREQUEST = 1, DHCPV4_BOOTREPLY = 2 @@ -37,6 +39,7 @@ enum dhcpv4_msg { }; enum dhcpv4_opt { + DHCPV4_OPT_PAD = 0, DHCPV4_OPT_NETMASK = 1, DHCPV4_OPT_ROUTER = 3, DHCPV4_OPT_DNSSERVER = 6, |