From 20316daf2d6f15fa2a8a1c38c498ddbaa4f71cde Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 11:28:59 +0200 Subject: [PATCH 01/12] confd: fix possible resource leak in firewall conf change Coverity scan detected a memory leak in the new firewall change() cb where allocated memory from ietf_interfaces_get_all_l3() was not freed on error paths when srx_get_diff() failed or returned NULL. This commit consolidates all cleanup paths to use the 'done:' label, ensuring ifaces, diff, and cfg are properly freed in all exit scenarios. Signed-off-by: Joachim Wiberg --- src/confd/src/infix-firewall.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/confd/src/infix-firewall.c b/src/confd/src/infix-firewall.c index 7223ed15..ebdb4539 100644 --- a/src/confd/src/infix-firewall.c +++ b/src/confd/src/infix-firewall.c @@ -542,10 +542,10 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module err = srx_get_diff(session, &diff); if (err) - goto err_release_data; + goto done; if (!diff) - goto err_release_data; + goto done; /* Create /etc/firewalld+ directory structure */ if (fmkpath(0755, FIREWALLD_DIR_NEXT) || @@ -554,7 +554,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module fmkpath(0755, FIREWALLD_POLICIES_DIR)) { ERROR("Failed creating " FIREWALLD_DIR_NEXT " directory structure"); err = SR_ERR_SYS; - goto err_release_data; + goto done; } if (lydx_get_descendant(diff, "firewall", "default", NULL) || @@ -630,7 +630,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module if (generate_policy(cnode, name, &priority)) { ERROR("Failed to generate policy %s", name); - goto err_release_data; + goto done; } } } @@ -644,7 +644,7 @@ done: if (diff) lyd_free_tree(diff); -err_release_data: + if (cfg) sr_release_data(cfg); From 81f1da6272634243bd9e7eac1f7c0d74c75ce71a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 16:45:20 +0200 Subject: [PATCH 02/12] package/board: fix RPi4 boot from aarch64 image Fixes a minor regression after merge of BPi-R3. The RPi4 device tree, specifically regulator-sd-io-1v8 in bcm2711-rpi-4-b.dts, requires the GPIO voltage regulator be built-in for the SD card controller. Fixes #1197 Signed-off-by: Joachim Wiberg --- package/board/banana-pi-r3/banana-pi-r3.mk | 2 +- package/board/raspberry-pi-4/raspberry-pi-4.mk | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/package/board/banana-pi-r3/banana-pi-r3.mk b/package/board/banana-pi-r3/banana-pi-r3.mk index b4b2ae95..a000411c 100644 --- a/package/board/banana-pi-r3/banana-pi-r3.mk +++ b/package/board/banana-pi-r3/banana-pi-r3.mk @@ -28,7 +28,7 @@ define BANANA_PI_R3_LINUX_CONFIG_FIXUPS $(call KCONFIG_SET_OPT,CONFIG_USB_XHCI_MTK,m) $(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_TPHY,m) $(call KCONFIG_SET_OPT,CONFIG_PHY_MTK_XSPHY,m) - $(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,m) + $(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,y) $(call KCONFIG_SET_OPT,CONFIG_REGULATOR_MT6380,m) $(call KCONFIG_SET_OPT,CONFIG_PWM_MEDIATEK,m) $(call KCONFIG_SET_OPT,CONFIG_SENSORS_PWM_FAN,m) diff --git a/package/board/raspberry-pi-4/raspberry-pi-4.mk b/package/board/raspberry-pi-4/raspberry-pi-4.mk index 0c4f1e3f..2dc74bfd 100644 --- a/package/board/raspberry-pi-4/raspberry-pi-4.mk +++ b/package/board/raspberry-pi-4/raspberry-pi-4.mk @@ -1,3 +1,5 @@ +# The CONFIG_REGULATOR_GPIO=y is load bearing for booting the RPi4 from +# SD card, see regulator-sd-io-1v8 in bcm2711-rpi-4-b.dts for details. define RASPBERRY_PI_4_LINUX_CONFIG_FIXUPS $(call KCONFIG_ENABLE_OPT,CONFIG_SOUND) $(call KCONFIG_ENABLE_OPT,CONFIG_SND) @@ -32,6 +34,7 @@ define RASPBERRY_PI_4_LINUX_CONFIG_FIXUPS $(call KCONFIG_ENABLE_OPT,CONFIG_NET_VENDOR_BROADCOM) $(call KCONFIG_SET_OPT,CONFIG_BCMGENET,m) $(call KCONFIG_SET_OPT,CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY,m) + $(call KCONFIG_SET_OPT,CONFIG_REGULATOR_GPIO,y) $(call KCONFIG_ENABLE_OPT,CONFIG_COMMON_CLK_BCM2835) $(call KCONFIG_ENABLE_OPT,CONFIG_CLK_RASPBERRYPI) $(call KCONFIG_ENABLE_OPT,CONFIG_DRM) From 0957fc3c119b1536dbb433689168373abbf44163 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:23:04 +0200 Subject: [PATCH 03/12] board/common: wait for mmc probe on rpi Signed-off-by: Joachim Wiberg --- board/common/rootfs/usr/libexec/infix/mnt | 32 +++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/board/common/rootfs/usr/libexec/infix/mnt b/board/common/rootfs/usr/libexec/infix/mnt index aafee06f..491326ea 100755 --- a/board/common/rootfs/usr/libexec/infix/mnt +++ b/board/common/rootfs/usr/libexec/infix/mnt @@ -51,6 +51,29 @@ factory_reset() sync } +is_rpi() +{ + [ -r /sys/firmware/devicetree/base/model ] || return 1 + + model=$(cat /sys/firmware/devicetree/base/model 2>/dev/null | tr -d '\0') + echo "$model" | grep -q "^Raspberry Pi" +} + +wait_mmc() +{ + # Try up to 50 times with 0.2s sleep = 10 second timeout + for _ in $(seq 50); do + if ls /dev/mmcblk* >/dev/null 2>&1; then + logger $opt -p user.notice -t "$nm" "MMC device available after delay" + return 0 + fi + sleep .2 + done + + logger $opt -p user.warn -t "$nm" "Timeout waiting for MMC device" + return 1 +} + mount_rw() { # If something is already setup, leave it be. @@ -103,6 +126,15 @@ if ! logger -? |grep -q "Log to kernel"; then opt="-c" fi + +# On Raspberry Pi, MMC controller may probe slowly, in particular if we +# netboot (ram load) the devcice wait for it +if is_rpi && ! ls /dev/mmcblk* >/dev/null 2>&1; then + wait_mmc +fi + +# The aux partition must be mounted before everything else since it's used +# for internal bookkeeping. if ! mount_rw aux >/dev/null 2>&1; then logger $opt -p user.warn -t "$nm" \ "No auxiliary partition found, software updates not supported." From 391e97157305a46c07bc4897ad15c206916a612f Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:23:33 +0200 Subject: [PATCH 04/12] board/common: expand var partition on sdcard Signed-off-by: Joachim Wiberg --- board/common/rootfs/usr/libexec/infix/mnt | 106 ++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/board/common/rootfs/usr/libexec/infix/mnt b/board/common/rootfs/usr/libexec/infix/mnt index 491326ea..7c99425f 100755 --- a/board/common/rootfs/usr/libexec/infix/mnt +++ b/board/common/rootfs/usr/libexec/infix/mnt @@ -74,11 +74,117 @@ wait_mmc() return 1 } +# This early on we don't have the luxury of /dev/disk/by-label/$1 +find_partition_by_label() +{ + label="$1" + + for diskpath in /sys/class/block/*; do + devname=$(basename "$diskpath") + [ -f "$diskpath/partition" ] && continue + + disk="/dev/$devname" + result=$(sgdisk -p "$disk" 2>/dev/null | awk -v label="$label" -v devname="$devname" ' + /^ *[0-9]/ { + if ($7 == label) { + if (devname ~ /^(mmcblk|nvme|loop)/) { + print devname "p" $1 + } else { + print devname $1 + } + exit 0 + } + } + ') + + if [ -n "$result" ]; then + echo "$result" + return 0 + fi + done + return 1 +} + +# Expand the given partition to fill up the rest of storage (sdcard) +resize_by_label() +{ + label="$1" + + devname=$(find_partition_by_label "$label") + if [ -z "$devname" ]; then + logger $opt -p user.err -t "$nm" "Label \"$label\" not found" + return 1 + fi + + part="/dev/$devname" + diskname=$(basename "$(readlink -f "/sys/class/block/$devname/..")") + disk="/dev/$diskname" + partnum="${devname##*[^0-9]}" + + logger $opt -p user.notice -t "$nm" "Found partition $part (partition $partnum on $disk)" + + start=$(sgdisk -i "$partnum" "$disk" 2>/dev/null | grep "First sector:" | awk '{print $3}') + if [ -z "$start" ]; then + logger $opt -p user.err -t "$nm" "Could not determine start sector for partition $partnum" + return 1 + fi + + printf "\r\033[K[ ⋯ ] Resizing /var partition on sdcard, please wait ..." > /dev/console + logger $opt -p user.notice -t "$nm" "Expanding partition $partnum from sector $start to end of disk" + + if ! sgdisk -e "$disk" 2>&1 | logger $opt -p user.notice -t "$nm"; then + logger $opt -p user.warn -t "$nm" "Failed expanding GPT on $disk" + return 1 + fi + + if ! sgdisk -d "$partnum" "$disk" >/dev/null 2>&1; then + logger $opt -p user.warn -t "$nm" "Failed deleting partition $partnum on $disk" + return 1 + fi + + if ! sgdisk -n "$partnum:$start:0" "$disk" >/dev/null 2>&1; then + logger $opt -p user.warn -t "$nm" "Failed recreating partition $partnum on $disk" + return 1 + fi + + if ! sgdisk -t "$partnum:8300" "$disk" >/dev/null 2>&1; then + logger $opt -p user.warn -t "$nm" "Failed setting partition type on $disk" + return 1 + fi + + if ! sgdisk -c "$partnum:$label" "$disk" >/dev/null 2>&1; then + logger $opt -p user.warn -t "$nm" "Failed setting partition label on $disk" + return 1 + fi + + logger $opt -p user.notice -t "$nm" "Partition table updated on $disk" + partprobe "$disk" 2>/dev/null + + logger $opt -p user.notice -t "$nm" "Resizing filesystem on $part" + if ! resize2fs "$part" 2>&1 | logger $opt -p user.notice -t "$nm"; then + logger $opt -p user.warn -t "$nm" "Failed resizing filesystem on $part" + return 1 + fi + + tune2fs -O resize_inode "$part" 2>/dev/null + printf "\r\033[K[ \033[32mOK\033[0m ] Resizing /var partition on sdcard, done. Rebooting ...\n" > /dev/console + logger $opt -p user.notice -t "$nm" "Partition expanded, rebooting to complete filesystem resize" + + reboot -f +} + mount_rw() { # If something is already setup, leave it be. mountpoint -q "/$1" && return 0 + if [ "$1" = "var" ]; then + if is_rpi && [ ! -e /mnt/aux/resized ] ; then + touch /mnt/aux/resized + resize_by_label "$1" + fi + fi + # TODO: Also look for UBI partitions mount LABEL="$1" 2>/dev/null && return 0 From b3ea0f320735134f9f86d17081d7c56a2d529ce5 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:24:22 +0200 Subject: [PATCH 05/12] board/aarch64: add support for std partition labels on cmdline Signed-off-by: Joachim Wiberg --- board/aarch64/linux_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/board/aarch64/linux_defconfig b/board/aarch64/linux_defconfig index f6efbf0d..b675a907 100644 --- a/board/aarch64/linux_defconfig +++ b/board/aarch64/linux_defconfig @@ -56,6 +56,7 @@ CONFIG_JUMP_LABEL=y # CONFIG_GCC_PLUGINS is not set CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set # CONFIG_COMPAT_BRK is not set CONFIG_KSM=y From 4123074272fad1d0d61ef1b1442127277cdf8a95 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:25:12 +0200 Subject: [PATCH 06/12] board/rpi: match bpi rootfs partition sizes Signed-off-by: Joachim Wiberg --- src/board/raspberry-pi-4/genimage.cfg.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/board/raspberry-pi-4/genimage.cfg.in b/src/board/raspberry-pi-4/genimage.cfg.in index 9e48da33..ee7147d7 100644 --- a/src/board/raspberry-pi-4/genimage.cfg.in +++ b/src/board/raspberry-pi-4/genimage.cfg.in @@ -48,14 +48,14 @@ image #INFIX_ID##VERSION#-rpi4-sdcard.img { partition primary { partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 bootable = true - size = 200M + size = 250M image = "rootfs.squashfs" } partition secondary { partition-type-uuid = 0FC63DAF-8483-4772-8E79-3D69D8477DE4 bootable = true - size = 200M + size = 250M image = "rootfs.squashfs" } From c76f3ea164d437b1eef4c5f0e20581435d260812 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:26:09 +0200 Subject: [PATCH 07/12] board/rpi: support standalone run of mkimage.sh Signed-off-by: Joachim Wiberg --- src/board/raspberry-pi-4/mkimage.sh | 179 +++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 6 deletions(-) diff --git a/src/board/raspberry-pi-4/mkimage.sh b/src/board/raspberry-pi-4/mkimage.sh index f2b39e34..b7b4c9d4 100755 --- a/src/board/raspberry-pi-4/mkimage.sh +++ b/src/board/raspberry-pi-4/mkimage.sh @@ -1,6 +1,152 @@ #!/bin/sh set -e +usage() +{ + cat <&2 + exit 1 + } + fi + fi + + # Find rootfs if not specified + if [ -z "$ROOT_DIR" ]; then + ROOT_DIR=$(find_build_dir) || { + echo "Error: Could not find rootfs directory. Set O= or use -r option" >&2 + exit 1 + } + fi + + # Set up environment variables (use BOOT_DIR as base) + export BINARIES_DIR="$BOOT_DIR/images" + export BUILD_DIR="$BOOT_DIR/build" + export BR2_EXTERNAL_INFIX_PATH + export RELEASE=${RELEASE:-""} + export INFIX_ID=${INFIX_ID:-"infix"} + + # Add host tools to PATH (for genimage, etc.) + for dir in "$BOOT_DIR" "$ROOT_DIR"; do + if [ -d "$dir/host/bin" ]; then + export PATH="$dir/host/bin:$PATH" + break + fi + done + + # Copy rootfs and partition images to boot directory + mkdir -p "$BINARIES_DIR" + if [ -f "$ROOT_DIR" ]; then + # Direct path to rootfs.squashfs file + echo "Copying rootfs from $ROOT_DIR to $BINARIES_DIR/rootfs.squashfs" + cp "$ROOT_DIR" "$BINARIES_DIR/rootfs.squashfs" + elif [ -f "$ROOT_DIR/images/rootfs.squashfs" ]; then + # Build directory with images/ - copy rootfs and partition images + echo "Copying rootfs and partitions from $ROOT_DIR/images/ to $BINARIES_DIR/" + cp "$ROOT_DIR/images/rootfs.squashfs" "$BINARIES_DIR/" + # Copy partition images (aux.ext4, cfg.ext4, var.ext4) if they exist + for img in aux.ext4 cfg.ext4 var.ext4; do + if [ -f "$ROOT_DIR/images/$img" ]; then + cp "$ROOT_DIR/images/$img" "$BINARIES_DIR/" + fi + done + elif [ -f "$ROOT_DIR/rootfs.squashfs" ]; then + # Directory directly containing rootfs.squashfs + echo "Copying rootfs from $ROOT_DIR/rootfs.squashfs to $BINARIES_DIR/" + cp "$ROOT_DIR/rootfs.squashfs" "$BINARIES_DIR/" + # Copy partition images if they exist in same directory + for img in aux.ext4 cfg.ext4 var.ext4; do + if [ -f "$ROOT_DIR/$img" ]; then + cp "$ROOT_DIR/$img" "$BINARIES_DIR/" + fi + done + else + echo "Error: Could not find rootfs.squashfs in $ROOT_DIR" >&2 + exit 1 + fi +fi + BOARD_DIR=$(dirname "$0") GENIMAGE_CFG="${BUILD_DIR}/genimage.cfg" GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp" @@ -9,36 +155,57 @@ GENIMAGE_TMP="${BUILD_DIR}/genimage.tmp" # key and our ixboot scripts. Make sure here they are installed in the # proper directory so genimage can create the DOS partition the SPL # reads config.txt from. -find "${BINARIES_DIR}" -type f -name '*.dtbo' -exec mv '{}' "${BINARIES_DIR}/rpi-firmware/overlays/" \; +find "${BINARIES_DIR}" -type f -name '*.dtbo' ! -path "${BINARIES_DIR}/rpi-firmware/overlays/*" -exec \ + mv '{}' "${BINARIES_DIR}/rpi-firmware/overlays/" \; # Create FILES array for the genimage.cfg generation FILES="" for f in "${BINARIES_DIR}"/rpi-firmware/*; do case "$f" in - *~|*.bak) continue ;; + *~ | *.bak) + continue + ;; esac - echo "${FILES}" | grep -q `basename $f` && continue # If already exist it has been added by us. + # If already exist it has been added by us. + echo "${FILES}" | grep -q "$(basename "$f")" && continue FILES="${FILES}\t\t\t\"${f#"${BINARIES_DIR}/"}\",\n" done + + FILES="${FILES}\t\t\t\"splash.bmp\",\n" -echo $FILES + KERNEL=$(sed -n 's/^kernel=//p' "${BINARIES_DIR}/rpi-firmware/config.txt") FILES="${FILES}\t\t\t\"${KERNEL}\"" - +# Create genimage.cfg from template .in sed "s|#BOOT_FILES#|${FILES}|" "${BOARD_DIR}/genimage.cfg.in" | \ sed "s|#INFIX_ID#|${INFIX_ID}|" | \ sed "s|#VERSION#|${RELEASE}|" > "${GENIMAGE_CFG}" - +# Create temporary root path ROOTPATH_TMP=$(mktemp -d) trap 'rm -rf \"$ROOTPATH_TMP\"' EXIT +# Clean previous genimage temp directory rm -rf "${GENIMAGE_TMP}" +# Generate the SD card image genimage \ --rootpath "${ROOTPATH_TMP}" \ --tmppath "${GENIMAGE_TMP}" \ --inputpath "${BINARIES_DIR}" \ --outputpath "${BINARIES_DIR}" \ --config "${GENIMAGE_CFG}" + +# Print the resulting image path +if [ "$STANDALONE" -eq 1 ]; then + echo "" + echo "SD card image created successfully:" + for img in "${BINARIES_DIR}"/*-sdcard.img; do + if [ -f "$img" ]; then + # Get relative path from current directory + rel_path=$(realpath --relative-to="$PWD" "$img" 2>/dev/null || echo "$img") + echo " $rel_path" + fi + done +fi From 948247254ba3855e471cc00727a3a4806cfe60de Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 Oct 2025 21:26:40 +0200 Subject: [PATCH 08/12] board/bpi: minor, whitespace cleanup Signed-off-by: Joachim Wiberg --- src/board/banana-pi-r3/genimage.cfg.in | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/board/banana-pi-r3/genimage.cfg.in b/src/board/banana-pi-r3/genimage.cfg.in index 9c9b695f..c3734ad4 100644 --- a/src/board/banana-pi-r3/genimage.cfg.in +++ b/src/board/banana-pi-r3/genimage.cfg.in @@ -1,4 +1,3 @@ - image cfg.ext4 { empty = true temporary = true @@ -27,19 +26,19 @@ image #INFIX_ID##VERSION#-bpi-r3-sdcard.img { partition bl2 { image = "bl2.img" offset = 1024s # 0x80000 = sector 1024 - size = 4M # 0x400000 + size = 4M # 0x400000 bootable = true - } + } - # Factory/calibration data (sectors 9216-13311) - partition factory { - offset = 4608K # 0x480000 - size = 2M # 0x200000 - } + # Factory/calibration data (sectors 9216-13311) + partition factory { + offset = 4608K # 0x480000 + size = 2M # 0x200000 + } -# FIP partition - BL31 + U-Boot (sectors 13312-17407) + # FIP partition - BL31 + U-Boot (sectors 13312-17407) partition fip { - # partition-type = 0x83 # Linux filesystem +# partition-type = 0x83 # Linux filesystem image = "fip.bin" offset = 13312s size = 4096s From 151f3491a2155e0a5c8c0b5c1da22fc0931d8687 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 14:35:00 +0200 Subject: [PATCH 09/12] cli: fix error handling in text-editor and change commands Fixes #1194 Signed-off-by: Joachim Wiberg --- package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash | 2 +- package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash index 717f3a8f..64eef92a 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.hash @@ -1,3 +1,3 @@ # Locally calculated sha256 9d9d33b873917ca5d0bdcc47a36d2fd385971ab0c045d1472fcadf95ee5bcf5b LICENCE -sha256 a6fe769a8f24a065b274f4e0f5f1fec634b2aae5bdd586aa6f71fe60ca6b8a64 klish-plugin-sysrepo-30bc6294489807ea026abed20f94d1ad1583cc6b-git4.tar.gz +sha256 cfe1064849a158f3eb9e82f12a709723115fc9bc4d30056e0e96ea0ba03672a2 klish-plugin-sysrepo-4e86a836c9b09a14c9625ea3d3b56b6578be4833-git4.tar.gz diff --git a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk index f8030eb7..ddd22ffb 100644 --- a/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk +++ b/package/klish-plugin-sysrepo/klish-plugin-sysrepo.mk @@ -4,7 +4,7 @@ # ################################################################################ -KLISH_PLUGIN_SYSREPO_VERSION = 30bc6294489807ea026abed20f94d1ad1583cc6b +KLISH_PLUGIN_SYSREPO_VERSION = 4e86a836c9b09a14c9625ea3d3b56b6578be4833 KLISH_PLUGIN_SYSREPO_SITE = https://github.com/kernelkit/klish-plugin-sysrepo.git #KLISH_PLUGIN_SYSREPO_VERSION = cdd3eb51a7f7ee0ed5bd925fa636061d3b1b85fb #KLISH_PLUGIN_SYSREPO_SITE = https://src.libcode.org/pkun/klish-plugin-sysrepo.git From c972eebaac55d902a9afbf8f928ca631c9c46549 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 17:25:09 +0200 Subject: [PATCH 10/12] doc: drop TODO.org file, replaced entirely with issues and project Signed-off-by: Joachim Wiberg --- doc/TODO.org | 72 ---------------------------------------------------- 1 file changed, 72 deletions(-) delete mode 100644 doc/TODO.org diff --git a/doc/TODO.org b/doc/TODO.org deleted file mode 100644 index 7e7840ce..00000000 --- a/doc/TODO.org +++ /dev/null @@ -1,72 +0,0 @@ -* TODO Add support for firewall -- [X] All "implicit" policies in zones are now policies: intra- and inter-zone policies -- [X] Add locked rules for implicit drop/reject policy as last rule in policy (ANY, ANY) -- [X] Firewall logs should show IN=iface (IIF) before SOURCE -- [X] Interfaces are not defaulting to the default zone, must handle bridge - ports and changes to enslavement, so regenerate every time is a must! -- [ ] firewalld helpers -- possibly for conntrack, e.g., ftp -- [ ] With =modprobe br_netfilter= firewalld would see *all* traffic, but there are - issues, , and limits to what - seem to be possible atm. You may also need to enable these callbacks: - =echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-iptables= - =echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-ip6tables= - =echo 1 | sudo tee /proc/sys/net/bridge/bridge-nf-call-arptables= -- [X] Add missing upper to port forward since port ranges are supported, see services! -- [X] =[do] show firewall= not available yet -- [X] Add RPC to pause firewall using =firewall-cmd --panic-on= and restart - firewall again with =firewall-cmd --panic-off=. The current state can - be queried using =firewall-cmd --query-panic=, which returns =yes= -- [X] Remove debug log messages! -- [X] Add "Log Messages" section to =show firewall= when =LogDenied ≠ off= -- [ ] Investigate filtering out firewall log messages from other log files -- [1/2] Rename policy->policy to policy->action, and replace allow->forward -- [X] Rename zone->sources to networks -- [X] A zone's action is for ingress, clarify this if missing! -- [X] Any services/ports listed in a zone with policy:accept are a NO-OP -- [X] =firwall-cmd --reload= takes fooooorever! :-( -- [X] If forwarding is disabled in a zone then the zone matrix should - show deny for the same zone-to-zone communication -- [X] We should show the implicit rules for communicating with the HOST -- [X] Investigate "padlock" on built-in policys (and zones?) and expose more? -- [X] Document established,related somewhere, fixed/padlocked policy? Also, - document why this is a good idea to always have enabled. See RH docs. -- [ ] Podman published ports, -- [ ] Software fastpath -- +[ ] Allow overriding/editing immutable policies and zones+ -- [X] Add tests: basic (end device), wan-lan, wan-lan-dmz, +hammer (stress)+ -- [X] Add documentation - - See - - Add some tool tips: nc, nmap, ping, and socat to stress the firewall -- [X] Fix inference so we can remove defaults from factory-config! -- [X] Add iperf service -- [X] Add nftables ownership=yes setting, introduced in later firewalld versions -- [ ] Investigate fail2ban integration with firewalld, for more info, see: - https://github.com/firewalld/firewalld/issues/1466#issuecomment-2773130569 -- [ ] Update screenshots for documentation -- [ ] Review both cli-pretty and yanger code -- [ ] Review default-zone handling (needed?) -- [ ] Clean up =INFER_POLICY= ifdefs -- [ ] Revisit built-in fallback zones (public, block, drop) - -* TODO doc: User Guide - -- Feature set and scope, e.g. - - Device discovery: LLDP, mDNS-SD how do they work, interfacing with Windows/macOS/Linux - - Network redundancy protocols: STP/RSTP, MRP -- Configuring the system; using ifupdown2, enabling/disabling services -- Diagnosing the system; using rmon, port mirroring, debugging services, searching logs -- Limitations, e.g., PRP/HSR or IEEE 802.1CB will not be possible to support -- Tips & Trix - -* TODO document how to set up passwordless SSH -* TODO add setup wizard, based on pdmenu - - - setup-port script to tweak ethtool settings - - setup-iface script to configure a layer-3 interface - - setup-bridge script that creates a new bridge with config from cmdline - - setup-firewall script that can do basic firewall rules and masquerading - -* TODO split out qemu Config.in to a "make run-menuconfing" -* TODO rename qemu/ to run/, perhaps? -* TODO ship qemu/* with output/images/ for stand-alone runs of older builds - From 887e34e0ef0c61077091be01297ba35c147aa9a2 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 18:00:37 +0200 Subject: [PATCH 11/12] doc: fix RESTCONF scripting examples and curl.sh wrapper The curl.sh wrapper script had several issues: - Used 'shift 2' incorrectly without proper argument validation - Required hostname as enviroment variable instead of option - Lacked proper option parsing, should behave like a cross between curl and sysrepocfg All examples have been updated to match the refactored script, and a local copy in utils/curl.sh has been added. Signed-off-by: Joachim Wiberg --- doc/scripting-restconf.md | 148 ++++++++++++++++++++++++++------------ utils/curl.sh | 74 +++++++++++++++++++ 2 files changed, 178 insertions(+), 44 deletions(-) create mode 100755 utils/curl.sh diff --git a/doc/scripting-restconf.md b/doc/scripting-restconf.md index 567c4442..5f9069b5 100644 --- a/doc/scripting-restconf.md +++ b/doc/scripting-restconf.md @@ -16,23 +16,79 @@ To simplify RESTCONF operations, create a `curl.sh` wrapper script: ```bash #!/bin/sh +# RESTCONF CLI wrapper for curl -AUTH=${AUTH:-admin:admin} +# Show usage and exit +usage() +{ + cat <<-EOF >&2 + Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...] + + Options: + -h HOST Target host (default: infix.local) + -d DS Datastore: running, operational, startup (default: running) + -u CREDS Credentials as user:pass (default: admin:admin) + + Methods: GET, POST, PUT, PATCH, DELETE + EOF + exit "$1" +} + +# Default values HOST=${HOST:-infix.local} +DATASTORE=running +AUTH=admin:admin -method=$1 -path=$2 +# Parse options +while getopts "h:d:u:" opt; do + case $opt in + h) HOST="$OPTARG" ;; + d) DATASTORE="$OPTARG" ;; + u) AUTH="$OPTARG" ;; + *) usage 1 ;; + esac +done +shift $((OPTIND - 1)) + +# Validate required arguments +if [ $# -lt 2 ]; then + echo "Error: METHOD and PATH are required" >&2 + usage 1 +fi + +METHOD=$1 +PATH=$2 shift 2 -set -x -exec curl \ - --insecure \ - --user ${AUTH} \ - --request ${method} \ - --header "Content-Type: application/yang-data+json" \ - --header "Accept: application/yang-data+json" \ - "$@" \ - https://${HOST}/restconf/ds/ietf-datastores:${path} +# Ensure PATH starts with / +case "$PATH" in + /*) ;; + *) PATH="/$PATH" ;; +esac + +# Build URL based on datastore +case "$DATASTORE" in + running|startup) + URL="https://${HOST}/restconf/data${PATH}" + ;; + operational) + URL="https://${HOST}/restconf/data${PATH}" + ;; + *) + echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2 + exit 1 + ;; +esac + +# Execute curl with all remaining arguments passed through +exec /usr/bin/curl \ + --insecure \ + --user "${AUTH}" \ + --request "${METHOD}" \ + --header "Content-Type: application/yang-data+json" \ + --header "Accept: application/yang-data+json" \ + "$@" \ + "${URL}" ``` Make it executable: @@ -41,12 +97,16 @@ Make it executable: ~$ chmod +x curl.sh ``` -This wrapper handles authentication, headers, and the base URL construction, -making commands much cleaner. You can override defaults with environment -variables: +This wrapper handles authentication, headers, SSL certificates, and URL +construction, making commands much cleaner. You can override defaults with +command-line options or environment variables: ```bash -~$ HOST=192.168.1.10 AUTH=admin:secret ./curl.sh GET running/... +# Using command-line options +~$ ./curl.sh -h 192.168.1.10 -d operational -u admin:secret GET /ietf-interfaces:interfaces + +# Using environment variables +~$ HOST=192.168.1.10 ./curl.sh GET /ietf-system:system ``` The examples below show both raw `curl` commands and the equivalent using @@ -63,7 +123,7 @@ practical workflows. **List all interface names:** ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null | jq -r '.["ietf-interfaces:interfaces"]["interface"][].name' +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null | jq -r '.["ietf-interfaces:interfaces"]["interface"][].name' lo e0 e1 @@ -89,7 +149,7 @@ This returns all supported YANG modules, revisions, and features. Useful for exploration or backup: ```bash -~$ ./curl.sh example.local GET running -o backup.json +~$ ./curl.sh -h example.local GET / -o backup.json ``` ### Common Workflow Patterns @@ -99,21 +159,21 @@ Useful for exploration or backup: Get all interfaces with IPs and search: ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \ | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["ietf-ip:ipv4"]["address"][]?.ip == "192.168.1.100") | .name' ``` #### Pattern 2: List all interfaces that are down ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \ | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | select(.["oper-status"] == "down") | .name' ``` #### Pattern 3: Get statistics for all interfaces ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces 2>/dev/null \ +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces 2>/dev/null \ | jq -r '.["ietf-interfaces:interfaces"]["interface"][] | "\(.name): RX \(.statistics["in-octets"]) TX \(.statistics["out-octets"])"' ``` @@ -128,7 +188,7 @@ e1: RX 0 TX 0 #### Pattern 4: Check if interface exists before configuring ```bash -~$ if ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=eth0 2>/dev/null | grep -q "ietf-interfaces:interface"; then +~$ if ./curl.sh -h example.local GET /ietf-interfaces:interfaces/interface=eth0 2>/dev/null | grep -q "ietf-interfaces:interface"; then echo "Interface eth0 exists" else echo "Interface eth0 not found" @@ -157,7 +217,7 @@ Example of fetching JSON configuration data: **Using curl.sh:** ```bash -~$ ./curl.sh example.local GET running/ietf-system:system/hostname +~$ ./curl.sh -h example.local GET /ietf-system:system/hostname { "ietf-system:system": { "hostname": "foo" @@ -181,7 +241,7 @@ Example of updating configuration with inline JSON data: **Using curl.sh:** ```bash -~$ ./curl.sh example.local PATCH running/ietf-system:system \ +~$ ./curl.sh -h example.local PATCH /ietf-system:system \ -d '{"ietf-system:system":{"hostname":"bar"}}' ``` @@ -190,8 +250,8 @@ Example of updating configuration with inline JSON data: Add an IP address to the loopback interface: ```bash -~$ ./curl.sh example.local POST \ - running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ +~$ ./curl.sh -h example.local POST \ + /ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ -d '{ "prefix-length": 32 }' ``` @@ -200,8 +260,8 @@ Add an IP address to the loopback interface: Remove an IP address from the loopback interface: ```bash -~$ ./curl.sh example.local DELETE \ - running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 +~$ ./curl.sh -h example.local DELETE \ + /ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 ``` ### Copy Running to Startup @@ -228,8 +288,8 @@ and then update startup with it: **Using curl.sh:** ```bash -~$ ./curl.sh example.local GET running -o running-config.json -~$ ./curl.sh example.local PUT startup -d @running-config.json +~$ ./curl.sh -h example.local GET / -o running-config.json +~$ ./curl.sh -h example.local -d startup PUT / -d @running-config.json ``` ## Operational Data @@ -239,7 +299,7 @@ and then update startup with it: Get the running configuration for the loopback interface: ```bash -~$ ./curl.sh example.local GET running/ietf-interfaces:interfaces/interface=lo +~$ ./curl.sh -h example.local GET /ietf-interfaces:interfaces/interface=lo ``` ### Read Interface Operational State @@ -247,7 +307,7 @@ Get the running configuration for the loopback interface: Get operational data (state, statistics, etc.) for an interface: ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=lo +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces/interface=lo ``` This includes administrative and operational state, MAC address, MTU, and @@ -258,7 +318,7 @@ statistics counters. Extract specific statistics using `jq`: ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces/interface=eth0 2>/dev/null \ +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces/interface=eth0 2>/dev/null \ | jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]' ``` @@ -267,7 +327,7 @@ Extract specific statistics using `jq`: Get operational data for all interfaces: ```bash -~$ ./curl.sh example.local GET operational/ietf-interfaces:interfaces +~$ ./curl.sh -h example.local -d operational GET /ietf-interfaces:interfaces ``` ### Read Routing Table @@ -275,7 +335,7 @@ Get operational data for all interfaces: Get the IPv4 routing table: ```bash -~$ ./curl.sh example.local GET operational/ietf-routing:routing/ribs/rib=ipv4-default +~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/ribs/rib=ipv4-default ``` ### Read OSPF State @@ -283,13 +343,13 @@ Get the IPv4 routing table: Get OSPF operational data (neighbors, routes, etc.): ```bash -~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default +~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default ``` Or get just the neighbor information: ```bash -~$ ./curl.sh example.local GET operational/ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default/ietf-ospf:ospf/areas/area=0.0.0.0/interfaces +~$ ./curl.sh -h example.local -d operational GET /ietf-routing:routing/control-plane-protocols/control-plane-protocol=ietf-ospf:ospfv2,default/ietf-ospf:ospf/areas/area=0.0.0.0/interfaces ``` ## System Operations (RPCs) @@ -345,22 +405,22 @@ Create a `Makefile` to simplify common operations: HOST ?= infix.local lo-running: - ./curl.sh $(HOST) GET running/ietf-interfaces:interfaces/interface=lo + ./curl.sh -h $(HOST) GET /ietf-interfaces:interfaces/interface=lo lo-operational: - ./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=lo + ./curl.sh -h $(HOST) -d operational GET /ietf-interfaces:interfaces/interface=lo lo-add-ip: - ./curl.sh $(HOST) POST \ - running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ + ./curl.sh -h $(HOST) POST \ + /ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 \ -d '{ "prefix-length": 32 }' lo-del-ip: - ./curl.sh $(HOST) DELETE \ - running/ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 + ./curl.sh -h $(HOST) DELETE \ + /ietf-interfaces:interfaces/interface=lo/ietf-ip:ipv4/address=192.168.254.254 %-stats: - @./curl.sh $(HOST) GET operational/ietf-interfaces:interfaces/interface=$* 2>/dev/null \ + @./curl.sh -h $(HOST) -d operational GET /ietf-interfaces:interfaces/interface=$* 2>/dev/null \ | jq -r '.["ietf-interfaces:interfaces"]["interface"][0]["statistics"]["in-octets"]' %-monitor: diff --git a/utils/curl.sh b/utils/curl.sh new file mode 100755 index 00000000..dd26ba93 --- /dev/null +++ b/utils/curl.sh @@ -0,0 +1,74 @@ +#!/bin/sh +# RESTCONF CLI wrapper for curl + +# Show usage and exit +usage() +{ + cat <<-EOF >&2 + Usage: $0 [-h HOST] [-d DATASTORE] [-u USER:PASS] METHOD PATH [CURL_ARGS...] + + Options: + -h HOST Target host (default: infix.local) + -d DS Datastore: running, operational, startup (default: running) + -u CREDS Credentials as user:pass (default: admin:admin) + + Methods: GET, POST, PUT, PATCH, DELETE + EOF + exit "$1" +} + +# Default values +HOST=${HOST:-infix.local} +DATASTORE=running +AUTH=admin:admin + +# Parse options +while getopts "h:d:u:" opt; do + case $opt in + h) HOST="$OPTARG" ;; + d) DATASTORE="$OPTARG" ;; + u) AUTH="$OPTARG" ;; + *) usage 1 ;; + esac +done +shift $((OPTIND - 1)) + +# Validate required arguments +if [ $# -lt 2 ]; then + echo "Error: METHOD and PATH are required" >&2 + usage 1 +fi + +METHOD=$1 +PATH=$2 +shift 2 + +# Ensure PATH starts with / +case "$PATH" in + /*) ;; + *) PATH="/$PATH" ;; +esac + +# Build URL based on datastore +case "$DATASTORE" in + running|startup) + URL="https://${HOST}/restconf/data${PATH}" + ;; + operational) + URL="https://${HOST}/restconf/data${PATH}" + ;; + *) + echo "Error: Invalid datastore '$DATASTORE'. Use: running, operational, or startup" >&2 + exit 1 + ;; +esac + +# Execute curl with all remaining arguments passed through +exec /usr/bin/curl \ + --insecure \ + --user "${AUTH}" \ + --request "${METHOD}" \ + --header "Content-Type: application/yang-data+json" \ + --header "Accept: application/yang-data+json" \ + "$@" \ + "${URL}" From acb6cdc0437b68b13d98d7aeefe3028e847978ef Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Mon, 13 Oct 2025 17:17:19 +0200 Subject: [PATCH 12/12] doc: update changelog with latest features and fixes in v25.10 Signed-off-by: Joachim Wiberg --- doc/ChangeLog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index f229d368..0dbda7eb 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -11,9 +11,13 @@ All notable changes to the project are documented in this file. - Upgrade Linux kernel to 6.12.50 (LTS) - Extend NETCONF and RESTCONF scripting documentation with operational data examples, discovery patterns, and common workflow examples, issue #1156 +- Initial support for a zone-based firewall, based on `firewalld`, issue #448 +- Automatically expand `/var` partition on SD card at first boot on RPi ### Fixes +- Fix #1194: CLI `text-editor` command does not do proper input sanitation +- Fix #1197: RPi4 no longer boots after BPi-R3 merge, introduced in v25.09 [v25.09.0][] - 2025-09-30 ------------------------- @@ -1656,6 +1660,7 @@ Supported YANG models in addition to those used by sysrepo and netopeer: [buildroot]: https://buildroot.org/ [UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.09.0...HEAD +[v25.10.0]: https://github.com/kernelkit/infix/compare/v25.09.0...v26.10.0 [v25.09.0]: https://github.com/kernelkit/infix/compare/v25.08.0...v26.09.0 [v25.08.0]: https://github.com/kernelkit/infix/compare/v25.06.1...v26.08.0 [v25.06.0]: https://github.com/kernelkit/infix/compare/v25.05.1...v26.06.0