summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Gundersen <teg@jklm.no>2014-04-06 14:05:32 +0200
committerTom Gundersen <teg@jklm.no>2014-04-06 19:36:05 +0200
commit3b7ca119fdc501e21f017695dc9b6f82fdbd1d93 (patch)
treeefefc912fa1925f1197dd0e5b56a14ad2282de38
parent19aa72f74e41045510b4af3f1415b419d42ff20b (diff)
sd-dhcp-client: move magic cookie into DHCPMessage struct
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.
-rw-r--r--src/libsystemd-network/dhcp-option.c12
-rw-r--r--src/libsystemd-network/dhcp-packet.c14
-rw-r--r--src/libsystemd-network/dhcp-protocol.h4
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c11
4 files changed, 20 insertions, 21 deletions
diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c
index 4d45b3b3a4..1b92e8616b 100644
--- a/src/libsystemd-network/dhcp-option.c
+++ b/src/libsystemd-network/dhcp-option.c
@@ -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;
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 4f90c283a2..0549f575ac 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -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);
diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 9aa9618b44..400e953f41 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -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,
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 06b2d1c60d..5824e6ee91 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -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 "