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