summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2009-02-28 09:00:40 +0000
committerRoy Marples <roy@marples.name>2009-02-28 09:00:40 +0000
commit8df4b32f928dc8ce7c091645987089700f6e5d61 (patch)
tree671ae834f387d681455c9980130909d74b6459e7
parent8e344c5022f73bbe43fa0c4480b8f2e468646b0d (diff)
downloaddhcpcd-8df4b32f928dc8ce7c091645987089700f6e5d61.tar.xz
Backport UDP validation from trunk
-rw-r--r--client.c2
-rw-r--r--net.c50
-rw-r--r--net.h2
3 files changed, 26 insertions, 28 deletions
diff --git a/client.c b/client.c
index d14bd751..e9645662 100644
--- a/client.c
+++ b/client.c
@@ -1548,7 +1548,7 @@ handle_dhcp_packet(struct if_state *state, const struct options *options)
}
if (bytes == -1)
break;
- if (valid_udp_packet(packet) == -1)
+ if (valid_udp_packet(packet, bytes) == -1)
continue;
bytes = get_udp_data(&pp, packet);
if ((size_t)bytes > sizeof(*dhcp)) {
diff --git a/net.c b/net.c
index fa5af103..29344f82 100644
--- a/net.c
+++ b/net.c
@@ -634,44 +634,42 @@ get_udp_data(const uint8_t **data, const uint8_t *udp)
}
int
-valid_udp_packet(const uint8_t *data)
+valid_udp_packet(const uint8_t *data, size_t data_len)
{
struct udp_dhcp_packet packet;
- uint16_t bytes;
- uint16_t ipsum;
- uint16_t iplen;
- uint16_t udpsum;
- struct in_addr source;
- struct in_addr dest;
- int retval = 0;
-
- memcpy(&packet, data, sizeof(packet));
- bytes = ntohs(packet.ip.ip_len);
- ipsum = packet.ip.ip_sum;
- iplen = packet.ip.ip_len;
- udpsum = packet.udp.uh_sum;
+ uint16_t bytes, udpsum;
- if (0 != checksum(&packet.ip, sizeof(packet.ip))) {
+ if (data_len > sizeof(packet)) {
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy(&packet, data, data_len);
+ if (checksum(&packet.ip, sizeof(packet.ip)) != 0) {
errno = EINVAL;
return -1;
}
- packet.ip.ip_sum = 0;
- memcpy(&source, &packet.ip.ip_src, sizeof(packet.ip.ip_src));
- memcpy(&dest, &packet.ip.ip_dst, sizeof(packet.ip.ip_dst));
- memset(&packet.ip, 0, sizeof(packet.ip));
+ bytes = ntohs(packet.ip.ip_len);
+ if (data_len < bytes) {
+ errno = EINVAL;
+ return -1;
+ }
+ udpsum = packet.udp.uh_sum;
packet.udp.uh_sum = 0;
-
- packet.ip.ip_p = IPPROTO_UDP;
- memcpy(&packet.ip.ip_src, &source, sizeof(packet.ip.ip_src));
- memcpy(&packet.ip.ip_dst, &dest, sizeof(packet.ip.ip_dst));
+ packet.ip.ip_hl = 0;
+ packet.ip.ip_v = 0;
+ packet.ip.ip_tos = 0;
packet.ip.ip_len = packet.udp.uh_ulen;
- if (udpsum && udpsum != checksum(&packet, bytes)) {
+ packet.ip.ip_id = 0;
+ packet.ip.ip_off = 0;
+ packet.ip.ip_ttl = 0;
+ packet.ip.ip_sum = 0;
+ if (udpsum && checksum(&packet, bytes) != udpsum) {
errno = EINVAL;
- retval = -1;
+ return -1;
}
- return retval;
+ return 0;
}
int
diff --git a/net.h b/net.h
index e9005d02..1447aba0 100644
--- a/net.h
+++ b/net.h
@@ -160,7 +160,7 @@ const size_t udp_dhcp_len;
ssize_t make_udp_packet(uint8_t **, const uint8_t *, size_t,
struct in_addr, struct in_addr);
ssize_t get_udp_data(const uint8_t **, const uint8_t *);
-int valid_udp_packet(const uint8_t *);
+int valid_udp_packet(const uint8_t *, size_t);
int open_socket(struct interface *, int);
ssize_t send_packet(const struct interface *, struct in_addr,