sd-dhcp-client: move magic cookie into DHCPMessage struct
authorTom Gundersen <teg@jklm.no>
Sun, 6 Apr 2014 12:05:32 +0000 (14:05 +0200)
committerTom Gundersen <teg@jklm.no>
Sun, 6 Apr 2014 17:36:05 +0000 (19:36 +0200)
Also move the checking of it to the main message handler, rather than the
options parser.

Fix a bug, so we now drop the packet if any of the magic bytes don't match.
Before we used to only drop the packet if they were all wrong.

src/libsystemd-network/dhcp-option.c
src/libsystemd-network/dhcp-packet.c
src/libsystemd-network/dhcp-protocol.h
src/libsystemd-network/sd-dhcp-client.c

index 4d45b3b..1b92e86 100644 (file)
@@ -149,17 +149,13 @@ int dhcp_option_parse(DHCPMessage *message, size_t len,
         if (!message)
                 return -EINVAL;
 
-        if (len < sizeof(DHCPMessage) + 4)
+        if (len < sizeof(DHCPMessage))
                 return -EINVAL;
 
-        len -= sizeof(DHCPMessage) + 4;
+        len -= sizeof(DHCPMessage);
 
-        if (opt[0] != 0x63 && opt[1] != 0x82 && opt[2] != 0x53 &&
-                        opt[3] != 0x63)
-                return -EINVAL;
-
-        res = parse_options(&opt[4], len, &overload, &message_type,
-                        cb, user_data);
+        res = parse_options(opt, len, &overload, &message_type,
+                            cb, user_data);
         if (res < 0)
                 return res;
 
index 4f90c28..0549f57 100644 (file)
@@ -43,23 +43,13 @@ int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
 
         assert(op == BOOTREQUEST || op == BOOTREPLY);
 
-        *opt = (uint8_t *)(message + 1);
-
-        if (*optlen < 4)
-                return -ENOBUFS;
-        *optlen -= 4;
-
         message->op = op;
         message->htype = ARPHRD_ETHER;
         message->hlen = ETHER_ADDR_LEN;
         message->xid = htobe32(xid);
+        message->magic = htobe32(DHCP_MAGIC_COOKIE);
 
-        (*opt)[0] = 0x63;
-        (*opt)[1] = 0x82;
-        (*opt)[2] = 0x53;
-        (*opt)[3] = 0x63;
-
-        *opt += 4;
+        *opt = (uint8_t *)(message + 1);
 
         err = dhcp_option_append(opt, optlen, DHCP_OPTION_MESSAGE_TYPE, 1,
                                  &type);
index 9aa9618..400e953 100644 (file)
@@ -43,6 +43,7 @@ struct DHCPMessage {
         uint8_t chaddr[16];
         uint8_t sname[64];
         uint8_t file[128];
+        be32_t magic;
 } _packed_;
 
 typedef struct DHCPMessage DHCPMessage;
@@ -58,7 +59,8 @@ typedef struct DHCPPacket DHCPPacket;
 #define DHCP_IP_SIZE            (int32_t)(sizeof(struct iphdr))
 #define DHCP_IP_UDP_SIZE        (int32_t)(sizeof(struct udphdr) + DHCP_IP_SIZE)
 #define DHCP_MESSAGE_SIZE       (int32_t)(sizeof(DHCPMessage))
-#define DHCP_MIN_OPTIONS_SIZE   312
+#define DHCP_MIN_OPTIONS_SIZE   308
+#define DHCP_MAGIC_COOKIE       (uint32_t)(0x63825363)
 
 enum {
         DHCP_PORT_SERVER                        = 67,
index 06b2d1c..5824e6e 100644 (file)
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <net/ethernet.h>
+#include <net/if_arp.h>
 #include <sys/param.h>
 #include <sys/ioctl.h>
 
@@ -936,6 +937,11 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                 return 0;
         }
 
+        if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
+                log_dhcp_client(client, "not a DHCP message: ignoring");
+                return 0;
+        }
+
         if (message->op != BOOTREPLY) {
                 log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
                 return 0;
@@ -948,6 +954,11 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                 return 0;
         }
 
+        if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
+                log_dhcp_client(client, "not an ethernet packet");
+                return 0;
+        }
+
         if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
                    ETH_ALEN)) {
                 log_dhcp_client(client, "received chaddr does not match "