From 4602822fc888baea13295b57d3dd9474754dc2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 23 Feb 2026 19:52:16 +0100 Subject: [PATCH 1/4] confd: Add YANG pattern constraints for string leaves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add input validation patterns to string-type leaves in container, firewall, DHCP, and interface YANG models. Also use mkdtemp() for temporary key files in keystore. Signed-off-by: Mattias Walström --- .gitignore | 2 +- src/confd/src/keystore.c | 25 +++++++----- src/confd/yang/confd/infix-containers.yang | 40 ++++++++++++++----- ....yang => infix-containers@2026-02-23.yang} | 0 src/confd/yang/confd/infix-dhcp-server.yang | 12 ++++-- src/confd/yang/confd/infix-firewall.yang | 12 ++++-- src/confd/yang/confd/infix-interfaces.yang | 1 + src/confd/yang/containers.inc | 2 +- 8 files changed, 68 insertions(+), 26 deletions(-) rename src/confd/yang/confd/{infix-containers@2025-12-09.yang => infix-containers@2026-02-23.yang} (100%) diff --git a/.gitignore b/.gitignore index 354f63f00..40975fc54 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .claude .gdb_history .claude +AGENTS.md /.backup /.ccache /dl @@ -11,4 +12,3 @@ /test/.log /local.mk /test/spec/Readme.adoc - diff --git a/src/confd/src/keystore.c b/src/confd/src/keystore.c index 069467485..6f493e5c0 100644 --- a/src/confd/src/keystore.c +++ b/src/confd/src/keystore.c @@ -12,8 +12,6 @@ #define XPATH_KEYSTORE_ASYM "/ietf-keystore:keystore/asymmetric-keys" #define XPATH_KEYSTORE_SYM "/ietf-keystore:keystore/symmetric-keys" -#define SSH_PRIVATE_KEY "/tmp/ssh.key" -#define SSH_PUBLIC_KEY "/tmp/ssh.pub" /* return file size */ static size_t filesz(const char *fn) @@ -91,6 +89,9 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s } for (size_t i = 0; i < count; i++) { + char tmpdir[] = "/tmp/keystore.XXXXXX"; + char priv_path[sizeof(tmpdir) + 16]; + char pub_path[sizeof(tmpdir) + 16]; 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; @@ -115,16 +116,24 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s continue; NOTE("SSH key (%s) does not exist, generating...", name); - if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) { + + if (!mkdtemp(tmpdir)) { + ERRNO("Failed creating temp dir for SSH key generation"); + goto next; + } + snprintf(priv_path, sizeof(priv_path), "%s/ssh.key", tmpdir); + snprintf(pub_path, sizeof(pub_path), "%s/ssh.pub", tmpdir); + + if (systemf("/usr/libexec/infix/mkkeys %s %s", priv_path, pub_path)) { ERROR("Failed generating SSH keys for %s", name); goto next; } - priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); + priv_key = filerd(priv_path, filesz(priv_path)); if (!priv_key) goto next; - pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); + pub_key = filerd(pub_path, filesz(pub_path)); if (!pub_key) goto next; @@ -140,10 +149,8 @@ static int keystore_update(sr_session_ctx_t *session, struct lyd_node *config, s 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 (rmrf(tmpdir)) + ERRNO("Failed removing temp dir %s", tmpdir); if (priv_key) free(priv_key); diff --git a/src/confd/yang/confd/infix-containers.yang b/src/confd/yang/confd/infix-containers.yang index a1ddd09ee..f0950002b 100644 --- a/src/confd/yang/confd/infix-containers.yang +++ b/src/confd/yang/confd/infix-containers.yang @@ -22,6 +22,11 @@ module infix-containers { prefix infix-sys; } + revision 2026-02-23 { + description "Input validation improvements"; + reference "internal"; + } + revision 2025-12-09 { description "Add resource management: - Add resource-limit container with memory and cpu configuration. @@ -84,6 +89,17 @@ module infix-containers { } } + + typedef image-reference { + description "OCI image reference or transport URI. + Allows registry references (e.g., quay.io/user/image:tag), + transport prefixes (docker://, oci-archive:, dir:), and + download URLs (ftp://, http://, https://)."; + type string { + pattern '[a-zA-Z0-9][a-zA-Z0-9_./:@=+%~-]*'; + } + } + typedef mount-type { type enumeration { enum bind { @@ -181,7 +197,7 @@ module infix-containers { container will be put on a queue that retries pull every time there is a route change in the host's system."; mandatory true; - type string; + type image-reference; } container checksum { @@ -240,7 +256,9 @@ module infix-containers { leaf command { description "Override ENTRYPOINT from image and run command + args."; - type string; + type string { + pattern '[a-zA-Z0-9_./ :=@%^,+-]+'; + } } leaf hostname { @@ -298,7 +316,9 @@ module infix-containers { NOTE: Some (*) options only work with masquerading container bridges, which automatically create VETH pairs with one end in the host bridge and the other in the container."; - type string; + type string { + pattern '[a-zA-Z_][a-zA-Z0-9_]*=[a-zA-Z0-9.:_/-]+'; + } } } @@ -310,7 +330,9 @@ module infix-containers { Sample: 8080:80 -- forward tcp port 8080 to container port 80 69:69/udp -- forward udp port 69 to container port 69 127.0.0.1:8080:80 -- forward only from loopback interface"; - type string; + type string { + pattern '[0-9.:\[\]]+(/[a-zA-Z]+)?'; + } } leaf-list dns { @@ -464,7 +486,7 @@ module infix-containers { When mounting files, directories (and globs) from the host, the source must be an absolute path."; type string { - pattern '/.*'; + pattern '/[a-zA-Z0-9_./*?-]+([ ]?[a-zA-Z0-9_./*?-]+)*'; } } } @@ -493,7 +515,7 @@ module infix-containers { or import the text file using the 'content' node."; mandatory true; type string { - pattern '/.*'; + pattern '/[a-zA-Z0-9_./-]+(/[a-zA-Z0-9_./-]+)*'; } } @@ -545,7 +567,7 @@ module infix-containers { description "Absolute path to target destination directory inside the container."; mandatory true; type string { - pattern '/.*'; + pattern '/[a-zA-Z0-9_./-]+(/[a-zA-Z0-9_./-]+)*'; } } } @@ -593,12 +615,12 @@ module infix-containers { input { leaf uri { description "The URL or local file path, e.g., /lib/oci/archive.tar.gz"; - type string; + type image-reference; mandatory true; } leaf name { description "Image name[:tag], default: basename of archive dir + :latest"; - type string; + type image-reference; } } } diff --git a/src/confd/yang/confd/infix-containers@2025-12-09.yang b/src/confd/yang/confd/infix-containers@2026-02-23.yang similarity index 100% rename from src/confd/yang/confd/infix-containers@2025-12-09.yang rename to src/confd/yang/confd/infix-containers@2026-02-23.yang diff --git a/src/confd/yang/confd/infix-dhcp-server.yang b/src/confd/yang/confd/infix-dhcp-server.yang index 84d6242dc..10acf7fb1 100644 --- a/src/confd/yang/confd/infix-dhcp-server.yang +++ b/src/confd/yang/confd/infix-dhcp-server.yang @@ -113,7 +113,9 @@ module infix-dhcp-server { case default-opt { leaf string { description "Generic string value."; - type string; + type string { + pattern '[^\p{Cc}]*'; + } } } } @@ -150,7 +152,9 @@ module infix-dhcp-server { leaf description { description "Additional information about this subnet (e.g., purpose, location, or notes)."; - type string; + type string { + pattern '[^\p{Cc}]*'; + } } leaf enabled { @@ -206,7 +210,9 @@ module infix-dhcp-server { leaf description { description "Additional information about this entry, e.g., owner's name, equipment details, or location."; - type string; + type string { + pattern '[^\p{Cc}]*'; + } } container match { diff --git a/src/confd/yang/confd/infix-firewall.yang b/src/confd/yang/confd/infix-firewall.yang index 92a9c7f53..ca2119db1 100644 --- a/src/confd/yang/confd/infix-firewall.yang +++ b/src/confd/yang/confd/infix-firewall.yang @@ -201,7 +201,9 @@ module infix-firewall { leaf description { description "Free-form description of the zone."; - type string; + type string { + pattern '[^\p{Cc}<>&]*'; + } } leaf-list interface { @@ -304,7 +306,9 @@ module infix-firewall { leaf description { description "Free-form description of this policy's purpose and scope."; - type string; + type string { + pattern '[^\p{Cc}<>&]*'; + } } leaf-list ingress { @@ -421,7 +425,9 @@ module infix-firewall { leaf description { description "Free-form description of the service."; - type string; + type string { + pattern '[^\p{Cc}<>&]*'; + } } list port { diff --git a/src/confd/yang/confd/infix-interfaces.yang b/src/confd/yang/confd/infix-interfaces.yang index 097b581dc..3e6d88ba0 100644 --- a/src/confd/yang/confd/infix-interfaces.yang +++ b/src/confd/yang/confd/infix-interfaces.yang @@ -204,6 +204,7 @@ module infix-interfaces { deviate replace { type string { length "0..64"; + pattern '[^\p{Cc}]*'; } } } diff --git a/src/confd/yang/containers.inc b/src/confd/yang/containers.inc index 6f13f9713..dc629ad9d 100644 --- a/src/confd/yang/containers.inc +++ b/src/confd/yang/containers.inc @@ -1,5 +1,5 @@ # -*- sh -*- MODULES=( "infix-interfaces -e containers" - "infix-containers@2025-12-09.yang" + "infix-containers@2026-02-23.yang" ) From 3759b0c0293d498b23eabf3a80288fde76894f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 24 Feb 2026 16:47:59 +0100 Subject: [PATCH 2/4] sysrepo: Do not report old errors This is a bug introduced in sysrepo 4.x --- ...add-support-for-running-in-foregroun.patch | 6 +++- ...NE-to-return-any-error-to-sysrepocfg.patch | 6 +++- ...3-Allow-to-copy-from-factory-default.patch | 7 ++-- ...sysrepoctl-to-install-factory-config.patch | 7 ++-- ...e-new-log-level-SEC-for-audit-trails.patch | 6 +++- ...ail-for-high-priority-system-changes.patch | 6 +++- ...sr_shmsub_listen_thread-exit-process.patch | 6 +++- .../4.2.10/0008-Cross-compile-fixes.patch | 7 ++-- ...kfifo-set-sysrepo-group-if-available.patch | 6 +++- ..._path-reporting-stale-libyang-errors.patch | 32 +++++++++++++++++++ 10 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 patches/sysrepo/4.2.10/0010-Fix-sr_lyd_new_path-reporting-stale-libyang-errors.patch diff --git a/patches/sysrepo/4.2.10/0001-sysrepo-plugind-add-support-for-running-in-foregroun.patch b/patches/sysrepo/4.2.10/0001-sysrepo-plugind-add-support-for-running-in-foregroun.patch index 251697fb2..de6f9661a 100644 --- a/patches/sysrepo/4.2.10/0001-sysrepo-plugind-add-support-for-running-in-foregroun.patch +++ b/patches/sysrepo/4.2.10/0001-sysrepo-plugind-add-support-for-running-in-foregroun.patch @@ -1,11 +1,15 @@ From efe7706fd7397c2feb384afea00ee97e74287df0 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 28 Mar 2023 10:37:53 +0200 -Subject: [PATCH 1/9] sysrepo-plugind: add support for running in foreground +Subject: [PATCH 01/10] sysrepo-plugind: add support for running in foreground with syslog +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/executables/sysrepo-plugind.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/patches/sysrepo/4.2.10/0002-Allow-SR_EV_DONE-to-return-any-error-to-sysrepocfg.patch b/patches/sysrepo/4.2.10/0002-Allow-SR_EV_DONE-to-return-any-error-to-sysrepocfg.patch index f09b75612..6ae9c2688 100644 --- a/patches/sysrepo/4.2.10/0002-Allow-SR_EV_DONE-to-return-any-error-to-sysrepocfg.patch +++ b/patches/sysrepo/4.2.10/0002-Allow-SR_EV_DONE-to-return-any-error-to-sysrepocfg.patch @@ -1,7 +1,10 @@ From 11b9938206cf2bafc456bb22e14c7f85a604760c Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Tue, 7 May 2024 15:41:53 +0200 -Subject: [PATCH 2/9] Allow SR_EV_DONE to return any error to sysrepocfg +Subject: [PATCH 02/10] Allow SR_EV_DONE to return any error to sysrepocfg +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires Importing a system configuration with sysrepocfg the model callbacks do @@ -17,6 +20,7 @@ This patch is a clumsy way of forcing the (first) error to bubble up to the surface and cause a non-zero exit code from sysrepocfg. Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/shm_sub.c | 40 +++++++++++++++++++++++++++++++--------- src/shm_sub.h | 2 +- diff --git a/patches/sysrepo/4.2.10/0003-Allow-to-copy-from-factory-default.patch b/patches/sysrepo/4.2.10/0003-Allow-to-copy-from-factory-default.patch index ccf526eb3..f0ff852a6 100644 --- a/patches/sysrepo/4.2.10/0003-Allow-to-copy-from-factory-default.patch +++ b/patches/sysrepo/4.2.10/0003-Allow-to-copy-from-factory-default.patch @@ -1,10 +1,13 @@ From 9e0267d4f20733b2a26df6d0ee0bc4019db8b13f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Wed, 8 May 2024 17:00:50 +0200 -Subject: [PATCH 3/9] Allow to copy from factory default +Subject: [PATCH 03/10] Allow to copy from factory default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires -Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/sysrepo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/patches/sysrepo/4.2.10/0004-Add-z-switch-to-sysrepoctl-to-install-factory-config.patch b/patches/sysrepo/4.2.10/0004-Add-z-switch-to-sysrepoctl-to-install-factory-config.patch index a2d0d547c..9c4bed159 100644 --- a/patches/sysrepo/4.2.10/0004-Add-z-switch-to-sysrepoctl-to-install-factory-config.patch +++ b/patches/sysrepo/4.2.10/0004-Add-z-switch-to-sysrepoctl-to-install-factory-config.patch @@ -1,13 +1,16 @@ From e0c899ba266b959544d7cc08c917cebba7ac91c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 6 May 2024 14:49:32 +0200 -Subject: [PATCH 4/9] Add -z switch to sysrepoctl to install factory config +Subject: [PATCH 04/10] Add -z switch to sysrepoctl to install factory config from a json file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires This to be able to load the yang modules during build time instead on boot. -Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/executables/sysrepoctl.c | 20 +++++++++++++-- src/lyd_mods.h | 7 ++++++ diff --git a/patches/sysrepo/4.2.10/0005-Introduce-new-log-level-SEC-for-audit-trails.patch b/patches/sysrepo/4.2.10/0005-Introduce-new-log-level-SEC-for-audit-trails.patch index 1884baf9b..949e962cd 100644 --- a/patches/sysrepo/4.2.10/0005-Introduce-new-log-level-SEC-for-audit-trails.patch +++ b/patches/sysrepo/4.2.10/0005-Introduce-new-log-level-SEC-for-audit-trails.patch @@ -1,7 +1,10 @@ From c7602dc8eabb941e0a163208aaf4de92dd5ef526 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 21 Aug 2024 16:00:35 +0200 -Subject: [PATCH 5/9] Introduce new log level [SEC] for audit trails +Subject: [PATCH 05/10] Introduce new log level [SEC] for audit trails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires This adds a new log level for security and audit trail related log @@ -19,6 +22,7 @@ system log daemon, dropping any [SEVERITY] prefix. Also, \n is most often dropped by log daemons. Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/log.c | 18 +++++++++++++++++- src/log.h | 1 + diff --git a/patches/sysrepo/4.2.10/0006-Add-audit-trail-for-high-priority-system-changes.patch b/patches/sysrepo/4.2.10/0006-Add-audit-trail-for-high-priority-system-changes.patch index 68ce67cb9..76255bd76 100644 --- a/patches/sysrepo/4.2.10/0006-Add-audit-trail-for-high-priority-system-changes.patch +++ b/patches/sysrepo/4.2.10/0006-Add-audit-trail-for-high-priority-system-changes.patch @@ -1,7 +1,10 @@ From a86dfdd4a5cb74c1f8c90c8d5aea6f5505c1b88c Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 21 Aug 2024 16:04:43 +0200 -Subject: [PATCH 6/9] Add audit trail for high priority system changes +Subject: [PATCH 06/10] Add audit trail for high priority system changes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires Committing a change to running, copying to a datastore, or calling an @@ -13,6 +16,7 @@ is when the system actually activates the changes. Copying to startup or other datastores is handled separately. Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/sysrepo.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/patches/sysrepo/4.2.10/0007-On-error-in-sr_shmsub_listen_thread-exit-process.patch b/patches/sysrepo/4.2.10/0007-On-error-in-sr_shmsub_listen_thread-exit-process.patch index c02449e69..c941de79c 100644 --- a/patches/sysrepo/4.2.10/0007-On-error-in-sr_shmsub_listen_thread-exit-process.patch +++ b/patches/sysrepo/4.2.10/0007-On-error-in-sr_shmsub_listen_thread-exit-process.patch @@ -1,7 +1,10 @@ From dbf08c67d8f17bdf98466b18fd72a230269e5d46 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Fri, 23 Aug 2024 12:22:06 +0200 -Subject: [PATCH 7/9] On error in sr_shmsub_listen_thread(), exit process +Subject: [PATCH 07/10] On error in sr_shmsub_listen_thread(), exit process +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires If processing callback events in, e.g., sysrepo-plugind, make sure to @@ -9,6 +12,7 @@ log the error and exit(1) the entire process so the system can decide to handle the problem. For example, restart all dependent services. Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/shm_sub.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/patches/sysrepo/4.2.10/0008-Cross-compile-fixes.patch b/patches/sysrepo/4.2.10/0008-Cross-compile-fixes.patch index 221b13f9b..87f0d085e 100644 --- a/patches/sysrepo/4.2.10/0008-Cross-compile-fixes.patch +++ b/patches/sysrepo/4.2.10/0008-Cross-compile-fixes.patch @@ -1,10 +1,13 @@ From 2549c966c090dd38a7a09907d27d13107d15aedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 16 Dec 2025 08:18:32 +0100 -Subject: [PATCH 8/9] Cross compile fixes +Subject: [PATCH 08/10] Cross compile fixes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires -Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- CMakeModules/SetupPrintedContext.cmake | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/patches/sysrepo/4.2.10/0009-sr_mkfifo-set-sysrepo-group-if-available.patch b/patches/sysrepo/4.2.10/0009-sr_mkfifo-set-sysrepo-group-if-available.patch index d75f9d57d..fb52d3303 100644 --- a/patches/sysrepo/4.2.10/0009-sr_mkfifo-set-sysrepo-group-if-available.patch +++ b/patches/sysrepo/4.2.10/0009-sr_mkfifo-set-sysrepo-group-if-available.patch @@ -1,13 +1,17 @@ From 78d62382bf9d665764844a0f686b27e42d73bea9 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 7 Jan 2026 18:09:32 +0100 -Subject: [PATCH 9/9] sr_mkfifo(): set sysrepo group if available +Subject: [PATCH 09/10] sr_mkfifo(): set sysrepo group if available +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit Organization: Wires We already set the umask, set the group to allow users of the sysrepo group to initiate events. Signed-off-by: Joachim Wiberg +Signed-off-by: Mattias Walström --- src/common.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/patches/sysrepo/4.2.10/0010-Fix-sr_lyd_new_path-reporting-stale-libyang-errors.patch b/patches/sysrepo/4.2.10/0010-Fix-sr_lyd_new_path-reporting-stale-libyang-errors.patch new file mode 100644 index 000000000..af2266faf --- /dev/null +++ b/patches/sysrepo/4.2.10/0010-Fix-sr_lyd_new_path-reporting-stale-libyang-errors.patch @@ -0,0 +1,32 @@ +From ab76b2dd926cd181838b555ef4e25712539aeabc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= +Date: Tue, 24 Feb 2026 16:45:35 +0100 +Subject: [PATCH 10/10] Fix sr_lyd_new_path() reporting stale libyang errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Organization: Wires + +Signed-off-by: Mattias Walström +--- + src/ly_wrap.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/ly_wrap.c b/src/ly_wrap.c +index 340b8b2a..465580e0 100644 +--- a/src/ly_wrap.c ++++ b/src/ly_wrap.c +@@ -610,6 +610,10 @@ sr_lyd_new_path(struct lyd_node *parent, const struct ly_ctx *ctx, const char *p + { + sr_error_info_t *err_info = NULL; + uint32_t temp_lo = LY_LOSTORE; ++ const struct ly_ctx *err_ctx = ctx ? ctx : LYD_CTX(parent); ++ ++ /* clear any stale errors so sr_errinfo_new_ly() only finds fresh ones */ ++ ly_err_clean((struct ly_ctx *)err_ctx, NULL); + + ly_temp_log_options(&temp_lo); + +-- +2.43.0 + From 6a6d14389bea3446cec79f5859c55149d957fd3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 24 Feb 2026 16:49:43 +0100 Subject: [PATCH 3/4] confd: ntp: Minor cleanup --- src/confd/src/ntp.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/confd/src/ntp.c b/src/confd/src/ntp.c index 82b98591b..2cf2465af 100644 --- a/src/confd/src/ntp.c +++ b/src/confd/src/ntp.c @@ -35,18 +35,11 @@ static int change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd return SR_ERR_OK; case SR_EV_DONE: - /* Check if NTP container exists (presence container) */ - if (!lydx_get_xpathf(config, XPATH_NTP_)) { - DEBUG("NTP server disabled, removing config"); - systemf("rm -f %s", NTP_CONF); - - return SR_ERR_OK; - } - /* Check if passed validation in previous event */ - if (!fexist(NTP_NEXT)) + if (!fexist(NTP_NEXT)) { + (void)remove(NTP_CONF); return SR_ERR_OK; - + } (void)remove(NTP_PREV); (void)rename(NTP_CONF, NTP_PREV); (void)rename(NTP_NEXT, NTP_CONF); From 4423bdbe3722c20271bea8593fa8661e8bae88d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 24 Feb 2026 21:38:25 +0100 Subject: [PATCH 4/4] yanger: Adapt to new stricter pattern for publish --- src/statd/python/yanger/infix_containers.py | 2 +- .../cli/show-routing-table_--ip_ipv4 | 18 ++-- .../cli/show-routing-table_--ip_ipv6 | 12 +-- test/case/statd/containers/ietf-routing.json | 30 +++--- .../statd/containers/infix-containers.json | 2 +- test/case/statd/containers/operational.json | 91 ++++++++++++++----- test/case/statd/containers/system/timestamp | 2 +- 7 files changed, 102 insertions(+), 55 deletions(-) diff --git a/src/statd/python/yanger/infix_containers.py b/src/statd/python/yanger/infix_containers.py index 9461e8ef8..bf0654160 100644 --- a/src/statd/python/yanger/infix_containers.py +++ b/src/statd/python/yanger/infix_containers.py @@ -48,7 +48,7 @@ def network(ps, inspect): if port["host_ip"]: addr = f"{port['host_ip']}:" - pub = f"{addr}{port['host_port']}->{port['container_port']}/{port['protocol']}" + pub = f"{addr}{port['host_port']}:{port['container_port']}/{port['protocol']}" net["publish"].append(pub) return net diff --git a/test/case/statd/containers/cli/show-routing-table_--ip_ipv4 b/test/case/statd/containers/cli/show-routing-table_--ip_ipv4 index 3b3926213..11b7eb2ad 100644 --- a/test/case/statd/containers/cli/show-routing-table_--ip_ipv4 +++ b/test/case/statd/containers/cli/show-routing-table_--ip_ipv4 @@ -1,12 +1,12 @@  DESTINATION PREF NEXT-HOP PROTO UPTIME ->* 0.0.0.0/0 110/2 10.1.1.100 ospfv2 16:03:51 - 0.0.0.0/0 254/0 br0 static 16:04:31 - 10.1.1.0/24 110/1 e6 ospfv2 16:04:45 ->* 10.1.1.0/24 0/0 e6 direct 16:04:45 - * 10.1.1.1/32 0/0 e4.8 direct 16:04:46 ->* 10.1.1.1/32 0/0 e3.8 direct 16:04:46 ->* 10.1.2.0/24 110/2 10.1.1.100 ospfv2 16:03:51 +>* 0.0.0.0/0 110/2 10.1.1.100 ospfv2 06:43:38 + 0.0.0.0/0 254/0 br0 static 06:44:18 + 10.1.1.0/24 110/1 e6 ospfv2 06:44:32 +>* 10.1.1.0/24 0/0 e6 direct 06:44:32 + * 10.1.1.1/32 0/0 e4.8 direct 06:44:33 +>* 10.1.1.1/32 0/0 e3.8 direct 06:44:33 +>* 10.1.2.0/24 110/2 10.1.1.100 ospfv2 06:43:38 * 10.1.2.1 ->* 10.1.3.0/24 110/2 10.1.1.100 ospfv2 16:03:51 +>* 10.1.3.0/24 110/2 10.1.1.100 ospfv2 06:43:38 * 10.1.3.1 ->* 169.254.0.0/16 0/0 br0 direct 16:04:40 +>* 169.254.0.0/16 0/0 br0 direct 06:44:27 diff --git a/test/case/statd/containers/cli/show-routing-table_--ip_ipv6 b/test/case/statd/containers/cli/show-routing-table_--ip_ipv6 index c4288d341..5fbc2fac4 100644 --- a/test/case/statd/containers/cli/show-routing-table_--ip_ipv6 +++ b/test/case/statd/containers/cli/show-routing-table_--ip_ipv6 @@ -1,7 +1,7 @@  DESTINATION PREF NEXT-HOP PROTO UPTIME - * fe80::/64 0/0 e6 direct 16:04:44 - * fe80::/64 0/0 br0 direct 16:04:45 - * fe80::/64 0/0 e2 direct 16:04:47 - * fe80::/64 0/0 e7 direct 16:05:37 - * fe80::/64 0/0 e5 direct 16:05:37 ->* fe80::/64 0/0 e1 direct 16:05:37 + * fe80::/64 0/0 e6 direct 06:44:31 + * fe80::/64 0/0 br0 direct 06:44:32 + * fe80::/64 0/0 e2 direct 06:44:34 + * fe80::/64 0/0 e7 direct 06:45:24 + * fe80::/64 0/0 e5 direct 06:45:24 +>* fe80::/64 0/0 e1 direct 06:45:24 diff --git a/test/case/statd/containers/ietf-routing.json b/test/case/statd/containers/ietf-routing.json index a0193f23c..a9fa2a5fe 100644 --- a/test/case/statd/containers/ietf-routing.json +++ b/test/case/statd/containers/ietf-routing.json @@ -18,7 +18,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -36,7 +36,7 @@ "ietf-ipv4-unicast-routing:destination-prefix": "0.0.0.0/0", "source-protocol": "static", "route-preference": 254, - "last-updated": "2025-02-11T19:55:29+00:00", + "last-updated": "2026-02-25T05:15:42+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -52,7 +52,7 @@ "source-protocol": "ietf-ospf:ospfv2", "route-preference": 110, "ietf-ospf:metric": 1, - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -70,7 +70,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -88,7 +88,7 @@ "ietf-ipv4-unicast-routing:destination-prefix": "10.1.1.1/32", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:55:14+00:00", + "last-updated": "2026-02-25T05:15:27+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -109,7 +109,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:55:14+00:00", + "last-updated": "2026-02-25T05:15:27+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -131,7 +131,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -159,7 +159,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -186,7 +186,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:55:20+00:00", + "last-updated": "2026-02-25T05:15:33+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -212,7 +212,7 @@ "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:55:16+00:00", + "last-updated": "2026-02-25T05:15:29+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -230,7 +230,7 @@ "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -248,7 +248,7 @@ "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:55:13+00:00", + "last-updated": "2026-02-25T05:15:26+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -266,7 +266,7 @@ "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -284,7 +284,7 @@ "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", "source-protocol": "direct", "route-preference": 0, - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -305,7 +305,7 @@ "active": [ null ], - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ diff --git a/test/case/statd/containers/infix-containers.json b/test/case/statd/containers/infix-containers.json index e025a635a..b9bd654d5 100644 --- a/test/case/statd/containers/infix-containers.json +++ b/test/case/statd/containers/infix-containers.json @@ -39,7 +39,7 @@ } ], "publish": [ - "34515->91/tcp" + "34515:91/tcp" ] } }, diff --git a/test/case/statd/containers/operational.json b/test/case/statd/containers/operational.json index 2489c43af..cfa06ffef 100644 --- a/test/case/statd/containers/operational.json +++ b/test/case/statd/containers/operational.json @@ -693,13 +693,21 @@ "ietf-ospf:interfaces": { "ietf-ospf:interface": [ { + "cost": 1, + "dead-interval": 40, "enabled": true, + "hello-interval": 10, + "hello-timer": 2, "ietf-ospf:neighbors": { "ietf-ospf:neighbor": [ { "address": "10.1.2.1", - "dead-timer": 22506, + "dead-timer": 22, + "infix-routing:interface-name": "e3.8:10.1.1.1", + "infix-routing:role": "DROther", + "infix-routing:uptime": 57, "neighbor-router-id": "10.1.2.1", + "priority": 1, "state": "full" } ] @@ -707,16 +715,28 @@ "interface-type": "point-to-point", "name": "e3.8", "passive": false, - "state": "point-to-point" + "priority": 1, + "retransmit-interval": 5, + "state": "point-to-point", + "transmit-delay": 1, + "wait-timer": 40 }, { + "cost": 1, + "dead-interval": 40, "enabled": true, + "hello-interval": 10, + "hello-timer": 2, "ietf-ospf:neighbors": { "ietf-ospf:neighbor": [ { "address": "10.1.3.1", - "dead-timer": 22334, + "dead-timer": 22, + "infix-routing:interface-name": "e4.8:10.1.1.1", + "infix-routing:role": "DROther", + "infix-routing:uptime": 57, "neighbor-router-id": "10.1.3.1", + "priority": 1, "state": "full" } ] @@ -724,22 +744,34 @@ "interface-type": "point-to-point", "name": "e4.8", "passive": false, - "state": "point-to-point" + "priority": 1, + "retransmit-interval": 5, + "state": "point-to-point", + "transmit-delay": 1, + "wait-timer": 40 }, { "bdr-ip-addr": "10.1.1.101", "bdr-router-id": "10.1.1.1", + "cost": 1, + "dead-interval": 40, "dr-ip-addr": "10.1.1.100", "dr-router-id": "192.168.100.1", "enabled": true, + "hello-interval": 10, + "hello-timer": 2, "ietf-ospf:neighbors": { "ietf-ospf:neighbor": [ { "address": "10.1.1.100", "bdr-router-id": "10.1.1.1", - "dead-timer": 31385, + "dead-timer": 31, "dr-router-id": "192.168.100.1", + "infix-routing:interface-name": "e6:10.1.1.101", + "infix-routing:role": "DR", + "infix-routing:uptime": 23, "neighbor-router-id": "192.168.100.1", + "priority": 1, "state": "full" } ] @@ -747,7 +779,11 @@ "interface-type": "broadcast", "name": "e6", "passive": false, - "state": "bdr" + "priority": 1, + "retransmit-interval": 5, + "state": "bdr", + "transmit-delay": 1, + "wait-timer": 40 } ] } @@ -757,6 +793,8 @@ "ietf-ospf:local-rib": { "ietf-ospf:route": [ { + "infix-routing:area-id": "0.0.0.1", + "metric": 2, "next-hops": { "next-hop": [ { @@ -768,6 +806,8 @@ "route-type": "inter-area" }, { + "infix-routing:area-id": "0.0.0.1", + "metric": 1, "next-hops": { "next-hop": [ { @@ -779,6 +819,8 @@ "route-type": "intra-area" }, { + "infix-routing:area-id": "0.0.0.1", + "metric": 2, "next-hops": { "next-hop": [ { @@ -793,6 +835,8 @@ "route-type": "intra-area" }, { + "infix-routing:area-id": "0.0.0.1", + "metric": 2, "next-hops": { "next-hop": [ { @@ -815,6 +859,9 @@ } ] }, + "interfaces": { + "interface": [] + }, "ribs": { "rib": [ { @@ -828,7 +875,7 @@ ], "ietf-ipv4-unicast-routing:destination-prefix": "0.0.0.0/0", "ietf-ospf:metric": 2, - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -846,7 +893,7 @@ }, { "ietf-ipv4-unicast-routing:destination-prefix": "0.0.0.0/0", - "last-updated": "2025-02-11T19:55:29+00:00", + "last-updated": "2026-02-25T05:15:42+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -862,7 +909,7 @@ { "ietf-ipv4-unicast-routing:destination-prefix": "10.1.1.0/24", "ietf-ospf:metric": 1, - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -880,7 +927,7 @@ null ], "ietf-ipv4-unicast-routing:destination-prefix": "10.1.1.0/24", - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -898,7 +945,7 @@ }, { "ietf-ipv4-unicast-routing:destination-prefix": "10.1.1.1/32", - "last-updated": "2025-02-11T19:55:14+00:00", + "last-updated": "2026-02-25T05:15:27+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -919,7 +966,7 @@ null ], "ietf-ipv4-unicast-routing:destination-prefix": "10.1.1.1/32", - "last-updated": "2025-02-11T19:55:14+00:00", + "last-updated": "2026-02-25T05:15:27+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -941,7 +988,7 @@ ], "ietf-ipv4-unicast-routing:destination-prefix": "10.1.2.0/24", "ietf-ospf:metric": 2, - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -969,7 +1016,7 @@ ], "ietf-ipv4-unicast-routing:destination-prefix": "10.1.3.0/24", "ietf-ospf:metric": 2, - "last-updated": "2025-02-11T19:56:09+00:00", + "last-updated": "2026-02-25T05:16:22+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -996,7 +1043,7 @@ null ], "ietf-ipv4-unicast-routing:destination-prefix": "169.254.0.0/16", - "last-updated": "2025-02-11T19:55:20+00:00", + "last-updated": "2026-02-25T05:15:33+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1022,7 +1069,7 @@ "route": [ { "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:55:16+00:00", + "last-updated": "2026-02-25T05:15:29+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1040,7 +1087,7 @@ }, { "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:55:15+00:00", + "last-updated": "2026-02-25T05:15:28+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1058,7 +1105,7 @@ }, { "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:55:13+00:00", + "last-updated": "2026-02-25T05:15:26+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1076,7 +1123,7 @@ }, { "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1094,7 +1141,7 @@ }, { "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1115,7 +1162,7 @@ null ], "ietf-ipv6-unicast-routing:destination-prefix": "fe80::/64", - "last-updated": "2025-02-11T19:54:23+00:00", + "last-updated": "2026-02-25T05:14:36+00:00", "next-hop": { "next-hop-list": { "next-hop": [ @@ -1175,7 +1222,7 @@ } ], "publish": [ - "34515->91/tcp" + "34515:91/tcp" ] }, "running": true, diff --git a/test/case/statd/containers/system/timestamp b/test/case/statd/containers/system/timestamp index ac8ff0a0d..ea11ae2c2 100644 --- a/test/case/statd/containers/system/timestamp +++ b/test/case/statd/containers/system/timestamp @@ -1,2 +1,2 @@ -1739303782 +1771996595