]>
git.ipfire.org Git - people/ms/network.git/blob - src/networkd/daemon.c
1 /*#############################################################################
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
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. #
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. #
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/>. #
19 #############################################################################*/
24 #include <systemd/sd-bus.h>
25 #include <systemd/sd-daemon.h>
26 #include <systemd/sd-device.h>
27 #include <systemd/sd-event.h>
28 #include <systemd/sd-netlink.h>
41 // Increase the receive buffer to 128 MiB
42 #define RCVBUF_SIZE 128 * 1024 * 1024
59 sd_device_monitor
* devmon
;
72 static int __nw_daemon_terminate(sd_event_source
* source
, const struct signalfd_siginfo
* si
,
74 DEBUG("Received signal to terminate...\n");
76 return sd_event_exit(sd_event_source_get_event(source
), 0);
79 static int __nw_daemon_reload(sd_event_source
* source
, const struct signalfd_siginfo
* si
,
81 nw_daemon
* daemon
= (nw_daemon
*)daemon
;
83 DEBUG("Received signal to reload...\n");
86 nw_daemon_reload(daemon
);
91 static int nw_daemon_setup_loop(nw_daemon
* daemon
) {
94 // Fetch a reference to the default event loop
95 r
= sd_event_default(&daemon
->loop
);
97 ERROR("Could not setup event loop: %s\n", strerror(-r
));
101 // Enable the watchdog
102 r
= sd_event_set_watchdog(daemon
->loop
, 1);
104 ERROR("Could not activate watchdog: %s\n", strerror(-r
));
108 // Listen for SIGTERM
109 r
= sd_event_add_signal(daemon
->loop
, NULL
, SIGTERM
|SD_EVENT_SIGNAL_PROCMASK
,
110 __nw_daemon_terminate
, daemon
);
112 ERROR("Could not register handling SIGTERM: %s\n", strerror(-r
));
117 r
= sd_event_add_signal(daemon
->loop
, NULL
, SIGINT
|SD_EVENT_SIGNAL_PROCMASK
,
118 __nw_daemon_terminate
, daemon
);
120 ERROR("Could not register handling SIGINT: %s\n", strerror(-r
));
125 r
= sd_event_add_signal(daemon
->loop
, NULL
, SIGHUP
|SD_EVENT_SIGNAL_PROCMASK
,
126 __nw_daemon_reload
, daemon
);
128 ERROR("Could not register handling SIGHUP: %s\n", strerror(-r
));
135 static int nw_daemon_load_config(nw_daemon
* daemon
) {
138 // Read configuration file
139 r
= nw_config_create(&daemon
->config
, CONFIG_DIR
"/settings");
146 static int nw_start_device_monitor(nw_daemon
* daemon
) {
149 const char* subsystems
[] = {
156 // Create a new connection to monitor any devices
157 r
= sd_device_monitor_new(&daemon
->devmon
);
159 ERROR("Could not inititalize the device monitor: %m\n");
163 // Increase the receive buffer
164 r
= sd_device_monitor_set_receive_buffer_size(daemon
->devmon
, RCVBUF_SIZE
);
166 ERROR("Could not increase buffer size for the device monitor: %m\n");
170 // Filter for events for all relevant subsystems
171 for (const char** subsystem
= subsystems
; *subsystem
; subsystem
++) {
172 r
= sd_device_monitor_filter_add_match_subsystem_devtype(
173 daemon
->devmon
, *subsystem
, NULL
);
175 ERROR("Could not add device monitor for the %s subsystem: %m\n", *subsystem
);
180 // Attach the device monitor to the event loop
181 r
= sd_device_monitor_attach_event(daemon
->devmon
, daemon
->loop
);
183 ERROR("Could not attach the device monitor to the event loop: %m\n");
187 // Start processing events...
188 r
= sd_device_monitor_start(daemon
->devmon
, nw_devmon_handle_uevent
, daemon
);
190 ERROR("Could not start the device monitor: %m\n");
197 static int nw_daemon_connect_rtnl(nw_daemon
* daemon
, int fd
) {
200 // Connect to Netlink
201 r
= sd_netlink_open(&daemon
->rtnl
);
203 ERROR("Could not connect to the kernel's netlink interface: %m\n");
207 // Increase the receive buffer
208 r
= sd_netlink_increase_rxbuf(daemon
->rtnl
, RCVBUF_SIZE
);
210 ERROR("Could not increase receive buffer for the netlink socket: %m\n");
214 // Connect it to the event loop
215 r
= sd_netlink_attach_event(daemon
->rtnl
, daemon
->loop
, 0);
217 ERROR("Could not connect the netlink socket to the event loop: %m\n");
221 // Register callback for new interfaces
222 r
= sd_netlink_add_match(daemon
->rtnl
, NULL
, RTM_NEWLINK
, nw_link_process
, NULL
,
223 daemon
, "networkd-RTM_NEWLINK");
225 ERROR("Could not register RTM_NEWLINK: %m\n");
229 // Register callback for deleted interfaces
230 r
= sd_netlink_add_match(daemon
->rtnl
, NULL
, RTM_DELLINK
, nw_link_process
, NULL
,
231 daemon
, "networkd-RTM_DELLINK");
233 ERROR("Could not register RTM_DELLINK: %m\n");
240 static int nw_daemon_enumerate_links(nw_daemon
* daemon
) {
243 // Create a new links container
244 r
= nw_links_create(&daemon
->links
, daemon
);
248 return nw_links_enumerate(daemon
->links
);
251 static int nw_daemon_enumerate_ports(nw_daemon
* daemon
) {
254 // Create a new ports container
255 r
= nw_ports_create(&daemon
->ports
, daemon
);
259 return nw_ports_enumerate(daemon
->ports
);
262 static int nw_daemon_enumerate_zones(nw_daemon
* daemon
) {
265 // Create a new zones container
266 r
= nw_zones_create(&daemon
->zones
, daemon
);
270 return nw_zones_enumerate(daemon
->zones
);
273 static int nw_daemon_enumerate(nw_daemon
* daemon
) {
277 r
= nw_daemon_enumerate_links(daemon
);
282 r
= nw_daemon_enumerate_ports(daemon
);
287 r
= nw_daemon_enumerate_zones(daemon
);
294 static int nw_daemon_setup(nw_daemon
* daemon
) {
297 // Read the configuration
298 r
= nw_daemon_load_config(daemon
);
302 // Setup the event loop
303 r
= nw_daemon_setup_loop(daemon
);
307 // Connect to the kernel's netlink interface
308 r
= nw_daemon_connect_rtnl(daemon
, 0);
312 // Connect to the system bus
313 r
= nw_bus_connect(daemon
->bus
, daemon
->loop
, daemon
);
318 r
= nw_start_device_monitor(daemon
);
322 // Enumerate everything we need to know
323 r
= nw_daemon_enumerate(daemon
);
330 int nw_daemon_create(nw_daemon
** daemon
) {
333 nw_daemon
* d
= calloc(1, sizeof(*d
));
337 // Initialize reference counter
341 r
= nw_daemon_setup(d
);
356 static void nw_daemon_cleanup(nw_daemon
* daemon
) {
358 nw_ports_unref(daemon
->ports
);
360 nw_zones_unref(daemon
->zones
);
362 nw_links_unref(daemon
->links
);
364 nw_config_unref(daemon
->config
);
367 static void nw_daemon_free(nw_daemon
* daemon
) {
368 // Cleanup common objects
369 nw_daemon_cleanup(daemon
);
372 sd_bus_unref(daemon
->bus
);
374 sd_event_unref(daemon
->loop
);
379 nw_daemon
* nw_daemon_ref(nw_daemon
* daemon
) {
385 nw_daemon
* nw_daemon_unref(nw_daemon
* daemon
) {
386 if (--daemon
->nrefs
> 0)
389 nw_daemon_free(daemon
);
394 This function contains the main loop of the daemon...
396 int nw_daemon_run(nw_daemon
* daemon
) {
399 // We are now ready to process any requests
400 sd_notify(0, "READY=1\n" "STATUS=Processing requests...");
402 // Launch the event loop
403 r
= sd_event_loop(daemon
->loop
);
405 ERROR("Could not run the event loop: %s\n", strerror(-r
));
409 // Let systemd know that we are shutting down
410 sd_notify(0, "STOPPING=1\n" "STATUS=Shutting down...");
412 // Save the configuration
413 r
= nw_daemon_save(daemon
);
417 // Cleanup everything
418 nw_daemon_cleanup(daemon
);
423 sd_notifyf(0, "ERRNO=%i", -r
);
425 // Cleanup everything
426 nw_daemon_cleanup(daemon
);
431 int nw_daemon_reload(nw_daemon
* daemon
) {
432 DEBUG("Reloading daemon...\n");
440 Saves the configuration to disk
442 int nw_daemon_save(nw_daemon
* daemon
) {
445 DEBUG("Saving configuration...\n");
448 r
= nw_config_write(daemon
->config
);
453 r
= nw_ports_save(daemon
->ports
);
458 r
= nw_zones_save(daemon
->zones
);
468 sd_netlink
* nw_daemon_get_rtnl(nw_daemon
* daemon
) {
475 nw_links
* nw_daemon_links(nw_daemon
* daemon
) {
476 return nw_links_ref(daemon
->links
);
479 void nw_daemon_drop_link(nw_daemon
* daemon
, nw_link
* link
) {
483 nw_links_drop_link(daemon
->links
, link
);
486 nw_link
* nw_daemon_get_link_by_ifindex(nw_daemon
* daemon
, int ifindex
) {
490 return nw_links_get_by_ifindex(daemon
->links
, ifindex
);
493 nw_link
* nw_daemon_get_link_by_name(nw_daemon
* daemon
, const char* name
) {
497 return nw_links_get_by_name(daemon
->links
, name
);
503 nw_ports
* nw_daemon_ports(nw_daemon
* daemon
) {
504 return nw_ports_ref(daemon
->ports
);
507 nw_port
* nw_daemon_get_port_by_name(nw_daemon
* daemon
, const char* name
) {
511 return nw_ports_get_by_name(daemon
->ports
, name
);
518 nw_zones
* nw_daemon_zones(nw_daemon
* daemon
) {
519 return nw_zones_ref(daemon
->zones
);
522 nw_zone
* nw_daemon_get_zone_by_name(nw_daemon
* daemon
, const char* name
) {
526 return nw_zones_get_by_name(daemon
->zones
, name
);