Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
6 changes: 1 addition & 5 deletions board/common/rootfs/usr/share/udhcpc/default.script
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ACTION="$1"
IP_CACHE="/var/lib/misc/${interface}.cache"
RESOLV_CONF="/run/resolvconf/interfaces/${interface}.conf"
NTPFILE="/run/chrony/dhcp-sources.d/${interface}.sources"
NAME="/etc/netd/conf.d/${interface}-dhcp.conf"
NAME="/etc/net.d/${interface}-dhcp.conf"
NEXT="${NAME}+"

[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
Expand Down Expand Up @@ -118,17 +118,13 @@ set_dhcp_routes()
# Reduce changes needed by comparing with previous route(s)
cmp -s "$NAME" "$NEXT" && return
mv "$NEXT" "$NAME"

initctl reload netd
}

clr_dhcp_routes()
{
log "deleting DHCP routes"
[ -f "$NAME" ] || return
rm "$NAME"

initctl reload netd
}

clr_dhcp_addresses()
Expand Down
3 changes: 2 additions & 1 deletion doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Change Log

All notable changes to the project are documented in this file.

[v26.02.1][] - 2026-03-11
[v26.02.1][] - 2026-03-12
-------------------------

### Changes
Expand All @@ -17,6 +17,7 @@ All notable changes to the project are documented in this file.

