summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r--src/libsystemd-network/dhcp-internal.h3
-rw-r--r--src/libsystemd-network/dhcp-network.c15
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c4
-rw-r--r--src/libsystemd-network/test-dhcp-client.c2
4 files changed, 18 insertions, 6 deletions
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index 6f6f1218d9..1069c8a03b 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 9d579177a4..f119cae7ff 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 d8a9d20e4c..6b19666c3b 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 450b6d4d3c..7cbe10d5a7 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;