1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <net/if_arp.h>
7 #include "arphrd-util.h"
8 #include "id128-util.h"
9 #include "memory-util.h"
10 #include "networkd-address-generation.h"
11 #include "networkd-link.h"
12 #include "networkd-network.h"
13 #include "string-util.h"
15 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
17 /* https://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xml */
18 #define SUBNET_ROUTER_ANYCAST_ADDRESS ((const struct in6_addr) { .s6_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } })
19 #define SUBNET_ROUTER_ANYCAST_PREFIXLEN 64
20 #define RESERVED_INTERFACE_IDENTIFIERS_ADDRESS ((const struct in6_addr) { .s6_addr = { 0x02, 0x00, 0x5E, 0xFF, 0xFE } })
21 #define RESERVED_INTERFACE_IDENTIFIERS_PREFIXLEN 40
22 #define RESERVED_SUBNET_ANYCAST_ADDRESSES ((const struct in6_addr) { .s6_addr = { 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80 } })
23 #define RESERVED_SUBNET_ANYCAST_PREFIXLEN 57
25 #define DHCP_PD_APP_ID SD_ID128_MAKE(fb,b9,37,ca,4a,ed,4a,4d,b0,70,7f,aa,71,c0,c9,85)
26 #define NDISC_APP_ID SD_ID128_MAKE(13,ac,81,a7,d5,3f,49,78,92,79,5d,0c,29,3a,bc,7e)
27 #define RADV_APP_ID SD_ID128_MAKE(1f,1e,90,c8,5c,78,4f,dc,8e,61,2d,59,0d,53,c1,25)
29 typedef enum AddressGenerationType
{
30 ADDRESS_GENERATION_EUI64
,
31 ADDRESS_GENERATION_STATIC
,
32 ADDRESS_GENERATION_PREFIXSTABLE
,
33 _ADDRESS_GENERATION_TYPE_MAX
,
34 _ADDRESS_GENERATION_TYPE_INVALID
= -EINVAL
,
35 } AddressGenerationType
;
37 typedef struct IPv6Token
{
38 AddressGenerationType type
;
39 struct in6_addr address
;
40 sd_id128_t secret_key
;
43 static int generate_eui64_address(const Link
*link
, const struct in6_addr
*prefix
, struct in6_addr
*ret
) {
48 memcpy(ret
->s6_addr
, prefix
, 8);
50 switch (link
->iftype
) {
51 case ARPHRD_INFINIBAND
:
52 /* Use last 8 byte. See RFC4391 section 8 */
53 memcpy(&ret
->s6_addr
[8], &link
->hw_addr
.infiniband
[INFINIBAND_ALEN
- 8], 8);
56 /* see RFC4291 section 2.5.1 */
57 ret
->s6_addr
[8] = link
->hw_addr
.ether
.ether_addr_octet
[0];
58 ret
->s6_addr
[9] = link
->hw_addr
.ether
.ether_addr_octet
[1];
59 ret
->s6_addr
[10] = link
->hw_addr
.ether
.ether_addr_octet
[2];
60 ret
->s6_addr
[11] = 0xff;
61 ret
->s6_addr
[12] = 0xfe;
62 ret
->s6_addr
[13] = link
->hw_addr
.ether
.ether_addr_octet
[3];
63 ret
->s6_addr
[14] = link
->hw_addr
.ether
.ether_addr_octet
[4];
64 ret
->s6_addr
[15] = link
->hw_addr
.ether
.ether_addr_octet
[5];
67 return log_link_debug_errno(link
, SYNTHETIC_ERRNO(EINVAL
),
68 "Token=eui64 is not supported for interface type %s, ignoring.",
69 strna(arphrd_to_name(link
->iftype
)));
72 ret
->s6_addr
[8] ^= 1 << 1;
76 static bool stable_private_address_is_valid(const struct in6_addr
*addr
) {
79 /* According to rfc4291, generated address should not be in the following ranges. */
81 if (in6_addr_prefix_covers(&SUBNET_ROUTER_ANYCAST_ADDRESS
, SUBNET_ROUTER_ANYCAST_PREFIXLEN
, addr
))
84 if (in6_addr_prefix_covers(&RESERVED_INTERFACE_IDENTIFIERS_ADDRESS
, RESERVED_INTERFACE_IDENTIFIERS_PREFIXLEN
, addr
))
87 if (in6_addr_prefix_covers(&RESERVED_SUBNET_ANYCAST_ADDRESSES
, RESERVED_SUBNET_ANYCAST_PREFIXLEN
, addr
))
93 static void generate_stable_private_address_one(
95 const sd_id128_t
*secret_key
,
96 const struct in6_addr
*prefix
,
98 struct in6_addr
*ret
) {
100 struct siphash state
;
108 /* According to RFC7217 section 5.1
109 * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
111 siphash24_init(&state
, secret_key
->bytes
);
113 siphash24_compress(prefix
, 8, &state
);
114 siphash24_compress_string(link
->ifname
, &state
);
115 if (link
->iftype
== ARPHRD_INFINIBAND
)
116 /* Only last 8 bytes of IB MAC are stable */
117 siphash24_compress(&link
->hw_addr
.infiniband
[INFINIBAND_ALEN
- 8], 8, &state
);
119 siphash24_compress(link
->hw_addr
.bytes
, link
->hw_addr
.length
, &state
);
120 siphash24_compress(&dad_counter
, sizeof(uint8_t), &state
);
122 rid
= htole64(siphash24_finalize(&state
));
124 memcpy(ret
->s6_addr
, prefix
->s6_addr
, 8);
125 memcpy(ret
->s6_addr
+ 8, &rid
, 8);
128 static int generate_stable_private_address(
130 const sd_id128_t
*app_id
,
131 const sd_id128_t
*secret_key
,
132 const struct in6_addr
*prefix
,
133 struct in6_addr
*ret
) {
135 sd_id128_t secret_machine_key
;
136 struct in6_addr addr
;
146 if (sd_id128_is_null(*secret_key
)) {
147 r
= sd_id128_get_machine_app_specific(*app_id
, &secret_machine_key
);
149 return log_link_debug_errno(link
, r
, "Failed to generate secret key for IPv6 stable private address: %m");
151 secret_key
= &secret_machine_key
;
154 /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop does
155 * not actually attempt Duplicate Address Detection; the counter will be incremented only when
156 * the address generation algorithm produces an invalid address, and the loop may exit with an
157 * address which ends up being unusable due to duplication on the link. */
158 for (i
= 0; i
< DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
; i
++) {
159 generate_stable_private_address_one(link
, secret_key
, prefix
, i
, &addr
);
161 if (stable_private_address_is_valid(&addr
))
164 if (i
>= DAD_CONFLICTS_IDGEN_RETRIES_RFC7217
)
165 /* propagate recognizable errors. */
166 return log_link_debug_errno(link
, SYNTHETIC_ERRNO(ENOANO
),
167 "Failed to generate stable private address.");
173 static int generate_addresses(
176 const sd_id128_t
*app_id
,
177 const struct in6_addr
*prefix
,
181 _cleanup_set_free_ Set
*addresses
= NULL
;
182 struct in6_addr masked
;
189 assert(prefixlen
> 0 && prefixlen
<= 64);
193 in6_addr_mask(&masked
, prefixlen
);
195 SET_FOREACH(j
, tokens
) {
196 struct in6_addr addr
, *copy
;
199 case ADDRESS_GENERATION_EUI64
:
200 if (generate_eui64_address(link
, &masked
, &addr
) < 0)
204 case ADDRESS_GENERATION_STATIC
:
205 memcpy(addr
.s6_addr
, masked
.s6_addr
, 8);
206 memcpy(addr
.s6_addr
+ 8, j
->address
.s6_addr
+ 8, 8);
209 case ADDRESS_GENERATION_PREFIXSTABLE
:
210 if (in6_addr_is_set(&j
->address
) && !in6_addr_equal(&j
->address
, &masked
))
213 if (generate_stable_private_address(link
, app_id
, &j
->secret_key
, &masked
, &addr
) < 0)
219 assert_not_reached();
222 copy
= newdup(struct in6_addr
, &addr
, 1);
226 r
= set_ensure_consume(&addresses
, &in6_addr_hash_ops_free
, copy
);
231 /* fall back to EUI-64 if no token is provided */
232 if (set_isempty(addresses
)) {
233 _cleanup_free_
struct in6_addr
*addr
= NULL
;
235 addr
= new(struct in6_addr
, 1);
239 if (IN_SET(link
->iftype
, ARPHRD_ETHER
, ARPHRD_INFINIBAND
))
240 r
= generate_eui64_address(link
, &masked
, addr
);
242 r
= generate_stable_private_address(link
, app_id
, &SD_ID128_NULL
, &masked
, addr
);
246 r
= set_ensure_consume(&addresses
, &in6_addr_hash_ops_free
, TAKE_PTR(addr
));
251 *ret
= TAKE_PTR(addresses
);
255 int dhcp_pd_generate_addresses(Link
*link
, const struct in6_addr
*prefix
, Set
**ret
) {
256 return generate_addresses(link
, link
->network
->dhcp_pd_tokens
, &DHCP_PD_APP_ID
, prefix
, 64, ret
);
259 int ndisc_generate_addresses(Link
*link
, const struct in6_addr
*prefix
, uint8_t prefixlen
, Set
**ret
) {
260 return generate_addresses(link
, link
->network
->ndisc_tokens
, &NDISC_APP_ID
, prefix
, prefixlen
, ret
);
263 int radv_generate_addresses(Link
*link
, Set
*tokens
, const struct in6_addr
*prefix
, uint8_t prefixlen
, Set
**ret
) {
264 return generate_addresses(link
, tokens
, &RADV_APP_ID
, prefix
, prefixlen
, ret
);
267 static void ipv6_token_hash_func(const IPv6Token
*p
, struct siphash
*state
) {
268 siphash24_compress(&p
->type
, sizeof(p
->type
), state
);
269 siphash24_compress(&p
->address
, sizeof(p
->address
), state
);
270 id128_hash_func(&p
->secret_key
, state
);
273 static int ipv6_token_compare_func(const IPv6Token
*a
, const IPv6Token
*b
) {
276 r
= CMP(a
->type
, b
->type
);
280 r
= memcmp(&a
->address
, &b
->address
, sizeof(struct in6_addr
));
284 return id128_compare_func(&a
->secret_key
, &b
->secret_key
);
287 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
290 ipv6_token_hash_func
,
291 ipv6_token_compare_func
,
294 static int ipv6_token_add(Set
**tokens
, AddressGenerationType type
, const struct in6_addr
*addr
, const sd_id128_t
*secret_key
) {
298 assert(type
>= 0 && type
< _ADDRESS_GENERATION_TYPE_MAX
);
302 p
= new(IPv6Token
, 1);
309 .secret_key
= *secret_key
,
312 return set_ensure_consume(tokens
, &ipv6_token_hash_ops
, p
);
315 int config_parse_address_generation_type(
317 const char *filename
,
320 unsigned section_line
,
327 _cleanup_free_
char *addr_alloc
= NULL
;
328 sd_id128_t secret_key
= SD_ID128_NULL
;
329 union in_addr_union buffer
= {};
330 AddressGenerationType type
;
340 if (isempty(rvalue
)) {
341 *tokens
= set_free(*tokens
);
345 if ((addr
= startswith(rvalue
, "prefixstable"))) {
348 type
= ADDRESS_GENERATION_PREFIXSTABLE
;
353 comma
= strchr(addr
, ',');
355 addr_alloc
= strndup(addr
, comma
- addr
);
361 } else if (*addr
== ',')
362 comma
= TAKE_PTR(addr
);
363 else if (*addr
== '\0') {
367 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
368 "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
374 r
= sd_id128_from_string(comma
+ 1, &secret_key
);
376 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
377 "Failed to parse secret key in %s=, ignoring assignment: %s",
381 if (sd_id128_is_null(secret_key
)) {
382 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
383 "Secret key in %s= cannot be null, ignoring assignment: %s",
389 } else if (streq(rvalue
, "eui64")) {
390 type
= ADDRESS_GENERATION_EUI64
;
393 type
= ADDRESS_GENERATION_STATIC
;
395 addr
= startswith(rvalue
, "static:");
401 r
= in_addr_from_string(AF_INET6
, addr
, &buffer
);
403 log_syntax(unit
, LOG_WARNING
, filename
, line
, r
,
404 "Failed to parse IP address in %s=, ignoring assignment: %s",
411 case ADDRESS_GENERATION_EUI64
:
412 assert(in6_addr_is_null(&buffer
.in6
));
415 case ADDRESS_GENERATION_STATIC
:
416 /* Only last 64 bits are used. */
417 memzero(buffer
.in6
.s6_addr
, 8);
419 if (in6_addr_is_null(&buffer
.in6
)) {
420 log_syntax(unit
, LOG_WARNING
, filename
, line
, 0,
421 "IPv6 address in %s= cannot be the ANY address, ignoring assignment: %s",
427 case ADDRESS_GENERATION_PREFIXSTABLE
:
428 /* At most, the initial 64 bits are used. */
429 (void) in6_addr_mask(&buffer
.in6
, 64);
433 assert_not_reached();
436 r
= ipv6_token_add(tokens
, type
, &buffer
.in6
, &secret_key
);