[systemd-commits] src/libsystemd-network

Michal Sekletar msekleta at kemper.freedesktop.org
Mon Jul 7 03:57:13 PDT 2014


 src/libsystemd-network/dhcp-internal.h    |    3 ++-
 src/libsystemd-network/dhcp-network.c     |   15 +++++++++++++--
 src/libsystemd-network/sd-dhcp-client.c   |    4 ++--
 src/libsystemd-network/test-dhcp-client.c |    2 +-
 4 files changed, 18 insertions(+), 6 deletions(-)

New commits:
commit 58587a7a0c3bf5595190486781d3bbc00654c6ef
Author: Michal Sekletar <msekleta at redhat.com>
Date:   Thu Jun 19 15:14:14 2014 +0200

    dhcp-network: add check for DHCP.chaddr
    
    Check that received DHCP packets actually include our MAC address in
    chaddr field. BPF interpreter has 32 bit wide registers but MAC address
    is 48 bits long so we have to do check in two steps.

diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index 6f6f121..1069c8a 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -24,13 +24,14 @@
 
 #include <stdint.h>
 #include <linux/if_packet.h>
+#include <net/ethernet.h>
 
 #include "socket-util.h"
 
 #include "sd-dhcp-client.h"
 #include "dhcp-protocol.h"
 
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t xid);
+int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t xid, struct ether_addr mac_addr);
 int dhcp_network_bind_udp_socket(be32_t address, uint16_t port);
 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
                                  const void *packet, size_t len);
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 9d57917..f119cae 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -33,7 +33,7 @@
 #include "dhcp-internal.h"
 
 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
-                                 uint32_t xid) {
+                                 uint32_t xid, struct ether_addr mac_addr) {
         struct sock_filter filter[] = {
             BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0),                                 /* A <- packet length */
             BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(DHCPPacket), 1, 0),         /* packet >= DHCPPacket ? */
@@ -60,7 +60,18 @@ int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
             BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.xid)),    /* A <- client identifier */
             BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, xid, 1, 0),                        /* client identifier == xid ? */
             BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
-            /* TODO: match chaddr */
+            BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) &mac_addr))),                    /* A <- 4 bytes of client's MAC */
+            BPF_STMT(BPF_MISC + BPF_TAX, 0),                                                       /* X <- A */
+            BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)),                 /* A <- 4 bytes of MAC from dhcp.chaddr */
+            BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),                                                /* A xor X */
+            BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                                          /* A == 0 ? */
+            BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
+            BPF_STMT(BPF_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) &mac_addr) + 4)))), /* A <- remainder of client's MAC */
+            BPF_STMT(BPF_MISC + BPF_TAX, 0),                                                       /* X <- A */
+            BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4),             /* A <- remainder of MAC from dhcp.chaddr */
+            BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0),                                                /* A xor X */
+            BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0),                                          /* A == 0 ? */
+            BPF_STMT(BPF_RET + BPF_K, 0),                                                          /* ignore */
             BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)),  /* A <- DHCP magic cookie */
             BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0),          /* cookie == DHCP magic cookie ? */
             BPF_STMT(BPF_RET + BPF_K, 0),                                          /* ignore */
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index d8a9d20..6b19666 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -751,7 +751,7 @@ static int client_start(sd_dhcp_client *client) {
 
         client->xid = random_u32();
 
-        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
+        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
         if (r < 0) {
                 client_stop(client, r);
                 return r;
@@ -795,7 +795,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
         client->state = DHCP_STATE_REBINDING;
         client->attempt = 1;
 
-        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid);
+        r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
         if (r < 0) {
                 client_stop(client, r);
                 return 0;
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 450b6d4..7cbe10d 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -196,7 +196,7 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
         return 575;
 }
 
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t id)
+int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t id, struct ether_addr mac)
 {
         if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
                 return -errno;



More information about the systemd-commits mailing list