summaryrefslogtreecommitdiff
path: root/src/libsystemd-dhcp
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-02-23 17:30:13 +0100
committerTom Gundersen <teg@jklm.no>2014-02-23 17:52:31 +0100
commit5266a81ea2b5d355916695c1ecc8c4570a54727b (patch)
treebb56e464d908c6d9d1a12824b66fa248260fd3ba /src/libsystemd-dhcp
parent3bb621e1e66b704c0c2dcef31c66f7c646dd47f6 (diff)
sd-dhcp: use FIONREAD to get correct size of incoming DHCP packet
This avoids the problem of broken DHCP servers sending us too big packets that don't fit in our buffer.
Diffstat (limited to 'src/libsystemd-dhcp')
-rw-r--r--src/libsystemd-dhcp/dhcp-packet.c2
-rw-r--r--src/libsystemd-dhcp/sd-dhcp-client.c36
2 files changed, 26 insertions, 12 deletions
diff --git a/src/libsystemd-dhcp/dhcp-packet.c b/src/libsystemd-dhcp/dhcp-packet.c
index 7c209fa658..8f9ec43c43 100644
--- a/src/libsystemd-dhcp/dhcp-packet.c
+++ b/src/libsystemd-dhcp/dhcp-packet.c
@@ -119,6 +119,8 @@ void dhcp_packet_append_ip_headers(DHCPPacket *packet, uint16_t len) {
int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len) {
size_t hdrlen;
+ assert(packet);
+
/* IP */
if (len < DHCP_IP_SIZE) {
diff --git a/src/libsystemd-dhcp/sd-dhcp-client.c b/src/libsystemd-dhcp/sd-dhcp-client.c
index 54bc19511d..63b7b24d87 100644
--- a/src/libsystemd-dhcp/sd-dhcp-client.c
+++ b/src/libsystemd-dhcp/sd-dhcp-client.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <net/ethernet.h>
#include <sys/param.h>
+#include <sys/ioctl.h>
#include "util.h"
#include "list.h"
@@ -847,16 +848,23 @@ error:
static int client_receive_message_udp(sd_event_source *s, int fd,
uint32_t revents, void *userdata) {
sd_dhcp_client *client = userdata;
- uint8_t buf[sizeof(DHCPMessage) + DHCP_MIN_OPTIONS_SIZE];
- int buflen = sizeof(buf);
- int len, r = 0;
+ _cleanup_free_ DHCPMessage *message = NULL;
+ int buflen = 0, len, r;
usec_t time_now;
assert(s);
assert(client);
assert(client->event);
- len = read(fd, &buf, buflen);
+ r = ioctl(fd, FIONREAD, &buflen);
+ if (r < 0 || buflen <= 0)
+ buflen = sizeof(DHCPMessage) + DHCP_MIN_OPTIONS_SIZE;
+
+ message = malloc0(buflen);
+ if (!message)
+ return -ENOMEM;
+
+ len = read(fd, message, buflen);
if (len < 0)
return 0;
@@ -864,29 +872,33 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
if (r < 0)
return client_stop(client, r);
- return client_handle_message(client, (DHCPMessage *) buf, len,
+ return client_handle_message(client, message, len,
time_now);
}
static int client_receive_message_raw(sd_event_source *s, int fd,
uint32_t revents, void *userdata) {
sd_dhcp_client *client = userdata;
- uint8_t buf[sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE];
- int buflen = sizeof(buf);
- int len, r = 0;
- DHCPPacket *packet;
+ _cleanup_free_ DHCPPacket *packet = NULL;
+ int buflen = 0, len, r;
usec_t time_now;
assert(s);
assert(client);
assert(client->event);
- len = read(fd, &buf, buflen);
+ r = ioctl(fd, FIONREAD, &buflen);
+ if (r < 0 || buflen <= 0)
+ buflen = sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE;
+
+ packet = malloc0(buflen);
+ if (!packet)
+ return -ENOMEM;
+
+ len = read(fd, packet, buflen);
if (len < 0)
return 0;
- packet = (DHCPPacket *) buf;
-
r = dhcp_packet_verify_headers(packet, len);
if (r < 0)
return 0;