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
|
* Added netconf ssh subsystem
|
||||||
* Renamed from `clixon` built in `docker/base`
|
* Renamed from `clixon` built in `docker/base`
|
||||||
* C-API
|
* C-API
|
||||||
|
* Added `with-defaults` parameter (default 0) to `xmldb_get0()`
|
||||||
* Added `sock_flags` parameter to `clixon_proc_socket()`
|
* Added `sock_flags` parameter to `clixon_proc_socket()`
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
|
||||||
|
|
@ -180,7 +180,7 @@ startup_common(clicon_handle h,
|
||||||
* It is done below, later in this function
|
* It is done below, later in this function
|
||||||
*/
|
*/
|
||||||
if (clicon_option_bool(h, "CLICON_XMLDB_UPGRADE_CHECKOLD")){
|
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;
|
goto done;
|
||||||
if (ret == 0){ /* ret should not be 0 */
|
if (ret == 0){ /* ret should not be 0 */
|
||||||
/* Print upgraded db: -q backend switch for debugging/ showing upgraded config only */
|
/* Print upgraded db: -q backend switch for debugging/ showing upgraded config only */
|
||||||
|
|
@ -197,7 +197,7 @@ startup_common(clicon_handle h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
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;
|
goto done;
|
||||||
}
|
}
|
||||||
if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE
|
if (msdiff && msdiff->md_status == 0){ // Possibly check for CLICON_XMLDB_MODSTATE
|
||||||
|
|
@ -488,7 +488,7 @@ validate_common(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* This is the state we are going to */
|
/* 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;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -497,7 +497,7 @@ validate_common(clicon_handle h,
|
||||||
(void*)(XML_FLAG_MARK|XML_FLAG_CHANGE));
|
(void*)(XML_FLAG_MARK|XML_FLAG_CHANGE));
|
||||||
/* 2. Parse xml trees
|
/* 2. Parse xml trees
|
||||||
* This is the state we are going from */
|
* 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;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
@ -960,7 +960,7 @@ from_client_restart_one(clicon_handle h,
|
||||||
if ((td = transaction_new()) == NULL)
|
if ((td = transaction_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* This is the state we are going to */
|
/* 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;
|
goto done;
|
||||||
if ((ret = xml_yang_validate_all_top(h, td->td_target, &xerr)) < 0)
|
if ((ret = xml_yang_validate_all_top(h, td->td_target, &xerr)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -970,7 +970,7 @@ from_client_restart_one(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* This is the state we are going from */
|
/* 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;
|
goto done;
|
||||||
|
|
||||||
/* 3. Compute differences */
|
/* 3. Compute differences */
|
||||||
|
|
|
||||||
|
|
@ -180,16 +180,18 @@ client_get_streams(clicon_handle h,
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] xpath XPath selection, may be used to filter early
|
* @param[in] xpath XPath selection, may be used to filter early
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @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
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
* @retval -1 Error (fatal)
|
* @retval -1 Error (fatal)
|
||||||
* @retval 0 Statedata callback failed (clicon_err called)
|
* @retval 0 Statedata callback failed (clicon_err called)
|
||||||
* @retval 1 OK
|
* @retval 1 OK
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_client_statedata(clicon_handle h,
|
get_client_statedata(clicon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
cxobj **xret)
|
withdefaults_type wdef,
|
||||||
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
yang_stmt *yspec;
|
yang_stmt *yspec;
|
||||||
|
|
@ -258,16 +260,63 @@ get_client_statedata(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* Use plugin state callbacks */
|
/* 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;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
/* Add default state to config if present */
|
switch (wdef){
|
||||||
if (xml_default_recurse(*xret, 1) < 0)
|
case WITHDEFAULTS_REPORT_ALL:
|
||||||
goto done;
|
case WITHDEFAULTS_EXPLICIT:
|
||||||
/* Add default global state */
|
/* Add global defaults. */
|
||||||
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
if (xml_global_defaults(h, *xret, nsc, xpath, yspec, 1) < 0)
|
||||||
goto done;
|
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 */
|
retval = 1; /* OK */
|
||||||
done:
|
done:
|
||||||
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
clicon_debug(1, "%s %d", __FUNCTION__, retval);
|
||||||
|
|
@ -416,141 +465,6 @@ element2value(clicon_handle h,
|
||||||
return 1;
|
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
|
/*! Extract offset and limit from get/list-pagination
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
|
|
@ -592,6 +506,8 @@ list_pagination_hdr(clicon_handle h,
|
||||||
* @param[in] db Database name
|
* @param[in] db Database name
|
||||||
* @param[in] xpath XPath point to object to get
|
* @param[in] xpath XPath point to object to get
|
||||||
* @param[in] nsc Namespace context of xpath
|
* @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..
|
* @param[out] cbret Return xml tree, eg <rpc-reply>..., <rpc-error..
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
|
@ -610,6 +526,7 @@ get_list_pagination(clicon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *username,
|
char *username,
|
||||||
|
withdefaults_type wdef,
|
||||||
cbuf *cbret
|
cbuf *cbret
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
@ -733,7 +650,7 @@ get_list_pagination(clicon_handle h,
|
||||||
/* Append predicate to original xpath and replace it */
|
/* Append predicate to original xpath and replace it */
|
||||||
xpath2 = cbuf_get(cbpath);
|
xpath2 = cbuf_get(cbpath);
|
||||||
/* specific xpath */
|
/* 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){
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -803,8 +720,6 @@ get_list_pagination(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (with_defaults(xml_parent(xe), xret) < 0)
|
|
||||||
goto done;
|
|
||||||
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
if (xpath_vec(xret, nsc, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Help function to filter out anything that is outside of xpath */
|
/* Help function to filter out anything that is outside of xpath */
|
||||||
|
|
@ -900,6 +815,8 @@ get_common(clicon_handle h,
|
||||||
cxobj *xfind;
|
cxobj *xfind;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
uint32_t limit = 0;
|
uint32_t limit = 0;
|
||||||
|
withdefaults_type wdef = WITHDEFAULTS_REPORT_ALL;
|
||||||
|
char *wdefstr;
|
||||||
|
|
||||||
clicon_debug(1, "%s", __FUNCTION__);
|
clicon_debug(1, "%s", __FUNCTION__);
|
||||||
username = clicon_username_get(h);
|
username = clicon_username_get(h);
|
||||||
|
|
@ -939,6 +856,8 @@ get_common(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ((wdefstr = xml_find_body(xe, "with-defaults")) != NULL)
|
||||||
|
wdef = withdefaults_str2int(wdefstr);
|
||||||
/* Check if list pagination */
|
/* Check if list pagination */
|
||||||
if ((xfind = xml_find_type(xe, NULL, "list-pagination", CX_ELMNT)) != NULL){
|
if ((xfind = xml_find_type(xe, NULL, "list-pagination", CX_ELMNT)) != NULL){
|
||||||
/* with non-presence list-pagination, use ad-hoc algorithm to determine
|
/* 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,
|
if (get_list_pagination(h, ce,
|
||||||
xfind,
|
xfind,
|
||||||
content, db,
|
content, db,
|
||||||
depth, yspec, xpath, nsc, username,
|
depth, yspec, xpath, nsc, username, wdef,
|
||||||
cbret) < 0)
|
cbret) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -971,7 +890,7 @@ get_common(clicon_handle h,
|
||||||
switch (content){
|
switch (content){
|
||||||
case CONTENT_CONFIG: /* config data only */
|
case CONTENT_CONFIG: /* config data only */
|
||||||
/* specific xpath */
|
/* 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){
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -986,7 +905,7 @@ get_common(clicon_handle h,
|
||||||
case CONTENT_NONCONFIG: /* state data only */
|
case CONTENT_NONCONFIG: /* state data only */
|
||||||
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
if (clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||||
/* Whole config tree, for validate debug */
|
/* 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){
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -999,7 +918,7 @@ get_common(clicon_handle h,
|
||||||
}
|
}
|
||||||
else if (content == CONTENT_ALL){
|
else if (content == CONTENT_ALL){
|
||||||
/* specific xpath */
|
/* 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){
|
if ((cbmsg = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1024,7 +943,7 @@ get_common(clicon_handle h,
|
||||||
break;
|
break;
|
||||||
case CONTENT_ALL: /* both config and state */
|
case CONTENT_ALL: /* both config and state */
|
||||||
case CONTENT_NONCONFIG: /* state data only */
|
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;
|
goto done;
|
||||||
if (ret == 0){ /* Error from callback (error in xret) */
|
if (ret == 0){ /* Error from callback (error in xret) */
|
||||||
if (clixon_xml2cbuf(cbret, xret, 0, 0, -1, 0) < 0)
|
if (clixon_xml2cbuf(cbret, xret, 0, 0, -1, 0) < 0)
|
||||||
|
|
@ -1033,8 +952,6 @@ get_common(clicon_handle h,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (with_defaults(xe, xret) < 0)
|
|
||||||
goto done;
|
|
||||||
if (content != CONTENT_CONFIG &&
|
if (content != CONTENT_CONFIG &&
|
||||||
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
clicon_option_bool(h, "CLICON_VALIDATE_STATE_XML")){
|
||||||
/* Check XML by validating it. return internal error with error cause
|
/* 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] yspec Yang spec
|
||||||
* @param[in] nsc Namespace context
|
* @param[in] nsc Namespace context
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
* @param[in] pagmode List pagination mode
|
* @param[in] wdef With-defaults parameter, see RFC 6243
|
||||||
* @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,out] xret State XML tree is merged with existing tree.
|
* @param[in,out] xret State XML tree is merged with existing tree.
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Statedata callback failed (xret set with netconf-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,
|
yang_stmt *yspec,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
|
withdefaults_type wdef,
|
||||||
cxobj **xret)
|
cxobj **xret)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -388,10 +386,9 @@ clixon_plugin_statedata_all(clicon_handle h,
|
||||||
if (xml_sort_recurse(x) < 0)
|
if (xml_sort_recurse(x) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Remove global defaults and empty non-presence containers */
|
/* 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)
|
if (xml_defaults_nopresence(x, 2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_default_recurse(x, 1) < 0)
|
|
||||||
goto done;
|
|
||||||
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
if ((ret = netconf_trymerge(x, yspec, xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ db_merge(clicon_handle h,
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
|
|
||||||
/* Get data as xml from db1 */
|
/* 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;
|
goto done;
|
||||||
xml_name_set(xt, NETCONF_INPUT_CONFIG);
|
xml_name_set(xt, NETCONF_INPUT_CONFIG);
|
||||||
/* Merge xml into db2. Without commit */
|
/* 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_daemon_all(clicon_handle h);
|
||||||
|
|
||||||
int clixon_plugin_statedata_all(clicon_handle h, yang_stmt *yspec, cvec *nsc, char *xpath,
|
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_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);
|
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 */
|
* Get config according to xpath */
|
||||||
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
|
if ((nsc1 = xml_nsctx_init(NULL, "urn:ietf:params:xml:ns:yang:ietf-interfaces")) == NULL)
|
||||||
goto done;
|
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;
|
goto done;
|
||||||
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
|
if (xpath_vec(xt, nsc1, "/interfaces/interface/name", &xvec, &xlen) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,8 @@ int xmldb_disconnect(clicon_handle h);
|
||||||
/* in clixon_datastore_read.[ch] */
|
/* in clixon_datastore_read.[ch] */
|
||||||
int xmldb_get(clicon_handle h, const char *db, cvec *nsc, char *xpath, cxobj **xtop);
|
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,
|
int xmldb_get0(clicon_handle h, const char *db, yang_bind yb,
|
||||||
cvec *nsc, const char *xpath,
|
cvec *nsc, const char *xpath, int copy, withdefaults_type wdef,
|
||||||
int copy, cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
cxobj **xtop, modstate_diff_t *msd, cxobj **xerr);
|
||||||
int xmldb_get0_clear(clicon_handle h, cxobj *x);
|
int xmldb_get0_clear(clicon_handle h, cxobj *x);
|
||||||
int xmldb_get0_free(clicon_handle h, cxobj **xp);
|
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] */
|
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;
|
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
|
* Macros
|
||||||
*/
|
*/
|
||||||
|
|
@ -142,6 +153,8 @@ typedef enum framing_type netconf_framing_type;
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
char *withdefaults_int2str(int keyword);
|
||||||
|
int withdefaults_str2int(char *str);
|
||||||
int netconf_in_use(cbuf *cb, char *type, char *message);
|
int netconf_in_use(cbuf *cb, char *type, char *message);
|
||||||
int netconf_invalid_value(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);
|
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_rpc_isaction(cxobj *xn);
|
||||||
int xml_find_action(cxobj *xn, int top, cxobj **xap);
|
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 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_ */
|
#endif /* _CLIXON_XML_MAP_H_ */
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@
|
||||||
#include "clixon_plugin.h"
|
#include "clixon_plugin.h"
|
||||||
#include "clixon_options.h"
|
#include "clixon_options.h"
|
||||||
#include "clixon_data.h"
|
#include "clixon_data.h"
|
||||||
|
#include "clixon_netconf_lib.h"
|
||||||
#include "clixon_datastore.h"
|
#include "clixon_datastore.h"
|
||||||
#include "clixon_datastore_write.h"
|
#include "clixon_datastore_write.h"
|
||||||
#include "clixon_datastore_read.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] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
* @param[in] nsc External XML namespace context, or NULL
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @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] xret Single return XML tree. Free with xml_free()
|
||||||
* @param[out] msdiff If set, return modules-state differences
|
* @param[out] msdiff If set, return modules-state differences
|
||||||
* @param[out] xerr XML error if retval is 0
|
* @param[out] xerr XML error if retval is 0
|
||||||
|
|
@ -677,6 +678,7 @@ xmldb_get_nocache(clicon_handle h,
|
||||||
yang_bind yb,
|
yang_bind yb,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
const char *xpath,
|
const char *xpath,
|
||||||
|
withdefaults_type wdef,
|
||||||
cxobj **xtop,
|
cxobj **xtop,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
|
|
@ -734,6 +736,54 @@ xmldb_get_nocache(clicon_handle h,
|
||||||
if (xml_default_recurse(xt, 0) < 0)
|
if (xml_default_recurse(xt, 0) < 0)
|
||||||
goto done;
|
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 empty NACM config, then disable NACM if loaded
|
||||||
*/
|
*/
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
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] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
* @param[in] nsc External XML namespace context, or NULL
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @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] xret Single return XML tree. Free with xml_free()
|
||||||
* @param[out] msdiff If set, return modules-state differences
|
* @param[out] msdiff If set, return modules-state differences
|
||||||
* @param[out] xerr XML error if retval is 0
|
* @param[out] xerr XML error if retval is 0
|
||||||
|
|
@ -789,6 +840,7 @@ xmldb_get_cache(clicon_handle h,
|
||||||
yang_bind yb,
|
yang_bind yb,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
const char *xpath,
|
const char *xpath,
|
||||||
|
withdefaults_type wdef,
|
||||||
cxobj **xtop,
|
cxobj **xtop,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
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)
|
if (xml_apply(x1t, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)(XML_FLAG_MARK|XML_FLAG_CHANGE)) < 0)
|
||||||
goto done;
|
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)
|
if (xml_defaults_nopresence(x0t, 2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (yb != YB_NONE){
|
switch (wdef){
|
||||||
/* Add default global values */
|
case WITHDEFAULTS_REPORT_ALL:
|
||||||
if (xml_global_defaults(h, x1t, nsc, xpath, yspec, 0) < 0)
|
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;
|
goto done;
|
||||||
/* Add default recursive values */
|
if (xml_tree_prune_flags(x1t, XML_FLAG_MARK, XML_FLAG_MARK)
|
||||||
if (xml_default_recurse(x1t, 0) < 0)
|
< 0)
|
||||||
|
goto done;
|
||||||
|
if (xml_defaults_nopresence(x1t, 1) < 0)
|
||||||
goto done;
|
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 empty NACM config, then disable NACM if loaded
|
||||||
*/
|
*/
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
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] yb How to bind yang to XML top-level when parsing
|
||||||
* @param[in] nsc External XML namespace context, or NULL
|
* @param[in] nsc External XML namespace context, or NULL
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @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] xret Single return XML tree. Free with xml_free()
|
||||||
* @param[out] msdiff If set, return modules-state differences
|
* @param[out] msdiff If set, return modules-state differences
|
||||||
* @param[out] xerr XML error if retval is 0
|
* @param[out] xerr XML error if retval is 0
|
||||||
|
|
@ -947,6 +1034,7 @@ xmldb_get_zerocopy(clicon_handle h,
|
||||||
yang_bind yb,
|
yang_bind yb,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
const char *xpath,
|
const char *xpath,
|
||||||
|
withdefaults_type wdef,
|
||||||
cxobj **xtop,
|
cxobj **xtop,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
|
|
@ -1005,6 +1093,54 @@ xmldb_get_zerocopy(clicon_handle h,
|
||||||
if (xml_default_recurse(x0t, 0) < 0)
|
if (xml_default_recurse(x0t, 0) < 0)
|
||||||
goto done;
|
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 empty NACM config, then disable NACM if loaded
|
||||||
*/
|
*/
|
||||||
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
if (clicon_option_bool(h, "CLICON_NACM_DISABLED_ON_EMPTY")){
|
||||||
|
|
@ -1050,7 +1186,7 @@ xmldb_get(clicon_handle h,
|
||||||
char *xpath,
|
char *xpath,
|
||||||
cxobj **xret)
|
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
|
/*! 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] nsc External XML namespace context, or NULL
|
||||||
* @param[in] xpath String with XPATH syntax. or NULL for all
|
* @param[in] xpath String with XPATH syntax. or NULL for all
|
||||||
* @param[in] copy Force copy. Overrides cache_zerocopy -> cache
|
* @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] xret Single return XML tree. Free with xml_free()
|
||||||
* @param[out] msdiff If set, return modules-state differences (upgrade code)
|
* @param[out] msdiff If set, return modules-state differences (upgrade code)
|
||||||
* @param[out] xerr XML error if retval is 0
|
* @param[out] xerr XML error if retval is 0
|
||||||
|
|
@ -1077,7 +1214,7 @@ xmldb_get(clicon_handle h,
|
||||||
* @code
|
* @code
|
||||||
* cxobj *xt;
|
* cxobj *xt;
|
||||||
* cxobj *xerr = NULL;
|
* 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;
|
* err;
|
||||||
* if (ret == 0){ # Not if YB_NONE
|
* if (ret == 0){ # Not if YB_NONE
|
||||||
* # Error handling
|
* # Error handling
|
||||||
|
|
@ -1098,18 +1235,19 @@ xmldb_get(clicon_handle h,
|
||||||
* And a db content:
|
* And a db content:
|
||||||
* <c><x>1</x></c>
|
* <c><x>1</x></c>
|
||||||
* With the following call:
|
* 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
|
* 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:
|
* (the existing tree is discarded), the default (empty) xml tree is:
|
||||||
* <c><x>0</x></c>
|
* <c><x>0</x></c>
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xmldb_get0(clicon_handle h,
|
xmldb_get0(clicon_handle h,
|
||||||
const char *db,
|
const char *db,
|
||||||
yang_bind yb,
|
yang_bind yb,
|
||||||
cvec *nsc,
|
cvec *nsc,
|
||||||
const char *xpath,
|
const char *xpath,
|
||||||
int copy,
|
int copy,
|
||||||
|
withdefaults_type wdef,
|
||||||
cxobj **xret,
|
cxobj **xret,
|
||||||
modstate_diff_t *msdiff,
|
modstate_diff_t *msdiff,
|
||||||
cxobj **xerr)
|
cxobj **xerr)
|
||||||
|
|
@ -1122,7 +1260,7 @@ xmldb_get0(clicon_handle h,
|
||||||
* Add default values in copy
|
* Add default values in copy
|
||||||
* Copy deleted by xmldb_free
|
* 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;
|
break;
|
||||||
case DATASTORE_CACHE_ZEROCOPY:
|
case DATASTORE_CACHE_ZEROCOPY:
|
||||||
/* Get cache (file if empty) mark xpath match in original tree
|
/* 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
|
* Default values and markings removed in xmldb_clear
|
||||||
*/
|
*/
|
||||||
if (!copy){
|
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;
|
break;
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
@ -1139,7 +1277,7 @@ xmldb_get0(clicon_handle h,
|
||||||
* Add default values in copy, return copy
|
* Add default values in copy, return copy
|
||||||
* Copy deleted by xmldb_free
|
* 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;
|
break;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
|
|
|
||||||
|
|
@ -1216,7 +1216,7 @@ nacm_access_pre(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else if (strcmp(mode, "internal")==0){
|
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;
|
goto done;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,35 @@
|
||||||
|
|
||||||
#include "clixon_netconf_lib.h"
|
#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
|
/*! Create Netconf in-use error XML tree according to RFC 6241 Appendix A
|
||||||
*
|
*
|
||||||
* The request requires a resource that already is in use.
|
* The request requires a resource that already is in use.
|
||||||
|
|
|
||||||
|
|
@ -1725,7 +1725,7 @@ xml_find_type_value(cxobj *xt,
|
||||||
* @code
|
* @code
|
||||||
* cxobj *x = xml_find_type(x, "prefix", "name", CX_ATTR);
|
* cxobj *x = xml_find_type(x, "prefix", "name", CX_ATTR);
|
||||||
* @endcode
|
* @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
|
* @see xml_find_value where a body can be found as well
|
||||||
*/
|
*/
|
||||||
cxobj *
|
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
|
/*! Try to see if intermediate nodes are necessary for default values, create if so
|
||||||
*
|
*
|
||||||
* @param[in] yt Yang container (no-presence)
|
* @param[in] yt Yang container (no-presence)
|
||||||
|
* @param[in] state Set if global state, otherwise config
|
||||||
* @param[out] createp Need to create XML container
|
* @param[out] createp Need to create XML container
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_nopresence_try(yang_stmt *yt,
|
xml_nopresence_try(yang_stmt *yt,
|
||||||
|
int state,
|
||||||
int *createp)
|
int *createp)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -801,9 +803,14 @@ xml_nopresence_try(yang_stmt *yt,
|
||||||
while ((y = yn_each(yt, y)) != NULL) {
|
while ((y = yn_each(yt, y)) != NULL) {
|
||||||
switch (yang_keyword_get(y)){
|
switch (yang_keyword_get(y)){
|
||||||
case Y_LEAF:
|
case Y_LEAF:
|
||||||
if (!cv_flag(yang_cv_get(y), V_UNSET)){ /* Default value exists */
|
/* Default value exists */
|
||||||
/* Need to create container */
|
if (!cv_flag(yang_cv_get(y), V_UNSET)){
|
||||||
*createp = 1;
|
/* Want to add state defaults, but this is config */
|
||||||
|
if (state && yang_config_ancestor(y))
|
||||||
|
;
|
||||||
|
else
|
||||||
|
/* Need to create container */
|
||||||
|
*createp = 1;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -812,7 +819,7 @@ xml_nopresence_try(yang_stmt *yt,
|
||||||
/* If this is non-presence, (and it does not exist in xt) call recursively
|
/* 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?
|
* 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;
|
goto done;
|
||||||
if (*createp)
|
if (*createp)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -837,6 +844,8 @@ xml_nopresence_try(yang_stmt *yt,
|
||||||
* @param[in] state Set if global state, otherwise config
|
* @param[in] state Set if global state, otherwise config
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
|
* XXX If state, should not add config defaults
|
||||||
|
* if (state && yang_config(yc))
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_default1(yang_stmt *yt,
|
xml_default1(yang_stmt *yt,
|
||||||
|
|
@ -867,10 +876,14 @@ xml_default1(yang_stmt *yt,
|
||||||
case Y_OUTPUT:
|
case Y_OUTPUT:
|
||||||
yc = NULL;
|
yc = NULL;
|
||||||
while ((yc = yn_each(yt, yc)) != NULL) {
|
while ((yc = yn_each(yt, yc)) != NULL) {
|
||||||
|
/* If config parameter and local is config false */
|
||||||
if (!state && !yang_config(yc))
|
if (!state && !yang_config(yc))
|
||||||
continue;
|
continue;
|
||||||
switch (yang_keyword_get(yc)){
|
switch (yang_keyword_get(yc)){
|
||||||
case Y_LEAF:
|
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){
|
if ((cv = yang_cv_get(yc)) == NULL){
|
||||||
clicon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should",
|
clicon_err(OE_YANG,0, "Internal error: yang leaf %s not populated with cv as it should",
|
||||||
yang_argument_get(yc));
|
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){
|
if (xml_find_type(xt, NULL, yang_argument_get(yc), CX_ELMNT) == NULL){
|
||||||
/* No such container exist, recursively try if needed */
|
/* 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;
|
goto done;
|
||||||
if (create){
|
if (create){
|
||||||
/* Retval shows there is a default value need to create the
|
/* Retval shows there is a default value need to create the
|
||||||
|
|
@ -2342,3 +2355,108 @@ purge_tagged_nodes(cxobj *xn,
|
||||||
done:
|
done:
|
||||||
return retval;
|
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)
|
* if (clixon_xml_find_index(xp, yp, NULL, "a", ns, cvk, xv) < 0)
|
||||||
* err;
|
* err;
|
||||||
* for (i=0; i<clixon_xvec_len(xv); i++){
|
* 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);
|
* clixon_xvec_free(xvec);
|
||||||
|
|
|
||||||
|
|
@ -1602,12 +1602,20 @@ yang_order(yang_stmt *y)
|
||||||
return retval;
|
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 *
|
char *
|
||||||
yang_key2str(int keyword)
|
yang_key2str(int keyword)
|
||||||
{
|
{
|
||||||
return (char*)clicon_int2str(ykmap, 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
|
int
|
||||||
yang_str2key(char *str)
|
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>eth1</name><mtu wd:default=\"true\">1500</mtu></interface>\
|
||||||
<interface><name>eth2</name><mtu>9000</mtu></interface>\
|
<interface><name>eth2</name><mtu>9000</mtu></interface>\
|
||||||
<interface><name>eth3</name><mtu wd:default=\"true\">1500</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>"
|
</interfaces></data></rpc-reply>"
|
||||||
|
|
||||||
new "rfc8040 4.3. RESTCONF GET json"
|
new "rfc8040 4.3. RESTCONF GET json"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue