]> git.ipfire.org Git - network.git/blame - src/networkd/bus.c
networkd: Implement enumerating zones on the bus
[network.git] / src / networkd / bus.c
CommitLineData
09a6af17
MT
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#include <string.h>
23
24#include <systemd/sd-bus.h>
25#include <systemd/sd-event.h>
26
27#include "bus.h"
28#include "daemon.h"
29#include "logging.h"
ebc65f19 30#include "zone-bus.h"
09a6af17 31
bf42846c 32static int nw_bus_daemon_reload(sd_bus_message* m, void* data, sd_bus_error* error) {
1dc98e40
MT
33 struct nw_daemon* daemon = (struct nw_daemon*)data;
34
35 // Reload the daemon
36 nw_daemon_reload(daemon);
37
38 // Respond with an empty message
39 return sd_bus_reply_method_return(m, NULL);
09a6af17
MT
40}
41
9806a600
MT
42static const sd_bus_vtable daemon_vtable[] = {
43 SD_BUS_VTABLE_START(0),
44 SD_BUS_METHOD("Reload", SD_BUS_NO_ARGS, SD_BUS_NO_RESULT,
45 nw_bus_daemon_reload, SD_BUS_VTABLE_UNPRIVILEGED),
46 SD_BUS_VTABLE_END,
47};
48
49const struct nw_bus_implementation daemon_implementation = {
50 .path = "/org/ipfire/network1",
51 .interface = "org.ipfire.network1",
52 .vtables = BUS_VTABLES(daemon_vtable),
ebc65f19 53 .children = BUS_IMPLEMENTATIONS(&zone_bus_impl),
9806a600
MT
54};
55
bf42846c
MT
56static int nw_bus_on_connect(sd_bus_message* m, void* data, sd_bus_error* error) {
57 struct nw_daemon* daemon = (struct nw_daemon*)data;
58
59 DEBUG("Connected to D-Bus\n");
60
61 return 0;
62}
63
eaeca0f9 64int nw_bus_connect(sd_bus* bus, sd_event* loop, struct nw_daemon* daemon) {
09a6af17
MT
65 int r;
66
67 // Create a bus object
68 r = sd_bus_new(&bus);
69 if (r < 0) {
70 ERROR("Could not allocate a bus object: %s\n", strerror(-r));
71 return 1;
72 }
73
74 // Set description
75 r = sd_bus_set_description(bus, NETWORKD_BUS_DESCRIPTION);
76 if (r < 0) {
77 ERROR("Could not set bus description: %s\n", strerror(-r));
78 return 1;
79 }
80
81 const char* address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
82 if (!address)
83 address = DEFAULT_SYSTEM_BUS_ADDRESS;
84
85 // Set bus address
86 r = sd_bus_set_address(bus, address);
87 if (r < 0) {
88 ERROR("Could not set bus address: %s\n", strerror(-r));
89 return 1;
90 }
91
92 // Set bus client
93 r = sd_bus_set_bus_client(bus, 1);
94 if (r < 0) {
95 ERROR("Could not set bus client: %s\n", strerror(-r));
96 return 1;
97 }
98
99 // Request some credentials for all messages
100 r = sd_bus_negotiate_creds(bus, 1,
101 SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
102 if (r < 0) {
103 ERROR("Could not negotiate creds: %s\n", strerror(-r));
104 return 1;
105 }
106
107 // Automatically bind when the socket is available
108 r = sd_bus_set_watch_bind(bus, 1);
109 if (r < 0) {
110 ERROR("Could not watch socket: %s\n", strerror(-r));
111 return 1;
112 }
113
114 // Emit a connected signal when we are connected
115 r = sd_bus_set_connected_signal(bus, 1);
116 if (r < 0) {
117 ERROR("Could not enable sending a connect signal: %s\n", strerror(-r));
118 return 1;
119 }
120
121 // Connect to the bus
122 r = sd_bus_start(bus);
123 if (r < 0) {
124 ERROR("Could not connect to bus: %s\n", strerror(-r));
125 return 1;
126 }
127
9806a600 128 // Register the implementation
eaeca0f9 129 r = nw_bus_register_implementation(bus, &daemon_implementation, daemon);
9806a600
MT
130 if (r)
131 return r;
09a6af17
MT
132
133 // Request interface name
9806a600 134 r = sd_bus_request_name_async(bus, NULL, "org.ipfire.network1", 0, NULL, NULL);
09a6af17
MT
135 if (r < 0) {
136 ERROR("Could not request bus name: %s\n", strerror(-r));
137 return 1;
138 }
139
140 // Attach the event loop
141 r = sd_bus_attach_event(bus, loop, 0);
142 if (r < 0) {
143 ERROR("Could not attach bus to event loop: %s\n", strerror(-r));
144 return 1;
145 }
146
bf42846c
MT
147 // Request receiving a connect signal
148 r = sd_bus_match_signal_async(bus, NULL, "org.freedesktop.DBus.Local",
149 NULL, "org.freedesktop.DBus.Local", "Connected", nw_bus_on_connect, NULL, NULL);
150 if (r < 0) {
151 ERROR("Could not request match on Connected signal: %s\n", strerror(-r));
152 return 1;
153 }
154
09a6af17
MT
155 return 0;
156}
9806a600
MT
157
158int nw_bus_register_implementation(sd_bus* bus,
159 const struct nw_bus_implementation* impl, void* data) {
160 int r;
161
162 DEBUG("Registering bus object implementation for path=%s iface=%s\n",
163 impl->path, impl->interface);
164
165 for (const sd_bus_vtable** vtable = impl->vtables; vtable && *vtable; vtable++) {
166 r = sd_bus_add_object_vtable(bus, NULL, impl->path, impl->interface, *vtable, data);
167 if (r < 0) {
168 ERROR("Could not register bus path %s with interface %s: %m\n",
169 impl->path, impl->interface);
170 return 1;
171 }
172 }
173
ebc65f19
MT
174 // Register the node enumerator
175 if (impl->node_enumerator) {
176 r = sd_bus_add_node_enumerator(bus, NULL, impl->path, impl->node_enumerator, data);
177 if (r < 0) {
178 ERROR("Could not add the node enumerator for %s: %m\n", impl->path);
179 return 1;
180 }
181 }
182
183 // Register any child implementations
184 for (int i = 0; impl->children && impl->children[i]; i++) {
185 r = nw_bus_register_implementation(bus, impl->children[i], data);
186 if (r)
187 return r;
188 }
189
9806a600
MT
190 return 0;
191}