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-message-util.h"
10 #include "bus-polkit.h"
11 #include "networkd-dhcp-server-bus.h"
12 #include "networkd-json.h"
13 #include "networkd-link-bus.h"
14 #include "networkd-link.h"
15 #include "networkd-manager-bus.h"
16 #include "networkd-manager.h"
17 #include "networkd-network-bus.h"
18 #include "path-util.h"
19 #include "strv.h"
20 #include "user-util.h"
21
method_list_links(sd_bus_message * message,void * userdata,sd_bus_error * error)22 static int method_list_links(sd_bus_message *message, void *userdata, sd_bus_error *error) {
23 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
24 Manager *manager = userdata;
25 Link *link;
26 int r;
27
28 r = sd_bus_message_new_method_return(message, &reply);
29 if (r < 0)
30 return r;
31
32 r = sd_bus_message_open_container(reply, 'a', "(iso)");
33 if (r < 0)
34 return r;
35
36 HASHMAP_FOREACH(link, manager->links_by_index) {
37 _cleanup_free_ char *path = NULL;
38
39 path = link_bus_path(link);
40 if (!path)
41 return -ENOMEM;
42
43 r = sd_bus_message_append(
44 reply, "(iso)",
45 link->ifindex,
46 link->ifname,
47 empty_to_root(path));
48 if (r < 0)
49 return r;
50 }
51
52 r = sd_bus_message_close_container(reply);
53 if (r < 0)
54 return r;
55
56 return sd_bus_send(NULL, reply, NULL);
57 }
58
method_get_link_by_name(sd_bus_message * message,void * userdata,sd_bus_error * error)59 static int method_get_link_by_name(sd_bus_message *message, void *userdata, sd_bus_error *error) {
60 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
61 _cleanup_free_ char *path = NULL;
62 Manager *manager = userdata;
63 const char *name;
64 Link *link;
65 int r;
66
67 r = sd_bus_message_read(message, "s", &name);
68 if (r < 0)
69 return r;
70
71 if (link_get_by_name(manager, name, &link) < 0)
72 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %s not known", name);
73
74 r = sd_bus_message_new_method_return(message, &reply);
75 if (r < 0)
76 return r;
77
78 path = link_bus_path(link);
79 if (!path)
80 return -ENOMEM;
81
82 r = sd_bus_message_append(reply, "io", link->ifindex, empty_to_root(path));
83 if (r < 0)
84 return r;
85
86 return sd_bus_send(NULL, reply, NULL);
87 }
88
method_get_link_by_index(sd_bus_message * message,void * userdata,sd_bus_error * error)89 static int method_get_link_by_index(sd_bus_message *message, void *userdata, sd_bus_error *error) {
90 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
91 _cleanup_free_ char *path = NULL;
92 Manager *manager = userdata;
93 int ifindex, r;
94 Link *link;
95
96 r = bus_message_read_ifindex(message, error, &ifindex);
97 if (r < 0)
98 return r;
99
100 r = link_get_by_index(manager, ifindex, &link);
101 if (r < 0)
102 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
103
104 r = sd_bus_message_new_method_return(message, &reply);
105 if (r < 0)
106 return r;
107
108 path = link_bus_path(link);
109 if (!path)
110 return -ENOMEM;
111
112 r = sd_bus_message_append(reply, "so", link->ifname, empty_to_root(path));
113 if (r < 0)
114 return r;
115
116 return sd_bus_send(NULL, reply, NULL);
117 }
118
call_link_method(Manager * m,sd_bus_message * message,sd_bus_message_handler_t handler,sd_bus_error * error)119 static int call_link_method(Manager *m, sd_bus_message *message, sd_bus_message_handler_t handler, sd_bus_error *error) {
120 int ifindex, r;
121 Link *l;
122
123 assert(m);
124 assert(message);
125 assert(handler);
126
127 r = bus_message_read_ifindex(message, error, &ifindex);
128 if (r < 0)
129 return r;
130
131 r = link_get_by_index(m, ifindex, &l);
132 if (r < 0)
133 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %i not known", ifindex);
134
135 return handler(message, l, error);
136 }
137
bus_method_set_link_ntp_servers(sd_bus_message * message,void * userdata,sd_bus_error * error)138 static int bus_method_set_link_ntp_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
139 return call_link_method(userdata, message, bus_link_method_set_ntp_servers, error);
140 }
141
bus_method_set_link_dns_servers(sd_bus_message * message,void * userdata,sd_bus_error * error)142 static int bus_method_set_link_dns_servers(sd_bus_message *message, void *userdata, sd_bus_error *error) {
143 return call_link_method(userdata, message, bus_link_method_set_dns_servers, error);
144 }
145
bus_method_set_link_dns_servers_ex(sd_bus_message * message,void * userdata,sd_bus_error * error)146 static int bus_method_set_link_dns_servers_ex(sd_bus_message *message, void *userdata, sd_bus_error *error) {
147 return call_link_method(userdata, message, bus_link_method_set_dns_servers_ex, error);
148 }
149
bus_method_set_link_domains(sd_bus_message * message,void * userdata,sd_bus_error * error)150 static int bus_method_set_link_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
151 return call_link_method(userdata, message, bus_link_method_set_domains, error);
152 }
153
bus_method_set_link_default_route(sd_bus_message * message,void * userdata,sd_bus_error * error)154 static int bus_method_set_link_default_route(sd_bus_message *message, void *userdata, sd_bus_error *error) {
155 return call_link_method(userdata, message, bus_link_method_set_default_route, error);
156 }
157
bus_method_set_link_llmnr(sd_bus_message * message,void * userdata,sd_bus_error * error)158 static int bus_method_set_link_llmnr(sd_bus_message *message, void *userdata, sd_bus_error *error) {
159 return call_link_method(userdata, message, bus_link_method_set_llmnr, error);
160 }
161
bus_method_set_link_mdns(sd_bus_message * message,void * userdata,sd_bus_error * error)162 static int bus_method_set_link_mdns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
163 return call_link_method(userdata, message, bus_link_method_set_mdns, error);
164 }
165
bus_method_set_link_dns_over_tls(sd_bus_message * message,void * userdata,sd_bus_error * error)166 static int bus_method_set_link_dns_over_tls(sd_bus_message *message, void *userdata, sd_bus_error *error) {
167 return call_link_method(userdata, message, bus_link_method_set_dns_over_tls, error);
168 }
169
bus_method_set_link_dnssec(sd_bus_message * message,void * userdata,sd_bus_error * error)170 static int bus_method_set_link_dnssec(sd_bus_message *message, void *userdata, sd_bus_error *error) {
171 return call_link_method(userdata, message, bus_link_method_set_dnssec, error);
172 }
173
bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message * message,void * userdata,sd_bus_error * error)174 static int bus_method_set_link_dnssec_negative_trust_anchors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
175 return call_link_method(userdata, message, bus_link_method_set_dnssec_negative_trust_anchors, error);
176 }
177
bus_method_revert_link_ntp(sd_bus_message * message,void * userdata,sd_bus_error * error)178 static int bus_method_revert_link_ntp(sd_bus_message *message, void *userdata, sd_bus_error *error) {
179 return call_link_method(userdata, message, bus_link_method_revert_ntp, error);
180 }
181
bus_method_revert_link_dns(sd_bus_message * message,void * userdata,sd_bus_error * error)182 static int bus_method_revert_link_dns(sd_bus_message *message, void *userdata, sd_bus_error *error) {
183 return call_link_method(userdata, message, bus_link_method_revert_dns, error);
184 }
185
bus_method_renew_link(sd_bus_message * message,void * userdata,sd_bus_error * error)186 static int bus_method_renew_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
187 return call_link_method(userdata, message, bus_link_method_renew, error);
188 }
189
bus_method_force_renew_link(sd_bus_message * message,void * userdata,sd_bus_error * error)190 static int bus_method_force_renew_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
191 return call_link_method(userdata, message, bus_link_method_force_renew, error);
192 }
193
bus_method_reconfigure_link(sd_bus_message * message,void * userdata,sd_bus_error * error)194 static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
195 return call_link_method(userdata, message, bus_link_method_reconfigure, error);
196 }
197
bus_method_reload(sd_bus_message * message,void * userdata,sd_bus_error * error)198 static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
199 Manager *manager = userdata;
200 Link *link;
201 int r;
202
203 r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
204 "org.freedesktop.network1.reload",
205 NULL, true, UID_INVALID,
206 &manager->polkit_registry, error);
207 if (r < 0)
208 return r;
209 if (r == 0)
210 return 1; /* Polkit will call us back */
211
212 r = netdev_load(manager, true);
213 if (r < 0)
214 return r;
215
216 r = network_reload(manager);
217 if (r < 0)
218 return r;
219
220 HASHMAP_FOREACH(link, manager->links_by_index) {
221 r = link_reconfigure(link, /* force = */ false);
222 if (r < 0)
223 return r;
224 }
225
226 return sd_bus_reply_method_return(message, NULL);
227 }
228
bus_method_describe_link(sd_bus_message * message,void * userdata,sd_bus_error * error)229 static int bus_method_describe_link(sd_bus_message *message, void *userdata, sd_bus_error *error) {
230 return call_link_method(userdata, message, bus_link_method_describe, error);
231 }
232
bus_method_describe(sd_bus_message * message,void * userdata,sd_bus_error * error)233 static int bus_method_describe(sd_bus_message *message, void *userdata, sd_bus_error *error) {
234 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
235 _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
236 _cleanup_free_ char *text = NULL;
237 Manager *manager = userdata;
238 int r;
239
240 assert(message);
241 assert(manager);
242
243 r = manager_build_json(manager, &v);
244 if (r < 0)
245 return log_error_errno(r, "Failed to build JSON data: %m");
246
247 r = json_variant_format(v, 0, &text);
248 if (r < 0)
249 return log_error_errno(r, "Failed to format JSON data: %m");
250
251 r = sd_bus_message_new_method_return(message, &reply);
252 if (r < 0)
253 return r;
254
255 r = sd_bus_message_append(reply, "s", text);
256 if (r < 0)
257 return r;
258
259 return sd_bus_send(NULL, reply, NULL);
260 }
261
property_get_namespace_id(sd_bus * bus,const char * path,const char * interface,const char * property,sd_bus_message * reply,void * userdata,sd_bus_error * error)262 static int property_get_namespace_id(
263 sd_bus *bus,
264 const char *path,
265 const char *interface,
266 const char *property,
267 sd_bus_message *reply,
268 void *userdata,
269 sd_bus_error *error) {
270
271 uint64_t id = 0;
272 struct stat st;
273
274 assert(bus);
275 assert(reply);
276
277 /* Returns our own network namespace ID, i.e. the inode number of /proc/self/ns/net. This allows
278 * unprivileged clients to determine whether they are in the same network namespace as us (note that
279 * access to that path is restricted, thus they can't check directly unless privileged). */
280
281 if (stat("/proc/self/ns/net", &st) < 0) {
282 log_warning_errno(errno, "Failed to stat network namespace, ignoring: %m");
283 id = 0;
284 } else
285 id = st.st_ino;
286
287 return sd_bus_message_append(reply, "t", id);
288 }
289
290 static const sd_bus_vtable manager_vtable[] = {
291 SD_BUS_VTABLE_START(0),
292
293 SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
294 SD_BUS_PROPERTY("CarrierState", "s", property_get_carrier_state, offsetof(Manager, carrier_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
295 SD_BUS_PROPERTY("AddressState", "s", property_get_address_state, offsetof(Manager, address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
296 SD_BUS_PROPERTY("IPv4AddressState", "s", property_get_address_state, offsetof(Manager, ipv4_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
297 SD_BUS_PROPERTY("IPv6AddressState", "s", property_get_address_state, offsetof(Manager, ipv6_address_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
298 SD_BUS_PROPERTY("OnlineState", "s", property_get_online_state, offsetof(Manager, online_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
299 SD_BUS_PROPERTY("NamespaceId", "t", property_get_namespace_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
300
301 SD_BUS_METHOD_WITH_ARGS("ListLinks",
302 SD_BUS_NO_ARGS,
303 SD_BUS_RESULT("a(iso)", links),
304 method_list_links,
305 SD_BUS_VTABLE_UNPRIVILEGED),
306 SD_BUS_METHOD_WITH_ARGS("GetLinkByName",
307 SD_BUS_ARGS("s", name),
308 SD_BUS_RESULT("i", ifindex, "o", path),
309 method_get_link_by_name,
310 SD_BUS_VTABLE_UNPRIVILEGED),
311 SD_BUS_METHOD_WITH_ARGS("GetLinkByIndex",
312 SD_BUS_ARGS("i", ifindex),
313 SD_BUS_RESULT("s", name, "o", path),
314 method_get_link_by_index,
315 SD_BUS_VTABLE_UNPRIVILEGED),
316 SD_BUS_METHOD_WITH_ARGS("SetLinkNTP",
317 SD_BUS_ARGS("i", ifindex, "as", servers),
318 SD_BUS_NO_RESULT,
319 bus_method_set_link_ntp_servers,
320 SD_BUS_VTABLE_UNPRIVILEGED),
321 SD_BUS_METHOD_WITH_ARGS("SetLinkDNS",
322 SD_BUS_ARGS("i", ifindex, "a(iay)", addresses),
323 SD_BUS_NO_RESULT,
324 bus_method_set_link_dns_servers,
325 SD_BUS_VTABLE_UNPRIVILEGED),
326 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSEx",
327 SD_BUS_ARGS("i", ifindex, "a(iayqs)", addresses),
328 SD_BUS_NO_RESULT,
329 bus_method_set_link_dns_servers_ex,
330 SD_BUS_VTABLE_UNPRIVILEGED),
331 SD_BUS_METHOD_WITH_ARGS("SetLinkDomains",
332 SD_BUS_ARGS("i", ifindex, "a(sb)", domains),
333 SD_BUS_NO_RESULT,
334 bus_method_set_link_domains,
335 SD_BUS_VTABLE_UNPRIVILEGED),
336 SD_BUS_METHOD_WITH_ARGS("SetLinkDefaultRoute",
337 SD_BUS_ARGS("i", ifindex, "b", enable),
338 SD_BUS_NO_RESULT,
339 bus_method_set_link_default_route,
340 SD_BUS_VTABLE_UNPRIVILEGED),
341 SD_BUS_METHOD_WITH_ARGS("SetLinkLLMNR",
342 SD_BUS_ARGS("i", ifindex, "s", mode),
343 SD_BUS_NO_RESULT,
344 bus_method_set_link_llmnr,
345 SD_BUS_VTABLE_UNPRIVILEGED),
346 SD_BUS_METHOD_WITH_ARGS("SetLinkMulticastDNS",
347 SD_BUS_ARGS("i", ifindex, "s", mode),
348 SD_BUS_NO_RESULT,
349 bus_method_set_link_mdns,
350 SD_BUS_VTABLE_UNPRIVILEGED),
351 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSOverTLS",
352 SD_BUS_ARGS("i", ifindex, "s", mode),
353 SD_BUS_NO_RESULT,
354 bus_method_set_link_dns_over_tls,
355 SD_BUS_VTABLE_UNPRIVILEGED),
356 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSEC",
357 SD_BUS_ARGS("i", ifindex, "s", mode),
358 SD_BUS_NO_RESULT,
359 bus_method_set_link_dnssec,
360 SD_BUS_VTABLE_UNPRIVILEGED),
361 SD_BUS_METHOD_WITH_ARGS("SetLinkDNSSECNegativeTrustAnchors",
362 SD_BUS_ARGS("i", ifindex, "as", names),
363 SD_BUS_NO_RESULT,
364 bus_method_set_link_dnssec_negative_trust_anchors,
365 SD_BUS_VTABLE_UNPRIVILEGED),
366 SD_BUS_METHOD_WITH_ARGS("RevertLinkNTP",
367 SD_BUS_ARGS("i", ifindex),
368 SD_BUS_NO_RESULT,
369 bus_method_revert_link_ntp,
370 SD_BUS_VTABLE_UNPRIVILEGED),
371 SD_BUS_METHOD_WITH_ARGS("RevertLinkDNS",
372 SD_BUS_ARGS("i", ifindex),
373 SD_BUS_NO_RESULT,
374 bus_method_revert_link_dns,
375 SD_BUS_VTABLE_UNPRIVILEGED),
376 SD_BUS_METHOD_WITH_ARGS("RenewLink",
377 SD_BUS_ARGS("i", ifindex),
378 SD_BUS_NO_RESULT,
379 bus_method_renew_link,
380 SD_BUS_VTABLE_UNPRIVILEGED),
381 SD_BUS_METHOD_WITH_ARGS("ForceRenewLink",
382 SD_BUS_ARGS("i", ifindex),
383 SD_BUS_NO_RESULT,
384 bus_method_force_renew_link,
385 SD_BUS_VTABLE_UNPRIVILEGED),
386 SD_BUS_METHOD_WITH_ARGS("ReconfigureLink",
387 SD_BUS_ARGS("i", ifindex),
388 SD_BUS_NO_RESULT,
389 bus_method_reconfigure_link,
390 SD_BUS_VTABLE_UNPRIVILEGED),
391 SD_BUS_METHOD_WITH_ARGS("Reload",
392 SD_BUS_NO_ARGS,
393 SD_BUS_NO_RESULT,
394 bus_method_reload,
395 SD_BUS_VTABLE_UNPRIVILEGED),
396 SD_BUS_METHOD_WITH_ARGS("DescribeLink",
397 SD_BUS_ARGS("i", ifindex),
398 SD_BUS_RESULT("s", json),
399 bus_method_describe_link,
400 SD_BUS_VTABLE_UNPRIVILEGED),
401 SD_BUS_METHOD_WITH_ARGS("Describe",
402 SD_BUS_NO_ARGS,
403 SD_BUS_RESULT("s", json),
404 bus_method_describe,
405 SD_BUS_VTABLE_UNPRIVILEGED),
406
407 SD_BUS_VTABLE_END
408 };
409
manager_send_changed_strv(Manager * manager,char ** properties)410 int manager_send_changed_strv(Manager *manager, char **properties) {
411 assert(manager);
412 assert(properties);
413
414 if (sd_bus_is_ready(manager->bus) <= 0)
415 return 0;
416
417 return sd_bus_emit_properties_changed_strv(
418 manager->bus,
419 "/org/freedesktop/network1",
420 "org.freedesktop.network1.Manager",
421 properties);
422 }
423
424 const BusObjectImplementation manager_object = {
425 "/org/freedesktop/network1",
426 "org.freedesktop.network1.Manager",
427 .vtables = BUS_VTABLES(manager_vtable),
428 .children = BUS_IMPLEMENTATIONS(&dhcp_server_object, &link_object, &network_object),
429 };
430