From 489487be16dad02d1d18943f63e791199b6e9a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Wed, 29 Oct 2025 22:03:52 +0100 Subject: [PATCH 1/7] test: syslog: Make syslog/remote test more robust --- test/case/ietf_syslog/remote/test.adoc | 3 +-- test/case/ietf_syslog/remote/test.py | 12 +++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/test/case/ietf_syslog/remote/test.adoc b/test/case/ietf_syslog/remote/test.adoc index c7b7069b3..602f78126 100644 --- a/test/case/ietf_syslog/remote/test.adoc +++ b/test/case/ietf_syslog/remote/test.adoc @@ -14,7 +14,6 @@ image::topology.svg[Remote syslog topology, align=center, scaledwidth=75%] . Set up topology and attach to client and server DUTs . Configure client DUT as syslog client with server DUT as remote, and configure server DUT as syslog server -. Send security:notice log message from client -. Verify reception of client log message, incl. sorting to /log/security on server +. Send security:notice log message from client and verify reception of client log message, incl. sorting to /log/security on server diff --git a/test/case/ietf_syslog/remote/test.py b/test/case/ietf_syslog/remote/test.py index c65a133bc..1ee695415 100755 --- a/test/case/ietf_syslog/remote/test.py +++ b/test/case/ietf_syslog/remote/test.py @@ -6,6 +6,11 @@ """ import infamy +def syslog_check(clientssh, serverssh): + clientssh.runsh("logger -t test -m client -p security.notice TestMessage") + return serverssh.runsh("tail -n10 /log/security |grep 'test - client - TestMessage'").returncode == 0 + + with infamy.Test() as test: with test.step("Set up topology and attach to client and server DUTs"): env = infamy.Env() @@ -142,11 +147,8 @@ } }) - with test.step("Send security:notice log message from client"): - clientssh.runsh("logger -t test -m client -p security.notice TestMessage") + with test.step("Send security:notice log message from client and verify reception of client log message, incl. sorting to /log/security on server"): + infamy.until(lambda: syslog_check(clientssh, serverssh) == True) - with test.step("Verify reception of client log message, incl. sorting to /log/security on server"): - infamy.until(lambda: serverssh.runsh( - "grep 'test - client - TestMessage' /log/security").returncode == 0) test.succeed() From 9aba65e14b989ba25313f65595b7560e1b5abfac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 28 Oct 2025 11:24:44 +0100 Subject: [PATCH 2/7] test: ntp: Make NTP tests more robust --- test/infamy/ntp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/infamy/ntp.py b/test/infamy/ntp.py index 4704189e5..03a599af9 100644 --- a/test/infamy/ntp.py +++ b/test/infamy/ntp.py @@ -10,7 +10,7 @@ def _get_ntp(target): if data is None: return None - return data["system-state"].get("infix-system:ntp", None) or data["system-state"].get("ntp", None) + return data.get("system-state", {}).get("infix-system:ntp", None) or data.get("system-state", {}).get("ntp", None) def _get_ntp_sources(target): From 021e864a6f2388a615a8190121f07b9edfe2a130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Sat, 25 Oct 2025 23:39:55 +0200 Subject: [PATCH 3/7] all.yaml: meta/bootorder.py needs to be run after ietf-system (where upgrade resides) To verify the bootorder is still valid after that part of the suite has run. --- test/case/all.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/case/all.yaml b/test/case/all.yaml index b3b025528..40fbbb75f 100644 --- a/test/case/all.yaml +++ b/test/case/all.yaml @@ -17,14 +17,15 @@ - name: Misc tests suite: misc/all.yaml + +- name: "IETF System" + suite: ietf_system/all.yaml + # Upgrade may leave wrong boot order - case: meta/bootorder.py infamy: specification: False -- name: "IETF System" - suite: ietf_system/all.yaml - - name: "IETF Syslog" suite: ietf_syslog/all.yaml From da297713989d8e467da1ebf3e23a9ee729e76ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Sat, 25 Oct 2025 23:40:59 +0200 Subject: [PATCH 4/7] confd: Refactor how sysrepo callbacks are handled Sysrepo only care about model changes, but we want the system configuration. Therefore add a common callback for all modules and handle dependencies between the modules, if someone should be run before another for example. --- src/confd/src/core.c | 222 ++++++++++++++++++++++---- src/confd/src/core.h | 52 +++--- src/confd/src/ietf-factory-default.c | 2 +- src/confd/src/ietf-hardware.c | 30 +--- src/confd/src/ietf-interfaces.c | 93 ++--------- src/confd/src/ietf-keystore.c | 189 +++++++++++++--------- src/confd/src/ietf-routing.c | 47 ++---- src/confd/src/ietf-syslog.c | 70 ++++---- src/confd/src/ietf-system.c | 128 ++++++++------- src/confd/src/infix-containers.c | 35 +--- src/confd/src/infix-dhcp-client.c | 26 +-- src/confd/src/infix-dhcp-server.c | 42 +++-- src/confd/src/infix-factory.c | 2 +- src/confd/src/infix-firewall.c | 46 +++--- src/confd/src/infix-meta.c | 15 +- src/confd/src/infix-services.c | 215 +++++++++---------------- src/confd/src/infix-system-software.c | 2 +- 17 files changed, 600 insertions(+), 616 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 719d62288..11f8d1adf 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: BSD-3-Clause */ +#include #include +#include #include "core.h" struct confd confd; @@ -75,21 +77,116 @@ int core_post_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *modul return SR_ERR_SYS; } - /* skip reload in bootstrap, implicit reload in runlevel change */ - if (systemf("runlevel >/dev/null 2>&1")) { - /* trigger any tasks waiting for confd to have applied *-config */ - system("initctl -nbq cond set bootstrap"); + + return SR_ERR_OK; +} + +static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, + const char *xpath, sr_event_t event, uint32_t request_id, void *_confd) +{ + struct lyd_node *diff = NULL, *config = NULL; + static uint32_t last_event = -1; + struct confd *confd = _confd; + static uint32_t last_id = 0; + confd_dependency_t result; + sr_data_t *cfg = NULL; + int rc = SR_ERR_OK; + + if (request_id == last_id && last_event == event) return SR_ERR_OK; + last_id = request_id; + last_event = event; + + if (event == SR_EV_CHANGE || event == SR_EV_DONE) { + rc = srx_get_diff(session, &diff); + if (rc != SR_ERR_OK) { + ERROR("Failed to get diff: %d", rc); + return rc; + } + rc = sr_get_data(session, "//.", 0, 0, 0, &cfg); + if (rc || !cfg) + goto free_diff; + + config = cfg->tree; +#if 0 + /* Debug: print diff to file */ + FILE *f = fopen("/tmp/confd-diff.json", "w"); + if (f) { + lyd_print_file(f, diff, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + fclose(f); + } +#endif } - if (systemf("initctl -b reload")) { - EMERG("initctl reload: failed applying new configuration!"); - return SR_ERR_SYS; - } + /* ietf-interfaces */ + if ((rc = ietf_interfaces_change(session, config, diff, event, confd))) + goto free_diff; - AUDIT("The new configuration has been applied."); + /* infix-dhcp-client*/ + if ((rc = infix_dhcp_client_change(session, config, diff, event, confd))) + goto free_diff; - return SR_ERR_OK; + /* ietf-keystore */ + if ((rc = ietf_keystore_change(session, config, diff, event, confd))) + goto free_diff; + + /* infix-services */ + if ((rc = infix_services_change(session, config, diff, event, confd))) + goto free_diff; + + /* ietf-syslog*/ + if ((rc = ietf_syslog_change(session, config, diff, event, confd))) + goto free_diff; + + /* ietf-system */ + if ((rc = ietf_system_change(session, config, diff, event, confd))) + goto free_diff; + + /* infix-containers */ + if ((rc = infix_containers_change(session, config, diff, event, confd))) + goto free_diff; + + /* ietf-hardware */ + if ((rc = ietf_hardware_change(session, config, diff, event, confd))) + goto free_diff; + + /* ietf-routing */ + if ((rc = ietf_routing_change(session, config, diff, event, confd))) + goto free_diff; + + /* infix-dhcp-server */ + if ((rc = infix_dhcp_server_change(session, config, diff, event, confd))) + goto free_diff; + + /* infix-firewall */ + if ((rc = infix_firewall_change(session, config, diff, event, confd))) + goto free_diff; + + if (cfg) + sr_release_data(cfg); + + if (event == SR_EV_DONE) { + /* skip reload in bootstrap, implicit reload in runlevel change */ + if (systemf("runlevel >/dev/null 2>&1")) { + /* trigger any tasks waiting for confd to have applied *-config */ + system("initctl -nbq cond set bootstrap"); + return SR_ERR_OK; + } + + if (systemf("initctl -b reload")) { + EMERG("initctl reload: failed applying new configuration!"); + return SR_ERR_SYS; + } + + AUDIT("The new configuration has been applied."); + } +free_diff: + lyd_free_tree(diff); + return rc; +} + +static 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); } int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) @@ -136,56 +233,119 @@ 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 = ietf_interfaces_init(&confd); - if (rc) + rc = subscribe_module("ietf-interfaces", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-interfaces"); goto err; - rc = ietf_keystore_init(&confd); - if (rc) + } + rc = subscribe_module("ietf-netconf-acm", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-netconf-acm"); goto err; - rc = ietf_syslog_init(&confd); - if (rc) + } + rc = subscribe_module("infix-dhcp-client", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to infix-dhcp-client"); goto err; - rc = ietf_system_init(&confd); - if (rc) + } + rc = subscribe_module("ietf-keystore", &confd, SR_SUBSCR_UPDATE); + if (rc) { + ERROR("Failed to subscribe to ietf-keystore"); goto err; - rc = infix_containers_init(&confd); - if (rc) + } + rc = subscribe_module("infix-services", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to infix-services"); + goto err; + } + rc = subscribe_module("ietf-system", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-system"); + goto err; + } + rc = subscribe_module("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); + if (rc) { + ERROR("Failed to subscribe to infix-containers"); + goto err; + } +#endif + rc = subscribe_module("infix-dhcp-server", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to infix-dhcp-server"); + goto err; + } + rc = subscribe_module("ietf-routing", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-routing"); + goto err; + } + rc = subscribe_module("ietf-hardware", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-hardware"); + goto err; + } + rc = subscribe_module("infix-firewall", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to infix-firewall"); + goto err; + } + rc = subscribe_module("infix-meta", &confd, SR_SUBSCR_UPDATE); + if (rc) { + ERROR("Failed to subscribe to infix-meta"); goto err; - rc = infix_dhcp_client_init(&confd); + } + + rc = ietf_system_rpc_init(&confd); if (rc) goto err; - rc = infix_dhcp_server_init(&confd); + rc = infix_containers_rpc_init(&confd); if (rc) goto err; - rc = infix_factory_init(&confd); + rc = infix_dhcp_server_rpc_init(&confd); if (rc) goto err; - rc = ietf_factory_default_init(&confd); + + rc = infix_factory_rpc_init(&confd); if (rc) goto err; - rc = ietf_routing_init(&confd); + + rc = ietf_factory_default_rpc_init(&confd); if (rc) goto err; - rc = infix_meta_init(&confd); + + rc = infix_firewall_rpc_init(&confd); if (rc) goto err; - rc = infix_system_sw_init(&confd); + + rc = infix_system_sw_rpc_init(&confd); if (rc) goto err; - rc = infix_services_init(&confd); + + /* Candidate infer configurations */ + rc = ietf_hardware_candidate_init(&confd); if (rc) goto err; - rc = ietf_hardware_init(&confd); + + rc = infix_firewall_candidate_init(&confd); if (rc) goto err; - rc = infix_firewall_init(&confd); + + rc = infix_dhcp_server_candidate_init(&confd); if (rc) goto err; + rc = infix_dhcp_client_candidate_init(&confd); + if (rc) + goto err; /* YOUR_INIT GOES HERE */ return SR_ERR_OK; - err: ERROR("init failed: %s", sr_strerror(rc)); if (confd.root) diff --git a/src/confd/src/core.h b/src/confd/src/core.h index 90595595c..d2289c340 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -133,6 +133,7 @@ uint32_t core_hook_prio (void); int core_pre_hook (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); int core_post_hook (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); int core_startup_save (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); +int core_wait_change (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) @@ -206,57 +207,70 @@ static inline int register_rpc(sr_session_ctx_t *session, const char *xpath, return rc; } + /* ietf-interfaces.c */ -int ietf_interfaces_init(struct confd *confd); +int ietf_interfaces_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); +int ietf_interfaces_cand_init(struct confd *confd); /* ietf-syslog.c */ -int ietf_syslog_init(struct confd *confd); +int ietf_syslog_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* ietf-system.c */ -int ietf_system_init (struct confd *confd); +int ietf_system_rpc_init (struct confd *confd); int hostnamefmt (struct confd *confd, const char *fmt, char *hostnm, size_t hostlen, char *domain, size_t domlen); +int ietf_system_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* infix-containers.c */ #ifdef CONTAINERS -int infix_containers_init(struct confd *confd); +int infix_containers_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); +int infix_containers_rpc_init(struct confd *confd); #else -static inline int infix_containers_init(struct confd *confd) { return 0; } +static inline int infix_containers_rpc_init(struct confd *confd) { return 0; } +static inline int infix_containers_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { return 0; } #endif /* infix-dhcp-common.c */ int dhcp_option_lookup(const struct lyd_node *id); /* infix-dhcp-client.c */ -int infix_dhcp_client_init(struct confd *confd); +int infix_dhcp_client_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); +int infix_dhcp_client_candidate_init(struct confd *confd); /* infix-dhcp-server.c */ -int infix_dhcp_server_init(struct confd *confd); - -/* ietf-factory-default */ -int ietf_factory_default_init(struct confd *confd); +int infix_dhcp_server_candidate_init(struct confd *confd); +int infix_dhcp_server_rpc_init(struct confd *confd); +int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* ietf-routing */ -int ietf_routing_init(struct confd *confd); +int ietf_routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* infix-factory.c */ -int infix_factory_init(struct confd *confd); +int infix_factory_rpc_init(struct confd *confd); -/* infix-factory.c */ -int infix_meta_init(struct confd *confd); +/* ietf-factory-default */ +int ietf_factory_default_rpc_init(struct confd *confd); + +/* infix-meta.c */ +int infix_meta_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* infix-system-software.c */ -int infix_system_sw_init(struct confd *confd); +int infix_system_sw_rpc_init(struct confd *confd); /* infix-services.c */ -int infix_services_init(struct confd *confd); +int infix_services_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* ietf-hardware.c */ -int ietf_hardware_init(struct confd *confd); +int ietf_hardware_candidate_init(struct confd *confd); +int ietf_hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* ietf-keystore.c */ -int ietf_keystore_init(struct confd *confd); +#define SSH_HOSTKEYS "/etc/ssh/hostkeys" +#define SSH_HOSTKEYS_NEXT SSH_HOSTKEYS"+" +int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); /* infix-firewall.c */ -int infix_firewall_init(struct confd *confd); +int infix_firewall_rpc_init(struct confd *confd); +int infix_firewall_candidate_init(struct confd *confd); +int infix_firewall_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd); #endif /* CONFD_CORE_H_ */ diff --git a/src/confd/src/ietf-factory-default.c b/src/confd/src/ietf-factory-default.c index 5fca3fe60..398419ea4 100644 --- a/src/confd/src/ietf-factory-default.c +++ b/src/confd/src/ietf-factory-default.c @@ -16,7 +16,7 @@ static int factory_reset(sr_session_ctx_t *session, uint32_t sub_id, const char return 0; } -int ietf_factory_default_init(struct confd *confd) +int ietf_factory_default_rpc_init(struct confd *confd) { int rc; diff --git a/src/confd/src/ietf-hardware.c b/src/confd/src/ietf-hardware.c index 371439549..1d0993ed4 100644 --- a/src/confd/src/ietf-hardware.c +++ b/src/confd/src/ietf-hardware.c @@ -183,26 +183,15 @@ static int hardware_cand(sr_session_ctx_t *session, uint32_t sub_id, const char return err; } -static int change_hardware(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *priv) +int ietf_hardware_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *diff, *difs = NULL, *dif = NULL, *cifs = NULL, *cif = NULL; - sr_data_t *cfg; + struct lyd_node *difs = NULL, *dif = NULL, *cifs = NULL, *cif = NULL; int rc = SR_ERR_OK; - struct confd *confd = (struct confd *)priv; - if (event != SR_EV_DONE) + if (event != SR_EV_DONE || !lydx_find_xpathf(diff, XPATH_BASE_)) return SR_ERR_OK; - rc = sr_get_data(session, XPATH_BASE_ "//.", 0, 0, 0, &cfg); - if (rc || !cfg) - goto err; - - rc = srx_get_diff(session, &diff); - if (rc) - goto err_release_data; - - cifs = lydx_get_descendant(cfg->tree, "hardware", "component", NULL); + cifs = lydx_get_descendant(config, "hardware", "component", NULL); difs = lydx_get_descendant(diff, "hardware", "component", NULL); LYX_LIST_FOR_EACH(difs, dif, "component") { @@ -216,7 +205,7 @@ static int change_hardware(sr_session_ctx_t *session, uint32_t sub_id, const cha if (op == LYDX_OP_DELETE) { if (usb_authorize(confd->root, name, 0)) { rc = SR_ERR_INTERNAL; - goto err_release_diff; + goto err;; } continue; } @@ -233,23 +222,18 @@ static int change_hardware(sr_session_ctx_t *session, uint32_t sub_id, const cha admin_state = lydx_get_cattr(state, "admin-state"); if (usb_authorize(confd->root, name, !strcmp(admin_state, "unlocked"))) { rc = SR_ERR_INTERNAL; - goto err_release_diff; + goto err;; } } } -err_release_diff: - lyd_free_tree(diff); -err_release_data: - sr_release_data(cfg); err: return rc; } -int ietf_hardware_init(struct confd *confd) +int ietf_hardware_candidate_init(struct confd *confd) { int rc = 0; - REGISTER_CHANGE(confd->session, "ietf-hardware", XPATH_BASE_, 0, change_hardware, confd, &confd->sub); REGISTER_CHANGE(confd->cand, "ietf-hardware", XPATH_BASE_, SR_SUBSCR_UPDATE, hardware_cand, confd, &confd->sub); diff --git a/src/confd/src/ietf-interfaces.c b/src/confd/src/ietf-interfaces.c index bd6e0df52..db10e3f71 100644 --- a/src/confd/src/ietf-interfaces.c +++ b/src/confd/src/ietf-interfaces.c @@ -787,12 +787,9 @@ static sr_error_t ifchange_post(sr_session_ctx_t *session, struct dagger *net, return err ? SR_ERR_INTERNAL : SR_ERR_OK; } -static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +int ietf_interfaces_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *diff, *cifs, *difs, *cif, *dif; - struct confd *confd = _confd; - sr_data_t *cfg; + struct lyd_node *cifs, *difs, *cif, *dif; sr_error_t err; switch (event) { @@ -814,19 +811,11 @@ static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *modu if (err) return err; - err = sr_get_data(session, "//.", 0, 0, 0, &cfg); - if (err || !cfg) - goto err_abandon; - - err = srx_get_diff(session, (struct lyd_node **)&diff); - if (err) - goto err_release_data; - - cifs = lydx_get_descendant(cfg->tree, "interfaces", "interface", NULL); + cifs = lydx_get_descendant(config, "interfaces", "interface", NULL); difs = lydx_get_descendant(diff, "interfaces", "interface", NULL); err = netdag_init(session, &confd->netdag, cifs, difs); if (err) - goto err_free_diff; + goto err_out; LYX_LIST_FOR_EACH(difs, dif, "interface") { LYX_LIST_FOR_EACH(cifs, cif, "interface") @@ -840,71 +829,9 @@ static int ifchange(sr_session_ctx_t *session, uint32_t sub_id, const char *modu } err = err ? : ifchange_post(session, &confd->netdag, cifs, difs); - -err_free_diff: - lyd_free_tree(diff); -err_release_data: - sr_release_data(cfg); -err_abandon: if (err) dagger_abandon(&confd->netdag); - - return err; -} - -static int keystorecb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) -{ - const struct lyd_node *diff; - const char *secret_name; - struct confd *confd = _confd; - struct lyd_node *interfaces, *interface, *dkeys, *dkey, *wifi; - sr_data_t *cfg = NULL; - int err = SR_ERR_OK; - - switch (event) { - case SR_EV_CHANGE: - break; - default: - return SR_ERR_OK; - } - - err = sr_get_data(session, "/interfaces/interface", 0, 0, 0, &cfg); - if (err || !cfg) - return err; - - diff = sr_get_change_diff(session); - if (!diff) - goto cleanup; - - interfaces = lydx_get_descendant(cfg->tree, "interfaces", "interface", NULL); - dkeys = lydx_get_descendant((struct lyd_node*) diff, "keystore", "symmetric-keys", "symmetric-key", NULL); - - LYX_LIST_FOR_EACH(dkeys, dkey, "symmetric-key") { - secret_name = lydx_get_cattr(dkey, "name"); - if (!secret_name) - continue; - - LYX_LIST_FOR_EACH(interfaces, interface, "interface") { - const char *name; - - if (iftype_from_iface(interface) != IFT_WIFI) - continue; - - wifi = lydx_get_child(interface, "wifi"); - if (!wifi) - continue; - - name = lydx_get_cattr(wifi, "secret"); - if (!name || strcmp(name, secret_name)) - continue; - wifi_gen(NULL, interface, &confd->netdag); - } - } - -cleanup: - if (cfg) - sr_release_data(cfg); +err_out: return err; } @@ -974,18 +901,16 @@ int ietf_interfaces_get_all_l3(const struct lyd_node *tree, char ***ifaces) return 0; } -int ietf_interfaces_init(struct confd *confd) +int ietf_interfaces_cand_init(struct confd *confd) { - int rc; + int rc = SR_ERR_OK; - REGISTER_CHANGE(confd->session, "ietf-interfaces", "/ietf-interfaces:interfaces//.", - SR_SUBSCR_CHANGE_ALL_MODULES, ifchange, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-keystore", "//*", - SR_SUBSCR_CHANGE_ALL_MODULES, keystorecb, confd, &confd->sub); REGISTER_CHANGE(confd->cand, "ietf-interfaces", "/ietf-interfaces:interfaces//.", SR_SUBSCR_UPDATE, ifchange_cand, confd, &confd->sub); return SR_ERR_OK; fail: ERROR("failed, error %d: %s", rc, sr_strerror(rc)); + return rc; + } diff --git a/src/confd/src/ietf-keystore.c b/src/confd/src/ietf-keystore.c index 2e1e38f78..a87303ee5 100644 --- a/src/confd/src/ietf-keystore.c +++ b/src/confd/src/ietf-keystore.c @@ -51,106 +51,141 @@ static char *filerd(const char *fn, size_t len) return buf; } -static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, - const char *xpath, sr_event_t event, uint32_t request_id, void *_) +int ietf_keystore_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - int rc = SR_ERR_INTERNAL; - sr_val_t *list = NULL; + struct lyd_node *changes, *change; + sr_val_t *list = NULL; + int rc = SR_ERR_OK; size_t count = 0; + if (diff && !lydx_find_xpathf(diff, XPATH_KEYSTORE_)) + return SR_ERR_OK; switch (event) { case SR_EV_UPDATE: - /* Check SSH (and NETCONF) default hostkey pair */ - break; - default: - return SR_ERR_OK; - } + 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) { + sr_val_t *entry = &list[i]; - 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; - 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; + } - 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) { + 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); - continue; + free(private_key_format); } + } + if (list) + sr_free_values(list, count); - 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; + break; + case SR_EV_CHANGE: + case SR_EV_ENABLED: + break; + case SR_EV_ABORT: + rmrf(SSH_HOSTKEYS_NEXT); + return SR_ERR_OK; + case SR_EV_DONE: + if(fexist(SSH_HOSTKEYS_NEXT)) { + if(rmrf(SSH_HOSTKEYS)) { + ERRNO("Failed to remove old SSH hostkeys: %d", errno); + } - 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; - } + if (rename(SSH_HOSTKEYS_NEXT, SSH_HOSTKEYS)) + ERRNO("Failed switching to new %s", SSH_HOSTKEYS); + } + return SR_ERR_OK; - priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); - if (!priv_key) - goto next; + default: + return SR_ERR_OK; + } - pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); - if (!pub_key) - goto next; + changes = lydx_get_descendant(config, "keystore", "asymmetric-keys", "asymmetric-key", NULL); - 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"); + LYX_LIST_FOR_EACH(changes, change, "asymmetric-key") { + const char *name, *private_key_type, *public_key_type; + const char *private_key, *public_key; - if (priv_key) - free(priv_key); + 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 (pub_key) - free(pub_key); + if (strcmp(private_key_type, "infix-crypto-types:rsa-private-key-format")) { + INFO("Private key %s is not of SSH type", name); + continue; + } - free(name); - } - free(public_key_format); - free(private_key_format); + if (strcmp(public_key_type, "infix-crypto-types:ssh-public-key-format")) { + INFO("Public key %s is not of SSH type", name); + continue; } - } - if (list) - sr_free_values(list, count); + 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; + } - return SR_ERR_OK; -} + if(systemf("/usr/libexec/infix/mksshkey %s %s %s %s", name, SSH_HOSTKEYS_NEXT, public_key, private_key)) + rc = SR_ERR_INTERNAL; + } -int ietf_keystore_init(struct confd *confd) -{ - int rc; - - REGISTER_CHANGE(confd->session, "ietf-keystore", "/ietf-keystore:keystore//.", - SR_SUBSCR_UPDATE, change_cb, confd, &confd->sub); - return SR_ERR_OK; -fail: - if(rc) - ERROR("%s failed: %s", __func__, sr_strerror(rc)); return rc; } diff --git a/src/confd/src/ietf-routing.c b/src/confd/src/ietf-routing.c index 9e0a6ae90..152ad9421 100644 --- a/src/confd/src/ietf-routing.c +++ b/src/confd/src/ietf-routing.c @@ -244,17 +244,18 @@ static int parse_static_routes(sr_session_ctx_t *session, struct lyd_node *paren return num_routes; } -static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *priv) +int ietf_routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { int staticd_enabled = 0, ospfd_enabled = 0, bfdd_enabled = 0; + struct lyd_node *cplane, *cplanes; bool ospfd_running, bfdd_running; - struct lyd_node *cplane, *tmp; bool restart_zebra = false; int rc = SR_ERR_OK; - sr_data_t *cfg; FILE *fp; + if (diff && !lydx_get_xpathf(diff, "/ietf-routing:routing")) + return SR_ERR_OK; + switch (event) { case SR_EV_ENABLED: /* first time, on register. */ case SR_EV_CHANGE: /* regular change (copy cand running) */ @@ -351,27 +352,18 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su return SR_ERR_OK; } - rc = sr_get_data(session, "/ietf-routing:routing/control-plane-protocols//.", 0, 0, 0, &cfg); - if (rc || !cfg) { - NOTE("No control-plane-protocols available."); - goto err_close; - } - - LY_LIST_FOR(lyd_child(cfg->tree), tmp) { - LY_LIST_FOR(lyd_child(tmp), cplane) { - const char *type; + cplanes = lydx_get_descendant(config, "routing", "control-plane-protocols", "control-plane-protocol", NULL); + LYX_LIST_FOR_EACH(cplanes, cplane, "control-plane-protocol") { + const char *type; - type = lydx_get_cattr(cplane, "type"); - if (!strcmp(type, "infix-routing:static")) { - staticd_enabled = parse_static_routes(session, lydx_get_child(cplane, "static-routes"), fp); - } else if (!strcmp(type, "infix-routing:ospfv2")) { - parse_ospf(session, lydx_get_child(cplane, "ospf")); - } + type = lydx_get_cattr(cplane, "type"); + if (!strcmp(type, "infix-routing:static")) { + staticd_enabled = parse_static_routes(session, lydx_get_child(cplane, "static-routes"), fp); + } else if (!strcmp(type, "infix-routing:ospfv2")) { + parse_ospf(session, lydx_get_child(cplane, "ospf")); } } - sr_release_data(cfg); -err_close: fclose(fp); if (!staticd_enabled) (void)remove(STATICD_CONF_NEXT); @@ -379,16 +371,3 @@ static int change_control_plane_protocols(sr_session_ctx_t *session, uint32_t su err_abandon: return rc; } - -int ietf_routing_init(struct confd *confd) -{ - int rc = 0; - - REGISTER_CHANGE(confd->session, "ietf-routing", "/ietf-routing:routing/control-plane-protocols", - 0, change_control_plane_protocols, confd, &confd->sub); - - return SR_ERR_OK; -fail: - ERROR("Init routing failed: %s", sr_strerror(rc)); - return rc; -} diff --git a/src/confd/src/ietf-syslog.c b/src/confd/src/ietf-syslog.c index 9e63437d7..46fec31e7 100644 --- a/src/confd/src/ietf-syslog.c +++ b/src/confd/src/ietf-syslog.c @@ -218,13 +218,12 @@ static const char *getnm(struct lyd_node *node, char *xpath, size_t len) return name; } -static int file_change(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 file_change(sr_session_ctx_t *session, struct lyd_node *config,struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *files, *file, *tree; int err; - if (SR_EV_DONE != event) + if (SR_EV_DONE != event || !lydx_get_xpathf(diff, XPATH_FILE_)) return SR_ERR_OK; err = srx_get_diff(session, &tree); @@ -253,21 +252,15 @@ static int file_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m return SR_ERR_OK; } -static int remote_change(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 remote_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *remotes, *remote, *tree; - int err; - - if (SR_EV_DONE != event) - return SR_ERR_OK; + struct lyd_node *dremotes, *remote; - err = srx_get_diff(session, &tree); - if (err) + if (SR_EV_DONE != event || !lydx_get_xpathf(diff, XPATH_REMOTE_)) return SR_ERR_OK; - remotes = lydx_get_descendant(tree, "syslog", "actions", "remote", "destination", NULL); - LYX_LIST_FOR_EACH(remotes, remote, "destination") { + dremotes = lydx_get_descendant(diff, "syslog", "actions", "remote", "destination", NULL); + LYX_LIST_FOR_EACH(dremotes, remote, "destination") { struct lyd_node *node = lydx_get_child(remote, "name"); enum lydx_op op = lydx_get_op(node); char path[512] = XPATH_REMOTE_; @@ -283,23 +276,22 @@ static int remote_change(sr_session_ctx_t *session, uint32_t sub_id, const char addr.address = srx_get_str(session, "%s/udp/address", path); srx_get_int(session, &addr.port, SR_UINT16_T, "%s/udp/port", path); - action(session, name, xpath, &addr); + action(session, name, path, &addr); } } - srx_free_changes(tree); systemf("initctl -nbq touch sysklogd"); return SR_ERR_OK; } -static int rotate_change(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 rotate_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { + char path[512] = XPATH_ROTATE_; char *sz, *cnt; FILE *fp; - if (SR_EV_DONE != event) + if (SR_EV_DONE != event || !lydx_get_xpathf(diff, XPATH_ROTATE_)) return SR_ERR_OK; fp = fopen(SYSLOG_ROTATE, "w"); @@ -308,13 +300,13 @@ static int rotate_change(sr_session_ctx_t *session, uint32_t sub_id, const char return SR_ERR_SYS; } - sz = srx_get_str(session, "%s/max-file-size", xpath); + sz = srx_get_str(session, "%s/max-file-size", path); if (sz) { fprintf(fp, "rotate_size %sk\n", sz); free(sz); } - cnt = srx_get_str(session, "%s/number-of-files", xpath); + cnt = srx_get_str(session, "%s/number-of-files", path); if (cnt) { fprintf(fp, "rotate_count %s\n", cnt); free(cnt); @@ -326,18 +318,18 @@ static int rotate_change(sr_session_ctx_t *session, uint32_t sub_id, const char return SR_ERR_OK; } -static int server_change(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 server_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { + char path[512] = XPATH_SERVER_; sr_val_t *list = NULL; size_t count; FILE *fp; - if (SR_EV_DONE != event) + if (SR_EV_DONE != event || !lydx_get_xpathf(diff, XPATH_SERVER_)) return SR_ERR_OK; - if (!srx_enabled(session, "%s/enabled", xpath)) { - if (remove(SYSLOG_SERVER)) + if (!srx_enabled(session, "%s/enabled", path)) { + if (erase(SYSLOG_SERVER)) ERRNO("failed disabling syslog server"); goto done; } @@ -351,7 +343,7 @@ static int server_change(sr_session_ctx_t *session, uint32_t sub_id, const char /* Allow listening on port 514, or custom listen below */ fprintf(fp, "secure_mode 0\n"); - if (!srx_get_items(session, &list, &count, "%s/listen/udp", xpath)) { + if (!srx_get_items(session, &list, &count, "%s/listen/udp", path)) { for (size_t i = 0; i < count; ++i) { sr_val_t *entry = &list[i]; char *address, *port; @@ -373,21 +365,17 @@ static int server_change(sr_session_ctx_t *session, uint32_t sub_id, const char return SR_ERR_OK; } - -int ietf_syslog_init(struct confd *confd) +int ietf_syslog_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - int rc = SR_ERR_SYS; - - if (!confd) - goto fail; - - REGISTER_CHANGE(confd->session, "ietf-syslog", XPATH_FILE_"//.", 0, file_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-syslog", XPATH_REMOTE_"//.", 0, remote_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-syslog", XPATH_ROTATE_"//.", 0, rotate_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-syslog", XPATH_SERVER_"//.", 0, server_change, confd, &confd->sub); + int rc = SR_ERR_OK; + if ((rc = file_change(session, config, diff, event, confd))) + return rc; + if ((rc = remote_change(session, config, diff, event, confd))) + return rc; + if ((rc = rotate_change(session, config, diff, event, confd))) + return rc; + if ((rc = server_change(session, config, diff, event, confd))) + return rc; return SR_ERR_OK; -fail: - ERROR("%s failed: %s", __func__, sr_strerror(rc)); - return rc; } diff --git a/src/confd/src/ietf-system.c b/src/confd/src/ietf-system.c index ccecd9d85..1a6b7eb57 100644 --- a/src/confd/src/ietf-system.c +++ b/src/confd/src/ietf-system.c @@ -21,12 +21,18 @@ #include "base64.h" #include "core.h" -#define NACM_BASE_ "/ietf-netconf-acm:nacm" -#define XPATH_BASE_ "/ietf-system:system" -#define XPATH_AUTH_ XPATH_BASE_"/authentication" -#define CLOCK_PATH_ "/ietf-system:system-state/clock" -#define PLATFORM_PATH_ "/ietf-system:system-state/platform" -#define PASSWORD_PATH "/ietf-system:system/authentication/user/password" +#define NACM_BASE_ "/ietf-netconf-acm:nacm" +#define XPATH_BASE_ "/ietf-system:system" +#define XPATH_AUTH_ XPATH_BASE_"/authentication" +#define XPATH_NTP_ XPATH_BASE_"/ntp" +#define XPATH_DNS_ XPATH_BASE_"/dns-resolver" +#define XPATH_HOSTNAME_ XPATH_BASE_"/hostname" +#define XPATH_MOTD_BANNER_ XPATH_BASE_"/infix-system:motd-banner" +#define XPATH_MOTD_ XPATH_BASE_"/infix-system:motd" +#define XPATH_EDITOR_ XPATH_BASE_"/infix-system:text-editor" +#define CLOCK_PATH_ "/ietf-system:system-state/clock" +#define PLATFORM_PATH_ "/ietf-system:system-state/platform" +#define PASSWORD_PATH "/ietf-system:system/authentication/user/password" #define _PATH_PASSWD "/etc/passwd" #define _PATH_HOSTNAME "/etc/hostname" @@ -210,12 +216,13 @@ static int sys_reload_services(void) #define TIMEZONE_PREV TIMEZONE_CONF "-" #define TIMEZONE_NEXT TIMEZONE_CONF "+" -static int change_clock(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 change_clock(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { char *tz_utc_offset, *timezone; int rc = SR_ERR_OK; + if (diff && !lydx_get_xpathf(diff, XPATH_BASE_"/clock")) + return SR_ERR_OK; switch (event) { case SR_EV_ENABLED: /* first time, on register. */ case SR_EV_CHANGE: /* regular change (copy cand running) */ @@ -280,8 +287,7 @@ static int change_clock(sr_session_ctx_t *session, uint32_t sub_id, const char * return rc; } -static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *_, sr_event_t event, unsigned request_id, void *priv) +static int change_ntp(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { sr_change_iter_t *iter = NULL; int rc, err = SR_ERR_OK; @@ -289,6 +295,8 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo sr_val_t *val; size_t cnt; + if (diff && !lydx_get_xpathf(diff, XPATH_NTP_)) + return SR_ERR_OK; switch (event) { case SR_EV_ENABLED: /* first time, on register. */ case SR_EV_CHANGE: /* regular change (copy cand running) */ @@ -299,7 +307,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return SR_ERR_OK; case SR_EV_DONE: - if (!srx_enabled(session, XPATH_BASE_"/ntp/enabled")) { + if (!srx_enabled(session, XPATH_NTP_"/enabled")) { systemf("rm -rf /etc/chrony/conf.d/* /etc/chrony/sources.d/*"); systemf("initctl -nbq disable chronyd"); return SR_ERR_OK; @@ -411,8 +419,7 @@ static int change_ntp(sr_session_ctx_t *session, uint32_t sub_id, const char *mo #define RESOLV_PREV RESOLV_CONF "-" #define RESOLV_NEXT RESOLV_CONF "+" -static int change_dns(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 change_dns(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { const char *fn = RESOLV_NEXT; int timeout = 0, attempts = 0; @@ -421,6 +428,9 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo size_t cnt; FILE *fp; + if (diff && !lydx_get_xpathf(diff, XPATH_DNS_)) + return SR_ERR_OK; + switch (event) { case SR_EV_ENABLED: /* first time, on register. */ case SR_EV_CHANGE: /* regular change (copy cand running) */ @@ -453,8 +463,8 @@ static int change_dns(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return SR_ERR_SYS; } - SRX_GET_UINT8(session, timeout, XPATH_BASE_"/dns-resolver/options/timeout"); - SRX_GET_UINT8(session, attempts, XPATH_BASE_"/dns-resolver/options/attempts"); + SRX_GET_UINT8(session, timeout, XPATH_DNS_"/options/timeout"); + SRX_GET_UINT8(session, attempts, XPATH_DNS_"/dns-resolver/options/attempts"); if (timeout || attempts) { fprintf(fp, "options"); if (timeout) @@ -1288,11 +1298,10 @@ static sr_error_t change_auth_done(struct confd *confd, sr_session_ctx_t *sessio return err; } -static int change_auth(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 change_auth(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct confd *confd = (struct confd *)priv; - + if (diff && !lydx_get_xpathf(diff, XPATH_AUTH_)) + return SR_ERR_OK; switch (event) { case SR_EV_UPDATE: return change_auth_ctp(confd, session); @@ -1307,14 +1316,13 @@ static int change_auth(sr_session_ctx_t *session, uint32_t sub_id, const char *m return SR_ERR_OK; } -static int change_nacm(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *_, sr_event_t event, unsigned request_id, void *priv) +static int change_nacm(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { sr_val_t *users = NULL; size_t user_count = 0; int rc; - if (event != SR_EV_DONE) + if (event != SR_EV_DONE ||!lydx_get_xpathf(diff, NACM_BASE_)) return SR_ERR_OK; /* Fetch all users from ietf-system */ @@ -1346,18 +1354,18 @@ static int change_nacm(sr_session_ctx_t *session, uint32_t sub_id, const char *m return 0; } -static int change_motd(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 change_motd(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { const char *fn = "/etc/motd"; char *message; int rc = 0; + /* Ignore all events except SR_EV_DONE */ - if (event != SR_EV_DONE) + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, XPATH_MOTD_)) return SR_ERR_OK; - message = srx_get_str(session, "%s", xpath); + message = srx_get_str(session, "%s", XPATH_MOTD_); if (message) { rc = writesf(message, "w", "%s", fn); free(message); @@ -1371,8 +1379,7 @@ static int change_motd(sr_session_ctx_t *session, uint32_t sub_id, const char *m return SR_ERR_OK; } -static int change_motd_banner(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 change_motd_banner(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { const char *fn = "/etc/motd"; unsigned char *raw; @@ -1380,24 +1387,24 @@ static int change_motd_banner(sr_session_ctx_t *session, uint32_t sub_id, const int rc = 0; /* Ignore all events except SR_EV_DONE */ - if (event != SR_EV_DONE) + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, XPATH_MOTD_BANNER_)) return SR_ERR_OK; - legacy = srx_get_str(session, "/ietf-system:system/infix-system:motd"); + legacy = srx_get_str(session, XPATH_MOTD_); if (legacy) { - NOTE("Legacy /system/motd exists, skipping %s", xpath); + NOTE("Legacy /system/motd exists, skipping %s", XPATH_MOTD_BANNER_); free(legacy); return SR_ERR_OK; } - raw = (unsigned char *)srx_get_str(session, "%s", xpath); + raw = (unsigned char *)srx_get_str(session, "%s", XPATH_BASE_"/infix-system:motd-banner"); if (raw) { unsigned char *txt; size_t txt_len; txt = base64_decode(raw, strlen((char *)raw), &txt_len); if (!txt) { - ERRNO("failed base64 decoding of %s", xpath); + ERRNO("failed base64 decoding of %s", XPATH_BASE_"/infix-system:motd-banner"); rc = -1; } else { FILE *fp = fopen(fn, "w"); @@ -1431,8 +1438,7 @@ static int change_motd_banner(sr_session_ctx_t *session, uint32_t sub_id, const return SR_ERR_OK; } -static int change_editor(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 change_editor(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { const char *alt = "/etc/alternatives/editor"; struct { const char *editor, *path; } map[] = { @@ -1444,10 +1450,10 @@ static int change_editor(sr_session_ctx_t *session, uint32_t sub_id, const char int rc = 0; /* Ignore all events except SR_EV_DONE */ - if (event != SR_EV_DONE) + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, XPATH_EDITOR_)) return SR_ERR_OK; - editor = srx_get_str(session, "%s", xpath); + editor = srx_get_str(session, "%s", XPATH_BASE_"/infix-system:text-editor"); if (!editor) return SR_ERR_OK; @@ -1550,20 +1556,18 @@ int hostnamefmt(struct confd *confd, const char *fmt, char *hostnm, size_t hostl return 0; } -static int change_hostname(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 change_hostname(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct confd *confd = (struct confd *)priv; const char *hostip = "127.0.1.1"; char hostnm[65], domain[65]; char buf[256], *fmt; FILE *nfp, *fp; int err, fd; - if (event != SR_EV_DONE) + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, XPATH_HOSTNAME_)) return SR_ERR_OK; - fmt = srx_get_str(session, "%s", xpath); + fmt = srx_get_str(session, "%s", XPATH_BASE_"/hostname"); if (!fmt) fmt = strdup(nm); @@ -1648,24 +1652,38 @@ static int change_hostname(sr_session_ctx_t *session, uint32_t sub_id, const cha return SR_ERR_OK; } -int ietf_system_init(struct confd *confd) + +int ietf_system_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) +{ + int rc = SR_ERR_OK; + if ((rc = change_auth(session, config, diff, event, confd))) + return rc; + if ((rc = change_ntp(session, config, diff, event, confd))) + return rc; + if ((rc = change_dns(session, config, diff, event, confd))) + return rc; + if ((rc = change_editor(session,config, diff, event, confd))) + return rc; + if ((rc = change_clock(session, config, diff, event, confd))) + return rc; + if ((rc = change_hostname(session, config, diff, event, confd))) + return rc; + if ((rc = change_motd(session, config, diff, event, confd))) + return rc; + if ((rc = change_motd_banner(session, config, diff, event, confd))) + return rc; + if ((rc = change_nacm(session, config, diff, event, confd))) /* Must be called after ietf_system_change_auth, which create the users */ + return rc; + + return SR_ERR_OK; +} + +int ietf_system_rpc_init(struct confd *confd) { int rc; os_init(); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_AUTH_, 0, change_auth, confd, &confd->sub); - REGISTER_MONITOR(confd->session, "ietf-netconf-acm", "/ietf-netconf-acm:nacm//.", - 0, change_nacm, confd, &confd->sub); - - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/hostname", 0, change_hostname, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/infix-system:motd", 0, change_motd, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/infix-system:motd-banner", 0, change_motd_banner, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/infix-system:text-editor", 0, change_editor, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/clock", 0, change_clock, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/ntp", 0, change_ntp, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ietf-system", XPATH_BASE_"/dns-resolver", 0, change_dns, confd, &confd->sub); - REGISTER_RPC(confd->session, "/ietf-system:system-restart", rpc_exec, "reboot", &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:system-shutdown", rpc_exec, "poweroff", &confd->sub); REGISTER_RPC(confd->session, "/ietf-system:set-current-datetime", rpc_set_datetime, NULL, &confd->sub); diff --git a/src/confd/src/infix-containers.c b/src/confd/src/infix-containers.c index 1c5799305..e73f325c0 100644 --- a/src/confd/src/infix-containers.c +++ b/src/confd/src/infix-containers.c @@ -349,23 +349,19 @@ static int del(const char *name) return SR_ERR_OK; } -static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +int infix_containers_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *diff, *cifs, *difs, *cif, *dif; + struct lyd_node *cifs, *difs, *cif, *dif; sr_error_t err = 0; - sr_data_t *cfg; + if (diff && !lydx_get_xpathf(diff, CFG_XPATH)) + return SR_ERR_OK; switch (event) { case SR_EV_DONE: break; case SR_EV_CHANGE: - err = sr_get_data(session, CFG_XPATH "//.", 0, 0, 0, &cfg); - if (err || !cfg) - return SR_ERR_INTERNAL; - - cifs = lydx_get_descendant(cfg->tree, "containers", "container", NULL); + cifs = lydx_get_descendant(config, "containers", "container", NULL); LYX_LIST_FOR_EACH(cifs, cif, "container") { struct lyd_node *mount; LYX_LIST_FOR_EACH(lyd_child(cif), mount, "mount") { @@ -379,13 +375,10 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module "Container '%s': mount '%s' source file '%s' is invalid: %s", lydx_get_cattr(cif, "name"), id, src, reason); sr_session_set_error_message(session, errmsg); - sr_release_data(cfg); return SR_ERR_VALIDATION_FAILED; } } } - - sr_release_data(cfg); return SR_ERR_OK; case SR_EV_ABORT: @@ -393,15 +386,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module return SR_ERR_OK; } - err = sr_get_data(session, CFG_XPATH "//.", 0, 0, 0, &cfg); - if (err || !cfg) - goto err_abandon; - - err = srx_get_diff(session, &diff); - if (err) - goto err_release_data; - - cifs = lydx_get_descendant(cfg->tree, "containers", "container", NULL); + cifs = lydx_get_descendant(config, "containers", "container", NULL); difs = lydx_get_descendant(diff, "containers", "container", NULL); /* find the modified one, delete or recreate only that */ @@ -422,11 +407,6 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module } } - lyd_free_tree(diff); -err_release_data: - sr_release_data(cfg); -err_abandon: - return err; } @@ -484,11 +464,10 @@ static int oci_load(sr_session_ctx_t *session, uint32_t sub_id, const char *xpat return SR_ERR_OK; } -int infix_containers_init(struct confd *confd) +int infix_containers_rpc_init(struct confd *confd) { int rc; - REGISTER_CHANGE(confd->session, MODULE, CFG_XPATH, 0, change, confd, &confd->sub); REGISTER_RPC(confd->session, CFG_XPATH "/container/start", action, NULL, &confd->sub); REGISTER_RPC(confd->session, CFG_XPATH "/container/stop", action, NULL, &confd->sub); REGISTER_RPC(confd->session, CFG_XPATH "/container/restart", action, NULL, &confd->sub); diff --git a/src/confd/src/infix-dhcp-client.c b/src/confd/src/infix-dhcp-client.c index a3f5be7a9..5310d6bfc 100644 --- a/src/confd/src/infix-dhcp-client.c +++ b/src/confd/src/infix-dhcp-client.c @@ -278,12 +278,10 @@ static void del(const char *ifname) systemf("initctl -bfq delete dhcp-client-%s", ifname); } -static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +int infix_dhcp_client_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *global, *diff, *cifs, *difs, *cif, *dif; + struct lyd_node *global, *cifs, *difs, *cif, *dif; sr_error_t err = 0; - sr_data_t *cfg; int ena = 0; switch (event) { @@ -295,18 +293,10 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module return SR_ERR_OK; } - err = sr_get_data(session, "//.", 0, 0, 0, &cfg); - if (err || !cfg) - goto err_abandon; - - err = srx_get_diff(session, &diff); - if (err) - goto err_release_data; - - global = lydx_get_descendant(cfg->tree, "dhcp-client", NULL); + global = lydx_get_descendant(config, "dhcp-client", NULL); ena = lydx_is_enabled(global, "enabled"); - cifs = lydx_get_descendant(cfg->tree, "dhcp-client", "client-if", NULL); + cifs = lydx_get_descendant(config, "dhcp-client", "client-if", NULL); difs = lydx_get_descendant(diff, "dhcp-client", "client-if", NULL); /* find the modified one, delete or recreate only that */ @@ -339,11 +329,6 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module } } - lyd_free_tree(diff); -err_release_data: - sr_release_data(cfg); -err_abandon: - return err; } @@ -421,11 +406,10 @@ static int cand(sr_session_ctx_t *session, uint32_t sub_id, const char *module, return SR_ERR_OK; } -int infix_dhcp_client_init(struct confd *confd) +int infix_dhcp_client_candidate_init(struct confd *confd) { int rc; - REGISTER_CHANGE(confd->session, MODULE, XPATH, 0, change, confd, &confd->sub); REGISTER_CHANGE(confd->cand, MODULE, XPATH"//.", SR_SUBSCR_UPDATE, cand, confd, &confd->sub); return SR_ERR_OK; diff --git a/src/confd/src/infix-dhcp-server.c b/src/confd/src/infix-dhcp-server.c index 2e921b92a..2a5431749 100644 --- a/src/confd/src/infix-dhcp-server.c +++ b/src/confd/src/infix-dhcp-server.c @@ -294,13 +294,14 @@ static void del(const char *subnet, struct lyd_node *cfg) ERRNO("Failed switching to new %s", DNSMASQ_LEASES); } -static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +int infix_dhcp_server_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { - struct lyd_node *global, *diff, *cifs, *difs, *cif, *dif; + struct lyd_node *global, *cifs, *difs, *cif, *dif; int enabled = 0, added = 0, deleted = 0; sr_error_t err = 0; - sr_data_t *cfg; + + if (!lydx_get_xpathf(diff, CFG_XPATH)) + return SR_ERR_OK; switch (event) { case SR_EV_DONE: @@ -311,18 +312,10 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module return SR_ERR_OK; } - err = sr_get_data(session, "//.", 0, 0, 0, &cfg); - if (err || !cfg) - goto err_abandon; - - err = srx_get_diff(session, &diff); - if (err) - goto err_release_data; - - global = lydx_get_descendant(cfg->tree, "dhcp-server", NULL); + global = lydx_get_descendant(config, "dhcp-server", NULL); enabled = lydx_is_enabled(global, "enabled"); - cifs = lydx_get_descendant(cfg->tree, "dhcp-server", "subnet", NULL); + cifs = lydx_get_descendant(config, "dhcp-server", "subnet", NULL); difs = lydx_get_descendant(diff, "dhcp-server", "subnet", NULL); /* find the modified one, delete or recreate only that */ @@ -356,7 +349,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module if (!fp) goto err_done; - node = lydx_get_xpathf(cfg->tree, "/ietf-system:system/hostname"); + node = lydx_get_xpathf(config, "/ietf-system:system/hostname"); if (node) { const char *hostname = lyd_get_value(node); const char *ptr = hostname ? strchr(hostname, '.') : NULL; @@ -385,11 +378,6 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module if (added || deleted) system("initctl -nbq touch dnsmasq"); - lyd_free_tree(diff); -err_release_data: - sr_release_data(cfg); -err_abandon: - return err; } @@ -461,12 +449,22 @@ static int clear_stats(sr_session_ctx_t *session, uint32_t sub_id, const char *x return SR_ERR_OK; } -int infix_dhcp_server_init(struct confd *confd) +int infix_dhcp_server_candidate_init(struct confd *confd) { int rc; - REGISTER_CHANGE(confd->session, MODULE, CFG_XPATH, 0, change, confd, &confd->sub); REGISTER_CHANGE(confd->cand, MODULE, CFG_XPATH "//.", SR_SUBSCR_UPDATE, cand, confd, &confd->sub); + + return SR_ERR_OK; +fail: + ERROR("init failed: %s", sr_strerror(rc)); + return rc; +} + +int infix_dhcp_server_rpc_init(struct confd *confd) +{ + int rc; + REGISTER_RPC(confd->session, CFG_XPATH "/statistics/clear", clear_stats, NULL, &confd->sub); return SR_ERR_OK; diff --git a/src/confd/src/infix-factory.c b/src/confd/src/infix-factory.c index c793a71f6..1c5645798 100644 --- a/src/confd/src/infix-factory.c +++ b/src/confd/src/infix-factory.c @@ -33,7 +33,7 @@ static int rpc(sr_session_ctx_t *session, uint32_t sub_id, const char *xpath, return rc; } -int infix_factory_init(struct confd *confd) +int infix_factory_rpc_init(struct confd *confd) { int rc; REGISTER_RPC(confd->session, "/infix-factory-default:factory-default", rpc, NULL, &confd->fsub); diff --git a/src/confd/src/infix-firewall.c b/src/confd/src/infix-firewall.c index ebdb45395..88086356d 100644 --- a/src/confd/src/infix-firewall.c +++ b/src/confd/src/infix-firewall.c @@ -477,16 +477,16 @@ static int infer_policy(sr_session_ctx_t *session, const char *name, const char } #endif -static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +int infix_firewall_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *tree, *global; struct lyd_node *clist, *cnode; - struct lyd_node *diff = NULL; sr_error_t err = SR_ERR_OK; - sr_data_t *cfg = NULL; char **ifaces = NULL; + if (diff && !lydx_get_xpathf(diff, XPATH)) + return SR_ERR_OK; + switch (event) { case SR_EV_CHANGE: /* Generate configuration to /etc/firewalld+ */ @@ -518,11 +518,7 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module return SR_ERR_OK; } - err = sr_get_data(session, "//.", 0, 0, 0, &cfg); - if (err || !cfg) - return SR_ERR_INTERNAL; - - tree = cfg->tree; + tree = config; global = lydx_get_descendant(tree, "firewall", NULL); /* Clean up any stale /etc/firewalld+ first */ @@ -540,13 +536,6 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module ifaces = NULL; } - err = srx_get_diff(session, &diff); - if (err) - goto done; - - if (!diff) - goto done; - /* Create /etc/firewalld+ directory structure */ if (fmkpath(0755, FIREWALLD_DIR_NEXT) || fmkpath(0755, FIREWALLD_ZONES_DIR) || @@ -642,12 +631,6 @@ static int change(sr_session_ctx_t *session, uint32_t sub_id, const char *module free(ifaces); } - if (diff) - lyd_free_tree(diff); - - if (cfg) - sr_release_data(cfg); - return err; } @@ -699,7 +682,7 @@ static int cand(sr_session_ctx_t *session, uint32_t sub_id, const char *module, #if INFER_POLICY /* Infer allow-host-ipv6 policy */ - rc = infer_policy(session, "allow-host-ipv6", + rc = infer_policy(session, "allow-host-ipv6", "Allows basic IPv6 functionality for the host.", "continue", any, host, icmp_types); if (rc) @@ -725,12 +708,10 @@ static int lockdown(sr_session_ctx_t *session, uint32_t sub_id, const char *xpat return SR_ERR_OK; } -int infix_firewall_init(struct confd *confd) +int infix_firewall_rpc_init(struct confd *confd) { int rc; - REGISTER_CHANGE(confd->session, MODULE, XPATH "//.", 0, change, confd, &confd->sub); - REGISTER_CHANGE(confd->cand, MODULE, XPATH "//.", SR_SUBSCR_UPDATE, cand, confd, &confd->sub); REGISTER_RPC(confd->session, XPATH "/lockdown-mode", lockdown, NULL, &confd->sub); return SR_ERR_OK; @@ -738,3 +719,16 @@ int infix_firewall_init(struct confd *confd) ERROR("init failed: %s", sr_strerror(rc)); return rc; } + + +int infix_firewall_candidate_init(struct confd *confd) +{ + int rc; + + REGISTER_CHANGE(confd->cand, MODULE, XPATH "//.", SR_SUBSCR_UPDATE, cand, confd, &confd->sub); + + return SR_ERR_OK; +fail: + ERROR("init failed: %s", sr_strerror(rc)); + return rc; +} diff --git a/src/confd/src/infix-meta.c b/src/confd/src/infix-meta.c index 2936fdc54..d460b82e3 100644 --- a/src/confd/src/infix-meta.c +++ b/src/confd/src/infix-meta.c @@ -18,23 +18,10 @@ static int set_version(sr_session_ctx_t *session) return SR_ERR_OK; } -static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *priv) +int infix_meta_change_cb(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { if (event == SR_EV_UPDATE) return set_version(session); return SR_ERR_OK; } - -int infix_meta_init(struct confd *confd) -{ - int rc; - - REGISTER_CHANGE(confd->session, "infix-meta", META_XPATH, SR_SUBSCR_UPDATE, - change_cb, confd, &confd->sub); - return SR_ERR_OK; -fail: - ERROR("%s(): failed. %s", __func__, sr_strerror(rc)); - return rc; -} diff --git a/src/confd/src/infix-services.c b/src/confd/src/infix-services.c index 001eba202..6a1d8f08c 100644 --- a/src/confd/src/infix-services.c +++ b/src/confd/src/infix-services.c @@ -19,9 +19,6 @@ #define GENERATE_ENUM(ENUM) ENUM, #define GENERATE_STRING(STRING) #STRING, -#define SSH_HOSTKEYS "/etc/ssh/hostkeys" -#define SSH_HOSTKEYS_NEXT SSH_HOSTKEYS"+" - #define LLDP_CONFIG "/etc/lldpd.d/confd.conf" #define LLDP_CONFIG_NEXT LLDP_CONFIG"+" @@ -39,7 +36,13 @@ #define SSHD_CONFIG_BASE SSH_BASE "/sshd_config.d" #define SSHD_CONFIG_LISTEN SSHD_CONFIG_BASE "/listen.conf" #define SSHD_CONFIG_HOSTKEY SSHD_CONFIG_BASE "/host-keys.conf" - +#define LLDP_XPATH "/ieee802-dot1ab-lldp:lldp" +#define SSH_XPATH "/infix-services:ssh" +#define MDNS_XPATH "/infix-services:mdns" +#define WEB_XPATH "/infix-services:web" +#define WEB_RESTCONF_XPATH WEB_XPATH"/restconf" +#define WEB_NETBROWSE_XPATH WEB_XPATH"/netbrowse" +#define WEB_CONSOLE_XPATH WEB_XPATH"/console" typedef enum { FOREACH_SVC(GENERATE_ENUM) } svc; @@ -184,13 +187,13 @@ static void svc_enadis(int ena, svc type, const char *svc) systemf("initctl -nbq touch avahi"); systemf("initctl -nbq touch nginx"); } - +/* TODO Handle in dependency tracking static int hostname_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, const char *xpath, sr_event_t event, unsigned request_id, void *_confd) { return mdns_records("update", all); } - +*/ static void fput_list(FILE *fp, struct lyd_node *cfg, const char *list, const char *heading) { const char *prefix = heading; @@ -279,14 +282,16 @@ static void mdns_cname(sr_session_ctx_t *session) svc_enadis(ena, none, "mdns-alias"); } -static int mdns_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int mdns_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *srv = NULL; sr_data_t *cfg; int ena; - cfg = get(session, event, xpath, &srv, "mdns", NULL); + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, MDNS_XPATH)) + return SR_ERR_OK; + + cfg = get(session, event, MDNS_XPATH, &srv, "mdns", NULL); if (!cfg) return SR_ERR_OK; @@ -305,20 +310,18 @@ static int mdns_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m return put(cfg); } -static int lldp_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int lldp_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *node = NULL; - sr_data_t *cfg; struct lyd_node *subnode; + if (diff && !lydx_get_xpathf(diff, LLDP_XPATH)) + return SR_ERR_OK; + switch (event) { case SR_EV_ENABLED: case SR_EV_CHANGE: - if (sr_get_data(session, xpath, 0, 0, 0, &cfg) || !cfg) - break; - - node = cfg->tree; + node = lydx_get_xpathf(config, LLDP_XPATH); if (lydx_is_enabled(node, "enabled")){ const char *tx_interval = lydx_get_cattr(node, "message-tx-interval"); FILE *fp = fopen(LLDP_CONFIG_NEXT, "w"); @@ -342,7 +345,7 @@ static int lldp_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m fclose(fp); } - return put(cfg); + return SR_ERR_OK; case SR_EV_DONE: if (fexist(LLDP_CONFIG_NEXT)){ @@ -356,7 +359,7 @@ static int lldp_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m if (erase(LLDP_CONFIG)) ERRNO("Failed to remove old %s", LLDP_CONFIG); - svc_change(session, event, xpath, "lldp", "lldpd"); + svc_change(session, event, LLDP_XPATH, "lldp", "lldpd"); break; case SR_EV_ABORT: @@ -370,13 +373,15 @@ static int lldp_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m return SR_ERR_OK; } -static int ttyd_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int ttyd_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *srv = NULL; sr_data_t *cfg; - cfg = get(session, event, xpath, &srv, "web", "console", NULL); + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, WEB_CONSOLE_XPATH)) + return SR_ERR_OK; + + cfg = get(session, event, WEB_XPATH, &srv, "web", "console", NULL); if (!cfg) return SR_ERR_OK; @@ -385,13 +390,15 @@ static int ttyd_change(sr_session_ctx_t *session, uint32_t sub_id, const char *m return put(cfg); } -static int netbrowse_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int netbrowse_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *srv = NULL; sr_data_t *cfg; - cfg = get(session, event, xpath, &srv, "web", "netbrowse", NULL); + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, WEB_NETBROWSE_XPATH)) + return SR_ERR_OK; + + cfg = get(session, event, WEB_XPATH, &srv, "web", "netbrowse", NULL); if (!cfg) return SR_ERR_OK; @@ -401,13 +408,19 @@ static int netbrowse_change(sr_session_ctx_t *session, uint32_t sub_id, const ch return put(cfg); } -static int restconf_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int restconf_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *srv = NULL; sr_data_t *cfg; + char *out; + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, WEB_RESTCONF_XPATH)) + return SR_ERR_OK; - cfg = get(session, event, xpath, &srv, "web", "restconf", NULL); + ERROR("RESTCONF CHANGES DETECTED"); + lyd_print_mem(&out, diff, LYD_JSON, + LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL); + ERROR("%s", out); + cfg = get(session, event, WEB_XPATH, &srv, "web", "restconf", NULL); if (!cfg) return SR_ERR_OK; @@ -416,17 +429,18 @@ static int restconf_change(sr_session_ctx_t *session, uint32_t sub_id, const cha return put(cfg); } -static int ssh_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) +static int ssh_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *ssh = NULL, *listen, *host_key; sr_error_t rc = SR_ERR_OK; - sr_data_t *cfg; FILE *fp; + if (diff && !lydx_get_xpathf(diff, SSH_XPATH)) + return SR_ERR_OK; + switch (event) { case SR_EV_DONE: - return svc_change(session, event, xpath, "ssh", "sshd"); + return svc_change(session, event, SSH_XPATH, "ssh", "sshd"); case SR_EV_ENABLED: case SR_EV_CHANGE: break; @@ -436,10 +450,7 @@ static int ssh_change(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return SR_ERR_OK; } - if (sr_get_data(session, xpath, 0, 0, 0, &cfg) || !cfg) { - return SR_ERR_OK; - } - ssh = cfg->tree; + ssh = lydx_get_xpathf(config, SSH_XPATH); if (!lydx_is_enabled(ssh, "enabled")) { goto out; @@ -479,27 +490,29 @@ static int ssh_change(sr_session_ctx_t *session, uint32_t sub_id, const char *mo fclose(fp); out: - sr_release_data(cfg); return rc; } -static int web_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) + +static int web_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { struct lyd_node *srv = NULL; sr_data_t *cfg; int ena; - cfg = get(session, event, xpath, &srv, "web", NULL); + if (event != SR_EV_DONE || !lydx_get_xpathf(diff, WEB_XPATH)) + return SR_ERR_OK; + + cfg = get(session, event, WEB_XPATH, &srv, "web", NULL); if (!cfg) return SR_ERR_OK; ena = lydx_is_enabled(srv, "enabled"); if (ena) { - svc_enadis(srx_enabled(session, "%s/console/enabled", xpath), ttyd, "ttyd"); - svc_enadis(srx_enabled(session, "%s/netbrowse/enabled", xpath), netbrowse, "netbrowse"); - svc_enadis(srx_enabled(session, "%s/restconf/enabled", xpath), restconf, "restconf"); + svc_enadis(srx_enabled(session, "%s/enabled", WEB_CONSOLE_XPATH), ttyd, "ttyd"); + svc_enadis(srx_enabled(session, "%s/enabled", WEB_NETBROWSE_XPATH), netbrowse, "netbrowse"); + svc_enadis(srx_enabled(session, "%s/enabled", WEB_RESTCONF_XPATH), restconf, "restconf"); } else { svc_enadis(0, ttyd, NULL); svc_enadis(0, netbrowse, NULL); @@ -512,104 +525,30 @@ static int web_change(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return put(cfg); } -/* Store SSH public/private keys */ -static int change_keystore_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, - const char *xpath, sr_event_t event, uint32_t request_id, void *_) -{ - int rc = SR_ERR_OK; - sr_data_t *cfg; - struct lyd_node *changes, *change; - - switch (event) { - case SR_EV_CHANGE: - case SR_EV_ENABLED: - break; - case SR_EV_ABORT: - rmrf(SSH_HOSTKEYS_NEXT); - return SR_ERR_OK; - case SR_EV_DONE: - 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); - - svc_change(session, event, "/infix-services:ssh", "ssh", "sshd"); - } - return SR_ERR_OK; - - default: - return SR_ERR_OK; - } - - if (sr_get_data(session, "/ietf-keystore:keystore/asymmetric-keys//.", 0, 0, 0, &cfg) || !cfg) { - return SR_ERR_OK; - } - changes = lydx_get_descendant(cfg->tree, "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; - - 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); - continue; - } - - if (strcmp(public_key_type, "infix-crypto-types:ssh-public-key-format")) { - INFO("Public key %s is not of SSH type", name); - 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; - } - - sr_release_data(cfg); - - return rc; -} - -int infix_services_init(struct confd *confd) +int infix_services_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { int rc; - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:mdns", - 0, mdns_change, confd, &confd->sub); - REGISTER_MONITOR(confd->session, "ietf-system", "/ietf-system:system/hostname", - 0, hostname_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:ssh", - 0, ssh_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:web", - 0, web_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:web/infix-services:console", - 0, ttyd_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:web/infix-services:netbrowse", - 0, netbrowse_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "infix-services", "/infix-services:web/infix-services:restconf", - 0, restconf_change, confd, &confd->sub); - REGISTER_CHANGE(confd->session, "ieee802-dot1ab-lldp", "/ieee802-dot1ab-lldp:lldp", - 0, lldp_change, confd, &confd->sub); - - /* Store SSH keys */ - REGISTER_CHANGE(confd->session, "ietf-keystore", "/ietf-keystore:keystore//.", - 0, change_keystore_cb, confd, &confd->sub); - + rc = lldp_change(session, config, diff, event, confd); + if (rc) + return rc; + rc = mdns_change(session, config, diff, event, confd); /* TODO: Depends on hostname changes */ + if (rc) + return rc; + rc = ssh_change(session, config, diff, event, confd); /* TODO: Depends on keystore changes*/ + if (rc) + return rc; + rc = web_change(session, config, diff, event, confd); + if (rc) + return rc; + rc = ttyd_change(session, config, diff, event, confd); + if (rc) + return rc; + rc = restconf_change(session, config, diff, event, confd); + if (rc) + return rc; + rc = netbrowse_change(session, config, diff, event, confd); + if (rc) + return rc; return SR_ERR_OK; -fail: - ERROR("init failed: %s", sr_strerror(rc)); - return rc; } diff --git a/src/confd/src/infix-system-software.c b/src/confd/src/infix-system-software.c index c9427d089..783121aee 100644 --- a/src/confd/src/infix-system-software.c +++ b/src/confd/src/infix-system-software.c @@ -89,7 +89,7 @@ static int infix_system_sw_set_boot_order(sr_session_ctx_t *session, uint32_t su return SR_ERR_OK; } -int infix_system_sw_init(struct confd *confd) +int infix_system_sw_rpc_init(struct confd *confd) { int rc = 0; From 5cdcf1f4fe4c1e05f52a9f70554337979ec56e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 27 Oct 2025 20:36:39 +0100 Subject: [PATCH 5/7] confd: Add support for dependency tracking between modules Sysrepo lack the functionallity for if change in model A also should demand actions of model B. Previous we have handled this by having callbacks for keystore changes in for example infix-services to be able to reconfigure SSH on asymmetric key changes. This commit instead add a pass where dependencies are found and added to the diff. --- src/confd/src/core.c | 131 +++++++++++++++++++++++++++++++++ src/confd/src/core.h | 6 ++ src/confd/src/infix-services.c | 8 +- 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 11f8d1adf..501f38d61 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -81,6 +81,125 @@ int core_post_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *modul return SR_ERR_OK; } +static confd_dependency_t add_dependencies(struct lyd_node **diff, const char *xpath, const char *value) +{ + 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)) { + /* 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) { + ERROR("lyd_new_path failed with rc=%d", rc); + return CONFD_DEP_ERROR; + } + + root = new_node; + while (root->parent) + root = lyd_parent(root); + + rc = lyd_merge_siblings(diff, root, LYD_MERGE_DESTRUCT); + if (rc != LY_SUCCESS) { + ERROR("lyd_merge_siblings failed with rc=%d", rc); + lyd_free_tree(root); + return CONFD_DEP_ERROR; + } + + target = lydx_get_xpathf(*diff, "%s", xpath); + if (target) { + lyd_new_meta(LYD_CTX(target), target, NULL, + "yang:operation", "replace", false, NULL); + } else { + return CONFD_DEP_ERROR; + } + + return CONFD_DEP_ADDED; + } + + return CONFD_DEP_DONE; +} + +static confd_dependency_t handle_dependencies(struct lyd_node **diff, struct lyd_node *config) +{ + struct lyd_node *dkeys, *dkey, *hostname; + confd_dependency_t result = CONFD_DEP_DONE; + const char *key_name; + + dkeys = lydx_get_descendant(*diff, "keystore", "symmetric-keys", "symmetric-key", NULL); + + LYX_LIST_FOR_EACH(dkeys, dkey, "symmetric-key") { + struct ly_set *ifaces; + uint32_t i; + + key_name = lydx_get_cattr(dkey, "name"); + ifaces = lydx_find_xpathf(config, "/ietf-interfaces:interfaces/interface[infix-interfaces:wifi/secret='%s']", key_name); + if (ifaces && ifaces->count > 0) { + for (i = 0; i < ifaces->count; i++) { + struct lyd_node *iface = ifaces->dnodes[i]; + const char *ifname; + char xpath[256]; + ifname = lydx_get_cattr(iface, "name"); + snprintf(xpath, sizeof(xpath), "/ietf-interfaces:interfaces/interface[name='%s']/infix-interfaces:wifi/secret", ifname); + result = add_dependencies(diff, xpath, key_name); + if (result == CONFD_DEP_ERROR) { + ERROR("Failed to add wifi node to diff for interface %s", ifname); + ly_set_free(ifaces, NULL); + return result; + } + } + ly_set_free(ifaces, NULL); + } + } + + dkeys = lydx_get_descendant(*diff, "keystore", "asymmetric-keys", "asymmetric-key", NULL); + LYX_LIST_FOR_EACH(dkeys, dkey, "asymmetric-key") { + struct ly_set *hostkeys; + uint32_t i; + + key_name = lydx_get_cattr(dkey, "name"); + hostkeys = lydx_find_xpathf(config, "/infix-services:ssh/hostkey[.='%s']", key_name); + if (hostkeys && hostkeys->count > 0) { + for (i = 0; i < hostkeys->count; i++) { + char xpath[256]; + snprintf(xpath, sizeof(xpath), "/infix-services:ssh/hostkey[.='%s']", key_name); + result = add_dependencies(diff, xpath, key_name); + if (result == CONFD_DEP_ERROR) { + ERROR("Failed to add ssh hostkey to diff for key %s", key_name); + ly_set_free(hostkeys, NULL); + return result; + } + } + ly_set_free(hostkeys, NULL); + } + } + + hostname = lydx_get_xpathf(*diff, "/ietf-system:system/hostname"); + if (hostname) { + struct lyd_node *mdns, *dhcp_server; + + dhcp_server = lydx_get_xpathf(config, "/infix-dhcp-server:dhcp-server/enabled"); + if(dhcp_server && lydx_is_enabled(dhcp_server, "enabled")) { + result = add_dependencies(diff, "/infix-dhcp-server:dhcp-server/enabled", "true"); + if (result == CONFD_DEP_ERROR) { + ERROR("Failed to add dhcp-server to diff on hostname change"); + return result; + } + } + mdns = lydx_get_xpathf(config, "/infix-services:mdns"); + if (mdns && lydx_is_enabled(mdns, "enabled")) { + result = add_dependencies(diff, "/infix-services:mdns/enabled", "true"); + if (result == CONFD_DEP_ERROR) { + ERROR("Failed to add mdns to diff on hostname change"); + return result; + } + } + } + + return result; +} + static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *module_name, const char *xpath, sr_event_t event, uint32_t request_id, void *_confd) { @@ -91,6 +210,7 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod confd_dependency_t result; sr_data_t *cfg = NULL; int rc = SR_ERR_OK; + int max_dep = 10; if (request_id == last_id && last_event == event) return SR_ERR_OK; @@ -108,6 +228,17 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod goto free_diff; config = cfg->tree; + while ((result = handle_dependencies(&diff, config)) != CONFD_DEP_DONE) { + if (max_dep == 0) { + ERROR("Max dependency depth reached"); + return SR_ERR_INTERNAL; + } + if (result == CONFD_DEP_ERROR) { + ERROR("Failed to add dependencies"); + return SR_ERR_INTERNAL; + } + max_dep--; + } #if 0 /* Debug: print diff to file */ FILE *f = fopen("/tmp/confd-diff.json", "w"); diff --git a/src/confd/src/core.h b/src/confd/src/core.h index d2289c340..8d0983427 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -100,6 +101,11 @@ static inline char *xpath_base(const char *xpath) return path; } +typedef enum { + CONFD_DEP_DONE = 0, + CONFD_DEP_ADDED = 1, + CONFD_DEP_ERROR = 2 +} confd_dependency_t; #define REGISTER_CHANGE(s,m,x,f,c,a,u) \ if ((rc = register_change(s, m, x, f, c, a, u))) \ diff --git a/src/confd/src/infix-services.c b/src/confd/src/infix-services.c index 6a1d8f08c..1502195ae 100644 --- a/src/confd/src/infix-services.c +++ b/src/confd/src/infix-services.c @@ -187,13 +187,7 @@ static void svc_enadis(int ena, svc type, const char *svc) systemf("initctl -nbq touch avahi"); systemf("initctl -nbq touch nginx"); } -/* TODO Handle in dependency tracking -static int hostname_change(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *_confd) -{ - return mdns_records("update", all); -} -*/ + static void fput_list(FILE *fp, struct lyd_node *cfg, const char *list, const char *heading) { const char *prefix = heading; From 98b30d7d45fda21a5c8fd88e2d0b67c6e8f4cace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Tue, 28 Oct 2025 14:55:29 +0100 Subject: [PATCH 6/7] confd: Remove core hooks Not needed anymore, the configuration change is sequential in change_cb. --- src/confd/src/core.c | 82 +++++++++----------------------------------- src/confd/src/core.h | 32 +---------------- 2 files changed, 17 insertions(+), 97 deletions(-) diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 501f38d61..8ba0ba985 100644 --- a/src/confd/src/core.c +++ b/src/confd/src/core.c @@ -8,16 +8,16 @@ struct confd confd; -uint32_t core_hook_prio(void) -{ - static uint32_t hook_prio = CB_PRIO_PASSIVE; - - return hook_prio--; -} - 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) { + 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; @@ -28,59 +28,6 @@ int core_startup_save(sr_session_ctx_t *session, uint32_t sub_id, const char *mo return SR_ERR_OK; } -static const char *ev2str(sr_event_t ev) -{ - switch (ev) { - case SR_EV_UPDATE: return "UPDATE"; - case SR_EV_CHANGE: return "CHANGE"; - case SR_EV_DONE: return "DONE"; - case SR_EV_ABORT: return "ABORT"; - case SR_EV_ENABLED: return "ENABLED"; - case SR_EV_RPC: return "ABORT"; - default: - break; - } - - return "UNKNOWN"; -} - -int core_pre_hook(sr_session_ctx_t *session, uint32_t sub_id, const char *module, - const char *xpath, sr_event_t event, unsigned request_id, void *priv) -{ - return 0; -} - -/* - * Run on UPDATE to see how many modules have changes in the inbound changeset - * Run on DONE, after the last module callback has run, to activate changes. - * For details, see https://github.com/sysrepo/sysrepo/issues/2188 - */ -int core_post_hook(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 size_t num_changes = 0; - - switch (event) { - case SR_EV_CHANGE: - num_changes++; - return SR_ERR_OK; - case SR_EV_ABORT: - num_changes = 0; - return SR_ERR_OK; - case SR_EV_DONE: - num_changes--; - if (num_changes > 0) - return SR_ERR_OK; - break; - default: - ERROR("core_post_hook() should not be called with event %s", ev2str(event)); - return SR_ERR_SYS; - } - - - return SR_ERR_OK; -} - static confd_dependency_t add_dependencies(struct lyd_node **diff, const char *xpath, const char *value) { struct lyd_node *new_node = NULL; @@ -204,17 +151,17 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod const char *xpath, sr_event_t event, uint32_t request_id, void *_confd) { struct lyd_node *diff = NULL, *config = NULL; - static uint32_t last_event = -1; + static sr_event_t last_event = -1; struct confd *confd = _confd; - static uint32_t last_id = 0; + static uint32_t last_request = 0; confd_dependency_t result; sr_data_t *cfg = NULL; int rc = SR_ERR_OK; int max_dep = 10; - if (request_id == last_id && last_event == event) + if (request_id == last_request && last_event == event) return SR_ERR_OK; - last_id = request_id; + last_request = request_id; last_event = event; if (event == SR_EV_CHANGE || event == SR_EV_DONE) { @@ -316,8 +263,11 @@ static int change_cb(sr_session_ctx_t *session, uint32_t sub_id, const char *mod return rc; } -static 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_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) && + sr_module_change_subscribe(confd->startup, model, "//.", core_startup_save, NULL, + CB_PRIO_PASSIVE, SR_SUBSCR_PASSIVE | SR_SUBSCR_CHANGE_ALL_MODULES, &confd->sub); } int sr_plugin_init_cb(sr_session_ctx_t *session, void **priv) diff --git a/src/confd/src/core.h b/src/confd/src/core.h index 8d0983427..0317f83ec 100644 --- a/src/confd/src/core.h +++ b/src/confd/src/core.h @@ -135,48 +135,18 @@ struct confd { struct dagger netdag; }; -uint32_t core_hook_prio (void); -int core_pre_hook (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); -int core_post_hook (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); int core_startup_save (sr_session_ctx_t *, uint32_t, const char *, const char *, sr_event_t, unsigned, void *); -int core_wait_change (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) { - struct confd *ptr = (struct confd *)arg; - bool need_core_hooks; - int rc; - - /* - * For standard subscribtions we hook into the callback chain - * for all modules to figure out, per changeset, which of the - * callbacks is the last one. This is where we want to call the - * global commit-done hook for candidate -> running changes and - * the startup-save hook for running -> startup copying. - */ - - need_core_hooks = !(flags & SR_SUBSCR_UPDATE); - - if (need_core_hooks) { - sr_module_change_subscribe(ptr->session, module, xpath, core_pre_hook, NULL, - 0, SR_SUBSCR_PASSIVE, sub); - } - - rc = sr_module_change_subscribe(session, module, xpath, cb, arg, + int rc = sr_module_change_subscribe(session, module, xpath, cb, arg, CB_PRIO_PRIMARY, flags | SR_SUBSCR_DEFAULT, sub); if (rc) { ERROR("failed subscribing to changes of %s: %s", xpath, sr_strerror(rc)); return rc; } - if (need_core_hooks) { - sr_module_change_subscribe(ptr->session, module, xpath, core_post_hook, NULL, - core_hook_prio(), SR_SUBSCR_PASSIVE, sub); - sr_module_change_subscribe(ptr->startup, module, xpath, core_startup_save, NULL, - core_hook_prio(), SR_SUBSCR_PASSIVE, sub); - } - return 0; } From a280960d47952ff02e549850c435ba8bb6502956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Fri, 31 Oct 2025 09:43:54 +0100 Subject: [PATCH 7/7] kernel-upgrade: Improve error handling --- .github/workflows/check-kernel-release.yml | 3 ++ utils/kernel-upgrade.sh | 49 ++++++++++++++++------ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/.github/workflows/check-kernel-release.yml b/.github/workflows/check-kernel-release.yml index 101fc33c2..a067edaa5 100644 --- a/.github/workflows/check-kernel-release.yml +++ b/.github/workflows/check-kernel-release.yml @@ -25,6 +25,7 @@ jobs: - name: Fetch kernel.org and check for 6.12 release id: check run: | + set -e -o pipefail # Fetch the kernel.org frontpage and extract 6.12 version CURRENT_VERSION=$(curl -s https://www.kernel.org/ | grep -oP '6\.12\.\d+' | head -n1) @@ -56,6 +57,7 @@ jobs: - name: Set up git credentials if: steps.check.outputs.new_release == 'true' run: | + set -e -o pipefail git config --global user.email "ael-bot@users.noreply.github.com" git config --global user.name "ael-bot" @@ -68,6 +70,7 @@ jobs: env: GIT_TERMINAL_PROMPT: 0 run: | + set -e -o pipefail ./utils/kernel-upgrade.sh linux - name: Create pull request diff --git a/utils/kernel-upgrade.sh b/utils/kernel-upgrade.sh index 2607911d1..ce07927af 100755 --- a/utils/kernel-upgrade.sh +++ b/utils/kernel-upgrade.sh @@ -6,7 +6,7 @@ # Usage: ./utils/kernel-upgrade.sh # -set -e +set -e -o pipefail # Parse arguments if [ $# -ne 1 ]; then @@ -139,15 +139,6 @@ rebase_kernel() { log_info "Run 'git rebase --abort' to cancel or resolve conflicts manually" exit 1 fi - - # Push rebased branch to kkit remote - log_info "Pushing rebased branch to $KKIT_REMOTE..." - if git -C "$LINUX_DIR" push "$KKIT_REMOTE" "$LINUX_BRANCH" --force-with-lease; then - log_info "Successfully pushed to $KKIT_REMOTE" - else - log_error "Push failed" - exit 1 - fi } # Update infix and run kernel refresh @@ -195,8 +186,8 @@ update_infix() { # Check if versions are the same if [ "$OLD_VERSION" = "$NEW_VERSION" ]; then - log_info "Kernel version unchanged ($OLD_VERSION), skipping refresh" - return 0 + log_info "Kernel version unchanged ($OLD_VERSION), nothing to do" + exit 0 fi # Run kernel refresh script @@ -231,6 +222,16 @@ update_infix() { else log_warn "doc/ChangeLog.md not found, skipping changelog update" fi + + # Commit all changes + log_info "Committing changes to infix..." + git -C "$INFIX_DIR" add -A + if git -C "$INFIX_DIR" diff-index --quiet HEAD --; then + log_info "No changes to commit" + else + git -C "$INFIX_DIR" commit -m "Upgrade Linux kernel to $NEW_VERSION" + log_info "Changes committed" + fi } # Check for uncommitted changes @@ -254,6 +255,29 @@ check_clean_working_tree() { log_info "Working tree is clean" } +# Push changes to remotes +push_changes() { + log_info "Pushing changes to remotes..." + + # Push rebased linux branch to kkit remote + log_info "Pushing rebased linux branch to $KKIT_REMOTE..." + if git -C "$LINUX_DIR" push "$KKIT_REMOTE" "$LINUX_BRANCH" --force-with-lease; then + log_info "Successfully pushed linux branch to $KKIT_REMOTE" + else + log_error "Push to linux remote failed" + exit 1 + fi + + # Push infix branch to origin + log_info "Pushing infix branch to origin..." + if git -C "$INFIX_DIR" push origin "$INFIX_BRANCH"; then + log_info "Successfully pushed infix branch to origin" + else + log_error "Push to infix remote failed" + exit 1 + fi +} + # Main execution main() { log_info "Starting automated kernel upgrade test..." @@ -265,6 +289,7 @@ main() { update_linux_kernel rebase_kernel update_infix + push_changes log_info "Kernel upgrade completed successfully!" }