* NACM extension (RFC8341)
* NACM module support (RFC8341 A1+A2)
* Recovery user "_nacm_recovery" added.
* Example use is restconf PUT when NACM edit-config is permitted, then automatic commit and discard are permitted using recovery user.
* Example user changed adm1 to andy to comply with RFC8341 example
* Yang code upgrade (RFC7950)
* RPC method input parameters validated
* see https://github.com/clicon/clixon/issues/4
* Correct XML namespace handling
* XML multiple modules was based on "loose" semantics so that yang modules were found by iterating thorugh namespaces until a match was made. This did not adhere to proper [XML namespace handling](https://www.w3.org/TR/2009/REC-xml-names-20091208), and causes problems with overlapping names and false positives. Below see XML accepted (but wrong), and correct namespace declaration:
```
<rpc><my-own-method></rpc> # Wrong but accepted
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"> # Correct
<my-own-method xmlns="http://example.net/me/my-own/1.0">
</rpc>
```
* To keep old loose semantics set config option CLICON_XML_NS_ITERATE (true by default)
* XML to JSON translator support for mapping xmlns attribute to module name prefix.
* Default namespace is still "urn:ietf:params:xml:ns:netconf:base:1.0"
* See https://github.com/clicon/clixon/issues/49
* Changed all make tags --> make TAGS
* Keyvalue datastore removed (it has been disabled since 3.3.3)
* debug rpc added in example application (should be in clixon-config).
This commit is contained in:
parent
e5c0b06cf9
commit
ae1af8da9e
63 changed files with 1852 additions and 3492 deletions
|
|
@ -658,15 +658,18 @@ yang_find_schemanode(yang_node *yn,
|
|||
return ysmatch;
|
||||
}
|
||||
|
||||
/*! Find first matching data node in all (sub)modules in a yang spec
|
||||
/*! Find first matching data node in all modules in a yang spec (prefixes)
|
||||
*
|
||||
* @param[in] ysp Yang specification
|
||||
* @param[in] argument Name of node. If NULL match first
|
||||
* @param[in] nodeid Name of node. If NULL match first
|
||||
* @param[in] class See yang_class for class of yang nodes
|
||||
* A yang specification has modules as children which in turn can have
|
||||
* syntax-nodes as children. This function goes through all the modules to
|
||||
* look for nodes. Note that if a child to a module is a choice,
|
||||
* the search is made recursively made to the choice's children.
|
||||
* @note works for import prefix, but not work for generic XML parsing where
|
||||
* xmlns and xmlns:ns are used.
|
||||
* @see yang_find_top_ns
|
||||
*/
|
||||
yang_stmt *
|
||||
yang_find_topnode(yang_spec *ysp,
|
||||
|
|
@ -677,7 +680,7 @@ yang_find_topnode(yang_spec *ysp,
|
|||
yang_stmt *yres = NULL; /* result */
|
||||
char *prefix = NULL;
|
||||
char *id = NULL;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
if (yang_nodeid_split(nodeid, &prefix, &id) < 0)
|
||||
goto done;
|
||||
|
|
@ -719,7 +722,7 @@ yang_find_topnode(yang_spec *ysp,
|
|||
}
|
||||
|
||||
/*! Given a yang statement, find the prefix associated to this module
|
||||
* @param[in] ys Yang statement
|
||||
* @param[in] ys Yang statement in module tree (or module itself)
|
||||
* @retval NULL Not found
|
||||
* @retval prefix Prefix as char* pointer into yang tree
|
||||
* @code
|
||||
|
|
@ -745,6 +748,34 @@ yang_find_myprefix(yang_stmt *ys)
|
|||
return prefix;
|
||||
}
|
||||
|
||||
/*! Given a yang statement, find the namespace URI associated to this module
|
||||
* @param[in] ys Yang statement in module tree (or module itself)
|
||||
* @retval NULL Not found
|
||||
* @retval namespace Namspace URI as char* pointer into yang tree
|
||||
* @code
|
||||
* char *myns = yang_find_mynamespace(ys);
|
||||
* @endcode
|
||||
* @see yang_find_module_by_namespace
|
||||
*/
|
||||
char *
|
||||
yang_find_mynamespace(yang_stmt *ys)
|
||||
{
|
||||
yang_stmt *ymod; /* My module */
|
||||
yang_stmt *ynamespace;
|
||||
char *namespace = NULL;
|
||||
|
||||
if ((ymod = ys_module(ys)) == NULL){
|
||||
clicon_err(OE_YANG, 0, "My yang module not found");
|
||||
goto done;
|
||||
}
|
||||
if ((ynamespace = yang_find((yang_node*)ymod, Y_NAMESPACE, NULL)) == NULL)
|
||||
goto done;
|
||||
namespace = ynamespace->ys_argument;
|
||||
done:
|
||||
return namespace;
|
||||
}
|
||||
|
||||
|
||||
/*! Find matching y in yp:s children, return 0 and index or -1 if not found.
|
||||
* @retval 0 not found
|
||||
* @retval 1 found
|
||||
|
|
@ -811,7 +842,52 @@ yang_key2str(int keyword)
|
|||
return (char*)clicon_int2str(ykmap, keyword);
|
||||
}
|
||||
|
||||
/*! Find top module or sub-module given a statement.
|
||||
/*! Find top data node among all modules by namespace in xml tree
|
||||
* @param[in] ysp Yang specification
|
||||
* @param[in] xt XML node
|
||||
* @param[out] ymod Yang module (NULL if not found)
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @note works for xml namespaces (xmlns / xmlns:ns)
|
||||
*/
|
||||
int
|
||||
ys_module_by_xml(yang_spec *ysp,
|
||||
cxobj *xt,
|
||||
yang_stmt **ymodp)
|
||||
{
|
||||
int retval = -1;
|
||||
yang_stmt *ym = NULL; /* module */
|
||||
char *prefix = NULL;
|
||||
char *namespace = NULL; /* namespace URI */
|
||||
|
||||
if (ymodp)
|
||||
*ymodp = NULL;
|
||||
prefix = xml_namespace(xt);
|
||||
if (prefix){
|
||||
/* Get namespace for prefix */
|
||||
if (xml2ns(xt, prefix, &namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
else{
|
||||
/* Get default namespace */
|
||||
if (xml2ns(xt, NULL, &namespace) < 0)
|
||||
goto done;
|
||||
}
|
||||
/* No namespace found, give up */
|
||||
if (namespace == NULL)
|
||||
goto ok;
|
||||
/* We got the namespace, now get the module */
|
||||
ym = yang_find_module_by_namespace(ysp, namespace);
|
||||
/* Set result param */
|
||||
if (ymodp && ym)
|
||||
*ymodp = ym;
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Find the top module or sub-module given a statement from within a yang tree
|
||||
* Ultimate top is yang spec, dont return that
|
||||
* The routine recursively finds ancestors.
|
||||
* @param[in] ys Any yang statement in a yang tree
|
||||
|
|
@ -840,7 +916,7 @@ ys_module(yang_stmt *ys)
|
|||
return ys;
|
||||
}
|
||||
|
||||
/*! Find top of tree, the yang specification
|
||||
/*! Find top of tree, the yang specification from within the tree
|
||||
* @param[in] ys Any yang statement in a yang tree
|
||||
* @retval yspec The top yang specification
|
||||
* @see ys_module
|
||||
|
|
@ -1005,6 +1081,29 @@ yang_find_module_by_prefix(yang_stmt *ys,
|
|||
return ymod;
|
||||
}
|
||||
|
||||
/*! Given a yang statement and a namespace, return yang module
|
||||
*
|
||||
* @param[in] yspec A yang specification
|
||||
* @param[in] namespace namespace
|
||||
* @retval ymod Yang module statement if found
|
||||
* @retval NULL not found
|
||||
*/
|
||||
yang_stmt *
|
||||
yang_find_module_by_namespace(yang_spec *yspec,
|
||||
char *namespace)
|
||||
{
|
||||
yang_stmt *ymod = NULL;
|
||||
|
||||
if (namespace == NULL)
|
||||
goto done;
|
||||
while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) {
|
||||
if (yang_find((yang_node*)ymod, Y_NAMESPACE, namespace) != NULL)
|
||||
break;
|
||||
}
|
||||
done:
|
||||
return ymod;
|
||||
}
|
||||
|
||||
/*! string is quoted if it contains space or tab, needs double '' */
|
||||
static int inline
|
||||
quotedstring(char *s)
|
||||
|
|
@ -1984,6 +2083,7 @@ yang_parse_filename(const char *filename,
|
|||
int fd = -1;
|
||||
struct stat st;
|
||||
|
||||
// clicon_debug(1, "%s %s", __FUNCTION__, filename);
|
||||
if (stat(filename, &st) < 0){
|
||||
clicon_err(OE_YANG, errno, "%s not found", filename);
|
||||
goto done;
|
||||
|
|
@ -2903,6 +3003,8 @@ yang_spec_load_dir(clicon_handle h,
|
|||
len = b-base;
|
||||
else
|
||||
len = strlen(base);
|
||||
/* remove duplicates: there may be cornercases that dont work, eg
|
||||
* mix of revisions and not? */
|
||||
for (j = (i+1); j < ndp; j++)
|
||||
if (strncmp(base, dp[j].d_name, len) == 0)
|
||||
break;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue