]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-manager.c
Merge pull request #113 from mezcalero/address-family
[thirdparty/systemd.git] / src / network / networkd-manager.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/socket.h>
23 #include <linux/if.h>
24
25 #include "conf-parser.h"
26 #include "path-util.h"
27 #include "networkd.h"
28 #include "networkd-netdev.h"
29 #include "networkd-link.h"
30 #include "libudev-private.h"
31 #include "udev-util.h"
32 #include "rtnl-util.h"
33 #include "bus-util.h"
34 #include "def.h"
35 #include "virt.h"
36
37 #include "sd-rtnl.h"
38 #include "sd-daemon.h"
39
40 /* use 8 MB for receive socket kernel queue. */
41 #define RCVBUF_SIZE (8*1024*1024)
42
43 const char* const network_dirs[] = {
44 "/etc/systemd/network",
45 "/run/systemd/network",
46 "/usr/lib/systemd/network",
47 #ifdef HAVE_SPLIT_USR
48 "/lib/systemd/network",
49 #endif
50 NULL};
51
52 static int setup_default_address_pool(Manager *m) {
53 AddressPool *p;
54 int r;
55
56 assert(m);
57
58 /* Add in the well-known private address ranges. */
59
60 r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7);
61 if (r < 0)
62 return r;
63
64 r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16);
65 if (r < 0)
66 return r;
67
68 r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12);
69 if (r < 0)
70 return r;
71
72 r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8);
73 if (r < 0)
74 return r;
75
76 return 0;
77 }
78
79 static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) {
80 Manager *m = userdata;
81
82 assert(s);
83 assert(m);
84
85 m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source);
86
87 manager_connect_bus(m);
88
89 return 0;
90 }
91
92 static int manager_reset_all(Manager *m) {
93 Link *link;
94 Iterator i;
95 int r;
96
97 assert(m);
98
99 HASHMAP_FOREACH(link, m->links, i) {
100 r = link_carrier_reset(link);
101 if (r < 0)
102 log_link_warning_errno(link, r, "could not reset carrier: %m");
103 }
104
105 return 0;
106 }
107
108 static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
109 Manager *m = userdata;
110 int b, r;
111
112 assert(message);
113
114 r = sd_bus_message_read(message, "b", &b);
115 if (r < 0) {
116 log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m");
117 return 0;
118 }
119
120 if (b)
121 return 0;
122
123 log_debug("Coming back from suspend, resetting all connections...");
124
125 manager_reset_all(m);
126
127 return 0;
128 }
129
130 int manager_connect_bus(Manager *m) {
131 int r;
132
133 assert(m);
134
135 r = sd_bus_default_system(&m->bus);
136 if (r == -ENOENT) {
137 /* We failed to connect? Yuck, we must be in early
138 * boot. Let's try in 5s again. As soon as we have
139 * kdbus we can stop doing this... */
140
141 log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m");
142
143 r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m);
144 if (r < 0)
145 return log_error_errno(r, "Failed to install bus reconnect time event: %m");
146
147 return 0;
148 } if (r < 0)
149 return r;
150
151 r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
152 "type='signal',"
153 "sender='org.freedesktop.login1',"
154 "interface='org.freedesktop.login1.Manager',"
155 "member='PrepareForSleep',"
156 "path='/org/freedesktop/login1'",
157 match_prepare_for_sleep,
158 m);
159 if (r < 0)
160 return log_error_errno(r, "Failed to add match for PrepareForSleep: %m");
161
162 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
163 if (r < 0)
164 return log_error_errno(r, "Failed to add manager object vtable: %m");
165
166 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
167 if (r < 0)
168 return log_error_errno(r, "Failed to add link object vtable: %m");
169
170 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
171 if (r < 0)
172 return log_error_errno(r, "Failed to add link enumerator: %m");
173
174 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
175 if (r < 0)
176 return log_error_errno(r, "Failed to add network object vtable: %m");
177
178 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
179 if (r < 0)
180 return log_error_errno(r, "Failed to add network enumerator: %m");
181
182 r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0);
183 if (r < 0)
184 return log_error_errno(r, "Failed to register name: %m");
185
186 r = sd_bus_attach_event(m->bus, m->event, 0);
187 if (r < 0)
188 return log_error_errno(r, "Failed to attach bus to event loop: %m");
189
190 return 0;
191 }
192
193 static int manager_udev_process_link(Manager *m, struct udev_device *device) {
194 Link *link = NULL;
195 int r, ifindex;
196
197 assert(m);
198 assert(device);
199
200 if (!streq_ptr(udev_device_get_action(device), "add"))
201 return 0;
202
203 ifindex = udev_device_get_ifindex(device);
204 if (ifindex <= 0) {
205 log_debug("ignoring udev ADD event for device with invalid ifindex");
206 return 0;
207 }
208
209 r = link_get(m, ifindex, &link);
210 if (r == -ENODEV)
211 return 0;
212 else if (r < 0)
213 return r;
214
215 r = link_initialized(link, device);
216 if (r < 0)
217 return r;
218
219 return 0;
220 }
221
222 static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
223 Manager *m = userdata;
224 struct udev_monitor *monitor = m->udev_monitor;
225 _cleanup_udev_device_unref_ struct udev_device *device = NULL;
226
227 device = udev_monitor_receive_device(monitor);
228 if (!device)
229 return -ENOMEM;
230
231 manager_udev_process_link(m, device);
232 return 0;
233 }
234
235 static int manager_connect_udev(Manager *m) {
236 int r;
237
238 /* udev does not initialize devices inside containers,
239 * so we rely on them being already initialized before
240 * entering the container */
241 if (detect_container(NULL) > 0)
242 return 0;
243
244 m->udev = udev_new();
245 if (!m->udev)
246 return -ENOMEM;
247
248 m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
249 if (!m->udev_monitor)
250 return -ENOMEM;
251
252 r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL);
253 if (r < 0)
254 return log_error_errno(r, "Could not add udev monitor filter: %m");
255
256 r = udev_monitor_enable_receiving(m->udev_monitor);
257 if (r < 0) {
258 log_error("Could not enable udev monitor");
259 return r;
260 }
261
262 r = sd_event_add_io(m->event,
263 &m->udev_event_source,
264 udev_monitor_get_fd(m->udev_monitor),
265 EPOLLIN, manager_dispatch_link_udev,
266 m);
267 if (r < 0)
268 return r;
269
270 r = sd_event_source_set_description(m->udev_event_source, "networkd-udev");
271 if (r < 0)
272 return r;
273
274 return 0;
275 }
276
277 static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, void *userdata) {
278 Manager *m = userdata;
279 Link *link = NULL;
280 NetDev *netdev = NULL;
281 uint16_t type;
282 const char *name;
283 int r, ifindex;
284
285 assert(rtnl);
286 assert(message);
287 assert(m);
288
289 if (sd_rtnl_message_is_error(message)) {
290 r = sd_rtnl_message_get_errno(message);
291 if (r < 0)
292 log_warning_errno(r, "rtnl: could not receive link: %m");
293
294 return 0;
295 }
296
297 r = sd_rtnl_message_get_type(message, &type);
298 if (r < 0) {
299 log_warning_errno(r, "rtnl: could not get message type: %m");
300 return 0;
301 } else if (type != RTM_NEWLINK && type != RTM_DELLINK) {
302 log_warning("rtnl: received unexpected message type when processing link");
303 return 0;
304 }
305
306 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
307 if (r < 0) {
308 log_warning_errno(r, "rtnl: could not get ifindex from link: %m");
309 return 0;
310 } else if (ifindex <= 0) {
311 log_warning("rtnl: received link message with invalid ifindex: %d", ifindex);
312 return 0;
313 } else
314 link_get(m, ifindex, &link);
315
316 r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &name);
317 if (r < 0) {
318 log_warning_errno(r, "rtnl: received link message without ifname: %m");
319 return 0;
320 } else
321 netdev_get(m, name, &netdev);
322
323 switch (type) {
324 case RTM_NEWLINK:
325 if (!link) {
326 /* link is new, so add it */
327 r = link_add(m, message, &link);
328 if (r < 0) {
329 log_warning_errno(r, "could not add new link: %m");
330 return 0;
331 }
332 }
333
334 if (netdev) {
335 /* netdev exists, so make sure the ifindex matches */
336 r = netdev_set_ifindex(netdev, message);
337 if (r < 0) {
338 log_warning_errno(r, "could not set ifindex on netdev: %m");
339 return 0;
340 }
341 }
342
343 r = link_update(link, message);
344 if (r < 0)
345 return 0;
346
347 break;
348
349 case RTM_DELLINK:
350 link_drop(link);
351 netdev_drop(netdev);
352
353 break;
354
355 default:
356 assert_not_reached("Received invalid RTNL message type.");
357 }
358
359 return 1;
360 }
361
362 static int systemd_netlink_fd(void) {
363 int n, fd, rtnl_fd = -EINVAL;
364
365 n = sd_listen_fds(true);
366 if (n <= 0)
367 return -EINVAL;
368
369 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
370 if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
371 if (rtnl_fd >= 0)
372 return -EINVAL;
373
374 rtnl_fd = fd;
375 }
376 }
377
378 return rtnl_fd;
379 }
380
381 static int manager_connect_rtnl(Manager *m) {
382 int fd, r;
383
384 assert(m);
385
386 fd = systemd_netlink_fd();
387 if (fd < 0)
388 r = sd_rtnl_open(&m->rtnl, 3, RTNLGRP_LINK, RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR);
389 else
390 r = sd_rtnl_open_fd(&m->rtnl, fd, 0);
391 if (r < 0)
392 return r;
393
394 r = sd_rtnl_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
395 if (r < 0)
396 return r;
397
398 r = sd_rtnl_attach_event(m->rtnl, m->event, 0);
399 if (r < 0)
400 return r;
401
402 r = sd_rtnl_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m);
403 if (r < 0)
404 return r;
405
406 r = sd_rtnl_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m);
407 if (r < 0)
408 return r;
409
410 r = sd_rtnl_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
411 if (r < 0)
412 return r;
413
414 r = sd_rtnl_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
415 if (r < 0)
416 return r;
417
418 return 0;
419 }
420
421 int manager_new(Manager **ret) {
422 _cleanup_manager_free_ Manager *m = NULL;
423 int r;
424
425 m = new0(Manager, 1);
426 if (!m)
427 return -ENOMEM;
428
429 m->state_file = strdup("/run/systemd/netif/state");
430 if (!m->state_file)
431 return -ENOMEM;
432
433 r = sd_event_default(&m->event);
434 if (r < 0)
435 return r;
436
437 sd_event_set_watchdog(m->event, true);
438
439 sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
440 sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL);
441
442 r = manager_connect_rtnl(m);
443 if (r < 0)
444 return r;
445
446 r = manager_connect_udev(m);
447 if (r < 0)
448 return r;
449
450 m->netdevs = hashmap_new(&string_hash_ops);
451 if (!m->netdevs)
452 return -ENOMEM;
453
454 LIST_HEAD_INIT(m->networks);
455
456 r = setup_default_address_pool(m);
457 if (r < 0)
458 return r;
459
460 *ret = m;
461 m = NULL;
462
463 return 0;
464 }
465
466 void manager_free(Manager *m) {
467 Network *network;
468 NetDev *netdev;
469 Link *link;
470 AddressPool *pool;
471
472 if (!m)
473 return;
474
475 free(m->state_file);
476
477 udev_monitor_unref(m->udev_monitor);
478 udev_unref(m->udev);
479 sd_bus_unref(m->bus);
480 sd_bus_slot_unref(m->prepare_for_sleep_slot);
481 sd_event_source_unref(m->udev_event_source);
482 sd_event_source_unref(m->bus_retry_event_source);
483 sd_event_unref(m->event);
484
485 while ((link = hashmap_first(m->links)))
486 link_unref(link);
487 hashmap_free(m->links);
488
489 while ((network = m->networks))
490 network_free(network);
491
492 hashmap_free(m->networks_by_name);
493
494 while ((netdev = hashmap_first(m->netdevs)))
495 netdev_unref(netdev);
496 hashmap_free(m->netdevs);
497
498 while ((pool = m->address_pools))
499 address_pool_free(pool);
500
501 sd_rtnl_unref(m->rtnl);
502
503 free(m);
504 }
505
506 static bool manager_check_idle(void *userdata) {
507 Manager *m = userdata;
508 Link *link;
509 Iterator i;
510
511 assert(m);
512
513 HASHMAP_FOREACH(link, m->links, i) {
514 /* we are not woken on udev activity, so let's just wait for the
515 * pending udev event */
516 if (link->state == LINK_STATE_PENDING)
517 return false;
518
519 if (!link->network)
520 continue;
521
522 /* we are not woken on netork activity, so let's stay around */
523 if (link_lldp_enabled(link) ||
524 link_ipv4ll_enabled(link) ||
525 link_dhcp4_server_enabled(link) ||
526 link_dhcp4_enabled(link) ||
527 link_dhcp6_enabled(link))
528 return false;
529 }
530
531 return true;
532 }
533
534 int manager_run(Manager *m) {
535 assert(m);
536
537 if (m->bus)
538 return bus_event_loop_with_idle(
539 m->event,
540 m->bus,
541 "org.freedesktop.network1",
542 DEFAULT_EXIT_USEC,
543 manager_check_idle,
544 m);
545 else
546 /* failed to connect to the bus, so we lose exit-on-idle logic,
547 this should not happen except if dbus is not around at all */
548 return sd_event_loop(m->event);
549 }
550
551 int manager_load_config(Manager *m) {
552 int r;
553
554 /* update timestamp */
555 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
556
557 r = netdev_load(m);
558 if (r < 0)
559 return r;
560
561 r = network_load(m);
562 if (r < 0)
563 return r;
564
565 return 0;
566 }
567
568 bool manager_should_reload(Manager *m) {
569 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
570 }
571
572 int manager_rtnl_enumerate_links(Manager *m) {
573 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
574 sd_rtnl_message *link;
575 int r;
576
577 assert(m);
578 assert(m->rtnl);
579
580 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
581 if (r < 0)
582 return r;
583
584 r = sd_rtnl_message_request_dump(req, true);
585 if (r < 0)
586 return r;
587
588 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
589 if (r < 0)
590 return r;
591
592 for (link = reply; link; link = sd_rtnl_message_next(link)) {
593 int k;
594
595 m->enumerating = true;
596
597 k = manager_rtnl_process_link(m->rtnl, link, m);
598 if (k < 0)
599 r = k;
600
601 m->enumerating = false;
602 }
603
604 return r;
605 }
606
607 int manager_rtnl_enumerate_addresses(Manager *m) {
608 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
609 sd_rtnl_message *addr;
610 int r;
611
612 assert(m);
613 assert(m->rtnl);
614
615 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
616 if (r < 0)
617 return r;
618
619 r = sd_rtnl_message_request_dump(req, true);
620 if (r < 0)
621 return r;
622
623 r = sd_rtnl_call(m->rtnl, req, 0, &reply);
624 if (r < 0)
625 return r;
626
627 for (addr = reply; addr; addr = sd_rtnl_message_next(addr)) {
628 int k;
629
630 m->enumerating = true;
631
632 k = link_rtnl_process_address(m->rtnl, addr, m);
633 if (k < 0)
634 r = k;
635
636 m->enumerating = false;
637 }
638
639 return r;
640 }
641
642 static int set_put_in_addr(Set *s, const struct in_addr *address) {
643 char *p;
644 int r;
645
646 assert(s);
647
648 r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
649 if (r < 0)
650 return r;
651
652 r = set_consume(s, p);
653 if (r == -EEXIST)
654 return 0;
655
656 return r;
657 }
658
659 static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
660 int r, i, c = 0;
661
662 assert(s);
663 assert(n <= 0 || addresses);
664
665 for (i = 0; i < n; i++) {
666 r = set_put_in_addr(s, addresses+i);
667 if (r < 0)
668 return r;
669
670 c += r;
671 }
672
673 return c;
674 }
675
676 static void print_string_set(FILE *f, const char *field, Set *s) {
677 bool space = false;
678 Iterator i;
679 char *p;
680
681 if (set_isempty(s))
682 return;
683
684 fputs(field, f);
685
686 SET_FOREACH(p, s, i) {
687 if (space)
688 fputc(' ', f);
689 fputs(p, f);
690 space = true;
691 }
692 fputc('\n', f);
693 }
694
695 int manager_save(Manager *m) {
696 _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
697 Link *link;
698 Iterator i;
699 _cleanup_free_ char *temp_path = NULL;
700 _cleanup_fclose_ FILE *f = NULL;
701 LinkOperationalState operstate = LINK_OPERSTATE_OFF;
702 const char *operstate_str;
703 int r;
704
705 assert(m);
706 assert(m->state_file);
707
708 /* We add all NTP and DNS server to a set, to filter out duplicates */
709 dns = set_new(&string_hash_ops);
710 if (!dns)
711 return -ENOMEM;
712
713 ntp = set_new(&string_hash_ops);
714 if (!ntp)
715 return -ENOMEM;
716
717 domains = set_new(&string_hash_ops);
718 if (!domains)
719 return -ENOMEM;
720
721 HASHMAP_FOREACH(link, m->links, i) {
722 if (link->flags & IFF_LOOPBACK)
723 continue;
724
725 if (link->operstate > operstate)
726 operstate = link->operstate;
727
728 if (!link->network)
729 continue;
730
731 /* First add the static configured entries */
732 r = set_put_strdupv(dns, link->network->dns);
733 if (r < 0)
734 return r;
735
736 r = set_put_strdupv(ntp, link->network->ntp);
737 if (r < 0)
738 return r;
739
740 r = set_put_strdupv(domains, link->network->domains);
741 if (r < 0)
742 return r;
743
744 if (!link->dhcp_lease)
745 continue;
746
747 /* Secondly, add the entries acquired via DHCP */
748 if (link->network->dhcp_dns) {
749 const struct in_addr *addresses;
750
751 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
752 if (r > 0) {
753 r = set_put_in_addrv(dns, addresses, r);
754 if (r < 0)
755 return r;
756 } else if (r < 0 && r != -ENOENT)
757 return r;
758 }
759
760 if (link->network->dhcp_ntp) {
761 const struct in_addr *addresses;
762
763 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
764 if (r > 0) {
765 r = set_put_in_addrv(ntp, addresses, r);
766 if (r < 0)
767 return r;
768 } else if (r < 0 && r != -ENOENT)
769 return r;
770 }
771
772 if (link->network->dhcp_domains) {
773 const char *domainname;
774
775 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
776 if (r >= 0) {
777 r = set_put_strdup(domains, domainname);
778 if (r < 0)
779 return r;
780 } else if (r != -ENOENT)
781 return r;
782 }
783 }
784
785 operstate_str = link_operstate_to_string(operstate);
786 assert(operstate_str);
787
788 r = fopen_temporary(m->state_file, &f, &temp_path);
789 if (r < 0)
790 return r;
791
792 fchmod(fileno(f), 0644);
793
794 fprintf(f,
795 "# This is private data. Do not parse.\n"
796 "OPER_STATE=%s\n", operstate_str);
797
798 print_string_set(f, "DNS=", dns);
799 print_string_set(f, "NTP=", ntp);
800 print_string_set(f, "DOMAINS=", domains);
801
802 r = fflush_and_check(f);
803 if (r < 0)
804 goto fail;
805
806 if (rename(temp_path, m->state_file) < 0) {
807 r = -errno;
808 goto fail;
809 }
810
811 if (m->operational_state != operstate) {
812 m->operational_state = operstate;
813 r = manager_send_changed(m, "OperationalState", NULL);
814 if (r < 0)
815 log_error_errno(r, "Could not emit changed OperationalState: %m");
816 }
817
818 return 0;
819
820 fail:
821 log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
822 unlink(m->state_file);
823 unlink(temp_path);
824 return r;
825 }
826
827 int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
828 AddressPool *p;
829 int r;
830
831 assert(m);
832 assert(prefixlen > 0);
833 assert(found);
834
835 LIST_FOREACH(address_pools, p, m->address_pools) {
836 if (p->family != family)
837 continue;
838
839 r = address_pool_acquire(p, prefixlen, found);
840 if (r != 0)
841 return r;
842 }
843
844 return 0;
845 }
846
847 const char *address_family_boolean_to_string(AddressFamilyBoolean b) {
848 if (b == ADDRESS_FAMILY_YES ||
849 b == ADDRESS_FAMILY_NO)
850 return yes_no(b == ADDRESS_FAMILY_YES);
851
852 if (b == ADDRESS_FAMILY_IPV4)
853 return "ipv4";
854 if (b == ADDRESS_FAMILY_IPV6)
855 return "ipv6";
856
857 return NULL;
858 }
859
860 AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
861 int r;
862
863 /* Make this a true superset of a boolean */
864
865 r = parse_boolean(s);
866 if (r > 0)
867 return ADDRESS_FAMILY_YES;
868 if (r == 0)
869 return ADDRESS_FAMILY_NO;
870
871 if (streq(s, "ipv4"))
872 return ADDRESS_FAMILY_IPV4;
873 if (streq(s, "ipv6"))
874 return ADDRESS_FAMILY_IPV6;
875
876 return _ADDRESS_FAMILY_BOOLEAN_INVALID;
877 }
878
879 DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");