diff --git a/src/confd/src/core.c b/src/confd/src/core.c index 719d6228..11f8d1ad 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,23 +77,118 @@ 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; - } - - if (systemf("initctl -b reload")) { - EMERG("initctl reload: failed applying new configuration!"); - return SR_ERR_SYS; - } - - AUDIT("The new configuration has been applied."); 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 + } + + /* ietf-interfaces */ + if ((rc = ietf_interfaces_change(session, config, diff, event, confd))) + goto free_diff; + + /* infix-dhcp-client*/ + if ((rc = infix_dhcp_client_change(session, config, diff, event, confd))) + goto free_diff; + + /* 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) { int log_opts = LOG_PID | LOG_NDELAY; @@ -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); + rc = subscribe_module("ietf-interfaces", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-interfaces"); + goto err; + } + rc = subscribe_module("ietf-netconf-acm", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to ietf-netconf-acm"); + goto err; + } + rc = subscribe_module("infix-dhcp-client", &confd, 0); + if (rc) { + ERROR("Failed to subscribe to infix-dhcp-client"); + goto err; + } + rc = subscribe_module("ietf-keystore", &confd, SR_SUBSCR_UPDATE); + if (rc) { + ERROR("Failed to subscribe to ietf-keystore"); + goto err; + } + 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 = ietf_system_rpc_init(&confd); if (rc) goto err; - rc = ietf_keystore_init(&confd); + rc = infix_containers_rpc_init(&confd); if (rc) goto err; - rc = ietf_syslog_init(&confd); - if (rc) - goto err; - rc = ietf_system_init(&confd); - if (rc) - goto err; - rc = infix_containers_init(&confd); - if (rc) - goto err; - rc = infix_dhcp_client_init(&confd); - if (rc) - goto err; - rc = infix_dhcp_server_init(&confd); - if (rc) - goto err; - rc = infix_factory_init(&confd); - if (rc) - goto err; - rc = ietf_factory_default_init(&confd); - if (rc) - goto err; - rc = ietf_routing_init(&confd); - if (rc) - goto err; - rc = infix_meta_init(&confd); - if (rc) - goto err; - rc = infix_system_sw_init(&confd); - if (rc) - goto err; - rc = infix_services_init(&confd); - if (rc) - goto err; - rc = ietf_hardware_init(&confd); - if (rc) - goto err; - rc = infix_firewall_init(&confd); + rc = infix_dhcp_server_rpc_init(&confd); if (rc) goto err; + rc = infix_factory_rpc_init(&confd); + if (rc) + goto err; + + rc = ietf_factory_default_rpc_init(&confd); + if (rc) + goto err; + + rc = infix_firewall_rpc_init(&confd); + if (rc) + goto err; + + rc = infix_system_sw_rpc_init(&confd); + if (rc) + goto err; + + /* Candidate infer configurations */ + rc = ietf_hardware_candidate_init(&confd); + if (rc) + goto err; + + rc = infix_firewall_candidate_init(&confd); + if (rc) + goto err; + + 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 90595595..d2289c34 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 5fca3fe6..398419ea 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 37143954..1d0993ed 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 bd6e0df5..db10e3f7 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 2e1e38f7..a87303ee 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 */ + 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; + } + + + for (size_t i = 0; i < count; ++i) { + sr_val_t *entry = &list[i]; + + if (!srx_isset(session, "%s/cleartext-private-key", entry->xpath) && !srx_isset(session, "%s/public-key", entry->xpath)) { + char *private_key_format, *public_key_format; + + public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath); + if (!public_key_format) + continue; + private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath); + if (!private_key_format) { + free(public_key_format); + continue; + } + + if (!strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") && + !strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format")) { + char *pub_key = NULL, *priv_key = NULL, *name; + + name = srx_get_str(session, "%s/name", entry->xpath); + NOTE("SSH key (%s) does not exist, generating...", name); + if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) { + ERROR("Failed to generate SSH keys for %s", name); + goto next; + } + + priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); + if (!priv_key) + goto next; + + pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); + if (!pub_key) + goto next; + + rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath); + if (rc) { + ERROR("Failed setting private key for %s... rc: %d", name, rc); + goto next; + } + rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath); + if (rc != SR_ERR_OK) { + ERROR("Failed setting public key for %s... rc: %d", name, rc); + goto next; + } + next: + if (erase(SSH_PRIVATE_KEY)) + ERRNO("Failed removing SSH server private key"); + if (erase(SSH_PUBLIC_KEY)) + ERRNO("Failed removing SSH server public key"); + + if (priv_key) + free(priv_key); + + if (pub_key) + free(pub_key); + + free(name); + } + free(public_key_format); + free(private_key_format); + } + } + if (list) + sr_free_values(list, count); + 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); + } + + if (rename(SSH_HOSTKEYS_NEXT, SSH_HOSTKEYS)) + ERRNO("Failed switching to new %s", SSH_HOSTKEYS); + } + return SR_ERR_OK; + default: return SR_ERR_OK; } - 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; - } + changes = lydx_get_descendant(config, "keystore", "asymmetric-keys", "asymmetric-key", NULL); + LYX_LIST_FOR_EACH(changes, change, "asymmetric-key") { + const char *name, *private_key_type, *public_key_type; + const char *private_key, *public_key; - for (size_t i = 0; i < count; ++i) { - sr_val_t *entry = &list[i]; + 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 (!srx_isset(session, "%s/cleartext-private-key", entry->xpath) && !srx_isset(session, "%s/public-key", entry->xpath)) { - char *private_key_format, *public_key_format; - - public_key_format = srx_get_str(session, "%s/public-key-format", entry->xpath); - if (!public_key_format) - continue; - private_key_format = srx_get_str(session, "%s/private-key-format", entry->xpath); - if (!private_key_format) { - free(public_key_format); - continue; - } - - if (!strcmp(private_key_format, "infix-crypto-types:rsa-private-key-format") && - !strcmp(public_key_format, "infix-crypto-types:ssh-public-key-format")) { - char *pub_key = NULL, *priv_key = NULL, *name; - - name = srx_get_str(session, "%s/name", entry->xpath); - NOTE("SSH key (%s) does not exist, generating...", name); - if (systemf("/usr/libexec/infix/mkkeys %s %s", SSH_PRIVATE_KEY, SSH_PUBLIC_KEY)) { - ERROR("Failed to generate SSH keys for %s", name); - goto next; - } - - priv_key = filerd(SSH_PRIVATE_KEY, filesz(SSH_PRIVATE_KEY)); - if (!priv_key) - goto next; - - pub_key = filerd(SSH_PUBLIC_KEY, filesz(SSH_PUBLIC_KEY)); - if (!pub_key) - goto next; - - rc = srx_set_str(session, priv_key, 0, "%s/cleartext-private-key", entry->xpath); - if (rc) { - ERROR("Failed setting private key for %s... rc: %d", name, rc); - goto next; - } - rc = srx_set_str(session, pub_key, 0, "%s/public-key", entry->xpath); - if (rc != SR_ERR_OK) { - ERROR("Failed setting public key for %s... rc: %d", name, rc); - goto next; - } - next: - if (erase(SSH_PRIVATE_KEY)) - ERRNO("Failed removing SSH server private key"); - if (erase(SSH_PUBLIC_KEY)) - ERRNO("Failed removing SSH server public key"); - - if (priv_key) - free(priv_key); - - if (pub_key) - free(pub_key); - - free(name); - } - free(public_key_format); - free(private_key_format); + 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; } - if (list) - sr_free_values(list, count); - - return SR_ERR_OK; -} - -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 9e0a6ae9..152ad942 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; - } + 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; - LY_LIST_FOR(lyd_child(cfg->tree), tmp) { - LY_LIST_FOR(lyd_child(tmp), cplane) { - 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 @@ err_close: 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 9e63437d..46fec31e 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; + struct lyd_node *dremotes, *remote; - if (SR_EV_DONE != event) + if (SR_EV_DONE != event || !lydx_get_xpathf(diff, XPATH_REMOTE_)) return SR_ERR_OK; - err = srx_get_diff(session, &tree); - if (err) - 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 @@ done: 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 ccecd9d8..1a6b7eb5 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 @@ err: 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 @@ cleanup: 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 @@ cleanup: 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 @@ err: 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 1c579930..e73f325c 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 a3f5be7a..5310d6bf 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 2e921b92..2a543174 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 @@ err_done: 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 c793a71f..1c564579 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 ebdb4539..88086356 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 @@ done: 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 @@ fail: 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 2936fdc5..d460b82e 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 001eba20..6a1d8f08 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 c9427d08..783121ae 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;