Skip to content
Open
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
11 changes: 11 additions & 0 deletions board/common/post-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,14 @@ mkuserguide()
if [ "$BR2_PACKAGE_WEBUI" = "y" ]; then
mkuserguide
fi

# The common rootfs skeleton carries confs for optional daemons, drop
# them when the daemon is not part of this image.
if [ "$BR2_PACKAGE_TTYD" != "y" ]; then
rm -f "$TARGET_DIR/etc/finit.d/available/ttyd.conf" \
"$TARGET_DIR/etc/nginx/available/ttyd.conf"
fi

# Drop dangling Finit enabled/*.conf symlinks, e.g., optional services
# not part of this image, they cause noise at every initctl reload.
find "$TARGET_DIR/etc/finit.d/enabled" -xtype l -delete 2>/dev/null
36 changes: 36 additions & 0 deletions doc/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,51 @@ All notable changes to the project are documented in this file.

- Upgrade Linux kernel to 6.18.42 (LTS)
- Upgrade Buildroot to 2025.02.15 (LTS)
- Upgrade mdns-alias to [v1.3][ma13]: fixes crash on hostname change while
disconnected from Avahi, treats entry group failures and CNAME collisions
as transient (retried instead of exiting), and quieter logs by default
- Add support for firewall address-set (ipset): named sets of IP addresses and
networks, usable as zone sources for per-IP access control, issue #1189
- Build RPi64 SD card images in release builds
- Include .pkg files in release builds
- The `statd` service now logs at `notice` level by default, like other
services, and supports `-v <level>` to adjust verbosity at runtime

### Fixes

- Fix annoying "cannot deselect all services" or reset to YANG default in the
web interface's firewall configuration page
- Fix sporadic slow response, or timeouts, when reading device status while
mDNS neighbors are being discovered, e.g., after an mDNS restart. Updates
to the neighbor table are now batched, and politely retried when other users
or services keep the system busy, logged as:

statd[3558]: mdns: operational datastore busy, retrying ...

- Fix interface setup failures after an interrupted or failed configuration
change. Leftover interfaces could break all subsequent changes to the
interface configuration, until reboot, logged as:

dagger[2599]: Aborting: /run/net/131/action/init/br0/50-init.ip failed with exitcode 1
confd[2599]: Failed to apply interface configuration

with `RTNETLINK answers: File exists` in the failing script's log.
Creating and deleting interfaces is now tolerant to such leftovers
- Fix slow response, or timeouts, when configuring the system or reading
status while a periodic status snapshot is in progress. On slower systems
with a big configuration, the snapshot, taken every five minutes, could
hold up other users for minutes. Snapshots now run in a separate
low-priority process, `statd-journal`, reading status in small chunks to
let other users interleave
- Fix noisy logs on minimal builds, repeated on every configuration change:

finit[1]: Skipping /etc/finit.d/enabled/webui.conf, dangling symlink: No such file or directory
finit[1]: service_register():/etc/finit.d/enabled/ttyd.conf: skipping ttyd: No such file or directory

Optional services not included in the image are now skipped when enabled
in the configuration, and leftover confs are dropped at build time

[ma13]: https://github.com/troglobit/mdns-alias/releases/tag/v1.3

[v26.06.0][] - 2026-07-01
-------------------------
Expand Down
2 changes: 1 addition & 1 deletion package/mdns-alias/mdns-alias.hash
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# From GitHub release
sha256 9f194fa0b6e34fd915054394ef5b820a4f6b1755ace5ed1011bfba6df550accf mdns-alias-1.2.tar.gz
sha256 8186f0758f184cbdcab1033e4945117a587356c323e53bcdd19d47911ee2567b mdns-alias-1.3.tar.gz

# Locally generated
sha256 3d6f910b5e198f3daab48047b8ee6949040f7abee3927daf2e231f265faf7d91 LICENSE
2 changes: 1 addition & 1 deletion package/mdns-alias/mdns-alias.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
################################################################################

MDNS_ALIAS_VERSION = 1.2
MDNS_ALIAS_VERSION = 1.3
MDNS_ALIAS_SITE = https://github.com/troglobit/mdns-alias/releases/download/v$(MDNS_ALIAS_VERSION)
MDNS_ALIAS_LICENSE = ISC
MDNS_ALIAS_LICENSE_FILES = LICENSE
Expand Down
2 changes: 1 addition & 1 deletion package/statd/statd.conf
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
#set DEBUG=1
service name:statd [12345] <pid/confd> statd -f -p /run/statd.pid -n -- Status daemon
service name:statd [12345] <pid/confd> statd -- Status daemon
Comment thread
troglobit marked this conversation as resolved.
6 changes: 6 additions & 0 deletions src/confd/src/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ int finit_enable(const char *svc)
(int)(at - svc), svc);
}

if (!fexist(src)) {
/* Optional service not part of this image, avoid dangling symlink */
INFO("%s is not available in this image, cannot enable", svc);
return 0;
}

snprintf(dst, sizeof(dst), FINIT_RCSD "/enabled/%s.conf", svc);
if (symlink(src, dst) && errno != EEXIST) {
ERRNO("failed enabling %s", svc);
Expand Down
82 changes: 68 additions & 14 deletions src/confd/src/interfaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,26 @@ static int eth_gen_del(struct lyd_node *dif, FILE *ip)
return 0;
}

static int link_gen_del(struct lyd_node *dif, FILE *ip)
/*
* Tolerate the interface already being gone, e.g., leftover state from
* an earlier, partially applied generation -- a failed teardown would
* abort the whole generation.
*/
static int link_gen_del(struct dagger *net, struct lyd_node *dif)
{
fprintf(ip, "link del dev %s\n", lydx_get_cattr(dif, "name"));
const char *ifname = lydx_get_cattr(dif, "name");
FILE *sh;

sh = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT, "exit-del.sh");
if (!sh)
return -EIO;

fprintf(sh, "ip link del dev %s 2>/dev/null || true\n", ifname);
fclose(sh);
return 0;
}

static int veth_gen_del(struct lyd_node *dif, FILE *sh)
static int veth_gen_del(struct dagger *net, struct lyd_node *dif)
{
if (!veth_is_primary(dif))
return 0;
Expand All @@ -526,7 +539,7 @@ static int veth_gen_del(struct lyd_node *dif, FILE *sh)
if (lydx_get_child(dif, "container-network"))
return 0;

return link_gen_del(dif, sh);
return link_gen_del(net, dif);
}

static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
Expand All @@ -538,10 +551,6 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,

DEBUG_IFACE(dif, "");

ip = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT, "exit.ip");
if (!ip)
return -EIO;

type = iftype_from_iface(dif);
if (type == IFT_UNKNOWN)
/* The interface is still in running, so we need to
Expand All @@ -554,11 +563,14 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
switch (type) {
case IFT_ETH:
case IFT_LO:
ip = dagger_fopen_net_exit(net, ifname, NETDAG_EXIT, "exit.ip");
if (!ip)
return -EIO;
eth_gen_del(dif, ip);
fclose(ip);
break;
case IFT_VETH:
veth_gen_del(dif, ip);
break;
return veth_gen_del(net, dif);
case IFT_WIFI:
wifi_del_iface(dif, net);
break;
Expand All @@ -571,11 +583,9 @@ static int netdag_gen_iface_del(struct dagger *net, struct lyd_node *dif,
case IFT_VXLAN:
case IFT_WIREGUARD:
case IFT_UNKNOWN:
link_gen_del(dif, ip);
break;
return link_gen_del(net, dif);
}

fclose(ip);
return 0;
}

Expand Down Expand Up @@ -617,6 +627,49 @@ static sr_error_t netdag_gen_iface_timeout(struct dagger *net, const char *ifnam
return SR_ERR_OK;
}

/*
* A netlink-created interface may linger from an earlier, partially
* applied generation, causing our `link add` to fail with EEXIST and
* abort the whole generation. Remove any leftover before creating.
*/
static int netdag_gen_ensure_absent(struct dagger *net, struct lyd_node *cif)
{
const char *ifname = lydx_get_cattr(cif, "name");
const char *peer = NULL;
FILE *sh;

switch (iftype_from_iface(cif)) {
case IFT_BRIDGE:
case IFT_DUMMY:
case IFT_GRE:
case IFT_GRETAP:
case IFT_LAG:
case IFT_VLAN:
case IFT_VXLAN:
case IFT_WIREGUARD:
break;
case IFT_VETH:
/* primary's `link add` creates both ends */
if (!veth_is_primary(cif))
return 0;
peer = lydx_get_cattr(lydx_get_child(cif, "veth"), "peer");
break;
default:
return 0;
}

sh = dagger_fopen_net_init(net, ifname, NETDAG_INIT_PRE, "ensure-absent.sh");
if (!sh)
return -EIO;

fprintf(sh, "ip link del dev %s 2>/dev/null || true\n", ifname);
if (peer)
fprintf(sh, "ip link del dev %s 2>/dev/null || true\n", peer);
fclose(sh);

return 0;
}

static sr_error_t netdag_gen_iface(sr_session_ctx_t *session, struct dagger *net,
struct lyd_node *dif, struct lyd_node *cif)
{
Expand Down Expand Up @@ -683,7 +736,8 @@ static sr_error_t netdag_gen_iface(sr_session_ctx_t *session, struct dagger *net
}

if (op == LYDX_OP_CREATE) {
err = netdag_gen_afspec_add(session, net, dif, cif, ip);
err = netdag_gen_ensure_absent(net, cif);
err = err ? : netdag_gen_afspec_add(session, net, dif, cif, ip);
if (err)
goto err_close_ip;
}
Expand Down
7 changes: 4 additions & 3 deletions src/confd/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -655,10 +655,11 @@ int main(int argc, char **argv)
else if (!strcmp(optarg, "warning"))
log_level = LOG_WARNING;
else if (!strcmp(optarg, "info"))
log_level = LOG_NOTICE;
else if (!strcmp(optarg, "debug"))
log_level = LOG_INFO;
else if (!strcmp(optarg, "debug")) {
log_level = LOG_DEBUG;
else {
debug = 1;
} else {
fprintf(stderr, "confd error: Invalid verbosity \"%s\"\n", optarg);
return EXIT_FAILURE;
}
Expand Down
1 change: 1 addition & 0 deletions src/statd/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ ACLOCAL_AMFLAGS = -I m4
sbin_PROGRAMS = statd
statd_SOURCES = statd.c shared.c shared.h journal.c journal_retention.c journal.h avahi.c avahi.h
statd_CPPFLAGS = -D_DEFAULT_SOURCE -D_GNU_SOURCE
statd_CPPFLAGS += -DSTATD_VERSION=\"$(PACKAGE_VERSION)\"
statd_CFLAGS = -W -Wall -Wextra
statd_CFLAGS += $(jansson_CFLAGS) $(libyang_CFLAGS) $(sysrepo_CFLAGS)
statd_CFLAGS += $(libsrx_CFLAGS) $(libite_CFLAGS)
Expand Down
Loading