]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/network/networkd-link-bus.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / network / networkd-link-bus.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
e331e246 2
15761549
YW
3#include <net/if.h>
4#include <netinet/in.h>
5#include <sys/capability.h>
6
b5efdb8a 7#include "alloc-util.h"
a879e1a4 8#include "bus-common-errors.h"
40af3d02 9#include "bus-get-properties.h"
10d46204 10#include "bus-message-util.h"
269e4d2d 11#include "bus-polkit.h"
15761549 12#include "dns-domain.h"
0bc30a20 13#include "networkd-dhcp4.h"
54a16efe 14#include "networkd-json.h"
6a1af3d4 15#include "networkd-link-bus.h"
e331e246 16#include "networkd-link.h"
23f53b99 17#include "networkd-manager.h"
3b5a4fc6 18#include "networkd-state-file.h"
6bedfcbb 19#include "parse-util.h"
15761549 20#include "resolve-util.h"
e77bd3fd 21#include "socket-netlink.h"
cf0fbc49 22#include "strv.h"
15761549 23#include "user-util.h"
e331e246 24
35c5a9ca
YW
25BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
26BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState);
27BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState);
bcdcc596 28BUS_DEFINE_PROPERTY_GET_ENUM(property_get_online_state, link_online_state, LinkOnlineState);
e331e246
TG
29static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
30
a879e1a4
YW
31static int property_get_bit_rates(
32 sd_bus *bus,
33 const char *path,
34 const char *interface,
35 const char *property,
36 sd_bus_message *reply,
37 void *userdata,
38 sd_bus_error *error) {
39
99534007 40 Link *link = ASSERT_PTR(userdata);
a879e1a4 41 Manager *manager;
42a63431
YW
42 double interval_sec;
43 uint64_t tx, rx;
a879e1a4
YW
44
45 assert(bus);
46 assert(reply);
a879e1a4
YW
47
48 manager = link->manager;
49
e813de54
YW
50 if (!manager->use_speed_meter ||
51 manager->speed_meter_usec_old == 0 ||
52 !link->stats_updated)
53 return sd_bus_message_append(reply, "(tt)", UINT64_MAX, UINT64_MAX);
a879e1a4
YW
54
55 assert(manager->speed_meter_usec_new > manager->speed_meter_usec_old);
42a63431 56 interval_sec = (manager->speed_meter_usec_new - manager->speed_meter_usec_old) / USEC_PER_SEC;
a879e1a4
YW
57
58 if (link->stats_new.tx_bytes > link->stats_old.tx_bytes)
42a63431 59 tx = (uint64_t) ((link->stats_new.tx_bytes - link->stats_old.tx_bytes) / interval_sec);
a879e1a4 60 else
42a63431 61 tx = (uint64_t) ((UINT64_MAX - (link->stats_old.tx_bytes - link->stats_new.tx_bytes)) / interval_sec);
a879e1a4
YW
62
63 if (link->stats_new.rx_bytes > link->stats_old.rx_bytes)
42a63431 64 rx = (uint64_t) ((link->stats_new.rx_bytes - link->stats_old.rx_bytes) / interval_sec);
a879e1a4 65 else
42a63431 66 rx = (uint64_t) ((UINT64_MAX - (link->stats_old.rx_bytes - link->stats_new.rx_bytes)) / interval_sec);
a879e1a4 67
42a63431 68 return sd_bus_message_append(reply, "(tt)", tx, rx);
a879e1a4
YW
69}
70
15761549
YW
71static int verify_managed_link(Link *l, sd_bus_error *error) {
72 assert(l);
73
74 if (l->flags & IFF_LOOPBACK)
75 return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname);
76
77 return 0;
78}
79
80int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
81 _cleanup_strv_free_ char **ntp = NULL;
99534007 82 Link *l = ASSERT_PTR(userdata);
15761549 83 int r;
15761549
YW
84
85 assert(message);
15761549
YW
86
87 r = verify_managed_link(l, error);
88 if (r < 0)
89 return r;
90
91 r = sd_bus_message_read_strv(message, &ntp);
92 if (r < 0)
93 return r;
94
95 STRV_FOREACH(i, ntp) {
96 r = dns_name_is_valid_or_address(*i);
97 if (r < 0)
98 return r;
99 if (r == 0)
100 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NTP server: %s", *i);
101 }
102
7b36fb9f
LP
103 r = bus_verify_polkit_async(
104 message,
105 "org.freedesktop.network1.set-ntp-servers",
106 /* details= */ NULL,
107 &l->manager->polkit_registry,
108 error);
15761549
YW
109 if (r < 0)
110 return r;
111 if (r == 0)
112 return 1; /* Polkit will call us back */
113
114 strv_free_and_replace(l->ntp, ntp);
115
bd7d9028 116 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
117 if (r < 0)
118 return r;
15761549
YW
119
120 return sd_bus_reply_method_return(message, NULL);
121}
122
4e11ddfd 123static int bus_link_method_set_dns_servers_internal(sd_bus_message *message, void *userdata, sd_bus_error *error, bool extended) {
10d46204 124 struct in_addr_full **dns;
99534007 125 Link *l = ASSERT_PTR(userdata);
10d46204 126 size_t n;
15761549
YW
127 int r;
128
129 assert(message);
15761549
YW
130
131 r = verify_managed_link(l, error);
132 if (r < 0)
133 return r;
134
10d46204 135 r = bus_message_read_dns_servers(message, error, extended, &dns, &n);
15761549
YW
136 if (r < 0)
137 return r;
138
7b36fb9f
LP
139 r = bus_verify_polkit_async(
140 message,
141 "org.freedesktop.network1.set-dns-servers",
142 /* details= */ NULL,
143 &l->manager->polkit_registry,
144 error);
15761549 145 if (r < 0)
e77bd3fd
YW
146 goto finalize;
147 if (r == 0) {
148 r = 1; /* Polkit will call us back */
149 goto finalize;
150 }
151
f5fbe71d 152 if (l->n_dns != UINT_MAX)
e77bd3fd
YW
153 for (unsigned i = 0; i < l->n_dns; i++)
154 in_addr_full_free(l->dns[i]);
15761549
YW
155
156 free_and_replace(l->dns, dns);
157 l->n_dns = n;
158
bd7d9028 159 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
160 if (r < 0)
161 return r;
15761549
YW
162
163 return sd_bus_reply_method_return(message, NULL);
e77bd3fd
YW
164
165finalize:
166 for (size_t i = 0; i < n; i++)
167 in_addr_full_free(dns[i]);
168 free(dns);
169
170 return r;
15761549
YW
171}
172
4e11ddfd
YW
173int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
174 return bus_link_method_set_dns_servers_internal(message, userdata, error, false);
175}
176
177int bus_link_method_set_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) {
178 return bus_link_method_set_dns_servers_internal(message, userdata, error, true);
179}
180
15761549 181int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
6e4571f0 182 _cleanup_ordered_set_free_ OrderedSet *search_domains = NULL, *route_domains = NULL;
99534007 183 Link *l = ASSERT_PTR(userdata);
15761549
YW
184 int r;
185
186 assert(message);
15761549
YW
187
188 r = verify_managed_link(l, error);
189 if (r < 0)
190 return r;
191
192 r = sd_bus_message_enter_container(message, 'a', "(sb)");
193 if (r < 0)
194 return r;
195
1f65aa3a
YW
196 search_domains = ordered_set_new(&string_hash_ops_free);
197 if (!search_domains)
198 return -ENOMEM;
199
200 route_domains = ordered_set_new(&string_hash_ops_free);
201 if (!route_domains)
202 return -ENOMEM;
203
15761549
YW
204 for (;;) {
205 _cleanup_free_ char *str = NULL;
15761549
YW
206 const char *name;
207 int route_only;
208
209 r = sd_bus_message_read(message, "(sb)", &name, &route_only);
210 if (r < 0)
211 return r;
212 if (r == 0)
213 break;
214
215 r = dns_name_is_valid(name);
216 if (r < 0)
217 return r;
218 if (r == 0)
219 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
220 if (!route_only && dns_name_is_root(name))
1b09b81c 221 return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
15761549
YW
222
223 r = dns_name_normalize(name, 0, &str);
224 if (r < 0)
225 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
226
1f65aa3a 227 r = ordered_set_consume(route_only ? route_domains : search_domains, TAKE_PTR(str));
6e4571f0
YW
228 if (r == -EEXIST)
229 continue;
15761549
YW
230 if (r < 0)
231 return r;
15761549
YW
232 }
233
234 r = sd_bus_message_exit_container(message);
235 if (r < 0)
236 return r;
237
7b36fb9f
LP
238 r = bus_verify_polkit_async(
239 message,
240 "org.freedesktop.network1.set-domains",
241 /* details= */ NULL,
242 &l->manager->polkit_registry,
243 error);
15761549
YW
244 if (r < 0)
245 return r;
246 if (r == 0)
247 return 1; /* Polkit will call us back */
248
6e4571f0
YW
249 ordered_set_free(l->search_domains);
250 ordered_set_free(l->route_domains);
15761549
YW
251 l->search_domains = TAKE_PTR(search_domains);
252 l->route_domains = TAKE_PTR(route_domains);
253
bd7d9028 254 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
255 if (r < 0)
256 return r;
15761549
YW
257
258 return sd_bus_reply_method_return(message, NULL);
259}
260
261int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 262 Link *l = ASSERT_PTR(userdata);
15761549
YW
263 int r, b;
264
265 assert(message);
15761549
YW
266
267 r = verify_managed_link(l, error);
268 if (r < 0)
269 return r;
270
271 r = sd_bus_message_read(message, "b", &b);
272 if (r < 0)
273 return r;
274
7b36fb9f
LP
275 r = bus_verify_polkit_async(
276 message,
277 "org.freedesktop.network1.set-default-route",
278 /* details= */ NULL,
279 &l->manager->polkit_registry,
280 error);
15761549
YW
281 if (r < 0)
282 return r;
283 if (r == 0)
284 return 1; /* Polkit will call us back */
285
286 if (l->dns_default_route != b) {
287 l->dns_default_route = b;
1b142221 288
bd7d9028 289 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
290 if (r < 0)
291 return r;
15761549
YW
292 }
293
294 return sd_bus_reply_method_return(message, NULL);
295}
296
297int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 298 Link *l = ASSERT_PTR(userdata);
15761549
YW
299 ResolveSupport mode;
300 const char *llmnr;
301 int r;
302
303 assert(message);
15761549
YW
304
305 r = verify_managed_link(l, error);
306 if (r < 0)
307 return r;
308
309 r = sd_bus_message_read(message, "s", &llmnr);
310 if (r < 0)
311 return r;
312
313 if (isempty(llmnr))
314 mode = RESOLVE_SUPPORT_YES;
315 else {
316 mode = resolve_support_from_string(llmnr);
317 if (mode < 0)
318 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
319 }
320
7b36fb9f
LP
321 r = bus_verify_polkit_async(
322 message,
323 "org.freedesktop.network1.set-llmnr",
324 /* details= */ NULL,
325 &l->manager->polkit_registry,
326 error);
15761549
YW
327 if (r < 0)
328 return r;
329 if (r == 0)
330 return 1; /* Polkit will call us back */
331
332 if (l->llmnr != mode) {
333 l->llmnr = mode;
1b142221 334
bd7d9028 335 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
336 if (r < 0)
337 return r;
15761549
YW
338 }
339
340 return sd_bus_reply_method_return(message, NULL);
341}
342
343int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 344 Link *l = ASSERT_PTR(userdata);
15761549
YW
345 ResolveSupport mode;
346 const char *mdns;
347 int r;
348
349 assert(message);
15761549
YW
350
351 r = verify_managed_link(l, error);
352 if (r < 0)
353 return r;
354
355 r = sd_bus_message_read(message, "s", &mdns);
356 if (r < 0)
357 return r;
358
359 if (isempty(mdns))
360 mode = RESOLVE_SUPPORT_NO;
361 else {
362 mode = resolve_support_from_string(mdns);
363 if (mode < 0)
364 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
365 }
366
7b36fb9f
LP
367 r = bus_verify_polkit_async(
368 message,
369 "org.freedesktop.network1.set-mdns",
370 /* details= */ NULL,
371 &l->manager->polkit_registry,
372 error);
15761549
YW
373 if (r < 0)
374 return r;
375 if (r == 0)
376 return 1; /* Polkit will call us back */
377
378 if (l->mdns != mode) {
379 l->mdns = mode;
1b142221 380
bd7d9028 381 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
382 if (r < 0)
383 return r;
15761549
YW
384 }
385
386 return sd_bus_reply_method_return(message, NULL);
387}
388
389int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 390 Link *l = ASSERT_PTR(userdata);
15761549
YW
391 const char *dns_over_tls;
392 DnsOverTlsMode mode;
393 int r;
394
395 assert(message);
15761549
YW
396
397 r = verify_managed_link(l, error);
398 if (r < 0)
399 return r;
400
401 r = sd_bus_message_read(message, "s", &dns_over_tls);
402 if (r < 0)
403 return r;
404
405 if (isempty(dns_over_tls))
406 mode = _DNS_OVER_TLS_MODE_INVALID;
407 else {
408 mode = dns_over_tls_mode_from_string(dns_over_tls);
409 if (mode < 0)
410 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
411 }
412
7b36fb9f
LP
413 r = bus_verify_polkit_async(
414 message,
415 "org.freedesktop.network1.set-dns-over-tls",
416 /* details= */ NULL,
417 &l->manager->polkit_registry,
418 error);
15761549
YW
419 if (r < 0)
420 return r;
421 if (r == 0)
422 return 1; /* Polkit will call us back */
423
424 if (l->dns_over_tls_mode != mode) {
425 l->dns_over_tls_mode = mode;
1b142221 426
bd7d9028 427 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
428 if (r < 0)
429 return r;
15761549
YW
430 }
431
432 return sd_bus_reply_method_return(message, NULL);
433}
434
435int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 436 Link *l = ASSERT_PTR(userdata);
15761549
YW
437 const char *dnssec;
438 DnssecMode mode;
439 int r;
440
441 assert(message);
15761549
YW
442
443 r = verify_managed_link(l, error);
444 if (r < 0)
445 return r;
446
447 r = sd_bus_message_read(message, "s", &dnssec);
448 if (r < 0)
449 return r;
450
451 if (isempty(dnssec))
452 mode = _DNSSEC_MODE_INVALID;
453 else {
454 mode = dnssec_mode_from_string(dnssec);
455 if (mode < 0)
456 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
457 }
458
7b36fb9f
LP
459 r = bus_verify_polkit_async(
460 message,
461 "org.freedesktop.network1.set-dnssec",
462 /* details= */ NULL,
463 &l->manager->polkit_registry,
464 error);
15761549
YW
465 if (r < 0)
466 return r;
467 if (r == 0)
468 return 1; /* Polkit will call us back */
469
470 if (l->dnssec_mode != mode) {
471 l->dnssec_mode = mode;
1b142221 472
bd7d9028 473 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
474 if (r < 0)
475 return r;
15761549
YW
476 }
477
478 return sd_bus_reply_method_return(message, NULL);
479}
480
481int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
482 _cleanup_set_free_free_ Set *ns = NULL;
483 _cleanup_strv_free_ char **ntas = NULL;
99534007 484 Link *l = ASSERT_PTR(userdata);
15761549 485 int r;
15761549
YW
486
487 assert(message);
15761549
YW
488
489 r = verify_managed_link(l, error);
490 if (r < 0)
491 return r;
492
493 r = sd_bus_message_read_strv(message, &ntas);
494 if (r < 0)
495 return r;
496
497 STRV_FOREACH(i, ntas) {
498 r = dns_name_is_valid(*i);
499 if (r < 0)
500 return r;
501 if (r == 0)
502 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i);
503 }
504
505 ns = set_new(&dns_name_hash_ops);
506 if (!ns)
507 return -ENOMEM;
508
509 STRV_FOREACH(i, ntas) {
be327321 510 r = set_put_strdup(&ns, *i);
15761549
YW
511 if (r < 0)
512 return r;
513 }
514
7b36fb9f
LP
515 r = bus_verify_polkit_async(
516 message,
517 "org.freedesktop.network1.set-dnssec-negative-trust-anchors",
518 /* details= */ NULL,
519 &l->manager->polkit_registry,
520 error);
15761549
YW
521 if (r < 0)
522 return r;
523 if (r == 0)
524 return 1; /* Polkit will call us back */
525
526 set_free_free(l->dnssec_negative_trust_anchors);
527 l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
528
bd7d9028 529 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
530 if (r < 0)
531 return r;
15761549
YW
532
533 return sd_bus_reply_method_return(message, NULL);
534}
535
536int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 537 Link *l = ASSERT_PTR(userdata);
15761549
YW
538 int r;
539
540 assert(message);
15761549
YW
541
542 r = verify_managed_link(l, error);
543 if (r < 0)
544 return r;
545
7b36fb9f
LP
546 r = bus_verify_polkit_async(
547 message,
548 "org.freedesktop.network1.revert-ntp",
549 /* details= */ NULL,
550 &l->manager->polkit_registry, error);
15761549
YW
551 if (r < 0)
552 return r;
553 if (r == 0)
554 return 1; /* Polkit will call us back */
555
556 link_ntp_settings_clear(l);
1b142221 557
bd7d9028 558 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
559 if (r < 0)
560 return r;
15761549
YW
561
562 return sd_bus_reply_method_return(message, NULL);
563}
564
565int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 566 Link *l = ASSERT_PTR(userdata);
15761549
YW
567 int r;
568
569 assert(message);
15761549
YW
570
571 r = verify_managed_link(l, error);
572 if (r < 0)
573 return r;
574
7b36fb9f
LP
575 r = bus_verify_polkit_async(
576 message,
577 "org.freedesktop.network1.revert-dns",
578 /* details= */ NULL,
579 &l->manager->polkit_registry,
580 error);
15761549
YW
581 if (r < 0)
582 return r;
583 if (r == 0)
584 return 1; /* Polkit will call us back */
585
586 link_dns_settings_clear(l);
1b142221 587
bd7d9028 588 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
1b142221
YW
589 if (r < 0)
590 return r;
15761549
YW
591
592 return sd_bus_reply_method_return(message, NULL);
593}
594
90867f6a 595int bus_link_method_force_renew(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 596 Link *l = ASSERT_PTR(userdata);
90867f6a
SS
597 int r;
598
90867f6a
SS
599 if (!l->network)
600 return sd_bus_error_setf(error, BUS_ERROR_UNMANAGED_INTERFACE,
601 "Interface %s is not managed by systemd-networkd",
602 l->ifname);
603
7b36fb9f
LP
604 r = bus_verify_polkit_async(
605 message,
606 "org.freedesktop.network1.forcerenew",
607 /* details= */ NULL,
608 &l->manager->polkit_registry,
609 error);
90867f6a
SS
610 if (r < 0)
611 return r;
612 if (r == 0)
613 return 1; /* Polkit will call us back */
614
d311f5e2 615 if (sd_dhcp_server_is_running(l->dhcp_server)) {
90867f6a
SS
616 r = sd_dhcp_server_forcerenew(l->dhcp_server);
617 if (r < 0)
618 return r;
619 }
620
621 return sd_bus_reply_method_return(message, NULL);
622}
623
ae65d7db 624int bus_link_method_renew(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 625 Link *l = ASSERT_PTR(userdata);
ae65d7db
YW
626 int r;
627
ae65d7db
YW
628 if (!l->network)
629 return sd_bus_error_setf(error, BUS_ERROR_UNMANAGED_INTERFACE,
630 "Interface %s is not managed by systemd-networkd",
631 l->ifname);
632
7b36fb9f
LP
633 r = bus_verify_polkit_async(
634 message,
635 "org.freedesktop.network1.renew",
636 /* details= */ NULL,
637 &l->manager->polkit_registry,
638 error);
ae65d7db
YW
639 if (r < 0)
640 return r;
641 if (r == 0)
642 return 1; /* Polkit will call us back */
643
0bc30a20 644 r = dhcp4_renew(l);
9bd91e34
YW
645 if (r < 0)
646 return r;
ae65d7db
YW
647
648 return sd_bus_reply_method_return(message, NULL);
649}
650
99b8517c 651int bus_link_method_reconfigure(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 652 Link *l = ASSERT_PTR(userdata);
99b8517c
YW
653 int r;
654
655 assert(message);
99b8517c 656
7b36fb9f
LP
657 r = bus_verify_polkit_async(
658 message,
659 "org.freedesktop.network1.reconfigure",
660 /* details= */ NULL,
661 &l->manager->polkit_registry,
662 error);
99b8517c
YW
663 if (r < 0)
664 return r;
665 if (r == 0)
666 return 1; /* Polkit will call us back */
667
7f80fa12 668 r = link_reconfigure(l, /* force = */ true);
99b8517c
YW
669 if (r < 0)
670 return r;
8bceafa7
YW
671 if (r > 0) {
672 link_set_state(l, LINK_STATE_INITIALIZED);
bd7d9028 673 r = link_save_and_clean_full(l, /* also_save_manager = */ true);
8bceafa7
YW
674 if (r < 0)
675 return r;
676 }
0ce0e347 677
99b8517c
YW
678 return sd_bus_reply_method_return(message, NULL);
679}
680
54a16efe
YW
681int bus_link_method_describe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
682 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
683 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
684 _cleanup_free_ char *text = NULL;
99534007 685 Link *link = ASSERT_PTR(userdata);
54a16efe
YW
686 int r;
687
688 assert(message);
54a16efe
YW
689
690 r = link_build_json(link, &v);
691 if (r < 0)
692 return log_link_error_errno(link, r, "Failed to build JSON data: %m");
693
694 r = json_variant_format(v, 0, &text);
695 if (r < 0)
696 return log_link_error_errno(link, r, "Failed to format JSON data: %m");
697
698 r = sd_bus_message_new_method_return(message, &reply);
699 if (r < 0)
700 return r;
701
702 r = sd_bus_message_append(reply, "s", text);
703 if (r < 0)
704 return r;
705
706 return sd_bus_send(NULL, reply, NULL);
707}
708
6e194652 709static const sd_bus_vtable link_vtable[] = {
e331e246
TG
710 SD_BUS_VTABLE_START(0),
711
712 SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
35c5a9ca
YW
713 SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
714 SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
8430841b
L
715 SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Link, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
716 SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Link, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
bcdcc596 717 SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Link, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
e331e246 718 SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
42a63431 719 SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
e331e246 720
23c32ff8
YW
721 SD_BUS_METHOD_WITH_ARGS("SetNTP",
722 SD_BUS_ARGS("as", servers),
723 SD_BUS_NO_RESULT,
724 bus_link_method_set_ntp_servers,
725 SD_BUS_VTABLE_UNPRIVILEGED),
726 SD_BUS_METHOD_WITH_ARGS("SetDNS",
727 SD_BUS_ARGS("a(iay)", addresses),
728 SD_BUS_NO_RESULT,
729 bus_link_method_set_dns_servers,
730 SD_BUS_VTABLE_UNPRIVILEGED),
731 SD_BUS_METHOD_WITH_ARGS("SetDNSEx",
732 SD_BUS_ARGS("a(iayqs)", addresses),
733 SD_BUS_NO_RESULT,
734 bus_link_method_set_dns_servers_ex,
735 SD_BUS_VTABLE_UNPRIVILEGED),
736 SD_BUS_METHOD_WITH_ARGS("SetDomains",
737 SD_BUS_ARGS("a(sb)", domains),
738 SD_BUS_NO_RESULT,
739 bus_link_method_set_domains,
740 SD_BUS_VTABLE_UNPRIVILEGED),
741 SD_BUS_METHOD_WITH_ARGS("SetDefaultRoute",
742 SD_BUS_ARGS("b", enable),
743 SD_BUS_NO_RESULT,
744 bus_link_method_set_default_route,
745 SD_BUS_VTABLE_UNPRIVILEGED),
746 SD_BUS_METHOD_WITH_ARGS("SetLLMNR",
747 SD_BUS_ARGS("s", mode),
748 SD_BUS_NO_RESULT,
749 bus_link_method_set_llmnr,
750 SD_BUS_VTABLE_UNPRIVILEGED),
751 SD_BUS_METHOD_WITH_ARGS("SetMulticastDNS",
752 SD_BUS_ARGS("s", mode),
753 SD_BUS_NO_RESULT,
754 bus_link_method_set_mdns,
755 SD_BUS_VTABLE_UNPRIVILEGED),
756 SD_BUS_METHOD_WITH_ARGS("SetDNSOverTLS",
757 SD_BUS_ARGS("s", mode),
758 SD_BUS_NO_RESULT,
759 bus_link_method_set_dns_over_tls,
760 SD_BUS_VTABLE_UNPRIVILEGED),
761 SD_BUS_METHOD_WITH_ARGS("SetDNSSEC",
762 SD_BUS_ARGS("s", mode),
763 SD_BUS_NO_RESULT,
764 bus_link_method_set_dnssec,
765 SD_BUS_VTABLE_UNPRIVILEGED),
766 SD_BUS_METHOD_WITH_ARGS("SetDNSSECNegativeTrustAnchors",
767 SD_BUS_ARGS("as", names),
768 SD_BUS_NO_RESULT,
769 bus_link_method_set_dnssec_negative_trust_anchors,
770 SD_BUS_VTABLE_UNPRIVILEGED),
771 SD_BUS_METHOD_WITH_ARGS("RevertNTP",
772 SD_BUS_NO_ARGS,
773 SD_BUS_NO_RESULT,
774 bus_link_method_revert_ntp,
775 SD_BUS_VTABLE_UNPRIVILEGED),
776 SD_BUS_METHOD_WITH_ARGS("RevertDNS",
777 SD_BUS_NO_ARGS,
778 SD_BUS_NO_RESULT,
779 bus_link_method_revert_dns,
780 SD_BUS_VTABLE_UNPRIVILEGED),
781 SD_BUS_METHOD_WITH_ARGS("Renew",
782 SD_BUS_NO_ARGS,
783 SD_BUS_NO_RESULT,
784 bus_link_method_renew,
785 SD_BUS_VTABLE_UNPRIVILEGED),
786 SD_BUS_METHOD_WITH_ARGS("ForceRenew",
787 SD_BUS_NO_ARGS,
788 SD_BUS_NO_RESULT,
789 bus_link_method_force_renew,
790 SD_BUS_VTABLE_UNPRIVILEGED),
791 SD_BUS_METHOD_WITH_ARGS("Reconfigure",
792 SD_BUS_NO_ARGS,
793 SD_BUS_NO_RESULT,
794 bus_link_method_reconfigure,
795 SD_BUS_VTABLE_UNPRIVILEGED),
54a16efe
YW
796 SD_BUS_METHOD_WITH_ARGS("Describe",
797 SD_BUS_NO_ARGS,
798 SD_BUS_RESULT("s", json),
799 bus_link_method_describe,
800 SD_BUS_VTABLE_UNPRIVILEGED),
15761549 801
e331e246
TG
802 SD_BUS_VTABLE_END
803};
804
6a1af3d4 805char *link_bus_path(Link *link) {
c8f5edea 806 _cleanup_free_ char *ifindex = NULL;
e331e246 807 char *p;
c8f5edea 808 int r;
e331e246
TG
809
810 assert(link);
811 assert(link->ifindex > 0);
812
c8f5edea
TG
813 if (asprintf(&ifindex, "%d", link->ifindex) < 0)
814 return NULL;
815
816 r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p);
817 if (r < 0)
02f50053 818 return NULL;
e331e246
TG
819
820 return p;
821}
822
823int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
824 _cleanup_strv_free_ char **l = NULL;
99534007 825 Manager *m = ASSERT_PTR(userdata);
fdb90ac6 826 unsigned c = 0;
e331e246 827 Link *link;
e331e246
TG
828
829 assert(bus);
830 assert(path);
e331e246
TG
831 assert(nodes);
832
6eab614d 833 l = new0(char*, hashmap_size(m->links_by_index) + 1);
fdb90ac6
LP
834 if (!l)
835 return -ENOMEM;
836
6eab614d 837 HASHMAP_FOREACH(link, m->links_by_index) {
e331e246
TG
838 char *p;
839
840 p = link_bus_path(link);
841 if (!p)
842 return -ENOMEM;
843
fdb90ac6 844 l[c++] = p;
e331e246
TG
845 }
846
fdb90ac6 847 l[c] = NULL;
ae2a15bc 848 *nodes = TAKE_PTR(l);
e331e246
TG
849
850 return 1;
851}
852
853int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
c8f5edea 854 _cleanup_free_ char *identifier = NULL;
99534007 855 Manager *m = ASSERT_PTR(userdata);
e331e246
TG
856 Link *link;
857 int ifindex, r;
858
859 assert(bus);
860 assert(path);
861 assert(interface);
e331e246
TG
862 assert(found);
863
c8f5edea 864 r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
a7f6e7e8 865 if (r <= 0)
c8f5edea
TG
866 return 0;
867
597da51b
ZJS
868 ifindex = parse_ifindex(identifier);
869 if (ifindex < 0)
e331e246
TG
870 return 0;
871
6eab614d 872 r = link_get_by_index(m, ifindex, &link);
e331e246
TG
873 if (r < 0)
874 return 0;
875
2cb1cabb
YW
876 if (streq(interface, "org.freedesktop.network1.DHCPServer") &&
877 (!link->dhcp_server || sd_dhcp_server_is_in_relay_mode(link->dhcp_server)))
cf72a786
MAL
878 return 0;
879
f8da534e 880 if (streq(interface, "org.freedesktop.network1.DHCPv4Client") && !link->dhcp_client)
881 return 0;
882
883 if (streq(interface, "org.freedesktop.network1.DHCPv6Client") && !link->dhcp6_client)
884 return 0;
885
e331e246
TG
886 *found = link;
887
888 return 1;
889}
890
aa3108f6 891int link_send_changed_strv(Link *link, char **properties) {
e331e246 892 _cleanup_free_ char *p = NULL;
e331e246
TG
893
894 assert(link);
895 assert(link->manager);
aa3108f6 896 assert(properties);
e331e246 897
5dbec9bd 898 if (sd_bus_is_ready(link->manager->bus) <= 0)
aa3108f6 899 return 0;
e331e246
TG
900
901 p = link_bus_path(link);
902 if (!p)
903 return -ENOMEM;
904
905 return sd_bus_emit_properties_changed_strv(
906 link->manager->bus,
907 p,
908 "org.freedesktop.network1.Link",
aa3108f6
YW
909 properties);
910}
911
912int link_send_changed(Link *link, const char *property, ...) {
913 char **properties;
914
915 properties = strv_from_stdarg_alloca(property);
916
917 return link_send_changed_strv(link, properties);
e331e246 918}
6e194652
YW
919
920const BusObjectImplementation link_object = {
921 "/org/freedesktop/network1/link",
922 "org.freedesktop.network1.Link",
923 .fallback_vtables = BUS_FALLBACK_VTABLES({link_vtable, link_object_find}),
924 .node_enumerator = link_node_enumerator,
925};