systemd/0580-sd-dhcp-client-support...

637 lines
30 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 76253e73f9c9c24fec755e485516f3b55d0707b4 Mon Sep 17 00:00:00 2001
From: Dan Williams <dcbw@redhat.com>
Date: Wed, 8 Oct 2014 14:15:45 -0500
Subject: [PATCH] sd-dhcp-client: support non-Ethernet hardware addresses
Like Infiniband. See RFC 4390 section 2.1 for details on DHCP
and Infiniband; chaddr is zeroed, hlen is set to 0, and htype
is set to ARPHRD_INFINIBAND because IB hardware addresses
are 20 bytes in length.
---
src/libsystemd-network/dhcp-internal.h | 10 ++--
src/libsystemd-network/dhcp-network.c | 54 ++++++++++++++++++----
src/libsystemd-network/dhcp-packet.c | 8 ++--
src/libsystemd-network/sd-dhcp-client.c | 74 +++++++++++++++++++++++-------
src/libsystemd-network/sd-dhcp-server.c | 8 ++--
src/libsystemd-network/sd-dhcp6-client.c | 36 +++++++++++----
src/libsystemd-network/test-dhcp-client.c | 14 ++++--
src/libsystemd-network/test-dhcp-option.c | 2 +-
src/libsystemd-network/test-dhcp6-client.c | 8 +++-
src/network/networkd-dhcp4.c | 4 +-
src/network/networkd-link.c | 12 +++--
src/systemd/sd-dhcp-client.h | 4 +-
src/systemd/sd-dhcp6-client.h | 4 +-
13 files changed, 179 insertions(+), 59 deletions(-)
diff --git a/src/libsystemd-network/dhcp-internal.h b/src/libsystemd-network/dhcp-internal.h
index 1069c8a03b..d358a49307 100644
--- a/src/libsystemd-network/dhcp-internal.h
+++ b/src/libsystemd-network/dhcp-internal.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <linux/if_packet.h>
+#include <net/if_arp.h>
#include <net/ethernet.h>
#include "socket-util.h"
@@ -31,7 +32,9 @@
#include "sd-dhcp-client.h"
#include "dhcp-protocol.h"
-int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link, uint32_t xid, struct ether_addr mac_addr);
+int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
+ uint32_t xid, const uint8_t *mac_addr,
+ size_t mac_addr_len, uint16_t arp_type);
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);
@@ -47,8 +50,9 @@ typedef int (*dhcp_option_cb_t)(uint8_t code, uint8_t len,
int dhcp_option_parse(DHCPMessage *message, size_t len,
dhcp_option_cb_t cb, void *user_data);
-int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid, uint8_t type,
- size_t optlen, size_t *optoffset);
+int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
+ uint8_t type, uint16_t arp_type, size_t optlen,
+ size_t *optoffset);
uint16_t dhcp_packet_checksum(uint8_t *buf, size_t len);
diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 1ced5cf292..29e9993f66 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -22,6 +22,7 @@
#include <sys/socket.h>
#include <string.h>
#include <linux/if_packet.h>
+#include <linux/if_infiniband.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
#include <stdio.h>
@@ -32,9 +33,12 @@
#include "dhcp-internal.h"
-int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
- uint32_t xid, struct ether_addr mac_addr) {
-
+static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
+ uint32_t xid, const uint8_t *mac_addr,
+ size_t mac_addr_len,
+ const uint8_t *bcast_addr,
+ const struct ether_addr *eth_mac,
+ uint16_t arp_type, uint8_t dhcp_hlen) {
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 ? */
@@ -57,21 +61,21 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), /* op == BOOTREPLY ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.htype)), /* A <- DHCP header type */
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0), /* header type == ARPHRD_ETHER ? */
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, arp_type, 1, 0), /* header type == arp_type ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(DHCPPacket, dhcp.hlen)), /* A <- mac address length */
- BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHER_ADDR_LEN, 1, 0), /* address length == ETHER_ADDR_LEN ? */
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, dhcp_hlen, 1, 0), /* address length == dhcp_hlen ? */
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
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 */
- BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) &mac_addr))), /* A <- 4 bytes of client's MAC */
+ BPF_STMT(BPF_LD + BPF_IMM, htobe32(*((unsigned int *) eth_mac))), /* 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_LD + BPF_IMM, htobe16(*((unsigned short *) (((char *) eth_mac) + 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 */
@@ -107,8 +111,9 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
link->ll.sll_family = AF_PACKET;
link->ll.sll_protocol = htons(ETH_P_IP);
link->ll.sll_ifindex = ifindex;
- link->ll.sll_halen = ETH_ALEN;
- memset(link->ll.sll_addr, 0xff, ETH_ALEN);
+ link->ll.sll_hatype = htons(arp_type);
+ link->ll.sll_halen = mac_addr_len;
+ memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
r = bind(s, &link->sa, sizeof(link->ll));
if (r < 0)
@@ -120,6 +125,37 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
return r;
}
+int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link,
+ uint32_t xid, const uint8_t *mac_addr,
+ size_t mac_addr_len, uint16_t arp_type) {
+ static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+ /* Default broadcast address for IPoIB */
+ static const uint8_t ib_bcast[] = {
+ 0x00, 0xff, 0xff, 0xff, 0xff, 0x12, 0x40, 0x1b,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff
+ };
+ struct ether_addr eth_mac = { { 0, 0, 0, 0, 0, 0 } };
+ const uint8_t *bcast_addr = NULL;
+ uint8_t dhcp_hlen = 0;
+
+ assert_return(mac_addr_len > 0, -EINVAL);
+
+ if (arp_type == ARPHRD_ETHER) {
+ assert_return(mac_addr_len == ETH_ALEN, -EINVAL);
+ memcpy(&eth_mac, mac_addr, ETH_ALEN);
+ bcast_addr = eth_bcast;
+ dhcp_hlen = ETH_ALEN;
+ } else if (arp_type == ARPHRD_INFINIBAND) {
+ assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL);
+ bcast_addr = ib_bcast;
+ } else
+ return -EINVAL;
+
+ return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len,
+ bcast_addr, &eth_mac, arp_type, dhcp_hlen);
+}
+
int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
union sockaddr_union src = {
.in.sin_family = AF_INET,
diff --git a/src/libsystemd-network/dhcp-packet.c b/src/libsystemd-network/dhcp-packet.c
index 9f850fdebb..7581daeeeb 100644
--- a/src/libsystemd-network/dhcp-packet.c
+++ b/src/libsystemd-network/dhcp-packet.c
@@ -38,15 +38,17 @@
#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
int dhcp_message_init(DHCPMessage *message, uint8_t op, uint32_t xid,
- uint8_t type, size_t optlen, size_t *optoffset) {
+ uint8_t type, uint16_t arp_type, size_t optlen,
+ size_t *optoffset) {
size_t offset = 0;
int r;
assert(op == BOOTREQUEST || op == BOOTREPLY);
+ assert(arp_type == ARPHRD_ETHER || arp_type == ARPHRD_INFINIBAND);
message->op = op;
- message->htype = ARPHRD_ETHER;
- message->hlen = ETHER_ADDR_LEN;
+ message->htype = arp_type;
+ message->hlen = (arp_type == ARPHRD_ETHER) ? ETHER_ADDR_LEN : 0;
message->xid = htobe32(xid);
message->magic = htobe32(DHCP_MAGIC_COOKIE);
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 2f94c16078..0eba4c379d 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <net/ethernet.h>
#include <net/if_arp.h>
+#include <linux/if_infiniband.h>
#include <netinet/ether.h>
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -37,6 +38,8 @@
#include "dhcp-lease-internal.h"
#include "sd-dhcp-client.h"
+#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+
struct sd_dhcp_client {
RefCount n_ref;
@@ -57,6 +60,9 @@ struct sd_dhcp_client {
uint8_t type;
struct ether_addr mac_addr;
} _packed_ client_id;
+ uint8_t mac_addr[MAX_MAC_ADDR_LEN];
+ size_t mac_addr_len;
+ uint16_t arp_type;
char *hostname;
char *vendor_class_identifier;
uint32_t mtu;
@@ -163,15 +169,25 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index) {
return 0;
}
-int sd_dhcp_client_set_mac(sd_dhcp_client *client,
- const struct ether_addr *addr) {
+int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type) {
DHCP_CLIENT_DONT_DESTROY(client);
bool need_restart = false;
assert_return(client, -EINVAL);
assert_return(addr, -EINVAL);
+ assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
+ assert_return(arp_type > 0, -EINVAL);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
+ else
+ return -EINVAL;
- if (memcmp(&client->client_id.mac_addr, addr, ETH_ALEN) == 0)
+ if (client->mac_addr_len == addr_len &&
+ memcmp(&client->mac_addr, addr, addr_len) == 0)
return 0;
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
@@ -181,6 +197,10 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client,
client_stop(client, DHCP_EVENT_STOP);
}
+ memcpy(&client->mac_addr, addr, addr_len);
+ client->mac_addr_len = addr_len;
+ client->arp_type = arp_type;
+
memcpy(&client->client_id.mac_addr, addr, ETH_ALEN);
client->client_id.type = 0x01;
@@ -318,7 +338,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
return -ENOMEM;
r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
- optlen, &optoffset);
+ client->arp_type, optlen, &optoffset);
if (r < 0)
return r;
@@ -337,14 +357,17 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
Note: some interfaces needs this to be enabled, but some networks
needs this to be disabled as broadcasts are filteretd, so this
needs to be configurable */
- if (client->request_broadcast)
+ if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
packet->dhcp.flags = htobe16(0x8000);
/* RFC2132 section 4.1.1:
The client MUST include its hardware address in the chaddr field, if
- necessary for delivery of DHCP reply messages.
+ necessary for delivery of DHCP reply messages. Non-Ethernet
+ interfaces will leave 'chaddr' empty and use the client identifier
+ instead (eg, RFC 4390 section 2.1).
*/
- memcpy(&packet->dhcp.chaddr, &client->client_id.mac_addr, ETH_ALEN);
+ if (client->arp_type == ARPHRD_ETHER)
+ memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
Identifier option is not set */
@@ -843,7 +866,9 @@ static int client_start(sd_dhcp_client *client) {
client->xid = random_u32();
- r = dhcp_network_bind_raw_socket(client->index, &client->link, client->xid, client->client_id.mac_addr);
+ r = dhcp_network_bind_raw_socket(client->index, &client->link,
+ client->xid, client->mac_addr,
+ client->mac_addr_len, client->arp_type);
if (r < 0) {
client_stop(client, r);
return r;
@@ -887,7 +912,9 @@ 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, client->client_id.mac_addr);
+ r = dhcp_network_bind_raw_socket(client->index, &client->link,
+ client->xid, client->mac_addr,
+ client->mac_addr_len, client->arp_type);
if (r < 0) {
client_stop(client, r);
return 0;
@@ -1331,6 +1358,9 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPMessage *message = NULL;
int buflen = 0, len, r;
+ const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
+ const struct ether_addr *expected_chaddr = NULL;
+ uint8_t expected_hlen = 0;
assert(s);
assert(client);
@@ -1367,13 +1397,26 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
return 0;
}
- if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
- log_dhcp_client(client, "not an ethernet packet");
+ if (message->htype != client->arp_type) {
+ log_dhcp_client(client, "packet type does not match client type");
+ return 0;
+ }
+
+ if (client->arp_type == ARPHRD_ETHER) {
+ expected_hlen = ETH_ALEN;
+ expected_chaddr = (const struct ether_addr *) &client->mac_addr;
+ } else {
+ /* Non-ethernet links expect zero chaddr */
+ expected_hlen = 0;
+ expected_chaddr = &zero_mac;
+ }
+
+ if (message->hlen != expected_hlen) {
+ log_dhcp_client(client, "unexpected packet hlen %d", message->hlen);
return 0;
}
- if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
- ETH_ALEN)) {
+ if (memcmp(&message->chaddr[0], expected_chaddr, ETH_ALEN)) {
log_dhcp_client(client, "received chaddr does not match "
"expected: ignoring");
return 0;
@@ -1455,7 +1498,6 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
}
int sd_dhcp_client_start(sd_dhcp_client *client) {
- char buffer[ETHER_ADDR_TO_STRING_MAX];
int r;
assert_return(client, -EINVAL);
@@ -1469,9 +1511,7 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
r = client_start(client);
if (r >= 0)
- log_dhcp_client(client, "STARTED on ifindex %u with address %s",
- client->index,
- ether_addr_to_string(&client->client_id.mac_addr, buffer));
+ log_dhcp_client(client, "STARTED on ifindex %u", client->index);
return r;
}
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index a6d6178e72..24fedd2375 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -392,8 +392,8 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
return -ENOMEM;
r = dhcp_message_init(&packet->dhcp, BOOTREPLY,
- be32toh(req->message->xid), type, req->max_optlen,
- &optoffset);
+ be32toh(req->message->xid), type, ARPHRD_ETHER,
+ req->max_optlen, &optoffset);
if (r < 0)
return r;
@@ -513,8 +513,8 @@ static int server_send_forcerenew(sd_dhcp_server *server, be32_t address,
return -ENOMEM;
r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
- DHCP_FORCERENEW, DHCP_MIN_OPTIONS_SIZE,
- &optoffset);
+ DHCP_FORCERENEW, ARPHRD_ETHER,
+ DHCP_MIN_OPTIONS_SIZE, &optoffset);
if (r < 0)
return r;
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 6ea68c915f..fa4f9b5dc2 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -22,6 +22,7 @@
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <linux/if_infiniband.h>
#include "udev.h"
#include "udev-util.h"
@@ -44,6 +45,8 @@
*/
#define MAX_DUID_LEN 128
+#define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
+
struct sd_dhcp6_client {
RefCount n_ref;
@@ -51,7 +54,9 @@ struct sd_dhcp6_client {
sd_event *event;
int event_priority;
int index;
- struct ether_addr mac_addr;
+ uint8_t mac_addr[MAX_MAC_ADDR_LEN];
+ size_t mac_addr_len;
+ uint16_t arp_type;
DHCP6IA ia_na;
be32_t transaction_id;
usec_t transaction_start;
@@ -160,15 +165,28 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index)
return 0;
}
-int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
- const struct ether_addr *mac_addr)
+int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type)
{
assert_return(client, -EINVAL);
-
- if (mac_addr)
- memcpy(&client->mac_addr, mac_addr, sizeof(client->mac_addr));
+ assert_return(addr, -EINVAL);
+ assert_return(addr_len > 0 && addr_len <= MAX_MAC_ADDR_LEN, -EINVAL);
+ assert_return(arp_type > 0, -EINVAL);
+
+ if (arp_type == ARPHRD_ETHER)
+ assert_return(addr_len == ETH_ALEN, -EINVAL);
+ else if (arp_type == ARPHRD_INFINIBAND)
+ assert_return(addr_len == INFINIBAND_ALEN, -EINVAL);
else
- memset(&client->mac_addr, 0x00, sizeof(client->mac_addr));
+ return -EINVAL;
+
+ if (client->mac_addr_len == addr_len &&
+ memcmp(&client->mac_addr, addr, addr_len) == 0)
+ return 0;
+
+ memcpy(&client->mac_addr, addr, addr_len);
+ client->mac_addr_len = addr_len;
+ client->arp_type = arp_type;
return 0;
}
@@ -646,8 +664,8 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
siphash24((uint8_t*)&id, name, strlen(name), HASH_KEY.bytes);
else
/* fall back to mac address if no predictable name available */
- siphash24((uint8_t*)&id, &client->mac_addr, ETH_ALEN,
- HASH_KEY.bytes);
+ siphash24((uint8_t*)&id, &client->mac_addr,
+ client->mac_addr_len, HASH_KEY.bytes);
/* fold into 32 bits */
client->ia_na.id = (id & 0xffffffff) ^ (id >> 32);
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index c48aa04b8d..7dab97de2f 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -196,7 +196,9 @@ 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, struct ether_addr mac)
+int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link,
+ uint32_t id, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type)
{
if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
return -errno;
@@ -244,7 +246,10 @@ static void test_discover_message(sd_event *e)
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
- assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
+ assert_se(sd_dhcp_client_set_mac(client,
+ (const uint8_t *) &mac_addr,
+ sizeof (mac_addr),
+ ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
@@ -462,7 +467,10 @@ static void test_addr_acq(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
- assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
+ assert_se(sd_dhcp_client_set_mac(client,
+ (const uint8_t *) &mac_addr,
+ sizeof (mac_addr),
+ ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
>= 0);
diff --git a/src/libsystemd-network/test-dhcp-option.c b/src/libsystemd-network/test-dhcp-option.c
index 63cdc7aa06..eac3844f96 100644
--- a/src/libsystemd-network/test-dhcp-option.c
+++ b/src/libsystemd-network/test-dhcp-option.c
@@ -92,7 +92,7 @@ static void test_message_init(void)
message = malloc0(len);
assert_se(dhcp_message_init(message, BOOTREQUEST, 0x12345678,
- DHCP_DISCOVER, optlen, &optoffset) >= 0);
+ DHCP_DISCOVER, ARPHRD_ETHER, optlen, &optoffset) >= 0);
assert_se(message->xid == htobe32(0x12345678));
assert_se(message->op == BOOTREQUEST);
diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c
index 37ddfc2cfa..26b28a20e8 100644
--- a/src/libsystemd-network/test-dhcp6-client.c
+++ b/src/libsystemd-network/test-dhcp6-client.c
@@ -66,7 +66,9 @@ static int test_client_basic(sd_event *e) {
assert_se(sd_dhcp6_client_set_index(client, -1) == 0);
assert_se(sd_dhcp6_client_set_index(client, 42) >= 0);
- assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
+ assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
+ sizeof (mac_addr),
+ ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_CLIENTID) == -EINVAL);
assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
@@ -572,7 +574,9 @@ static int test_client_solicit(sd_event *e) {
assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
- assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
+ assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
+ sizeof (mac_addr),
+ ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp6_client_set_callback(client,
test_client_solicit_cb, e) >= 0);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index e451af8643..63bfa86f99 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -599,7 +599,9 @@ int dhcp4_configure(Link *link) {
if (r < 0)
return r;
- r = sd_dhcp_client_set_mac(link->dhcp_client, &link->mac);
+ r = sd_dhcp_client_set_mac(link->dhcp_client,
+ (const uint8_t *) &link->mac,
+ sizeof (link->mac), ARPHRD_ETHER);
if (r < 0)
return r;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index dcbe38a90a..c6e173fbc6 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -909,7 +909,9 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
return;
}
- r = sd_dhcp6_client_set_mac(link->dhcp6_client, &link->mac);
+ r = sd_dhcp6_client_set_mac(link->dhcp6_client,
+ (const uint8_t *) &link->mac,
+ sizeof (link->mac), ARPHRD_ETHER);
if (r < 0) {
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
return;
@@ -1647,7 +1649,9 @@ int link_update(Link *link, sd_rtnl_message *m) {
if (link->dhcp_client) {
r = sd_dhcp_client_set_mac(link->dhcp_client,
- &link->mac);
+ (const uint8_t *) &link->mac,
+ sizeof (link->mac),
+ ARPHRD_ETHER);
if (r < 0) {
log_warning_link(link,
"Could not update MAC address in DHCP client: %s",
@@ -1658,7 +1662,9 @@ int link_update(Link *link, sd_rtnl_message *m) {
if (link->dhcp6_client) {
r = sd_dhcp6_client_set_mac(link->dhcp6_client,
- &link->mac);
+ (const uint8_t *) &link->mac,
+ sizeof (link->mac),
+ ARPHRD_ETHER);
if (r < 0) {
log_warning_link(link,
"Could not update MAC address in DHCPv6 client: %s",
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 98c67829b7..7416f82193 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -49,8 +49,8 @@ int sd_dhcp_client_set_request_address(sd_dhcp_client *client,
const struct in_addr *last_address);
int sd_dhcp_client_set_request_broadcast(sd_dhcp_client *client, int broadcast);
int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index);
-int sd_dhcp_client_set_mac(sd_dhcp_client *client,
- const struct ether_addr *addr);
+int sd_dhcp_client_set_mac(sd_dhcp_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type);
int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu);
int sd_dhcp_client_set_hostname(sd_dhcp_client *client, const char *hostname);
int sd_dhcp_client_set_vendor_class_identifier(sd_dhcp_client *client, const char *vci);
diff --git a/src/systemd/sd-dhcp6-client.h b/src/systemd/sd-dhcp6-client.h
index a4409e8d4e..c7f168fe21 100644
--- a/src/systemd/sd-dhcp6-client.h
+++ b/src/systemd/sd-dhcp6-client.h
@@ -43,8 +43,8 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
sd_dhcp6_client_cb_t cb, void *userdata);
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
-int sd_dhcp6_client_set_mac(sd_dhcp6_client *client,
- const struct ether_addr *mac_addr);
+int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
+ size_t addr_len, uint16_t arp_type);
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
size_t duid_len);
int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client,