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