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