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