- Fix #1389: legacy name limit in firewalld triggered problems with policy names
- Fix #1416: `show firewall` command show an error when the firewall is disabled
- Fix #1438: default route from DHCP client not set at boot, regression in v26.02.0
- Fix instabilities in Zebra route manager after Frr upgrade in v26.02.0
- Fix regression in MVEBU SafeXcel Crypto Engine for Marvell Armada SOCs (37xx,
7k, 8k, and CN913x series). Firmware package lost in v26.01.0
Expand Down
3 changes: 2 additions & 1 deletion package/netd/Config.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ config BR2_PACKAGE_NETD
bool "netd"
select BR2_PACKAGE_LIBITE
select BR2_PACKAGE_LIBCONFUSE
select BR2_PACKAGE_LIBEV
help
Network route daemon. Manages static routes and RIP routing.
Reads configuration from /etc/netd/conf.d/*.conf.
Reads configuration from /etc/net.d/*.conf.

With FRR: Full routing via gRPC, vtysh, or frr.conf.
Without FRR: Standalone Linux backend via rtnetlink.
Expand Down
4 changes: 2 additions & 2 deletions package/netd/netd.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#
################################################################################

NETD_VERSION = 1.0
NETD_VERSION = 1.1.0
NETD_SITE_METHOD = local
NETD_SITE = $(BR2_EXTERNAL_INFIX_PATH)/src/netd
NETD_LICENSE = BSD-3-Clause
NETD_LICENSE_FILES = LICENSE
NETD_REDISTRIBUTE = NO
NETD_DEPENDENCIES = libite libconfuse jansson
NETD_DEPENDENCIES = libite libconfuse jansson libev
NETD_AUTORECONF = YES

NETD_CONF_ENV = CFLAGS="$(INFIX_CFLAGS)"
Expand Down
2 changes: 1 addition & 1 deletion src/confd/src/routing.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#define XPATH_BASE_ "/ietf-routing:routing/control-plane-protocols/control-plane-protocol"
#define XPATH_OSPF_ XPATH_BASE_ "/ietf-ospf:ospf"
#define NETD_CONF "/etc/netd/conf.d/confd.conf"
#define NETD_CONF "/etc/net.d/confd.conf"
#define NETD_CONF_NEXT NETD_CONF "+"
#define NETD_CONF_PREV NETD_CONF "-"
#define OSPFD_CONF "/etc/frr/ospfd.conf"
Expand Down
2 changes: 1 addition & 1 deletion src/netd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ netd_SOURCES = src/netd.c src/netd.h src/config.c src/config.h
netd_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE -I$(srcdir)/src
netd_CFLAGS = -W -Wall -Wextra
netd_CFLAGS += $(libite_CFLAGS) $(libconfuse_CFLAGS) $(jansson_CFLAGS)
netd_LDADD = $(libite_LIBS) $(libconfuse_LIBS) $(jansson_LIBS)
netd_LDADD = $(libite_LIBS) $(libconfuse_LIBS) $(jansson_LIBS) $(EV_LIBS)

# Backend selection: FRR gRPC, FRR frr.conf, or Linux kernel
if HAVE_FRR_GRPC
Expand Down
8 changes: 4 additions & 4 deletions src/netd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ make install

netd uses [libconfuse](https://github.com/martinh/libconfuse) for configuration parsing, providing a clean and structured format.

Configuration files are placed in `/etc/netd/conf.d/` with the `.conf` extension. Files are processed in alphabetical order.
Configuration files are placed in `/etc/net.d/` with the `.conf` extension. Files are processed in alphabetical order.

### Configuration Format

Expand Down Expand Up @@ -219,10 +219,10 @@ rip {

### Configuration Files

Configuration files must be placed in `/etc/netd/conf.d/` with the `.conf` extension:
Configuration files must be placed in `/etc/net.d/` with the `.conf` extension:

```bash
/etc/netd/conf.d/
/etc/net.d/
├── 10-static.conf # Static routes
├── 20-rip.conf # RIP configuration
└── 99-local.conf # Local overrides
Expand Down Expand Up @@ -256,7 +256,7 @@ netd validates configuration on reload. Check syslog for errors.

```
┌─────────┐
│ confd │ Writes /etc/netd/conf.d/confd.conf
│ confd │ Writes /etc/net.d/confd.conf
└────┬────┘
│ SIGHUP
Expand Down
12 changes: 11 additions & 1 deletion src/netd/configure.ac
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
AC_PREREQ(2.61)
AC_INIT([netd], [1.0.0], [https://github.com/kernelkit/infix/issues])
AC_INIT([netd], [1.1.0], [https://github.com/kernelkit/infix/issues])
AM_INIT_AUTOMAKE(1.11 foreign subdir-objects)
AM_SILENT_RULES(yes)

Expand Down Expand Up @@ -81,6 +81,16 @@ PKG_CHECK_MODULES([libite], [libite >= 2.6.1])
PKG_CHECK_MODULES([libconfuse], [libconfuse >= 3.0])
PKG_CHECK_MODULES([jansson], [jansson >= 2.0])

AC_CHECK_HEADER([ev.h],
[saved_LIBS="$LIBS"
AC_CHECK_LIB([ev], [ev_loop_new],
[EV_LIBS="-lev"],
[AC_MSG_ERROR("libev not found")])
LIBS="$saved_LIBS"],
[AC_MSG_ERROR("ev.h not found")]
)
AC_SUBST([EV_LIBS])

test "x$prefix" = xNONE && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'

Expand Down
127 changes: 86 additions & 41 deletions src/netd/src/netd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

#include <errno.h>
#include <getopt.h>
#include <sys/inotify.h>
#include <ev.h>
#include <libite/lite.h>

#include "netd.h"
#include "config.h"

int debug;

static sig_atomic_t do_reload;
static sig_atomic_t do_shutdown;

static struct route_head active_routes = TAILQ_HEAD_INITIALIZER(active_routes);
static struct rip_config active_rip;

Expand Down Expand Up @@ -46,19 +45,7 @@ static int backend_apply(struct route_head *routes, struct rip_config *rip) {
}
#endif

static void sighup_handler(int sig)
{
(void)sig;

INFO("Got SIGHUP, reloading ...");
do_reload = 1;
}

static void sigterm_handler(int sig)
{
(void)sig;
do_shutdown = 1;
}
static ev_timer retry_w;

static void route_list_free(struct route_head *head)
{
Expand Down Expand Up @@ -118,7 +105,7 @@ static void rip_config_free(struct rip_config *cfg)
}
}

static void reload(void)
static void reload(struct ev_loop *loop)
{
struct route_head new_routes = TAILQ_HEAD_INITIALIZER(new_routes);
struct rip_redistribute *redist;
Expand All @@ -129,7 +116,7 @@ static void reload(void)
struct route *r;
int count = 0;

INFO("Reloading configuration");
DEBUG("Reloading configuration");

rip_config_init(&new_rip);

Expand All @@ -148,11 +135,16 @@ static void reload(void)

/* Apply config via backend */
if (backend_apply(&new_routes, &new_rip)) {
ERROR("Failed applying config via backend");
ERROR("Failed applying config via backend, retry in 5s");
route_list_free(&new_routes);
rip_config_free(&new_rip);
ev_timer_stop(loop, &retry_w);
ev_timer_set(&retry_w, 5., 0.);
ev_timer_start(loop, &retry_w);
pidfile(NULL);
return;
}
ev_timer_stop(loop, &retry_w);

route_list_free(&active_routes);
TAILQ_INIT(&active_routes);
Expand Down Expand Up @@ -214,49 +206,77 @@ static void reload(void)
}
}

