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