Merge pull request #17444 from BtbN/fix_ib_dhcp4

networkd: fix DHCP on InfiniBand interfaces
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-10-29 19:27:29 +01:00 committed by GitHub
commit 58f848148f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 218 additions and 80 deletions

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <errno.h>
#include <inttypes.h>
#include <net/ethernet.h>
#include <stdio.h>
#include <sys/types.h>
@ -9,6 +10,20 @@
#include "macro.h"
#include "string-util.h"
char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);
assert(addr->length <= HW_ADDR_MAX_SIZE);
for (size_t i = 0; i < addr->length; i++) {
sprintf(&buffer[3*i], "%02"PRIx8, addr->addr.bytes[i]);
if (i < addr->length - 1)
buffer[3*i + 2] = ':';
}
return buffer;
}
char* ether_addr_to_string(const struct ether_addr *addr, char buffer[ETHER_ADDR_TO_STRING_MAX]) {
assert(addr);
assert(buffer);

View file

@ -1,11 +1,35 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <linux/if_infiniband.h>
#include <net/ethernet.h>
#include <stdbool.h>
#include "hash-funcs.h"
/* This is MAX_ADDR_LEN as defined in linux/netdevice.h, but net/if_arp.h
* defines a macro of the same name with a much lower size. */
#define HW_ADDR_MAX_SIZE 32
union hw_addr_union {
struct ether_addr ether;
uint8_t infiniband[INFINIBAND_ALEN];
uint8_t bytes[HW_ADDR_MAX_SIZE];
};
typedef struct hw_addr_data {
union hw_addr_union addr;
size_t length;
} hw_addr_data;
#define HW_ADDR_TO_STRING_MAX (3*HW_ADDR_MAX_SIZE)
char* hw_addr_to_string(const hw_addr_data *addr, char buffer[HW_ADDR_TO_STRING_MAX]);
/* Use only as function argument, never stand-alone! */
#define HW_ADDR_TO_STR(hw_addr) hw_addr_to_string((hw_addr), (char[HW_ADDR_TO_STRING_MAX]){})
#define HW_ADDR_NULL ((const hw_addr_data){})
#define ETHER_ADDR_FORMAT_STR "%02X%02X%02X%02X%02X%02X"
#define ETHER_ADDR_FORMAT_VAL(x) (x).ether_addr_octet[0], (x).ether_addr_octet[1], (x).ether_addr_octet[2], (x).ether_addr_octet[3], (x).ether_addr_octet[4], (x).ether_addr_octet[5]

View file

@ -29,10 +29,10 @@ typedef struct DHCPServerData {
extern const struct hash_ops dhcp_option_hash_ops;
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,
uint16_t port);
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,
const uint8_t *bcast_addr, size_t bcast_addr_len,
uint16_t arp_type, uint16_t port);
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type);
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
const void *packet, size_t len);

View file

