summaryrefslogtreecommitdiffhomepage
path: root/src
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
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')
-rw-r--r--src/dhcpv4.c18
-rw-r--r--src/dhcpv4.h3
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,