]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-address.c
network: cleanup networkd-route.h
[thirdparty/systemd.git] / src / network / networkd-address.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
f579559b
TG
2
3#include <net/if.h>
4
b5efdb8a 5#include "alloc-util.h"
f579559b 6#include "conf-parser.h"
12c2884c 7#include "firewall-util.h"
0a970718 8#include "memory-util.h"
081aea25 9#include "missing_network.h"
fc2f9534 10#include "netlink-util.h"
6bedfcbb 11#include "networkd-address.h"
23f53b99 12#include "networkd-manager.h"
50550722 13#include "networkd-ndisc.h"
6bedfcbb 14#include "parse-util.h"
3ac8e543 15#include "set.h"
d31645ad 16#include "socket-util.h"
07630cea 17#include "string-util.h"
51517f9e 18#include "strv.h"
3ac8e543 19#include "utf8.h"
f579559b 20
1b566071 21#define ADDRESSES_PER_LINK_MAX 2048U
8c34b963
LP
22#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
23
5ead5352
SS
24int generate_ipv6_eui_64_address(Link *link, struct in6_addr *ret) {
25 assert(link);
26 assert(ret);
27
28 /* see RFC4291 section 2.5.1 */
29 ret->s6_addr[8] = link->mac.ether_addr_octet[0];
30 ret->s6_addr[8] ^= 1 << 1;
31 ret->s6_addr[9] = link->mac.ether_addr_octet[1];
32 ret->s6_addr[10] = link->mac.ether_addr_octet[2];
33 ret->s6_addr[11] = 0xff;
34 ret->s6_addr[12] = 0xfe;
35 ret->s6_addr[13] = link->mac.ether_addr_octet[3];
36 ret->s6_addr[14] = link->mac.ether_addr_octet[4];
37 ret->s6_addr[15] = link->mac.ether_addr_octet[5];
38
39 return 0;
40}
41
f0213e37 42int address_new(Address **ret) {
8e766630 43 _cleanup_(address_freep) Address *address = NULL;
f0213e37 44
17f9c355 45 address = new(Address, 1);
f0213e37
TG
46 if (!address)
47 return -ENOMEM;
aba496a5 48
17f9c355
YW
49 *address = (Address) {
50 .family = AF_UNSPEC,
51 .scope = RT_SCOPE_UNIVERSE,
52 .cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME,
53 .cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME,
051e77ca 54 .duplicate_address_detection = ADDRESS_FAMILY_IPV6,
de697db0 55 .prefix_route = true,
17f9c355 56 };
f0213e37 57
1cc6c93a 58 *ret = TAKE_PTR(address);
f0213e37
TG
59
60 return 0;
aba496a5
UTL
61}
62
9560e5b3 63static int address_new_static(Network *network, const char *filename, unsigned section_line, Address **ret) {
8e766630
LP
64 _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL;
65 _cleanup_(address_freep) Address *address = NULL;
f0213e37 66 int r;
f579559b 67
8c34b963
LP
68 assert(network);
69 assert(ret);
48317c39 70 assert(!!filename == (section_line > 0));
8c34b963 71
48317c39 72 if (filename) {
f4859fc7
SS
73 r = network_config_section_new(filename, section_line, &n);
74 if (r < 0)
75 return r;
76
77 address = hashmap_get(network->addresses_by_section, n);
6ae115c1 78 if (address) {
1cc6c93a 79 *ret = TAKE_PTR(address);
6ae115c1
TG
80
81 return 0;
82 }
83 }
84
8c34b963
LP
85 if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX)
86 return -E2BIG;
87
f0213e37
TG
88 r = address_new(&address);
89 if (r < 0)
90 return r;
801bd9e8 91
0f7f2769
YW
92 address->network = network;
93 LIST_APPEND(addresses, network->static_addresses, address);
94 network->n_static_addresses++;
95
48317c39 96 if (filename) {
1cc6c93a 97 address->section = TAKE_PTR(n);
fcc48287 98
3e570042
YW
99 r = hashmap_ensure_allocated(&network->addresses_by_section, &network_config_hash_ops);
100 if (r < 0)
101 return r;
102
f7fe70ea
SS
103 r = hashmap_put(network->addresses_by_section, address->section, address);
104 if (r < 0)
105 return r;
6ae115c1
TG
106 }
107
1cc6c93a 108 *ret = TAKE_PTR(address);
f579559b
TG
109
110 return 0;
111}
112
113void address_free(Address *address) {
114 if (!address)
115 return;
116
f048a16b 117 if (address->network) {
3d3d4255 118 LIST_REMOVE(addresses, address->network->static_addresses, address);
8c34b963
LP
119 assert(address->network->n_static_addresses > 0);
120 address->network->n_static_addresses--;
f579559b 121
de4224aa 122 if (address->section)
f4859fc7 123 hashmap_remove(address->network->addresses_by_section, address->section);
f048a16b 124 }
6ae115c1 125
051e77ca 126 if (address->link && !address->acd) {
50550722 127 NDiscAddress *n;
50550722 128
cf1d700d 129 set_remove(address->link->addresses, address);
adda1ed9 130 set_remove(address->link->addresses_foreign, address);
e5526518 131 set_remove(address->link->static_addresses, address);
6e537f62
YW
132 if (address->link->dhcp_address == address)
133 address->link->dhcp_address = NULL;
134 if (address->link->dhcp_address_old == address)
135 address->link->dhcp_address_old = NULL;
1633c457
YW
136 set_remove(address->link->dhcp6_addresses, address);
137 set_remove(address->link->dhcp6_addresses_old, address);
138 set_remove(address->link->dhcp6_pd_addresses, address);
139 set_remove(address->link->dhcp6_pd_addresses_old, address);
90e74a66 140 SET_FOREACH(n, address->link->ndisc_addresses)
50550722
YW
141 if (n->address == address)
142 free(set_remove(address->link->ndisc_addresses, n));
f150100a
SS
143
144 if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address))
145 memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr));
adda1ed9 146 }
cf1d700d 147
051e77ca
SS
148 sd_ipv4acd_unref(address->acd);
149
de4224aa
YW
150 network_config_section_free(address->section);
151 free(address->label);
f579559b
TG
152 free(address);
153}
154
24be9181
ZJS
155static uint32_t address_prefix(const Address *a) {
156 assert(a);
157
158 /* make sure we don't try to shift by 32.
159 * See ISO/IEC 9899:TC3 § 6.5.7.3. */
160 if (a->prefixlen == 0)
161 return 0;
162
163 if (a->in_addr_peer.in.s_addr != 0)
164 return be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
165 else
166 return be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
167}
168
99a28784 169void address_hash_func(const Address *a, struct siphash *state) {
3ac8e543
TG
170 assert(a);
171
172 siphash24_compress(&a->family, sizeof(a->family), state);
173
174 switch (a->family) {
175 case AF_INET:
176 siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
177
178 /* peer prefix */
24be9181
ZJS
179 uint32_t prefix = address_prefix(a);
180 siphash24_compress(&prefix, sizeof(prefix), state);
3ac8e543 181
4831981d 182 _fallthrough_;
3ac8e543
TG
183 case AF_INET6:
184 /* local address */
185 siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
186
187 break;
188 default:
189 /* treat any other address family as AF_UNSPEC */
190 break;
191 }
192}
193
99a28784 194int address_compare_func(const Address *a1, const Address *a2) {
a0edd02e 195 int r;
3ac8e543 196
a0edd02e
FB
197 r = CMP(a1->family, a2->family);
198 if (r != 0)
199 return r;
3ac8e543
TG
200
201 switch (a1->family) {
202 /* use the same notion of equality as the kernel does */
203 case AF_INET:
a0edd02e
FB
204 r = CMP(a1->prefixlen, a2->prefixlen);
205 if (r != 0)
206 return r;
3ac8e543 207
24be9181
ZJS
208 uint32_t prefix1 = address_prefix(a1);
209 uint32_t prefix2 = address_prefix(a2);
210 r = CMP(prefix1, prefix2);
211 if (r != 0)
212 return r;
3ac8e543 213
4831981d 214 _fallthrough_;
3ac8e543
TG
215 case AF_INET6:
216 return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
217 default:
218 /* treat any other address family as AF_UNSPEC */
219 return 0;
220 }
221}
222
8eec0b9d 223DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(address_hash_ops, Address, address_hash_func, address_compare_func, address_free);
3ac8e543
TG
224
225bool address_equal(Address *a1, Address *a2) {
226 if (a1 == a2)
227 return true;
228
229 if (!a1 || !a2)
230 return false;
231
232 return address_compare_func(a1, a2) == 0;
233}
234
91b5f997
TG
235static int address_establish(Address *address, Link *link) {
236 bool masq;
237 int r;
238
239 assert(address);
240 assert(link);
241
242 masq = link->network &&
fcf50cff
TG
243 link->network->ip_masquerade &&
244 address->family == AF_INET &&
245 address->scope < RT_SCOPE_LINK;
91b5f997
TG
246
247 /* Add firewall entry if this is requested */
248 if (address->ip_masquerade_done != masq) {
249 union in_addr_union masked = address->in_addr;
250 in_addr_mask(address->family, &masked, address->prefixlen);
251
252 r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
253 if (r < 0)
7750b796 254 return r;
91b5f997
TG
255
256 address->ip_masquerade_done = masq;
257 }
258
259 return 0;
260}
261
adda1ed9
TG
262static int address_add_internal(Link *link, Set **addresses,
263 int family,
264 const union in_addr_union *in_addr,
265 unsigned char prefixlen,
266 Address **ret) {
8e766630 267 _cleanup_(address_freep) Address *address = NULL;
cf1d700d
TG
268 int r;
269
270 assert(link);
adda1ed9 271 assert(addresses);
054f0db4 272 assert(in_addr);
054f0db4
TG
273
274 r = address_new(&address);
275 if (r < 0)
276 return r;
277
278 address->family = family;
279 address->in_addr = *in_addr;
280 address->prefixlen = prefixlen;
63bbe5c7
TG
281 /* Consider address tentative until we get the real flags from the kernel */
282 address->flags = IFA_F_TENTATIVE;
cf1d700d 283
de7fef4b 284 r = set_ensure_put(addresses, &address_hash_ops, address);
cf1d700d
TG
285 if (r < 0)
286 return r;
75a302b5
YW
287 if (r == 0)
288 return -EEXIST;
cf1d700d
TG
289
290 address->link = link;
291
adda1ed9
TG
292 if (ret)
293 *ret = address;
de7fef4b 294 TAKE_PTR(address);
cf1d700d
TG
295 return 0;
296}
297
adda1ed9
TG
298int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
299 return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret);
300}
301
c4a03a56 302int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
cab974b0 303 Address *address;
e7780c8d
TG
304 int r;
305
cab974b0
TG
306 r = address_get(link, family, in_addr, prefixlen, &address);
307 if (r == -ENOENT) {
308 /* Address does not exist, create a new one */
309 r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address);
310 if (r < 0)
311 return r;
312 } else if (r == 0) {
313 /* Take over a foreign address */
de7fef4b 314 r = set_ensure_put(&link->addresses, &address_hash_ops, address);
cab974b0
TG
315 if (r < 0)
316 return r;
317
318 set_remove(link->addresses_foreign, address);
319 } else if (r == 1) {
320 /* Already exists, do nothing */
321 ;
322 } else
e7780c8d
TG
323 return r;
324
cab974b0
TG
325 if (ret)
326 *ret = address;
e7780c8d
TG
327
328 return 0;
adda1ed9
TG
329}
330
fcf50cff 331static int address_release(Address *address) {
5a8bcb67
LP
332 int r;
333
334 assert(address);
fcf50cff 335 assert(address->link);
5a8bcb67 336
91b5f997
TG
337 /* Remove masquerading firewall entry if it was added */
338 if (address->ip_masquerade_done) {
5a8bcb67
LP
339 union in_addr_union masked = address->in_addr;
340 in_addr_mask(address->family, &masked, address->prefixlen);
341
91b5f997 342 r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0);
5a8bcb67 343 if (r < 0)
7750b796 344 return r;
5a8bcb67 345
91b5f997 346 address->ip_masquerade_done = false;
5a8bcb67
LP
347 }
348
349 return 0;
350}
351
889b550f
LP
352int address_update(
353 Address *address,
354 unsigned char flags,
355 unsigned char scope,
356 const struct ifa_cacheinfo *cinfo) {
357
36c32f61 358 bool ready;
e7ab854c 359 int r;
36c32f61
TG
360
361 assert(address);
ea121d8f 362 assert(address->link);
36c32f61
TG
363 assert(cinfo);
364
365 ready = address_is_ready(address);
366
367 address->flags = flags;
368 address->scope = scope;
369 address->cinfo = *cinfo;
370
ea121d8f
YW
371 if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
372 return 0;
373
959f65d3 374 link_update_operstate(address->link, true);
c8f7123e 375 link_check_ready(address->link);
7209086d 376
97f00074
YW
377 if (!ready && address_is_ready(address)) {
378 if (address->callback) {
379 r = address->callback(address);
380 if (r < 0)
381 return r;
382 }
7209086d 383
97f00074
YW
384 if (address->family == AF_INET6 &&
385 in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
386 IN6_IS_ADDR_UNSPECIFIED(&address->link->ipv6ll_address) > 0) {
387
388 r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
389 if (r < 0)
390 return r;
391 }
a3a019e1 392 }
36c32f61
TG
393
394 return 0;
395}
396
91b5f997 397int address_drop(Address *address) {
8012cd39
TG
398 Link *link;
399 bool ready;
7750b796 400 int r;
8012cd39 401
5a8bcb67 402 assert(address);
91b5f997 403
8012cd39
TG
404 ready = address_is_ready(address);
405 link = address->link;
406
7750b796
YW
407 r = address_release(address);
408 if (r < 0)
409 log_link_warning_errno(link, r, "Failed to disable IP masquerading, ignoring: %m");
410
91b5f997
TG
411 address_free(address);
412
959f65d3 413 link_update_operstate(link, true);
84de38c5 414
8012cd39
TG
415 if (link && !ready)
416 link_check_ready(link);
417
91b5f997
TG
418 return 0;
419}
420
1b566071
LP
421int address_get(Link *link,
422 int family,
423 const union in_addr_union *in_addr,
424 unsigned char prefixlen,
425 Address **ret) {
426
427 Address address, *existing;
91b5f997 428
5a8bcb67 429 assert(link);
91b5f997 430 assert(in_addr);
5a8bcb67 431
1b566071
LP
432 address = (Address) {
433 .family = family,
434 .in_addr = *in_addr,
435 .prefixlen = prefixlen,
436 };
5a8bcb67 437
91b5f997 438 existing = set_get(link->addresses, &address);
cab974b0 439 if (existing) {
1b566071
LP
440 if (ret)
441 *ret = existing;
cab974b0 442 return 1;
adda1ed9 443 }
5a8bcb67 444
1b566071
LP
445 existing = set_get(link->addresses_foreign, &address);
446 if (existing) {
447 if (ret)
448 *ret = existing;
449 return 0;
450 }
5a8bcb67 451
1b566071 452 return -ENOENT;
5a8bcb67
LP
453}
454
5eec0a08
YW
455static bool address_exists_internal(Set *addresses, int family, const union in_addr_union *in_addr) {
456 Address *address;
5eec0a08 457
90e74a66 458 SET_FOREACH(address, addresses) {
5eec0a08
YW
459 if (address->family != family)
460 continue;
461 if (in_addr_equal(address->family, &address->in_addr, in_addr))
462 return true;
463 }
464
465 return false;
466}
467
468bool address_exists(Link *link, int family, const union in_addr_union *in_addr) {
469 assert(link);
470 assert(IN_SET(family, AF_INET, AF_INET6));
471 assert(in_addr);
472
473 if (address_exists_internal(link->addresses, family, in_addr))
474 return true;
475 if (address_exists_internal(link->addresses_foreign, family, in_addr))
476 return true;
477 return false;
478}
479
302a796f 480static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
63ae0569
YW
481 int r;
482
483 assert(m);
484 assert(link);
485 assert(link->ifname);
486
487 if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
488 return 1;
489
490 r = sd_netlink_message_get_errno(m);
491 if (r < 0 && r != -EADDRNOTAVAIL)
5ecb131d 492 log_link_message_warning_errno(link, m, r, "Could not drop address");
fb282d4e 493 else if (r >= 0)
93b0b88c 494 (void) manager_rtnl_process_address(rtnl, m, link->manager);
63ae0569
YW
495
496 return 1;
497}
498
483d099e
ZJS
499int address_remove(
500 Address *address,
501 Link *link,
302a796f 502 link_netlink_message_handler_t callback) {
483d099e 503
4afd3348 504 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
407fe036
TG
505 int r;
506
507 assert(address);
4c701096 508 assert(IN_SET(address->family, AF_INET, AF_INET6));
407fe036
TG
509 assert(link);
510 assert(link->ifindex > 0);
511 assert(link->manager);
512 assert(link->manager->rtnl);
513
30226d27 514 if (DEBUG_LOGGING) {
7750b796
YW
515 _cleanup_free_ char *b = NULL;
516
517 (void) in_addr_to_string(address->family, &address->in_addr, &b);
518 log_link_debug(link, "Removing address %s", strna(b));
30226d27
TJ
519 }
520
151b9b96
LP
521 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR,
522 link->ifindex, address->family);
eb56eb9b 523 if (r < 0)
7750b796 524 return log_link_error_errno(link, r, "Could not allocate RTM_DELADDR message: %m");
407fe036 525
5a723174 526 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
eb56eb9b 527 if (r < 0)
7750b796 528 return log_link_error_errno(link, r, "Could not set prefixlen: %m");
5a723174 529
43409486 530 r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
eb56eb9b 531 if (r < 0)
7750b796 532 return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
407fe036 533
302a796f
YW
534 r = netlink_call_async(link->manager->rtnl, NULL, req,
535 callback ?: address_remove_handler,
536 link_netlink_destroy_callback, link);
eb56eb9b 537 if (r < 0)
7750b796 538 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
407fe036 539
563c69c6
TG
540 link_ref(link);
541
407fe036
TG
542 return 0;
543}
544
11bf3cce 545static int address_acquire(Link *link, Address *original, Address **ret) {
67a46833 546 union in_addr_union in_addr = IN_ADDR_NULL;
11bf3cce 547 struct in_addr broadcast = {};
8e766630 548 _cleanup_(address_freep) Address *na = NULL;
11bf3cce
LP
549 int r;
550
551 assert(link);
552 assert(original);
553 assert(ret);
554
555 /* Something useful was configured? just use it */
7e43ebfb
YW
556 r = in_addr_is_null(original->family, &original->in_addr);
557 if (r <= 0)
558 return r;
11bf3cce
LP
559
560 /* The address is configured to be 0.0.0.0 or [::] by the user?
561 * Then let's acquire something more useful from the pool. */
562 r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr);
6a7a4e4d 563 if (r < 0)
7750b796
YW
564 return r;
565 if (r == 0)
11bf3cce 566 return -EBUSY;
11bf3cce
LP
567
568 if (original->family == AF_INET) {
d076c6f9 569 /* Pick first address in range for ourselves ... */
11bf3cce
LP
570 in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1);
571
572 /* .. and use last as broadcast address */
e87e2b78
SS
573 if (original->prefixlen > 30)
574 broadcast.s_addr = 0;
575 else
576 broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen);
11bf3cce
LP
577 } else if (original->family == AF_INET6)
578 in_addr.in6.s6_addr[15] |= 1;
579
f0213e37 580 r = address_new(&na);
11bf3cce
LP
581 if (r < 0)
582 return r;
583
584 na->family = original->family;
585 na->prefixlen = original->prefixlen;
586 na->scope = original->scope;
587 na->cinfo = original->cinfo;
588
589 if (original->label) {
590 na->label = strdup(original->label);
0099bc15 591 if (!na->label)
11bf3cce 592 return -ENOMEM;
11bf3cce
LP
593 }
594
595 na->broadcast = broadcast;
596 na->in_addr = in_addr;
597
598 LIST_PREPEND(addresses, link->pool_addresses, na);
599
1cc6c93a 600 *ret = TAKE_PTR(na);
0099bc15 601
11bf3cce
LP
602 return 0;
603}
604
1b566071
LP
605int address_configure(
606 Address *address,
607 Link *link,
302a796f 608 link_netlink_message_handler_t callback,
80b0e860
YW
609 bool update,
610 Address **ret) {
1b566071 611
4afd3348 612 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
80b0e860 613 Address *a;
f579559b
TG
614 int r;
615
c166a070 616 assert(address);
4c701096 617 assert(IN_SET(address->family, AF_INET, AF_INET6));
c166a070
TG
618 assert(link);
619 assert(link->ifindex > 0);
f882c247 620 assert(link->manager);
c166a070 621 assert(link->manager->rtnl);
bd1175bc 622 assert(callback);
f882c247 623
1b566071
LP
624 /* If this is a new address, then refuse adding more than the limit */
625 if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
626 set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
7750b796
YW
627 return log_link_error_errno(link, SYNTHETIC_ERRNO(E2BIG),
628 "Too many addresses are configured, refusing: %m");
1b566071 629
11bf3cce
LP
630 r = address_acquire(link, address, &address);
631 if (r < 0)
7750b796 632 return log_link_error_errno(link, r, "Failed to acquire an address from pool: %m");
11bf3cce 633
3606ca65
YW
634 if (DEBUG_LOGGING) {
635 _cleanup_free_ char *str = NULL;
636
637 (void) in_addr_to_string(address->family, &address->in_addr, &str);
638 log_link_debug(link, "%s address: %s", update ? "Updating" : "Configuring", strna(str));
639 }
640
66669078
TG
641 if (update)
642 r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req,
643 link->ifindex, address->family);
644 else
645 r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR,
646 link->ifindex, address->family);
eb56eb9b 647 if (r < 0)
7750b796 648 return log_link_error_errno(link, r, "Could not allocate RTM_NEWADDR message: %m");
f579559b 649
5a723174 650 r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen);
eb56eb9b 651 if (r < 0)
7750b796 652 return log_link_error_errno(link, r, "Could not set prefixlen: %m");
5a723174 653
851c9f82
PF
654 address->flags |= IFA_F_PERMANENT;
655
e63be084
SS
656 if (address->home_address)
657 address->flags |= IFA_F_HOMEADDRESS;
658
051e77ca 659 if (!FLAGS_SET(address->duplicate_address_detection, ADDRESS_FAMILY_IPV6))
e63be084
SS
660 address->flags |= IFA_F_NODAD;
661
662 if (address->manage_temporary_address)
663 address->flags |= IFA_F_MANAGETEMPADDR;
664
de697db0 665 if (!address->prefix_route)
e63be084
SS
666 address->flags |= IFA_F_NOPREFIXROUTE;
667
668 if (address->autojoin)
669 address->flags |= IFA_F_MCAUTOJOIN;
670
851c9f82 671 r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
eb56eb9b 672 if (r < 0)
7750b796 673 return log_link_error_errno(link, r, "Could not set flags: %m");
5a723174 674
851c9f82 675 if (address->flags & ~0xff) {
1c4baffc 676 r = sd_netlink_message_append_u32(req, IFA_FLAGS, address->flags);
851c9f82 677 if (r < 0)
7750b796 678 return log_link_error_errno(link, r, "Could not set extended flags: %m");
851c9f82
PF
679 }
680
5c1d3fc9 681 r = sd_rtnl_message_addr_set_scope(req, address->scope);
eb56eb9b 682 if (r < 0)
7750b796 683 return log_link_error_errno(link, r, "Could not set scope: %m");
5a723174 684
43409486 685 r = netlink_message_append_in_addr_union(req, IFA_LOCAL, address->family, &address->in_addr);
eb56eb9b 686 if (r < 0)
7750b796 687 return log_link_error_errno(link, r, "Could not append IFA_LOCAL attribute: %m");
f579559b 688
d40b01e4 689 if (in_addr_is_null(address->family, &address->in_addr_peer) == 0) {
43409486 690 r = netlink_message_append_in_addr_union(req, IFA_ADDRESS, address->family, &address->in_addr_peer);
eb56eb9b 691 if (r < 0)
7750b796 692 return log_link_error_errno(link, r, "Could not append IFA_ADDRESS attribute: %m");
66e0bb33
YW
693 } else if (address->family == AF_INET && address->prefixlen <= 30) {
694 r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast);
695 if (r < 0)
7750b796 696 return log_link_error_errno(link, r, "Could not append IFA_BROADCAST attribute: %m");
f579559b
TG
697 }
698
699 if (address->label) {
1c4baffc 700 r = sd_netlink_message_append_string(req, IFA_LABEL, address->label);
eb56eb9b 701 if (r < 0)
7750b796 702 return log_link_error_errno(link, r, "Could not append IFA_LABEL attribute: %m");
f579559b
TG
703 }
704
66e0bb33 705 r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, &address->cinfo);
eb56eb9b 706 if (r < 0)
7750b796 707 return log_link_error_errno(link, r, "Could not append IFA_CACHEINFO attribute: %m");
68ceb9df 708
fcf50cff 709 r = address_establish(address, link);
eb56eb9b 710 if (r < 0)
7750b796 711 log_link_warning_errno(link, r, "Could not enable IP masquerading, ignoring: %m");
fcf50cff 712
dfef713f 713 r = netlink_call_async(link->manager->rtnl, NULL, req, callback, link_netlink_destroy_callback, link);
fcf50cff
TG
714 if (r < 0) {
715 address_release(address);
7750b796 716 return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
fcf50cff 717 }
f579559b 718
563c69c6
TG
719 link_ref(link);
720
dfef713f 721 if (address->family == AF_INET6 && !in_addr_is_null(address->family, &address->in_addr_peer))
80b0e860 722 r = address_add(link, address->family, &address->in_addr_peer, address->prefixlen, &a);
dfef713f 723 else
80b0e860 724 r = address_add(link, address->family, &address->in_addr, address->prefixlen, &a);
adda1ed9
TG
725 if (r < 0) {
726 address_release(address);
7750b796 727 return log_link_error_errno(link, r, "Could not add address: %m");
adda1ed9
TG
728 }
729
051e77ca
SS
730 if (address->acd) {
731 assert(address->family == AF_INET);
732 if (DEBUG_LOGGING) {
733 _cleanup_free_ char *pretty = NULL;
734
735 (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
98b02994 736 log_link_debug(link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
051e77ca
SS
737 }
738
e92b60b2 739 r = sd_ipv4acd_start(address->acd, true);
051e77ca
SS
740 if (r < 0)
741 log_link_warning_errno(link, r, "Failed to start IPv4ACD client, ignoring: %m");
742 }
743
80b0e860
YW
744 if (ret)
745 *ret = a;
746
54a1a535 747 return 1;
f579559b
TG
748}
749
051e77ca
SS
750static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
751 _cleanup_free_ char *pretty = NULL;
752 Address *address;
753 Link *link;
754 int r;
755
756 assert(acd);
757 assert(userdata);
758
759 address = (Address *) userdata;
760 link = address->link;
761
762 (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
763 switch (event) {
764 case SD_IPV4ACD_EVENT_STOP:
765 log_link_debug(link, "Stopping ACD client...");
766 return;
767
768 case SD_IPV4ACD_EVENT_BIND:
769 log_link_debug(link, "Successfully claimed address %s", strna(pretty));
770 link_check_ready(link);
771 break;
772
773 case SD_IPV4ACD_EVENT_CONFLICT:
774 log_link_warning(link, "DAD conflict. Dropping address %s", strna(pretty));
775 r = address_remove(address, link, NULL);
776 if (r < 0)
777 log_link_error_errno(link, r, "Failed to drop DAD conflicted address %s", strna(pretty));;
778
779 link_check_ready(link);
780 break;
781
782 default:
783 assert_not_reached("Invalid IPv4ACD event.");
784 }
785
786 sd_ipv4acd_stop(acd);
787
788 return;
789}
790
791int configure_ipv4_duplicate_address_detection(Link *link, Address *address) {
792 int r;
793
794 assert(link);
795 assert(address);
796 assert(address->family == AF_INET);
797 assert(!address->link && address->network);
798
799 address->link = link;
800
801 r = sd_ipv4acd_new(&address->acd);
802 if (r < 0)
803 return r;
804
805 r = sd_ipv4acd_attach_event(address->acd, NULL, 0);
806 if (r < 0)
807 return r;
808
809 r = sd_ipv4acd_set_ifindex(address->acd, link->ifindex);
810 if (r < 0)
811 return r;
812
813 r = sd_ipv4acd_set_mac(address->acd, &link->mac);
814 if (r < 0)
815 return r;
816
817 r = sd_ipv4acd_set_address(address->acd, &address->in_addr.in);
818 if (r < 0)
819 return r;
820
821 r = sd_ipv4acd_set_callback(address->acd, static_address_on_acd, address);
822 if (r < 0)
823 return r;
824
825 return 0;
826}
827
44e7b949
LP
828int config_parse_broadcast(
829 const char *unit,
eb0ea358
TG
830 const char *filename,
831 unsigned line,
832 const char *section,
833 unsigned section_line,
834 const char *lvalue,
835 int ltype,
836 const char *rvalue,
837 void *data,
838 void *userdata) {
44e7b949 839
eb0ea358 840 Network *network = userdata;
fcbf4cb7 841 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
eb0ea358
TG
842 int r;
843
844 assert(filename);
845 assert(section);
846 assert(lvalue);
847 assert(rvalue);
848 assert(data);
849
f4859fc7 850 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
851 if (r == -ENOMEM)
852 return log_oom();
853 if (r < 0) {
854 log_syntax(unit, LOG_WARNING, filename, line, r,
855 "Failed to allocate new address, ignoring assignment: %m");
856 return 0;
857 }
eb0ea358 858
482e2ac1 859 if (n->family == AF_INET6) {
d96edb2c 860 log_syntax(unit, LOG_WARNING, filename, line, 0,
2850cd40 861 "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
482e2ac1
TG
862 return 0;
863 }
864
44e7b949 865 r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast);
eb0ea358 866 if (r < 0) {
d96edb2c 867 log_syntax(unit, LOG_WARNING, filename, line, r,
2850cd40 868 "Broadcast is invalid, ignoring assignment: %s", rvalue);
eb0ea358
TG
869 return 0;
870 }
871
44e7b949 872 n->family = AF_INET;
eb0ea358
TG
873 n = NULL;
874
875 return 0;
876}
877
f579559b
TG
878int config_parse_address(const char *unit,
879 const char *filename,
880 unsigned line,
881 const char *section,
71a61510 882 unsigned section_line,
f579559b
TG
883 const char *lvalue,
884 int ltype,
885 const char *rvalue,
886 void *data,
887 void *userdata) {
44e7b949 888
6ae115c1 889 Network *network = userdata;
fcbf4cb7 890 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
44e7b949 891 union in_addr_union buffer;
b7cb4452 892 unsigned char prefixlen;
44e7b949 893 int r, f;
f579559b
TG
894
895 assert(filename);
6ae115c1 896 assert(section);
f579559b
TG
897 assert(lvalue);
898 assert(rvalue);
899 assert(data);
900
92fe133a
TG
901 if (streq(section, "Network")) {
902 /* we are not in an Address section, so treat
903 * this as the special '0' section */
f4859fc7
SS
904 r = address_new_static(network, NULL, 0, &n);
905 } else
906 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
907 if (r == -ENOMEM)
908 return log_oom();
909 if (r < 0) {
910 log_syntax(unit, LOG_WARNING, filename, line, r,
911 "Failed to allocate new address, ignoring assignment: %m");
912 return 0;
913 }
f579559b
TG
914
915 /* Address=address/prefixlen */
0f707207
YW
916 r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_REFUSE, &f, &buffer, &prefixlen);
917 if (r == -ENOANO) {
d96edb2c 918 log_syntax(unit, LOG_WARNING, filename, line, r,
0f707207
YW
919 "An address '%s' is specified without prefix length. "
920 "The behavior of parsing addresses without prefix length will be changed in the future release. "
921 "Please specify prefix length explicitly.", rvalue);
922
923 r = in_addr_prefix_from_string_auto_internal(rvalue, PREFIXLEN_LEGACY, &f, &buffer, &prefixlen);
924 }
f579559b 925 if (r < 0) {
d96edb2c 926 log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid address '%s', ignoring assignment: %m", rvalue);
f579559b
TG
927 return 0;
928 }
929
44e7b949 930 if (n->family != AF_UNSPEC && f != n->family) {
d96edb2c 931 log_syntax(unit, LOG_WARNING, filename, line, 0, "Address is incompatible, ignoring assignment: %s", rvalue);
44e7b949
LP
932 return 0;
933 }
934
c9207ff3
YW
935 if (in_addr_is_null(f, &buffer)) {
936 /* Will use address from address pool. Note that for ipv6 case, prefix of the address
937 * pool is 8, but 40 bit is used by the global ID and 16 bit by the subnet ID. So,
938 * let's limit the prefix length to 64 or larger. See RFC4193. */
939 if ((f == AF_INET && prefixlen < 8) ||
940 (f == AF_INET6 && prefixlen < 64)) {
d96edb2c 941 log_syntax(unit, LOG_WARNING, filename, line, 0,
c9207ff3
YW
942 "Null address with invalid prefixlen='%u', ignoring assignment: %s",
943 prefixlen, rvalue);
944 return 0;
945 }
946 }
947
44e7b949 948 n->family = f;
b7cb4452 949 n->prefixlen = prefixlen;
44e7b949
LP
950
951 if (streq(lvalue, "Address"))
952 n->in_addr = buffer;
953 else
954 n->in_addr_peer = buffer;
955
3681d639 956 if (n->family == AF_INET && n->broadcast.s_addr == 0 && n->prefixlen <= 30)
fe2e4b69 957 n->broadcast.s_addr = n->in_addr.in.s_addr | htobe32(0xfffffffflu >> n->prefixlen);
eb0ea358 958
f579559b
TG
959 n = NULL;
960
961 return 0;
962}
6ae115c1 963
d31645ad
LP
964int config_parse_label(
965 const char *unit,
6ae115c1
TG
966 const char *filename,
967 unsigned line,
968 const char *section,
969 unsigned section_line,
970 const char *lvalue,
971 int ltype,
972 const char *rvalue,
973 void *data,
974 void *userdata) {
d31645ad 975
fcbf4cb7 976 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
d31645ad 977 Network *network = userdata;
6ae115c1
TG
978 int r;
979
980 assert(filename);
981 assert(section);
982 assert(lvalue);
983 assert(rvalue);
984 assert(data);
985
f4859fc7 986 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
987 if (r == -ENOMEM)
988 return log_oom();
989 if (r < 0) {
990 log_syntax(unit, LOG_WARNING, filename, line, r,
991 "Failed to allocate new address, ignoring assignment: %m");
992 return 0;
993 }
6ae115c1 994
a87d19fe 995 if (!address_label_valid(rvalue)) {
d96edb2c 996 log_syntax(unit, LOG_WARNING, filename, line, 0,
2850cd40 997 "Interface label is too long or invalid, ignoring assignment: %s", rvalue);
6ae115c1
TG
998 return 0;
999 }
1000
d31645ad
LP
1001 r = free_and_strdup(&n->label, rvalue);
1002 if (r < 0)
1003 return log_oom();
6ae115c1
TG
1004
1005 n = NULL;
6ae115c1
TG
1006 return 0;
1007}
ce6c77eb 1008
b5834a0b
SS
1009int config_parse_lifetime(const char *unit,
1010 const char *filename,
1011 unsigned line,
1012 const char *section,
1013 unsigned section_line,
1014 const char *lvalue,
1015 int ltype,
1016 const char *rvalue,
1017 void *data,
1018 void *userdata) {
1019 Network *network = userdata;
fcbf4cb7 1020 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
d2735796 1021 uint32_t k;
b5834a0b
SS
1022 int r;
1023
1024 assert(filename);
1025 assert(section);
1026 assert(lvalue);
1027 assert(rvalue);
1028 assert(data);
1029
f4859fc7 1030 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
1031 if (r == -ENOMEM)
1032 return log_oom();
1033 if (r < 0) {
1034 log_syntax(unit, LOG_WARNING, filename, line, r,
1035 "Failed to allocate new address, ignoring assignment: %m");
1036 return 0;
1037 }
b5834a0b 1038
10b20e5a
ZJS
1039 /* We accept only "forever", "infinity", empty, or "0". */
1040 if (STR_IN_SET(rvalue, "forever", "infinity", ""))
33680b0a
YW
1041 k = CACHE_INFO_INFINITY_LIFE_TIME;
1042 else if (streq(rvalue, "0"))
1043 k = 0;
1044 else {
d96edb2c 1045 log_syntax(unit, LOG_WARNING, filename, line, 0,
33680b0a 1046 "Invalid PreferredLifetime= value, ignoring: %s", rvalue);
b5834a0b
SS
1047 return 0;
1048 }
1049
33680b0a 1050 n->cinfo.ifa_prefered = k;
d2735796 1051 TAKE_PTR(n);
b5834a0b
SS
1052
1053 return 0;
1054}
1055
e63be084
SS
1056int config_parse_address_flags(const char *unit,
1057 const char *filename,
1058 unsigned line,
1059 const char *section,
1060 unsigned section_line,
1061 const char *lvalue,
1062 int ltype,
1063 const char *rvalue,
1064 void *data,
1065 void *userdata) {
1066 Network *network = userdata;
fcbf4cb7 1067 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
e63be084
SS
1068 int r;
1069
1070 assert(filename);
1071 assert(section);
1072 assert(lvalue);
1073 assert(rvalue);
1074 assert(data);
1075
f4859fc7 1076 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
1077 if (r == -ENOMEM)
1078 return log_oom();
1079 if (r < 0) {
1080 log_syntax(unit, LOG_WARNING, filename, line, r,
1081 "Failed to allocate new address, ignoring assignment: %m");
1082 return 0;
1083 }
e63be084
SS
1084
1085 r = parse_boolean(rvalue);
1086 if (r < 0) {
d96edb2c 1087 log_syntax(unit, LOG_WARNING, filename, line, r,
051e77ca 1088 "Failed to parse %s=, ignoring: %s", lvalue, rvalue);
e63be084
SS
1089 return 0;
1090 }
1091
1092 if (streq(lvalue, "HomeAddress"))
1093 n->home_address = r;
e63be084
SS
1094 else if (streq(lvalue, "ManageTemporaryAddress"))
1095 n->manage_temporary_address = r;
1096 else if (streq(lvalue, "PrefixRoute"))
de697db0
YW
1097 n->prefix_route = !r;
1098 else if (streq(lvalue, "AddPrefixRoute"))
e63be084
SS
1099 n->prefix_route = r;
1100 else if (streq(lvalue, "AutoJoin"))
1101 n->autojoin = r;
2850cd40
YW
1102 else
1103 assert_not_reached("Invalid address flag type.");
e63be084 1104
4aa4c4b0 1105 n = NULL;
e63be084
SS
1106 return 0;
1107}
1108
2959fb07
SS
1109int config_parse_address_scope(const char *unit,
1110 const char *filename,
1111 unsigned line,
1112 const char *section,
1113 unsigned section_line,
1114 const char *lvalue,
1115 int ltype,
1116 const char *rvalue,
1117 void *data,
1118 void *userdata) {
1119 Network *network = userdata;
fcbf4cb7 1120 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
2959fb07
SS
1121 int r;
1122
1123 assert(filename);
1124 assert(section);
1125 assert(lvalue);
1126 assert(rvalue);
1127 assert(data);
1128
1129 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
1130 if (r == -ENOMEM)
1131 return log_oom();
1132 if (r < 0) {
1133 log_syntax(unit, LOG_WARNING, filename, line, r,
1134 "Failed to allocate new address, ignoring assignment: %m");
1135 return 0;
1136 }
2959fb07
SS
1137
1138 if (streq(rvalue, "host"))
1139 n->scope = RT_SCOPE_HOST;
1140 else if (streq(rvalue, "link"))
1141 n->scope = RT_SCOPE_LINK;
1142 else if (streq(rvalue, "global"))
1143 n->scope = RT_SCOPE_UNIVERSE;
1144 else {
1145 r = safe_atou8(rvalue , &n->scope);
1146 if (r < 0) {
d96edb2c 1147 log_syntax(unit, LOG_WARNING, filename, line, r,
2850cd40 1148 "Could not parse address scope \"%s\", ignoring assignment: %m", rvalue);
2959fb07
SS
1149 return 0;
1150 }
1151 }
1152
07336a06 1153 n->scope_set = true;
2959fb07 1154 n = NULL;
2959fb07
SS
1155 return 0;
1156}
1157
051e77ca
SS
1158int config_parse_duplicate_address_detection(
1159 const char *unit,
1160 const char *filename,
1161 unsigned line,
1162 const char *section,
1163 unsigned section_line,
1164 const char *lvalue,
1165 int ltype,
1166 const char *rvalue,
1167 void *data,
1168 void *userdata) {
1169 Network *network = userdata;
1170 _cleanup_(address_free_or_set_invalidp) Address *n = NULL;
1171 AddressFamily a;
1172 int r;
1173
1174 assert(filename);
1175 assert(section);
1176 assert(lvalue);
1177 assert(rvalue);
1178 assert(data);
1179
1180 r = address_new_static(network, filename, section_line, &n);
d96edb2c
YW
1181 if (r == -ENOMEM)
1182 return log_oom();
1183 if (r < 0) {
1184 log_syntax(unit, LOG_WARNING, filename, line, r,
1185 "Failed to allocate new address, ignoring assignment: %m");
1186 return 0;
1187 }
051e77ca
SS
1188
1189 r = parse_boolean(rvalue);
1190 if (r >= 0) {
1191 log_syntax(unit, LOG_WARNING, filename, line, 0,
1192 "For historical reasons, %s=%s means %s=%s. "
1193 "Please use 'both', 'ipv4', 'ipv6' or 'none' instead.",
1194 lvalue, rvalue, lvalue, r ? "none" : "both");
1195 n->duplicate_address_detection = r ? ADDRESS_FAMILY_NO : ADDRESS_FAMILY_YES;
1196 n = NULL;
1197 return 0;
1198 }
1199
1200 a = duplicate_address_detection_address_family_from_string(rvalue);
1201 if (a < 0) {
d96edb2c 1202 log_syntax(unit, LOG_WARNING, filename, line, SYNTHETIC_ERRNO(EINVAL),
051e77ca
SS
1203 "Failed to parse %s=, ignoring: %s", lvalue, rvalue);
1204 return 0;
1205 }
1206
1207 n->duplicate_address_detection = a;
1208 n = NULL;
1209 return 0;
1210}
1211
ce6c77eb
TG
1212bool address_is_ready(const Address *a) {
1213 assert(a);
1214
ce158189 1215 return !(a->flags & IFA_F_TENTATIVE);
ce6c77eb 1216}
fcbf4cb7
YW
1217
1218int address_section_verify(Address *address) {
1219 if (section_is_invalid(address->section))
1220 return -EINVAL;
1221
1222 if (address->family == AF_UNSPEC) {
1223 assert(address->section);
1224
1225 return log_warning_errno(SYNTHETIC_ERRNO(EINVAL),
1226 "%s: Address section without Address= field configured. "
1227 "Ignoring [Address] section from line %u.",
1228 address->section->filename, address->section->line);
1229 }
1230
07336a06
YW
1231 if (!address->scope_set && in_addr_is_localhost(address->family, &address->in_addr) > 0)
1232 address->scope = RT_SCOPE_HOST;
1233
fcbf4cb7
YW
1234 return 0;
1235}