@ -19,9 +19,9 @@
#include "unaligned.h"
static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
uint32_t xid, const uint8_t *mac_addr,
size_t mac_addr_len,
uint32_t xid,
const uint8_t *bcast_addr,
size_t bcast_addr_len,
const struct ether_addr *eth_mac,
uint16_t arp_type, uint8_t dhcp_hlen,
uint16_t port) {
@ -104,9 +104,9 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
.sll_protocol = htobe16(ETH_P_IP),
.sll_ifindex = ifindex,
.sll_hatype = htobe16(arp_type),
.sll_halen = mac_addr_len,
.sll_halen = bcast_addr_len,
};
memcpy(link->ll.sll_addr, bcast_addr, mac_addr_len);
memcpy(link->ll.sll_addr, bcast_addr, bcast_addr_len);
r = bind(s, &link->sa, SOCKADDR_LL_LEN(link->ll));
if (r < 0)
@ -115,34 +115,44 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
return TAKE_FD(s);
}
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,
uint16_t port) {
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,
const uint8_t *bcast_addr, size_t bcast_addr_len,
uint16_t arp_type, uint16_t port) {
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;
const uint8_t *default_bcast_addr;
size_t expected_bcast_addr_len;
uint8_t dhcp_hlen = 0;
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;
default_bcast_addr = eth_bcast;
expected_bcast_addr_len = ETH_ALEN;
} else if (arp_type == ARPHRD_INFINIBAND) {
assert_return(mac_addr_len == INFINIBAND_ALEN, -EINVAL);
bcast_addr = ib_bcast;
default_bcast_addr = ib_bcast;
expected_bcast_addr_len = INFINIBAND_ALEN;
} else
return -EINVAL;
return _bind_raw_socket(ifindex, link, xid, mac_addr, mac_addr_len,
bcast_addr, &eth_mac, arp_type, dhcp_hlen, port);
if (bcast_addr && bcast_addr_len > 0)
assert_return(bcast_addr_len == expected_bcast_addr_len, -EINVAL);
else {
bcast_addr = default_bcast_addr;
bcast_addr_len = expected_bcast_addr_len;
}
return _bind_raw_socket(ifindex, link, xid, bcast_addr, bcast_addr_len,
&eth_mac, arp_type, dhcp_hlen, port);
}
int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {

View file

@ -82,6 +82,8 @@ struct sd_dhcp_client {
be32_t last_addr;
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
size_t mac_addr_len;
uint8_t bcast_addr[MAX_MAC_ADDR_LEN];
size_t bcast_addr_len;
uint16_t arp_type;
sd_dhcp_client_id client_id;
size_t client_id_len;
@ -277,6 +279,7 @@ int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
const uint8_t *bcast_addr,
size_t addr_len,
uint16_t arp_type) {
@ -297,7 +300,9 @@ int sd_dhcp_client_set_mac(
return -EINVAL;
if (client->mac_addr_len == addr_len &&
memcmp(&client->mac_addr, addr, addr_len) == 0)
memcmp(&client->mac_addr, addr, addr_len) == 0 &&
(client->bcast_addr_len > 0) == !!bcast_addr &&
(!bcast_addr || memcmp(&client->bcast_addr, bcast_addr, addr_len) == 0))
return 0;
if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) {
@ -309,6 +314,12 @@ int sd_dhcp_client_set_mac(
memcpy(&client->mac_addr, addr, addr_len);
client->mac_addr_len = addr_len;
client->arp_type = arp_type;
client->bcast_addr_len = 0;
if (bcast_addr) {
memcpy(&client->bcast_addr, bcast_addr, addr_len);
client->bcast_addr_len = addr_len;
}
if (need_restart && client->state != DHCP_STATE_STOPPED) {
r = sd_dhcp_client_start(client);
@ -1381,9 +1392,10 @@ static int client_start_delayed(sd_dhcp_client *client) {
client->xid = random_u32();
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
client->xid, client->mac_addr,
client->mac_addr_len, client->arp_type, client->port);
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
client->mac_addr, client->mac_addr_len,
client->bcast_addr, client->bcast_addr_len,
client->arp_type, client->port);
if (r < 0) {
client_stop(client, r);
return r;
@ -1431,10 +1443,10 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
client->state = DHCP_STATE_REBINDING;
client->attempt = 0;
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
client->xid, client->mac_addr,
client->mac_addr_len, client->arp_type,
client->port);
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link, client->xid,
client->mac_addr, client->mac_addr_len,
client->bcast_addr, client->bcast_addr_len,
client->arp_type, client->port);
if (r < 0) {
client_stop(client, r);
return 0;

View file

@ -23,6 +23,7 @@
#include "util.h"
static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
static uint8_t bcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
@ -247,6 +248,7 @@ int dhcp_network_bind_raw_socket(
union sockaddr_union *link,
uint32_t id,
const uint8_t *addr, size_t addr_len,
const uint8_t *bcaddr, size_t bcaddr_len,
uint16_t arp_type, uint16_t port) {
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
@ -296,7 +298,7 @@ static void test_discover_message(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
@ -513,7 +515,7 @@ static void test_addr_acq(sd_event *e) {
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);

View file

@ -495,6 +495,25 @@ int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short t
return 0;
}
int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, const hw_addr_data *data) {
int r;
assert_return(m, -EINVAL);
assert_return(!m->sealed, -EPERM);
assert_return(data, -EINVAL);
assert_return(data->length > 0, -EINVAL);
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
if (r < 0)
return r;
r = add_rtattr(m, type, data->addr.bytes, data->length);
if (r < 0)
return r;
return 0;
}
int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
int r;
@ -864,6 +883,30 @@ int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short typ
return 0;
}
int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, hw_addr_data *data) {
int r;
void *attr_data;
assert_return(m, -EINVAL);
r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
if (r < 0)
return r;
r = netlink_message_read_internal(m, type, &attr_data, NULL);
if (r < 0)
return r;
else if ((size_t) r > sizeof(union hw_addr_union))
return -EIO;
if (data) {
memcpy(data->addr.bytes, attr_data, r);
data->length = r;
}
return 0;
}
int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) {
int r;
void *attr_data;

View file

@ -5,6 +5,7 @@
#include "sd-netlink.h"
#include "ether-addr-util.h"
#include "in-addr-util.h"
#include "ordered-set.h"
#include "socket-util.h"
@ -100,9 +101,11 @@ int rtnl_log_create_error(int r);
userdata, description); \
})
int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, const hw_addr_data *data);
int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data);
int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data);
int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, hw_addr_data *data);
int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data);
void rtattr_append_attribute_internal(struct rtattr *rta, unsigned short type, const void *data, size_t data_length);

