Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NETCONF error tags #1636

Merged
merged 3 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/err_netconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ np_err_missing_element(sr_session_ctx_t *ev_sess, const char *elem_name)
sr_session_set_netconf_error(ev_sess, "protocol", "missing-element", NULL, NULL, msg, 1, "bad-element", elem_name);
}

void
np_err_missing_attribute(sr_session_ctx_t *ev_sess, const char *message, const char *elem_name)
{
sr_session_set_netconf_error(ev_sess, "protocol", "missing-attribute", NULL, NULL, message, 1, "bad-element", elem_name);
}

void
np_err_bad_element(sr_session_ctx_t *ev_sess, const char *elem_name, const char *description)
{
Expand Down
2 changes: 2 additions & 0 deletions src/err_netconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void np_err_lock_denied(sr_session_ctx_t *ev_sess, const char *err_msg, uint32_t

void np_err_missing_element(sr_session_ctx_t *ev_sess, const char *elem_name);

void np_err_missing_attribute(sr_session_ctx_t *ev_sess, const char *message, const char *elem_name);

void np_err_bad_element(sr_session_ctx_t *ev_sess, const char *elem_name, const char *description);

void np_err_invalid_value(sr_session_ctx_t *ev_sess, const char *description, const char *bad_elem_name);
Expand Down
85 changes: 82 additions & 3 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,64 @@ np2srv_err_nc(sr_error_info_err_t *err)
return NULL;
}

/**
* @brief Find the nth substring delimited by quotes.
*
* For example: abcd"ef"ghij"kl"mn -> index 0 is "ef", index 1 is "kl".
*
* @param[in] msg Input string with quoted substring.
* @param[in] index Number starting from 0 specifying the nth substring.
* @return Copied nth substring without quotes.
*/
static char *
np2srv_err_reply_get_quoted_string(const char *msg, uint32_t index)
{
char *ret;
const char *start = NULL, *end = NULL, *iter, *tmp;
uint32_t quote_cnt = 0, last_quote;

assert(msg);

last_quote = (index + 1) * 2;
for (iter = msg; *iter; ++iter) {
if (*iter != '\"') {
continue;
}
/* updating the start and end pointers - swap */
tmp = end;
end = iter;
start = tmp;
if (++quote_cnt == last_quote) {
/* nth substring found */
break;
}
}

if (!start) {
return NULL;
}

/* Skip first quote */
++start;
/* Copy substring */
ret = strndup(start, end - start);

return ret;
}

/**
* @brief Check that the @p str starts with the @p prefix.
*
* @param[in] prefix Required prefix.
* @param[in] str Input string to check.
* @return True if @p str start with @p prefix otherwise False.
*/
static ly_bool
np2srv_strstarts(const char *prefix, const char *str)
{
return strncmp(str, prefix, strlen(prefix)) == 0;
}

/**
* @brief Create NC error reply based on SR error info.
*
Expand All @@ -262,6 +320,9 @@ np2srv_err_reply_sr(const sr_error_info_t *err_info)
struct lyd_node *e;
const struct ly_ctx *ly_ctx;
size_t i;
char *str, *path;
const struct lysc_node *cn;
NC_ERR_TYPE errtype;

/* try to find a NETCONF error(s) */
for (i = 0; i < err_info->err_count; ++i) {
Expand All @@ -284,16 +345,34 @@ np2srv_err_reply_sr(const sr_error_info_t *err_info)

ly_ctx = sr_acquire_context(np2srv.sr_conn);
for (i = 0; i < err_info->err_count; ++i) {
/* generic error */
e = nc_err(ly_ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
nc_err_set_msg(e, err_info->err[i].message, "en");
if (np2srv_strstarts("Mandatory node", err_info->err[i].message) ||
np2srv_strstarts("Mandatory choice", err_info->err[i].message)) {
str = np2srv_err_reply_get_quoted_string(err_info->err[i].message, 0);
path = np2srv_err_reply_get_quoted_string(err_info->err[i].message, 1);
cn = lys_find_path(ly_ctx, NULL, path, 0);
if (cn && ((cn->nodetype & LYS_RPC) || (cn->nodetype & LYS_INPUT))) {
errtype = NC_ERR_TYPE_PROT;
} else {
errtype = NC_ERR_TYPE_APP;
}
e = nc_err(ly_ctx, NC_ERR_MISSING_ELEM, errtype, str);
free(str);
free(path);
} else if (err_info->err->err_code == SR_ERR_NO_MEMORY) {
e = nc_err(ly_ctx, NC_ERR_RES_DENIED, NC_ERR_TYPE_APP);
} else {
/* generic error */
e = nc_err(ly_ctx, NC_ERR_OP_FAILED, NC_ERR_TYPE_APP);
}

nc_err_set_msg(e, err_info->err[i].message, "en");
if (reply) {
nc_server_reply_add_err(reply, e);
} else {
reply = nc_server_reply_err(e);
}
}
/* clear for other errors */
sr_release_context(np2srv.sr_conn);

return reply;
Expand Down
4 changes: 2 additions & 2 deletions src/netconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ np2srv_rpc_get_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), const char
if (meta && !strcmp(lyd_get_meta_value(meta), "xpath")) {
meta = lyd_find_meta(node->meta, NULL, "ietf-netconf:select");
if (!meta) {
ERR("RPC with an XPath filter without the \"select\" attribute.");
np_err_missing_attribute(session, "Missing \"select\" attribute", "filter");
rc = SR_ERR_INVAL_ARG;
goto cleanup;
}
Expand Down Expand Up @@ -933,7 +933,7 @@ np2srv_rpc_subscribe_cb(sr_session_ctx_t *session, uint32_t UNUSED(sub_id), cons
if (meta && !strcmp(lyd_get_meta_value(meta), "xpath")) {
meta = lyd_find_meta(node->meta, NULL, "ietf-netconf:select");
if (!meta) {
ERR("RPC with an XPath filter without the \"select\" attribute.");
np_err_missing_attribute(session, "Missing \"select\" attribute", "filter");
rc = SR_ERR_INVAL_ARG;
goto cleanup;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})

# base test source
set(TEST_SRC "np2_test.c")
set(TEST_SRC "np2_test.c" "np2_other_client.c")

# list of all the tests
set(TESTS test_rpc test_edit test_filter test_subscribe_filter test_subscribe_param test_parallel_sessions
test_candidate test_with_defaults test_nacm test_sub_ntf test_sub_ntf_advanced test_sub_ntf_filter test_error)
test_candidate test_with_defaults test_nacm test_sub_ntf test_sub_ntf_advanced test_sub_ntf_filter test_error test_other_client)

if(CMAKE_C_FLAGS MATCHES "-fsanitize=thread")
message(WARNING "Features which use SIGEV_THREAD are known to be broken under TSAN, disabling tests for YANG-push and confirmed commit")
Expand Down
Loading