Merge pull request #21517 from yuwata/network-long-hw-addr

network: make MACAddress= can take longer address
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2021-11-25 20:21:38 +01:00
committed by GitHub
8 changed files with 118 additions and 15 deletions
+92
View File
@@ -1,7 +1,11 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <linux/if_arp.h>
#include "arphrd-util.h"
#include "device-util.h"
#include "log-link.h"
#include "memory-util.h"
#include "netif-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
@@ -99,3 +103,91 @@ int net_get_unique_predictable_data_from_name(
*ret = htole64(siphash24(v, sz, key->bytes));
return 0;
}
typedef struct Link {
const char *ifname;
} Link;
int net_verify_hardware_address(
const char *ifname,
bool warn_invalid,
uint16_t iftype,
const struct hw_addr_data *ib_hw_addr, /* current or parent HW address */
struct hw_addr_data *new_hw_addr) {
Link link = { .ifname = ifname };
assert(new_hw_addr);
if (new_hw_addr->length == 0)
return 0;
if (new_hw_addr->length != arphrd_to_hw_addr_len(iftype)) {
if (warn_invalid)
log_link_warning(&link,
"Specified MAC address with invalid length (%zu, expected %zu), refusing.",
new_hw_addr->length, arphrd_to_hw_addr_len(iftype));
return -EINVAL;
}
switch (iftype) {
case ARPHRD_ETHER:
/* see eth_random_addr() in the kernel */
if (ether_addr_is_null(&new_hw_addr->ether)) {
if (warn_invalid)
log_link_warning(&link, "Specified MAC address is null, refusing.");
return -EINVAL;
}
if (ether_addr_is_broadcast(&new_hw_addr->ether)) {
if (warn_invalid)
log_link_warning(&link, "Specified MAC address is broadcast, refusing.");
return -EINVAL;
}
if (ether_addr_is_multicast(&new_hw_addr->ether)) {
if (warn_invalid)
log_link_warning(&link, "Specified MAC address has multicast bit set, clearing the bit.");
new_hw_addr->bytes[0] &= 0xfe;
}
if (!ether_addr_is_local(&new_hw_addr->ether)) {
if (warn_invalid)
log_link_warning(&link, "Specified MAC address has not local assignment bit set, setting the bit.");
new_hw_addr->bytes[0] |= 0x02;
}
break;
case ARPHRD_INFINIBAND:
/* see ipoib_check_lladdr() in the kernel */
assert(ib_hw_addr);
assert(ib_hw_addr->length == INFINIBAND_ALEN);
if (warn_invalid &&
(!memeqzero(new_hw_addr->bytes, INFINIBAND_ALEN - 8) ||
memcmp(new_hw_addr->bytes, ib_hw_addr->bytes, INFINIBAND_ALEN - 8) != 0))
log_link_warning(&link, "Only the last 8 bytes of the InifniBand MAC address can be changed, ignoring the first 12 bytes.");
if (memeqzero(new_hw_addr->bytes + INFINIBAND_ALEN - 8, 8)) {
if (warn_invalid)
log_link_warning(&link, "The last 8 bytes of the InfiniBand MAC address cannot be null, refusing.");
return -EINVAL;
}
memcpy(new_hw_addr->bytes, ib_hw_addr->bytes, INFINIBAND_ALEN - 8);
break;
default:
if (warn_invalid)
log_link_warning(&link, "Unsupported interface type %s%u to set MAC address, refusing.",
strna(arphrd_to_name(iftype)), iftype);
return -EINVAL;
}
return 0;
}
+8
View File
@@ -7,7 +7,15 @@
#include "sd-device.h"
#include "sd-id128.h"
#include "ether-addr-util.h"
int net_get_type_string(sd_device *device, uint16_t iftype, char **ret);
const char *net_get_persistent_name(sd_device *device);
int net_get_unique_predictable_data(sd_device *device, bool use_sysname, uint64_t *ret);
int net_get_unique_predictable_data_from_name(const char *name, const sd_id128_t *key, uint64_t *ret);
int net_verify_hardware_address(
const char *ifname,
bool warn_invalid,
uint16_t iftype,
const struct hw_addr_data *ib_hw_addr,
struct hw_addr_data *new_hw_addr);