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