plugins exts UPDATE ext callback for data node validation
Fixes #1908
diff --git a/src/validation.c b/src/validation.c
index a0e7dfa..b95d0b2 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -264,8 +264,8 @@
LY_ERR
lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum lyd_type data_type, struct ly_set *node_when,
- uint32_t when_xp_opts, struct ly_set *node_types, struct ly_set *meta_types, struct ly_set *ext_val,
- uint32_t val_opts, struct lyd_node **diff)
+ uint32_t when_xp_opts, struct ly_set *node_types, struct ly_set *meta_types, struct ly_set *ext_node,
+ struct ly_set *ext_val, uint32_t val_opts, struct lyd_node **diff)
{
LY_ERR ret = LY_SUCCESS;
uint32_t i;
@@ -287,6 +287,23 @@
} while (i);
}
+ if (ext_node && ext_node->count) {
+ /* validate data nodes with extension instances */
+ i = ext_node->count;
+ do {
+ --i;
+
+ struct lyd_ctx_ext_node *ext_n = ext_node->objs[i];
+
+ /* validate the node */
+ ret = ext_n->ext->def->plugin->node(ext_n->ext, ext_n->node);
+ LY_CHECK_RET(ret);
+
+ /* remove this item from the set */
+ ly_set_rm_index(ext_node, i, free);
+ } while (i);
+ }
+
if (node_when) {
/* evaluate all when conditions */
uint32_t prev_count;
@@ -1466,6 +1483,29 @@
return LY_SUCCESS;
}
+LY_ERR
+lyd_validate_node_ext(struct lyd_node *node, struct ly_set *ext_node)
+{
+ struct lyd_ctx_ext_node *ext_n;
+ struct lysc_ext_instance *exts;
+ LY_ARRAY_COUNT_TYPE u;
+
+ /* try to find a relevant extension instance with node callback */
+ exts = node->schema->exts;
+ LY_ARRAY_FOR(exts, u) {
+ if (exts[u].def->plugin && exts[u].def->plugin->node) {
+ /* store for validation */
+ ext_n = malloc(sizeof *ext_n);
+ LY_CHECK_ERR_RET(!ext_n, LOGMEM(LYD_CTX(node)), LY_EMEM);
+ ext_n->ext = &exts[u];
+ ext_n->node = node;
+ LY_CHECK_RET(ly_set_add(ext_node, ext_n, 1, NULL));
+ }
+ }
+
+ return LY_SUCCESS;
+}
+
/**
* @brief Validate the whole data subtree.
*
@@ -1529,22 +1569,23 @@
LY_ERR
lyd_validate(struct lyd_node **tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t val_opts,
ly_bool validate_subtree, struct ly_set *node_when_p, struct ly_set *node_types_p, struct ly_set *meta_types_p,
- struct ly_set *ext_val_p, struct lyd_node **diff)
+ struct ly_set *ext_node_p, struct ly_set *ext_val_p, struct lyd_node **diff)
{
LY_ERR ret = LY_SUCCESS;
struct lyd_node *first, *next, **first2, *iter;
const struct lys_module *mod;
- struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_val = {0};
+ struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_node = {0}, ext_val = {0};
uint32_t i = 0;
assert(tree && ctx);
- assert((node_when_p && node_types_p && meta_types_p && ext_val_p) ||
- (!node_when_p && !node_types_p && !meta_types_p && !ext_val_p));
+ assert((node_when_p && node_types_p && meta_types_p && ext_node_p && ext_val_p) ||
+ (!node_when_p && !node_types_p && !meta_types_p && !ext_node_p && !ext_val_p));
if (!node_when_p) {
node_when_p = &node_when;
node_types_p = &node_types;
meta_types_p = &meta_types;
+ ext_node_p = &ext_node;
ext_val_p = &ext_val;
}
@@ -1598,8 +1639,8 @@
}
/* finish incompletely validated terminal values/attributes and when conditions */
- ret = lyd_validate_unres(first2, mod, LYD_TYPE_DATA_YANG, node_when_p, 0, node_types_p, meta_types_p, ext_val_p,
- val_opts, diff);
+ ret = lyd_validate_unres(first2, mod, LYD_TYPE_DATA_YANG, node_when_p, 0, node_types_p, meta_types_p,
+ ext_node_p, ext_val_p, val_opts, diff);
LY_CHECK_GOTO(ret, cleanup);
/* perform final validation that assumes the data tree is final */
@@ -1611,6 +1652,7 @@
ly_set_erase(&node_when, NULL);
ly_set_erase(&node_types, NULL);
ly_set_erase(&meta_types, NULL);
+ ly_set_erase(&ext_node, free);
ly_set_erase(&ext_val, free);
return ret;
}
@@ -1627,7 +1669,7 @@
*diff = NULL;
}
- return lyd_validate(tree, NULL, ctx, val_opts, 1, NULL, NULL, NULL, NULL, diff);
+ return lyd_validate(tree, NULL, ctx, val_opts, 1, NULL, NULL, NULL, NULL, NULL, diff);
}
LIBYANG_API_DEF LY_ERR
@@ -1639,7 +1681,8 @@
*diff = NULL;
}
- return lyd_validate(tree, module, (*tree) ? LYD_CTX(*tree) : module->ctx, val_opts, 1, NULL, NULL, NULL, NULL, diff);
+ return lyd_validate(tree, module, (*tree) ? LYD_CTX(*tree) : module->ctx, val_opts, 1, NULL, NULL, NULL, NULL, NULL,
+ diff);
}
/**
@@ -1717,6 +1760,7 @@
* @param[in] node_when_p Set of nodes with when conditions, if NULL a local set is used.
* @param[in] node_types_p Set of unres node types, if NULL a local set is used.
* @param[in] meta_types_p Set of unres metadata types, if NULL a local set is used.
+ * @param[in] ext_node_p Set of unres nodes with extensions to validate, if NULL a local set is used.
* @param[in] ext_val_p Set of parsed extension data to validate, if NULL a local set is used.
* @param[out] diff Optional diff with any changes made by the validation.
* @return LY_SUCCESS on success.
@@ -1725,20 +1769,21 @@
static LY_ERR
_lyd_validate_op(struct lyd_node *op_tree, struct lyd_node *op_node, const struct lyd_node *dep_tree, enum lyd_type data_type,
uint32_t int_opts, ly_bool validate_subtree, struct ly_set *node_when_p, struct ly_set *node_types_p,
- struct ly_set *meta_types_p, struct ly_set *ext_val_p, struct lyd_node **diff)
+ struct ly_set *meta_types_p, struct ly_set *ext_node_p, struct ly_set *ext_val_p, struct lyd_node **diff)
{
LY_ERR rc = LY_SUCCESS;
struct lyd_node *tree_sibling, *tree_parent, *op_subtree, *op_parent, *op_sibling_before, *op_sibling_after, *child;
- struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_val = {0};
+ struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_node = {0}, ext_val = {0};
assert(op_tree && op_node);
- assert((node_when_p && node_types_p && meta_types_p && ext_val_p) ||
- (!node_when_p && !node_types_p && !meta_types_p && !ext_val_p));
+ assert((node_when_p && node_types_p && meta_types_p && ext_node_p && ext_val_p) ||
+ (!node_when_p && !node_types_p && !meta_types_p && !ext_node_p && !ext_val_p));
if (!node_when_p) {
node_when_p = &node_when;
node_types_p = &node_types;
meta_types_p = &meta_types;
+ ext_node_p = &ext_node;
ext_val_p = &ext_val;
}
@@ -1780,7 +1825,7 @@
/* finish incompletely validated terminal values/attributes and when conditions on the full tree,
* account for unresolved 'when' that may appear in the non-validated dependency data tree */
LY_CHECK_GOTO(rc = lyd_validate_unres((struct lyd_node **)&dep_tree, NULL, data_type, node_when_p, LYXP_IGNORE_WHEN,
- node_types_p, meta_types_p, ext_val_p, 0, diff), cleanup);
+ node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff), cleanup);
/* perform final validation of the operation/notification */
lyd_validate_obsolete(op_node);
@@ -1806,6 +1851,7 @@
ly_set_erase(&node_when, NULL);
ly_set_erase(&node_types, NULL);
ly_set_erase(&meta_types, NULL);
+ ly_set_erase(&ext_node, free);
ly_set_erase(&ext_val, free);
return rc;
}
@@ -1848,8 +1894,8 @@
} else if (op_node->flags & LYD_EXT) {
/* fully validate the rest using the extension instance callback */
LY_CHECK_RET(lyd_validate_nested_ext(op_node, &ext_val));
- rc = lyd_validate_unres((struct lyd_node **)&dep_tree, NULL, data_type, NULL, 0, NULL, NULL, &ext_val,
- 0, diff);
+ rc = lyd_validate_unres((struct lyd_node **)&dep_tree, NULL, data_type, NULL, 0, NULL, NULL, NULL,
+ &ext_val, 0, diff);
ly_set_erase(&ext_val, free);
return rc;
}
@@ -1877,5 +1923,5 @@
}
/* validate */
- return _lyd_validate_op(op_tree, op_node, dep_tree, data_type, int_opts, 1, NULL, NULL, NULL, NULL, diff);
+ return _lyd_validate_op(op_tree, op_node, dep_tree, data_type, int_opts, 1, NULL, NULL, NULL, NULL, NULL, diff);
}