From ab106a609bc253c0dc49667e981108110b3a87a5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 6 Dec 2021 09:33:14 +0900 Subject: [PATCH] network: eui64 address is supported only ethernet or infiniband So, this makes prefixstable mode will be used for other interface types. --- man/systemd.network.xml | 8 +++++--- src/network/networkd-address-generation.c | 25 ++++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 82d50c9569e..0714ebcd772 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2208,7 +2208,8 @@ Table=1234 - The EUI-64 algorithm will be used to generate an address for that prefix. + The EUI-64 algorithm will be used to generate an address for that prefix. Only + supported by Ethernet or InfiniBand interfaces. @@ -2267,8 +2268,9 @@ Table=1234 If no address generation mode is specified (which is the default), or a received prefix does not match any of the addresses provided in prefixstable - mode, then the EUI-64 algorithm will be used to form an interface identifier for that - prefix. + mode, then the EUI-64 algorithm will be used for Ethernet or InfiniBand interfaces, + otherwise prefixstable will be used to form an interface identifier for + that prefix. This setting can be specified multiple times. If an empty string is assigned, then the all previous assignments are cleared. diff --git a/src/network/networkd-address-generation.c b/src/network/networkd-address-generation.c index 0d7d3ee6534..1e119732c50 100644 --- a/src/network/networkd-address-generation.c +++ b/src/network/networkd-address-generation.c @@ -4,6 +4,7 @@ #include "sd-id128.h" +#include "arphrd-util.h" #include "id128-util.h" #include "memory-util.h" #include "networkd-address-generation.h" @@ -39,17 +40,19 @@ typedef struct IPv6Token { sd_id128_t secret_key; } IPv6Token; -static void generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret) { +static int generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret) { assert(link); assert(prefix); assert(ret); memcpy(ret->s6_addr, prefix, 8); - if (link->iftype == ARPHRD_INFINIBAND) + switch (link->iftype) { + case ARPHRD_INFINIBAND: /* Use last 8 byte. See RFC4391 section 8 */ memcpy(&ret->s6_addr[8], &link->hw_addr.infiniband[INFINIBAND_ALEN - 8], 8); - else { + break; + case ARPHRD_ETHER: /* see RFC4291 section 2.5.1 */ ret->s6_addr[8] = link->hw_addr.ether.ether_addr_octet[0]; ret->s6_addr[9] = link->hw_addr.ether.ether_addr_octet[1]; @@ -59,9 +62,15 @@ static void generate_eui64_address(const Link *link, const struct in6_addr *pref ret->s6_addr[13] = link->hw_addr.ether.ether_addr_octet[3]; ret->s6_addr[14] = link->hw_addr.ether.ether_addr_octet[4]; ret->s6_addr[15] = link->hw_addr.ether.ether_addr_octet[5]; + break; + default: + return log_link_debug_errno(link, SYNTHETIC_ERRNO(EINVAL), + "Token=eui64 is not supported for interface type %s, ignoring.", + strna(arphrd_to_name(link->iftype))); } ret->s6_addr[8] ^= 1 << 1; + return 0; } static bool stable_private_address_is_valid(const struct in6_addr *addr) { @@ -188,7 +197,8 @@ static int generate_addresses( switch (j->type) { case ADDRESS_GENERATION_EUI64: - generate_eui64_address(link, &masked, &addr); + if (generate_eui64_address(link, &masked, &addr) < 0) + continue; break; case ADDRESS_GENERATION_STATIC: @@ -226,7 +236,12 @@ static int generate_addresses( if (!addr) return -ENOMEM; - generate_eui64_address(link, &masked, addr); + if (IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND)) + r = generate_eui64_address(link, &masked, addr); + else + r = generate_stable_private_address(link, app_id, &SD_ID128_NULL, &masked, addr); + if (r < 0) + return r; r = set_ensure_consume(&addresses, &in6_addr_hash_ops_free, addr); if (r < 0) -- 2.47.3