]> git.ipfire.org Git - people/ms/network.git/blob - src/networkd/bus.c
Makefile: Fix typo in localstatedir
[people/ms/network.git] / src / networkd / bus.c
1 /*#############################################################################
2 # #
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <stdlib.h>
22
23 #include <systemd/sd-bus.h>
24 #include <systemd/sd-event.h>
25
26 #include "bus.h"
27 #include "daemon.h"
28 #include "daemon-bus.h"
29 #include "logging.h"
30
31 static int nw_bus_on_connect(sd_bus_message* m, void* data, sd_bus_error* error) {
32 nw_daemon* daemon = (nw_daemon*)data;
33
34 DEBUG("Connected to D-Bus\n");
35
36 return 0;
37 }
38
39 int nw_bus_connect(sd_bus** bus, sd_event* loop, nw_daemon* daemon) {
40 sd_bus* b = NULL;
41 int r;
42
43 // Create a bus object
44 r = sd_bus_new(&b);
45 if (r < 0) {
46 ERROR("Could not allocate a bus object: %s\n", strerror(-r));
47 return 1;
48 }
49
50 // Set description
51 r = sd_bus_set_description(b, NETWORKD_BUS_DESCRIPTION);
52 if (r < 0) {
53 ERROR("Could not set bus description: %s\n", strerror(-r));
54 return 1;
55 }
56
57 const char* address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
58 if (!address)
59 address = DEFAULT_SYSTEM_BUS_ADDRESS;
60
61 // Set bus address
62 r = sd_bus_set_address(b, address);
63 if (r < 0) {
64 ERROR("Could not set bus address: %s\n", strerror(-r));
65 return 1;
66 }
67
68 // Set bus client
69 r = sd_bus_set_bus_client(b, 1);
70 if (r < 0) {
71 ERROR("Could not set bus client: %s\n", strerror(-r));
72 return 1;
73 }
74
75 // Request some credentials for all messages
76 r = sd_bus_negotiate_creds(b, 1,
77 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
78 if (r < 0) {
79 ERROR("Could not negotiate creds: %s\n", strerror(-r));
80 return 1;
81 }
82
83 // Automatically bind when the socket is available
84 r = sd_bus_set_watch_bind(b, 1);
85 if (r < 0) {
86 ERROR("Could not watch socket: %s\n", strerror(-r));
87 return 1;
88 }
89
90 // Emit a connected signal when we are connected
91 r = sd_bus_set_connected_signal(b, 1);
92 if (r < 0) {
93 ERROR("Could not enable sending a connect signal: %s\n", strerror(-r));
94 return 1;
95 }
96
97 // Connect to the bus
98 r = sd_bus_start(b);
99 if (r < 0) {
100 ERROR("Could not connect to bus: %s\n", strerror(-r));
101 return 1;
102 }
103
104 // Register the implementation
105 r = nw_bus_register_implementation(b, &daemon_bus_impl, daemon);
106 if (r)
107 return r;
108
109 // Request interface name
110 r = sd_bus_request_name_async(b, NULL, "org.ipfire.network1", 0, NULL, NULL);
111 if (r < 0) {
112 ERROR("Could not request bus name: %s\n", strerror(-r));
113 return 1;
114 }
115
116 // Attach the event loop
117 r = sd_bus_attach_event(b, loop, 0);
118 if (r < 0) {
119 ERROR("Could not attach bus to event loop: %s\n", strerror(-r));
120 return 1;
121 }
122
123 // Request receiving a connect signal
124 r = sd_bus_match_signal_async(b, NULL, "org.freedesktop.DBus.Local",
125 NULL, "org.freedesktop.DBus.Local", "Connected", nw_bus_on_connect, NULL, NULL);
126 if (r < 0) {
127 ERROR("Could not request match on Connected signal: %s\n", strerror(-r));
128 return 1;
129 }
130
131 // Return reference
132 *bus = b;
133
134 return 0;
135 }
136
137 int nw_bus_register_implementation(sd_bus* bus,
138 const struct nw_bus_implementation* impl, void* data) {
139 int r;
140
141 DEBUG("Registering bus object implementation for path=%s iface=%s\n",
142 impl->path, impl->interface);
143
144 // Register vtables
145 for (const sd_bus_vtable** vtable = impl->vtables; vtable && *vtable; vtable++) {
146 r = sd_bus_add_object_vtable(bus, NULL, impl->path, impl->interface, *vtable, data);
147 if (r < 0) {
148 ERROR("Could not register bus path %s with interface %s: %m\n",
149 impl->path, impl->interface);
150 return 1;
151 }
152 }
153
154 // Register fallback vtables
155 for (const struct nw_bus_vtable_pair* p = impl->fallback_vtables; p && p->vtable; p++) {
156 r = sd_bus_add_fallback_vtable(bus, NULL, impl->path, impl->interface,
157 p->vtable, p->object_find, data);
158 if (r < 0) {
159 ERROR("Could not register bus path %s with interface %s: %m\n",
160 impl->path, impl->interface);
161 return 1;
162 }
163 }
164
165 // Register the node enumerator
166 if (impl->node_enumerator) {
167 r = sd_bus_add_node_enumerator(bus, NULL, impl->path, impl->node_enumerator, data);
168 if (r < 0) {
169 ERROR("Could not add the node enumerator for %s: %m\n", impl->path);
170 return 1;
171 }
172 }
173
174 // Register any child implementations
175 for (int i = 0; impl->children && impl->children[i]; i++) {
176 r = nw_bus_register_implementation(bus, impl->children[i], data);
177 if (r)
178 return r;
179 }
180
181 return 0;
182 }