client messages CHANGE support for NMDA RPCs
diff --git a/src/messages_client.c b/src/messages_client.c
index 064faf4..d6f261f 100644
--- a/src/messages_client.c
+++ b/src/messages_client.c
@@ -514,6 +514,116 @@
return (struct nc_rpc *)rpc;
}
+API struct nc_rpc *
+nc_rpc_getdata(const char *datastore, const char *filter, const char *config_filter, char **origin_filter,
+ int origin_filter_count, int negated_origin_filter, uint16_t max_depth, int with_origin,
+ NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_getdata *rpc = NULL;
+ int i;
+
+ if (filter && filter[0] && (filter[0] != '<') && (filter[0] != '/') && !isalpha(filter[0])) {
+ ERR("Filter is neither an XML subtree nor an XPath expression (invalid first char '%c').", filter[0]);
+ return NULL;
+ } else if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ }
+
+ rpc = calloc(1, sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ rpc->type = NC_RPC_GETDATA;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ if (filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->filter = strdup(filter);
+ } else {
+ rpc->filter = (char *)filter;
+ }
+ if (config_filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->config_filter = strdup(config_filter);
+ } else {
+ rpc->config_filter = (char *)config_filter;
+ }
+ if (origin_filter && (paramtype == NC_PARAMTYPE_DUP_AND_FREE)) {
+ rpc->origin_filter = malloc(origin_filter_count * sizeof *rpc->origin_filter);
+ if (!rpc->origin_filter) {
+ ERRMEM;
+ goto error;
+ }
+ for (i = 0; i < origin_filter_count; ++i) {
+ rpc->origin_filter[i] = strdup(origin_filter[i]);
+ if (!rpc->origin_filter[i]) {
+ ERRMEM;
+ goto error;
+ }
+ ++rpc->origin_filter_count;
+ }
+ } else {
+ rpc->origin_filter = origin_filter;
+ rpc->origin_filter_count = origin_filter_count;
+ }
+ rpc->negated_origin_filter = negated_origin_filter;
+ rpc->max_depth = max_depth;
+ rpc->with_origin = with_origin;
+ rpc->wd_mode = wd_mode;
+
+ return (struct nc_rpc *)rpc;
+
+error:
+ nc_rpc_free((struct nc_rpc *)rpc);
+ return NULL;
+}
+
+API struct nc_rpc *
+nc_rpc_editdata(const char *datastore, NC_RPC_EDIT_DFLTOP default_op, const char *edit_content, NC_PARAMTYPE paramtype)
+{
+ struct nc_rpc_editdata *rpc;
+
+ if (!datastore) {
+ ERRARG("datastore");
+ return NULL;
+ } else if (!edit_content) {
+ ERRARG("edit_content");
+ return NULL;
+ }
+
+ if (edit_content[0] && (edit_content[0] != '<') && !isalpha(edit_content[0])) {
+ ERR("<edit-data> content is neither a URL nor an XML config (invalid first char '%c').", edit_content[0]);
+ return NULL;
+ }
+
+ rpc = malloc(sizeof *rpc);
+ if (!rpc) {
+ ERRMEM;
+ return NULL;
+ }
+
+ rpc->type = NC_RPC_EDITDATA;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->datastore = strdup(datastore);
+ } else {
+ rpc->datastore = (char *)datastore;
+ }
+ rpc->default_op = default_op;
+ if (paramtype == NC_PARAMTYPE_DUP_AND_FREE) {
+ rpc->edit_cont = strdup(edit_content);
+ } else {
+ rpc->edit_cont = (char *)edit_content;
+ }
+ rpc->free = (paramtype == NC_PARAMTYPE_CONST ? 0 : 1);
+
+ return (struct nc_rpc *)rpc;
+}
+
API void
nc_rpc_free(struct nc_rpc *rpc)
{
@@ -528,6 +638,9 @@
struct nc_rpc_validate *rpc_validate;
struct nc_rpc_getschema *rpc_getschema;
struct nc_rpc_subscribe *rpc_subscribe;
+ struct nc_rpc_getdata *rpc_getdata;
+ struct nc_rpc_editdata *rpc_editdata;
+ int i;
if (!rpc) {
return;
@@ -611,6 +724,25 @@
free(rpc_subscribe->stop);
}
break;
+ case NC_RPC_GETDATA:
+ rpc_getdata = (struct nc_rpc_getdata *)rpc;
+ if (rpc_getdata->free) {
+ free(rpc_getdata->datastore);
+ free(rpc_getdata->filter);
+ free(rpc_getdata->config_filter);
+ for (i = 0; i < rpc_getdata->origin_filter_count; ++i) {
+ free(rpc_getdata->origin_filter[i]);
+ }
+ free(rpc_getdata->origin_filter);
+ }
+ break;
+ case NC_RPC_EDITDATA:
+ rpc_editdata = (struct nc_rpc_editdata *)rpc;
+ if (rpc_editdata->free) {
+ free(rpc_editdata->datastore);
+ free(rpc_editdata->edit_cont);
+ }
+ break;
default:
/* nothing special needed */
break;
diff --git a/src/messages_client.h b/src/messages_client.h
index f597ee6..33df282 100644
--- a/src/messages_client.h
+++ b/src/messages_client.h
@@ -59,7 +59,11 @@
NC_RPC_GETSCHEMA, /**< \<get-schema\> RPC. */
/* notifications */
- NC_RPC_SUBSCRIBE /**< \<create-subscription\> RPC. */
+ NC_RPC_SUBSCRIBE, /**< \<create-subscription\> RPC. */
+
+ /* ietf-netconf-nmda */
+ NC_RPC_GETDATA, /**< \<get-data\> RPC. */
+ NC_RPC_EDITDATA, /**< \<edit-data\> RPC. */
} NC_RPC_TYPE;
/**
@@ -443,6 +447,49 @@
const char *stop_time, NC_PARAMTYPE paramtype);
/**
+ * @brief Create NETCONF RPC \<get-data\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] filter Optional filter data, an XML subtree or XPath expression (with JSON prefixes).
+ * @param[in] config_filter Optional config filter, "true" for config-only data, "false" for state-only data.
+ * @param[in] origin_filter Optional origin filter array, selects only nodes of this or derived origin.
+ * @param[in] origin_filter_count Count of filters is \p origin_filter.
+ * @param[in] neg_origin_filter Whether origin filters are negated or not.
+ * @param[in] max_depth Maximum depth of returned subtrees, 0 for unlimited.
+ * @param[in] with_origin Whether return data origin.
+ * @param[in] wd_mode Optional with-defaults capability mode.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_getdata(const char *datastore, const char *filter, const char *config_filter, char **origin_filter,
+ int origin_filter_count, int neg_origin_filter, uint16_t max_depth, int with_origin,
+ NC_WD_MODE wd_mode, NC_PARAMTYPE paramtype);
+
+/**
+ * @brief Create NETCONF RPC \<get-data\>
+ *
+ * Note that functions to create any RPC object do not check validity of the provided
+ * parameters. It is checked later while sending the RPC via a specific NETCONF session
+ * (#nc_send_rpc()) since the NETCONF capabilities of the session are needed for such a
+ * check. Created object can be sent via any NETCONF session which supports all the
+ * needed NETCONF capabilities for the RPC.
+ *
+ * @param[in] datastore Source datastore, foreign identity so a module name prefix is required.
+ * @param[in] default_op Optional default operation.
+ * @param[in] edit_content Config or URL where the config to perform is to be found.
+ * @param[in] paramtype How to further manage data parameters.
+ * @return Created RPC object to send via a NETCONF session or NULL in case of (memory allocation) error.
+ */
+struct nc_rpc *nc_rpc_editdata(const char *datastore, NC_RPC_EDIT_DFLTOP default_op, const char *edit_content,
+ NC_PARAMTYPE paramtype);
+
+/**
* @brief Free the NETCONF RPC object.
*
* @param[in] rpc Object to free.
diff --git a/src/messages_p.h b/src/messages_p.h
index a4b04b6..9825203 100644
--- a/src/messages_p.h
+++ b/src/messages_p.h
@@ -186,6 +186,28 @@
char free;
};
+struct nc_rpc_getdata {
+ NC_RPC_TYPE type; /**< NC_RPC_GETDATA */
+ char *datastore; /**< target datastore identity */
+ char *filter; /**< either XML subtree (starts with '<') or an XPath (starts with '/' or an alpha) */
+ char *config_filter; /**< config filter ("true"/"false") */
+ char **origin_filter; /**< origin filters */
+ int origin_filter_count; /**< origin filter count */
+ int negated_origin_filter; /**< whether origin filter is negated or not */
+ int max_depth; /**< max depth of returned subtrees, 0 for unlimited */
+ int with_origin; /**< whether to return origin of data */
+ NC_WD_MODE wd_mode;
+ char free;
+};
+
+struct nc_rpc_editdata {
+ NC_RPC_TYPE type; /**< NC_RPC_EDITDATA */
+ char *datastore; /**< target datastore identity */
+ NC_RPC_EDIT_DFLTOP default_op;
+ char *edit_cont; /**< either URL (starts with aplha) or config (starts with '<') */
+ char free;
+};
+
void nc_server_rpc_free(struct nc_server_rpc *rpc, struct ly_ctx *ctx);
void nc_client_err_clean(struct nc_err *err, struct ly_ctx *ctx);
diff --git a/src/session_client.c b/src/session_client.c
index caf1947..83abb92 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -1752,6 +1752,7 @@
case NC_RPC_GETCONFIG:
case NC_RPC_GET:
+ case NC_RPC_GETDATA:
/* we should definitely have received at least an empty "data" element even on empty reply, but fine */
if (!xml->child || !xml->child->child) {
/* we did not receive any data */
@@ -1796,6 +1797,7 @@
case NC_RPC_CANCEL:
case NC_RPC_VALIDATE:
case NC_RPC_SUBSCRIBE:
+ case NC_RPC_EDITDATA:
/* there is no output defined */
ERR("Unexpected data reply (root elem \"%s\").", xml->child ? xml->child->name : NULL);
return NULL;
@@ -1823,7 +1825,7 @@
return NULL;
}
} else {
- /* <get>, <get-config> */
+ /* <get>, <get-config>, <get-data> */
data_rpl->data = data;
}
lyd_free_withsiblings(rpc_act);
@@ -2260,8 +2262,11 @@
struct nc_rpc_validate *rpc_val;
struct nc_rpc_getschema *rpc_gs;
struct nc_rpc_subscribe *rpc_sub;
+ struct nc_rpc_getdata *rpc_getd;
+ struct nc_rpc_editdata *rpc_editd;
struct lyd_node *data, *node;
- const struct lys_module *ietfnc = NULL, *ietfncmon, *notifs, *ietfncwd = NULL;
+ const struct lys_module *mod = NULL, *ietfncwd;
+ int i;
char str[11];
uint64_t cur_msgid;
@@ -2279,12 +2284,53 @@
return NC_MSG_ERROR;
}
- if ((rpc->type != NC_RPC_GETSCHEMA) && (rpc->type != NC_RPC_ACT_GENERIC) && (rpc->type != NC_RPC_SUBSCRIBE)) {
- ietfnc = ly_ctx_get_module(session->ctx, "ietf-netconf", NULL, 1);
- if (!ietfnc) {
+ switch (rpc->type) {
+ case NC_RPC_ACT_GENERIC:
+ /* checked when parsing */
+ break;
+ case NC_RPC_GETCONFIG:
+ case NC_RPC_EDIT:
+ case NC_RPC_COPY:
+ case NC_RPC_DELETE:
+ case NC_RPC_LOCK:
+ case NC_RPC_UNLOCK:
+ case NC_RPC_GET:
+ case NC_RPC_KILL:
+ case NC_RPC_COMMIT:
+ case NC_RPC_DISCARD:
+ case NC_RPC_CANCEL:
+ case NC_RPC_VALIDATE:
+ mod = ly_ctx_get_module(session->ctx, "ietf-netconf", NULL, 1);
+ if (!mod) {
ERR("Session %u: missing \"ietf-netconf\" schema in the context.", session->id);
return NC_MSG_ERROR;
}
+ break;
+ case NC_RPC_GETSCHEMA:
+ mod = ly_ctx_get_module(session->ctx, "ietf-netconf-monitoring", NULL, 1);
+ if (!mod) {
+ ERR("Session %u: missing \"ietf-netconf-monitoring\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ break;
+ case NC_RPC_SUBSCRIBE:
+ mod = ly_ctx_get_module(session->ctx, "notifications", NULL, 1);
+ if (!mod) {
+ ERR("Session %u: missing \"notifications\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ break;
+ case NC_RPC_GETDATA:
+ case NC_RPC_EDITDATA:
+ mod = ly_ctx_get_module(session->ctx, "ietf-netconf-nmda", NULL, 1);
+ if (!mod) {
+ ERR("Session %u: missing \"ietf-netconf-nmda\" schema in the context.", session->id);
+ return NC_MSG_ERROR;
+ }
+ break;
+ case NC_RPC_UNKNOWN:
+ ERRINT;
+ return NC_MSG_ERROR;
}
switch (rpc->type) {
@@ -2306,19 +2352,19 @@
case NC_RPC_GETCONFIG:
rpc_gc = (struct nc_rpc_getconfig *)rpc;
- data = lyd_new(NULL, ietfnc, "get-config");
- node = lyd_new(data, ietfnc, "source");
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_gc->source], NULL);
+ data = lyd_new(NULL, mod, "get-config");
+ node = lyd_new(data, mod, "source");
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_gc->source], NULL);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
if (rpc_gc->filter) {
if (!rpc_gc->filter[0] || (rpc_gc->filter[0] == '<')) {
- node = lyd_new_anydata(data, ietfnc, "filter", rpc_gc->filter, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(data, mod, "filter", rpc_gc->filter, LYD_ANYDATA_SXML);
lyd_insert_attr(node, NULL, "type", "subtree");
} else {
- node = lyd_new_anydata(data, ietfnc, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
+ node = lyd_new_anydata(data, mod, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
lyd_insert_attr(node, NULL, "type", "xpath");
lyd_insert_attr(node, NULL, "select", rpc_gc->filter);
}
@@ -2329,12 +2375,11 @@
}
if (rpc_gc->wd_mode) {
+ ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
if (!ietfncwd) {
- ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
- if (!ietfncwd) {
- ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
- return NC_MSG_ERROR;
- }
+ ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
+ lyd_free(data);
+ return NC_MSG_ERROR;
}
switch (rpc_gc->wd_mode) {
case NC_WD_UNKNOWN:
@@ -2363,16 +2408,16 @@
case NC_RPC_EDIT:
rpc_e = (struct nc_rpc_edit *)rpc;
- data = lyd_new(NULL, ietfnc, "edit-config");
- node = lyd_new(data, ietfnc, "target");
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_e->target], NULL);
+ data = lyd_new(NULL, mod, "edit-config");
+ node = lyd_new(data, mod, "target");
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_e->target], NULL);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
if (rpc_e->default_op) {
- node = lyd_new_leaf(data, ietfnc, "default-operation", rpcedit_dfltop2str[rpc_e->default_op]);
+ node = lyd_new_leaf(data, mod, "default-operation", rpcedit_dfltop2str[rpc_e->default_op]);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2380,7 +2425,7 @@
}
if (rpc_e->test_opt) {
- node = lyd_new_leaf(data, ietfnc, "test-option", rpcedit_testopt2str[rpc_e->test_opt]);
+ node = lyd_new_leaf(data, mod, "test-option", rpcedit_testopt2str[rpc_e->test_opt]);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2388,7 +2433,7 @@
}
if (rpc_e->error_opt) {
- node = lyd_new_leaf(data, ietfnc, "error-option", rpcedit_erropt2str[rpc_e->error_opt]);
+ node = lyd_new_leaf(data, mod, "error-option", rpcedit_erropt2str[rpc_e->error_opt]);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2396,9 +2441,9 @@
}
if (!rpc_e->edit_cont[0] || (rpc_e->edit_cont[0] == '<')) {
- node = lyd_new_anydata(data, ietfnc, "config", rpc_e->edit_cont, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(data, mod, "config", rpc_e->edit_cont, LYD_ANYDATA_SXML);
} else {
- node = lyd_new_leaf(data, ietfnc, "url", rpc_e->edit_cont);
+ node = lyd_new_leaf(data, mod, "url", rpc_e->edit_cont);
}
if (!node) {
lyd_free(data);
@@ -2409,27 +2454,27 @@
case NC_RPC_COPY:
rpc_cp = (struct nc_rpc_copy *)rpc;
- data = lyd_new(NULL, ietfnc, "copy-config");
- node = lyd_new(data, ietfnc, "target");
+ data = lyd_new(NULL, mod, "copy-config");
+ node = lyd_new(data, mod, "target");
if (rpc_cp->url_trg) {
- node = lyd_new_leaf(node, ietfnc, "url", rpc_cp->url_trg);
+ node = lyd_new_leaf(node, mod, "url", rpc_cp->url_trg);
} else {
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_cp->target], NULL);
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_cp->target], NULL);
}
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
- node = lyd_new(data, ietfnc, "source");
+ node = lyd_new(data, mod, "source");
if (rpc_cp->url_config_src) {
if (!rpc_cp->url_config_src[0] || (rpc_cp->url_config_src[0] == '<')) {
- node = lyd_new_anydata(node, ietfnc, "config", rpc_cp->url_config_src, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(node, mod, "config", rpc_cp->url_config_src, LYD_ANYDATA_SXML);
} else {
- node = lyd_new_leaf(node, ietfnc, "url", rpc_cp->url_config_src);
+ node = lyd_new_leaf(node, mod, "url", rpc_cp->url_config_src);
}
} else {
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_cp->source], NULL);
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_cp->source], NULL);
}
if (!node) {
lyd_free(data);
@@ -2437,12 +2482,11 @@
}
if (rpc_cp->wd_mode) {
+ ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
if (!ietfncwd) {
- ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
- if (!ietfncwd) {
- ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
- return NC_MSG_ERROR;
- }
+ ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
+ lyd_free(data);
+ return NC_MSG_ERROR;
}
switch (rpc_cp->wd_mode) {
case NC_WD_UNKNOWN:
@@ -2471,12 +2515,12 @@
case NC_RPC_DELETE:
rpc_del = (struct nc_rpc_delete *)rpc;
- data = lyd_new(NULL, ietfnc, "delete-config");
- node = lyd_new(data, ietfnc, "target");
+ data = lyd_new(NULL, mod, "delete-config");
+ node = lyd_new(data, mod, "target");
if (rpc_del->url) {
- node = lyd_new_leaf(node, ietfnc, "url", rpc_del->url);
+ node = lyd_new_leaf(node, mod, "url", rpc_del->url);
} else {
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_del->target], NULL);
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_del->target], NULL);
}
if (!node) {
lyd_free(data);
@@ -2487,9 +2531,9 @@
case NC_RPC_LOCK:
rpc_lock = (struct nc_rpc_lock *)rpc;
- data = lyd_new(NULL, ietfnc, "lock");
- node = lyd_new(data, ietfnc, "target");
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_lock->target], NULL);
+ data = lyd_new(NULL, mod, "lock");
+ node = lyd_new(data, mod, "target");
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_lock->target], NULL);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2499,9 +2543,9 @@
case NC_RPC_UNLOCK:
rpc_lock = (struct nc_rpc_lock *)rpc;
- data = lyd_new(NULL, ietfnc, "unlock");
- node = lyd_new(data, ietfnc, "target");
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_lock->target], NULL);
+ data = lyd_new(NULL, mod, "unlock");
+ node = lyd_new(data, mod, "target");
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_lock->target], NULL);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2511,13 +2555,13 @@
case NC_RPC_GET:
rpc_g = (struct nc_rpc_get *)rpc;
- data = lyd_new(NULL, ietfnc, "get");
+ data = lyd_new(NULL, mod, "get");
if (rpc_g->filter) {
if (!rpc_g->filter[0] || (rpc_g->filter[0] == '<')) {
- node = lyd_new_anydata(data, ietfnc, "filter", rpc_g->filter, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(data, mod, "filter", rpc_g->filter, LYD_ANYDATA_SXML);
lyd_insert_attr(node, NULL, "type", "subtree");
} else {
- node = lyd_new_anydata(data, ietfnc, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
+ node = lyd_new_anydata(data, mod, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
lyd_insert_attr(node, NULL, "type", "xpath");
lyd_insert_attr(node, NULL, "select", rpc_g->filter);
}
@@ -2528,13 +2572,11 @@
}
if (rpc_g->wd_mode) {
+ ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
if (!ietfncwd) {
- ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
- if (!ietfncwd) {
- ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
- lyd_free(data);
- return NC_MSG_ERROR;
- }
+ ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
+ lyd_free(data);
+ return NC_MSG_ERROR;
}
switch (rpc_g->wd_mode) {
case NC_WD_ALL:
@@ -2564,26 +2606,26 @@
case NC_RPC_KILL:
rpc_k = (struct nc_rpc_kill *)rpc;
- data = lyd_new(NULL, ietfnc, "kill-session");
+ data = lyd_new(NULL, mod, "kill-session");
sprintf(str, "%u", rpc_k->sid);
- lyd_new_leaf(data, ietfnc, "session-id", str);
+ lyd_new_leaf(data, mod, "session-id", str);
break;
case NC_RPC_COMMIT:
rpc_com = (struct nc_rpc_commit *)rpc;
- data = lyd_new(NULL, ietfnc, "commit");
+ data = lyd_new(NULL, mod, "commit");
if (rpc_com->confirmed) {
- lyd_new_leaf(data, ietfnc, "confirmed", NULL);
+ lyd_new_leaf(data, mod, "confirmed", NULL);
}
if (rpc_com->confirm_timeout) {
sprintf(str, "%u", rpc_com->confirm_timeout);
- lyd_new_leaf(data, ietfnc, "confirm-timeout", str);
+ lyd_new_leaf(data, mod, "confirm-timeout", str);
}
if (rpc_com->persist) {
- node = lyd_new_leaf(data, ietfnc, "persist", rpc_com->persist);
+ node = lyd_new_leaf(data, mod, "persist", rpc_com->persist);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2591,7 +2633,7 @@
}
if (rpc_com->persist_id) {
- node = lyd_new_leaf(data, ietfnc, "persist-id", rpc_com->persist_id);
+ node = lyd_new_leaf(data, mod, "persist-id", rpc_com->persist_id);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2600,15 +2642,15 @@
break;
case NC_RPC_DISCARD:
- data = lyd_new(NULL, ietfnc, "discard-changes");
+ data = lyd_new(NULL, mod, "discard-changes");
break;
case NC_RPC_CANCEL:
rpc_can = (struct nc_rpc_cancel *)rpc;
- data = lyd_new(NULL, ietfnc, "cancel-commit");
+ data = lyd_new(NULL, mod, "cancel-commit");
if (rpc_can->persist_id) {
- node = lyd_new_leaf(data, ietfnc, "persist-id", rpc_can->persist_id);
+ node = lyd_new_leaf(data, mod, "persist-id", rpc_can->persist_id);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2619,16 +2661,16 @@
case NC_RPC_VALIDATE:
rpc_val = (struct nc_rpc_validate *)rpc;
- data = lyd_new(NULL, ietfnc, "validate");
- node = lyd_new(data, ietfnc, "source");
+ data = lyd_new(NULL, mod, "validate");
+ node = lyd_new(data, mod, "source");
if (rpc_val->url_config_src) {
if (!rpc_val->url_config_src[0] || (rpc_val->url_config_src[0] == '<')) {
- node = lyd_new_anydata(node, ietfnc, "config", rpc_val->url_config_src, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(node, mod, "config", rpc_val->url_config_src, LYD_ANYDATA_SXML);
} else {
- node = lyd_new_leaf(node, ietfnc, "url", rpc_val->url_config_src);
+ node = lyd_new_leaf(node, mod, "url", rpc_val->url_config_src);
}
} else {
- node = lyd_new_leaf(node, ietfnc, ncds2str[rpc_val->source], NULL);
+ node = lyd_new_leaf(node, mod, ncds2str[rpc_val->source], NULL);
}
if (!node) {
lyd_free(data);
@@ -2637,29 +2679,23 @@
break;
case NC_RPC_GETSCHEMA:
- ietfncmon = ly_ctx_get_module(session->ctx, "ietf-netconf-monitoring", NULL, 1);
- if (!ietfncmon) {
- ERR("Session %u: missing \"ietf-netconf-monitoring\" schema in the context.", session->id);
- return NC_MSG_ERROR;
- }
-
rpc_gs = (struct nc_rpc_getschema *)rpc;
- data = lyd_new(NULL, ietfncmon, "get-schema");
- node = lyd_new_leaf(data, ietfncmon, "identifier", rpc_gs->identifier);
+ data = lyd_new(NULL, mod, "get-schema");
+ node = lyd_new_leaf(data, mod, "identifier", rpc_gs->identifier);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
if (rpc_gs->version) {
- node = lyd_new_leaf(data, ietfncmon, "version", rpc_gs->version);
+ node = lyd_new_leaf(data, mod, "version", rpc_gs->version);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
}
if (rpc_gs->format) {
- node = lyd_new_leaf(data, ietfncmon, "format", rpc_gs->format);
+ node = lyd_new_leaf(data, mod, "format", rpc_gs->format);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2668,17 +2704,11 @@
break;
case NC_RPC_SUBSCRIBE:
- notifs = ly_ctx_get_module(session->ctx, "notifications", NULL, 1);
- if (!notifs) {
- ERR("Session %u: missing \"notifications\" schema in the context.", session->id);
- return NC_MSG_ERROR;
- }
-
rpc_sub = (struct nc_rpc_subscribe *)rpc;
- data = lyd_new(NULL, notifs, "create-subscription");
+ data = lyd_new(NULL, mod, "create-subscription");
if (rpc_sub->stream) {
- node = lyd_new_leaf(data, notifs, "stream", rpc_sub->stream);
+ node = lyd_new_leaf(data, mod, "stream", rpc_sub->stream);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2687,10 +2717,10 @@
if (rpc_sub->filter) {
if (!rpc_sub->filter[0] || (rpc_sub->filter[0] == '<')) {
- node = lyd_new_anydata(data, notifs, "filter", rpc_sub->filter, LYD_ANYDATA_SXML);
+ node = lyd_new_anydata(data, mod, "filter", rpc_sub->filter, LYD_ANYDATA_SXML);
lyd_insert_attr(node, NULL, "type", "subtree");
} else {
- node = lyd_new_anydata(data, notifs, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
+ node = lyd_new_anydata(data, mod, "filter", NULL, LYD_ANYDATA_CONSTSTRING);
lyd_insert_attr(node, NULL, "type", "xpath");
lyd_insert_attr(node, NULL, "select", rpc_sub->filter);
}
@@ -2701,7 +2731,7 @@
}
if (rpc_sub->start) {
- node = lyd_new_leaf(data, notifs, "startTime", rpc_sub->start);
+ node = lyd_new_leaf(data, mod, "startTime", rpc_sub->start);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
@@ -2709,13 +2739,125 @@
}
if (rpc_sub->stop) {
- node = lyd_new_leaf(data, notifs, "stopTime", rpc_sub->stop);
+ node = lyd_new_leaf(data, mod, "stopTime", rpc_sub->stop);
if (!node) {
lyd_free(data);
return NC_MSG_ERROR;
}
}
break;
+
+ case NC_RPC_GETDATA:
+ rpc_getd = (struct nc_rpc_getdata *)rpc;
+
+ data = lyd_new(NULL, mod, "get-data");
+ node = lyd_new_leaf(data, mod, "datastore", rpc_getd->datastore);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ if (rpc_getd->filter) {
+ if (!rpc_getd->filter[0] || (rpc_getd->filter[0] == '<')) {
+ node = lyd_new_anydata(data, mod, "subtree-filter", rpc_getd->filter, LYD_ANYDATA_SXML);
+ } else {
+ node = lyd_new_leaf(data, mod, "xpath-filter", rpc_getd->filter);
+ }
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ if (rpc_getd->config_filter) {
+ node = lyd_new_leaf(data, mod, "config-filter", rpc_getd->config_filter);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ for (i = 0; i < rpc_getd->origin_filter_count; ++i) {
+ node = lyd_new_leaf(data, mod, rpc_getd->negated_origin_filter ? "negated-origin-filter" : "origin-filter",
+ rpc_getd->origin_filter[i]);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ if (rpc_getd->max_depth) {
+ sprintf(str, "%u", rpc_getd->max_depth);
+ node = lyd_new_leaf(data, mod, "max-depth", str);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ if (rpc_getd->with_origin) {
+ node = lyd_new_leaf(data, mod, "with-origin", NULL);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (rpc_getd->wd_mode) {
+ ietfncwd = ly_ctx_get_module(session->ctx, "ietf-netconf-with-defaults", NULL, 1);
+ if (!ietfncwd) {
+ ERR("Session %u: missing \"ietf-netconf-with-defaults\" schema in the context.", session->id);
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ switch (rpc_getd->wd_mode) {
+ case NC_WD_UNKNOWN:
+ /* cannot get here */
+ break;
+ case NC_WD_ALL:
+ node = lyd_new_leaf(data, ietfncwd, "with-defaults", "report-all");
+ break;
+ case NC_WD_ALL_TAG:
+ node = lyd_new_leaf(data, ietfncwd, "with-defaults", "report-all-tagged");
+ break;
+ case NC_WD_TRIM:
+ node = lyd_new_leaf(data, ietfncwd, "with-defaults", "trim");
+ break;
+ case NC_WD_EXPLICIT:
+ node = lyd_new_leaf(data, ietfncwd, "with-defaults", "explicit");
+ break;
+ }
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+ break;
+
+ case NC_RPC_EDITDATA:
+ rpc_editd = (struct nc_rpc_editdata *)rpc;
+
+ data = lyd_new(NULL, mod, "edit-data");
+ node = lyd_new_leaf(data, mod, "datastore", rpc_editd->datastore);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+
+ if (rpc_editd->default_op) {
+ node = lyd_new_leaf(data, mod, "default-operation", rpcedit_dfltop2str[rpc_editd->default_op]);
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ }
+
+ if (!rpc_editd->edit_cont[0] || (rpc_editd->edit_cont[0] == '<')) {
+ node = lyd_new_anydata(data, mod, "config", rpc_editd->edit_cont, LYD_ANYDATA_SXML);
+ } else {
+ node = lyd_new_leaf(data, mod, "url", rpc_editd->edit_cont);
+ }
+ if (!node) {
+ lyd_free(data);
+ return NC_MSG_ERROR;
+ }
+ break;
+
default:
ERRINT;
return NC_MSG_ERROR;