]>
Commit | Line | Data |
---|---|---|
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 | 32 | static 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 |
42 | static 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 | ||
49 | const 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 |
56 | static 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 | 64 | int 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 | |
158 | int 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 | } |