]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/network/networkd-manager.c
networkd: propagate DNS/NTP server from uplink to dhcp server
[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(NULL) > 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 udev_monitor_unref(m->udev_monitor);
481 udev_unref(m->udev);
482 sd_bus_unref(m->bus);
483 sd_bus_slot_unref(m->prepare_for_sleep_slot);
484 sd_event_source_unref(m->udev_event_source);
485 sd_event_source_unref(m->bus_retry_event_source);
486 sd_event_unref(m->event);
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
506 free(m);
507 }
508
509 static bool manager_check_idle(void *userdata) {
510 Manager *m = userdata;
511 Link *link;
512 Iterator i;
513
514 assert(m);
515
516 HASHMAP_FOREACH(link, m->links, i) {
517 /* we are not woken on udev activity, so let's just wait for the
518 * pending udev event */
519 if (link->state == LINK_STATE_PENDING)
520 return false;
521
522 if (!link->network)
523 continue;
524
525 /* we are not woken on netork activity, so let's stay around */
526 if (link_lldp_enabled(link) ||
527 link_ipv4ll_enabled(link) ||
528 link_dhcp4_server_enabled(link) ||
529 link_dhcp4_enabled(link) ||
530 link_dhcp6_enabled(link))
531 return false;
532 }
533
534 return true;
535 }
536
537 int manager_run(Manager *m) {
538 assert(m);
539
540 if (m->bus)
541 return bus_event_loop_with_idle(
542 m->event,
543 m->bus,
544 "org.freedesktop.network1",
545 DEFAULT_EXIT_USEC,
546 manager_check_idle,
547 m);
548 else
549 /* failed to connect to the bus, so we lose exit-on-idle logic,
550 this should not happen except if dbus is not around at all */
551 return sd_event_loop(m->event);
552 }
553
554 int manager_load_config(Manager *m) {
555 int r;
556
557 /* update timestamp */
558 paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true);
559
560 r = netdev_load(m);
561 if (r < 0)
562 return r;
563
564 r = network_load(m);
565 if (r < 0)
566 return r;
567
568 return 0;
569 }
570
571 bool manager_should_reload(Manager *m) {
572 return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false);
573 }
574
575 int manager_rtnl_enumerate_links(Manager *m) {
576 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
577 sd_netlink_message *link;
578 int r;
579
580 assert(m);
581 assert(m->rtnl);
582
583 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
584 if (r < 0)
585 return r;
586
587 r = sd_netlink_message_request_dump(req, true);
588 if (r < 0)
589 return r;
590
591 r = sd_netlink_call(m->rtnl, req, 0, &reply);
592 if (r < 0)
593 return r;
594
595 for (link = reply; link; link = sd_netlink_message_next(link)) {
596 int k;
597
598 m->enumerating = true;
599
600 k = manager_rtnl_process_link(m->rtnl, link, m);
601 if (k < 0)
602 r = k;
603
604 m->enumerating = false;
605 }
606
607 return r;
608 }
609
610 int manager_rtnl_enumerate_addresses(Manager *m) {
611 _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
612 sd_netlink_message *addr;
613 int r;
614
615 assert(m);
616 assert(m->rtnl);
617
618 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
619 if (r < 0)
620 return r;
621
622 r = sd_netlink_message_request_dump(req, true);
623 if (r < 0)
624 return r;
625
626 r = sd_netlink_call(m->rtnl, req, 0, &reply);
627 if (r < 0)
628 return r;
629
630 for (addr = reply; addr; addr = sd_netlink_message_next(addr)) {
631 int k;
632
633 m->enumerating = true;
634
635 k = link_rtnl_process_address(m->rtnl, addr, m);
636 if (k < 0)
637 r = k;
638
639 m->enumerating = false;
640 }
641
642 return r;
643 }
644
645 static int set_put_in_addr(Set *s, const struct in_addr *address) {
646 char *p;
647 int r;
648
649 assert(s);
650
651 r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
652 if (r < 0)
653 return r;
654
655 r = set_consume(s, p);
656 if (r == -EEXIST)
657 return 0;
658
659 return r;
660 }
661
662 static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
663 int r, i, c = 0;
664
665 assert(s);
666 assert(n <= 0 || addresses);
667
668 for (i = 0; i < n; i++) {
669 r = set_put_in_addr(s, addresses+i);
670 if (r < 0)
671 return r;
672
673 c += r;
674 }
675
676 return c;
677 }
678
679 static void print_string_set(FILE *f, const char *field, Set *s) {
680 bool space = false;
681 Iterator i;
682 char *p;
683
684 if (set_isempty(s))
685 return;
686
687 fputs(field, f);
688
689 SET_FOREACH(p, s, i) {
690 if (space)
691 fputc(' ', f);
692 fputs(p, f);
693 space = true;
694 }
695 fputc('\n', f);
696 }
697
698 int manager_save(Manager *m) {
699 _cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
700 Link *link;
701 Iterator i;
702 _cleanup_free_ char *temp_path = NULL;
703 _cleanup_fclose_ FILE *f = NULL;
704 LinkOperationalState operstate = LINK_OPERSTATE_OFF;
705 const char *operstate_str;
706 int r;
707
708 assert(m);
709 assert(m->state_file);
710
711 /* We add all NTP and DNS server to a set, to filter out duplicates */
712 dns = set_new(&string_hash_ops);
713 if (!dns)
714 return -ENOMEM;
715
716 ntp = set_new(&string_hash_ops);
717 if (!ntp)
718 return -ENOMEM;
719
720 domains = set_new(&string_hash_ops);
721 if (!domains)
722 return -ENOMEM;
723
724 HASHMAP_FOREACH(link, m->links, i) {
725 if (link->flags & IFF_LOOPBACK)
726 continue;
727
728 if (link->operstate > operstate)
729 operstate = link->operstate;
730
731 if (!link->network)
732 continue;
733
734 /* First add the static configured entries */
735 r = set_put_strdupv(dns, link->network->dns);
736 if (r < 0)
737 return r;
738
739 r = set_put_strdupv(ntp, link->network->ntp);
740 if (r < 0)
741 return r;
742
743 r = set_put_strdupv(domains, link->network->domains);
744 if (r < 0)
745 return r;
746
747 if (!link->dhcp_lease)
748 continue;
749
750 /* Secondly, add the entries acquired via DHCP */
751 if (link->network->dhcp_dns) {
752 const struct in_addr *addresses;
753
754 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
755 if (r > 0) {
756 r = set_put_in_addrv(dns, addresses, r);
757 if (r < 0)
758 return r;
759 } else if (r < 0 && r != -ENOENT)
760 return r;
761 }
762
763 if (link->network->dhcp_ntp) {
764 const struct in_addr *addresses;
765
766 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
767 if (r > 0) {
768 r = set_put_in_addrv(ntp, addresses, r);
769 if (r < 0)
770 return r;
771 } else if (r < 0 && r != -ENOENT)
772 return r;
773 }
774
775 if (link->network->dhcp_domains) {
776 const char *domainname;
777
778 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
779 if (r >= 0) {
780 r = set_put_strdup(domains, domainname);
781 if (r < 0)
782 return r;
783 } else if (r != -ENOENT)
784 return r;
785 }
786 }
787
788 operstate_str = link_operstate_to_string(operstate);
789 assert(operstate_str);
790
791 r = fopen_temporary(m->state_file, &f, &temp_path);
792 if (r < 0)
793 return r;
794
795 fchmod(fileno(f), 0644);
796
797 fprintf(f,
798 "# This is private data. Do not parse.\n"
799 "OPER_STATE=%s\n", operstate_str);
800
801 print_string_set(f, "DNS=", dns);
802 print_string_set(f, "NTP=", ntp);
803 print_string_set(f, "DOMAINS=", domains);
804
805 r = fflush_and_check(f);
806 if (r < 0)
807 goto fail;
808
809 if (rename(temp_path, m->state_file) < 0) {
810 r = -errno;
811 goto fail;
812 }
813
814 if (m->operational_state != operstate) {
815 m->operational_state = operstate;
816 r = manager_send_changed(m, "OperationalState", NULL);
817 if (r < 0)
818 log_error_errno(r, "Could not emit changed OperationalState: %m");
819 }
820
821 return 0;
822
823 fail:
824 (void) unlink(m->state_file);
825 (void) unlink(temp_path);
826
827 return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
828 }
829
830 int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
831 AddressPool *p;
832 int r;
833
834 assert(m);
835 assert(prefixlen > 0);
836 assert(found);
837
838 LIST_FOREACH(address_pools, p, m->address_pools) {
839 if (p->family != family)
840 continue;
841
842 r = address_pool_acquire(p, prefixlen, found);
843 if (r != 0)
844 return r;
845 }
846
847 return 0;
848 }
849
850 Link* manager_find_uplink(Manager *m, Link *exclude) {
851 _cleanup_free_ struct local_address *gateways = NULL;
852 int n, i;
853
854 assert(m);
855
856 /* Looks for a suitable "uplink", via black magic: an
857 * interface that is up and where the default route with the
858 * highest priority points to. */
859
860 n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways);
861 if (n < 0) {
862 log_warning_errno(n, "Failed to determine list of default gateways: %m");
863 return NULL;
864 }
865
866 for (i = 0; i < n; i++) {
867 Link *link;
868
869 link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex));
870 if (!link) {
871 log_debug("Weird, found a gateway for a link we don't now. Ignoring.");
872 continue;
873 }
874
875 if (link == exclude)
876 continue;
877
878 if (link->operstate < LINK_OPERSTATE_ROUTABLE)
879 continue;
880
881 return link;
882 }
883
884 return NULL;
885 }