]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Backport UDP validation from trunk
authorRoy Marples <roy@marples.name>
Sat, 28 Feb 2009 09:00:40 +0000 (09:00 +0000)
committerRoy Marples <roy@marples.name>
Sat, 28 Feb 2009 09:00:40 +0000 (09:00 +0000)
client.c
net.c
net.h

index d14bd751aa0caf7d7f369bf6576af71562d0b71a..e9645662fa926899e8248b49835f097e13f59d19 100644 (file)
--- 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 fa5af103750660ee417d988b8e946df06ab1ba56..29344f828fcb76f6adc22318c493bc1650e9c2ad 100644 (file)
--- 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 e9005d021d56f8c2116d5bec21ae86147830fa04..1447aba0beb9aff4bede3d878da8098fcd88b7ba 100644 (file)
--- 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,