New plugin callback: ca_yang_patch - for modifying existing YANG modules
C-API: Added `spec` parameter to `xml2xpath()`
This commit is contained in:
parent
48a0fb9968
commit
a5220805b1
16 changed files with 318 additions and 193 deletions
|
|
@ -49,6 +49,7 @@ Expected: beginning of 2023
|
||||||
* Only schema-ref=inline, not shared-schema
|
* Only schema-ref=inline, not shared-schema
|
||||||
* Only presence containers can be mount-points
|
* Only presence containers can be mount-points
|
||||||
* New plugin callback: `ca_yang_mount`
|
* New plugin callback: `ca_yang_mount`
|
||||||
|
* To specify which YANG modules should be mounted
|
||||||
* Standards: RFC 8528
|
* Standards: RFC 8528
|
||||||
* To enable configure with `--enable-yang-schema-mount`
|
* To enable configure with `--enable-yang-schema-mount`
|
||||||
* Netconf monitoring RFC 6022
|
* Netconf monitoring RFC 6022
|
||||||
|
|
@ -86,6 +87,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 `spec` parameter to `xml2xpath()`, default 0
|
||||||
* Added `clicon_handle` parameter to all `xml_bind_*` calls
|
* Added `clicon_handle` parameter to all `xml_bind_*` calls
|
||||||
* All calls to `clicon_log_xml()` changed to new function `clicon_debug_xml()`
|
* All calls to `clicon_log_xml()` changed to new function `clicon_debug_xml()`
|
||||||
* Changed type of `veclen` parameter to `size_t` in `xpath_vec_flag()`
|
* Changed type of `veclen` parameter to `size_t` in `xpath_vec_flag()`
|
||||||
|
|
@ -94,6 +96,9 @@ Developers may need to change their code
|
||||||
|
|
||||||
### Minor features
|
### Minor features
|
||||||
|
|
||||||
|
* New plugin callbacks
|
||||||
|
* `ca_yang_mount` - see the RFC 8528 support
|
||||||
|
* `ca_yang_patch` - for modifying existing YANG modules
|
||||||
* Changed debug levels in `clicon_debug()` to be based on maskable flags:
|
* Changed debug levels in `clicon_debug()` to be based on maskable flags:
|
||||||
* Added flag names: `CLIXON_DBG_*`
|
* Added flag names: `CLIXON_DBG_*`
|
||||||
* Added maskable flags that can be combined when debugging:
|
* Added maskable flags that can be combined when debugging:
|
||||||
|
|
|
||||||
|
|
@ -485,7 +485,8 @@ from_client_edit_config(clicon_handle h,
|
||||||
/* <config> yang spec may be set to anyxml by ingress yang check,...*/
|
/* <config> yang spec may be set to anyxml by ingress yang check,...*/
|
||||||
if (xml_spec(xc) != NULL)
|
if (xml_spec(xc) != NULL)
|
||||||
xml_spec_set(xc, NULL);
|
xml_spec_set(xc, NULL);
|
||||||
/* Populate XML with Yang spec (why not do this in parser?)
|
/* Populate XML with Yang spec. Binding is done in from_client_msg only frm an RPC perspective,
|
||||||
|
* where <config> is ANYDATA
|
||||||
*/
|
*/
|
||||||
if ((ret = xml_bind_yang(h, xc, YB_MODULE, yspec, &xret)) < 0)
|
if ((ret = xml_bind_yang(h, xc, YB_MODULE, yspec, &xret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1560,7 +1561,7 @@ from_client_msg(clicon_handle h,
|
||||||
* 2. The backend has restarted and the client uses an old op_id
|
* 2. The backend has restarted and the client uses an old op_id
|
||||||
*/
|
*/
|
||||||
if (op_id != 0 && ce->ce_id != op_id){
|
if (op_id != 0 && ce->ce_id != op_id){
|
||||||
clicon_debug(1, "%s out-of-order sequence op-id:%u ce_id:%u", __FUNCTION__, op_id, ce->ce_id);
|
clicon_debug(1, "%s Warning: incoming session-id:%u does not match socket ce_id:%u", __FUNCTION__, op_id, ce->ce_id);
|
||||||
}
|
}
|
||||||
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
/* Check for empty frame (no mesaages), return empty message, not clear from RFC what to do */
|
||||||
if (xml_child_nr_type(xt, CX_ELMNT) == 0){
|
if (xml_child_nr_type(xt, CX_ELMNT) == 0){
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,19 @@ typedef int (datastore_upgrade_t)(clicon_handle h, const char *db, cxobj *xt, mo
|
||||||
*/
|
*/
|
||||||
typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, cxobj **yanglib);
|
typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, cxobj **yanglib);
|
||||||
|
|
||||||
|
/*! YANG module patch
|
||||||
|
*
|
||||||
|
* Given a parsed YANG module, give the ability to patch it before import recursion,
|
||||||
|
* grouping/uses checks, augments, etc
|
||||||
|
* Can be useful if YANG in some way needs modification.
|
||||||
|
* Deviations could be used as alternative (probably better)
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] ymod YANG module
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
typedef int (yang_patch_t)(clicon_handle h, yang_stmt *ymod);
|
||||||
|
|
||||||
/*! Startup status for use in startup-callback
|
/*! Startup status for use in startup-callback
|
||||||
* Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode
|
* Note that for STARTUP_ERR and STARTUP_INVALID, running runs in failsafe mode
|
||||||
* and startup contains the erroneous or invalid database.
|
* and startup contains the erroneous or invalid database.
|
||||||
|
|
@ -315,6 +328,8 @@ struct clixon_plugin_api{
|
||||||
plgstart_t *ca_start; /* Plugin start */
|
plgstart_t *ca_start; /* Plugin start */
|
||||||
plgexit_t *ca_exit; /* Plugin exit */
|
plgexit_t *ca_exit; /* Plugin exit */
|
||||||
plgextension_t *ca_extension; /* Yang extension/unknown handler */
|
plgextension_t *ca_extension; /* Yang extension/unknown handler */
|
||||||
|
yang_mount_t *ca_yang_mount; /* RFC 8528 schema mount */
|
||||||
|
yang_patch_t *ca_yang_patch; /* Patch yang after parse */
|
||||||
union {
|
union {
|
||||||
struct { /* cli-specific */
|
struct { /* cli-specific */
|
||||||
cli_prompthook_t *ci_prompt; /* Prompt hook */
|
cli_prompthook_t *ci_prompt; /* Prompt hook */
|
||||||
|
|
@ -342,7 +357,6 @@ struct clixon_plugin_api{
|
||||||
trans_cb_t *cb_trans_end; /* Transaction completed */
|
trans_cb_t *cb_trans_end; /* Transaction completed */
|
||||||
trans_cb_t *cb_trans_abort; /* Transaction aborted */
|
trans_cb_t *cb_trans_abort; /* Transaction aborted */
|
||||||
datastore_upgrade_t *cb_datastore_upgrade; /* General-purpose datastore upgrade */
|
datastore_upgrade_t *cb_datastore_upgrade; /* General-purpose datastore upgrade */
|
||||||
yang_mount_t *cb_yang_mount; /* RFC 8528 schema mount */
|
|
||||||
} cau_backend;
|
} cau_backend;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
@ -365,7 +379,6 @@ struct clixon_plugin_api{
|
||||||
#define ca_trans_end u.cau_backend.cb_trans_end
|
#define ca_trans_end u.cau_backend.cb_trans_end
|
||||||
#define ca_trans_abort u.cau_backend.cb_trans_abort
|
#define ca_trans_abort u.cau_backend.cb_trans_abort
|
||||||
#define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade
|
#define ca_datastore_upgrade u.cau_backend.cb_datastore_upgrade
|
||||||
#define ca_yang_mount u.cau_backend.cb_yang_mount
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Macros
|
* Macros
|
||||||
|
|
@ -444,6 +457,9 @@ int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *
|
||||||
int clixon_plugin_yang_mount_one(clixon_plugin_t *cp, clicon_handle h, cxobj *xt, cxobj **yanglib);
|
int clixon_plugin_yang_mount_one(clixon_plugin_t *cp, clicon_handle h, cxobj *xt, cxobj **yanglib);
|
||||||
int clixon_plugin_yang_mount_all(clicon_handle h, cxobj *xt, cxobj **yanglib);
|
int clixon_plugin_yang_mount_all(clicon_handle h, cxobj *xt, cxobj **yanglib);
|
||||||
|
|
||||||
|
int clixon_plugin_yang_patch_one(clixon_plugin_t *cp, clicon_handle h, yang_stmt *ymod);
|
||||||
|
int clixon_plugin_yang_patch_all(clicon_handle h, yang_stmt *ymod);
|
||||||
|
|
||||||
/* rpc callback API */
|
/* rpc callback API */
|
||||||
int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name);
|
int rpc_callback_register(clicon_handle h, clicon_rpc_cb cb, void *arg, const char *ns, const char *name);
|
||||||
int rpc_callback_call(clicon_handle h, cxobj *xe, void *arg, int *nrp, cbuf *cbret);
|
int rpc_callback_call(clicon_handle h, cxobj *xe, void *arg, int *nrp, cbuf *cbret);
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ int xml_tree_prune_flags(cxobj *xt, int flags, int mask);
|
||||||
int xml_namespace_change(cxobj *x, char *ns, char *prefix);
|
int xml_namespace_change(cxobj *x, char *ns, char *prefix);
|
||||||
int xml_sanity(cxobj *x, void *arg);
|
int xml_sanity(cxobj *x, void *arg);
|
||||||
int xml_non_config_data(cxobj *xt, cxobj **xerr);
|
int xml_non_config_data(cxobj *xt, cxobj **xerr);
|
||||||
int xml2xpath(cxobj *x, cvec *nsc, char **xpath);
|
|
||||||
int assign_namespace_element(cxobj *x0, cxobj *x1, cxobj *x1p);
|
int assign_namespace_element(cxobj *x0, cxobj *x1, cxobj *x1p);
|
||||||
int assign_namespace_body(cxobj *x0, cxobj *x1);
|
int assign_namespace_body(cxobj *x0, cxobj *x1);
|
||||||
int xml_merge(cxobj *x0, cxobj *x1, yang_stmt *yspec, char **reason);
|
int xml_merge(cxobj *x0, cxobj *x1, yang_stmt *yspec, char **reason);
|
||||||
|
|
|
||||||
|
|
@ -150,5 +150,6 @@ int xpath_vec(cxobj *xcur, cvec *nsc, const char *xpformat, cxobj ***vec, siz
|
||||||
|
|
||||||
int xpath2canonical(const char *xpath0, cvec *nsc0, yang_stmt *yspec, char **xpath1, cvec **nsc1, cbuf **cbreason);
|
int xpath2canonical(const char *xpath0, cvec *nsc0, yang_stmt *yspec, char **xpath1, cvec **nsc1, cbuf **cbreason);
|
||||||
int xpath_count(cxobj *xcur, cvec *nsc, const char *xpath, uint32_t *count);
|
int xpath_count(cxobj *xcur, cvec *nsc, const char *xpath, uint32_t *count);
|
||||||
|
int xml2xpath(cxobj *x, cvec *nsc, int spec, char **xpath);
|
||||||
|
|
||||||
#endif /* _CLIXON_XPATH_H */
|
#endif /* _CLIXON_XPATH_H */
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
*/
|
*/
|
||||||
yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
|
yang_stmt *yang_parse_file(FILE *fp, const char *name, yang_stmt *ysp);
|
||||||
int yang_file_find_match(clicon_handle h, const char *module, const char *revision, cbuf *fbuf);
|
int yang_file_find_match(clicon_handle h, const char *module, const char *revision, cbuf *fbuf);
|
||||||
yang_stmt *yang_parse_filename(const char *filename, yang_stmt *ysp);
|
yang_stmt *yang_parse_filename(clicon_handle h, const char *filename, yang_stmt *ysp);
|
||||||
yang_stmt *yang_parse_module(clicon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname);
|
yang_stmt *yang_parse_module(clicon_handle h, const char *module, const char *revision, yang_stmt *yspec, char *origname);
|
||||||
int yang_parse_post(clicon_handle h, yang_stmt *yspec, int modmin);
|
int yang_parse_post(clicon_handle h, yang_stmt *yspec, int modmin);
|
||||||
int yang_spec_parse_module(clicon_handle h, const char *module,
|
int yang_spec_parse_module(clicon_handle h, const char *module,
|
||||||
|
|
|
||||||
|
|
@ -487,6 +487,10 @@ text_modify(clicon_handle h,
|
||||||
char *createstr = NULL;
|
char *createstr = NULL;
|
||||||
yang_stmt *yrestype = NULL;
|
yang_stmt *yrestype = NULL;
|
||||||
char *restype;
|
char *restype;
|
||||||
|
#ifdef CLIXON_YANG_SCHEMA_MOUNT
|
||||||
|
int ismount = 0;
|
||||||
|
yang_stmt *mount_yspec = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (x1 == NULL){
|
if (x1 == NULL){
|
||||||
clicon_err(OE_XML, EINVAL, "x1 is missing");
|
clicon_err(OE_XML, EINVAL, "x1 is missing");
|
||||||
|
|
@ -908,6 +912,15 @@ text_modify(clicon_handle h,
|
||||||
yc = xml_spec(x1c);
|
yc = xml_spec(x1c);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifdef CLIXON_YANG_SCHEMA_MOUNT
|
||||||
|
/* Check if xc is unresolved mountpoint, ie no yang mount binding yet */
|
||||||
|
if ((ismount = xml_yang_mount_get(x1c, &mount_yspec)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (ismount && mount_yspec == NULL){
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
|
if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t,
|
||||||
yc, op,
|
yc, op,
|
||||||
username, xnacm, permit, cbret)) < 0)
|
username, xnacm, permit, cbret)) < 0)
|
||||||
|
|
|
||||||
|
|
@ -1045,7 +1045,7 @@ netconf_missing_choice_xml(cxobj **xret,
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* error-path: Path to the element with the missing choice. */
|
/* error-path: Path to the element with the missing choice. */
|
||||||
if (xml2xpath(x, NULL, &path) < 0)
|
if (xml2xpath(x, NULL, 0, &path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1407,7 +1407,7 @@ netconf_data_not_unique_xml(cxobj **xret,
|
||||||
if (cvec_len(cvk)){
|
if (cvec_len(cvk)){
|
||||||
if ((xinfo = xml_new("error-info", xerr, CX_ELMNT)) == NULL)
|
if ((xinfo = xml_new("error-info", xerr, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml2xpath(x, NULL, &path) < 0)
|
if (xml2xpath(x, NULL, 0, &path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1465,7 +1465,7 @@ netconf_minmax_elements_xml(cxobj **xret,
|
||||||
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
if ((xerr = xml_new("rpc-error", *xret, CX_ELMNT)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_parent(xp)){ /* Dont include root, eg <config> */
|
if (xml_parent(xp)){ /* Dont include root, eg <config> */
|
||||||
if (xml2xpath(xp, NULL, &path) < 0)
|
if (xml2xpath(xp, NULL, 0, &path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
if (xml_chardata_encode(&encpath, "%s", path) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -1069,6 +1069,65 @@ clixon_plugin_yang_mount_all(clicon_handle h,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Call plugin YANG schema patch
|
||||||
|
*
|
||||||
|
|
||||||
|
* @param[in] cp Plugin handle
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] ymod YANG module
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_plugin_yang_patch_one(clixon_plugin_t *cp,
|
||||||
|
clicon_handle h,
|
||||||
|
yang_stmt *ymod)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
yang_patch_t *fn;
|
||||||
|
void *wh = NULL;
|
||||||
|
|
||||||
|
if ((fn = cp->cp_api.ca_yang_patch) != NULL){
|
||||||
|
wh = NULL;
|
||||||
|
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
|
if (fn(h, ymod) < 0) {
|
||||||
|
if (clicon_errno < 0)
|
||||||
|
clicon_log(LOG_WARNING, "%s: Internal error: Yang patch callback in plugin: %s returned -1 but did not make a clicon_err call",
|
||||||
|
__FUNCTION__, cp->cp_name);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Call plugin YANG schema patch in all plugins.
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] ymod YANG module
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clixon_plugin_yang_patch_all(clicon_handle h,
|
||||||
|
yang_stmt *ymod)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
clixon_plugin_t *cp = NULL;
|
||||||
|
|
||||||
|
while ((cp = clixon_plugin_each(h, cp)) != NULL) {
|
||||||
|
if (clixon_plugin_yang_patch_one(cp, h, ymod) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
||||||
* RPC callbacks for both client/frontend and backend plugins.
|
* RPC callbacks for both client/frontend and backend plugins.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -579,7 +579,14 @@ xml_bind_yang0(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! RPC-specific
|
/*! RPC-specific
|
||||||
* @param[in] h Clixon handle (sometimes NULL)
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] xn XML action node
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[out] xerr Reason for failure, or NULL
|
||||||
|
* @retval 1 OK yang assignment made
|
||||||
|
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xml_bind_yang_rpc_rpc(clicon_handle h,
|
xml_bind_yang_rpc_rpc(clicon_handle h,
|
||||||
|
|
@ -637,7 +644,13 @@ xml_bind_yang_rpc_rpc(clicon_handle h,
|
||||||
* Find the innermost container or list containing an XML element that carries the name of the
|
* Find the innermost container or list containing an XML element that carries the name of the
|
||||||
* defined action.
|
* defined action.
|
||||||
* Only one action can be invoked in one rpc
|
* Only one action can be invoked in one rpc
|
||||||
* @param[in] h Clixon handle (sometimes NULL)
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] xn XML action node
|
||||||
|
* @param[in] yspec Yang spec
|
||||||
|
* @param[out] xerr Reason for failure, or NULL
|
||||||
|
* @retval 1 OK yang assignment made
|
||||||
|
* @retval 0 Partial or no yang assigment made (at least one failed) and xerr set
|
||||||
|
* @retval -1 Error
|
||||||
* XXX if not more action, consider folding into calling function
|
* XXX if not more action, consider folding into calling function
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
|
|
@ -671,7 +684,7 @@ xml_bind_yang_rpc_action(clicon_handle h,
|
||||||
/*! Find yang spec association of XML node for incoming RPC starting with <rpc>
|
/*! Find yang spec association of XML node for incoming RPC starting with <rpc>
|
||||||
*
|
*
|
||||||
* Incoming RPC has an "input" structure that is not taken care of by xml_bind_yang
|
* Incoming RPC has an "input" structure that is not taken care of by xml_bind_yang
|
||||||
* @param[in] h Clixon handle (sometimes NULL)
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xrpc XML rpc node
|
* @param[in] xrpc XML rpc node
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[out] xerr Reason for failure, or NULL
|
* @param[out] xerr Reason for failure, or NULL
|
||||||
|
|
|
||||||
|
|
@ -732,140 +732,6 @@ xml_non_config_data(cxobj *xt,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Given an XML node, build an xpath recursively to root, internal function
|
|
||||||
* @param[in] x XML object
|
|
||||||
* @param[in] nsc Namespace context
|
|
||||||
* @param[out] cb XPath string as cbuf.
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error. eg XML malformed
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
xml2xpath1(cxobj *x,
|
|
||||||
cvec *nsc,
|
|
||||||
cbuf *cb)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cxobj *xp;
|
|
||||||
yang_stmt *y = NULL;
|
|
||||||
cvec *cvk = NULL; /* vector of index keys */
|
|
||||||
cg_var *cvi;
|
|
||||||
char *keyname;
|
|
||||||
cxobj *xkey;
|
|
||||||
cxobj *xb;
|
|
||||||
char *b;
|
|
||||||
enum rfc_6020 keyword;
|
|
||||||
char *prefix = NULL;
|
|
||||||
char *namespace;
|
|
||||||
|
|
||||||
if ((xp = xml_parent(x)) == NULL)
|
|
||||||
goto ok;
|
|
||||||
if (xml2xpath1(xp, nsc, cb) < 0)
|
|
||||||
goto done;
|
|
||||||
if (nsc){
|
|
||||||
if (xml2ns(x, xml_prefix(x), &namespace) < 0)
|
|
||||||
goto done;
|
|
||||||
if (namespace){
|
|
||||||
if (xml_nsctx_get_prefix(nsc, namespace, &prefix) == 0)
|
|
||||||
; /* maybe NULL? */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
prefix = xml_prefix(x); /* maybe NULL? */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
prefix = xml_prefix(x);
|
|
||||||
/* XXX: sometimes there should be a /, sometimes not */
|
|
||||||
cprintf(cb, "/");
|
|
||||||
if (prefix)
|
|
||||||
cprintf(cb, "%s:", prefix);
|
|
||||||
cprintf(cb, "%s", xml_name(x));
|
|
||||||
if ((y = xml_spec(x)) != NULL){
|
|
||||||
keyword = yang_keyword_get(y);
|
|
||||||
switch (keyword){
|
|
||||||
case Y_LEAF_LIST:
|
|
||||||
if ((b = xml_body(x)) != NULL)
|
|
||||||
cprintf(cb, "[.=\"%s\"]", b);
|
|
||||||
else
|
|
||||||
cprintf(cb, "[.=\"\"]");
|
|
||||||
break;
|
|
||||||
case Y_LIST:
|
|
||||||
cvk = yang_cvec_get(y);
|
|
||||||
cvi = NULL;
|
|
||||||
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
|
||||||
keyname = cv_string_get(cvi);
|
|
||||||
if ((xkey = xml_find(x, keyname)) == NULL)
|
|
||||||
goto done; /* No key in xml */
|
|
||||||
if ((xb = xml_find(x, keyname)) == NULL)
|
|
||||||
goto done;
|
|
||||||
b = xml_body(xb);
|
|
||||||
cprintf(cb, "[");
|
|
||||||
if (prefix)
|
|
||||||
cprintf(cb, "%s:", prefix);
|
|
||||||
cprintf(cb, "%s=\"%s\"]", keyname, b?b:"");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ok:
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Given an XML node, build an xpath to root
|
|
||||||
*
|
|
||||||
* Creates an XPath from an XML node with some limitations, see notes below.
|
|
||||||
* The prefixes used are from the given namespace context if any, otherwise the native prefixes are used, if any.
|
|
||||||
* Note that this means that prefixes may be translated such as if the XML namespace mapping is different than the once used
|
|
||||||
* in the XML.
|
|
||||||
* Therefore, if nsc is "canonical", the returned xpath is also "canonical", even though the XML is not.
|
|
||||||
* @param[in] x XML object
|
|
||||||
* @param[in] nsc Namespace context
|
|
||||||
* @param[out] xpath Malloced xpath string. Need to free() after use
|
|
||||||
* @retval 0 OK
|
|
||||||
* @retval -1 Error. (eg XML malformed)
|
|
||||||
* @code
|
|
||||||
* char *xpath = NULL;
|
|
||||||
* cxobj *x;
|
|
||||||
* ... x is inside an xml tree ...
|
|
||||||
* if (xml2xpath(x, nsc, &xpath) < 0)
|
|
||||||
* err;
|
|
||||||
* free(xpath);
|
|
||||||
* @endcode
|
|
||||||
* @note x needs to be bound to YANG, see eg xml_bind_yang()
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
xml2xpath(cxobj *x,
|
|
||||||
cvec *nsc,
|
|
||||||
char **xpathp)
|
|
||||||
{
|
|
||||||
int retval = -1;
|
|
||||||
cbuf *cb;
|
|
||||||
char *xpath = NULL;
|
|
||||||
|
|
||||||
if ((cb = cbuf_new()) == NULL){
|
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (xml2xpath1(x, nsc, cb) < 0)
|
|
||||||
goto done;
|
|
||||||
/* XXX: see xpath in test statement,.. */
|
|
||||||
xpath = cbuf_get(cb);
|
|
||||||
if (xpathp){
|
|
||||||
if ((*xpathp = strdup(xpath)) == NULL){
|
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
xpath = NULL;
|
|
||||||
}
|
|
||||||
retval = 0;
|
|
||||||
done:
|
|
||||||
if (cb)
|
|
||||||
cbuf_free(cb);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! Check if the module tree x is in is assigned right XML namespace, assign if not
|
/*! Check if the module tree x is in is assigned right XML namespace, assign if not
|
||||||
* @param[in] x XML node
|
* @param[in] x XML node
|
||||||
*(0. You should probably find the XML root and apply this function to that.)
|
*(0. You should probably find the XML root and apply this function to that.)
|
||||||
|
|
|
||||||
|
|
@ -1164,3 +1164,143 @@ xpath_count(cxobj *xcur,
|
||||||
ctx_free(xc);
|
ctx_free(xc);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Given an XML node, build an xpath recursively to root, internal function
|
||||||
|
* @param[in] x XML object
|
||||||
|
* @param[in] nsc Namespace context
|
||||||
|
* @param[in] spec If set, recursively continue only to root without spec
|
||||||
|
* @param[out] cb XPath string as cbuf.
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error. eg XML malformed
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml2xpath1(cxobj *x,
|
||||||
|
cvec *nsc,
|
||||||
|
int spec,
|
||||||
|
cbuf *cb)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cxobj *xp;
|
||||||
|
yang_stmt *y = NULL;
|
||||||
|
cvec *cvk = NULL; /* vector of index keys */
|
||||||
|
cg_var *cvi;
|
||||||
|
char *keyname;
|
||||||
|
cxobj *xkey;
|
||||||
|
cxobj *xb;
|
||||||
|
char *b;
|
||||||
|
enum rfc_6020 keyword;
|
||||||
|
char *prefix = NULL;
|
||||||
|
char *namespace;
|
||||||
|
|
||||||
|
if ((xp = xml_parent(x)) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if (spec && xml_spec(x) == NULL)
|
||||||
|
goto ok;
|
||||||
|
if (xml2xpath1(xp, nsc, spec, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
if (nsc){
|
||||||
|
if (xml2ns(x, xml_prefix(x), &namespace) < 0)
|
||||||
|
goto done;
|
||||||
|
if (namespace){
|
||||||
|
if (xml_nsctx_get_prefix(nsc, namespace, &prefix) == 0)
|
||||||
|
; /* maybe NULL? */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prefix = xml_prefix(x); /* maybe NULL? */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
prefix = xml_prefix(x);
|
||||||
|
/* XXX: sometimes there should be a /, sometimes not */
|
||||||
|
cprintf(cb, "/");
|
||||||
|
if (prefix)
|
||||||
|
cprintf(cb, "%s:", prefix);
|
||||||
|
cprintf(cb, "%s", xml_name(x));
|
||||||
|
if ((y = xml_spec(x)) != NULL){
|
||||||
|
keyword = yang_keyword_get(y);
|
||||||
|
switch (keyword){
|
||||||
|
case Y_LEAF_LIST:
|
||||||
|
if ((b = xml_body(x)) != NULL)
|
||||||
|
cprintf(cb, "[.=\"%s\"]", b);
|
||||||
|
else
|
||||||
|
cprintf(cb, "[.=\"\"]");
|
||||||
|
break;
|
||||||
|
case Y_LIST:
|
||||||
|
cvk = yang_cvec_get(y);
|
||||||
|
cvi = NULL;
|
||||||
|
while ((cvi = cvec_each(cvk, cvi)) != NULL) {
|
||||||
|
keyname = cv_string_get(cvi);
|
||||||
|
if ((xkey = xml_find(x, keyname)) == NULL)
|
||||||
|
goto done; /* No key in xml */
|
||||||
|
if ((xb = xml_find(x, keyname)) == NULL)
|
||||||
|
goto done;
|
||||||
|
b = xml_body(xb);
|
||||||
|
cprintf(cb, "[");
|
||||||
|
if (prefix)
|
||||||
|
cprintf(cb, "%s:", prefix);
|
||||||
|
cprintf(cb, "%s=\"%s\"]", keyname, b?b:"");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok:
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Given an XML node, build an xpath to root
|
||||||
|
*
|
||||||
|
* Creates an XPath from an XML node with some limitations, see notes below.
|
||||||
|
* The prefixes used are from the given namespace context if any, otherwise the native prefixes are used, if any.
|
||||||
|
* Note that this means that prefixes may be translated such as if the XML namespace mapping is different than the once used
|
||||||
|
* in the XML.
|
||||||
|
* Therefore, if nsc is "canonical", the returned xpath is also "canonical", even though the XML is not.
|
||||||
|
* @param[in] x XML object
|
||||||
|
* @param[in] nsc Namespace context
|
||||||
|
* @param[in] spec If set, recursively continue only to root without spec
|
||||||
|
* @param[out] xpath Malloced xpath string. Need to free() after use
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error. (eg XML malformed)
|
||||||
|
* @code
|
||||||
|
* char *xpath = NULL;
|
||||||
|
* cxobj *x;
|
||||||
|
* ... x is inside an xml tree ...
|
||||||
|
* if (xml2xpath(x, nsc, &xpath) < 0)
|
||||||
|
* err;
|
||||||
|
* free(xpath);
|
||||||
|
* @endcode
|
||||||
|
* @note x needs to be bound to YANG, see eg xml_bind_yang()
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
xml2xpath(cxobj *x,
|
||||||
|
cvec *nsc,
|
||||||
|
int spec,
|
||||||
|
char **xpathp)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cbuf *cb;
|
||||||
|
char *xpath = NULL;
|
||||||
|
|
||||||
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (xml2xpath1(x, nsc, spec, cb) < 0)
|
||||||
|
goto done;
|
||||||
|
/* XXX: see xpath in test statement,.. */
|
||||||
|
xpath = cbuf_get(cb);
|
||||||
|
if (xpathp){
|
||||||
|
if ((*xpathp = strdup(xpath)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
xpath = NULL;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (cb)
|
||||||
|
cbuf_free(cb);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1013,6 +1013,7 @@ done:
|
||||||
/*! Open a file, read into a string and invoke yang parsing
|
/*! Open a file, read into a string and invoke yang parsing
|
||||||
*
|
*
|
||||||
* Similar to clicon_yang_str(), just read a file first
|
* Similar to clicon_yang_str(), just read a file first
|
||||||
|
* @param[in] h Clixon handle (can be NULL, but then no callbacks)
|
||||||
* @param[in] filename Name of file
|
* @param[in] filename Name of file
|
||||||
* @param[in] yspec Yang specification. Should have been created by caller using yspec_new
|
* @param[in] yspec Yang specification. Should have been created by caller using yspec_new
|
||||||
* @retval ymod Top-level yang (sub)module
|
* @retval ymod Top-level yang (sub)module
|
||||||
|
|
@ -1022,7 +1023,8 @@ done:
|
||||||
* See top of file for diagram of calling order
|
* See top of file for diagram of calling order
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
yang_parse_filename(const char *filename,
|
yang_parse_filename(clicon_handle h,
|
||||||
|
const char *filename,
|
||||||
yang_stmt *yspec)
|
yang_stmt *yspec)
|
||||||
{
|
{
|
||||||
yang_stmt *ymod = NULL;
|
yang_stmt *ymod = NULL;
|
||||||
|
|
@ -1040,6 +1042,9 @@ yang_parse_filename(const char *filename,
|
||||||
}
|
}
|
||||||
if ((ymod = yang_parse_file(fp, filename, yspec)) < 0)
|
if ((ymod = yang_parse_file(fp, filename, yspec)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
/* YANG patch hook */
|
||||||
|
if (h && clixon_plugin_yang_patch_all(h, ymod) < 0)
|
||||||
|
goto done;
|
||||||
done:
|
done:
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
@ -1097,7 +1102,7 @@ yang_parse_module(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
filename = cbuf_get(fbuf);
|
filename = cbuf_get(fbuf);
|
||||||
if ((ymod = yang_parse_filename(filename, yspec)) == NULL)
|
if ((ymod = yang_parse_filename(h, filename, yspec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
/* Sanity check that requested module name matches loaded module
|
/* Sanity check that requested module name matches loaded module
|
||||||
* If this does not match, the filename and containing module do not match
|
* If this does not match, the filename and containing module do not match
|
||||||
|
|
@ -1648,7 +1653,7 @@ yang_spec_parse_file(clicon_handle h,
|
||||||
*index(base, '@') = '\0';
|
*index(base, '@') = '\0';
|
||||||
if (yang_find(yspec, Y_MODULE, base) != NULL)
|
if (yang_find(yspec, Y_MODULE, base) != NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
if (yang_parse_filename(filename, yspec) == NULL)
|
if (yang_parse_filename(h, filename, yspec) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (yang_parse_post(h, yspec, modmin) < 0)
|
if (yang_parse_post(h, yspec, modmin) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1752,7 +1757,7 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
}
|
}
|
||||||
/* Create full filename */
|
/* Create full filename */
|
||||||
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
||||||
if ((ym = yang_parse_filename(filename, yspec)) == NULL)
|
if ((ym = yang_parse_filename(h, filename, yspec)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
revm = 0;
|
revm = 0;
|
||||||
if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL)
|
if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL)
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
@ -141,7 +140,7 @@ yang_schema_mount_point(yang_stmt *y)
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_yang_mount_get(cxobj *x,
|
xml_yang_mount_get(cxobj *xt,
|
||||||
yang_stmt **yspec)
|
yang_stmt **yspec)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -152,16 +151,16 @@ xml_yang_mount_get(cxobj *x,
|
||||||
char *xpath = NULL; // XXX free it
|
char *xpath = NULL; // XXX free it
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if ((y = xml_spec(x)) == NULL)
|
if ((y = xml_spec(xt)) == NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((ret = yang_schema_mount_point(y)) < 0)
|
if ((ret = yang_schema_mount_point(y)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
// XXX
|
// XXX hardcoded prefix: yangmnt
|
||||||
if ((yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL)
|
if ((yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
if (xml2xpath(x, NULL, &xpath) < 0)
|
if (xml2xpath(xt, NULL, 1, &xpath) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cvv = yang_cvec_get(yu)) == NULL)
|
if ((cvv = yang_cvec_get(yu)) == NULL)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
@ -203,12 +202,11 @@ xml_yang_mount_set(cxobj *x,
|
||||||
(yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL){
|
(yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL){
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (xml2xpath(x, NULL, &xpath) < 0)
|
if (xml2xpath(x, NULL, 0, &xpath) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((cvv = yang_cvec_get(yu)) != NULL &&
|
if ((cvv = yang_cvec_get(yu)) != NULL &&
|
||||||
(cv = cvec_find(cvv, xpath)) != NULL &&
|
(cv = cvec_find(cvv, xpath)) != NULL &&
|
||||||
(yspec0 = cv_void_get(cv)) != NULL){
|
(yspec0 = cv_void_get(cv)) != NULL){
|
||||||
assert(0);
|
|
||||||
ys_free(yspec0);
|
ys_free(yspec0);
|
||||||
cv_void_set(cv, NULL);
|
cv_void_set(cv, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +220,9 @@ xml_yang_mount_set(cxobj *x,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Free all yspec yang-mounts
|
/*! Free all yspec yang-mounts
|
||||||
* @aparm[in] cvv Cligen-variable vector containing xpath -> yspec mapping
|
*
|
||||||
|
* @param[in] cvv Cligen-variable vector containing xpath -> yspec mapping
|
||||||
|
* @retval 0 OK
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_yang_mount_freeall(cvec *cvv)
|
xml_yang_mount_freeall(cvec *cvv)
|
||||||
|
|
@ -243,10 +243,10 @@ xml_yang_mount_freeall(cvec *cvv)
|
||||||
*
|
*
|
||||||
* @param[in] x XML node
|
* @param[in] x XML node
|
||||||
* @param[in] arg cvec, if match add node
|
* @param[in] arg cvec, if match add node
|
||||||
* @retval -1 Error, aborted at first error encounter, return -1 to end user
|
|
||||||
* @retval 0 OK, continue
|
|
||||||
* @retval 1 Abort, dont continue with others, return 1 to end user
|
|
||||||
* @retval 2 Locally abort this subtree, continue with others
|
* @retval 2 Locally abort this subtree, continue with others
|
||||||
|
* @retval 1 Abort, dont continue with others, return 1 to end user
|
||||||
|
* @retval 0 OK, continue
|
||||||
|
* @retval -1 Error, aborted at first error encounter, return -1 to end user
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
find_schema_mounts(cxobj *x,
|
find_schema_mounts(cxobj *x,
|
||||||
|
|
@ -277,7 +277,7 @@ find_schema_mounts(cxobj *x,
|
||||||
*
|
*
|
||||||
* Brute force: traverse whole XML, match all x that have ymount as yspec
|
* Brute force: traverse whole XML, match all x that have ymount as yspec
|
||||||
* Add yang-library state for all x
|
* Add yang-library state for all x
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] xpath XML Xpath
|
* @param[in] xpath XML Xpath
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
* @param[in,out] xret Existing XML tree, merge x into this
|
* @param[in,out] xret Existing XML tree, merge x into this
|
||||||
|
|
@ -352,7 +352,7 @@ yang_schema_mount_statedata_yanglib(clicon_handle h,
|
||||||
|
|
||||||
/*! Get schema mount-point state according to RFC 8528
|
/*! Get schema mount-point state according to RFC 8528
|
||||||
*
|
*
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clixon handle
|
||||||
* @param[in] yspec Yang spec
|
* @param[in] yspec Yang spec
|
||||||
* @param[in] xpath XML Xpath
|
* @param[in] xpath XML Xpath
|
||||||
* @param[in] nsc XML Namespace context for xpath
|
* @param[in] nsc XML Namespace context for xpath
|
||||||
|
|
@ -437,7 +437,12 @@ yang_schema_mount_statedata(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Get yanglib, parse it and mount it
|
/*! Get yanglib from user plugin callback, parse it and mount it
|
||||||
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] xt
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_schema_yanglib_parse_mount(clicon_handle h,
|
yang_schema_yanglib_parse_mount(clicon_handle h,
|
||||||
|
|
@ -461,6 +466,7 @@ yang_schema_yanglib_parse_mount(clicon_handle h,
|
||||||
goto anydata;
|
goto anydata;
|
||||||
if (xml_yang_mount_set(xt, yspec) < 0)
|
if (xml_yang_mount_set(xt, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
yspec = NULL;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (yspec)
|
if (yspec)
|
||||||
|
|
@ -474,7 +480,8 @@ yang_schema_yanglib_parse_mount(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Check if XML nod is mount-point and return matching YANG child
|
/*! Check if XML nod is mount-point and return matching YANG child
|
||||||
* @param[in] h Clicon handle
|
*
|
||||||
|
* @param[in] h Clixon handle
|
||||||
* @param[in] x1 XML node
|
* @param[in] x1 XML node
|
||||||
* @param[in] x1c A child of x1
|
* @param[in] x1c A child of x1
|
||||||
* @param[out] yc YANG child
|
* @param[out] yc YANG child
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ main(int argc,
|
||||||
if (yang_filename){
|
if (yang_filename){
|
||||||
if ((yspec = yspec_new()) == NULL)
|
if ((yspec = yspec_new()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
if (yang_parse_filename(yang_filename, yspec) == NULL){
|
if (yang_parse_filename(NULL, yang_filename, yspec) == NULL){
|
||||||
fprintf(stderr, "yang parse error %s\n", clicon_err_reason);
|
fprintf(stderr, "yang parse error %s\n", clicon_err_reason);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -383,7 +383,7 @@ main(int argc,
|
||||||
char *xpathi = NULL;
|
char *xpathi = NULL;
|
||||||
for (i=0; i<xc->xc_size; i++){
|
for (i=0; i<xc->xc_size; i++){
|
||||||
xi = xc->xc_nodeset[i];
|
xi = xc->xc_nodeset[i];
|
||||||
if (xml2xpath(xi, nsc, &xpathi) < 0)
|
if (xml2xpath(xi, nsc, 0, &xpathi) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
fprintf(stdout, "Inverse: %s\n", xpathi);
|
fprintf(stdout, "Inverse: %s\n", xpathi);
|
||||||
if (xpathi){
|
if (xpathi){
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue