From 9c220d8a51fbbfc17541e342be42f642eb54876d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Nov 2025 21:19:02 +0100 Subject: [PATCH 1/6] board/common: utilize new finit-style logging for factory reset Signed-off-by: Joachim Wiberg --- board/common/rootfs/usr/libexec/infix/mnt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/board/common/rootfs/usr/libexec/infix/mnt b/board/common/rootfs/usr/libexec/infix/mnt index d46af0c64..fdc71f1a0 100755 --- a/board/common/rootfs/usr/libexec/infix/mnt +++ b/board/common/rootfs/usr/libexec/infix/mnt @@ -44,12 +44,15 @@ check_factory() factory_reset() { find /sys/class/leds/ -type l -exec sh -c 'echo 100 > $0/brightness' {} \; - logger $opt -p user.crit -t "$nm" "Resetting to factory defaults." + print_start "Resetting to factory defaults." + logger $opt -p user.notice -t "$nm" "Resetting to factory defaults." rm -rf /mnt/cfg/* /mnt/var/* - - logger $opt -p user.crit -t "$nm" "Factory reset complete." sync + + logger $opt -p user.notice -t "$nm" "Factory reset complete." + print_end 0 "Factory reset complete." + print_restore } is_mmc() From 04c86478c3968aa9cdc8d910ed7517c742b695c7 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Nov 2025 18:41:32 +0100 Subject: [PATCH 2/6] board/common: fix boot warnings, follow-up to 45efa94 In 45efa94 we introduced new mount options for the: 'aux', 'cfg', and 'var' partitions. To save boot time, we also disabled the periodic fsck check, which does not affect journal replay or other Ext4 safety or integrity checks. The latter involved calling tune2fs at runtime, but this caused the following to appear for the 'aux' partition, which is a reduced ext4 for systems that need to change U-Boot settings, e.g., to set MAC address on systems without a VPD. EXT4-fs: Mount option(s) incompatible with ext2 Note, this is a "bogus" warning, setting the fstypt to ext2 in fstab is not the way around this one. That's been tried. To make matters worse, the new mount option(s), e.g., 'commit=30', gave us another set of warnings from the kernel. This was due to the fstype being 'auto', so the kernel objected to options not being applicable to every filesystem it tried before ending up with extfs: squashfs: Unknown parameter 'commit' vfat: Unknown parameter 'commit' exfat: Unknown parameter 'commit' fuseblk: Unknown parameter 'commit' btrfs: Unknown parameter 'errors' This commit explicitly sets cfg and var to ext4, leaving mnt as auto, we also check before calling tune2fs that the partition/disk image is ext4. Signed-off-by: Joachim Wiberg --- board/common/rootfs/etc/fstab | 12 ++++++------ board/common/rootfs/usr/libexec/infix/mnt | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/board/common/rootfs/etc/fstab b/board/common/rootfs/etc/fstab index fc5850c79..70d11aac7 100644 --- a/board/common/rootfs/etc/fstab +++ b/board/common/rootfs/etc/fstab @@ -15,9 +15,9 @@ cfgfs /config configfs nofail,noauto 0 0 # The chosen backing storage for the overlays placed on /cfg, /etc, # /home, /root, and /var, are determined dynamically by /usr/libexec/infix/mnt # depending on the available devices. -mnttmp /mnt/tmp tmpfs defaults 0 0 -LABEL=aux /mnt/aux auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0 -LABEL=var /mnt/var auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0 -LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0 -hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0 -/usr/libexec/infix/mnt# /cfg helper none 0 0 +mnttmp /mnt/tmp tmpfs defaults 0 0 +LABEL=aux /mnt/aux auto noatime,nodiratime,noauto,errors=remount-ro 0 0 +LABEL=var /mnt/var ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0 +LABEL=cfg /mnt/cfg ext4 noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0 +hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0 +/usr/libexec/infix/mnt# /cfg helper none 0 0 diff --git a/board/common/rootfs/usr/libexec/infix/mnt b/board/common/rootfs/usr/libexec/infix/mnt index fdc71f1a0..852ead56f 100755 --- a/board/common/rootfs/usr/libexec/infix/mnt +++ b/board/common/rootfs/usr/libexec/infix/mnt @@ -292,8 +292,10 @@ mount_rw() # TODO: Also look for UBI partitions - # - tune2fs -c 0 -i 0 LABEL="$1" 2>/dev/null + # Disable periodic fsck, yet keeping safety checks on ext4 + if grep "LABEL=$label" /etc/fstab |grep -q ext4; then + tune2fs -c 0 -i 0 LABEL="$1" 2>/dev/null + fi mount LABEL="$1" 2>/dev/null && return 0 return 1 From b38e13a08a25acb3443bcbfc62158d7fd222c11d Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Nov 2025 18:39:06 +0100 Subject: [PATCH 3/6] board/common: check if partition/LABEL is available Check if partition/LABEL is available before trying to run tune2fs and mount commands on it. This change masks the kernel output: LABEL=var: Can't lookup blockdev commne when running `make run` on x86_64 builds. Signed-off-by: Joachim Wiberg --- board/common/rootfs/usr/libexec/infix/mnt | 43 +++++++++++++++++++---- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/board/common/rootfs/usr/libexec/infix/mnt b/board/common/rootfs/usr/libexec/infix/mnt index 852ead56f..4421613f3 100755 --- a/board/common/rootfs/usr/libexec/infix/mnt +++ b/board/common/rootfs/usr/libexec/infix/mnt @@ -108,15 +108,18 @@ find_partition_by_label() esac disk="/dev/$devname" + + # + # 1. Try GPT/MBR partition label using sgdisk + # result=$(sgdisk -p "$disk" 2>/dev/null | awk -v label="$label" -v devname="$devname" ' - /^ *[0-9]/ { + /^ *[0-9]/ { if ($7 == label) { - if (devname ~ /^(mmcblk|nvme|loop)/) { - print devname "p" $1 - } else { - print devname $1 - } - exit 0 + if (devname ~ /^(mmcblk|nvme|loop)/) + print devname "p" $1; + else + print devname $1; + exit 0; } } ') @@ -125,7 +128,30 @@ find_partition_by_label() echo "$result" return 0 fi + + # + # 2. Fallback: Check if the whole disk is an ext4/ext2/ext3 filesystem + # + + # Check for ext4/ext2/ext3 magic number (0xEF53) at offset 1080 (1024+56). + magic_number=$(dd if="$disk" bs=1 skip=1080 count=2 2>/dev/null | od -t x2 -A n | tr -d ' \n') + + # Check for both Little-Endian ('53ef') and Big-Endian ('ef53') interpretations of 0xEF53. + # This supports bi-endian architectures like MIPS that may run in BE mode, + # as well as the LE mode which is standard for RISC-V and ext filesystems. + if [ "$magic_number" = "ef53" ] || [ "$magic_number" = "53ef" ]; then + + # Read the volume label from offset 1144 (1024+120) + fslabel=$(dd if="$disk" bs=1 skip=1144 count=16 2>/dev/null | tr -d '\000') + logger $opt -p user.notice -t "$nm" "Found label $fslabel on disk $disk ..." + + if [ "$fslabel" = "$label" ]; then + echo "$devname" + return 0 + fi + fi done + return 1 } @@ -276,6 +302,9 @@ mount_rw() # If something is already setup, leave it be. mountpoint -q "/$1" && return 0 + # If partition doesn't exist (var is optional), signal caller. + find_partition_by_label "$1" >/dev/null || return 1 + # Check if /var has been resized to fill the sdcard/eMMC if [ "$1" = "var" ] && is_mmc; then if [ -f /mnt/aux/resized ] || [ -f /mnt/aux/resized.failed ]; then From 79ad6531509a08269d846bc6ad4a088a01fc14e9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Nov 2025 21:02:06 +0100 Subject: [PATCH 4/6] confd: minor coding style fixes and refactoring Collapse, simplify, and break up ietf_keystore_change() into multiple functions. Signed-off-by: Joachim Wiberg --- src/confd/src/core.c | 60 +++++----- src/confd/src/core.h | 1 - src/confd/src/ietf-keystore.c | 217 ++++++++++++++++++---------------- 3 files changed, 147 insertions(+), 131 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 8ba0ba985..c4a4ee5d6 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -8,16 +8,9 @@ struct confd confd; -int core_startup_save(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *priv) +static int startup_save(sr_session_ctx_t *session, uint32_t sub_id, const char *model, + const char *xpath, sr_event_t event, unsigned request_id, void *priv) { - sr_event_t last_event = -1; - static unsigned int last_request = -1; - if (last_event == event && last_request == request_id) - return SR_ERR_OK; - last_event = event; - last_request = request_id; - /* skip in bootstrap, triggered by load script to initialize startup datastore */ if (systemf("runlevel >/dev/null 2>&1")) return SR_ERR_OK; @@ -33,9 +26,10 @@ static confd_dependency_t add_dependencies(struct lyd_node **diff, const char *x struct lyd_node *new_node = NULL; struct lyd_node *target = NULL; struct lyd_node *root = NULL; - int rc; if (!lydx_get_xpathf(*diff, "%s", xpath)) { + int rc; + /* Create the path, potentially creating a new tree */ rc = lyd_new_path(NULL, LYD_CTX(*diff), xpath, value, LYD_NEW_PATH_UPDATE, &new_node); if (rc != LY_SUCCESS || !new_node) { @@ -147,7 +141,7 @@ static confd_dependency_t handle_dependencies(struct lyd_node **diff, struct lyd return result; } -static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, +static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *model_name, const char *xpath, sr_event_t event, uint32_t request_id, void *_confd) { struct lyd_node *diff = NULL, *config = NULL; @@ -258,16 +252,20 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod AUDIT("The new configuration has been applied."); } + free_diff: - lyd_free_tree(diff); - return rc; + lyd_free_tree(diff); + return rc; } -static inline int subscribe_module(char *model, struct confd *confd, int flags) { - return sr_module_change_subscribe(confd->session, model, "//.", change_cb, confd, - CB_PRIO_PRIMARY, SR_SUBSCR_CHANGE_ALL_MODULES | SR_SUBSCR_DEFAULT | flags, &confd->sub) && +static inline int subscribe_model(char *model, struct confd *confd, int flags) +{ + return sr_module_change_subscribe(confd->session, model, "//.", change_cb, confd, + CB_PRIO_PRIMARY, SR_SUBSCR_CHANGE_ALL_MODULES | + SR_SUBSCR_DEFAULT | flags, &confd->sub) && sr_module_change_subscribe(confd->startup, model, "//.", core_startup_save, NULL, - CB_PRIO_PASSIVE, SR_SUBSCR_PASSIVE | SR_SUBSCR_CHANGE_ALL_MODULES, &confd->sub); + CB_PRIO_PASSIVE, SR_SUBSCR_CHANGE_ALL_MODULES | + SR_SUBSCR_PASSIVE, &confd->sub); } int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) @@ -295,7 +293,7 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) if (!confd.conn) goto err; - /* The startup datastore is used for the core_startup_save() hook */ + /* The startup datastore is used for the startup_save() hook */ rc = sr_session_start(confd.conn, SR_DS_STARTUP, &confd.startup); if (rc) goto err; @@ -314,69 +312,69 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) */ confd.ifquirks = json_load_file("/etc/product/interface-quirks.json", 0, NULL); - rc = subscribe_module("ietf-interfaces", &confd, 0); + rc = subscribe_model("ietf-interfaces", &confd, 0); if (rc) { ERROR("Failed to subscribe to ietf-interfaces"); goto err; } - rc = subscribe_module("ietf-netconf-acm", &confd, 0); + rc = subscribe_model("ietf-netconf-acm", &confd, 0); if (rc) { ERROR("Failed to subscribe to ietf-netconf-acm"); goto err; } - rc = subscribe_module("infix-dhcp-client", &confd, 0); + rc = subscribe_model("infix-dhcp-client", &confd, 0); if (rc) { ERROR("Failed to subscribe to infix-dhcp-client"); goto err; } - rc = subscribe_module("ietf-keystore", &confd, SR_SUBSCR_UPDATE); + rc = subscribe_model("ietf-keystore", &confd, SR_SUBSCR_UPDATE); if (rc) { ERROR("Failed to subscribe to ietf-keystore"); goto err; } - rc = subscribe_module("infix-services", &confd, 0); + rc = subscribe_model("infix-services", &confd, 0); if (rc) { ERROR("Failed to subscribe to infix-services"); goto err; } - rc = subscribe_module("ietf-system", &confd, 0); + rc = subscribe_model("ietf-system", &confd, 0); if (rc) { ERROR("Failed to subscribe to ietf-system"); goto err; } - rc = subscribe_module("ieee802-dot1ab-lldp", &confd, 0); + rc = subscribe_model("ieee802-dot1ab-lldp", &confd, 0); if (rc) { ERROR("Failed to subscribe to ieee802-dot1ab-lldp"); goto err; } #ifdef CONTAINERS - rc = subscribe_module("infix-containers", &confd, 0); + rc = subscribe_model("infix-containers", &confd, 0); if (rc) { ERROR("Failed to subscribe to infix-containers"); goto err; } #endif - rc = subscribe_module("infix-dhcp-server", &confd, 0); + rc = subscribe_model("infix-dhcp-server", &confd, 0); if (rc) { ERROR("Failed to subscribe to infix-dhcp-server"); goto err; } - rc = subscribe_module("ietf-routing", &confd, 0); + rc = subscribe_model("ietf-routing", &confd, 0); if (rc) { ERROR("Failed to subscribe to ietf-routing"); goto err; } - rc = subscribe_module("ietf-hardware", &confd, 0); + rc = subscribe_model("ietf-hardware", &confd, 0); if (rc) { ERROR("Failed to subscribe to ietf-hardware"); goto err; } - rc = subscribe_module("infix-firewall", &confd, 0); + rc = subscribe_model("infix-firewall", &confd, 0); if (rc) { ERROR("Failed to subscribe to infix-firewall"); goto err; } - rc = subscribe_module("infix-meta", &confd, SR_SUBSCR_UPDATE); + rc = subscribe_model("infix-meta", &confd, SR_SUBSCR_UPDATE); if (rc) { ERROR("Failed to subscribe to infix-meta"); goto err; diff --git a/src/confd/src/core.h b/src/confd/src/core.h index 0317f83ec..d7c2f2e0d 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -135,7 +135,6 @@ struct confd { struct dagger netdag; }; -int core_startup_save (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); static inline int register_change(sr_session_ctx_t *session, const char *module, const char *xpath, int flags, sr_module_change_cb cb, void *arg, sr_subscription_ctx_t **sub) diff --git a/src/confd/src/ietf-keystore.c b/src/confd/src/ietf-keystore.c index a87303ee5..fa1d786fe 100644 --- a/src/confd/src/ietf-keystore.c +++ b/src/confd/src/ietf-keystore.c @@ -51,89 +51,122 @@ static char *filerd(const char *fn, size_t len) return buf; } -int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) +static int gen_hostkey(const char *name, struct lyd_node *change) { - struct lyd_node *changes, *change; - sr_val_t *list = NULL; + const char *private_key, *public_key; int rc = SR_ERR_OK; + + private_key = lydx_get_cattr(change, "cleartext-private-key"); + public_key = lydx_get_cattr(change, "public-key"); + + if (mkdir(SSH_HOSTKEYS_NEXT, 0600) && (errno != EEXIST)) { + ERRNO("Failed creating %s", SSH_HOSTKEYS_NEXT); + rc = SR_ERR_INTERNAL; + } + + if (systemf("/usr/libexec/infix/mksshkey %s %s %s %s", name, SSH_HOSTKEYS_NEXT, public_key, private_key)) + rc = SR_ERR_INTERNAL; + + return rc; +} + +static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff) +{ + const char *xpath = "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key"; + sr_val_t *list = NULL; size_t count = 0; - if (diff && !lydx_find_xpathf(diff, XPATH_KEYSTORE_)) - return SR_ERR_OK; + int rc; - switch (event) { - case SR_EV_UPDATE: - rc = sr_get_items(session, "/ietf-keystore:keystore/asymmetric-keys/asymmetric-key", 0, 0, &list, &count); - if (rc != SR_ERR_OK) { - ERROR("Cannot find any asymmetric keys in configuration"); - return 0; + rc = sr_get_items(session, xpath, 0, 0, &list, &count); + if (rc != SR_ERR_OK) { + ERROR("Cannot find any asymmetric keys in configuration"); + return 0; + } + + for (size_t i = 0; i < count; i++) { + char *name = srx_get_str(session, "%s/name", list[i].xpath); + char *public_key_format, *private_key_format; + char *pub_key = NULL, *priv_key = NULL; + sr_val_t *entry = &list[i]; + + if (srx_isset(session, "%s/cleartext-private-key", entry->xpath) || + srx_isset(session, "%s/public-key", entry->xpath)) + continue; + + public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath); + if (!public_key_format) + continue; + + private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath); + if (!private_key_format) { + free(public_key_format); + continue; } + if (strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") || + strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format")) + continue; - for (size_t i = 0; i < count; ++i) { - sr_val_t *entry = &list[i]; - - if (!srx_isset(session, "%s/cleartext-private-key", entry->xpath) && !srx_isset(session, "%s/public-key", entry->xpath)) { - char *private_key_format, *public_key_format; - - public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath); - if (!public_key_format) - continue; - private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath); - if (!private_key_format) { - free(public_key_format); - continue; - } - - if (!strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") && - !strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format")) { - char *pub_key = NULL, *priv_key = NULL, *name; - - name = srx_get_str(session, "%s/name", entry->xpath); - NOTE("SSH key (%s) does not exist, generating...", name); - if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) { - ERROR("Failed to generate SSH keys for %s", name); - goto next; - } - - priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); - if (!priv_key) - goto next; - - pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); - if (!pub_key) - goto next; - - rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath); - if (rc) { - ERROR("Failed setting private key for %s... rc: %d", name, rc); - goto next; - } - rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath); - if (rc != SR_ERR_OK) { - ERROR("Failed setting public key for %s... rc: %d", name, rc); - goto next; - } - next: - if (erase(SSH_PRIVATE_KEY)) - ERRNO("Failed removing SSH server private key"); - if (erase(SSH_PUBLIC_KEY)) - ERRNO("Failed removing SSH server public key"); - - if (priv_key) - free(priv_key); - - if (pub_key) - free(pub_key); - - free(name); - } - free(public_key_format); - free(private_key_format); - } + NOTE("SSH key (%s) does not exist, generating...", name); + if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) { + ERROR("Failed generating SSH keys for %s", name); + goto next; } - if (list) - sr_free_values(list, count); + priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); + if (!priv_key) + goto next; + + pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); + if (!pub_key) + goto next; + + rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath); + if (rc) { + ERROR("Failed setting private key for %s... rc: %d", name, rc); + goto next; + } + + rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath); + if (rc != SR_ERR_OK) { + ERROR("Failed setting public key for %s... rc: %d", name, rc); + goto next; + } + next: + if (erase(SSH_PRIVATE_KEY)) + ERRNO("Failed removing SSH server private key"); + if (erase(SSH_PUBLIC_KEY)) + ERRNO("Failed removing SSH server public key"); + + if (priv_key) + free(priv_key); + + if (pub_key) + free(pub_key); + + free(name); + free(public_key_format); + free(private_key_format); + } + + if (list) + sr_free_values(list, count); + + return 0; +} + +int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, + sr_event_t event, struct confd *confd) +{ + struct lyd_node *changes, *change; + int rc = SR_ERR_OK; + + if (diff && !lydx_find_xpathf(diff, XPATH_KEYSTORE_)) + return SR_ERR_OK; + + switch (event) { + case SR_EV_UPDATE: + rc = keystore_update(session, config, diff); break; case SR_EV_CHANGE: case SR_EV_ENABLED: @@ -142,49 +175,35 @@ int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, str rmrf(SSH_HOSTKEYS_NEXT); return SR_ERR_OK; case SR_EV_DONE: - if(fexist(SSH_HOSTKEYS_NEXT)) { - if(rmrf(SSH_HOSTKEYS)) { + if (fexist(SSH_HOSTKEYS_NEXT)) { + if (rmrf(SSH_HOSTKEYS)) ERRNO("Failed to remove old SSH hostkeys: %d", errno); - } - if (rename(SSH_HOSTKEYS_NEXT, SSH_HOSTKEYS)) ERRNO("Failed switching to new %s", SSH_HOSTKEYS); } return SR_ERR_OK; - default: return SR_ERR_OK; } changes = lydx_get_descendant(config, "keystore", "asymmetric-keys", "asymmetric-key", NULL); - LYX_LIST_FOR_EACH(changes, change, "asymmetric-key") { - const char *name, *private_key_type, *public_key_type; - const char *private_key, *public_key; + const char *name = lydx_get_cattr(change, "name"); + const char *type; - name = lydx_get_cattr(change, "name"); - private_key_type = lydx_get_cattr(change, "private-key-format"); - public_key_type = lydx_get_cattr(change, "public-key-format"); - - if (strcmp(private_key_type, "infix-crypto-types:rsa-private-key-format")) { - INFO("Private key %s is not of SSH type", name); + type = lydx_get_cattr(change, "private-key-format"); + if (strcmp(type, "infix-crypto-types:rsa-private-key-format")) { + INFO("Private key %s is not of SSH type (%s)", name, type); continue; } - if (strcmp(public_key_type, "infix-crypto-types:ssh-public-key-format")) { - INFO("Public key %s is not of SSH type", name); + type = lydx_get_cattr(change, "public-key-format"); + if (strcmp(type, "infix-crypto-types:ssh-public-key-format")) { + INFO("Public key %s is not of SSH type (%s)", name, type); continue; } - private_key = lydx_get_cattr(change, "cleartext-private-key"); - public_key = lydx_get_cattr(change, "public-key"); - - if (mkdir(SSH_HOSTKEYS_NEXT, 0600) && (errno != EEXIST)) { - ERRNO("Failed creating %s", SSH_HOSTKEYS_NEXT); - rc = SR_ERR_INTERNAL; - } - if(systemf("/usr/libexec/infix/mksshkey %s %s %s %s", name, SSH_HOSTKEYS_NEXT, public_key, private_key)) - rc = SR_ERR_INTERNAL; + gen_hostkey(name, change); } return rc; From 33999ceebc57b25ddc03c6c7acf93254fc256b5f Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Sun, 2 Nov 2025 21:05:34 +0100 Subject: [PATCH 5/6] confd: fix annoying warning in log This fixes the annoying libyang warning after commit da29771. confd[3375]: libyang[0]: Invalid argument ctx_node (lyd_find_xpath()). This happens when the diff is used in the wrong event when it is NULL. Signed-off-by: Joachim Wiberg --- src/confd/src/infix-dhcp-server.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/confd/src/infix-dhcp-server.c b/src/confd/src/infix-dhcp-server.c index 2a5431749..ffff18407 100644 --- a/src/confd/src/infix-dhcp-server.c +++ b/src/confd/src/infix-dhcp-server.c @@ -300,9 +300,6 @@ int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config, int enabled = 0, added = 0, deleted = 0; sr_error_t err = 0; - if (!lydx_get_xpathf(diff, CFG_XPATH)) - return SR_ERR_OK; - switch (event) { case SR_EV_DONE: break; @@ -312,6 +309,9 @@ int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config, return SR_ERR_OK; } + if (!lydx_get_xpathf(diff, CFG_XPATH)) + return SR_ERR_OK; + global = lydx_get_descendant(config, "dhcp-server", NULL); enabled = lydx_is_enabled(global, "enabled"); From f08947092b1d75cdd0fe0266f38e2956363e77ba Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 5 Nov 2025 20:41:10 +0100 Subject: [PATCH 6/6] confd: fix update of /cfg/startup-config.cfg Follow-up to ed23558 Signed-off-by: Joachim Wiberg --- src/confd/src/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index c4a4ee5d6..4fbf1bebb 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -262,8 +262,8 @@ static inline int subscribe_model(char *model, struct confd *confd, int flags) { return sr_module_change_subscribe(confd->session, model, "//.", change_cb, confd, CB_PRIO_PRIMARY, SR_SUBSCR_CHANGE_ALL_MODULES | - SR_SUBSCR_DEFAULT | flags, &confd->sub) && - sr_module_change_subscribe(confd->startup, model, "//.", core_startup_save, NULL, + SR_SUBSCR_DEFAULT | flags, &confd->sub) || + sr_module_change_subscribe(confd->startup, model, "//.", startup_save, NULL, CB_PRIO_PASSIVE, SR_SUBSCR_CHANGE_ALL_MODULES | SR_SUBSCR_PASSIVE, &confd->sub); }