diff options
author | Tom Gundersen <teg@jklm.no> | 2014-04-06 14:05:32 +0200 |
---|---|---|
committer | Tom Gundersen <teg@jklm.no> | 2014-04-06 19:36:05 +0200 |
commit | 3b7ca119fdc501e21f017695dc9b6f82fdbd1d93 (patch) | |
tree | efefc912fa1925f1197dd0e5b56a14ad2282de38 | |
parent | 19aa72f74e41045510b4af3f1415b419d42ff20b (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.c | 12 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp-packet.c | 14 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp-protocol.h | 4 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 11 |
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 " |