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