]> git.ipfire.org Git - people/ms/network.git/blame - src/networkd/daemon.c
networkd: Check if Ethernet addresses from config are usable
[people/ms/network.git] / src / networkd / daemon.c
CommitLineData
112358f3
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
025f60f1 21#include <errno.h>
112358f3
MT
22#include <stdlib.h>
23
09a6af17 24#include <systemd/sd-bus.h>
8a88982f 25#include <systemd/sd-daemon.h>
b286cd83 26#include <systemd/sd-device.h>
c7e1b5db 27#include <systemd/sd-event.h>
e62b300e 28#include <systemd/sd-netlink.h>
c7e1b5db 29
09a6af17 30#include "bus.h"
2ac78f28 31#include "config.h"
112358f3 32#include "daemon.h"
b286cd83 33#include "devmon.h"
eaf649ee 34#include "link.h"
18b8c841 35#include "links.h"
c251a9dd 36#include "logging.h"
b8db2713 37#include "ports.h"
19e74c9b 38#include "zone.h"
0c8e7342 39#include "zones.h"
112358f3 40
b286cd83
MT
41// Increase the receive buffer to 128 MiB
42#define RCVBUF_SIZE 128 * 1024 * 1024
43
112358f3
MT
44struct nw_daemon {
45 int nrefs;
c7e1b5db 46
2ac78f28
MT
47 struct nw_config* config;
48
c7e1b5db
MT
49 // Event Loop
50 sd_event* loop;
09a6af17 51
e62b300e
MT
52 // Netlink Connection
53 sd_netlink* rtnl;
54
09a6af17
MT
55 // DBus Connection
56 sd_bus* bus;
19e74c9b 57
b286cd83
MT
58 // udev Connection
59 sd_device_monitor* devmon;
60
18b8c841
MT
61 // Links
62 struct nw_links* links;
63
19e74c9b 64 // Zones
0c8e7342 65 struct nw_zones* zones;
b8db2713
MT
66
67 // Ports
68 struct nw_ports* ports;
69
112358f3
MT
70};
71
27a3a596 72static int __nw_daemon_terminate(sd_event_source* source, const struct signalfd_siginfo* si,
025f60f1
MT
73 void* data) {
74 DEBUG("Received signal to terminate...\n");
75
76 return sd_event_exit(sd_event_source_get_event(source), 0);
77}
78
27a3a596 79static int __nw_daemon_reload(sd_event_source* source, const struct signalfd_siginfo* si,
025f60f1 80 void* data) {
27a3a596
MT
81 struct nw_daemon* daemon = (struct nw_daemon*)daemon;
82
025f60f1
MT
83 DEBUG("Received signal to reload...\n");
84
27a3a596
MT
85 // Reload the daemon
86 nw_daemon_reload(daemon);
025f60f1
MT
87
88 return 0;
89}
90
c7e1b5db
MT
91static int nw_daemon_setup_loop(struct nw_daemon* daemon) {
92 int r;
93
94 // Fetch a reference to the default event loop
95 r = sd_event_default(&daemon->loop);
96 if (r < 0) {
025f60f1 97 ERROR("Could not setup event loop: %s\n", strerror(-r));
c7e1b5db
MT
98 return 1;
99 }
100
3b2316e4
MT
101 // Enable the watchdog
102 r = sd_event_set_watchdog(daemon->loop, 1);
103 if (r < 0) {
025f60f1
MT
104 ERROR("Could not activate watchdog: %s\n", strerror(-r));
105 return 1;
106 }
107
108 // Listen for SIGTERM
109 r = sd_event_add_signal(daemon->loop, NULL, SIGTERM|SD_EVENT_SIGNAL_PROCMASK,
27a3a596 110 __nw_daemon_terminate, daemon);
025f60f1
MT
111 if (r < 0) {
112 ERROR("Could not register handling SIGTERM: %s\n", strerror(-r));
113 return 1;
114 }
115
116 // Listen for SIGINT
117 r = sd_event_add_signal(daemon->loop, NULL, SIGINT|SD_EVENT_SIGNAL_PROCMASK,
27a3a596 118 __nw_daemon_terminate, daemon);
025f60f1
MT
119 if (r < 0) {
120 ERROR("Could not register handling SIGINT: %s\n", strerror(-r));
121 return 1;
122 }
123
124 // Listen for SIGHUP
125 r = sd_event_add_signal(daemon->loop, NULL, SIGHUP|SD_EVENT_SIGNAL_PROCMASK,
27a3a596 126 __nw_daemon_reload, daemon);
025f60f1
MT
127 if (r < 0) {
128 ERROR("Could not register handling SIGHUP: %s\n", strerror(-r));
3b2316e4
MT
129 return 1;
130 }
131
c7e1b5db
MT
132 return 0;
133}
134
19e74c9b 135static int nw_daemon_load_config(struct nw_daemon* daemon) {
c7e1b5db
MT
136 int r;
137
2ac78f28 138 // Read configuration file
b076fa8b 139 r = nw_config_create(&daemon->config, CONFIG_DIR "/settings");
2ac78f28
MT
140 if (r)
141 return r;
142
19e74c9b 143 // Load zones
0c8e7342 144 r = nw_zones_load(&daemon->zones);
19e74c9b
MT
145 if (r)
146 return r;
147
148 return r;
149}
150
b286cd83
MT
151static int nw_start_device_monitor(struct nw_daemon* daemon) {
152 int r;
153
154 const char* subsystems[] = {
155 "net",
156 "ieee80211",
157 "rfkill",
158 NULL,
159 };
160
161 // Create a new connection to monitor any devices
162 r = sd_device_monitor_new(&daemon->devmon);
163 if (r < 0) {
164 ERROR("Could not inititalize the device monitor: %m\n");
165 return 1;
166 }
167
168 // Increase the receive buffer
169 r = sd_device_monitor_set_receive_buffer_size(daemon->devmon, RCVBUF_SIZE);
170 if (r < 0) {
171 ERROR("Could not increase buffer size for the device monitor: %m\n");
172 return 1;
173 }
174
175 // Filter for events for all relevant subsystems
176 for (const char** subsystem = subsystems; *subsystem; subsystem++) {
177 r = sd_device_monitor_filter_add_match_subsystem_devtype(
178 daemon->devmon, *subsystem, NULL);
179 if (r < 1) {
180 ERROR("Could not add device monitor for the %s subsystem: %m\n", *subsystem);
181 return 1;
182 }
183 }
184
185 // Attach the device monitor to the event loop
186 r = sd_device_monitor_attach_event(daemon->devmon, daemon->loop);
187 if (r < 0) {
188 ERROR("Could not attach the device monitor to the event loop: %m\n");
189 return 1;
190 }
191
192 // Start processing events...
193 r = sd_device_monitor_start(daemon->devmon, nw_devmon_handle_uevent, daemon);
194 if (r < 0) {
195 ERROR("Could not start the device monitor: %m\n");
196 return 1;
197 }
198
199 return 0;
200}
201
e62b300e
MT
202static int nw_daemon_connect_rtnl(struct nw_daemon* daemon, int fd) {
203 int r;
204
205 // Connect to Netlink
206 r = sd_netlink_open(&daemon->rtnl);
207 if (r < 0) {
208 ERROR("Could not connect to the kernel's netlink interface: %m\n");
209 return 1;
210 }
211
212 // Increase the receive buffer
213 r = sd_netlink_increase_rxbuf(daemon->rtnl, RCVBUF_SIZE);
214 if (r < 0) {
215 ERROR("Could not increase receive buffer for the netlink socket: %m\n");
216 return 1;
217 }
218
219 // Connect it to the event loop
220 r = sd_netlink_attach_event(daemon->rtnl, daemon->loop, 0);
221 if (r < 0) {
222 ERROR("Could not connect the netlink socket to the event loop: %m\n");
223 return 1;
224 }
225
226 // Register callback for new interfaces
eaf649ee 227 r = sd_netlink_add_match(daemon->rtnl, NULL, RTM_NEWLINK, nw_link_process, NULL,
e62b300e
MT
228 daemon, "networkd-RTM_NEWLINK");
229 if (r < 0) {
230 ERROR("Could not register RTM_NEWLINK: %m\n");
231 return 1;
232 }
233
766f08ca
MT
234 // Register callback for deleted interfaces
235 r = sd_netlink_add_match(daemon->rtnl, NULL, RTM_DELLINK, nw_link_process, NULL,
236 daemon, "networkd-RTM_DELLINK");
237 if (r < 0) {
238 ERROR("Could not register RTM_DELLINK: %m\n");
239 return 1;
240 }
241
e62b300e
MT
242 return 0;
243}
244
18b8c841
MT
245static int nw_daemon_enumerate_links(struct nw_daemon* daemon) {
246 int r;
247
248 // Create a new links container
249 r = nw_links_create(&daemon->links, daemon);
250 if (r)
251 return r;
252
253 return nw_links_enumerate(daemon->links);
254}
255
b8db2713
MT
256static int nw_daemon_enumerate_ports(struct nw_daemon* daemon) {
257 int r;
258
259 // Create a new ports container
260 r = nw_ports_create(&daemon->ports, daemon);
261 if (r)
262 return r;
263
264 return nw_ports_enumerate(daemon->ports);
265}
266
18b8c841
MT
267static int nw_daemon_enumerate(struct nw_daemon* daemon) {
268 int r;
269
270 // Links
271 r = nw_daemon_enumerate_links(daemon);
272 if (r)
273 return r;
274
b8db2713
MT
275 // Ports
276 r = nw_daemon_enumerate_ports(daemon);
277 if (r)
278 return r;
279
18b8c841
MT
280 return 0;
281}
282
19e74c9b
MT
283static int nw_daemon_setup(struct nw_daemon* daemon) {
284 int r;
285
286 // Read the configuration
287 r = nw_daemon_load_config(daemon);
288 if (r)
289 return r;
290
c7e1b5db
MT
291 // Setup the event loop
292 r = nw_daemon_setup_loop(daemon);
293 if (r)
294 return r;
295
e62b300e
MT
296 // Connect to the kernel's netlink interface
297 r = nw_daemon_connect_rtnl(daemon, 0);
298 if (r)
299 return r;
300
09a6af17 301 // Connect to the system bus
eaeca0f9 302 r = nw_bus_connect(daemon->bus, daemon->loop, daemon);
09a6af17
MT
303 if (r)
304 return r;
305
b286cd83
MT
306 // Connect to udev
307 r = nw_start_device_monitor(daemon);
308 if (r)
309 return r;
310
18b8c841
MT
311 // Enumerate everything we need to know
312 r = nw_daemon_enumerate(daemon);
313 if (r)
314 return r;
315
c7e1b5db
MT
316 return 0;
317}
318
112358f3 319int nw_daemon_create(struct nw_daemon** daemon) {
c7e1b5db
MT
320 int r;
321
112358f3
MT
322 struct nw_daemon* d = calloc(1, sizeof(*d));
323 if (!d)
324 return 1;
325
326 // Initialize reference counter
327 d->nrefs = 1;
328
c7e1b5db
MT
329 // Setup the daemon
330 r = nw_daemon_setup(d);
331 if (r)
332 goto ERROR;
333
334 // Set the reference
335 *daemon = d;
336
112358f3 337 return 0;
c7e1b5db
MT
338
339ERROR:
340 nw_daemon_unref(d);
341
342 return r;
112358f3
MT
343}
344
18b8c841 345static void nw_daemon_cleanup(struct nw_daemon* daemon) {
b8db2713
MT
346 if (daemon->ports)
347 nw_ports_unref(daemon->ports);
0c8e7342
MT
348 if (daemon->zones)
349 nw_zones_unref(daemon->zones);
18b8c841
MT
350 if (daemon->links)
351 nw_links_unref(daemon->links);
2ac78f28
MT
352 if (daemon->config)
353 nw_config_unref(daemon->config);
18b8c841
MT
354}
355
356static void nw_daemon_free(struct nw_daemon* daemon) {
357 // Cleanup common objects
358 nw_daemon_cleanup(daemon);
359
09a6af17
MT
360 if (daemon->bus)
361 sd_bus_unref(daemon->bus);
c7e1b5db
MT
362 if (daemon->loop)
363 sd_event_unref(daemon->loop);
364
112358f3
MT
365 free(daemon);
366}
367
368struct nw_daemon* nw_daemon_ref(struct nw_daemon* daemon) {
369 daemon->nrefs++;
370
371 return daemon;
372}
373
374struct nw_daemon* nw_daemon_unref(struct nw_daemon* daemon) {
375 if (--daemon->nrefs > 0)
376 return daemon;
377
378 nw_daemon_free(daemon);
379 return NULL;
380}
c7e1b5db
MT
381
382/*
383 This function contains the main loop of the daemon...
384*/
385int nw_daemon_run(struct nw_daemon* daemon) {
386 int r;
387
8a88982f
MT
388 // We are now ready to process any requests
389 sd_notify(0, "READY=1\n" "STATUS=Processing requests...");
390
c7e1b5db
MT
391 // Launch the event loop
392 r = sd_event_loop(daemon->loop);
8a88982f
MT
393 if (r < 0) {
394 ERROR("Could not run the event loop: %s\n", strerror(-r));
395 goto ERROR;
c7e1b5db
MT
396 }
397
8a88982f
MT
398 // Let systemd know that we are shutting down
399 sd_notify(0, "STOPPING=1\n" "STATUS=Shutting down...");
400
18b8c841
MT
401 // Cleanup everything
402 nw_daemon_cleanup(daemon);
403
c7e1b5db 404 return 0;
8a88982f
MT
405
406ERROR:
407 sd_notifyf(0, "ERRNO=%i", -r);
408
18b8c841
MT
409 // Cleanup everything
410 nw_daemon_cleanup(daemon);
411
8a88982f 412 return 1;
c7e1b5db 413}
27a3a596
MT
414
415int nw_daemon_reload(struct nw_daemon* daemon) {
416 DEBUG("Reloading daemon...\n");
417
418 // XXX TODO
419
420 return 0;
421}
0c8e7342 422
eaf649ee
MT
423/*
424 Netlink
425*/
426sd_netlink* nw_daemon_get_rtnl(struct nw_daemon* daemon) {
427 return daemon->rtnl;
428}
429
766f08ca
MT
430/*
431 Links
432*/
433struct nw_links* nw_daemon_links(struct nw_daemon* daemon) {
434 return nw_links_ref(daemon->links);
435}
436
437void nw_daemon_drop_link(struct nw_daemon* daemon, struct nw_link* link) {
438 if (!daemon->links)
439 return;
440
441 nw_links_drop_link(daemon->links, link);
442}
443
444struct nw_link* nw_daemon_get_link_by_ifindex(struct nw_daemon* daemon, int ifindex) {
445 if (!daemon->links)
446 return NULL;
447
448 return nw_links_get_by_ifindex(daemon->links, ifindex);
449}
450
bd9ffd6a
MT
451/*
452 Zones
453*/
454
0c8e7342
MT
455struct nw_zones* nw_daemon_zones(struct nw_daemon* daemon) {
456 return nw_zones_ref(daemon->zones);
457}
bd9ffd6a
MT
458
459struct nw_zone* nw_daemon_get_zone_by_name(struct nw_daemon* daemon, const char* name) {
460 if (!daemon->zones)
461 return NULL;
462
463 return nw_zones_get_by_name(daemon->zones, name);
464}