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