]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
network: make manager_enumerate_internal() take sd_netlink object
[thirdparty/systemd.git] / src / network / networkd-manager.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
f579559b 2
9aa5d8ba 3#include <netinet/in.h>
091a364c 4#include <sys/socket.h>
9aa5d8ba 5#include <unistd.h>
bbf7c048 6#include <linux/if.h>
bce67bbe 7#include <linux/fib_rules.h>
c16c7808 8#include <linux/nexthop.h>
3bef724f 9
fc2f9534 10#include "sd-daemon.h"
07630cea 11#include "sd-netlink.h"
fc2f9534 12
b5efdb8a 13#include "alloc-util.h"
f63e09ef 14#include "bus-error.h"
ac9f55ed 15#include "bus-log-control-api.h"
269e4d2d 16#include "bus-polkit.h"
a97dcc12 17#include "bus-util.h"
07630cea 18#include "conf-parser.h"
a97dcc12 19#include "def.h"
482d1aeb 20#include "dns-domain.h"
3ffd4af2 21#include "fd-util.h"
0d39fa9c 22#include "fileio.h"
761cf19d 23#include "firewall-util.h"
af664001 24#include "fs-util.h"
4f5f911e 25#include "local-addresses.h"
07630cea 26#include "netlink-util.h"
dc0d4078 27#include "network-internal.h"
bfbf150e 28#include "networkd-address-pool.h"
cf72a786 29#include "networkd-dhcp-server-bus.h"
ca5ad760 30#include "networkd-dhcp6.h"
6a1af3d4 31#include "networkd-link-bus.h"
79a59fa5 32#include "networkd-manager-bus.h"
23f53b99 33#include "networkd-manager.h"
1939ebeb 34#include "networkd-neighbor.h"
ceac2c2b 35#include "networkd-network-bus.h"
75156ccb 36#include "networkd-nexthop.h"
19d9a5ad 37#include "networkd-queue.h"
ca183bf8 38#include "networkd-routing-policy-rule.h"
a879e1a4 39#include "networkd-speed-meter.h"
3b5a4fc6 40#include "networkd-state-file.h"
00616955 41#include "ordered-set.h"
b0c82192 42#include "path-lookup.h"
07630cea 43#include "path-util.h"
92b555aa 44#include "selinux-util.h"
07630cea 45#include "set.h"
ab76be55 46#include "signal-util.h"
d31f33e3 47#include "stat-util.h"
21486d9e 48#include "strv.h"
4b600505 49#include "sysctl-util.h"
e4de7287 50#include "tmpfile-util.h"
505f8da7 51
48d0248e
YW
52/* use 128 MB for receive socket kernel queue. */
53#define RCVBUF_SIZE (128*1024*1024)
be660c37 54
9c0a72f9
TG
55static int manager_reset_all(Manager *m) {
56 Link *link;
9c0a72f9
TG
57 int r;
58
59 assert(m);
60
6eab614d 61 HASHMAP_FOREACH(link, m->links_by_index) {
d09a179e 62 r = link_reconfigure_after_sleep(link);
f0269653 63 if (r < 0) {
d09a179e 64 log_link_warning_errno(link, r, "Failed to reconfigure interface: %m");
f0269653
YW
65 link_enter_failed(link);
66 }
9c0a72f9
TG
67 }
68
69 return 0;
70}
71
19070062 72static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
9c0a72f9
TG
73 Manager *m = userdata;
74 int b, r;
75
19070062 76 assert(message);
d7afd945 77 assert(m);
9c0a72f9
TG
78
79 r = sd_bus_message_read(message, "b", &b);
80 if (r < 0) {
d67b1d18 81 bus_log_parse_error(r);
9c0a72f9
TG
82 return 0;
83 }
84
85 if (b)
86 return 0;
87
88 log_debug("Coming back from suspend, resetting all connections...");
89
e1694a75 90 (void) manager_reset_all(m);
9c0a72f9
TG
91
92 return 0;
93}
94
d7afd945
LP
95static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
96 Manager *m = userdata;
9c0a72f9 97
d7afd945 98 assert(message);
9c0a72f9
TG
99 assert(m);
100
d7afd945
LP
101 /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
102 if (m->dynamic_hostname)
103 (void) manager_set_hostname(m, m->dynamic_hostname);
104 if (m->dynamic_timezone)
105 (void) manager_set_timezone(m, m->dynamic_timezone);
ccffa166 106 if (m->product_uuid_requested)
4e26a5ba 107 (void) manager_request_product_uuid(m);
9c0a72f9 108
d7afd945
LP
109 return 0;
110}
9c0a72f9 111
96243149 112static int manager_connect_bus(Manager *m) {
d7afd945
LP
113 int r;
114
115 assert(m);
96243149 116 assert(!m->bus);
7d6884b6 117
621e4509 118 r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network");
9c0a72f9 119 if (r < 0)
d7afd945 120 return log_error_errno(r, "Failed to connect to bus: %m");
9c0a72f9 121
e331e246
TG
122 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
123 if (r < 0)
124 return log_error_errno(r, "Failed to add manager object vtable: %m");
125
126 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
127 if (r < 0)
128 return log_error_errno(r, "Failed to add link object vtable: %m");
129
cf72a786
MAL
130 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.DHCPServer", dhcp_server_vtable, link_object_find, m);
131 if (r < 0)
132 return log_error_errno(r, "Failed to add link object vtable: %m");
133
e331e246
TG
134 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
135 if (r < 0)
136 return log_error_errno(r, "Failed to add link enumerator: %m");
3175fcde
TG
137
138 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
139 if (r < 0)
140 return log_error_errno(r, "Failed to add network object vtable: %m");
141
142 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
143 if (r < 0)
144 return log_error_errno(r, "Failed to add network enumerator: %m");
e331e246 145
ac9f55ed
LP
146 r = bus_log_control_api_register(m->bus);
147 if (r < 0)
148 return r;
149
696fc836 150 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL);
e331e246 151 if (r < 0)
0c0b9306 152 return log_error_errno(r, "Failed to request name: %m");
e331e246
TG
153
154 r = sd_bus_attach_event(m->bus, m->event, 0);
155 if (r < 0)
156 return log_error_errno(r, "Failed to attach bus to event loop: %m");
157
d7afd945
LP
158 r = sd_bus_match_signal_async(
159 m->bus,
cad43595 160 NULL,
d7afd945
LP
161 "org.freedesktop.DBus.Local",
162 NULL,
163 "org.freedesktop.DBus.Local",
164 "Connected",
165 on_connected, NULL, m);
166 if (r < 0)
167 return log_error_errno(r, "Failed to request match on Connected signal: %m");
168
169 r = sd_bus_match_signal_async(
170 m->bus,
cad43595 171 NULL,
d7afd945
LP
172 "org.freedesktop.login1",
173 "/org/freedesktop/login1",
174 "org.freedesktop.login1.Manager",
175 "PrepareForSleep",
176 match_prepare_for_sleep, NULL, m);
177 if (r < 0)
178 log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
7901cea1 179
9c0a72f9
TG
180 return 0;
181}
182
5fae368b
TG
183static int manager_connect_udev(Manager *m) {
184 int r;
f579559b 185
d31f33e3
YW
186 /* udev does not initialize devices inside containers, so we rely on them being already
187 * initialized before entering the container. */
188 if (path_is_read_only_fs("/sys") > 0)
5fae368b 189 return 0;
f579559b 190
d2ebf952 191 r = sd_device_monitor_new(&m->device_monitor);
02b59d57 192 if (r < 0)
d2ebf952 193 return log_error_errno(r, "Failed to initialize device monitor: %m");
02b59d57 194
a725efb0
YW
195 r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
196 if (r < 0)
197 log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
198
d2ebf952
YW
199 r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
200 if (r < 0)
201 return log_error_errno(r, "Could not add device monitor filter: %m");
505f8da7 202
deb2b734 203 r = sd_device_monitor_attach_event(m->device_monitor, m->event);
5fae368b 204 if (r < 0)
d2ebf952 205 return log_error_errno(r, "Failed to attach event to device monitor: %m");
505f8da7 206
deb2b734 207 r = sd_device_monitor_start(m->device_monitor, manager_udev_process_link, m);
505f8da7 208 if (r < 0)
d2ebf952 209 return log_error_errno(r, "Failed to start device monitor: %m");
11a7f229 210
505f8da7
TG
211 return 0;
212}
f579559b 213
5fae368b
TG
214static int systemd_netlink_fd(void) {
215 int n, fd, rtnl_fd = -EINVAL;
216
217 n = sd_listen_fds(true);
218 if (n <= 0)
219 return -EINVAL;
220
24e3ed84 221 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++)
5fae368b
TG
222 if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
223 if (rtnl_fd >= 0)
224 return -EINVAL;
225
226 rtnl_fd = fd;
227 }
5fae368b
TG
228
229 return rtnl_fd;
230}
231
05d0c2e3
JT
232static int manager_connect_genl(Manager *m) {
233 int r;
234
235 assert(m);
236
237 r = sd_genl_socket_open(&m->genl);
238 if (r < 0)
239 return r;
240
241 r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE);
242 if (r < 0)
8c63924c 243 log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m");
05d0c2e3
JT
244
245 r = sd_netlink_attach_event(m->genl, m->event, 0);
246 if (r < 0)
247 return r;
248
249 return 0;
250}
251
5fae368b
TG
252static int manager_connect_rtnl(Manager *m) {
253 int fd, r;
505f8da7
TG
254
255 assert(m);
505f8da7 256
5fae368b
TG
257 fd = systemd_netlink_fd();
258 if (fd < 0)
1c4baffc 259 r = sd_netlink_open(&m->rtnl);
5fae368b 260 else
1c4baffc 261 r = sd_netlink_open_fd(&m->rtnl, fd);
505f8da7
TG
262 if (r < 0)
263 return r;
264
e13af7bd
YW
265 /* Bump receiver buffer, but only if we are not called via socket activation, as in that
266 * case systemd sets the receive buffer size for us, and the value in the .socket unit
267 * should take full effect. */
268 if (fd < 0) {
269 r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
270 if (r < 0)
271 log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m");
272 }
f579559b 273
1c4baffc 274 r = sd_netlink_attach_event(m->rtnl, m->event, 0);
505f8da7
TG
275 if (r < 0)
276 return r;
f579559b 277
8dfed23d 278 r = netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
5fae368b
TG
279 if (r < 0)
280 return r;
505f8da7 281
8dfed23d 282 r = netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
5fae368b
TG
283 if (r < 0)
284 return r;
45af44d4 285
8dfed23d 286 r = netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
5fae368b
TG
287 if (r < 0)
288 return r;
289
8dfed23d 290 r = netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
5fae368b
TG
291 if (r < 0)
292 return r;
293
8dfed23d 294 r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
d1bdafd2
WKI
295 if (r < 0)
296 return r;
297
8dfed23d 298 r = netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
d1bdafd2
WKI
299 if (r < 0)
300 return r;
301
8dfed23d 302 r = netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
1c8e710c
TG
303 if (r < 0)
304 return r;
305
8dfed23d 306 r = netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
1c8e710c
TG
307 if (r < 0)
308 return r;
309
8dfed23d 310 r = netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
bce67bbe
SS
311 if (r < 0)
312 return r;
313
8dfed23d 314 r = netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
bce67bbe
SS
315 if (r < 0)
316 return r;
317
8dfed23d 318 r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
c16c7808
SS
319 if (r < 0)
320 return r;
321
8dfed23d 322 r = netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
c16c7808
SS
323 if (r < 0)
324 return r;
325
5fae368b 326 return 0;
45af44d4 327}
505f8da7 328
84de38c5
TG
329static int manager_dirty_handler(sd_event_source *s, void *userdata) {
330 Manager *m = userdata;
331 Link *link;
d23a66f2 332 int r;
84de38c5
TG
333
334 assert(m);
335
d23a66f2
YW
336 if (m->dirty) {
337 r = manager_save(m);
338 if (r < 0)
339 log_warning_errno(r, "Failed to update state file %s, ignoring: %m", m->state_file);
340 }
84de38c5 341
d23a66f2
YW
342 SET_FOREACH(link, m->dirty_links) {
343 r = link_save_and_clean(link);
344 if (r < 0)
345 log_link_warning_errno(link, r, "Failed to update link state file %s, ignoring: %m", link->state_file);
346 }
84de38c5
TG
347
348 return 1;
349}
350
ab76be55
ZJS
351static int signal_terminate_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
352 Manager *m = userdata;
353
354 assert(m);
355 m->restarting = false;
356
357 log_debug("Terminate operation initiated.");
358
359 return sd_event_exit(sd_event_source_get_event(s), 0);
360}
361
362static int signal_restart_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
363 Manager *m = userdata;
364
365 assert(m);
366 m->restarting = true;
367
368 log_debug("Restart operation initiated.");
369
370 return sd_event_exit(sd_event_source_get_event(s), 0);
371}
372
96243149 373int manager_setup(Manager *m, bool test_mode) {
45af44d4 374 int r;
f579559b 375
96243149 376 assert(m);
5fae368b 377
3534a043
YW
378 r = sd_event_default(&m->event);
379 if (r < 0)
380 return r;
381
ab76be55
ZJS
382 assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0);
383
05e21627 384 (void) sd_event_set_watchdog(m->event, true);
ab76be55
ZJS
385 (void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m);
386 (void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m);
387 (void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m);
5fae368b 388
84de38c5
TG
389 r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m);
390 if (r < 0)
391 return r;
392
19d9a5ad
YW
393 r = sd_event_add_post(m->event, NULL, manager_process_requests, m);
394 if (r < 0)
395 return r;
396
5fae368b 397 r = manager_connect_rtnl(m);
45af44d4
TG
398 if (r < 0)
399 return r;
400
05d0c2e3
JT
401 r = manager_connect_genl(m);
402 if (r < 0)
403 return r;
404
96243149
YW
405 if (test_mode)
406 return 0;
407
408 r = manager_connect_bus(m);
409 if (r < 0)
410 return r;
411
5fae368b
TG
412 r = manager_connect_udev(m);
413 if (r < 0)
414 return r;
45af44d4 415
05d0c2e3
JT
416 r = sd_resolve_default(&m->resolve);
417 if (r < 0)
418 return r;
419
420 r = sd_resolve_attach_event(m->resolve, m->event, 0);
421 if (r < 0)
422 return r;
423
ed76f585 424 r = address_pool_setup_default(m);
5fae368b
TG
425 if (r < 0)
426 return r;
f579559b 427
96243149
YW
428 m->state_file = strdup("/run/systemd/netif/state");
429 if (!m->state_file)
430 return -ENOMEM;
431
432 return 0;
433}
434
435int manager_new(Manager **ret) {
436 _cleanup_(manager_freep) Manager *m = NULL;
f579559b 437
96243149
YW
438 m = new(Manager, 1);
439 if (!m)
440 return -ENOMEM;
441
442 *m = (Manager) {
443 .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
444 .online_state = _LINK_ONLINE_STATE_INVALID,
445 .manage_foreign_routes = true,
446 .manage_foreign_rules = true,
447 .ethtool_fd = -1,
448 .dhcp_duid.type = DUID_TYPE_EN,
449 .dhcp6_duid.type = DUID_TYPE_EN,
450 .duid_product_uuid.type = DUID_TYPE_UUID,
451 };
452
453 *ret = TAKE_PTR(m);
f579559b
TG
454 return 0;
455}
456
75db809a 457Manager* manager_free(Manager *m) {
5fae368b 458 Link *link;
f579559b 459
5fae368b 460 if (!m)
75db809a 461 return NULL;
505f8da7 462
5fae368b 463 free(m->state_file);
505f8da7 464
6eab614d 465 HASHMAP_FOREACH(link, m->links_by_index)
2a99eed0 466 (void) link_stop_engines(link, true);
946f8e14 467
40b12fa2 468 m->request_queue = ordered_set_free(m->request_queue);
19d9a5ad 469
1633c457
YW
470 m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
471 m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);
f579559b 472
c4397d94 473 m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
0b54c870 474 m->links_by_name = hashmap_free(m->links_by_name);
fe321d45 475 m->links_by_hw_addr = hashmap_free(m->links_by_hw_addr);
6eab614d 476 m->links_by_index = hashmap_free_with_destructor(m->links_by_index, link_unref);
27dfc982 477
715d398e 478 m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
dbffab87 479
c4397d94 480 m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
5fae368b 481
bfbf150e 482 ordered_set_free_free(m->address_pools);
5fae368b 483
552b90a2
YW
484 hashmap_free(m->route_table_names_by_number);
485 hashmap_free(m->route_table_numbers_by_name);
c038ce46 486
eb72fa3a 487 set_free(m->rules);
bce67bbe 488
d4df6326
SS
489 sd_netlink_unref(m->rtnl);
490 sd_netlink_unref(m->genl);
491 sd_resolve_unref(m->resolve);
492
450fa34b
YW
493 /* reject (e.g. unreachable) type routes are managed by Manager, but may be referenced by a
494 * link. E.g., DHCP6 with prefix delegation creates unreachable routes, and they are referenced
495 * by the upstream link. And the links may be referenced by netlink slots. Hence, two
496 * set_free() must be called after the above sd_netlink_unref(). */
497 m->routes = set_free(m->routes);
498 m->routes_foreign = set_free(m->routes_foreign);
499
30f10837 500 m->nexthops = set_free(m->nexthops);
69e244e3
YW
501 m->nexthops_by_id = hashmap_free(m->nexthops_by_id);
502
a879e1a4 503 sd_event_source_unref(m->speed_meter_event_source);
2f5b4a77 504 sd_event_unref(m->event);
5fae368b 505
d2ebf952 506 sd_device_monitor_unref(m->device_monitor);
7d20d375 507
15761549 508 bus_verify_polkit_async_registry_free(m->polkit_registry);
92e31da1 509 sd_bus_flush_close_unref(m->bus);
7d20d375 510
7901cea1
MP
511 free(m->dynamic_timezone);
512 free(m->dynamic_hostname);
513
c643bda5
YW
514 safe_close(m->ethtool_fd);
515
761cf19d
FW
516 m->fw_ctx = fw_ctx_free(m->fw_ctx);
517
75db809a 518 return mfree(m);
5fae368b
TG
519}
520
b76d99d9 521int manager_start(Manager *m) {
84de38c5 522 Link *link;
a879e1a4 523 int r;
84de38c5 524
a97dcc12
TG
525 assert(m);
526
a879e1a4
YW
527 r = manager_start_speed_meter(m);
528 if (r < 0)
529 return log_error_errno(r, "Failed to initialize speed meter: %m");
530
84de38c5
TG
531 /* The dirty handler will deal with future serialization, but the first one
532 must be done explicitly. */
533
d23a66f2
YW
534 r = manager_save(m);
535 if (r < 0)
536 log_warning_errno(r, "Failed to update state file %s, ignoring: %m", m->state_file);
84de38c5 537
6eab614d 538 HASHMAP_FOREACH(link, m->links_by_index) {
d23a66f2
YW
539 r = link_save(link);
540 if (r < 0)
541 log_link_warning_errno(link, r, "Failed to update link state file %s, ignoring: %m", link->state_file);
542 }
84de38c5 543
b76d99d9 544 return 0;
a97dcc12
TG
545}
546
5fae368b
TG
547int manager_load_config(Manager *m) {
548 int r;
549
550 /* update timestamp */
dc0d4078 551 paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true);
5fae368b 552
e272b621 553 r = netdev_load(m, false);
f579559b
TG
554 if (r < 0)
555 return r;
556
7f06b3e1 557 r = network_load(m, &m->networks);
9021bb9f
TG
558 if (r < 0)
559 return r;
560
f579559b
TG
561 return 0;
562}
f882c247 563
5fae368b 564bool manager_should_reload(Manager *m) {
dc0d4078 565 return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false);
5fae368b
TG
566}
567
446aaaf3
YW
568static int manager_enumerate_internal(
569 Manager *m,
bdcd4ab2 570 sd_netlink *nl,
446aaaf3
YW
571 sd_netlink_message *req,
572 int (*process)(sd_netlink *, sd_netlink_message *, Manager *),
573 const char *name) {
574
575 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
bdcd4ab2 576 int k, r;
f882c247 577
5da8149f 578 assert(m);
bdcd4ab2 579 assert(nl);
446aaaf3
YW
580 assert(req);
581 assert(process);
f882c247 582
1c4baffc 583 r = sd_netlink_message_request_dump(req, true);
dd3efc09
TG
584 if (r < 0)
585 return r;
586
bdcd4ab2 587 r = sd_netlink_call(nl, req, 0, &reply);
446aaaf3 588 if (r < 0) {
92b555aa 589 if (name && (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing()))) {
bdcd4ab2 590 log_debug_errno(r, "%s is not supported by the kernel. Ignoring.", name);
446aaaf3
YW
591 return 0;
592 }
593
f2236469 594 return r;
446aaaf3 595 }
f2236469 596
446aaaf3 597 for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
6a24f148
TG
598 m->enumerating = true;
599
bdcd4ab2 600 k = process(nl, reply_one, m);
446aaaf3 601 if (k < 0 && r >= 0)
5fae368b 602 r = k;
6a24f148
TG
603
604 m->enumerating = false;
5fae368b 605 }
2e9f08ea 606
5fae368b 607 return r;
f882c247 608}
3bef724f 609
446aaaf3
YW
610static int manager_enumerate_links(Manager *m) {
611 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1346b1f0
TG
612 int r;
613
5fae368b
TG
614 assert(m);
615 assert(m->rtnl);
bcbca829 616
446aaaf3 617 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
5fae368b
TG
618 if (r < 0)
619 return r;
620
bdcd4ab2 621 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_link, NULL);
446aaaf3 622}
5fae368b 623
446aaaf3
YW
624static int manager_enumerate_addresses(Manager *m) {
625 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
626 int r;
6a24f148 627
446aaaf3
YW
628 assert(m);
629 assert(m->rtnl);
6a24f148 630
446aaaf3
YW
631 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
632 if (r < 0)
633 return r;
5fae368b 634
bdcd4ab2 635 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_address, NULL);
1346b1f0 636}
d1bdafd2 637
446aaaf3
YW
638static int manager_enumerate_neighbors(Manager *m) {
639 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
d1bdafd2
WKI
640 int r;
641
642 assert(m);
643 assert(m->rtnl);
644
645 r = sd_rtnl_message_new_neigh(m->rtnl, &req, RTM_GETNEIGH, 0, AF_UNSPEC);
646 if (r < 0)
647 return r;
648
bdcd4ab2 649 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_neighbor, NULL);
d1bdafd2 650}
1346b1f0 651
446aaaf3
YW
652static int manager_enumerate_routes(Manager *m) {
653 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c8e710c
TG
654 int r;
655
656 assert(m);
657 assert(m->rtnl);
658
5ff1ef31
YW
659 if (!m->manage_foreign_routes)
660 return 0;
661
1c8e710c
TG
662 r = sd_rtnl_message_new_route(m->rtnl, &req, RTM_GETROUTE, 0, 0);
663 if (r < 0)
664 return r;
665
bdcd4ab2 666 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_route, NULL);
1c8e710c
TG
667}
668
446aaaf3
YW
669static int manager_enumerate_rules(Manager *m) {
670 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
bce67bbe
SS
671 int r;
672
673 assert(m);
674 assert(m->rtnl);
675
d94dfe70
YW
676 if (!m->manage_foreign_rules)
677 return 0;
678
bce67bbe
SS
679 r = sd_rtnl_message_new_routing_policy_rule(m->rtnl, &req, RTM_GETRULE, 0);
680 if (r < 0)
681 return r;
682
bdcd4ab2 683 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_rule, "Routing policy rule");
bce67bbe
SS
684}
685
446aaaf3
YW
686static int manager_enumerate_nexthop(Manager *m) {
687 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
c16c7808
SS
688 int r;
689
690 assert(m);
691 assert(m->rtnl);
692
693 r = sd_rtnl_message_new_nexthop(m->rtnl, &req, RTM_GETNEXTHOP, 0, 0);
694 if (r < 0)
695 return r;
696
bdcd4ab2 697 return manager_enumerate_internal(m, m->rtnl, req, manager_rtnl_process_nexthop, "Next hop");
446aaaf3 698}
c16c7808 699
446aaaf3
YW
700int manager_enumerate(Manager *m) {
701 int r;
c16c7808 702
446aaaf3
YW
703 r = manager_enumerate_links(m);
704 if (r < 0)
705 return log_error_errno(r, "Could not enumerate links: %m");
c16c7808 706
446aaaf3
YW
707 r = manager_enumerate_addresses(m);
708 if (r < 0)
709 return log_error_errno(r, "Could not enumerate addresses: %m");
c16c7808 710
446aaaf3
YW
711 r = manager_enumerate_neighbors(m);
712 if (r < 0)
713 return log_error_errno(r, "Could not enumerate neighbors: %m");
c16c7808 714
0c0585ca
YW
715 r = manager_enumerate_nexthop(m);
716 if (r < 0)
717 return log_error_errno(r, "Could not enumerate nexthop rules: %m");
718
446aaaf3
YW
719 r = manager_enumerate_routes(m);
720 if (r < 0)
721 return log_error_errno(r, "Could not enumerate routes: %m");
c16c7808 722
446aaaf3
YW
723 r = manager_enumerate_rules(m);
724 if (r < 0)
725 return log_error_errno(r, "Could not enumerate routing policy rules: %m");
c16c7808 726
446aaaf3 727 return 0;
c16c7808
SS
728}
729
59eb33e0 730static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
59eb33e0 731 const sd_bus_error *e;
f63e09ef 732 int r;
59eb33e0
MP
733
734 assert(m);
59eb33e0
MP
735
736 e = sd_bus_message_get_error(m);
f63e09ef
YW
737 if (e) {
738 r = sd_bus_error_get_errno(e);
739 log_warning_errno(r, "Could not set hostname: %s", bus_error_message(e, r));
740 }
59eb33e0
MP
741
742 return 1;
743}
744
745int manager_set_hostname(Manager *m, const char *hostname) {
746 int r;
747
748 log_debug("Setting transient hostname: '%s'", strna(hostname));
d7afd945 749
b3f9c17a
YW
750 r = free_and_strdup_warn(&m->dynamic_hostname, hostname);
751 if (r < 0)
752 return r;
59eb33e0 753
5dbec9bd
ZJS
754 if (sd_bus_is_ready(m->bus) <= 0) {
755 log_debug("Not connected to system bus, setting system hostname later.");
59eb33e0
MP
756 return 0;
757 }
758
759 r = sd_bus_call_method_async(
760 m->bus,
761 NULL,
762 "org.freedesktop.hostname1",
763 "/org/freedesktop/hostname1",
764 "org.freedesktop.hostname1",
765 "SetHostname",
766 set_hostname_handler,
767 m,
768 "sb",
769 hostname,
770 false);
59eb33e0
MP
771 if (r < 0)
772 return log_error_errno(r, "Could not set transient hostname: %m");
773
774 return 0;
775}
776
777static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
59eb33e0 778 const sd_bus_error *e;
f63e09ef 779 int r;
59eb33e0
MP
780
781 assert(m);
59eb33e0
MP
782
783 e = sd_bus_message_get_error(m);
f63e09ef
YW
784 if (e) {
785 r = sd_bus_error_get_errno(e);
786 log_warning_errno(r, "Could not set timezone: %s", bus_error_message(e, r));
787 }
59eb33e0
MP
788
789 return 1;
790}
791
792int manager_set_timezone(Manager *m, const char *tz) {
793 int r;
794
795 assert(m);
796 assert(tz);
797
798 log_debug("Setting system timezone: '%s'", tz);
b3f9c17a
YW
799 r = free_and_strdup_warn(&m->dynamic_timezone, tz);
800 if (r < 0)
801 return r;
59eb33e0 802
5dbec9bd
ZJS
803 if (sd_bus_is_ready(m->bus) <= 0) {
804 log_debug("Not connected to system bus, setting system timezone later.");
59eb33e0
MP
805 return 0;
806 }
807
808 r = sd_bus_call_method_async(
809 m->bus,
810 NULL,
811 "org.freedesktop.timedate1",
812 "/org/freedesktop/timedate1",
813 "org.freedesktop.timedate1",
814 "SetTimezone",
815 set_timezone_handler,
816 m,
817 "sb",
818 tz,
819 false);
820 if (r < 0)
821 return log_error_errno(r, "Could not set timezone: %m");
822
823 return 0;
824}