INFO("Configuration reloaded");
pidfile(NULL);
}

static void inotify_cb(struct ev_loop *loop, ev_io *w, int revents)
{
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];

(void)revents;
while (read(w->fd, buf, sizeof(buf)) > 0)
;
DEBUG("conf.d changed, triggering reload");
reload(loop);
}

static void sighup_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
(void)w; (void)revents;
INFO("Got SIGHUP, reloading ...");
reload(loop);
}

static void sigterm_cb(struct ev_loop *loop, ev_signal *w, int revents)
{
(void)w; (void)revents;
ev_break(loop, EVBREAK_ALL);
}

static void retry_cb(struct ev_loop *loop, ev_timer *w, int revents)
{
(void)w; (void)revents;
reload(loop);
}

static int usage(int rc)
{
fprintf(stderr,
"Usage: netd [-dh]\n"
"Usage: netd [-dhv]\n"
" -d Enable debug (log to stderr)\n"
" -h Show this help text\n");
" -h Show this help text\n"
" -v Show version and exit\n");
return rc;
}

int main(int argc, char *argv[])
{
struct ev_loop *loop = EV_DEFAULT;
ev_signal sighup_w, sigterm_w, sigint_w;
ev_io inotify_w;
int log_opts = LOG_PID | LOG_NDELAY;
struct sigaction sa = { 0 };
int ifd = -1;
int c;

while ((c = getopt(argc, argv, "dhp:")) != -1) {
while ((c = getopt(argc, argv, "dhv")) != -1) {
switch (c) {
case 'd':
log_opts |= LOG_PERROR;
debug = 1;
break;
case 'h':
return usage(0);
case 'v':
puts("v" PACKAGE_VERSION);
return 0;
default:
return usage(1);
}
}

openlog("netd", log_opts, LOG_DAEMON);
setlogmask(LOG_UPTO(LOG_INFO));
INFO("starting");

/* Set up signal handlers */
sa.sa_handler = sighup_handler;
sigaction(SIGHUP, &sa, NULL);

sa.sa_handler = sigterm_handler;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
INFO("v%s starting", PACKAGE_VERSION);

if (backend_init()) {
ERROR("Failed to initialize backend");
Expand All @@ -267,19 +287,44 @@ int main(int argc, char *argv[])
TAILQ_INIT(&active_routes);
rip_config_init(&active_rip);

/* Signal watchers */
ev_signal_init(&sighup_w, sighup_cb, SIGHUP);
ev_signal_start(loop, &sighup_w);

ev_signal_init(&sigterm_w, sigterm_cb, SIGTERM);
ev_signal_start(loop, &sigterm_w);

ev_signal_init(&sigint_w, sigterm_cb, SIGINT);
ev_signal_start(loop, &sigint_w);

/* Retry timer — one-shot, started only on backend failure */
ev_timer_init(&retry_w, retry_cb, 0., 0.);

/* Watch conf.d for changes so we don't rely solely on signals */
mkdir(CONF_DIR, 0755);
ifd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
if (ifd < 0) {
ERROR("inotify_init1: %s, falling back to signals only", strerror(errno));
} else if (inotify_add_watch(ifd, CONF_DIR,
IN_CLOSE_WRITE | IN_DELETE |
IN_MOVED_TO | IN_MOVED_FROM) < 0) {
ERROR("inotify_add_watch %s: %s", CONF_DIR, strerror(errno));
close(ifd);
ifd = -1;
} else {
ev_io_init(&inotify_w, inotify_cb, ifd, EV_READ);
ev_io_start(loop, &inotify_w);
}

/* Initial load */
do_reload = 1;
reload(loop);

while (!do_shutdown) {
if (do_reload) {
do_reload = 0;
reload();
}
pause();
}
ev_run(loop, 0);

INFO("shutting down");

if (ifd >= 0)
close(ifd);
route_list_free(&active_routes);
rip_config_free(&active_rip);
backend_cleanup();
Expand Down
2 changes: 1 addition & 1 deletion src/netd/src/netd.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern int debug;
#define INFO(fmt, args...) LOG(LOG_INFO, fmt, ##args)
#define DEBUG(fmt, args...) do { if (debug) LOG(LOG_DEBUG, fmt, ##args); } while (0)

#define CONF_DIR "/etc/netd/conf.d"
#define CONF_DIR "/etc/net.d"

/* Nexthop types */
enum nh_type {
Expand Down
Loading