From 025e15fdccf92f00f1750bf34a05fdf8fd840fea Mon Sep 17 00:00:00 2001 From: Michal Vasko Date: Fri, 1 Mar 2024 14:43:08 +0100 Subject: [PATCH] netconf UPDATE updated sysrepo netconf err format --- CMakeLists.txt | 4 +- src/common.c | 20 ++-- src/err_netconf.c | 2 +- src/main.c | 135 ++++++++++++------------- src/netconf.c | 35 +++---- src/netconf_nmda.c | 6 +- src/netconf_subscribed_notifications.c | 10 +- 7 files changed, 96 insertions(+), 116 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cab63d9b..738c8718 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,8 +59,8 @@ set(LIBNETCONF2_DEP_SOVERSION 4.1.7) set(LIBNETCONF2_DEP_SOVERSION_MAJOR 4) # sysrepo required version -set(SYSREPO_DEP_VERSION 2.2.148) -set(SYSREPO_DEP_SOVERSION 7.22.0) +set(SYSREPO_DEP_VERSION 2.2.159) +set(SYSREPO_DEP_SOVERSION 7.24.0) set(SYSREPO_DEP_SOVERSION_MAJOR 7) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -std=c99") diff --git a/src/common.c b/src/common.c index 2b20dd59..358a11d8 100644 --- a/src/common.c +++ b/src/common.c @@ -62,8 +62,8 @@ np_ignore_rpc(sr_session_ctx_t *ev_sess, sr_event_t event, int *rc) if (sr_session_get_orig_name(ev_sess) && strcmp(sr_session_get_orig_name(ev_sess), "netopeer2")) { /* forbidden */ - sr_session_set_error_message(ev_sess, "Non-NETCONF originating RPC will not be executed."); *rc = SR_ERR_UNSUPPORTED; + sr_session_set_error(ev_sess, NULL, *rc, "Non-NETCONF originating RPC will not be executed."); return 1; } @@ -621,7 +621,7 @@ url_get(const char *url, sr_session_ctx_t *ev_sess) if (!np2srv.url_protocols) { ERR("No URL protocols enabled."); - sr_session_set_error_message(ev_sess, "No URL protocols enabled."); + sr_session_set_error(ev_sess, NULL, SR_ERR_UNSUPPORTED, "No URL protocols enabled."); return NULL; } @@ -640,7 +640,7 @@ url_get(const char *url, sr_session_ctx_t *ev_sess) res = curl_easy_perform(curl); if (res != CURLE_OK) { ERR("Failed to download data (curl: %s).", curl_buffer); - sr_session_set_error_message(ev_sess, curl_buffer); + sr_session_set_error(ev_sess, NULL, SR_ERR_OPERATION_FAILED, curl_buffer); goto cleanup; } @@ -674,20 +674,20 @@ op_parse_url(const char *url, int validate, int *rc, sr_session_ctx_t *ev_sess) /* load the whole config element */ if (lyd_parse_data_mem(ly_ctx, url_data, LYD_XML, LYD_PARSE_OPAQ | LYD_PARSE_ONLY | LYD_PARSE_NO_STATE, 0, &config)) { *rc = SR_ERR_LY; - sr_session_set_error_message(ev_sess, ly_err_last(ly_ctx)->msg); + sr_session_set_error(ev_sess, NULL, *rc, ly_err_last(ly_ctx)->msg); goto cleanup; } if (!config || config->schema) { *rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(ev_sess, "Missing top-level \"config\" element in URL data."); + sr_session_set_error(ev_sess, NULL, *rc, "Missing top-level \"config\" element in URL data."); goto cleanup; } opaq = (struct lyd_node_opaq *)config; if (strcmp(opaq->name.name, "config") || strcmp(opaq->name.module_ns, "urn:ietf:params:xml:ns:netconf:base:1.0")) { *rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(ev_sess, "Invalid top-level element in URL data, expected \"config\" with " + sr_session_set_error(ev_sess, NULL, *rc, "Invalid top-level element in URL data, expected \"config\" with " "namespace \"urn:ietf:params:xml:ns:netconf:base:1.0\"."); goto cleanup; } @@ -700,7 +700,7 @@ op_parse_url(const char *url, int validate, int *rc, sr_session_ctx_t *ev_sess) /* separate validation if requested */ if (lyd_validate_all(&data, NULL, LYD_VALIDATE_NO_STATE, NULL)) { *rc = SR_ERR_LY; - sr_session_set_error_message(ev_sess, ly_err_last(ly_ctx)->msg); + sr_session_set_error(ev_sess, NULL, *rc, ly_err_last(ly_ctx)->msg); goto cleanup; } } @@ -732,7 +732,7 @@ op_export_url(const char *url, struct lyd_node *data, uint32_t print_options, in /* print the config as expected by the other end */ if (lyd_new_opaq2(NULL, ly_ctx, "config", NULL, NULL, "urn:ietf:params:xml:ns:netconf:base:1.0", &config)) { *rc = SR_ERR_LY; - sr_session_set_error_message(ev_sess, ly_err_last(ly_ctx)->msg); + sr_session_set_error(ev_sess, NULL, *rc, ly_err_last(ly_ctx)->msg); ret = -1; goto cleanup; } @@ -767,7 +767,7 @@ op_export_url(const char *url, struct lyd_node *data, uint32_t print_options, in if (res != CURLE_OK) { ERR("Failed to upload data (curl: %s).", curl_buffer); *rc = SR_ERR_SYS; - sr_session_set_error_message(ev_sess, curl_buffer); + sr_session_set_error(ev_sess, NULL, *rc, curl_buffer); ret = -1; goto curl_cleanup; } @@ -829,7 +829,7 @@ op_parse_config(struct lyd_node_any *config, uint32_t parse_options, int *rc, sr } if (lyrc) { *rc = SR_ERR_LY; - sr_session_set_error_message(ev_sess, ly_err_last(ly_ctx)->msg); + sr_session_set_error(ev_sess, NULL, *rc, ly_err_last(ly_ctx)->msg); } return root; diff --git a/src/err_netconf.c b/src/err_netconf.c index ef8d9fa4..519cea8b 100644 --- a/src/err_netconf.c +++ b/src/err_netconf.c @@ -307,7 +307,7 @@ np_err_sr2nc_edit(sr_session_ctx_t *ev_sess, const sr_session_ctx_t *err_sess) return; mem_error: - sr_session_set_error_message(ev_sess, "Memory allocation failed."); + sr_session_set_error(ev_sess, NULL, SR_ERR_NO_MEMORY, "Memory allocation failed."); free(path); free(str); diff --git a/src/main.c b/src/main.c index b0df6363..64d47972 100644 --- a/src/main.c +++ b/src/main.c @@ -198,96 +198,86 @@ np2srv_err_nc(sr_error_info_err_t *err) struct lyd_node *e_first = NULL, *e, *err_info; const struct ly_ctx *ly_ctx; const char *err_type, *err_tag, *err_app_tag, *err_path, *err_msg, **err_info_elem = NULL, **err_info_val = NULL, *ns; - uint32_t err_info_count, i, j; - int r; + uint32_t err_info_count, j; /* only dictionary used, no need to keep locked */ ly_ctx = sr_acquire_context(np2srv.sr_conn); sr_release_context(np2srv.sr_conn); - i = 0; - while (1) { - /* read the next error */ - r = sr_err_get_netconf_error_idx(err, i, &err_type, &err_tag, &err_app_tag, &err_path, &err_msg, &err_info_elem, - &err_info_val, &err_info_count); - if (r == SR_ERR_NOT_FOUND) { - /* no more errors */ - break; - } else if (r) { - goto error; - } + /* read the error */ + if (sr_err_get_netconf_error(err, &err_type, &err_tag, &err_app_tag, &err_path, &err_msg, &err_info_elem, + &err_info_val, &err_info_count)) { + goto error; + } - /* rpc-error */ - if (lyd_new_opaq2(NULL, ly_ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &e)) { - goto error; - } + /* rpc-error */ + if (lyd_new_opaq2(NULL, ly_ctx, "rpc-error", NULL, NULL, NC_NS_BASE, &e)) { + goto error; + } - /* error-type */ - if (lyd_new_opaq2(e, NULL, "error-type", err_type, NULL, NC_NS_BASE, NULL)) { - goto error; - } + /* error-type */ + if (lyd_new_opaq2(e, NULL, "error-type", err_type, NULL, NC_NS_BASE, NULL)) { + goto error; + } + + /* error-tag */ + if (lyd_new_opaq2(e, NULL, "error-tag", err_tag, NULL, NC_NS_BASE, NULL)) { + goto error; + } - /* error-tag */ - if (lyd_new_opaq2(e, NULL, "error-tag", err_tag, NULL, NC_NS_BASE, NULL)) { + /* error-severity */ + if (lyd_new_opaq2(e, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) { + goto error; + } + + if (err_app_tag) { + /* error-app-tag */ + if (nc_err_set_app_tag(e, err_app_tag)) { goto error; } + } - /* error-severity */ - if (lyd_new_opaq2(e, NULL, "error-severity", "error", NULL, NC_NS_BASE, NULL)) { + if (err_path) { + /* error-path */ + if (nc_err_set_path(e, err_path)) { goto error; } + } - if (err_app_tag) { - /* error-app-tag */ - if (nc_err_set_app_tag(e, err_app_tag)) { - goto error; - } - } + /* error-message */ + if (nc_err_set_msg(e, err_msg, "en")) { + goto error; + } - if (err_path) { - /* error-path */ - if (nc_err_set_path(e, err_path)) { + /* error-info */ + err_info = NULL; + for (j = 0; j < err_info_count; ++j) { + if (!err_info) { + if (lyd_new_opaq2(e, NULL, "error-info", NULL, NULL, NC_NS_BASE, &err_info)) { goto error; } } - - /* error-message */ - if (nc_err_set_msg(e, err_msg, "en")) { - goto error; + if (!strcmp(err_info_elem[j], "bad-attribute") || !strcmp(err_info_elem[j], "bad-element") || + !strcmp(err_info_elem[j], "bad-namespace") || !strcmp(err_info_elem[j], "session-id")) { + /* NETCONF error-info */ + ns = NC_NS_BASE; + } else if (!strcmp(err_info_elem[j], "non-unique") || !strcmp(err_info_elem[j], "missing-choice")) { + /* YANG error-info */ + ns = "urn:ietf:params:xml:ns:yang:1"; + } else { + /* custom (unknown) */ + ns = "urn:netconf:custom-error-info"; } - - /* error-info */ - err_info = NULL; - for (j = 0; j < err_info_count; ++j) { - if (!err_info) { - if (lyd_new_opaq2(e, NULL, "error-info", NULL, NULL, NC_NS_BASE, &err_info)) { - goto error; - } - } - if (!strcmp(err_info_elem[j], "bad-attribute") || !strcmp(err_info_elem[j], "bad-element") || - !strcmp(err_info_elem[j], "bad-namespace") || !strcmp(err_info_elem[j], "session-id")) { - /* NETCONF error-info */ - ns = NC_NS_BASE; - } else if (!strcmp(err_info_elem[j], "non-unique") || !strcmp(err_info_elem[j], "missing-choice")) { - /* YANG error-info */ - ns = "urn:ietf:params:xml:ns:yang:1"; - } else { - /* custom (unknown) */ - ns = "urn:netconf:custom-error-info"; - } - if (lyd_new_opaq2(err_info, NULL, err_info_elem[j], err_info_val[j], NULL, ns, NULL)) { - goto error; - } + if (lyd_new_opaq2(err_info, NULL, err_info_elem[j], err_info_val[j], NULL, ns, NULL)) { + goto error; } - - /* append */ - lyd_insert_sibling(e_first, e, &e_first); - - free(err_info_elem); - free(err_info_val); - ++i; } + /* append */ + lyd_insert_sibling(e_first, e, &e_first); + + free(err_info_elem); + free(err_info_val); return e_first; error: @@ -311,15 +301,17 @@ np2srv_err_reply_sr(const sr_error_info_t *err_info) const struct ly_ctx *ly_ctx; size_t i; - /* try to find a NETCONF error */ + /* try to find a NETCONF error(s) */ for (i = 0; i < err_info->err_count; ++i) { if (err_info->err[i].error_format && !strcmp(err_info->err[i].error_format, "NETCONF")) { /* NETCONF error */ e = np2srv_err_nc(&err_info->err[i]); - if (e) { + + if (reply) { + nc_server_reply_add_err(reply, e); + } else { reply = nc_server_reply_err(e); } - break; } } @@ -339,7 +331,6 @@ np2srv_err_reply_sr(const sr_error_info_t *err_info) } else { reply = nc_server_reply_err(e); } - e = NULL; } sr_release_context(np2srv.sr_conn); diff --git a/src/netconf.c b/src/netconf.c index bafe0e60..f154e57d 100644 --- a/src/netconf.c +++ b/src/netconf.c @@ -279,7 +279,7 @@ np2srv_rpc_editconfig_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), con #else ly_set_free(nodeset, NULL); rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } @@ -365,7 +365,7 @@ np2srv_rpc_copyconfig_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), con #else ly_set_free(nodeset, NULL); rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } @@ -409,7 +409,7 @@ np2srv_rpc_copyconfig_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), con #else ly_set_free(nodeset, NULL); rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } @@ -537,7 +537,7 @@ np2srv_rpc_deleteconfig_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), c #else ly_set_free(nodeset, NULL); rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } @@ -644,8 +644,7 @@ np2srv_rpc_un_lock_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const goto cleanup; } else if (rc) { /* generic error */ - sr_session_get_error(user_sess->sess, &err_info); - sr_session_set_error_message(session, err_info->err[0].message); + sr_session_dup_error(user_sess->sess, session); goto cleanup; } @@ -675,7 +674,7 @@ np2srv_rpc_kill_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const cha sr_session_get_orig_data(session, 0, NULL, (const void **)&nc_sid); if (kill_sid == *nc_sid) { rc = SR_ERR_INVAL_ARG; - sr_session_set_error_message(session, "It is forbidden to kill own session."); + sr_session_set_error(session, NULL, rc, "It is forbidden to kill own session."); goto cleanup; } @@ -686,7 +685,7 @@ np2srv_rpc_kill_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const cha } if (!kill_sess) { rc = SR_ERR_INVAL_ARG; - sr_session_set_error_message(session, "Session with the specified \"session-id\" not found."); + sr_session_set_error(session, NULL, rc, "Session with the specified \"session-id\" not found."); goto cleanup; } @@ -695,8 +694,6 @@ np2srv_rpc_kill_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const cha nc_session_set_term_reason(kill_sess, NC_SESSION_TERM_KILLED); nc_session_set_killed_by(kill_sess, kill_sid); - /* success */ - cleanup: return rc; } @@ -726,13 +723,10 @@ np2srv_rpc_discard_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const /* sysrepo API */ rc = sr_copy_config(user_sess->sess, NULL, SR_DS_RUNNING, np2srv.sr_timeout); if (rc != SR_ERR_OK) { - sr_session_get_error(user_sess->sess, &err_info); - sr_session_set_error_message(session, err_info->err[0].message); + sr_session_dup_error(user_sess->sess, session); goto cleanup; } - /* success */ - cleanup: np_release_user_sess(user_sess); return rc; @@ -781,7 +775,7 @@ np2srv_rpc_validate_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const #else ly_set_free(nodeset, NULL); rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } @@ -799,8 +793,7 @@ np2srv_rpc_validate_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const /* sysrepo API */ rc = sr_validate(user_sess->sess, NULL, 0); if (rc != SR_ERR_OK) { - sr_session_get_error(user_sess->sess, &err_info); - sr_session_set_error_message(session, err_info->err[0].message); + sr_session_dup_error(user_sess->sess, session); goto cleanup; } } /* else already validated */ @@ -918,8 +911,8 @@ np2srv_rpc_subscribe_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), cons /* RFC 5277 section 6.5 */ if (nc_session_get_notif_status(ncs)) { - sr_session_set_error_message(session, "Session already subscribed."); rc = SR_ERR_EXISTS; + sr_session_set_error(session, NULL, rc, "Session already subscribed."); goto cleanup; } @@ -1023,8 +1016,7 @@ np2srv_rpc_subscribe_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), cons rc = sr_notif_subscribe_tree(user_sess->sess, ly_mod->name, xp_filter, start.tv_sec ? &start : NULL, stop.tv_sec ? &stop : NULL, np2srv_rpc_subscribe_ntf_cb, ntf_arg, 0, &np2srv.sr_notif_sub); if (rc != SR_ERR_OK) { - sr_session_get_error(user_sess->sess, &err_info); - sr_session_set_error_message(session, err_info->err[0].message); + sr_session_dup_error(user_sess->sess, session); goto cleanup; } } @@ -1035,8 +1027,7 @@ np2srv_rpc_subscribe_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), cons rc = sr_notif_subscribe_tree(user_sess->sess, stream, xp_filter, start.tv_sec ? &start : NULL, stop.tv_sec ? &stop : NULL, np2srv_rpc_subscribe_ntf_cb, ntf_arg, 0, &np2srv.sr_notif_sub); if (rc != SR_ERR_OK) { - sr_session_get_error(user_sess->sess, &err_info); - sr_session_set_error_message(session, err_info->err[0].message); + sr_session_dup_error(user_sess->sess, session); goto cleanup; } } diff --git a/src/netconf_nmda.c b/src/netconf_nmda.c index 8fc2cf1a..00d8cb41 100644 --- a/src/netconf_nmda.c +++ b/src/netconf_nmda.c @@ -138,7 +138,7 @@ np2srv_rpc_getdata_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const ds = SR_DS_FACTORY_DEFAULT; } else { rc = SR_ERR_INVAL_ARG; - sr_session_set_error_message(session, "Datastore \"%s\" is not supported.", lyd_get_value(&leaf->node)); + sr_session_set_error(session, NULL, rc, "Datastore \"%s\" is not supported.", lyd_get_value(&leaf->node)); goto cleanup; } @@ -246,7 +246,7 @@ np2srv_rpc_editdata_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const ds = SR_DS_CANDIDATE; } else { rc = SR_ERR_INVAL_ARG; - sr_session_set_error_message(session, "Datastore \"%s\" is not supported or writable.", lyd_get_value(&leaf->node)); + sr_session_set_error(session, NULL, rc, "Datastore \"%s\" is not supported or writable.", lyd_get_value(&leaf->node)); goto cleanup; } @@ -272,7 +272,7 @@ np2srv_rpc_editdata_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const } #else rc = SR_ERR_UNSUPPORTED; - sr_session_set_error_message(session, "URL not supported."); + sr_session_set_error(session, NULL, rc, "URL not supported."); goto cleanup; #endif } diff --git a/src/netconf_subscribed_notifications.c b/src/netconf_subscribed_notifications.c index 01eef06f..3d07f945 100644 --- a/src/netconf_subscribed_notifications.c +++ b/src/netconf_subscribed_notifications.c @@ -65,7 +65,7 @@ sub_ntf_error(sr_session_ctx_t *ev_sess, int sr_err, const char *fmt, ...) va_end(ap); ERR("%s", msg); - sr_session_set_error_message(ev_sess, "%s", msg); + sr_session_set_error(ev_sess, NULL, sr_err, "%s", msg); free(msg); return sr_err; @@ -81,7 +81,7 @@ static int sub_ntf_error_mem(sr_session_ctx_t *ev_sess) { EMEM; - sr_session_set_error_message(ev_sess, "Memory allocation failed."); + sr_session_set_error(ev_sess, NULL, SR_ERR_NO_MEMORY, "Memory allocation failed."); return SR_ERR_NO_MEMORY; } @@ -101,7 +101,7 @@ sub_ntf_error_ly(sr_session_ctx_t *ev_sess, const struct ly_ctx *ly_ctx) msg = ly_err_last(ly_ctx)->msg; ERR("%s", msg); - sr_session_set_error_message(ev_sess, "%s", msg); + sr_session_set_error(ev_sess, NULL, SR_ERR_LY, "%s", msg); return SR_ERR_LY; } @@ -407,7 +407,6 @@ sub_ntf_filter2xpath(sr_session_ctx_t *user_sess, sr_session_ctx_t *ev_sess, con { int rc = SR_ERR_OK; sr_data_t *subtree = NULL; - const sr_error_info_t *err_info; char *str; if (filter_name) { @@ -421,8 +420,7 @@ sub_ntf_filter2xpath(sr_session_ctx_t *user_sess, sr_session_ctx_t *ev_sess, con rc = sr_get_subtree(user_sess, str, 0, &subtree); free(str); if (rc) { - sr_session_get_error(user_sess, &err_info); - sr_session_set_error_message(ev_sess, err_info->err[0].message); + sr_session_dup_error(user_sess, ev_sess); goto cleanup; }