View file

@ -135,7 +135,7 @@ typedef struct LinkInfo {
sd_device *sd_device;
int ifindex;
unsigned short iftype;
struct ether_addr mac_address;
hw_addr_data hw_address;
struct ether_addr permanent_mac_address;
uint32_t master;
uint32_t mtu;
@ -416,13 +416,14 @@ static int decode_link(sd_netlink_message *m, LinkInfo *info, char **patterns, b
info->alternative_names = TAKE_PTR(altnames);
info->has_mac_address =
sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 &&
memcmp(&info->mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0;
netlink_message_read_hw_addr(m, IFLA_ADDRESS, &info->hw_address) >= 0 &&
memcmp(&info->hw_address, &HW_ADDR_NULL, sizeof(hw_addr_data)) != 0;
info->has_permanent_mac_address =
ethtool_get_permanent_macaddr(NULL, info->name, &info->permanent_mac_address) >= 0 &&
memcmp(&info->permanent_mac_address, &ETHER_ADDR_NULL, sizeof(struct ether_addr)) != 0 &&
memcmp(&info->permanent_mac_address, &info->mac_address, sizeof(struct ether_addr)) != 0;
(info->hw_address.length != sizeof(struct ether_addr) ||
memcmp(&info->permanent_mac_address, info->hw_address.addr.bytes, sizeof(struct ether_addr)) != 0);
(void) sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu);
(void) sd_netlink_message_read_u32(m, IFLA_MIN_MTU, &info->min_mtu);
@ -1526,9 +1527,9 @@ static int link_status_one(
if (info->has_mac_address) {
_cleanup_free_ char *description = NULL;
char ea[ETHER_ADDR_TO_STRING_MAX];
(void) ieee_oui(hwdb, &info->mac_address, &description);
if (info->hw_address.length == ETH_ALEN)
(void) ieee_oui(hwdb, &info->hw_address.addr.ether, &description);
r = table_add_many(table,
TABLE_EMPTY,
@ -1536,7 +1537,7 @@ static int link_status_one(
if (r < 0)
return table_log_add_error(r);
r = table_add_cell_stringf(table, NULL, "%s%s%s%s",
ether_addr_to_string(&info->mac_address, ea),
HW_ADDR_TO_STR(&info->hw_address),
description ? " (" : "",
strempty(description),
description ? ")" : "");

View file

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include <net/if.h>
#include <net/if_arp.h>
#include "alloc-util.h"
#include "firewall-util.h"
@ -21,16 +22,24 @@ int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret) {
assert(link);
assert(ret);
if (link->iftype == ARPHRD_INFINIBAND) {
/* see RFC4391 section 8 */
memcpy(&ret->s6_addr[8], &link->hw_addr.addr.infiniband[12], 8);
ret->s6_addr[8] ^= 1 << 1;
return 0;
}
/* see RFC4291 section 2.5.1 */
ret->s6_addr[8] = link->mac.ether_addr_octet[0];
ret->s6_addr[8] = link->hw_addr.addr.ether.ether_addr_octet[0];
ret->s6_addr[8] ^= 1 << 1;
ret->s6_addr[9] = link->mac.ether_addr_octet[1];
ret->s6_addr[10] = link->mac.ether_addr_octet[2];
ret->s6_addr[9] = link->hw_addr.addr.ether.ether_addr_octet[1];
ret->s6_addr[10] = link->hw_addr.addr.ether.ether_addr_octet[2];
ret->s6_addr[11] = 0xff;
ret->s6_addr[12] = 0xfe;
ret->s6_addr[13] = link->mac.ether_addr_octet[3];
ret->s6_addr[14] = link->mac.ether_addr_octet[4];
ret->s6_addr[15] = link->mac.ether_addr_octet[5];
ret->s6_addr[13] = link->hw_addr.addr.ether.ether_addr_octet[3];
ret->s6_addr[14] = link->hw_addr.addr.ether.ether_addr_octet[4];
ret->s6_addr[15] = link->hw_addr.addr.ether.ether_addr_octet[5];
return 0;
}
@ -1373,7 +1382,7 @@ static int ipv4_dad_configure(Address *address) {
if (r < 0)
return r;
r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
r = sd_ipv4acd_set_mac(address->acd, &address->link->hw_addr.addr.ether);
if (r < 0)
return r;
@ -1403,7 +1412,7 @@ static int ipv4_dad_update_mac_one(Address *address) {
if (r < 0)
return r;
r = sd_ipv4acd_set_mac(address->acd, &address->link->mac);
r = sd_ipv4acd_set_mac(address->acd, &address->link->hw_addr.addr.ether);
if (r < 0)
return r;

View file

@ -650,7 +650,7 @@ static int dhcp4_configure_dad(Link *link) {
if (r < 0)
return r;
r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->mac);
r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.addr.ether);
if (r < 0)
return r;
@ -672,7 +672,7 @@ static int dhcp4_dad_update_mac(Link *link) {
if (r < 0)
return r;
r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->mac);
r = sd_ipv4acd_set_mac(link->dhcp_acd, &link->hw_addr.addr.ether);
if (r < 0)
return r;
@ -1271,14 +1271,24 @@ static int dhcp4_set_client_identifier(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m");
break;
}
case DHCP_CLIENT_ID_MAC:
case DHCP_CLIENT_ID_MAC: {
const uint8_t *hw_addr = link->hw_addr.addr.bytes;
size_t hw_addr_len = link->hw_addr.length;
if (link->iftype == ARPHRD_INFINIBAND && hw_addr_len == INFINIBAND_ALEN) {
/* set_client_id expects only last 8 bytes of an IB address */
hw_addr += INFINIBAND_ALEN - 8;
hw_addr_len -= INFINIBAND_ALEN - 8;
}
r = sd_dhcp_client_set_client_id(link->dhcp_client,
ARPHRD_ETHER,
(const uint8_t *) &link->mac,
sizeof(link->mac));
link->iftype,
hw_addr,
hw_addr_len);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m");
break;
}
default:
assert_not_reached("Unknown client identifier type.");
}
@ -1325,8 +1335,9 @@ int dhcp4_configure(Link *link) {
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to initialize DHCP4 client: %m");
r = sd_dhcp_client_set_mac(link->dhcp_client,
(const uint8_t *) &link->mac,
sizeof (link->mac), ARPHRD_ETHER);
link->hw_addr.addr.bytes,
link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL,
link->hw_addr.length, link->iftype);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m");
@ -1484,7 +1495,9 @@ int dhcp4_update_mac(Link *link) {
if (!link->dhcp_client)
return 0;
r = sd_dhcp_client_set_mac(link->dhcp_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.addr.bytes,
link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL,
link->hw_addr.length, link->iftype);
if (r < 0)
return r;

View file

@ -1357,7 +1357,7 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) {
assert(link->network);
assert(client);
r = sd_dhcp6_client_set_mac(client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER);
r = sd_dhcp6_client_set_mac(client, link->hw_addr.addr.bytes, link->hw_addr.length, link->iftype);
if (r < 0)
return r;

View file

@ -181,7 +181,7 @@ int ipv4ll_configure(Link *link) {
return r;
}
r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
r = sd_ipv4ll_set_mac(link->ipv4ll, &link->hw_addr.addr.ether);
if (r < 0)
return r;
@ -211,7 +211,7 @@ int ipv4ll_update_mac(Link *link) {
if (r < 0)
return r;
r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac);
r = sd_ipv4ll_set_mac(link->ipv4ll, &link->hw_addr.addr.ether);
if (r < 0)
return r;

View file

@ -421,9 +421,13 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (r < 0)
log_link_debug_errno(link, r, "New device has no master, continuing without");
r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
r = netlink_message_read_hw_addr(message, IFLA_ADDRESS, &link->hw_addr);
if (r < 0)
log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
log_link_debug_errno(link, r, "Hardware address not found for new device, continuing without");
r = netlink_message_read_hw_addr(message, IFLA_BROADCAST, &link->bcast_addr);
if (r < 0)
log_link_debug_errno(link, r, "Broadcast address not found for new device, continuing without");
r = ethtool_get_permanent_macaddr(&manager->ethtool_fd, link->ifname, &link->permanent_mac);
if (r < 0)
@ -2167,7 +2171,7 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
r = network_get(link->manager, link->iftype, link->sd_device,
link->ifname, link->alternative_names, link->driver,
&link->mac, &link->permanent_mac,
&link->hw_addr.addr.ether, &link->permanent_mac,
link->wlan_iftype, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
@ -2302,7 +2306,7 @@ static int link_initialized_and_synced(Link *link) {
r = network_get(link->manager, link->iftype, link->sd_device,
link->ifname, link->alternative_names, link->driver,
&link->mac, &link->permanent_mac,
&link->hw_addr.addr.ether, &link->permanent_mac,
link->wlan_iftype, link->ssid, &link->bssid, &network);
if (r == -ENOENT) {
link_enter_unmanaged(link);
@ -2697,7 +2701,7 @@ static int link_admin_state_up(Link *link) {
int link_update(Link *link, sd_netlink_message *m) {
_cleanup_strv_free_ char **s = NULL;
struct ether_addr mac;
hw_addr_data hw_addr;
const char *ifname;
uint32_t mtu;
bool had_carrier, carrier_gained, carrier_lost, link_was_admin_up;
@ -2756,19 +2760,13 @@ int link_update(Link *link, sd_netlink_message *m) {
/* The kernel may broadcast NEWLINK messages without the MAC address
set, simply ignore them. */
r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac);
if (r >= 0 && memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN) != 0) {
r = netlink_message_read_hw_addr(m, IFLA_ADDRESS, &hw_addr);
if (r >= 0 && (link->hw_addr.length != hw_addr.length ||
memcmp(link->hw_addr.addr.bytes, hw_addr.addr.bytes, hw_addr.length) != 0)) {
memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, ETH_ALEN);
memcpy(link->hw_addr.addr.bytes, hw_addr.addr.bytes, hw_addr.length);
log_link_debug(link, "Gained new MAC address: "
"%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
mac.ether_addr_octet[0],
mac.ether_addr_octet[1],
mac.ether_addr_octet[2],
mac.ether_addr_octet[3],
mac.ether_addr_octet[4],
mac.ether_addr_octet[5]);
log_link_debug(link, "Gained new hardware address: %s", HW_ADDR_TO_STR(&hw_addr));
r = ipv4ll_update_mac(link);
if (r < 0)
@ -2787,7 +2785,7 @@ int link_update(Link *link, sd_netlink_message *m) {
return log_link_warning_errno(link, r, "Could not update MAC address for Router Advertisement: %m");
if (link->ndisc) {
r = sd_ndisc_set_mac(link->ndisc, &link->mac);
r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.addr.ether);
if (r < 0)
return log_link_warning_errno(link, r, "Could not update MAC for NDisc: %m");
}

View file

@ -16,6 +16,7 @@
#include "sd-radv.h"
#include "sd-netlink.h"
#include "ether-addr-util.h"
#include "log-link.h"
#include "network-util.h"
#include "networkd-util.h"
@ -52,7 +53,8 @@ typedef struct Link {
char *kind;
unsigned short iftype;
char *state_file;
struct ether_addr mac;
hw_addr_data hw_addr;
hw_addr_data bcast_addr;
struct ether_addr permanent_mac;
struct in6_addr ipv6ll_address;
uint32_t mtu;

View file

@ -93,7 +93,7 @@ int link_lldp_rx_configure(Link *link) {
if (r < 0)
return r;
r = sd_lldp_set_filter_address(link->lldp, &link->mac);
r = sd_lldp_set_filter_address(link->lldp, &link->hw_addr.addr.ether);
if (r < 0)
return r;

View file

@ -313,7 +313,7 @@ static int link_send_lldp(Link *link) {
SD_LLDP_SYSTEM_CAPABILITIES_STATION;
r = lldp_make_packet(link->network->lldp_emit,
&link->mac,
&link->hw_addr.addr.ether,
sd_id128_to_string(machine_id, machine_id_string),
link->ifname,
(uint16_t) ttl,

View file

@ -5,6 +5,7 @@
#include <arpa/inet.h>
#include <netinet/icmp6.h>
#include <net/if_arp.h>
#include <linux/if.h>
#include "sd-ndisc.h"
@ -593,7 +594,11 @@ static int make_stableprivate_address(Link *link, const struct in6_addr *prefix,
l = MAX(DIV_ROUND_UP(prefix_len, 8), 8);
siphash24_compress(prefix, l, &state);
siphash24_compress_string(link->ifname, &state);
siphash24_compress(&link->mac, sizeof(struct ether_addr), &state);
/* Only last 8 bytes of IB MAC are stable */
if (link->iftype == ARPHRD_INFINIBAND)
siphash24_compress(&link->hw_addr.addr.infiniband[12], 8, &state);
else
siphash24_compress(link->hw_addr.addr.bytes, link->hw_addr.length, &state);
siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
rid = htole64(siphash24_finalize(&state));
@ -1257,7 +1262,7 @@ int ndisc_configure(Link *link) {
return r;
}
r = sd_ndisc_set_mac(link->ndisc, &link->mac);
r = sd_ndisc_set_mac(link->ndisc, &link->hw_addr.addr.ether);
if (r < 0)
return r;

View file

@ -659,7 +659,7 @@ int radv_configure(Link *link) {
if (r < 0)
return r;
r = sd_radv_set_mac(link->radv, &link->mac);
r = sd_radv_set_mac(link->radv, &link->hw_addr.addr.ether);
if (r < 0)
return r;
@ -727,7 +727,7 @@ int radv_update_mac(Link *link) {
if (r < 0)
return r;
r = sd_radv_set_mac(link->radv, &link->mac);
r = sd_radv_set_mac(link->radv, &link->hw_addr.addr.ether);
if (r < 0)
return r;

View file

@ -126,6 +126,7 @@ int sd_dhcp_client_set_ifindex(
int sd_dhcp_client_set_mac(
sd_dhcp_client *client,
const uint8_t *addr,
const uint8_t *bcast_addr,
size_t addr_len,
uint16_t arp_type);
int sd_dhcp_client_set_client_id(