summaryrefslogtreecommitdiffhomepage
path: root/src/dhcpv4.c
diff options
context:
space:
mode:
authorHans Dedecker <dedeckeh@gmail.com>2019-04-26 14:15:55 +0200
committerHans Dedecker <dedeckeh@gmail.com>2019-04-26 14:23:50 +0200
commit09e5eca32c1872c1676c25dfd3f240b10bc85d55 (patch)
tree23a5b9cdd19e8cfa71e13f47e695add0a5ec4356 /src/dhcpv4.c
parent3cd48765b74e498f06397f4b90b64cafe3a82dd1 (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/dhcpv4.c')
-rw-r--r--src/dhcpv4.c18
1 files changed, 13 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),