Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
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-util.h"
10 : #include "dns-domain.h"
11 : #include "networkd-link-bus.h"
12 : #include "networkd-link.h"
13 : #include "networkd-manager.h"
14 : #include "parse-util.h"
15 : #include "resolve-util.h"
16 : #include "strv.h"
17 : #include "user-util.h"
18 :
19 0 : BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState);
20 0 : BUS_DEFINE_PROPERTY_GET_ENUM(property_get_carrier_state, link_carrier_state, LinkCarrierState);
21 0 : BUS_DEFINE_PROPERTY_GET_ENUM(property_get_address_state, link_address_state, LinkAddressState);
22 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState);
23 :
24 0 : static int property_get_bit_rates(
25 : sd_bus *bus,
26 : const char *path,
27 : const char *interface,
28 : const char *property,
29 : sd_bus_message *reply,
30 : void *userdata,
31 : sd_bus_error *error) {
32 :
33 0 : Link *link = userdata;
34 : Manager *manager;
35 : double interval_sec;
36 : uint64_t tx, rx;
37 :
38 0 : assert(bus);
39 0 : assert(reply);
40 0 : assert(userdata);
41 :
42 0 : manager = link->manager;
43 :
44 0 : if (!manager->use_speed_meter)
45 0 : return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is disabled.");
46 :
47 0 : if (manager->speed_meter_usec_old == 0)
48 0 : return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Speed meter is not active.");
49 :
50 0 : if (!link->stats_updated)
51 0 : return sd_bus_error_set(error, BUS_ERROR_SPEED_METER_INACTIVE, "Failed to measure bit-rates.");
52 :
53 0 : assert(manager->speed_meter_usec_new > manager->speed_meter_usec_old);
54 0 : interval_sec = (manager->speed_meter_usec_new - manager->speed_meter_usec_old) / USEC_PER_SEC;
55 :
56 0 : if (link->stats_new.tx_bytes > link->stats_old.tx_bytes)
57 0 : tx = (uint64_t) ((link->stats_new.tx_bytes - link->stats_old.tx_bytes) / interval_sec);
58 : else
59 0 : tx = (uint64_t) ((UINT64_MAX - (link->stats_old.tx_bytes - link->stats_new.tx_bytes)) / interval_sec);
60 :
61 0 : if (link->stats_new.rx_bytes > link->stats_old.rx_bytes)
62 0 : rx = (uint64_t) ((link->stats_new.rx_bytes - link->stats_old.rx_bytes) / interval_sec);
63 : else
64 0 : rx = (uint64_t) ((UINT64_MAX - (link->stats_old.rx_bytes - link->stats_new.rx_bytes)) / interval_sec);
65 :
66 0 : return sd_bus_message_append(reply, "(tt)", tx, rx);
67 : }
68 :
69 0 : static int verify_managed_link(Link *l, sd_bus_error *error) {
70 0 : assert(l);
71 :
72 0 : if (l->flags & IFF_LOOPBACK)
73 0 : return sd_bus_error_setf(error, BUS_ERROR_LINK_BUSY, "Link %s is loopback device.", l->ifname);
74 :
75 0 : return 0;
76 : }
77 :
78 0 : int bus_link_method_set_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
79 0 : _cleanup_strv_free_ char **ntp = NULL;
80 0 : Link *l = userdata;
81 : int r;
82 : char **i;
83 :
84 0 : assert(message);
85 0 : assert(l);
86 :
87 0 : r = verify_managed_link(l, error);
88 0 : if (r < 0)
89 0 : return r;
90 :
91 0 : r = sd_bus_message_read_strv(message, &ntp);
92 0 : if (r < 0)
93 0 : return r;
94 :
95 0 : STRV_FOREACH(i, ntp) {
96 0 : r = dns_name_is_valid_or_address(*i);
97 0 : if (r < 0)
98 0 : return r;
99 0 : if (r == 0)
100 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid NTP server: %s", *i);
101 : }
102 :
103 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
104 : "org.freedesktop.network1.set-ntp-servers",
105 : NULL, true, UID_INVALID,
106 0 : &l->manager->polkit_registry, error);
107 0 : if (r < 0)
108 0 : return r;
109 0 : if (r == 0)
110 0 : return 1; /* Polkit will call us back */
111 :
112 0 : strv_free_and_replace(l->ntp, ntp);
113 :
114 0 : (void) link_dirty(l);
115 :
116 0 : return sd_bus_reply_method_return(message, NULL);
117 : }
118 :
119 0 : int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
120 0 : _cleanup_free_ struct in_addr_data *dns = NULL;
121 0 : size_t allocated = 0, n = 0;
122 0 : Link *l = userdata;
123 : int r;
124 :
125 0 : assert(message);
126 0 : assert(l);
127 :
128 0 : r = verify_managed_link(l, error);
129 0 : if (r < 0)
130 0 : return r;
131 :
132 0 : r = sd_bus_message_enter_container(message, 'a', "(iay)");
133 0 : if (r < 0)
134 0 : return r;
135 :
136 0 : for (;;) {
137 : int family;
138 : size_t sz;
139 : const void *d;
140 :
141 : assert_cc(sizeof(int) == sizeof(int32_t));
142 :
143 0 : r = sd_bus_message_enter_container(message, 'r', "iay");
144 0 : if (r < 0)
145 0 : return r;
146 0 : if (r == 0)
147 0 : break;
148 :
149 0 : r = sd_bus_message_read(message, "i", &family);
150 0 : if (r < 0)
151 0 : return r;
152 :
153 0 : if (!IN_SET(family, AF_INET, AF_INET6))
154 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown address family %i", family);
155 :
156 0 : r = sd_bus_message_read_array(message, 'y', &d, &sz);
157 0 : if (r < 0)
158 0 : return r;
159 0 : if (sz != FAMILY_ADDRESS_SIZE(family))
160 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address size");
161 :
162 0 : if (!dns_server_address_valid(family, d))
163 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNS server address");
164 :
165 0 : r = sd_bus_message_exit_container(message);
166 0 : if (r < 0)
167 0 : return r;
168 :
169 0 : if (!GREEDY_REALLOC(dns, allocated, n+1))
170 0 : return -ENOMEM;
171 :
172 0 : dns[n].family = family;
173 0 : memcpy(&dns[n].address, d, sz);
174 0 : n++;
175 : }
176 :
177 0 : r = sd_bus_message_exit_container(message);
178 0 : if (r < 0)
179 0 : return r;
180 :
181 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
182 : "org.freedesktop.network1.set-dns-servers",
183 : NULL, true, UID_INVALID,
184 0 : &l->manager->polkit_registry, error);
185 0 : if (r < 0)
186 0 : return r;
187 0 : if (r == 0)
188 0 : return 1; /* Polkit will call us back */
189 :
190 0 : free_and_replace(l->dns, dns);
191 0 : l->n_dns = n;
192 :
193 0 : (void) link_dirty(l);
194 :
195 0 : return sd_bus_reply_method_return(message, NULL);
196 : }
197 :
198 0 : int bus_link_method_set_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
199 0 : _cleanup_(ordered_set_freep) OrderedSet *search_domains = NULL, *route_domains = NULL;
200 0 : Link *l = userdata;
201 : int r;
202 :
203 0 : assert(message);
204 0 : assert(l);
205 :
206 0 : r = verify_managed_link(l, error);
207 0 : if (r < 0)
208 0 : return r;
209 :
210 0 : r = sd_bus_message_enter_container(message, 'a', "(sb)");
211 0 : if (r < 0)
212 0 : return r;
213 :
214 0 : for (;;) {
215 0 : _cleanup_free_ char *str = NULL;
216 : OrderedSet **domains;
217 : const char *name;
218 : int route_only;
219 :
220 0 : r = sd_bus_message_read(message, "(sb)", &name, &route_only);
221 0 : if (r < 0)
222 0 : return r;
223 0 : if (r == 0)
224 0 : break;
225 :
226 0 : r = dns_name_is_valid(name);
227 0 : if (r < 0)
228 0 : return r;
229 0 : if (r == 0)
230 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
231 0 : if (!route_only && dns_name_is_root(name))
232 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
233 :
234 0 : r = dns_name_normalize(name, 0, &str);
235 0 : if (r < 0)
236 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
237 :
238 0 : domains = route_only ? &route_domains : &search_domains;
239 0 : r = ordered_set_ensure_allocated(domains, &string_hash_ops);
240 0 : if (r < 0)
241 0 : return r;
242 :
243 0 : r = ordered_set_put(*domains, str);
244 0 : if (r < 0)
245 0 : return r;
246 :
247 0 : TAKE_PTR(str);
248 : }
249 :
250 0 : r = sd_bus_message_exit_container(message);
251 0 : if (r < 0)
252 0 : return r;
253 :
254 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
255 : "org.freedesktop.network1.set-domains",
256 : NULL, true, UID_INVALID,
257 0 : &l->manager->polkit_registry, error);
258 0 : if (r < 0)
259 0 : return r;
260 0 : if (r == 0)
261 0 : return 1; /* Polkit will call us back */
262 :
263 0 : ordered_set_free_free(l->search_domains);
264 0 : ordered_set_free_free(l->route_domains);
265 0 : l->search_domains = TAKE_PTR(search_domains);
266 0 : l->route_domains = TAKE_PTR(route_domains);
267 :
268 0 : (void) link_dirty(l);
269 :
270 0 : return sd_bus_reply_method_return(message, NULL);
271 : }
272 :
273 0 : int bus_link_method_set_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
274 0 : Link *l = userdata;
275 : int r, b;
276 :
277 0 : assert(message);
278 0 : assert(l);
279 :
280 0 : r = verify_managed_link(l, error);
281 0 : if (r < 0)
282 0 : return r;
283 :
284 0 : r = sd_bus_message_read(message, "b", &b);
285 0 : if (r < 0)
286 0 : return r;
287 :
288 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
289 : "org.freedesktop.network1.set-default-route",
290 : NULL, true, UID_INVALID,
291 0 : &l->manager->polkit_registry, error);
292 0 : if (r < 0)
293 0 : return r;
294 0 : if (r == 0)
295 0 : return 1; /* Polkit will call us back */
296 :
297 0 : if (l->dns_default_route != b) {
298 0 : l->dns_default_route = b;
299 0 : (void) link_dirty(l);
300 : }
301 :
302 0 : return sd_bus_reply_method_return(message, NULL);
303 : }
304 :
305 0 : int bus_link_method_set_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
306 0 : Link *l = userdata;
307 : ResolveSupport mode;
308 : const char *llmnr;
309 : int r;
310 :
311 0 : assert(message);
312 0 : assert(l);
313 :
314 0 : r = verify_managed_link(l, error);
315 0 : if (r < 0)
316 0 : return r;
317 :
318 0 : r = sd_bus_message_read(message, "s", &llmnr);
319 0 : if (r < 0)
320 0 : return r;
321 :
322 0 : if (isempty(llmnr))
323 0 : mode = RESOLVE_SUPPORT_YES;
324 : else {
325 0 : mode = resolve_support_from_string(llmnr);
326 0 : if (mode < 0)
327 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid LLMNR setting: %s", llmnr);
328 : }
329 :
330 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
331 : "org.freedesktop.network1.set-llmnr",
332 : NULL, true, UID_INVALID,
333 0 : &l->manager->polkit_registry, error);
334 0 : if (r < 0)
335 0 : return r;
336 0 : if (r == 0)
337 0 : return 1; /* Polkit will call us back */
338 :
339 0 : if (l->llmnr != mode) {
340 0 : l->llmnr = mode;
341 0 : (void) link_dirty(l);
342 : }
343 :
344 0 : return sd_bus_reply_method_return(message, NULL);
345 : }
346 :
347 0 : int bus_link_method_set_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
348 0 : Link *l = userdata;
349 : ResolveSupport mode;
350 : const char *mdns;
351 : int r;
352 :
353 0 : assert(message);
354 0 : assert(l);
355 :
356 0 : r = verify_managed_link(l, error);
357 0 : if (r < 0)
358 0 : return r;
359 :
360 0 : r = sd_bus_message_read(message, "s", &mdns);
361 0 : if (r < 0)
362 0 : return r;
363 :
364 0 : if (isempty(mdns))
365 0 : mode = RESOLVE_SUPPORT_NO;
366 : else {
367 0 : mode = resolve_support_from_string(mdns);
368 0 : if (mode < 0)
369 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid MulticastDNS setting: %s", mdns);
370 : }
371 :
372 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
373 : "org.freedesktop.network1.set-mdns",
374 : NULL, true, UID_INVALID,
375 0 : &l->manager->polkit_registry, error);
376 0 : if (r < 0)
377 0 : return r;
378 0 : if (r == 0)
379 0 : return 1; /* Polkit will call us back */
380 :
381 0 : if (l->mdns != mode) {
382 0 : l->mdns = mode;
383 0 : (void) link_dirty(l);
384 : }
385 :
386 0 : return sd_bus_reply_method_return(message, NULL);
387 : }
388 :
389 0 : int bus_link_method_set_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
390 0 : Link *l = userdata;
391 : const char *dns_over_tls;
392 : DnsOverTlsMode mode;
393 : int r;
394 :
395 0 : assert(message);
396 0 : assert(l);
397 :
398 0 : r = verify_managed_link(l, error);
399 0 : if (r < 0)
400 0 : return r;
401 :
402 0 : r = sd_bus_message_read(message, "s", &dns_over_tls);
403 0 : if (r < 0)
404 0 : return r;
405 :
406 0 : if (isempty(dns_over_tls))
407 0 : mode = _DNS_OVER_TLS_MODE_INVALID;
408 : else {
409 0 : mode = dns_over_tls_mode_from_string(dns_over_tls);
410 0 : if (mode < 0)
411 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSOverTLS setting: %s", dns_over_tls);
412 : }
413 :
414 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
415 : "org.freedesktop.network1.set-dns-over-tls",
416 : NULL, true, UID_INVALID,
417 0 : &l->manager->polkit_registry, error);
418 0 : if (r < 0)
419 0 : return r;
420 0 : if (r == 0)
421 0 : return 1; /* Polkit will call us back */
422 :
423 0 : if (l->dns_over_tls_mode != mode) {
424 0 : l->dns_over_tls_mode = mode;
425 0 : (void) link_dirty(l);
426 : }
427 :
428 0 : return sd_bus_reply_method_return(message, NULL);
429 : }
430 :
431 0 : int bus_link_method_set_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
432 0 : Link *l = userdata;
433 : const char *dnssec;
434 : DnssecMode mode;
435 : int r;
436 :
437 0 : assert(message);
438 0 : assert(l);
439 :
440 0 : r = verify_managed_link(l, error);
441 0 : if (r < 0)
442 0 : return r;
443 :
444 0 : r = sd_bus_message_read(message, "s", &dnssec);
445 0 : if (r < 0)
446 0 : return r;
447 :
448 0 : if (isempty(dnssec))
449 0 : mode = _DNSSEC_MODE_INVALID;
450 : else {
451 0 : mode = dnssec_mode_from_string(dnssec);
452 0 : if (mode < 0)
453 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid DNSSEC setting: %s", dnssec);
454 : }
455 :
456 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
457 : "org.freedesktop.network1.set-dnssec",
458 : NULL, true, UID_INVALID,
459 0 : &l->manager->polkit_registry, error);
460 0 : if (r < 0)
461 0 : return r;
462 0 : if (r == 0)
463 0 : return 1; /* Polkit will call us back */
464 :
465 0 : if (l->dnssec_mode != mode) {
466 0 : l->dnssec_mode = mode;
467 0 : (void) link_dirty(l);
468 : }
469 :
470 0 : return sd_bus_reply_method_return(message, NULL);
471 : }
472 :
473 0 : int bus_link_method_set_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
474 0 : _cleanup_set_free_free_ Set *ns = NULL;
475 0 : _cleanup_strv_free_ char **ntas = NULL;
476 0 : Link *l = userdata;
477 : int r;
478 : char **i;
479 :
480 0 : assert(message);
481 0 : assert(l);
482 :
483 0 : r = verify_managed_link(l, error);
484 0 : if (r < 0)
485 0 : return r;
486 :
487 0 : r = sd_bus_message_read_strv(message, &ntas);
488 0 : if (r < 0)
489 0 : return r;
490 :
491 0 : STRV_FOREACH(i, ntas) {
492 0 : r = dns_name_is_valid(*i);
493 0 : if (r < 0)
494 0 : return r;
495 0 : if (r == 0)
496 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid negative trust anchor domain: %s", *i);
497 : }
498 :
499 0 : ns = set_new(&dns_name_hash_ops);
500 0 : if (!ns)
501 0 : return -ENOMEM;
502 :
503 0 : STRV_FOREACH(i, ntas) {
504 0 : r = set_put_strdup(ns, *i);
505 0 : if (r < 0)
506 0 : return r;
507 : }
508 :
509 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
510 : "org.freedesktop.network1.set-dnssec-negative-trust-anchors",
511 : NULL, true, UID_INVALID,
512 0 : &l->manager->polkit_registry, error);
513 0 : if (r < 0)
514 0 : return r;
515 0 : if (r == 0)
516 0 : return 1; /* Polkit will call us back */
517 :
518 0 : set_free_free(l->dnssec_negative_trust_anchors);
519 0 : l->dnssec_negative_trust_anchors = TAKE_PTR(ns);
520 :
521 0 : (void) link_dirty(l);
522 :
523 0 : return sd_bus_reply_method_return(message, NULL);
524 : }
525 :
526 0 : int bus_link_method_revert_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error) {
527 0 : Link *l = userdata;
528 : int r;
529 :
530 0 : assert(message);
531 0 : assert(l);
532 :
533 0 : r = verify_managed_link(l, error);
534 0 : if (r < 0)
535 0 : return r;
536 :
537 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
538 : "org.freedesktop.network1.revert-ntp",
539 : NULL, true, UID_INVALID,
540 0 : &l->manager->polkit_registry, error);
541 0 : if (r < 0)
542 0 : return r;
543 0 : if (r == 0)
544 0 : return 1; /* Polkit will call us back */
545 :
546 0 : link_ntp_settings_clear(l);
547 0 : (void) link_dirty(l);
548 :
549 0 : return sd_bus_reply_method_return(message, NULL);
550 : }
551 :
552 0 : int bus_link_method_revert_dns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
553 0 : Link *l = userdata;
554 : int r;
555 :
556 0 : assert(message);
557 0 : assert(l);
558 :
559 0 : r = verify_managed_link(l, error);
560 0 : if (r < 0)
561 0 : return r;
562 :
563 0 : r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
564 : "org.freedesktop.network1.revert-dns",
565 : NULL, true, UID_INVALID,
566 0 : &l->manager->polkit_registry, error);
567 0 : if (r < 0)
568 0 : return r;
569 0 : if (r == 0)
570 0 : return 1; /* Polkit will call us back */
571 :
572 0 : link_dns_settings_clear(l);
573 0 : (void) link_dirty(l);
574 :
575 0 : return sd_bus_reply_method_return(message, NULL);
576 : }
577 :
578 : const sd_bus_vtable link_vtable[] = {
579 : SD_BUS_VTABLE_START(0),
580 :
581 : SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
582 : SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Link, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
583 : SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Link, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
584 : SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
585 : SD_BUS_PROPERTY("BitRates", "(tt)", property_get_bit_rates, 0, 0),
586 :
587 : SD_BUS_METHOD("SetNTP", "as", NULL, bus_link_method_set_ntp_servers, SD_BUS_VTABLE_UNPRIVILEGED),
588 : SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, SD_BUS_VTABLE_UNPRIVILEGED),
589 : SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_domains, SD_BUS_VTABLE_UNPRIVILEGED),
590 : SD_BUS_METHOD("SetDefaultRoute", "b", NULL, bus_link_method_set_default_route, SD_BUS_VTABLE_UNPRIVILEGED),
591 : SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, SD_BUS_VTABLE_UNPRIVILEGED),
592 : SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, SD_BUS_VTABLE_UNPRIVILEGED),
593 : SD_BUS_METHOD("SetDNSOverTLS", "s", NULL, bus_link_method_set_dns_over_tls, SD_BUS_VTABLE_UNPRIVILEGED),
594 : SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, SD_BUS_VTABLE_UNPRIVILEGED),
595 : SD_BUS_METHOD("SetDNSSECNegativeTrustAnchors", "as", NULL, bus_link_method_set_dnssec_negative_trust_anchors, SD_BUS_VTABLE_UNPRIVILEGED),
596 : SD_BUS_METHOD("RevertNTP", NULL, NULL, bus_link_method_revert_ntp, SD_BUS_VTABLE_UNPRIVILEGED),
597 : SD_BUS_METHOD("RevertDNS", NULL, NULL, bus_link_method_revert_dns, SD_BUS_VTABLE_UNPRIVILEGED),
598 :
599 : SD_BUS_VTABLE_END
600 : };
601 :
602 0 : char *link_bus_path(Link *link) {
603 0 : _cleanup_free_ char *ifindex = NULL;
604 : char *p;
605 : int r;
606 :
607 0 : assert(link);
608 0 : assert(link->ifindex > 0);
609 :
610 0 : if (asprintf(&ifindex, "%d", link->ifindex) < 0)
611 0 : return NULL;
612 :
613 0 : r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p);
614 0 : if (r < 0)
615 0 : return NULL;
616 :
617 0 : return p;
618 : }
619 :
620 0 : int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
621 0 : _cleanup_strv_free_ char **l = NULL;
622 0 : Manager *m = userdata;
623 0 : unsigned c = 0;
624 : Link *link;
625 : Iterator i;
626 :
627 0 : assert(bus);
628 0 : assert(path);
629 0 : assert(m);
630 0 : assert(nodes);
631 :
632 0 : l = new0(char*, hashmap_size(m->links) + 1);
633 0 : if (!l)
634 0 : return -ENOMEM;
635 :
636 0 : HASHMAP_FOREACH(link, m->links, i) {
637 : char *p;
638 :
639 0 : p = link_bus_path(link);
640 0 : if (!p)
641 0 : return -ENOMEM;
642 :
643 0 : l[c++] = p;
644 : }
645 :
646 0 : l[c] = NULL;
647 0 : *nodes = TAKE_PTR(l);
648 :
649 0 : return 1;
650 : }
651 :
652 0 : int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
653 0 : _cleanup_free_ char *identifier = NULL;
654 0 : Manager *m = userdata;
655 : Link *link;
656 : int ifindex, r;
657 :
658 0 : assert(bus);
659 0 : assert(path);
660 0 : assert(interface);
661 0 : assert(m);
662 0 : assert(found);
663 :
664 0 : r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier);
665 0 : if (r <= 0)
666 0 : return 0;
667 :
668 0 : r = parse_ifindex(identifier, &ifindex);
669 0 : if (r < 0)
670 0 : return 0;
671 :
672 0 : r = link_get(m, ifindex, &link);
673 0 : if (r < 0)
674 0 : return 0;
675 :
676 0 : *found = link;
677 :
678 0 : return 1;
679 : }
680 :
681 11 : int link_send_changed_strv(Link *link, char **properties) {
682 11 : _cleanup_free_ char *p = NULL;
683 :
684 11 : assert(link);
685 11 : assert(link->manager);
686 11 : assert(properties);
687 :
688 11 : if (!link->manager->bus)
689 11 : return 0;
690 :
691 0 : p = link_bus_path(link);
692 0 : if (!p)
693 0 : return -ENOMEM;
694 :
695 0 : return sd_bus_emit_properties_changed_strv(
696 0 : link->manager->bus,
697 : p,
698 : "org.freedesktop.network1.Link",
699 : properties);
700 : }
701 :
702 6 : int link_send_changed(Link *link, const char *property, ...) {
703 : char **properties;
704 :
705 6 : properties = strv_from_stdarg_alloca(property);
706 :
707 6 : return link_send_changed_strv(link, properties);
708 : }
|