diff --git a/CHANGELOG.md b/CHANGELOG.md index f8cc52e2..888d3beb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Clixon Changelog -* [6.1.0](#610) Expected: beginning of 2023 +* [6.1.0](#610) Expected: 19 Feb 2023 * [6.0.0](#600) 29 Nov 2022 * [5.9.0](#590) 24 September 2022 * [5.8.0](#580) 28 July 2022 @@ -39,26 +39,23 @@ * [3.3.1](#331) June 7 2017 ## 6.1.0 -Expected: beginning of 2023 +Expected: 19 Feb 2023 ### New features * YANG schema mount RFC 8528 - * Experimental * Restrictions: * Only schema-ref=inline, not shared-schema - * Only presence containers can be mount-points + * Mount-points must be presence containers, regular containers or lists are not supported. * New plugin callback: `ca_yang_mount` * To specify which YANG modules should be mounted - * Standards: RFC 8528 - * To enable configure with `--enable-yang-schema-mount` + * To enable, set new option `CLICON_YANG_SCHEMA_MOUNT` to `true` * Netconf monitoring RFC 6022 * This is part 2, first part was in 6.0 * Datastores, sessions and statistics * Added clixon-specific transport identities: cli, snmp, netconf, restconf * Added source-host from native restonf, but no other transports * Hello statistics is based on backend statistics, hellos from RESTCONF, SNMP and CLI clients are included and dropped external NETCONF sessions are not - * Standards * RFC 6022 "YANG Module for NETCONF Monitoring" * See [Feature Request: Support RFC 6022 (NETCONF Monitoring)](https://github.com/clicon/clixon/issues/370) @@ -66,9 +63,10 @@ Expected: beginning of 2023 Users may have to change how they access the system -* New `clixon-config@2022-12-01.yang` revision - * Removed obsolete option: `CLICON_MODULE_LIBRARY_RFC7895' * Obsolete config options given in the configuration file are considered an error +* New `clixon-config@2022-12-01.yang` revision + * Added option: 'CLICON_YANG_SCHEMA_MOUNT` + * Removed obsolete option: `CLICON_MODULE_LIBRARY_RFC7895` * clixon-lib,yang * Moved all extended internal NETCONF attributes to the clicon-lib namespace * These are: content, depth, username, autocommit, copystartup, transport, source-host, objectcreate, objectexisted. @@ -77,8 +75,7 @@ Users may have to change how they access the system * This means that all get operations without `with-defaults` parameter do no longer return implicit default values, only explicitly set values. * Applies to NETCONF ``, `` and RESTCONF `GET` - * To keep backward-compatible behavior, define option `NETCONF_DEFAULT_RETRIEVAL_REPORT_ALL` in - include/clixon_custom.h + * To keep backward-compatible behavior, define option `NETCONF_DEFAULT_RETRIEVAL_REPORT_ALL` in `include/clixon_custom.h` * Alternatively, change all get operation to include with-defaults parameter `report-all` ### C/CLI-API changes on existing features @@ -100,8 +97,8 @@ Developers may need to change their code ### Minor features -* [Request to suppress auto-completion for "deprecated" / "obsolete" status and warn the user.](https://github.com/clicon/clixon/issues/410) - * Solved by: +* Done: [Request to suppress auto-completion for "deprecated" / "obsolete" status and warn the user.](https://github.com/clicon/clixon/issues/410) + * Implemented by: * Not generating any autocli syntax for obsolete YANG statements, * Hide statements for deprecated YANG statements. * New plugin callbacks diff --git a/apps/backend/backend_get.c b/apps/backend/backend_get.c index ef7e1270..9982c376 100644 --- a/apps/backend/backend_get.c +++ b/apps/backend/backend_get.c @@ -297,19 +297,19 @@ get_statedata(clicon_handle h, if (ret == 0) goto fail; } -#ifdef CLIXON_YANG_SCHEMA_MOUNT - if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0) - goto done; - if (ret == 0){ - if (clixon_netconf_internal_error(xerr, " . Internal error, schema_mounts_state_get returned invalid XML", NULL) < 0) + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ + if ((ret = yang_schema_mount_statedata(h, yspec, xpath, nsc, xret, &xerr)) < 0) goto done; - if (*xret) - xml_free(*xret); - *xret = xerr; - xerr = NULL; - goto fail; + if (ret == 0){ + if (clixon_netconf_internal_error(xerr, " . Internal error, schema_mounts_state_get returned invalid XML", NULL) < 0) + goto done; + if (*xret) + xml_free(*xret); + *xret = xerr; + xerr = NULL; + goto fail; + } } -#endif /* Use plugin state callbacks */ if ((ret = clixon_plugin_statedata_all(h, yspec, nsc, xpath, wdef, xret)) < 0) goto done; diff --git a/configure b/configure index 310aa9dd..422673e8 100755 --- a/configure +++ b/configure @@ -639,7 +639,6 @@ SYSCONFDIR MIB_GENERATED_YANG_DIR YANG_STANDARD_DIR YANG_INSTALLDIR -CLIXON_YANG_SCHEMA_MOUNT CLIXON_YANG_PATCH LIBXML2_CFLAGS with_libxml2 @@ -727,7 +726,6 @@ enable_option_checking enable_debug with_cligen enable_yang_patch -enable_yang_schema_mount with_libcurl enable_publish with_restconf @@ -1381,8 +1379,6 @@ Optional Features: --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-debug Build with debug symbols, default: no --enable-yang-patch Enable YANG patch, RFC 8072, default: no - --enable-yang-schema-mount - Enable YANG schema mount, RFC 8528, default: no --enable-publish Enable publish of notification streams using SSE and curl --disable-http1 Disable http1 for native restconf http/1, ie http/2 @@ -3407,6 +3403,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + # Set to native or fcgi -> compile apps/restconf # Enable build of apps/snmp HAVE_LIBNGHTTP2=false @@ -3424,6 +3421,9 @@ HAVE_HTTP1=false # Used in expansion in, e.g., example/main/example.xml.in + + + # ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -4683,30 +4683,6 @@ $as_echo "#define CLIXON_YANG_PATCH 1" >>confdefs.h fi -# Enable/disable YANG schema mount RFC 8528 -# Check whether --enable-yang-schema-mount was given. -if test "${enable_yang_schema_mount+set}" = set; then : - enableval=$enable_yang_schema_mount; - if test "$enableval" = no; then - enable_yang_schema_mount=no - else - enable_yang_schema_mount=yes - fi - -else - enable_yang_schema_mount=no -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: enable-yang-schema-mount is ${enable_yang_schema_mount}" >&5 -$as_echo "enable-yang-schema-mount is ${enable_yang_schema_mount}" >&6; } -if test "${enable_yang_schema_mount}" = "yes"; then - CLIXON_YANG_SCHEMA_MOUNT=1 - -$as_echo "#define CLIXON_YANG_SCHEMA_MOUNT 1" >>confdefs.h - -fi - # publish streams uses libcurl # Check whether --with-libcurl was given. diff --git a/configure.ac b/configure.ac index 35fa1302..6045506a 100644 --- a/configure.ac +++ b/configure.ac @@ -122,7 +122,6 @@ AC_SUBST(HAVE_HTTP1,false) AC_SUBST(with_libxml2) AC_SUBST(LIBXML2_CFLAGS) AC_SUBST(CLIXON_YANG_PATCH) -AC_SUBST(CLIXON_YANG_SCHEMA_MOUNT) # Where Clixon installs its YANG specs AC_SUBST(YANG_INSTALLDIR) # Examples require standard IETF YANGs. You need to provide these for example and tests @@ -202,22 +201,6 @@ if test "${enable_yang_patch}" = "yes"; then AC_DEFINE(CLIXON_YANG_PATCH, 1, [Enable YANG patch, RFC 8072]) fi -# Enable/disable YANG schema mount RFC 8528 -AC_ARG_ENABLE(yang-schema-mount, AS_HELP_STRING([--enable-yang-schema-mount],[Enable YANG schema mount, RFC 8528, default: no]),[ - if test "$enableval" = no; then - enable_yang_schema_mount=no - else - enable_yang_schema_mount=yes - fi - ], - [ enable_yang_schema_mount=no]) - -AC_MSG_RESULT(enable-yang-schema-mount is ${enable_yang_schema_mount}) -if test "${enable_yang_schema_mount}" = "yes"; then - CLIXON_YANG_SCHEMA_MOUNT=1 - AC_DEFINE(CLIXON_YANG_SCHEMA_MOUNT, 1, [Enable YANG schema mount, RFC 8528]) -fi - # publish streams uses libcurl AC_ARG_WITH([libcurl], [AS_HELP_STRING([--without-libcurl], diff --git a/example/main/example_backend.c b/example/main/example_backend.c index fb29688d..51d81e6f 100644 --- a/example/main/example_backend.c +++ b/example/main/example_backend.c @@ -898,6 +898,8 @@ example_upgrade(clicon_handle h, * Given an XML mount-point xt, return XML yang-lib modules-set * @param[in] h Clixon handle * @param[in] xt XML mount-point in XML tree + * @param[out] config If '0' all data nodes in the mounted schema are read-only + * @param[out] validate Do or dont do full RFC 7950 validation * @param[out] yanglib XML yang-lib module-set tree * @retval 0 OK * @retval -1 Error @@ -905,31 +907,40 @@ example_upgrade(clicon_handle h, * @see RFC 8528 */ int -main_yang_mount(clicon_handle h, - cxobj *xt, - cxobj **yanglib) +main_yang_mount(clicon_handle h, + cxobj *xt, + int *config, + validate_level *vl, + cxobj **yanglib) { int retval = -1; cbuf *cb = NULL; - if ((cb = cbuf_new()) == NULL){ - clicon_err(OE_UNIX, errno, "cbuf_new"); - goto done; + if (config) + *config = 1; + if (vl) + *vl = VL_FULL; + if (yanglib){ + if ((cb = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } + cprintf(cb, ""); + cprintf(cb, ""); + cprintf(cb, "mount"); + cprintf(cb, ""); + cprintf(cb, "clixon-example"); + cprintf(cb, "2022-11-01"); + cprintf(cb, "urn:example:urn"); + cprintf(cb, ""); + cprintf(cb, ""); + cprintf(cb, ""); + if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, yanglib, NULL) < 0) + goto done; + if (xml_rootchild(*yanglib, 0, yanglib) < 0) + goto done; } - cprintf(cb, ""); - cprintf(cb, ""); - cprintf(cb, "mount"); - cprintf(cb, ""); - cprintf(cb, "clixon-example"); - cprintf(cb, "2022-11-01"); - cprintf(cb, "urn:example:urn"); - cprintf(cb, ""); - cprintf(cb, ""); - cprintf(cb, ""); - if (clixon_xml_parse_string(cbuf_get(cb), YB_NONE, NULL, yanglib, NULL) < 0) - goto done; - if (xml_rootchild(*yanglib, 0, yanglib) < 0) - goto done; + retval = 0; done: if (cb) diff --git a/include/clixon_config.h.in b/include/clixon_config.h.in index fa506fc5..4dc456fe 100644 --- a/include/clixon_config.h.in +++ b/include/clixon_config.h.in @@ -21,9 +21,6 @@ /* Enable YANG patch, RFC 8072 */ #undef CLIXON_YANG_PATCH -/* Enable YANG schema mount, RFC 8528 */ -#undef CLIXON_YANG_SCHEMA_MOUNT - /* Define to 1 if you have the `alphasort' function. */ #undef HAVE_ALPHASORT diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h index 06214a26..2a9e4d3b 100644 --- a/lib/clixon/clixon_plugin.h +++ b/lib/clixon/clixon_plugin.h @@ -282,12 +282,15 @@ typedef int (datastore_upgrade_t)(clicon_handle h, const char *db, cxobj *xt, mo * No need to YANG bind. * @param[in] h Clixon handle * @param[in] xt XML mount-point in XML tree + * @param[out] config If '0' all data nodes in the mounted schema are read-only + * @param[out] vallevel Do or dont do full RFC 7950 validation * @param[out] yanglib XML yang-lib module-set tree. Freed by caller. * @retval 0 OK * @retval -1 Error * @see RFC 8528 (schema-mount) and RFC 8525 (yang-lib) */ -typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, cxobj **yanglib); +typedef int (yang_mount_t)(clicon_handle h, cxobj *xt, int *config, + validate_level *vl, cxobj **yanglib); /*! YANG module patch * @@ -454,8 +457,8 @@ int clixon_plugin_extension_all(clicon_handle h, yang_stmt *yext, yang_stmt *ys) int clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp, clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); int clixon_plugin_datastore_upgrade_all(clicon_handle h, const char *db, cxobj *xt, modstate_diff_t *msd); -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_one(clixon_plugin_t *cp, clicon_handle h, cxobj *xt, int *config, validate_level *vl, cxobj **yanglib); +int clixon_plugin_yang_mount_all(clicon_handle h, cxobj *xt, int *config, validate_level *vl, 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); diff --git a/lib/clixon/clixon_validate.h b/lib/clixon/clixon_validate.h index ec8ad0df..0f6483cc 100644 --- a/lib/clixon/clixon_validate.h +++ b/lib/clixon/clixon_validate.h @@ -40,16 +40,6 @@ #ifndef _CLIXON_VALIDATE_H_ #define _CLIXON_VALIDATE_H_ -/* - * Types - */ -/* Validation level at commit */ -enum validate_level_t { - VL_FULL = 0, /* Do full RFC 7950 validation , 0 : backward-compatible */ - VL_NONE, /* Do not do any validation */ -}; -typedef enum validate_level_t validate_level; - /* * Prototypes */ diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 35a8dd3c..70ee95cb 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -181,6 +181,12 @@ typedef struct yang_stmt yang_stmt; */ typedef int (yang_applyfn_t)(yang_stmt *ys, void *arg); +/* Validation level at commit */ +enum validate_level_t { + VL_FULL = 0, /* Do full RFC 7950 validation , 0 : backward-compatible */ + VL_NONE, /* Do not do any validation */ +}; +typedef enum validate_level_t validate_level; /* Yang data definition statement * See RFC 7950 Sec 3: diff --git a/lib/clixon/clixon_yang_schema_mount.h b/lib/clixon/clixon_yang_schema_mount.h index f7ef7afa..c5c3594a 100644 --- a/lib/clixon/clixon_yang_schema_mount.h +++ b/lib/clixon/clixon_yang_schema_mount.h @@ -54,7 +54,7 @@ * Prototypes */ int yang_schema_mount_point(yang_stmt *y); -int xml_yang_mount_get(cxobj *x, yang_stmt **yspec); +int xml_yang_mount_get(clicon_handle h, cxobj *x, validate_level *vl, yang_stmt **yspec); int xml_yang_mount_set(cxobj *x, yang_stmt *yspec); int xml_yang_mount_freeall(cvec *cvv); int yang_schema_mount_statedata(clicon_handle h, yang_stmt *yspec, char *xpath, cvec *nsc, cxobj **xret, cxobj **xerr); diff --git a/lib/src/clixon_datastore_write.c b/lib/src/clixon_datastore_write.c index 92745b09..5b8345ea 100644 --- a/lib/src/clixon_datastore_write.c +++ b/lib/src/clixon_datastore_write.c @@ -487,10 +487,8 @@ text_modify(clicon_handle h, char *createstr = NULL; yang_stmt *yrestype = NULL; char *restype; -#ifdef CLIXON_YANG_SCHEMA_MOUNT int ismount = 0; yang_stmt *mount_yspec = NULL; -#endif if (x1 == NULL){ clicon_err(OE_XML, EINVAL, "x1 is missing"); @@ -860,9 +858,8 @@ text_modify(clicon_handle h, x1cname = xml_name(x1c); /* Get yang spec of the child by child matching */ if ((yc = yang_find_datanode(y0, x1cname)) == NULL){ -#ifdef CLIXON_YANG_SCHEMA_MOUNT - yc = xml_spec(x1c); -#endif + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")) + yc = xml_spec(x1c); if (yc == NULL){ if (clicon_option_bool(h, "CLICON_YANG_UNKNOWN_ANYDATA") == 1){ /* Add dummy Y_ANYDATA yang stmt, see ysp_add */ @@ -908,22 +905,26 @@ text_modify(clicon_handle h, x0c = x0vec[i++]; x1cname = xml_name(x1c); if ((yc = yang_find_datanode(y0, x1cname)) == NULL){ -#ifdef CLIXON_YANG_SCHEMA_MOUNT - yc = xml_spec(x1c); -#endif + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")) + yc = xml_spec(x1c); } -#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; + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ + /* Check if xc is unresolved mountpoint, ie no yang mount binding yet */ + if ((ismount = xml_yang_mount_get(h, x1c, NULL, &mount_yspec)) < 0) + goto done; + if (ismount && mount_yspec == NULL){ + ret = 1; + } + else{ + if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t, + yc, op, + username, xnacm, permit, cbret)) < 0) + goto done; + } } - else -#endif - if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t, - yc, op, - username, xnacm, permit, cbret)) < 0) + else if ((ret = text_modify(h, x0c, x0, x0t, x1c, x1t, + yc, op, + username, xnacm, permit, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ if (ret == 0) diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index df93a3d2..6326abb8 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -1010,6 +1010,8 @@ clixon_plugin_datastore_upgrade_all(clicon_handle h, * @param[in] cp Plugin handle * @param[in] h Clixon handle * @param[in] xt XML mount-point in XML tree + * @param[out] config If '0' all data nodes in the mounted schema are read-only + * @param[out] validate Do or dont do full RFC 7950 validation * @param[out] yanglib XML yang-lib module-set tree * @retval 0 OK * @retval -1 Error @@ -1018,6 +1020,8 @@ int clixon_plugin_yang_mount_one(clixon_plugin_t *cp, clicon_handle h, cxobj *xt, + int *config, + validate_level *vl, cxobj **yanglib) { int retval = -1; @@ -1028,7 +1032,7 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp, wh = NULL; if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; - if (fn(h, xt, yanglib) < 0) { + if (fn(h, xt, config, vl, yanglib) < 0) { if (clicon_errno < 0) clicon_log(LOG_WARNING, "%s: Internal error: Yang mount callback in plugin: %s returned -1 but did not make a clicon_err call", __FUNCTION__, cp->cp_name); @@ -1046,22 +1050,27 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp, * * @param[in] h Clixon handle * @param[in] xt XML mount-point in XML tree + * @param[out] config If '0' all data nodes in the mounted schema are read-only + * @param[out] validate Do or dont do full RFC 7950 validation * @param[out] yanglib XML yang-lib module-set tree (freed by caller) * @retval 0 OK * @retval -1 Error */ int -clixon_plugin_yang_mount_all(clicon_handle h, - cxobj *xt, - cxobj **yanglib) +clixon_plugin_yang_mount_all(clicon_handle h, + cxobj *xt, + int *config, + validate_level *vl, + cxobj **yanglib) { int retval = -1; clixon_plugin_t *cp = NULL; while ((cp = clixon_plugin_each(h, cp)) != NULL) { - if (clixon_plugin_yang_mount_one(cp, h, xt, yanglib) < 0) + if (clixon_plugin_yang_mount_one(cp, h, xt, config, vl, yanglib) < 0) goto done; - if (*yanglib) + /* Break if find yanglib */ + if (yanglib && *yanglib) break; } retval = 0; diff --git a/lib/src/clixon_validate.c b/lib/src/clixon_validate.c index 1af42b14..338264a8 100644 --- a/lib/src/clixon_validate.c +++ b/lib/src/clixon_validate.c @@ -1007,16 +1007,15 @@ xml_yang_validate_add(clicon_handle h, cxobj *x; cg_var *cv0; enum cv_type cvtype; - -#ifdef CLIXON_YANG_SCHEMA_MOUNT - /* Do not validate beyond mountpoints */ - if ((ret = xml_yang_mount_get(xt, NULL)) < 0) - goto done; - if (ret == 1){ - retval = 1; - goto done; + validate_level vl = VL_NONE; + + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ + if ((ret = xml_yang_mount_get(h, xt, &vl, NULL)) < 0) + goto done; + /* Check if validate beyond mountpoints */ + if (ret == 1 && vl == VL_NONE) + goto ok; } -#endif /* if not given by argument (overide) use default link and !Node has a config sub-statement and it is false */ if ((yt = xml_spec(xt)) != NULL && yang_config(yt) != 0){ @@ -1076,6 +1075,7 @@ xml_yang_validate_add(clicon_handle h, if (ret == 0) goto fail; } + ok: retval = 1; done: if (cv) @@ -1224,14 +1224,15 @@ xml_yang_validate_all(clicon_handle h, cbuf *cb = NULL; cvec *nsc = NULL; int hit = 0; + validate_level vl = VL_NONE; -#ifdef CLIXON_YANG_SCHEMA_MOUNT - /* Do not validate beyond mountpoints */ - if ((ret = xml_yang_mount_get(xt, NULL)) < 0) - goto done; - if (ret == 1) - goto ok; /* Actually this may be somewhat too strict */ -#endif + if (clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ + if ((ret = xml_yang_mount_get(h, xt, &vl, NULL)) < 0) + goto done; + /* Check if validate beyond mountpoints */ + if (ret == 1 && vl == VL_NONE) + goto ok; + } /* if not given by argument (overide) use default link and !Node has a config sub-statement and it is false */ if ((yt = xml_spec(xt)) == NULL){ diff --git a/lib/src/clixon_xml_bind.c b/lib/src/clixon_xml_bind.c index b4fa3453..abf10e47 100644 --- a/lib/src/clixon_xml_bind.c +++ b/lib/src/clixon_xml_bind.c @@ -453,34 +453,34 @@ xml_bind_yang0_opt(clicon_handle h, goto ok; strip_body_objects(xt); ybc = YB_PARENT; -#ifdef CLIXON_YANG_SCHEMA_MOUNT - yspec1 = NULL; - if ((ret = xml_yang_mount_get(xt, &yspec1)) < 0) - goto done; - if (ret == 0) - yspec1 = yspec; - else{ - if (yspec1) - ybc = YB_MODULE; - else if (h == NULL) - goto ok; /* treat as anydata */ + if (h && clicon_option_bool(h, "CLICON_YANG_SCHEMA_MOUNT")){ + yspec1 = NULL; + if ((ret = xml_yang_mount_get(h, xt, NULL, &yspec1)) < 0) + goto done; + if (ret == 0) + yspec1 = yspec; else{ - if ((ret = yang_schema_yanglib_parse_mount(h, xt)) < 0) - goto done; - if (ret == 0) - goto ok; - /* Try again */ - if ((ret = xml_yang_mount_get(xt, &yspec1)) < 0) - goto done; if (yspec1) ybc = YB_MODULE; - else - goto ok; + else if (h == NULL) + goto ok; /* treat as anydata */ + else{ + if ((ret = yang_schema_yanglib_parse_mount(h, xt)) < 0) + goto done; + if (ret == 0) + goto ok; + /* Try again */ + if ((ret = xml_yang_mount_get(h, xt, NULL, &yspec1)) < 0) + goto done; + if (yspec1) + ybc = YB_MODULE; + else + goto ok; + } } } -#else - yspec1 = yspec; -#endif + else + yspec1 = yspec; xc = NULL; /* Apply on children */ while ((xc = xml_child_each(xt, xc, CX_ELMNT)) != NULL) { /* It is xml2ns in populate_self_parent that needs improvement */ diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index b158d3d2..a36cbfae 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -661,7 +661,6 @@ ys_free1(yang_stmt *ys, cv_free(cv); } if (ys->ys_cvec){ -#ifdef CLIXON_YANG_SCHEMA_MOUNT /* Schema mount uses cvec in unknown to keep track of all yspecs * Freed here once. */ @@ -669,7 +668,6 @@ ys_free1(yang_stmt *ys, strcmp(yang_argument_get(ys), "yangmnt:mount-point")==0){ xml_yang_mount_freeall(ys->ys_cvec); } -#endif cvec_free(ys->ys_cvec); ys->ys_cvec = NULL; } diff --git a/lib/src/clixon_yang_schema_mount.c b/lib/src/clixon_yang_schema_mount.c index 0f2ecad0..62f1d08f 100644 --- a/lib/src/clixon_yang_schema_mount.c +++ b/lib/src/clixon_yang_schema_mount.c @@ -133,15 +133,19 @@ yang_schema_mount_point(yang_stmt *y) /*! Get yangspec mount-point * + * @param[in] h Clixon handle * @param[in] x XML moint-point node + * @param[out] vallevel Do or dont do full RFC 7950 validation * @param[out] yspec YANG stmt spec * @retval 1 x is a mount-point: yspec may be set * @retval 0 x is not a mount point * @retval -1 Error */ int -xml_yang_mount_get(cxobj *xt, - yang_stmt **yspec) +xml_yang_mount_get(clicon_handle h, + cxobj *xt, + validate_level *vl, + yang_stmt **yspec) { int retval = -1; cvec *cvv = NULL; @@ -157,6 +161,9 @@ xml_yang_mount_get(cxobj *xt, goto done; if (ret == 0) goto fail; + /* Check validate level */ + if (clixon_plugin_yang_mount_all(h, xt, NULL, vl, NULL) < 0) + goto done; // XXX hardcoded prefix: yangmnt if ((yu = yang_find(y, Y_UNKNOWN, "yangmnt:mount-point")) == NULL) goto ok; @@ -168,6 +175,7 @@ xml_yang_mount_get(cxobj *xt, if ((cv = cvec_find(cvv, xpath)) == NULL) goto ok; if (yspec) + *yspec = cv_void_get(cv); ok: retval = 1; @@ -301,14 +309,16 @@ yang_schema_mount_statedata_yanglib(clicon_handle h, cxobj **xret, cxobj **xerr) { - int retval = -1; - cvec *cvv = NULL; - cg_var *cv; - cxobj *xmp; /* xml mount-point */ - cxobj *yanglib = NULL; /* xml yang-lib */ - cbuf *cb = NULL; - yang_stmt *yspec; - int ret; + int retval = -1; + cvec *cvv = NULL; + cg_var *cv; + cxobj *xmp; /* xml mount-point */ + cxobj *yanglib = NULL; /* xml yang-lib */ + cbuf *cb = NULL; + yang_stmt *yspec; + int ret; + int config = 1; + validate_level vl = VL_FULL; if ((cb = cbuf_new()) == NULL){ clicon_err(OE_UNIX, 0, "clicon buffer"); @@ -325,12 +335,11 @@ yang_schema_mount_statedata_yanglib(clicon_handle h, xmp = cv_void_get(cv); yanglib = NULL; /* User callback */ - if (clixon_plugin_yang_mount_all(h, xmp, &yanglib) < 0) + if (clixon_plugin_yang_mount_all(h, xmp, &config, &vl, &yanglib) < 0) goto done; if (yanglib == NULL) continue; yspec = clicon_dbspec_yang(h); - // if ((ret = xml_bind_yang(h, yanglib, YB_NONE, yspec, &xerr)) < 0) if ((ret = xml_bind_yang0(h, yanglib, YB_MODULE, yspec, xerr)) < 0) goto done; if (ret == 0) @@ -449,12 +458,14 @@ int yang_schema_yanglib_parse_mount(clicon_handle h, cxobj *xt) { - int retval = -1; - cxobj *yanglib = NULL; - yang_stmt *yspec = NULL; - int ret; + int retval = -1; + cxobj *yanglib = NULL; + yang_stmt *yspec = NULL; + int ret; + int config = 1; + validate_level vl = VL_FULL; - if (clixon_plugin_yang_mount_all(h, xt, &yanglib) < 0) + if (clixon_plugin_yang_mount_all(h, xt, &config, &vl, &yanglib) < 0) goto done; if (yanglib == NULL) goto anydata; @@ -504,7 +515,7 @@ yang_schema_get_child(clicon_handle h, int ret; x1cname = xml_name(x1c); - if ((ret = xml_yang_mount_get(x1, &yspec1)) < 0) + if ((ret = xml_yang_mount_get(h, x1, NULL, &yspec1)) < 0) goto done; if (ret == 1 && yspec1 != NULL){ if (ys_module_by_xml(yspec1, x1c, &ymod1) <0) diff --git a/test/config.sh.in b/test/config.sh.in index f57704e5..8b5e0913 100755 --- a/test/config.sh.in +++ b/test/config.sh.in @@ -91,7 +91,6 @@ SH_SUFFIX=@SH_SUFFIX@ LIBSTATIC_SUFFIX=@LIBSTATIC_SUFFIX@ LIBS="@LIBS@" CLIXON_YANG_PATCH=@CLIXON_YANG_PATCH@ -CLIXON_YANG_SCHEMA_MOUNT=@CLIXON_YANG_SCHEMA_MOUNT@ YANG_STANDARD_DIR=@YANG_STANDARD_DIR@ YANG_INSTALLDIR=@YANG_INSTALLDIR@ diff --git a/test/test_yang_schema_mount.sh b/test/test_yang_schema_mount.sh index b2036c18..7c57981e 100755 --- a/test/test_yang_schema_mount.sh +++ b/test/test_yang_schema_mount.sh @@ -5,12 +5,6 @@ # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi -if [ -z "${CLIXON_YANG_SCHEMA_MOUNT}" ]; then - echo "...skipped. To enable configure with: --enable-yang-schema-mount" - rm -rf $dir - if [ "$s" = $0 ]; then exit 0; else return 0; fi # skip -fi - APPNAME=example cfg=$dir/conf_mount.xml @@ -33,6 +27,7 @@ cat < $cfg true true true + true EOF diff --git a/yang/clixon/clixon-config@2022-12-01.yang b/yang/clixon/clixon-config@2022-12-01.yang index f9b419d0..38e8073f 100644 --- a/yang/clixon/clixon-config@2022-12-01.yang +++ b/yang/clixon/clixon-config@2022-12-01.yang @@ -48,7 +48,9 @@ module clixon-config { revision 2022-12-01 { description - "Removed (previosly marked) obsolete options: + "Added options: + CLICON_YANG_SCHEMA_MOUNT + Removed (previosly marked) obsolete options: CLICON_MODULE_LIBRARY_RFC7895 Released in Clixon 6.1"; } @@ -502,6 +504,12 @@ module clixon-config { "Location of backend .so plugins. Load all .so plugins in this dir as backend plugins"; } + leaf CLICON_YANG_SCHEMA_MOUNT{ + type boolean; + description + "YANG schema mount, RFC 8528"; + default false; + } leaf CLICON_BACKEND_REGEXP { type string; description