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