1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 
3 #include <net/if_arp.h>
4 
5 #include "sd-id128.h"
6 
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"
14 
15 #define DAD_CONFLICTS_IDGEN_RETRIES_RFC7217 3
16 
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
24 
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)
28 
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;
36 
37 typedef struct IPv6Token {
38         AddressGenerationType type;
39         struct in6_addr address;
40         sd_id128_t secret_key;
41 } IPv6Token;
42 
generate_eui64_address(const Link * link,const struct in6_addr * prefix,struct in6_addr * ret)43 static int generate_eui64_address(const Link *link, const struct in6_addr *prefix, struct in6_addr *ret) {
44         assert(link);
45         assert(prefix);
46         assert(ret);
47 
48         memcpy(ret->s6_addr, prefix, 8);
49 
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);
54                 break;
55         case ARPHRD_ETHER:
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];
65                 break;
66         default:
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)));
70         }
71 
72         ret->s6_addr[8] ^= 1 << 1;
73         return 0;
74 }
75 
stable_private_address_is_valid(const struct in6_addr * addr)76 static bool stable_private_address_is_valid(const struct in6_addr *addr) {
77         assert(addr);
78 
79         /* According to rfc4291, generated address should not be in the following ranges. */
80 
81         if (in6_addr_prefix_covers(&SUBNET_ROUTER_ANYCAST_ADDRESS, SUBNET_ROUTER_ANYCAST_PREFIXLEN, addr))
82                 return false;
83 
84         if (in6_addr_prefix_covers(&RESERVED_INTERFACE_IDENTIFIERS_ADDRESS, RESERVED_INTERFACE_IDENTIFIERS_PREFIXLEN, addr))
85                 return false;
86 
87         if (in6_addr_prefix_covers(&RESERVED_SUBNET_ANYCAST_ADDRESSES, RESERVED_SUBNET_ANYCAST_PREFIXLEN, addr))
88                 return false;
89 
90         return true;
91 }
92 
generate_stable_private_address_one(Link * link,const sd_id128_t * secret_key,const struct in6_addr * prefix,uint8_t dad_counter,struct in6_addr * ret)93 static void generate_stable_private_address_one(
94                 Link *link,
95                 const sd_id128_t *secret_key,
96                 const struct in6_addr *prefix,
97                 uint8_t dad_counter,
98                 struct in6_addr *ret) {
99 
100         struct siphash state;
101         uint64_t rid;
102 
103         assert(link);
104         assert(secret_key);
105         assert(prefix);
106         assert(ret);
107 
108         /* According to RFC7217 section 5.1
109          * RID = F(Prefix, Net_Iface, Network_ID, DAD_Counter, secret_key) */
110 
111         siphash24_init(&state, secret_key->bytes);
112 
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);
118         else
119                 siphash24_compress(link->hw_addr.bytes, link->hw_addr.length, &state);
120         siphash24_compress(&dad_counter, sizeof(uint8_t), &state);
121 
122         rid = htole64(siphash24_finalize(&state));
123 
124         memcpy(ret->s6_addr, prefix->s6_addr, 8);
125         memcpy(ret->s6_addr + 8, &rid, 8);
126 }
127 
generate_stable_private_address(Link * link,const sd_id128_t * app_id,const sd_id128_t * secret_key,const struct in6_addr * prefix,struct in6_addr * ret)128 static int generate_stable_private_address(
129                 Link *link,
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) {
134 
135         sd_id128_t secret_machine_key;
136         struct in6_addr addr;
137         uint8_t i;
138         int r;
139 
140         assert(link);
141         assert(app_id);
142         assert(secret_key);
143         assert(prefix);
144         assert(ret);
145 
146         if (sd_id128_is_null(*secret_key)) {
147                 r = sd_id128_get_machine_app_specific(*app_id, &secret_machine_key);
148                 if (r < 0)
149                         return log_link_debug_errno(link, r, "Failed to generate secret key for IPv6 stable private address: %m");
150 
151                 secret_key = &secret_machine_key;
152         }
153 
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);
160 
161                 if (stable_private_address_is_valid(&addr))
162                         break;
163         }
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.");
168 
169         *ret = addr;
170         return 0;
171 }
172 
generate_addresses(Link * link,Set * tokens,const sd_id128_t * app_id,const struct in6_addr * prefix,uint8_t prefixlen,Set ** ret)173 static int generate_addresses(
174                 Link *link,
175                 Set *tokens,
176                 const sd_id128_t *app_id,
177                 const struct in6_addr *prefix,
178                 uint8_t prefixlen,
179                 Set **ret) {
180 
181         _cleanup_set_free_ Set *addresses = NULL;
182         struct in6_addr masked;
183         IPv6Token *j;
184         int r;
185 
186         assert(link);
187         assert(app_id);
188         assert(prefix);
189         assert(prefixlen > 0 && prefixlen <= 64);
190         assert(ret);
191 
192         masked = *prefix;
193         in6_addr_mask(&masked, prefixlen);
194 
195         SET_FOREACH(j, tokens) {
196                 struct in6_addr addr, *copy;
197 
198                 switch (j->type) {
199                 case ADDRESS_GENERATION_EUI64:
200                         if (generate_eui64_address(link, &masked, &addr) < 0)
201                                 continue;
202                         break;
203 
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);
207                         break;
208 
209                 case ADDRESS_GENERATION_PREFIXSTABLE:
210                         if (in6_addr_is_set(&j->address) && !in6_addr_equal(&j->address, &masked))
211                                 continue;
212 
213                         if (generate_stable_private_address(link, app_id, &j->secret_key, &masked, &addr) < 0)
214                                 continue;
215 
216                         break;
217 
218                 default:
219                         assert_not_reached();
220                 }
221 
222                 copy = newdup(struct in6_addr, &addr, 1);
223                 if (!copy)
224                         return -ENOMEM;
225 
226                 r = set_ensure_consume(&addresses, &in6_addr_hash_ops_free, copy);
227                 if (r < 0)
228                         return r;
229         }
230 
231         /* fall back to EUI-64 if no token is provided */
232         if (set_isempty(addresses)) {
233                 _cleanup_free_ struct in6_addr *addr = NULL;
234 
235                 addr = new(struct in6_addr, 1);
236                 if (!addr)
237                         return -ENOMEM;
238 
239                 if (IN_SET(link->iftype, ARPHRD_ETHER, ARPHRD_INFINIBAND))
240                         r = generate_eui64_address(link, &masked, addr);
241                 else
242                         r = generate_stable_private_address(link, app_id, &SD_ID128_NULL, &masked, addr);
243                 if (r < 0)
244                         return r;
245 
246                 r = set_ensure_consume(&addresses, &in6_addr_hash_ops_free, TAKE_PTR(addr));
247                 if (r < 0)
248                         return r;
249         }
250 
251         *ret = TAKE_PTR(addresses);
252         return 0;
253 }
254 
dhcp_pd_generate_addresses(Link * link,const struct in6_addr * prefix,Set ** ret)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);
257 }
258 
ndisc_generate_addresses(Link * link,const struct in6_addr * prefix,uint8_t prefixlen,Set ** 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);
261 }
262 
radv_generate_addresses(Link * link,Set * tokens,const struct in6_addr * prefix,uint8_t prefixlen,Set ** 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);
265 }
266 
ipv6_token_hash_func(const IPv6Token * p,struct siphash * state)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);
271 }
272 
ipv6_token_compare_func(const IPv6Token * a,const IPv6Token * b)273 static int ipv6_token_compare_func(const IPv6Token *a, const IPv6Token *b) {
274         int r;
275 
276         r = CMP(a->type, b->type);
277         if (r != 0)
278                 return r;
279 
280         r = memcmp(&a->address, &b->address, sizeof(struct in6_addr));
281         if (r != 0)
282                 return r;
283 
284         return id128_compare_func(&a->secret_key, &b->secret_key);
285 }
286 
287 DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
288                 ipv6_token_hash_ops,
289                 IPv6Token,
290                 ipv6_token_hash_func,
291                 ipv6_token_compare_func,
292                 free);
293 
ipv6_token_add(Set ** tokens,AddressGenerationType type,const struct in6_addr * addr,const sd_id128_t * secret_key)294 static int ipv6_token_add(Set **tokens, AddressGenerationType type, const struct in6_addr *addr, const sd_id128_t *secret_key) {
295         IPv6Token *p;
296 
297         assert(tokens);
298         assert(type >= 0 && type < _ADDRESS_GENERATION_TYPE_MAX);
299         assert(addr);
300         assert(secret_key);
301 
302         p = new(IPv6Token, 1);
303         if (!p)
304                 return -ENOMEM;
305 
306         *p = (IPv6Token) {
307                  .type = type,
308                  .address = *addr,
309                  .secret_key = *secret_key,
310         };
311 
312         return set_ensure_consume(tokens, &ipv6_token_hash_ops, p);
313 }
314 
config_parse_address_generation_type(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)315 int config_parse_address_generation_type(
316                 const char *unit,
317                 const char *filename,
318                 unsigned line,
319                 const char *section,
320                 unsigned section_line,
321                 const char *lvalue,
322                 int ltype,
323                 const char *rvalue,
324                 void *data,
325                 void *userdata) {
326 
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;
331         Set **tokens = data;
332         const char *addr;
333         int r;
334 
335         assert(filename);
336         assert(lvalue);
337         assert(rvalue);
338         assert(data);
339 
340         if (isempty(rvalue)) {
341                 *tokens = set_free(*tokens);
342                 return 0;
343         }
344 
345         if ((addr = startswith(rvalue, "prefixstable"))) {
346                 const char *comma;
347 
348                 type = ADDRESS_GENERATION_PREFIXSTABLE;
349 
350                 if (*addr == ':') {
351                         addr++;
352 
353                         comma = strchr(addr, ',');
354                         if (comma) {
355                                 addr_alloc = strndup(addr, comma - addr);
356                                 if (!addr_alloc)
357                                         return log_oom();
358 
359                                 addr = addr_alloc;
360                         }
361                 } else if (*addr == ',')
362                         comma = TAKE_PTR(addr);
363                 else if (*addr == '\0') {
364                         comma = NULL;
365                         addr = NULL;
366                 } else {
367                         log_syntax(unit, LOG_WARNING, filename, line, 0,
368                                    "Invalid IPv6 token mode in %s=, ignoring assignment: %s",
369                                    lvalue, rvalue);
370                         return 0;
371                 }
372 
373                 if (comma) {
374                         r = sd_id128_from_string(comma + 1, &secret_key);
375                         if (r < 0) {
376                                 log_syntax(unit, LOG_WARNING, filename, line, r,
377                                            "Failed to parse secret key in %s=, ignoring assignment: %s",
378                                            lvalue, rvalue);
379                                 return 0;
380                         }
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",
384                                            lvalue, rvalue);
385                                 return 0;
386                         }
387                 }
388 
389         } else if (streq(rvalue, "eui64")) {
390                 type = ADDRESS_GENERATION_EUI64;
391                 addr = NULL;
392         } else {
393                 type = ADDRESS_GENERATION_STATIC;
394 
395                 addr = startswith(rvalue, "static:");
396                 if (!addr)
397                         addr = rvalue;
398         }
399 
400         if (addr) {
401                 r = in_addr_from_string(AF_INET6, addr, &buffer);
402                 if (r < 0) {
403                         log_syntax(unit, LOG_WARNING, filename, line, r,
404                                    "Failed to parse IP address in %s=, ignoring assignment: %s",
405                                    lvalue, rvalue);
406                         return 0;
407                 }
408         }
409 
410         switch (type) {
411         case ADDRESS_GENERATION_EUI64:
412                 assert(in6_addr_is_null(&buffer.in6));
413                 break;
414 
415         case ADDRESS_GENERATION_STATIC:
416                 /* Only last 64 bits are used. */
417                 memzero(buffer.in6.s6_addr, 8);
418 
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",
422                                    lvalue, rvalue);
423                         return 0;
424                 }
425                 break;
426 
427         case ADDRESS_GENERATION_PREFIXSTABLE:
428                 /* At most, the initial 64 bits are used. */
429                 (void) in6_addr_mask(&buffer.in6, 64);
430                 break;
431 
432         default:
433                 assert_not_reached();
434         }
435 
436         r = ipv6_token_add(tokens, type, &buffer.in6, &secret_key);
437         if (r < 0)
438                 return log_oom();
439 
440         return 0;
441 }
442