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