* Clixon configuration file top-level symbols has changed to clixon-configand namespace check is enforced.
* clixon-config YAML file has new revision: 2019-03-05. * New URN and changed top-level symbol to `clixon-config` * Removed obsolete `_CLICON_XML_NS_STRICT` variable and `CLICON_XML_NS_STRICT` config option.
This commit is contained in:
parent
4b17af0278
commit
98fb6eceef
50 changed files with 167 additions and 211 deletions
|
|
@ -167,9 +167,26 @@ parse_configfile(clicon_handle h,
|
|||
clicon_err(OE_CFG, 0, "Config file %s: Expected XML but is probably old sh style", filename);
|
||||
goto done;
|
||||
}
|
||||
if ((xc = xpath_first(xt, "config")) == NULL) {
|
||||
clicon_err(OE_CFG, 0, "Config file %s: Lacks top-level \"config\" element", filename);
|
||||
goto done;
|
||||
/* Hard-coded config for < 3.10 and clixon-config for >= 3.10 */
|
||||
if ((xc = xpath_first(xt, "clixon-config")) == NULL){
|
||||
/* Backward compatible code to accept "config" as top-level symbol.
|
||||
This cannot be controlled by config option due to bootstrap */
|
||||
#if 0
|
||||
if ((xc = xpath_first(xt, "config")) != NULL){
|
||||
if (xml_name_set(xc, "clixon-config") < 0)
|
||||
goto done;
|
||||
if (xml_apply0(xc, CX_ELMNT, xml_spec_populate, yspec) < 0)
|
||||
goto done;
|
||||
if (xml_apply0(xc, CX_ELMNT, xml_sort, NULL) < 0)
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
clicon_err(OE_CFG, 0, "Config file %s: Lacks top-level \"clixon_config\" element\nClixon config files should begin with: <clixon-config xmlns=\"http://clicon.org/config\" (See Changelog in Clixon 3.10)>", filename);
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (xml_apply0(xc, CX_ELMNT, xml_default, yspec) < 0)
|
||||
goto done;
|
||||
|
|
@ -286,18 +303,23 @@ clicon_options_main(clicon_handle h,
|
|||
}
|
||||
configfile = hash_value(copt, "CLICON_CONFIGFILE", NULL);
|
||||
clicon_debug(1, "CLICON_CONFIGFILE=%s", configfile);
|
||||
/* If file ends with .xml, assume it is new format */
|
||||
/* File must end with .xml */
|
||||
if ((suffix = rindex(configfile, '.')) != NULL){
|
||||
suffix++;
|
||||
xml = strcmp(suffix, "xml") == 0;
|
||||
}
|
||||
if (xml == 0){
|
||||
clicon_err(OE_CFG, 0, "%s: suffix %s not recognized (Run ./configure --with-config-compat?)", configfile, suffix);
|
||||
clicon_err(OE_CFG, 0, "%s: suffix %s not recognized", configfile, suffix);
|
||||
goto done;
|
||||
}
|
||||
/* XXX Kludge to low-level functions to search for xml in all yang modules */
|
||||
_CLICON_XML_NS_STRICT = 0;
|
||||
/* Read configfile first without yangspec, for bootstrapping */
|
||||
/* Read configfile first without yangspec, for bootstrapping, see second
|
||||
* time below with proper yangspec.
|
||||
* (You need to read the config-file to get the YANG_DIR to find the
|
||||
* the clixon yang-spec)
|
||||
* Difference from parsing with yangspec is:
|
||||
* - no default values
|
||||
* - no sanity checks
|
||||
*/
|
||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
||||
goto done;
|
||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
||||
|
|
@ -308,17 +330,23 @@ clicon_options_main(clicon_handle h,
|
|||
if (yang_spec_parse_module(h, "clixon-config", NULL, yspec) < 0)
|
||||
goto done;
|
||||
clicon_conf_xml_set(h, NULL);
|
||||
if (xconfig)
|
||||
if (xconfig){
|
||||
xml_free(xconfig);
|
||||
xconfig = NULL;
|
||||
}
|
||||
/* Read configfile second time now with check yang spec */
|
||||
if (parse_configfile(h, configfile, yspec, &xconfig) < 0)
|
||||
goto done;
|
||||
if (xml_rootchild(xconfig, 0, &xconfig) < 0)
|
||||
goto done;
|
||||
if (xml_spec(xconfig) == NULL){
|
||||
clicon_err(OE_CFG, 0, "Config file %s: did not find corresponding Yang specification\nHint: File does not begin with: <clixon-config xmlns=\"http://clicon.org/config\"> or clixon-config.yang not found?", configfile);
|
||||
|
||||
goto done;
|
||||
}
|
||||
/* Set clixon_conf pointer to handle */
|
||||
clicon_conf_xml_set(h, xconfig);
|
||||
/* XXX Kludge to low-level functions to search for xml in all yang modules */
|
||||
_CLICON_XML_NS_STRICT = clicon_option_bool(h, "CLICON_XML_NS_STRICT");
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -579,6 +579,7 @@ stream_notify(clicon_handle h,
|
|||
clicon_err(OE_UNIX, errno, "time2str");
|
||||
goto done;
|
||||
}
|
||||
/* From RFC5277 */
|
||||
cprintf(cb, "<notification xmlns=\"urn:ietf:params:xml:ns:netconf:notification:1.0\"><eventTime>%s</eventTime>%s</notification>", timestr, str);
|
||||
if (xml_parse_string(cbuf_get(cb), yspec, &xev) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -135,16 +135,6 @@ struct xml{
|
|||
/*
|
||||
* Variables
|
||||
*/
|
||||
/* If set to 1 which is default, strict namespace checking of XML is made.
|
||||
* If set to 0, "loose" namespace semantics is applied.
|
||||
* This means: iterate through all yang modules to find matching datanode
|
||||
* or rpc if no xmlns attribute specifies namespace.
|
||||
* This is _wrong_, but is the way Clixon originally was written, and some
|
||||
* code still relies on it.
|
||||
* This, of course, should change.
|
||||
* @see CLICON_XML_NS_STRICT clixon configure option
|
||||
*/
|
||||
int _CLICON_XML_NS_STRICT = 1;
|
||||
|
||||
/* Mapping between xml type <--> string */
|
||||
static const map_str2int xsmap[] = {
|
||||
|
|
|
|||
|
|
@ -835,47 +835,6 @@ xml_yang_validate_all_top(cxobj *xt,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*! Given XML node x, find yang spec in _any_ module matching name
|
||||
* This is non-struct namespace semantics (not correct) but necessary
|
||||
* in historic Clixon code.
|
||||
* Also, add a proper default namespaces statement (xmlns="uri") in x
|
||||
* @param[in] x XML node (find yang statement on this one)
|
||||
* @param[in] yspec Top-level yang spec
|
||||
* @param[out] y Yang stmt associated to x. NULL i not found
|
||||
* @retval 0 OK
|
||||
* @see CLICON_XML_NS_STRICT clixon config option
|
||||
*/
|
||||
int
|
||||
xml_yang_find_non_strict(cxobj *x,
|
||||
yang_spec *yspec,
|
||||
yang_stmt **yp)
|
||||
{
|
||||
int retval = -1;
|
||||
char *name;
|
||||
yang_stmt *ymod;
|
||||
int i;
|
||||
yang_stmt *y=NULL;
|
||||
char *ns;
|
||||
|
||||
name = xml_name(x);
|
||||
for (i=0; i<yspec->yp_len; i++){
|
||||
ymod = yspec->yp_stmt[i];
|
||||
if ((y = yang_find_schemanode((yang_node*)ymod, name)) != NULL)
|
||||
break;
|
||||
}
|
||||
if (y){
|
||||
*yp = y;
|
||||
if ((ns = yang_find_mynamespace(ymod)) != NULL){
|
||||
if (xml_find_type_value(x, NULL, "xmlns", CX_ATTR) == NULL)
|
||||
if (xmlns_set(x, NULL, ns) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Translate a single xml node to a cligen variable vector. Note not recursive
|
||||
* @param[in] xt XML tree containing one top node
|
||||
* @param[in] ys Yang spec containing type specification of top-node of xt
|
||||
|
|
@ -1738,11 +1697,6 @@ xml_spec_populate_rpc(clicon_handle h,
|
|||
yrpc = yang_find((yang_node*)ymod, Y_RPC, xml_name(x));
|
||||
/* Non-strict semantics: loop through all modules to find the node
|
||||
*/
|
||||
if (yrpc == NULL &&
|
||||
!clicon_option_bool(h, "CLICON_XML_NS_STRICT")){
|
||||
if (xml_yang_find_non_strict(x, yspec, &yrpc) < 0) /* find rpc */
|
||||
goto done;
|
||||
}
|
||||
if (yrpc){
|
||||
xml_spec_set(x, yrpc);
|
||||
if ((yi = yang_find((yang_node*)yrpc, Y_INPUT, NULL)) != NULL){
|
||||
|
|
@ -1758,14 +1712,12 @@ xml_spec_populate_rpc(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Add yang specification backpointer to XML node
|
||||
* @param[in] xt XML tree node
|
||||
* @param[in] arg Yang spec
|
||||
* @note This may be unnecessary if yspec is set on creation
|
||||
* @note For subs to anyxml nodes will not have spec set
|
||||
* @note No validation is done,... XXX
|
||||
* @note relies on kludge _CLICON_XML_NS_STRICT
|
||||
* @code
|
||||
* xml_apply(xc, CX_ELMNT, xml_spec_populate, yspec)
|
||||
* @endcode
|
||||
|
|
@ -1795,12 +1747,6 @@ xml_spec_populate(cxobj *x,
|
|||
goto done;
|
||||
if (ymod != NULL)
|
||||
y = yang_find_schemanode((yang_node*)ymod, name);
|
||||
/* Non-strict semantics: loop through all modules to find the node
|
||||
*/
|
||||
if (y == NULL && !_CLICON_XML_NS_STRICT){
|
||||
if (xml_yang_find_non_strict(x, yspec, &y) < 0)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (y)
|
||||
xml_spec_set(x, y);
|
||||
|
|
|
|||
|
|
@ -156,7 +156,10 @@ xml_child_spec(cxobj *x,
|
|||
char *name;
|
||||
|
||||
name = xml_name(x);
|
||||
|
||||
if (xp && (yparent = xml_spec(xp)) != NULL){
|
||||
/* First case: parent already has an associated yang statement,
|
||||
* then find matching child of that */
|
||||
if (yparent->ys_keyword == Y_RPC){
|
||||
if ((yi = yang_find((yang_node*)yparent, Y_INPUT, NULL)) != NULL)
|
||||
y = yang_find_datanode((yang_node*)yi, name);
|
||||
|
|
@ -165,14 +168,12 @@ xml_child_spec(cxobj *x,
|
|||
y = yang_find_datanode((yang_node*)yparent, name);
|
||||
}
|
||||
else if (yspec){
|
||||
/* Second case, this is a "root", need to find yang stmt from spec
|
||||
*/
|
||||
if (ys_module_by_xml(yspec, xp, &ymod) < 0)
|
||||
goto done;
|
||||
if (ymod != NULL)
|
||||
y = yang_find_schemanode((yang_node*)ymod, name);
|
||||
if (y == NULL && !_CLICON_XML_NS_STRICT){
|
||||
if (xml_yang_find_non_strict(x, yspec, &y) < 0) /* schemanode */
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
y = NULL;
|
||||
|
|
|
|||
|
|
@ -1801,12 +1801,13 @@ yang_expand(yang_node *yn)
|
|||
* Syntax parsing. A string is input and a syntax-tree is returned (or error).
|
||||
* A variable record is also returned containing a list of (global) variable values.
|
||||
* (cloned from cligen)
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] str String of yang statements
|
||||
* @param[in] name Log string, typically filename
|
||||
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] str String of yang statements
|
||||
* @param[in] name Log string, typically filename
|
||||
* @param[in] ysp Yang specification. Should ave been created by caller
|
||||
* using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error encountered
|
||||
* @retval NULL Error encountered
|
||||
* Calling order:
|
||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue