Moved with-defaults processing from get(-config) to xmldb_get when reading db
With-defaults: fixed cornercase in xpath used in list pagination C-API: Added `with-defaults` parameter (default 0) to `xmldb_get0()`
This commit is contained in:
parent
e885d63f68
commit
0d41d49fa9
19 changed files with 420 additions and 196 deletions
|
|
@ -51,6 +51,7 @@ Developers may need to change their code
|
|||
* Added netconf ssh subsystem
|
||||
* Renamed from `clixon` built in `docker/base`
|
||||
* C-API
|
||||
* Added `with-defaults` parameter (default 0) to `xmldb_get0()`
|
||||
* Added `sock_flags` parameter to `clixon_proc_socket()`
|
||||
|
||||
### Minor features
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ startup_common(clicon_handle h,
|
|||
* It is done below, later in this function
|
||||
*/
|
||||
if (clicon_option_bool(h, "CLICON_XMLDB_UPGRADE_CHECKOLD")){
|
||||
if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &xt, msdiff, &xerr)) < 0)
|
||||
if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &xt, msdiff, &xerr)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){ /* ret should not be 0 */
|
||||
/* Print upgraded db: -q backend switch for debugging/ showing upgraded config only */
|
||||
|
|
@ -197,7 +197,7 @@ startup_common(clicon_handle h,
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, &xt, msdiff, &xerr) < 0)
|
||||
if (xmldb_get0(h, db, YB_NONE, NULL, "/", 0, 0, &xt, msdiff, &xerr) < 0)
|
||||
goto done;
|
||||
}
|
||||
if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE
|
||||
|
|
@ -488,7 +488,7 @@ validate_common(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
/* This is the state we are going to */
|
||||
if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &td->td_target, NULL, xret)) < 0)
|
||||
if ((ret = xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -497,7 +497,7 @@ validate_common(clicon_handle h,
|
|||
(void*)(XML_FLAG_MARK|XML_FLAG_CHANGE));
|
||||
/* 2. Parse xml trees
|
||||
* This is the state we are going from */
|
||||
if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, &td->td_src, NULL, xret)) < 0)
|
||||
if ((ret = xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
|
|
@ -960,7 +960,7 @@ from_client_restart_one(clicon_handle h,
|
|||
if ((td = transaction_new()) == NULL)
|
||||
goto done;
|
||||
/* This is the state we are going to */
|
||||
if (xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, &td->td_target, NULL, NULL) < 0)
|
||||
if (xmldb_get0(h, "running", YB_MODULE, NULL, "/", 0, 0, &td->td_target, NULL, NULL) < 0)
|
||||
goto done;
|
||||
if ((ret = xml_yang_validate_all_top(h, td->td_target, &xerr)) < 0)
|
||||
goto done;
|
||||
|
|
@ -970,7 +970,7 @@ from_client_restart_one(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
/* This is the state we are going from */
|
||||
if (xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, &td->td_src, NULL, NULL) < 0)
|
||||
if (xmldb_get0(h, db, YB_MODULE, NULL, "/", 0, 0, &td->td_src, NULL, NULL) < 0)
|
||||
goto done;
|
||||
|
||||
/* 3. Compute differences */
|
||||
|
|
|
|||
|
|
@ -180,6 +180,7 @@ client_get_streams(clicon_handle h,
|
|||
* @param[in] h Clicon handle
|
||||
* @param[in] xpath XPath selection, may be used to filter early
|
||||
* @param[in] nsc XML Namespace context for xpath
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[in,out] xret Existing XML tree, merge x into this
|
||||
* @retval -1 Error (fatal)
|
||||
* @retval 0 Statedata callback failed (clicon_err called)
|
||||
|
|
@ -189,6 +190,7 @@ static int
|
|||
get_client_statedata(clicon_handle h,
|
||||
char *xpath,
|
||||
cvec *nsc,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -258,16 +260,63 @@ get_client_statedata(clicon_handle h,
|
|||
goto fail;
|
||||
}
|
||||
/* Use plugin state callbacks */
|
||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, xret)) < 0)
|
||||
if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, wdef, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
goto fail;
|
||||
/* Add default state to config if present */
|
||||
if (xml_default_recurse(*xret, 1) < 0)
|
||||
goto done;
|
||||
/* Add default global state */
|
||||
switch (wdef){
|
||||
case WITHDEFAULTS_REPORT_ALL:
|
||||
case WITHDEFAULTS_EXPLICIT:
|
||||
/* Add global defaults. */
|
||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
||||
goto done;
|
||||
/* Apply default values */
|
||||
if (xml_default_recurse(*xret, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_TRIM:
|
||||
/* Mark and remove nodes having schema default values */
|
||||
if (xml_apply((*xret), CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flags((*xret), XML_FLAG_MARK, XML_FLAG_MARK)
|
||||
< 0)
|
||||
goto done;
|
||||
if (xml_defaults_nopresence((*xret), 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
||||
cxobj *xc;
|
||||
char *ns;
|
||||
/* Add global defaults. */
|
||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
||||
goto done;
|
||||
/* Apply default values */
|
||||
if (xml_default_recurse(*xret, 1) < 0)
|
||||
goto done;
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each((*xret), xc, CX_ELMNT)) != NULL){
|
||||
/* Check if exists */
|
||||
ns = NULL;
|
||||
if (xml2ns(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||
goto done;
|
||||
if (ns == NULL){
|
||||
if (xmlns_set(xc, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Mark nodes having default schema values */
|
||||
if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_state_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add tag attributes to default nodes */
|
||||
if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
} /* switch wdef */
|
||||
retval = 1; /* OK */
|
||||
done:
|
||||
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||
|
|
@ -416,141 +465,6 @@ element2value(clicon_handle h,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*! Set flag on node having schema default value.
|
||||
* @param[in] x XML node
|
||||
* @param[in] flag Flag to be used
|
||||
* @retval 0 OK
|
||||
*/
|
||||
static int
|
||||
xml_flag_default_value(cxobj *x,
|
||||
uint16_t flag)
|
||||
{
|
||||
yang_stmt *y;
|
||||
cg_var *cv;
|
||||
char *yv;
|
||||
char *xv;
|
||||
|
||||
xml_flag_reset(x, flag); /* Assume not default value */
|
||||
if ((xv = xml_body(x)) == NULL)
|
||||
goto done;
|
||||
if ((y = xml_spec(x)) == NULL)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if (cv_name_get(cv) == NULL)
|
||||
goto done;
|
||||
if ((yv = cv2str_dup(cv)) == NULL)
|
||||
goto done;
|
||||
if (strcmp(xv, yv) == 0)
|
||||
xml_flag_set(x, flag); /* Actual value same as default value */
|
||||
free(yv);
|
||||
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Add default attribute to node with default value.
|
||||
* @param[in] x XML node
|
||||
* @param[in] flags Flags indicatiing default nodes
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
xml_add_default_tag(cxobj *x,
|
||||
uint16_t flags)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xattr;
|
||||
|
||||
if (xml_flag(x, flags)) {
|
||||
/* set default attribute */
|
||||
if ((xattr = xml_new("default", x, CX_ATTR)) == NULL)
|
||||
goto done;
|
||||
if (xml_value_set(xattr, "true") < 0)
|
||||
goto done;
|
||||
if (xml_prefix_set(xattr, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Update XML return tree according to RFC6243: with-defaults
|
||||
* @param[in] xe Request: <rpc><xn></rpc>
|
||||
* @param[in] xret XML return tree to be updated
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
with_defaults(cxobj *xe,
|
||||
cxobj *xret)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xfind;
|
||||
char *mode;
|
||||
cxobj *x;
|
||||
|
||||
if ((xfind = xml_find(xe, "with-defaults")) != NULL) {
|
||||
if ((mode = xml_find_value(xfind, "body")) == NULL)
|
||||
goto done;
|
||||
|
||||
if (strcmp(mode, "explicit") == 0) {
|
||||
/* Clear marked nodes */
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_reset,(void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Mark state nodes */
|
||||
if (xml_non_config_data(xret, NULL) < 0)
|
||||
goto done;
|
||||
/* Remove default configuration nodes */
|
||||
if (xml_tree_prune_flags(xret, XML_FLAG_DEFAULT, XML_FLAG_MARK | XML_FLAG_DEFAULT) < 0)
|
||||
goto done;
|
||||
/* Remove empty containers */
|
||||
if (xml_defaults_nopresence(xret, 1) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else if (strcmp(mode, "trim") == 0) {
|
||||
/* Remove default nodes from XML */
|
||||
if (xml_tree_prune_flags(xret, XML_FLAG_DEFAULT, XML_FLAG_DEFAULT) < 0)
|
||||
goto done;
|
||||
/* Mark and remove nodes having schema default values */
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flags(xret, XML_FLAG_MARK, XML_FLAG_MARK)
|
||||
< 0)
|
||||
goto done;
|
||||
/* Remove empty containers */
|
||||
if (xml_defaults_nopresence(xret, 1) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else if (strcmp(mode, "report-all-tagged") == 0) {
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(xret, x, CX_ELMNT)) != NULL)
|
||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||
goto done;
|
||||
/* Mark nodes having default schema values */
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add tag attributes to default nodes */
|
||||
if (xml_apply(xret, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
else if (strcmp(mode, "report-all") == 0) {
|
||||
/* Accept mode, do nothing */
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Extract offset and limit from get/list-pagination
|
||||
*
|
||||
* @param[in] h Clicon handle
|
||||
|
|
@ -592,6 +506,8 @@ list_pagination_hdr(clicon_handle h,
|
|||
* @param[in] db Database name
|
||||
* @param[in] xpath XPath point to object to get
|
||||
* @param[in] nsc Namespace context of xpath
|
||||
* @param[in] username
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
|
|
@ -610,6 +526,7 @@ get_list_pagination(clicon_handle h,
|
|||
char *xpath,
|
||||
cvec *nsc,
|
||||
char *username,
|
||||
withdefaults_type wdef,
|
||||
cbuf *cbret
|
||||
)
|
||||
{
|
||||
|
|
@ -733,7 +650,7 @@ get_list_pagination(clicon_handle h,
|
|||
/* Append predicate to original xpath and replace it */
|
||||
xpath2 = cbuf_get(cbpath);
|
||||
/* specific xpath */
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, &xret, NULL, NULL) < 0) {
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath2?xpath2:"/", 1, wdef, &xret, NULL, NULL) < 0) {
|
||||
if ((cbmsg = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
|
|
@ -803,8 +720,6 @@ get_list_pagination(clicon_handle h,
|
|||
goto ok;
|
||||
}
|
||||
}
|
||||
if (with_defaults(xml_parent(xe), xret) < 0)
|
||||
goto done;
|
||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||
goto done;
|
||||
/* Help function to filter out anything that is outside of xpath */
|
||||
|
|
@ -900,6 +815,8 @@ get_common(clicon_handle h,
|
|||
cxobj *xfind;
|
||||
uint32_t offset = 0;
|
||||
uint32_t limit = 0;
|
||||
withdefaults_type wdef = WITHDEFAULTS_REPORT_ALL;
|
||||
char *wdefstr;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
username = clicon_username_get(h);
|
||||
|
|
@ -939,6 +856,8 @@ get_common(clicon_handle h,
|
|||
goto ok;
|
||||
}
|
||||
}
|
||||
if ((wdefstr = xml_find_body(xe, "with-defaults")) != NULL)
|
||||
wdef = withdefaults_str2int(wdefstr);
|
||||
/* Check if list pagination */
|
||||
if ((xfind = xml_find_type(xe, NULL, "list-pagination", CX_ELMNT)) != NULL){
|
||||
/* with non-presence list-pagination, use ad-hoc algorithm to determine
|
||||
|
|
@ -962,7 +881,7 @@ get_common(clicon_handle h,
|
|||
if (get_list_pagination(h, ce,
|
||||
xfind,
|
||||
content, db,
|
||||
depth, yspec, xpath, nsc, username,
|
||||
depth, yspec, xpath, nsc, username, wdef,
|
||||
cbret) < 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
|
|
@ -971,7 +890,7 @@ get_common(clicon_handle h,
|
|||
switch (content){
|
||||
case CONTENT_CONFIG: /* config data only */
|
||||
/* specific xpath */
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath?xpath:"/", 1, &xret, NULL, NULL) < 0) {
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath?xpath:"/", 1, wdef, &xret, NULL, NULL) < 0) {
|
||||
if ((cbmsg = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
|
|
@ -986,7 +905,7 @@ get_common(clicon_handle h,
|
|||
case CONTENT_NONCONFIG: /* state data only */
|
||||
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||
/* Whole config tree, for validate debug */
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc, NULL, 1, &xret, NULL, NULL) < 0) {
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc, NULL, 1, wdef, &xret, NULL, NULL) < 0) {
|
||||
if ((cbmsg = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
|
|
@ -999,7 +918,7 @@ get_common(clicon_handle h,
|
|||
}
|
||||
else if (content == CONTENT_ALL){
|
||||
/* specific xpath */
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath?xpath:"/", 1, &xret, NULL, NULL) < 0) {
|
||||
if (xmldb_get0(h, db, YB_MODULE, nsc, xpath?xpath:"/", 1, wdef, &xret, NULL, NULL) < 0) {
|
||||
if ((cbmsg = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
|
|
@ -1024,7 +943,7 @@ get_common(clicon_handle h,
|
|||
break;
|
||||
case CONTENT_ALL: /* both config and state */
|
||||
case CONTENT_NONCONFIG: /* state data only */
|
||||
if ((ret = get_client_statedata(h, xpath?xpath:"/", nsc, &xret)) < 0)
|
||||
if ((ret = get_client_statedata(h, xpath?xpath:"/", nsc, wdef, &xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){ /* Error from callback (error in xret) */
|
||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, -1, 0) < 0)
|
||||
|
|
@ -1033,8 +952,6 @@ get_common(clicon_handle h,
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (with_defaults(xe, xret) < 0)
|
||||
goto done;
|
||||
if (content != CONTENT_CONFIG &&
|
||||
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||
/* Check XML by validating it. return internal error with error cause
|
||||
|
|
|
|||
|
|
@ -320,10 +320,7 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp,
|
|||
* @param[in] yspec Yang spec
|
||||
* @param[in] nsc Namespace context
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[in] pagmode List pagination mode
|
||||
* @param[in] offset Offset, for list pagination
|
||||
* @param[in] limit Limit, for list pagination
|
||||
* @param[out] remaining Remaining elements (if limit is non-zero)
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[in,out] xret State XML tree is merged with existing tree.
|
||||
* @retval -1 Error
|
||||
* @retval 0 Statedata callback failed (xret set with netconf-error)
|
||||
|
|
@ -335,6 +332,7 @@ clixon_plugin_statedata_all(clicon_handle h,
|
|||
yang_stmt *yspec,
|
||||
cvec *nsc,
|
||||
char *xpath,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -388,10 +386,9 @@ clixon_plugin_statedata_all(clicon_handle h,
|
|||
if (xml_sort_recurse(x) < 0)
|
||||
goto done;
|
||||
/* Remove global defaults and empty non-presence containers */
|
||||
/* XXX: only for state data and according to with-defaults setting */
|
||||
if (xml_defaults_nopresence(x, 2) < 0)
|
||||
goto done;
|
||||
if (xml_default_recurse(x, 1) < 0)
|
||||
goto done;
|
||||
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0)
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ db_merge(clicon_handle h,
|
|||
cxobj *xt = NULL;
|
||||
|
||||
/* Get data as xml from db1 */
|
||||
if (xmldb_get0(h, (char*)db1, YB_MODULE, NULL, NULL, 0, &xt, NULL, NULL) < 0)
|
||||
if (xmldb_get0(h, (char*)db1, YB_MODULE, NULL, NULL, 0, 0, &xt, NULL, NULL) < 0)
|
||||
goto done;
|
||||
xml_name_set(xt, NETCONF_INPUT_CONFIG);
|
||||
/* Merge xml into db2. Without commit */
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ int clixon_plugin_pre_daemon_all(clicon_handle h);
|
|||
int clixon_plugin_daemon_all(clicon_handle h);
|
||||
|
||||
int clixon_plugin_statedata_all(clicon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath,
|
||||
cxobj **xtop);
|
||||
withdefaults_type wdef, cxobj **xtop);
|
||||
int clixon_plugin_lockdb_all(clicon_handle h, char *db, int lock, int id);
|
||||
|
||||
int clixon_pagination_cb_register(clicon_handle h, handler_function fn, char *path, void *arg);
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ example_statedata(clicon_handle h,
|
|||
* Get config according to xpath */
|
||||
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
|
||||
goto done;
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc1, "/interfaces/interface/name", 1, &xt, NULL, NULL) < 0)
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc1, "/interfaces/interface/name", 1, 0, &xt, NULL, NULL) < 0)
|
||||
goto done;
|
||||
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ int xmldb_disconnect(clicon_handle h);
|
|||
/* in clixon_datastore_read.[ch] */
|
||||
int xmldb_get(clicon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xtop);
|
||||
int xmldb_get0(clicon_handle h, const char *db, yang_bind yb,
|
||||
cvec *nsc, const char *xpath,
|
||||
int copy, cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
||||
cvec *nsc, const char *xpath, int copy, withdefaults_type wdef,
|
||||
cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
||||
int xmldb_get0_clear(clicon_handle h, cxobj *x);
|
||||
int xmldb_get0_free(clicon_handle h, cxobj **xp);
|
||||
int xmldb_put(clicon_handle h, const char *db, enum operation_type op, cxobj *xt, char *username, cbuf *cbret); /* in clixon_datastore_write.[ch] */
|
||||
|
|
|
|||
|
|
@ -129,6 +129,17 @@ enum framing_type{
|
|||
};
|
||||
typedef enum framing_type netconf_framing_type;
|
||||
|
||||
/* NETCONF with-defaults
|
||||
* @see RFC 6243
|
||||
*/
|
||||
enum withdefaults_type{
|
||||
WITHDEFAULTS_REPORT_ALL = 0, /* default */
|
||||
WITHDEFAULTS_TRIM,
|
||||
WITHDEFAULTS_EXPLICIT,
|
||||
WITHDEFAULTS_REPORT_ALL_TAGGED
|
||||
};
|
||||
typedef enum withdefaults_type withdefaults_type;
|
||||
|
||||
/*
|
||||
* Macros
|
||||
*/
|
||||
|
|
@ -142,6 +153,8 @@ typedef enum framing_type netconf_framing_type;
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
char *withdefaults_int2str(int keyword);
|
||||
int withdefaults_str2int(char *str);
|
||||
int netconf_in_use(cbuf *cb, char *type, char *message);
|
||||
int netconf_invalid_value(cbuf *cb, char *type, char *message);
|
||||
int netconf_invalid_value_xml(cxobj **xret, char *type, char *message);
|
||||
|
|
|
|||
|
|
@ -79,5 +79,8 @@ int yang_xml_mandatory(cxobj *xt, yang_stmt *ys);
|
|||
int xml_rpc_isaction(cxobj *xn);
|
||||
int xml_find_action(cxobj *xn, int top, cxobj **xap);
|
||||
int purge_tagged_nodes(cxobj *xn, char *ns, char *name, char *value, int keepnode);
|
||||
int xml_add_default_tag(cxobj *x, uint16_t flags);
|
||||
int xml_flag_state_default_value(cxobj *x, uint16_t flag);
|
||||
int xml_flag_default_value(cxobj *x, uint16_t flag);
|
||||
|
||||
#endif /* _CLIXON_XML_MAP_H_ */
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@
|
|||
#include "clixon_plugin.h"
|
||||
#include "clixon_options.h"
|
||||
#include "clixon_data.h"
|
||||
#include "clixon_netconf_lib.h"
|
||||
#include "clixon_datastore.h"
|
||||
#include "clixon_datastore_write.h"
|
||||
#include "clixon_datastore_read.h"
|
||||
|
|
|
|||
|
|
@ -662,6 +662,7 @@ xmldb_readfile(clicon_handle h,
|
|||
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||
* @param[in] nsc External XML namespace context, or NULL
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
||||
* @param[out] msdiff If set, return modules-state differences
|
||||
* @param[out] xerr XML error if retval is 0
|
||||
|
|
@ -677,6 +678,7 @@ xmldb_get_nocache(clicon_handle h,
|
|||
yang_bind yb,
|
||||
cvec *nsc,
|
||||
const char *xpath,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xtop,
|
||||
modstate_diff_t *msdiff,
|
||||
cxobj **xerr)
|
||||
|
|
@ -734,6 +736,54 @@ xmldb_get_nocache(clicon_handle h,
|
|||
if (xml_default_recurse(xt, 0) < 0)
|
||||
goto done;
|
||||
}
|
||||
#if 1
|
||||
/* Sub-optimal: first add defaults, then remove them in some cases
|
||||
* Reason is code is primarily test for _cache case and I dont have time to "revert" it here
|
||||
*/
|
||||
switch (wdef){
|
||||
case WITHDEFAULTS_REPORT_ALL:
|
||||
break;
|
||||
case WITHDEFAULTS_TRIM:
|
||||
/* Mark and remove nodes having schema default values */
|
||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flags(xt, XML_FLAG_MARK, XML_FLAG_MARK)
|
||||
< 0)
|
||||
goto done;
|
||||
if (xml_defaults_nopresence(xt, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_EXPLICIT:
|
||||
if (xml_defaults_nopresence(xt, 2) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
||||
cxobj *x;
|
||||
char *ns;
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(xt, x, CX_ELMNT)) != NULL){
|
||||
ns = NULL;
|
||||
if (xml2ns(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||
goto done;
|
||||
if (ns == NULL){
|
||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Mark nodes having default schema values */
|
||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add tag attributes to default nodes */
|
||||
if (xml_apply(xt, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
} /* switch wdef */
|
||||
#endif
|
||||
/* If empty NACM config, then disable NACM if loaded
|
||||
*/
|
||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
||||
|
|
@ -774,6 +824,7 @@ xmldb_get_nocache(clicon_handle h,
|
|||
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||
* @param[in] nsc External XML namespace context, or NULL
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
||||
* @param[out] msdiff If set, return modules-state differences
|
||||
* @param[out] xerr XML error if retval is 0
|
||||
|
|
@ -789,6 +840,7 @@ xmldb_get_cache(clicon_handle h,
|
|||
yang_bind yb,
|
||||
cvec *nsc,
|
||||
const char *xpath,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xtop,
|
||||
modstate_diff_t *msdiff,
|
||||
cxobj **xerr)
|
||||
|
|
@ -889,17 +941,52 @@ xmldb_get_cache(clicon_handle h,
|
|||
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* Remove global defaults and empty non-presence containers */
|
||||
/* Original tree: Remove global defaults and empty non-presence containers */
|
||||
if (xml_defaults_nopresence(x0t, 2) < 0)
|
||||
goto done;
|
||||
if (yb != YB_NONE){
|
||||
/* Add default global values */
|
||||
if (xml_global_defaults(h, x1t, nsc, xpath, yspec, 0) < 0)
|
||||
switch (wdef){
|
||||
case WITHDEFAULTS_REPORT_ALL:
|
||||
break;
|
||||
case WITHDEFAULTS_TRIM:
|
||||
/* Mark and remove nodes having schema default values */
|
||||
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add default recursive values */
|
||||
if (xml_default_recurse(x1t, 0) < 0)
|
||||
if (xml_tree_prune_flags(x1t, XML_FLAG_MARK, XML_FLAG_MARK)
|
||||
< 0)
|
||||
goto done;
|
||||
if (xml_defaults_nopresence(x1t, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_EXPLICIT:
|
||||
if (xml_defaults_nopresence(x1t, 2) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
||||
cxobj *x;
|
||||
char *ns;
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(x1t, x, CX_ELMNT)) != NULL){
|
||||
ns = NULL;
|
||||
if (xml2ns(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||
goto done;
|
||||
if (ns == NULL){
|
||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Mark nodes having default schema values */
|
||||
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add tag attributes to default nodes */
|
||||
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
} /* switch wdef */
|
||||
/* If empty NACM config, then disable NACM if loaded
|
||||
*/
|
||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
||||
|
|
@ -932,7 +1019,7 @@ xmldb_get_cache(clicon_handle h,
|
|||
* @param[in] yb How to bind yang to XML top-level when parsing
|
||||
* @param[in] nsc External XML namespace context, or NULL
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[in] config If set only configuration data, else also state
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
||||
* @param[out] msdiff If set, return modules-state differences
|
||||
* @param[out] xerr XML error if retval is 0
|
||||
|
|
@ -947,6 +1034,7 @@ xmldb_get_zerocopy(clicon_handle h,
|
|||
yang_bind yb,
|
||||
cvec *nsc,
|
||||
const char *xpath,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xtop,
|
||||
modstate_diff_t *msdiff,
|
||||
cxobj **xerr)
|
||||
|
|
@ -1005,6 +1093,54 @@ xmldb_get_zerocopy(clicon_handle h,
|
|||
if (xml_default_recurse(x0t, 0) < 0)
|
||||
goto done;
|
||||
}
|
||||
#if 1
|
||||
/* Sub-optimal: first add defaults, then remove them in some cases
|
||||
* Reason is code is primarily test for _cache case and I dont have time to "revert" it here
|
||||
*/
|
||||
switch (wdef){
|
||||
case WITHDEFAULTS_REPORT_ALL:
|
||||
break;
|
||||
case WITHDEFAULTS_TRIM:
|
||||
/* Mark and remove nodes having schema default values */
|
||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
if (xml_tree_prune_flags(x0t, XML_FLAG_MARK, XML_FLAG_MARK)
|
||||
< 0)
|
||||
goto done;
|
||||
if (xml_defaults_nopresence(x0t, 1) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_EXPLICIT:
|
||||
if (xml_defaults_nopresence(x0t, 2) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case WITHDEFAULTS_REPORT_ALL_TAGGED:{
|
||||
cxobj *x;
|
||||
char *ns;
|
||||
x = NULL;
|
||||
while ((x = xml_child_each(x0t, x, CX_ELMNT)) != NULL){
|
||||
ns = NULL;
|
||||
if (xml2ns(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, &ns) < 0)
|
||||
goto done;
|
||||
if (ns == NULL){
|
||||
if (xmlns_set(x, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) < 0)
|
||||
goto done;
|
||||
}
|
||||
else if (strcmp(ns, IETF_NETCONF_WITH_DEFAULTS_ATTR_NAMESPACE) != 0){
|
||||
/* XXX: Assume if namespace is set that it is withdefaults otherwise just ignore? */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Mark nodes having default schema values */
|
||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_flag_default_value, (void*) XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
/* Add tag attributes to default nodes */
|
||||
if (xml_apply(x0t, CX_ELMNT, (xml_applyfn_t*) xml_add_default_tag, (void*) (XML_FLAG_DEFAULT | XML_FLAG_MARK)) < 0)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
} /* switch wdef */
|
||||
#endif
|
||||
/* If empty NACM config, then disable NACM if loaded
|
||||
*/
|
||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
||||
|
|
@ -1050,7 +1186,7 @@ xmldb_get(clicon_handle h,
|
|||
char *xpath,
|
||||
cxobj **xret)
|
||||
{
|
||||
return xmldb_get0(h, db, YB_MODULE, nsc, xpath, 1, xret, NULL, NULL);
|
||||
return xmldb_get0(h, db, YB_MODULE, nsc, xpath, 1, 0, xret, NULL, NULL);
|
||||
}
|
||||
|
||||
/*! Zero-copy variant of get content of database
|
||||
|
|
@ -1067,6 +1203,7 @@ xmldb_get(clicon_handle h,
|
|||
* @param[in] nsc External XML namespace context, or NULL
|
||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||
* @param[in] copy Force copy. Overrides cache_zerocopy -> cache
|
||||
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||
* @param[out] xret Single return XML tree. Free with xml_free()
|
||||
* @param[out] msdiff If set, return modules-state differences (upgrade code)
|
||||
* @param[out] xerr XML error if retval is 0
|
||||
|
|
@ -1077,7 +1214,7 @@ xmldb_get(clicon_handle h,
|
|||
* @code
|
||||
* cxobj *xt;
|
||||
* cxobj *xerr = NULL;
|
||||
* if (xmldb_get0(h, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, &xt, NULL, &xerr) < 0)
|
||||
* if (xmldb_get0(h, "running", YB_MODULE, nsc, "/interface[name="eth"]", 0, 0, &xt, NULL, &xerr) < 0)
|
||||
* err;
|
||||
* if (ret == 0){ # Not if YB_NONE
|
||||
* # Error handling
|
||||
|
|
@ -1098,7 +1235,7 @@ xmldb_get(clicon_handle h,
|
|||
* And a db content:
|
||||
* <c><x>1</x></c>
|
||||
* With the following call:
|
||||
* xmldb_get0(h, "running", NULL, NULL, "/c[x=0]", 1, &xt, NULL, NULL)
|
||||
* xmldb_get0(h, "running", NULL, NULL, "/c[x=0]", 1, 0, &xt, NULL, NULL)
|
||||
* which result in a miss (there is no c with x=0), but when the returned xt is printed
|
||||
* (the existing tree is discarded), the default (empty) xml tree is:
|
||||
* <c><x>0</x></c>
|
||||
|
|
@ -1110,6 +1247,7 @@ xmldb_get0(clicon_handle h,
|
|||
cvec *nsc,
|
||||
const char *xpath,
|
||||
int copy,
|
||||
withdefaults_type wdef,
|
||||
cxobj **xret,
|
||||
modstate_diff_t *msdiff,
|
||||
cxobj **xerr)
|
||||
|
|
@ -1122,7 +1260,7 @@ xmldb_get0(clicon_handle h,
|
|||
* Add default values in copy
|
||||
* Copy deleted by xmldb_free
|
||||
*/
|
||||
retval = xmldb_get_nocache(h, db, yb, nsc, xpath, xret, msdiff, xerr);
|
||||
retval = xmldb_get_nocache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
||||
break;
|
||||
case DATASTORE_CACHE_ZEROCOPY:
|
||||
/* Get cache (file if empty) mark xpath match in original tree
|
||||
|
|
@ -1130,7 +1268,7 @@ xmldb_get0(clicon_handle h,
|
|||
* Default values and markings removed in xmldb_clear
|
||||
*/
|
||||
if (!copy){
|
||||
retval = xmldb_get_zerocopy(h, db, yb, nsc, xpath, xret, msdiff, xerr);
|
||||
retval = xmldb_get_zerocopy(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
|
|
@ -1139,7 +1277,7 @@ xmldb_get0(clicon_handle h,
|
|||
* Add default values in copy, return copy
|
||||
* Copy deleted by xmldb_free
|
||||
*/
|
||||
retval = xmldb_get_cache(h, db, yb, nsc, xpath, xret, msdiff, xerr);
|
||||
retval = xmldb_get_cache(h, db, yb, nsc, xpath, wdef, xret, msdiff, xerr);
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,7 @@ nacm_access_pre(clicon_handle h,
|
|||
goto done;
|
||||
}
|
||||
else if (strcmp(mode, "internal")==0){
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc, "nacm", 1, &xnacm0, NULL, NULL) < 0)
|
||||
if (xmldb_get0(h, "running", YB_MODULE, nsc, "nacm", 1, 0, &xnacm0, NULL, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
|
|
|
|||
|
|
@ -77,6 +77,35 @@
|
|||
|
||||
#include "clixon_netconf_lib.h"
|
||||
|
||||
/* Mapping between RFC6243 withdefaults strings <--> ints
|
||||
*/
|
||||
static const map_str2int wdmap[] = {
|
||||
{"report-all", WITHDEFAULTS_REPORT_ALL},
|
||||
{"trim", WITHDEFAULTS_TRIM},
|
||||
{"explicit", WITHDEFAULTS_EXPLICIT},
|
||||
{"report-all-tagged", WITHDEFAULTS_REPORT_ALL_TAGGED}
|
||||
};
|
||||
|
||||
/*! Map from with-defaults ints to strings
|
||||
* @param[in] int Integer representation of withdefaults values
|
||||
* @retval str String representation of withdefaults values
|
||||
*/
|
||||
char *
|
||||
withdefaults_int2str(int keyword)
|
||||
{
|
||||
return (char*)clicon_int2str(wdmap, keyword);
|
||||
}
|
||||
|
||||
/*! Map from with-defaults strings to ints
|
||||
* @param[in] str String representation of withdefaults values
|
||||
* @retval int Integer representation of withdefaults values
|
||||
*/
|
||||
int
|
||||
withdefaults_str2int(char *str)
|
||||
{
|
||||
return clicon_str2int(wdmap, str);
|
||||
}
|
||||
|
||||
/*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A
|
||||
*
|
||||
* The request requires a resource that already is in use.
|
||||
|
|
|
|||
|
|
@ -1725,7 +1725,7 @@ xml_find_type_value(cxobj *xt,
|
|||
* @code
|
||||
* cxobj *x = xml_find_type(x, "prefix", "name", CX_ATTR);
|
||||
* @endcode
|
||||
* @see xml_find which finds any child given name
|
||||
* @see xml_find which finds any child given name (and no prefix)
|
||||
* @see xml_find_value where a body can be found as well
|
||||
*/
|
||||
cxobj *
|
||||
|
|
|
|||
|
|
@ -781,12 +781,14 @@ xml_default_create(yang_stmt *y,
|
|||
/*! Try to see if intermediate nodes are necessary for default values, create if so
|
||||
*
|
||||
* @param[in] yt Yang container (no-presence)
|
||||
* @param[in] state Set if global state, otherwise config
|
||||
* @param[out] createp Need to create XML container
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
xml_nopresence_try(yang_stmt *yt,
|
||||
int state,
|
||||
int *createp)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -801,7 +803,12 @@ xml_nopresence_try(yang_stmt *yt,
|
|||
while ((y = yn_each(yt, y)) != NULL) {
|
||||
switch (yang_keyword_get(y)){
|
||||
case Y_LEAF:
|
||||
if (!cv_flag(yang_cv_get(y), V_UNSET)){ /* Default value exists */
|
||||
/* Default value exists */
|
||||
if (!cv_flag(yang_cv_get(y), V_UNSET)){
|
||||
/* Want to add state defaults, but this is config */
|
||||
if (state && yang_config_ancestor(y))
|
||||
;
|
||||
else
|
||||
/* Need to create container */
|
||||
*createp = 1;
|
||||
goto ok;
|
||||
|
|
@ -812,7 +819,7 @@ xml_nopresence_try(yang_stmt *yt,
|
|||
/* If this is non-presence, (and it does not exist in xt) call recursively
|
||||
* and create nodes if any default value exist first. Then continue and populate?
|
||||
*/
|
||||
if (xml_nopresence_try(y, createp) < 0)
|
||||
if (xml_nopresence_try(y, state, createp) < 0)
|
||||
goto done;
|
||||
if (*createp)
|
||||
goto ok;
|
||||
|
|
@ -837,6 +844,8 @@ xml_nopresence_try(yang_stmt *yt,
|
|||
* @param[in] state Set if global state, otherwise config
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* XXX If state, should not add config defaults
|
||||
* if (state && yang_config(yc))
|
||||
*/
|
||||
static int
|
||||
xml_default1(yang_stmt *yt,
|
||||
|
|
@ -867,10 +876,14 @@ xml_default1(yang_stmt *yt,
|
|||
case Y_OUTPUT:
|
||||
yc = NULL;
|
||||
while ((yc = yn_each(yt, yc)) != NULL) {
|
||||
/* If config parameter and local is config false */
|
||||
if (!state && !yang_config(yc))
|
||||
continue;
|
||||
switch (yang_keyword_get(yc)){
|
||||
case Y_LEAF:
|
||||
/* Want to add state defaults, but this is config */
|
||||
if (state && yang_config_ancestor(yc))
|
||||
break;
|
||||
if ((cv = yang_cv_get(yc)) == NULL){
|
||||
clicon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should",
|
||||
yang_argument_get(yc));
|
||||
|
|
@ -903,7 +916,7 @@ xml_default1(yang_stmt *yt,
|
|||
*/
|
||||
if (xml_find_type(xt, NULL, yang_argument_get(yc), CX_ELMNT) == NULL){
|
||||
/* No such container exist, recursively try if needed */
|
||||
if (xml_nopresence_try(yc, &create) < 0)
|
||||
if (xml_nopresence_try(yc, state, &create) < 0)
|
||||
goto done;
|
||||
if (create){
|
||||
/* Retval shows there is a default value need to create the
|
||||
|
|
@ -2342,3 +2355,108 @@ purge_tagged_nodes(cxobj *xn,
|
|||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Add default attribute to node with default value.
|
||||
*
|
||||
* Used in with-default code for report-all-tagged
|
||||
* @param[in] x XML node
|
||||
* @param[in] flags Flags indicatiing default nodes
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
int
|
||||
xml_add_default_tag(cxobj *x,
|
||||
uint16_t flags)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *xattr;
|
||||
|
||||
if (xml_flag(x, flags)) {
|
||||
/* set default attribute */
|
||||
if ((xattr = xml_new("default", x, CX_ATTR)) == NULL)
|
||||
goto done;
|
||||
if (xml_value_set(xattr, "true") < 0)
|
||||
goto done;
|
||||
if (xml_prefix_set(xattr, IETF_NETCONF_WITH_DEFAULTS_ATTR_PREFIX) < 0)
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Set flag on node having schema default value. (non-config)
|
||||
*
|
||||
* Used in with-default code for trim/report-all-tagged
|
||||
* @param[in] x XML node
|
||||
* @param[in] flag Flag to be used
|
||||
* @retval 0 OK
|
||||
* @see xml_flag_default_value for config default value
|
||||
*/
|
||||
int
|
||||
xml_flag_state_default_value(cxobj *x,
|
||||
uint16_t flag)
|
||||
{
|
||||
yang_stmt *y;
|
||||
cg_var *cv;
|
||||
char *yv;
|
||||
char *xv;
|
||||
|
||||
xml_flag_reset(x, flag); /* Assume not default value */
|
||||
if ((xv = xml_body(x)) == NULL)
|
||||
goto done;
|
||||
if ((y = xml_spec(x)) == NULL)
|
||||
goto done;
|
||||
if (yang_config_ancestor(y) == 1)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if (cv_name_get(cv) == NULL)
|
||||
goto done;
|
||||
if ((yv = cv2str_dup(cv)) == NULL)
|
||||
goto done;
|
||||
if (strcmp(xv, yv) == 0)
|
||||
xml_flag_set(x, flag); /* Actual value same as default value */
|
||||
free(yv);
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Set flag on node having schema default value. (config)
|
||||
*
|
||||
* Used in with-default code for trim and report-all-tagged
|
||||
* @param[in] x XML node
|
||||
* @param[in] flag Flag to be used
|
||||
* @retval 0 OK
|
||||
* @see xml_flag_state_default_value for non-config default value
|
||||
*/
|
||||
int
|
||||
xml_flag_default_value(cxobj *x,
|
||||
uint16_t flag)
|
||||
{
|
||||
yang_stmt *y;
|
||||
cg_var *cv;
|
||||
char *yv;
|
||||
char *xv;
|
||||
|
||||
xml_flag_reset(x, flag); /* Assume not default value */
|
||||
if ((xv = xml_body(x)) == NULL)
|
||||
goto done;
|
||||
if ((y = xml_spec(x)) == NULL)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if ((cv = yang_cv_get(y)) == NULL)
|
||||
goto done;
|
||||
if (cv_name_get(cv) == NULL)
|
||||
goto done;
|
||||
if ((yv = cv2str_dup(cv)) == NULL)
|
||||
goto done;
|
||||
if (strcmp(xv, yv) == 0)
|
||||
xml_flag_set(x, flag); /* Actual value same as default value */
|
||||
free(yv);
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1501,7 +1501,7 @@ xml_find_index_yang(cxobj *xp,
|
|||
* if (clixon_xml_find_index(xp, yp, NULL, "a", ns, cvk, xv) < 0)
|
||||
* err;
|
||||
* for (i=0; i<clixon_xvec_len(xv); i++){
|
||||
* x = clixon_xpath_i(xv, i);
|
||||
* x = clixon_xvec_i(xv, i);
|
||||
* ...
|
||||
* }
|
||||
* clixon_xvec_free(xvec);
|
||||
|
|
|
|||
|
|
@ -1602,12 +1602,20 @@ yang_order(yang_stmt *y)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Map from YANG keywords ints to strings
|
||||
* @param[in] int Integer representation of YANG keywords
|
||||
* @retval str String representation of YANG keywords
|
||||
*/
|
||||
char *
|
||||
yang_key2str(int keyword)
|
||||
{
|
||||
return (char*)clicon_int2str(ykmap, keyword);
|
||||
}
|
||||
|
||||
/*! Map from yang keyword strings to ints
|
||||
* @param[in] str String representation of YANG keywords
|
||||
* @retval int Integer representation of YANG keywords
|
||||
*/
|
||||
int
|
||||
yang_str2key(char *str)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -485,7 +485,6 @@ expecteof_netconf "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO" \
|
|||
<interface><name>eth1</name><mtu wd:default=\"true\">1500</mtu></interface>\
|
||||
<interface><name>eth2</name><mtu>9000</mtu></interface>\
|
||||
<interface><name>eth3</name><mtu wd:default=\"true\">1500</mtu></interface>\
|
||||
<cedv><edv wd:default=\"true\">edv</edv></cedv><cdv><dv wd:default=\"true\">dv</dv></cdv>\
|
||||
</interfaces></data></rpc-reply>"
|
||||
|
||||
new "rfc8040 4.3. RESTCONF GET json"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue