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