]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-manager.c
meson: use '_' as separator in fuzz test names
[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"
ac9f55ed 14#include "bus-log-control-api.h"
269e4d2d 15#include "bus-polkit.h"
a97dcc12 16#include "bus-util.h"
07630cea 17#include "conf-parser.h"
a97dcc12 18#include "def.h"
a7f95575 19#include "device-private.h"
21486d9e 20#include "device-util.h"
482d1aeb 21#include "dns-domain.h"
3ffd4af2 22#include "fd-util.h"
0d39fa9c 23#include "fileio.h"
4f5f911e 24#include "local-addresses.h"
07630cea 25#include "netlink-util.h"
dc0d4078 26#include "network-internal.h"
bfbf150e 27#include "networkd-address-pool.h"
cf72a786 28#include "networkd-dhcp-server-bus.h"
ca5ad760 29#include "networkd-dhcp6.h"
6a1af3d4 30#include "networkd-link-bus.h"
79a59fa5 31#include "networkd-manager-bus.h"
23f53b99 32#include "networkd-manager.h"
1939ebeb 33#include "networkd-neighbor.h"
ceac2c2b 34#include "networkd-network-bus.h"
75156ccb 35#include "networkd-nexthop.h"
ca183bf8 36#include "networkd-routing-policy-rule.h"
a879e1a4 37#include "networkd-speed-meter.h"
00616955 38#include "ordered-set.h"
b0c82192 39#include "path-lookup.h"
07630cea 40#include "path-util.h"
92b555aa 41#include "selinux-util.h"
07630cea 42#include "set.h"
ab76be55 43#include "signal-util.h"
d31f33e3 44#include "stat-util.h"
21486d9e 45#include "strv.h"
4b600505 46#include "sysctl-util.h"
e4de7287 47#include "tmpfile-util.h"
299ad32d 48#include "udev-util.h"
505f8da7 49
48d0248e
YW
50/* use 128 MB for receive socket kernel queue. */
51#define RCVBUF_SIZE (128*1024*1024)
be660c37 52
9c0a72f9
TG
53static int manager_reset_all(Manager *m) {
54 Link *link;
9c0a72f9
TG
55 int r;
56
57 assert(m);
58
90e74a66 59 HASHMAP_FOREACH(link, m->links) {
9c0a72f9
TG
60 r = link_carrier_reset(link);
61 if (r < 0)
2f3cf1f9 62 log_link_warning_errno(link, r, "Could not reset carrier: %m");
9c0a72f9
TG
63 }
64
65 return 0;
66}
67
19070062 68static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
9c0a72f9
TG
69 Manager *m = userdata;
70 int b, r;
71
19070062 72 assert(message);
d7afd945 73 assert(m);
9c0a72f9
TG
74
75 r = sd_bus_message_read(message, "b", &b);
76 if (r < 0) {
d67b1d18 77 bus_log_parse_error(r);
9c0a72f9
TG
78 return 0;
79 }
80
81 if (b)
82 return 0;
83
84 log_debug("Coming back from suspend, resetting all connections...");
85
e1694a75 86 (void) manager_reset_all(m);
9c0a72f9
TG
87
88 return 0;
89}
90
d7afd945
LP
91static int on_connected(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) {
92 Manager *m = userdata;
9c0a72f9 93
d7afd945 94 assert(message);
9c0a72f9
TG
95 assert(m);
96
d7afd945
LP
97 /* Did we get a timezone or transient hostname from DHCP while D-Bus wasn't up yet? */
98 if (m->dynamic_hostname)
99 (void) manager_set_hostname(m, m->dynamic_hostname);
100 if (m->dynamic_timezone)
101 (void) manager_set_timezone(m, m->dynamic_timezone);
27dfc982
YW
102 if (m->links_requesting_uuid)
103 (void) manager_request_product_uuid(m, NULL);
9c0a72f9 104
d7afd945
LP
105 return 0;
106}
9c0a72f9 107
d7afd945
LP
108int manager_connect_bus(Manager *m) {
109 int r;
110
111 assert(m);
9c0a72f9 112
d7afd945 113 if (m->bus)
9c0a72f9 114 return 0;
7d6884b6 115
621e4509 116 r = bus_open_system_watch_bind_with_description(&m->bus, "bus-api-network");
9c0a72f9 117 if (r < 0)
d7afd945 118 return log_error_errno(r, "Failed to connect to bus: %m");
9c0a72f9 119
e331e246
TG
120 r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m);
121 if (r < 0)
122 return log_error_errno(r, "Failed to add manager object vtable: %m");
123
124 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m);
125 if (r < 0)
126 return log_error_errno(r, "Failed to add link object vtable: %m");
127
cf72a786
MAL
128 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.DHCPServer", dhcp_server_vtable, link_object_find, m);
129 if (r < 0)
130 return log_error_errno(r, "Failed to add link object vtable: %m");
131
e331e246
TG
132 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m);
133 if (r < 0)
134 return log_error_errno(r, "Failed to add link enumerator: %m");
3175fcde
TG
135
136 r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m);
137 if (r < 0)
138 return log_error_errno(r, "Failed to add network object vtable: %m");
139
140 r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m);
141 if (r < 0)
142 return log_error_errno(r, "Failed to add network enumerator: %m");
e331e246 143
ac9f55ed
LP
144 r = bus_log_control_api_register(m->bus);
145 if (r < 0)
146 return r;
147
696fc836 148 r = sd_bus_request_name_async(m->bus, NULL, "org.freedesktop.network1", 0, NULL, NULL);
e331e246 149 if (r < 0)
0c0b9306 150 return log_error_errno(r, "Failed to request name: %m");
e331e246
TG
151
152 r = sd_bus_attach_event(m->bus, m->event, 0);
153 if (r < 0)
154 return log_error_errno(r, "Failed to attach bus to event loop: %m");
155
d7afd945
LP
156 r = sd_bus_match_signal_async(
157 m->bus,
cad43595 158 NULL,
d7afd945
LP
159 "org.freedesktop.DBus.Local",
160 NULL,
161 "org.freedesktop.DBus.Local",
162 "Connected",
163 on_connected, NULL, m);
164 if (r < 0)
165 return log_error_errno(r, "Failed to request match on Connected signal: %m");
166
167 r = sd_bus_match_signal_async(
168 m->bus,
cad43595 169 NULL,
d7afd945
LP
170 "org.freedesktop.login1",
171 "/org/freedesktop/login1",
172 "org.freedesktop.login1.Manager",
173 "PrepareForSleep",
174 match_prepare_for_sleep, NULL, m);
175 if (r < 0)
176 log_warning_errno(r, "Failed to request match for PrepareForSleep, ignoring: %m");
7901cea1 177
9c0a72f9
TG
178 return 0;
179}
180
d2ebf952
YW
181static int manager_udev_process_link(sd_device_monitor *monitor, sd_device *device, void *userdata) {
182 Manager *m = userdata;
a7f95575 183 DeviceAction action;
5fae368b
TG
184 Link *link = NULL;
185 int r, ifindex;
5544ee85 186
5fae368b
TG
187 assert(m);
188 assert(device);
5544ee85 189
a7f95575 190 r = device_get_action(device, &action);
21486d9e 191 if (r < 0) {
a7f95575 192 log_device_debug_errno(device, r, "Failed to get udev action, ignoring device: %m");
5fae368b 193 return 0;
21486d9e
YW
194 }
195
cd17bb6e
LP
196 /* Ignore the "remove" uevent — let's remove a device only if rtnetlink says so. All other uevents
197 * are "positive" events in some form, i.e. inform us about a changed or new network interface, that
198 * still exists — and we are interested in that. */
199 if (action == DEVICE_ACTION_REMOVE)
21486d9e 200 return 0;
5544ee85 201
51517f9e 202 r = sd_device_get_ifindex(device, &ifindex);
7606377e 203 if (r < 0) {
cd17bb6e
LP
204 log_device_debug_errno(device, r, "Ignoring udev %s event for device without ifindex or with invalid ifindex: %m",
205 device_action_to_string(action));
5fae368b 206 return 0;
5544ee85
TG
207 }
208
299ad32d
YW
209 r = device_is_renaming(device);
210 if (r < 0) {
a7f95575
YW
211 log_device_error_errno(device, r, "Failed to determine the device is renamed or not, ignoring '%s' uevent: %m",
212 device_action_to_string(action));
299ad32d
YW
213 return 0;
214 }
215 if (r > 0) {
1cdea1a2 216 log_device_debug(device, "Interface is under renaming, wait for the interface to be renamed.");
299ad32d
YW
217 return 0;
218 }
219
5fae368b 220 r = link_get(m, ifindex, &link);
d2ebf952
YW
221 if (r < 0) {
222 if (r != -ENODEV)
223 log_debug_errno(r, "Failed to get link from ifindex %i, ignoring: %m", ifindex);
5fae368b 224 return 0;
d2ebf952 225 }
02b59d57 226
d2ebf952 227 (void) link_initialized(link, device);
e1694a75 228
f579559b
TG
229 return 0;
230}
231
5fae368b
TG
232static int manager_connect_udev(Manager *m) {
233 int r;
f579559b 234
d31f33e3
YW
235 /* udev does not initialize devices inside containers, so we rely on them being already
236 * initialized before entering the container. */
237 if (path_is_read_only_fs("/sys") > 0)
5fae368b 238 return 0;
f579559b 239
d2ebf952 240 r = sd_device_monitor_new(&m->device_monitor);
02b59d57 241 if (r < 0)
d2ebf952 242 return log_error_errno(r, "Failed to initialize device monitor: %m");
02b59d57 243
a725efb0
YW
244 r = sd_device_monitor_set_receive_buffer_size(m->device_monitor, RCVBUF_SIZE);
245 if (r < 0)
246 log_warning_errno(r, "Failed to increase buffer size for device monitor, ignoring: %m");
247
d2ebf952
YW
248 r = sd_device_monitor_filter_add_match_subsystem_devtype(m->device_monitor, "net", NULL);
249 if (r < 0)
250 return log_error_errno(r, "Could not add device monitor filter: %m");
505f8da7 251
deb2b734 252 r = sd_device_monitor_attach_event(m->device_monitor, m->event);
5fae368b 253 if (r < 0)
d2ebf952 254 return log_error_errno(r, "Failed to attach event to device monitor: %m");
505f8da7 255
deb2b734 256 r = sd_device_monitor_start(m->device_monitor, manager_udev_process_link, m);
505f8da7 257 if (r < 0)
d2ebf952 258 return log_error_errno(r, "Failed to start device monitor: %m");
11a7f229 259
505f8da7
TG
260 return 0;
261}
f579559b 262
8dfed23d 263static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
505f8da7 264 Link *link = NULL;
4d473d5d 265 NetDev *netdev = NULL;
f2236469 266 uint16_t type;
ca4e095a 267 const char *name;
505f8da7 268 int r, ifindex;
f579559b 269
505f8da7
TG
270 assert(rtnl);
271 assert(message);
f579559b
TG
272 assert(m);
273
1c4baffc
TG
274 if (sd_netlink_message_is_error(message)) {
275 r = sd_netlink_message_get_errno(message);
45af44d4 276 if (r < 0)
5ecb131d 277 log_message_warning_errno(message, r, "rtnl: Could not receive link message, ignoring");
45af44d4
TG
278
279 return 0;
280 }
281
1c4baffc 282 r = sd_netlink_message_get_type(message, &type);
f2236469 283 if (r < 0) {
e1694a75 284 log_warning_errno(r, "rtnl: Could not get message type, ignoring: %m");
f2236469 285 return 0;
25a1bffc 286 } else if (!IN_SET(type, RTM_NEWLINK, RTM_DELLINK)) {
7f474ed7 287 log_warning("rtnl: Received unexpected message type %u when processing link, ignoring.", type);
cdfee943 288 return 0;
f2236469
TG
289 }
290
505f8da7 291 r = sd_rtnl_message_link_get_ifindex(message, &ifindex);
45af44d4 292 if (r < 0) {
7f474ed7 293 log_warning_errno(r, "rtnl: Could not get ifindex from link message, ignoring: %m");
45af44d4
TG
294 return 0;
295 } else if (ifindex <= 0) {
7f474ed7 296 log_warning("rtnl: received link message with invalid ifindex %d, ignoring.", ifindex);
505f8da7 297 return 0;
a0db8e46 298 }
f579559b 299
1c4baffc 300 r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
45af44d4 301 if (r < 0) {
e1694a75 302 log_warning_errno(r, "rtnl: Received link message without ifname, ignoring: %m");
4d473d5d 303 return 0;
a0db8e46
ZJS
304 }
305
306 (void) link_get(m, ifindex, &link);
307 (void) netdev_get(m, name, &netdev);
4d473d5d
TG
308
309 switch (type) {
310 case RTM_NEWLINK:
311 if (!link) {
312 /* link is new, so add it */
313 r = link_add(m, message, &link);
314 if (r < 0) {
7f474ed7 315 log_warning_errno(r, "Could not process new link message, ignoring: %m");
4d473d5d
TG
316 return 0;
317 }
318 }
319
320 if (netdev) {
321 /* netdev exists, so make sure the ifindex matches */
505f8da7
TG
322 r = netdev_set_ifindex(netdev, message);
323 if (r < 0) {
7f474ed7 324 log_warning_errno(r, "Could not process new link message for netdev, ignoring: %m");
505f8da7
TG
325 return 0;
326 }
327 }
e1202047 328
f2236469 329 r = link_update(link, message);
e1694a75 330 if (r < 0) {
7f474ed7 331 log_warning_errno(r, "Could not process link message, ignoring: %m");
f2236469 332 return 0;
e1694a75 333 }
4d473d5d
TG
334
335 break;
336
337 case RTM_DELLINK:
338 link_drop(link);
339 netdev_drop(netdev);
340
341 break;
342
343 default:
7f474ed7 344 assert_not_reached("Received link message with invalid RTNL message type.");
f2236469 345 }
505f8da7
TG
346
347 return 1;
348}
349
5fae368b
TG
350static int systemd_netlink_fd(void) {
351 int n, fd, rtnl_fd = -EINVAL;
352
353 n = sd_listen_fds(true);
354 if (n <= 0)
355 return -EINVAL;
356
357 for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) {
358 if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) {
359 if (rtnl_fd >= 0)
360 return -EINVAL;
361
362 rtnl_fd = fd;
363 }
364 }
365
366 return rtnl_fd;
367}
368
05d0c2e3
JT
369static int manager_connect_genl(Manager *m) {
370 int r;
371
372 assert(m);
373
374 r = sd_genl_socket_open(&m->genl);
375 if (r < 0)
376 return r;
377
378 r = sd_netlink_inc_rcvbuf(m->genl, RCVBUF_SIZE);
379 if (r < 0)
8c63924c 380 log_warning_errno(r, "Failed to increase receive buffer size for general netlink socket, ignoring: %m");
05d0c2e3
JT
381
382 r = sd_netlink_attach_event(m->genl, m->event, 0);
383 if (r < 0)
384 return r;
385
386 return 0;
387}
388
5fae368b
TG
389static int manager_connect_rtnl(Manager *m) {
390 int fd, r;
505f8da7
TG
391
392 assert(m);
505f8da7 393
5fae368b
TG
394 fd = systemd_netlink_fd();
395 if (fd < 0)
1c4baffc 396 r = sd_netlink_open(&m->rtnl);
5fae368b 397 else
1c4baffc 398 r = sd_netlink_open_fd(&m->rtnl, fd);
505f8da7
TG
399 if (r < 0)
400 return r;
401
e13af7bd
YW
402 /* Bump receiver buffer, but only if we are not called via socket activation, as in that
403 * case systemd sets the receive buffer size for us, and the value in the .socket unit
404 * should take full effect. */
405 if (fd < 0) {
406 r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE);
407 if (r < 0)
408 log_warning_errno(r, "Failed to increase receive buffer size for rtnl socket, ignoring: %m");
409 }
f579559b 410
1c4baffc 411 r = sd_netlink_attach_event(m->rtnl, m->event, 0);
505f8da7
TG
412 if (r < 0)
413 return r;
f579559b 414
8dfed23d 415 r = netlink_add_match(m->rtnl, NULL, RTM_NEWLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
5fae368b
TG
416 if (r < 0)
417 return r;
505f8da7 418
8dfed23d 419 r = netlink_add_match(m->rtnl, NULL, RTM_DELLINK, &manager_rtnl_process_link, NULL, m, "network-rtnl_process_link");
5fae368b
TG
420 if (r < 0)
421 return r;
45af44d4 422
8dfed23d 423 r = netlink_add_match(m->rtnl, NULL, RTM_NEWADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
5fae368b
TG
424 if (r < 0)
425 return r;
426
8dfed23d 427 r = netlink_add_match(m->rtnl, NULL, RTM_DELADDR, &manager_rtnl_process_address, NULL, m, "network-rtnl_process_address");
5fae368b
TG
428 if (r < 0)
429 return r;
430
8dfed23d 431 r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
d1bdafd2
WKI
432 if (r < 0)
433 return r;
434
8dfed23d 435 r = netlink_add_match(m->rtnl, NULL, RTM_DELNEIGH, &manager_rtnl_process_neighbor, NULL, m, "network-rtnl_process_neighbor");
d1bdafd2
WKI
436 if (r < 0)
437 return r;
438
8dfed23d 439 r = netlink_add_match(m->rtnl, NULL, RTM_NEWROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
1c8e710c
TG
440 if (r < 0)
441 return r;
442
8dfed23d 443 r = netlink_add_match(m->rtnl, NULL, RTM_DELROUTE, &manager_rtnl_process_route, NULL, m, "network-rtnl_process_route");
1c8e710c
TG
444 if (r < 0)
445 return r;
446
8dfed23d 447 r = netlink_add_match(m->rtnl, NULL, RTM_NEWRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
bce67bbe
SS
448 if (r < 0)
449 return r;
450
8dfed23d 451 r = netlink_add_match(m->rtnl, NULL, RTM_DELRULE, &manager_rtnl_process_rule, NULL, m, "network-rtnl_process_rule");
bce67bbe
SS
452 if (r < 0)
453 return r;
454
8dfed23d 455 r = netlink_add_match(m->rtnl, NULL, RTM_NEWNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
c16c7808
SS
456 if (r < 0)
457 return r;
458
8dfed23d 459 r = netlink_add_match(m->rtnl, NULL, RTM_DELNEXTHOP, &manager_rtnl_process_nexthop, NULL, m, "network-rtnl_process_nexthop");
c16c7808
SS
460 if (r < 0)
461 return r;
462
5fae368b 463 return 0;
45af44d4 464}
505f8da7 465
87d64897 466static int ordered_set_put_dns_server(OrderedSet *s, int ifindex, struct in_addr_full *dns) {
e77bd3fd 467 const char *p;
84de38c5
TG
468 int r;
469
470 assert(s);
e77bd3fd 471 assert(dns);
5512a963 472
87d64897
YW
473 if (dns->ifindex != 0 && dns->ifindex != ifindex)
474 return 0;
475
e77bd3fd
YW
476 p = in_addr_full_to_string(dns);
477 if (!p)
478 return 0;
5512a963 479
e77bd3fd 480 r = ordered_set_put_strdup(s, p);
5512a963
LP
481 if (r == -EEXIST)
482 return 0;
483
484 return r;
485}
486
87d64897 487static int ordered_set_put_dns_servers(OrderedSet *s, int ifindex, struct in_addr_full **dns, unsigned n) {
5512a963
LP
488 int r, c = 0;
489 unsigned i;
490
491 assert(s);
e77bd3fd 492 assert(dns || n == 0);
5512a963
LP
493
494 for (i = 0; i < n; i++) {
87d64897 495 r = ordered_set_put_dns_server(s, ifindex, dns[i]);
5512a963
LP
496 if (r < 0)
497 return r;
498
499 c += r;
500 }
501
502 return c;
503}
504
505static int ordered_set_put_in4_addr(OrderedSet *s, const struct in_addr *address) {
506 char *p;
507 int r;
508
509 assert(s);
510 assert(address);
84de38c5
TG
511
512 r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p);
513 if (r < 0)
514 return r;
515
00616955 516 r = ordered_set_consume(s, p);
84de38c5
TG
517 if (r == -EEXIST)
518 return 0;
519
520 return r;
521}
522
072320ea
TH
523static int ordered_set_put_in4_addrv(OrderedSet *s,
524 const struct in_addr *addresses,
525 size_t n,
526 bool (*predicate)(const struct in_addr *addr)) {
5512a963 527 int r, c = 0;
072320ea 528 size_t i;
84de38c5
TG
529
530 assert(s);
5512a963 531 assert(n == 0 || addresses);
84de38c5
TG
532
533 for (i = 0; i < n; i++) {
072320ea
TH
534 if (predicate && !predicate(&addresses[i]))
535 continue;
5512a963 536 r = ordered_set_put_in4_addr(s, addresses+i);
84de38c5
TG
537 if (r < 0)
538 return r;
539
540 c += r;
541 }
542
543 return c;
544}
545
84de38c5 546static int manager_save(Manager *m) {
2a71d57f 547 _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *sip = NULL, *search_domains = NULL, *route_domains = NULL;
299d578f 548 const char *operstate_str, *carrier_state_str, *address_state_str;
84de38c5 549 LinkOperationalState operstate = LINK_OPERSTATE_OFF;
7f3c07ad
YW
550 LinkCarrierState carrier_state = LINK_CARRIER_STATE_OFF;
551 LinkAddressState address_state = LINK_ADDRESS_STATE_OFF;
299d578f
SS
552 _cleanup_free_ char *temp_path = NULL;
553 _cleanup_strv_free_ char **p = NULL;
554 _cleanup_fclose_ FILE *f = NULL;
555 Link *link;
84de38c5
TG
556 int r;
557
558 assert(m);
559 assert(m->state_file);
560
561 /* We add all NTP and DNS server to a set, to filter out duplicates */
00616955 562 dns = ordered_set_new(&string_hash_ops);
84de38c5
TG
563 if (!dns)
564 return -ENOMEM;
565
00616955 566 ntp = ordered_set_new(&string_hash_ops);
84de38c5
TG
567 if (!ntp)
568 return -ENOMEM;
569
284e8fd0
SS
570 sip = ordered_set_new(&string_hash_ops);
571 if (!sip)
299d578f
SS
572 return -ENOMEM;
573
482d1aeb 574 search_domains = ordered_set_new(&dns_name_hash_ops);
3df9bec5
LP
575 if (!search_domains)
576 return -ENOMEM;
577
482d1aeb 578 route_domains = ordered_set_new(&dns_name_hash_ops);
3df9bec5 579 if (!route_domains)
84de38c5
TG
580 return -ENOMEM;
581
90e74a66 582 HASHMAP_FOREACH(link, m->links) {
2a71d57f
LP
583 const struct in_addr *addresses;
584
84de38c5
TG
585 if (link->flags & IFF_LOOPBACK)
586 continue;
587
588 if (link->operstate > operstate)
589 operstate = link->operstate;
590
7f3c07ad
YW
591 if (link->carrier_state > carrier_state)
592 carrier_state = link->carrier_state;
593
594 if (link->address_state > address_state)
595 address_state = link->address_state;
596
84de38c5
TG
597 if (!link->network)
598 continue;
599
600 /* First add the static configured entries */
87d64897
YW
601 if (link->n_dns != (unsigned) -1)
602 r = ordered_set_put_dns_servers(dns, link->ifindex, link->dns, link->n_dns);
603 else
604 r = ordered_set_put_dns_servers(dns, link->ifindex, link->network->dns, link->network->n_dns);
84de38c5
TG
605 if (r < 0)
606 return r;
607
15761549 608 r = ordered_set_put_strdupv(ntp, link->ntp ?: link->network->ntp);
84de38c5
TG
609 if (r < 0)
610 return r;
611
15761549 612 r = ordered_set_put_string_set(search_domains, link->search_domains ?: link->network->search_domains);
3df9bec5
LP
613 if (r < 0)
614 return r;
615
15761549 616 r = ordered_set_put_string_set(route_domains, link->route_domains ?: link->network->route_domains);
84de38c5
TG
617 if (r < 0)
618 return r;
619
620 if (!link->dhcp_lease)
621 continue;
622
623 /* Secondly, add the entries acquired via DHCP */
27cb34f5 624 if (link->network->dhcp_use_dns) {
84de38c5
TG
625 r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
626 if (r > 0) {
072320ea 627 r = ordered_set_put_in4_addrv(dns, addresses, r, in4_addr_is_non_local);
84de38c5
TG
628 if (r < 0)
629 return r;
630 } else if (r < 0 && r != -ENODATA)
631 return r;
632 }
633
27cb34f5 634 if (link->network->dhcp_use_ntp) {
84de38c5
TG
635 r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
636 if (r > 0) {
072320ea 637 r = ordered_set_put_in4_addrv(ntp, addresses, r, in4_addr_is_non_local);
84de38c5
TG
638 if (r < 0)
639 return r;
640 } else if (r < 0 && r != -ENODATA)
641 return r;
642 }
643
299d578f 644 if (link->network->dhcp_use_sip) {
299d578f
SS
645 r = sd_dhcp_lease_get_sip(link->dhcp_lease, &addresses);
646 if (r > 0) {
647 r = ordered_set_put_in4_addrv(sip, addresses, r, in4_addr_is_non_local);
648 if (r < 0)
649 return r;
650 } else if (r < 0 && r != -ENODATA)
651 return r;
652 }
653
b2a81c0b 654 if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
84de38c5 655 const char *domainname;
b85bc551 656 char **domains = NULL;
84de38c5 657
b85bc551 658 OrderedSet *target_domains = (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) ? search_domains : route_domains;
84de38c5
TG
659 r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
660 if (r >= 0) {
b85bc551
DW
661 r = ordered_set_put_strdup(target_domains, domainname);
662 if (r < 0)
663 return r;
664 } else if (r != -ENODATA)
665 return r;
b2a81c0b 666
b85bc551
DW
667 r = sd_dhcp_lease_get_search_domains(link->dhcp_lease, &domains);
668 if (r >= 0) {
669 r = ordered_set_put_strdupv(target_domains, domains);
84de38c5
TG
670 if (r < 0)
671 return r;
672 } else if (r != -ENODATA)
673 return r;
674 }
675 }
676
7f3c07ad
YW
677 if (carrier_state >= LINK_CARRIER_STATE_ENSLAVED)
678 carrier_state = LINK_CARRIER_STATE_CARRIER;
679
84de38c5
TG
680 operstate_str = link_operstate_to_string(operstate);
681 assert(operstate_str);
682
ac999bf0
YW
683 carrier_state_str = link_carrier_state_to_string(carrier_state);
684 assert(carrier_state_str);
685
686 address_state_str = link_address_state_to_string(address_state);
687 assert(address_state_str);
688
84de38c5
TG
689 r = fopen_temporary(m->state_file, &f, &temp_path);
690 if (r < 0)
691 return r;
692
5512a963 693 (void) fchmod(fileno(f), 0644);
84de38c5
TG
694
695 fprintf(f,
696 "# This is private data. Do not parse.\n"
ac999bf0
YW
697 "OPER_STATE=%s\n"
698 "CARRIER_STATE=%s\n"
699 "ADDRESS_STATE=%s\n",
700 operstate_str, carrier_state_str, address_state_str);
84de38c5 701
53ae3f64
ZJS
702 ordered_set_print(f, "DNS=", dns);
703 ordered_set_print(f, "NTP=", ntp);
299d578f 704 ordered_set_print(f, "SIP=", sip);
53ae3f64
ZJS
705 ordered_set_print(f, "DOMAINS=", search_domains);
706 ordered_set_print(f, "ROUTE_DOMAINS=", route_domains);
84de38c5 707
458d8ae3
ZJS
708 r = routing_policy_serialize_rules(m->rules, f);
709 if (r < 0)
710 goto fail;
bce67bbe 711
84de38c5
TG
712 r = fflush_and_check(f);
713 if (r < 0)
714 goto fail;
715
716 if (rename(temp_path, m->state_file) < 0) {
717 r = -errno;
718 goto fail;
719 }
720
721 if (m->operational_state != operstate) {
722 m->operational_state = operstate;
7f3c07ad
YW
723 if (strv_extend(&p, "OperationalState") < 0)
724 log_oom();
725 }
726
727 if (m->carrier_state != carrier_state) {
728 m->carrier_state = carrier_state;
729 if (strv_extend(&p, "CarrierState") < 0)
730 log_oom();
731 }
732
733 if (m->address_state != address_state) {
734 m->address_state = address_state;
735 if (strv_extend(&p, "AddressState") < 0)
736 log_oom();
737 }
738
739 if (p) {
740 r = manager_send_changed_strv(m, p);
84de38c5 741 if (r < 0)
7f3c07ad 742 log_error_errno(r, "Could not emit changed properties: %m");
84de38c5
TG
743 }
744
745 m->dirty = false;
746
747 return 0;
748
749fail:
750 (void) unlink(m->state_file);
751 (void) unlink(temp_path);
752
753 return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
754}
755
756static int manager_dirty_handler(sd_event_source *s, void *userdata) {
757 Manager *m = userdata;
758 Link *link;
84de38c5
TG
759
760 assert(m);
761
762 if (m->dirty)
763 manager_save(m);
764
90e74a66 765 SET_FOREACH(link, m->dirty_links)
c2a65950 766 (void) link_save_and_clean(link);
84de38c5
TG
767
768 return 1;
769}
770
ab76be55
ZJS
771static int signal_terminate_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
772 Manager *m = userdata;
773
774 assert(m);
775 m->restarting = false;
776
777 log_debug("Terminate operation initiated.");
778
779 return sd_event_exit(sd_event_source_get_event(s), 0);
780}
781
782static int signal_restart_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
783 Manager *m = userdata;
784
785 assert(m);
786 m->restarting = true;
787
788 log_debug("Restart operation initiated.");
789
790 return sd_event_exit(sd_event_source_get_event(s), 0);
791}
792
3534a043 793int manager_new(Manager **ret) {
8e766630 794 _cleanup_(manager_freep) Manager *m = NULL;
45af44d4 795 int r;
f579559b 796
a879e1a4 797 m = new(Manager, 1);
5fae368b
TG
798 if (!m)
799 return -ENOMEM;
45af44d4 800
a879e1a4
YW
801 *m = (Manager) {
802 .speed_meter_interval_usec = SPEED_METER_DEFAULT_TIME_INTERVAL,
5d3b8017 803 .manage_foreign_routes = true,
c643bda5 804 .ethtool_fd = -1,
a879e1a4
YW
805 };
806
5fae368b
TG
807 m->state_file = strdup("/run/systemd/netif/state");
808 if (!m->state_file)
809 return -ENOMEM;
810
3534a043
YW
811 r = sd_event_default(&m->event);
812 if (r < 0)
813 return r;
814
ab76be55
ZJS
815 assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0);
816
05e21627 817 (void) sd_event_set_watchdog(m->event, true);
ab76be55
ZJS
818 (void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m);
819 (void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m);
820 (void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m);
5fae368b 821
84de38c5
TG
822 r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m);
823 if (r < 0)
824 return r;
825
5fae368b 826 r = manager_connect_rtnl(m);
45af44d4
TG
827 if (r < 0)
828 return r;
829
05d0c2e3
JT
830 r = manager_connect_genl(m);
831 if (r < 0)
832 return r;
833
5fae368b
TG
834 r = manager_connect_udev(m);
835 if (r < 0)
836 return r;
45af44d4 837
05d0c2e3
JT
838 r = sd_resolve_default(&m->resolve);
839 if (r < 0)
840 return r;
841
842 r = sd_resolve_attach_event(m->resolve, m->event, 0);
843 if (r < 0)
844 return r;
845
ed76f585 846 r = address_pool_setup_default(m);
5fae368b
TG
847 if (r < 0)
848 return r;
f579559b 849
8341a5c3 850 m->duid.type = DUID_TYPE_EN;
413708d1 851
458d8ae3 852 (void) routing_policy_load_rules(m->state_file, &m->rules_saved);
bce67bbe 853
1cc6c93a 854 *ret = TAKE_PTR(m);
f579559b 855
f579559b
TG
856 return 0;
857}
858
5fae368b 859void manager_free(Manager *m) {
5fae368b 860 Link *link;
f579559b 861
5fae368b
TG
862 if (!m)
863 return;
505f8da7 864
5fae368b 865 free(m->state_file);
505f8da7 866
90e74a66 867 HASHMAP_FOREACH(link, m->links)
2a99eed0 868 (void) link_stop_engines(link, true);
946f8e14 869
1633c457
YW
870 m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
871 m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);
f579559b 872
c4397d94 873 m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
5f707e12
YW
874 m->links_requesting_uuid = set_free_with_destructor(m->links_requesting_uuid, link_unref);
875 m->links = hashmap_free_with_destructor(m->links, link_unref);
27dfc982 876
5f707e12 877 m->duids_requesting_uuid = set_free(m->duids_requesting_uuid);
715d398e 878 m->networks = ordered_hashmap_free_with_destructor(m->networks, network_unref);
dbffab87 879
c4397d94 880 m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
5fae368b 881
bfbf150e 882 ordered_set_free_free(m->address_pools);
5fae368b 883
f19ee681
YW
884 /* routing_policy_rule_free() access m->rules and m->rules_foreign.
885 * So, it is necessary to set NULL after the sets are freed. */
8eec0b9d
YW
886 m->rules = set_free(m->rules);
887 m->rules_foreign = set_free(m->rules_foreign);
888 set_free(m->rules_saved);
bce67bbe 889
ad208fac
YW
890 m->routes = set_free(m->routes);
891 m->routes_foreign = set_free(m->routes_foreign);
892
d4df6326
SS
893 sd_netlink_unref(m->rtnl);
894 sd_netlink_unref(m->genl);
895 sd_resolve_unref(m->resolve);
896
a879e1a4 897 sd_event_source_unref(m->speed_meter_event_source);
2f5b4a77 898 sd_event_unref(m->event);
5fae368b 899
d2ebf952 900 sd_device_monitor_unref(m->device_monitor);
7d20d375 901
15761549 902 bus_verify_polkit_async_registry_free(m->polkit_registry);
92e31da1 903 sd_bus_flush_close_unref(m->bus);
7d20d375 904
7901cea1
MP
905 free(m->dynamic_timezone);
906 free(m->dynamic_hostname);
907
c643bda5
YW
908 safe_close(m->ethtool_fd);
909
5fae368b
TG
910 free(m);
911}
912
b76d99d9 913int manager_start(Manager *m) {
84de38c5 914 Link *link;
a879e1a4 915 int r;
84de38c5 916
a97dcc12
TG
917 assert(m);
918
a879e1a4
YW
919 r = manager_start_speed_meter(m);
920 if (r < 0)
921 return log_error_errno(r, "Failed to initialize speed meter: %m");
922
84de38c5
TG
923 /* The dirty handler will deal with future serialization, but the first one
924 must be done explicitly. */
925
926 manager_save(m);
927
90e74a66 928 HASHMAP_FOREACH(link, m->links)
c2a65950 929 (void) link_save(link);
84de38c5 930
b76d99d9 931 return 0;
a97dcc12
TG
932}
933
5fae368b
TG
934int manager_load_config(Manager *m) {
935 int r;
936
937 /* update timestamp */
dc0d4078 938 paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, true);
5fae368b 939
e272b621 940 r = netdev_load(m, false);
f579559b
TG
941 if (r < 0)
942 return r;
943
7f06b3e1 944 r = network_load(m, &m->networks);
9021bb9f
TG
945 if (r < 0)
946 return r;
947
f579559b
TG
948 return 0;
949}
f882c247 950
5fae368b 951bool manager_should_reload(Manager *m) {
dc0d4078 952 return paths_check_timestamp(NETWORK_DIRS, &m->network_dirs_ts_usec, false);
5fae368b
TG
953}
954
446aaaf3
YW
955static int manager_enumerate_internal(
956 Manager *m,
957 sd_netlink_message *req,
958 int (*process)(sd_netlink *, sd_netlink_message *, Manager *),
959 const char *name) {
960
961 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *reply = NULL;
f882c247
TG
962 int r;
963
5da8149f 964 assert(m);
5fae368b 965 assert(m->rtnl);
446aaaf3
YW
966 assert(req);
967 assert(process);
f882c247 968
1c4baffc 969 r = sd_netlink_message_request_dump(req, true);
dd3efc09
TG
970 if (r < 0)
971 return r;
972
1c4baffc 973 r = sd_netlink_call(m->rtnl, req, 0, &reply);
446aaaf3 974 if (r < 0) {
92b555aa 975 if (name && (r == -EOPNOTSUPP || (r == -EINVAL && mac_selinux_enforcing()))) {
446aaaf3
YW
976 log_debug_errno(r, "%s are not supported by the kernel. Ignoring.", name);
977 return 0;
978 }
979
f2236469 980 return r;
446aaaf3 981 }
f2236469 982
446aaaf3 983 for (sd_netlink_message *reply_one = reply; reply_one; reply_one = sd_netlink_message_next(reply_one)) {
5fae368b 984 int k;
2e9f08ea 985
6a24f148
TG
986 m->enumerating = true;
987
446aaaf3
YW
988 k = process(m->rtnl, reply_one, m);
989 if (k < 0 && r >= 0)
5fae368b 990 r = k;
6a24f148
TG
991
992 m->enumerating = false;
5fae368b 993 }
2e9f08ea 994
5fae368b 995 return r;
f882c247 996}
3bef724f 997
446aaaf3
YW
998static int manager_enumerate_links(Manager *m) {
999 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1346b1f0
TG
1000 int r;
1001
5fae368b
TG
1002 assert(m);
1003 assert(m->rtnl);
bcbca829 1004
446aaaf3 1005 r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0);
5fae368b
TG
1006 if (r < 0)
1007 return r;
1008
446aaaf3
YW
1009 return manager_enumerate_internal(m, req, manager_rtnl_process_link, NULL);
1010}
5fae368b 1011
446aaaf3
YW
1012static int manager_enumerate_addresses(Manager *m) {
1013 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1014 int r;
6a24f148 1015
446aaaf3
YW
1016 assert(m);
1017 assert(m->rtnl);
6a24f148 1018
446aaaf3
YW
1019 r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0);
1020 if (r < 0)
1021 return r;
5fae368b 1022
446aaaf3 1023 return manager_enumerate_internal(m, req, manager_rtnl_process_address, NULL);
1346b1f0 1024}
d1bdafd2 1025
446aaaf3
YW
1026static int manager_enumerate_neighbors(Manager *m) {
1027 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
d1bdafd2
WKI
1028 int r;
1029
1030 assert(m);
1031 assert(m->rtnl);
1032
1033 r = sd_rtnl_message_new_neigh(m->rtnl, &req, RTM_GETNEIGH, 0, AF_UNSPEC);
1034 if (r < 0)
1035 return r;
1036
446aaaf3 1037 return manager_enumerate_internal(m, req, manager_rtnl_process_neighbor, NULL);
d1bdafd2 1038}
1346b1f0 1039
446aaaf3
YW
1040static int manager_enumerate_routes(Manager *m) {
1041 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
1c8e710c
TG
1042 int r;
1043
1044 assert(m);
1045 assert(m->rtnl);
1046
5ff1ef31
YW
1047 if (!m->manage_foreign_routes)
1048 return 0;
1049
1c8e710c
TG
1050 r = sd_rtnl_message_new_route(m->rtnl, &req, RTM_GETROUTE, 0, 0);
1051 if (r < 0)
1052 return r;
1053
446aaaf3 1054 return manager_enumerate_internal(m, req, manager_rtnl_process_route, NULL);
1c8e710c
TG
1055}
1056
446aaaf3
YW
1057static int manager_enumerate_rules(Manager *m) {
1058 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
bce67bbe
SS
1059 int r;
1060
1061 assert(m);
1062 assert(m->rtnl);
1063
1064 r = sd_rtnl_message_new_routing_policy_rule(m->rtnl, &req, RTM_GETRULE, 0);
1065 if (r < 0)
1066 return r;
1067
446aaaf3 1068 return manager_enumerate_internal(m, req, manager_rtnl_process_rule, "Routing policy rules");
bce67bbe
SS
1069}
1070
446aaaf3
YW
1071static int manager_enumerate_nexthop(Manager *m) {
1072 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
c16c7808
SS
1073 int r;
1074
1075 assert(m);
1076 assert(m->rtnl);
1077
1078 r = sd_rtnl_message_new_nexthop(m->rtnl, &req, RTM_GETNEXTHOP, 0, 0);
1079 if (r < 0)
1080 return r;
1081
446aaaf3
YW
1082 return manager_enumerate_internal(m, req, manager_rtnl_process_nexthop, "Nexthop rules");
1083}
c16c7808 1084
446aaaf3
YW
1085int manager_enumerate(Manager *m) {
1086 int r;
c16c7808 1087
446aaaf3
YW
1088 r = manager_enumerate_links(m);
1089 if (r < 0)
1090 return log_error_errno(r, "Could not enumerate links: %m");
c16c7808 1091
446aaaf3
YW
1092 r = manager_enumerate_addresses(m);
1093 if (r < 0)
1094 return log_error_errno(r, "Could not enumerate addresses: %m");
c16c7808 1095
446aaaf3
YW
1096 r = manager_enumerate_neighbors(m);
1097 if (r < 0)
1098 return log_error_errno(r, "Could not enumerate neighbors: %m");
c16c7808 1099
446aaaf3
YW
1100 r = manager_enumerate_routes(m);
1101 if (r < 0)
1102 return log_error_errno(r, "Could not enumerate routes: %m");
c16c7808 1103
446aaaf3
YW
1104 r = manager_enumerate_rules(m);
1105 if (r < 0)
1106 return log_error_errno(r, "Could not enumerate routing policy rules: %m");
c16c7808 1107
446aaaf3
YW
1108 r = manager_enumerate_nexthop(m);
1109 if (r < 0)
1110 return log_error_errno(r, "Could not enumerate nexthop rules: %m");
1111
1112 return 0;
c16c7808
SS
1113}
1114
4f5f911e
LP
1115Link* manager_find_uplink(Manager *m, Link *exclude) {
1116 _cleanup_free_ struct local_address *gateways = NULL;
1117 int n, i;
1118
1119 assert(m);
1120
1121 /* Looks for a suitable "uplink", via black magic: an
1122 * interface that is up and where the default route with the
1123 * highest priority points to. */
1124
1125 n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways);
1126 if (n < 0) {
1127 log_warning_errno(n, "Failed to determine list of default gateways: %m");
1128 return NULL;
1129 }
1130
1131 for (i = 0; i < n; i++) {
1132 Link *link;
1133
1134 link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex));
1135 if (!link) {
c2c940bd 1136 log_debug("Weird, found a gateway for a link we don't know. Ignoring.");
4f5f911e
LP
1137 continue;
1138 }
1139
1140 if (link == exclude)
1141 continue;
1142
1143 if (link->operstate < LINK_OPERSTATE_ROUTABLE)
1144 continue;
1145
1146 return link;
1147 }
1148
1149 return NULL;
1150}
84de38c5
TG
1151
1152void manager_dirty(Manager *manager) {
1153 assert(manager);
1154
1155 /* the serialized state in /run is no longer up-to-date */
1156 manager->dirty = true;
1157}
59eb33e0
MP
1158
1159static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
0a0e594a 1160 _unused_ Manager *manager = userdata;
59eb33e0
MP
1161 const sd_bus_error *e;
1162
1163 assert(m);
1164 assert(manager);
1165
1166 e = sd_bus_message_get_error(m);
1167 if (e)
1168 log_warning_errno(sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message);
1169
1170 return 1;
1171}
1172
1173int manager_set_hostname(Manager *m, const char *hostname) {
1174 int r;
1175
1176 log_debug("Setting transient hostname: '%s'", strna(hostname));
d7afd945 1177
7901cea1
MP
1178 if (free_and_strdup(&m->dynamic_hostname, hostname) < 0)
1179 return log_oom();
59eb33e0 1180
d7afd945 1181 if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
e0d95f03 1182 log_debug("Not connected to system bus, setting hostname later.");
59eb33e0
MP
1183 return 0;
1184 }
1185
1186 r = sd_bus_call_method_async(
1187 m->bus,
1188 NULL,
1189 "org.freedesktop.hostname1",
1190 "/org/freedesktop/hostname1",
1191 "org.freedesktop.hostname1",
1192 "SetHostname",
1193 set_hostname_handler,
1194 m,
1195 "sb",
1196 hostname,
1197 false);
1198
1199 if (r < 0)
1200 return log_error_errno(r, "Could not set transient hostname: %m");
1201
1202 return 0;
1203}
1204
1205static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
0a0e594a 1206 _unused_ Manager *manager = userdata;
59eb33e0
MP
1207 const sd_bus_error *e;
1208
1209 assert(m);
1210 assert(manager);
1211
1212 e = sd_bus_message_get_error(m);
1213 if (e)
1214 log_warning_errno(sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message);
1215
1216 return 1;
1217}
1218
1219int manager_set_timezone(Manager *m, const char *tz) {
1220 int r;
1221
1222 assert(m);
1223 assert(tz);
1224
1225 log_debug("Setting system timezone: '%s'", tz);
7901cea1
MP
1226 if (free_and_strdup(&m->dynamic_timezone, tz) < 0)
1227 return log_oom();
59eb33e0 1228
d7afd945 1229 if (!m->bus || sd_bus_is_ready(m->bus) <= 0) {
e0d95f03 1230 log_debug("Not connected to system bus, setting timezone later.");
59eb33e0
MP
1231 return 0;
1232 }
1233
1234 r = sd_bus_call_method_async(
1235 m->bus,
1236 NULL,
1237 "org.freedesktop.timedate1",
1238 "/org/freedesktop/timedate1",
1239 "org.freedesktop.timedate1",
1240 "SetTimezone",
1241 set_timezone_handler,
1242 m,
1243 "sb",
1244 tz,
1245 false);
1246 if (r < 0)
1247 return log_error_errno(r, "Could not set timezone: %m");
1248
1249 return 0;
1250}