blob: 97f02d6e35483eb365a8baee43fdb291c95ced3c [file] [log] [blame]
Michal Vaskocde73ac2019-11-14 16:10:27 +01001/**
2 * @file validation.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief Validation
5 *
6 * Copyright (c) 2019 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include <assert.h>
16#include <string.h>
17
18#include "common.h"
19#include "xpath.h"
20#include "tree_data_internal.h"
Michal Vasko14654712020-02-06 08:35:21 +010021#include "tree_schema_internal.h"
Michal Vaskocde73ac2019-11-14 16:10:27 +010022
23/**
24 * @brief Evaluate a single "when" condition.
25 *
26 * @param[in] when When to evaluate.
27 * @param[in] node Node whose existence depends on this when.
28 * @param[in] trees Array of all data trees.
29 * @return LY_ERR value (LY_EINCOMPLETE if a referenced node does not have its when evaluated)
30 */
31static LY_ERR
32lyd_val_when(struct lysc_when *when, struct lyd_node *node, const struct lyd_node **trees)
33{
34 LY_ERR ret;
35 const struct lyd_node *ctx_node;
36 struct lyxp_set xp_set;
37
38 memset(&xp_set, 0, sizeof xp_set);
39
40 if (when->context == node->schema) {
41 ctx_node = node;
42 } else {
43 assert((!when->context && !node->parent) || (when->context == node->parent->schema));
44 ctx_node = (struct lyd_node *)node->parent;
45 }
46
47 /* evaluate when */
48 ret = lyxp_eval(when->cond, LYD_UNKNOWN, when->module, ctx_node, ctx_node ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG,
49 trees, &xp_set, LYXP_SCHEMA);
50 lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
51
52 /* return error or LY_EINCOMPLETE for dependant unresolved when */
53 LY_CHECK_RET(ret);
54
55 /* take action based on the result */
56 if (!xp_set.val.bool) {
57 if (node->flags & LYD_WHEN_TRUE) {
58 /* autodelete */
59 lyd_free_tree(node);
60 } else {
61 /* invalid data */
62 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOWHEN, when->cond->expr);
63 ret = LY_EVALID;
64 }
65 } else {
66 /* remember that when evaluated to true */
67 node->flags |= LYD_WHEN_TRUE;
68 }
69
70 return ret;
71}
72
73LY_ERR
74lyd_validate_unres(struct ly_set *node_types, struct ly_set *attr_types, struct ly_set *node_when, LYD_FORMAT format,
75 ly_clb_resolve_prefix get_prefix_clb, void *parser_data, const struct lyd_node **trees)
76{
77 LY_ERR ret = LY_SUCCESS;
78 uint32_t u;
79
80 /* finish incompletely validated terminal values */
81 for (u = 0; node_types && (u < node_types->count); u++) {
82 struct lyd_node_term *node = (struct lyd_node_term *)node_types->objs[u];
83
84 /* validate and store the value of the node */
85 ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1, get_prefix_clb,
86 parser_data, format, trees);
87 LY_CHECK_RET(ret);
88 }
89
90 /* ... and attribute values */
91 for (u = 0; attr_types && (u < attr_types->count); u++) {
92 struct lyd_attr *attr = (struct lyd_attr *)attr_types->objs[u];
93
94 /* validate and store the value of the node */
Michal Vasko8d544252020-03-02 10:19:52 +010095 ret = lyd_value_parse_attr(attr->parent->schema->module->ctx, attr, attr->value.original,
96 strlen(attr->value.original), 0, 1, get_prefix_clb, parser_data, format, NULL, trees);
Michal Vaskocde73ac2019-11-14 16:10:27 +010097 LY_CHECK_RET(ret);
98 }
99
100 /* no when conditions */
101 if (!node_when || !node_when->count) {
102 return ret;
103 }
104
105 /* evaluate all when conditions */
106 uint32_t prev_count;
107 do {
108 prev_count = node_when->count;
109 u = 0;
110 while (u < node_when->count) {
111 /* evaluate all when expressions that affect this node's existence */
112 struct lyd_node *node = (struct lyd_node *)node_when->objs[u];
113 const struct lysc_node *schema = node->schema;
114 int unres_when = 0;
115
116 do {
117 uint32_t i;
118 LY_ARRAY_FOR(schema->when, i) {
119 ret = lyd_val_when(schema->when[i], node, trees);
120 if (ret) {
121 break;
122 }
123 }
124 if (ret == LY_EINCOMPLETE) {
125 /* could not evaluate this when */
126 unres_when = 1;
127 break;
128 } else if (ret) {
129 /* error */
130 return ret;
131 }
132 schema = schema->parent;
133 } while (schema && (schema->nodetype & (LYS_CASE | LYS_CHOICE)));
134
135 if (unres_when) {
136 /* keep in set and go to the next node */
137 ++u;
138 } else {
139 /* remove this node from the set */
140 ly_set_rm_index(node_when, u, NULL);
141 }
142 }
143
144 /* there must have been some when conditions resolved */
145 } while (prev_count > node_when->count);
146
147 /* there could have been no cyclic when dependencies, checked during compilation */
148 assert(!node_when->count);
149
150 return ret;
151}
152
153static const struct lys_module *
154lyd_val_next_module(const struct lys_module **modules, int mod_count, struct ly_ctx *ctx, uint32_t *i)
155{
156 if (modules && mod_count) {
157 return modules[(*i)++];
158 }
159
160 return ly_ctx_get_module_iter(ctx, i);
161}
162
Michal Vasko9b368d32020-02-14 13:53:31 +0100163static int
164lyd_val_has_choice_data(const struct lysc_node *snode, struct lyd_node *sibling)
165{
166 const struct lysc_node *iter = NULL;
167
168 assert(snode->nodetype == LYS_CHOICE);
169
170 while ((iter = lys_getnext(iter, snode, NULL, 0))) {
171 switch (iter->nodetype) {
172 case LYS_CONTAINER:
173 case LYS_ANYXML:
174 case LYS_ANYDATA:
175 case LYS_LEAF:
176 if (!lyd_find_sibling_val(sibling, iter, NULL, 0, NULL)) {
177 /* one case child data instance found */
178 return 1;
179 }
180 break;
181 case LYS_LIST:
182 case LYS_LEAFLIST:
183 if (!lyd_find_sibling_next2(sibling, iter, NULL, 0, NULL)) {
184 /* one case child data instance found */
185 return 1;
186 }
187 break;
188 default:
189 assert(0);
190 LOGINT(snode->module->ctx);
191 return 0;
192 }
193 }
194
195 return 0;
196}
197
Michal Vaskocde73ac2019-11-14 16:10:27 +0100198static LY_ERR
Michal Vaskoa3881362020-01-21 15:57:35 +0100199lyd_validate_mandatory(const struct lysc_node *snode, struct lyd_node *sibling)
200{
Michal Vaskoa3881362020-01-21 15:57:35 +0100201 if (snode->nodetype == LYS_CHOICE) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100202 /* some data of a choice case exist */
203 if (lyd_val_has_choice_data(snode, sibling)) {
204 return LY_SUCCESS;
205 }
206 } else {
207 assert(snode->nodetype & (LYS_LEAF | LYS_CONTAINER | LYD_NODE_ANY));
Michal Vaskoa3881362020-01-21 15:57:35 +0100208
Michal Vasko9b368d32020-02-14 13:53:31 +0100209 if (!lyd_find_sibling_val(sibling, snode, NULL, 0, NULL)) {
210 /* data instance found */
211 return LY_SUCCESS;
Michal Vaskoa3881362020-01-21 15:57:35 +0100212 }
213 }
214
215 /* node instance not found */
216 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAND, snode->name);
217 return LY_EVALID;
218}
219
220static LY_ERR
221lyd_validate_minmax(const struct lysc_node *snode, uint32_t min, uint32_t max, struct lyd_node *sibling)
222{
Michal Vaskoacd83e72020-02-04 14:12:01 +0100223 uint32_t count = 0;
224 struct lyd_node *iter;
225
Michal Vasko9b368d32020-02-14 13:53:31 +0100226 assert(min || max);
227
Michal Vaskoacd83e72020-02-04 14:12:01 +0100228 LY_LIST_FOR(sibling, iter) {
229 if (iter->schema == snode) {
230 ++count;
Michal Vasko9b368d32020-02-14 13:53:31 +0100231
232 if (min && (count == min)) {
233 /* satisfied */
234 min = 0;
235 if (!max) {
236 /* nothing more to check */
237 break;
238 }
239 }
240 if (max && (count > max)) {
241 /* not satisifed */
242 break;
243 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100244 }
245 }
246
Michal Vasko9b368d32020-02-14 13:53:31 +0100247 if (min) {
248 assert(count < min);
Michal Vaskoacd83e72020-02-04 14:12:01 +0100249 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMIN, snode->name);
250 return LY_EVALID;
251 } else if (max && (count > max)) {
252 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAX, snode->name);
253 return LY_EVALID;
254 }
255
Michal Vaskoa3881362020-01-21 15:57:35 +0100256 return LY_SUCCESS;
257}
258
Michal Vasko14654712020-02-06 08:35:21 +0100259static struct lyd_node *
260lyd_val_uniq_find_leaf(const struct lysc_node_leaf *uniq_leaf, struct lyd_node *list)
261{
Michal Vasko9b368d32020-02-14 13:53:31 +0100262 struct lyd_node *node;
263 const struct lysc_node *iter;
264 size_t depth = 0, i;
Michal Vasko14654712020-02-06 08:35:21 +0100265
Michal Vasko9b368d32020-02-14 13:53:31 +0100266 /* get leaf depth */
267 for (iter = (struct lysc_node *)uniq_leaf; iter && (iter != list->schema); iter = iter->parent) {
268 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
269 ++depth;
270 }
Michal Vasko14654712020-02-06 08:35:21 +0100271 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100272
273 node = list;
274 while (node && depth) {
275 /* find schema node with this depth */
276 for (i = depth - 1, iter = (struct lysc_node *)uniq_leaf; i; iter = iter->parent) {
277 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
278 --i;
279 }
280 }
281
282 /* find iter instance in children */
283 assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
284 lyd_find_sibling_val(lyd_node_children(node), iter, NULL, 0, &node);
285 --depth;
286 }
287
Michal Vasko14654712020-02-06 08:35:21 +0100288 return node;
289}
290
291/*
292 * actions (cb_data):
293 * 0 - compare all uniques
294 * n - compare n-th unique
295 */
296static int
297lyd_val_uniq_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
298{
299 struct ly_ctx *ctx;
300 struct lysc_node_list *slist;
301 struct lyd_node *diter, *first, *second;
302 struct lyd_value *val1, *val2;
303 char *path1, *path2, *uniq_str, *ptr;
304 uint32_t i, j, action;
305
306 assert(val1_p && val2_p);
307
308 first = *((struct lyd_node **)val1_p);
309 second = *((struct lyd_node **)val2_p);
310 action = (uintptr_t)cb_data;
311
312 assert(first && (first->schema->nodetype == LYS_LIST));
313 assert(second && (second->schema == first->schema));
314
315 ctx = first->schema->module->ctx;
316
317 slist = (struct lysc_node_list *)first->schema;
318
319 /* compare unique leaves */
320 if (action > 0) {
321 i = action - 1;
322 if (i < LY_ARRAY_SIZE(slist->uniques)) {
323 goto uniquecheck;
324 }
325 }
326 LY_ARRAY_FOR(slist->uniques, i) {
327uniquecheck:
328 LY_ARRAY_FOR(slist->uniques[i], j) {
329 /* first */
330 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], first);
331 if (diter) {
332 val1 = &((struct lyd_node_term *)diter)->value;
333 } else {
334 /* use default value */
335 val1 = slist->uniques[i][j]->dflt;
336 }
337
338 /* second */
339 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], second);
340 if (diter) {
341 val2 = &((struct lyd_node_term *)diter)->value;
342 } else {
343 /* use default value */
344 val2 = slist->uniques[i][j]->dflt;
345 }
346
347 if (!val1 || !val2 || val1->realtype->plugin->compare(val1, val2)) {
348 /* values differ or either one is not set */
349 break;
350 }
351 }
352 if (j && (j == LY_ARRAY_SIZE(slist->uniques[i]))) {
353 /* all unique leafs are the same in this set, create this nice error */
354 path1 = lyd_path(first, LYD_PATH_LOG, NULL, 0);
355 path2 = lyd_path(second, LYD_PATH_LOG, NULL, 0);
356
357 /* use buffer to rebuild the unique string */
358 uniq_str = malloc(1024);
359 uniq_str[0] = '\0';
360 ptr = uniq_str;
361 LY_ARRAY_FOR(slist->uniques[i], j) {
362 if (j) {
363 strcpy(ptr, " ");
364 ++ptr;
365 }
366 ptr = lysc_path_until((struct lysc_node *)slist->uniques[i][j], (struct lysc_node *)slist, LYSC_PATH_LOG,
367 ptr, 1024 - (ptr - uniq_str));
368 if (!ptr) {
369 /* path will be incomplete, whatever */
370 break;
371 }
372
373 ptr += strlen(ptr);
374 }
375 LOGVAL(ctx, LY_VLOG_LYD, second, LY_VCODE_NOUNIQ, uniq_str, path1, path2);
376
377 free(path1);
378 free(path2);
379 free(uniq_str);
380 return 1;
381 }
382
383 if (action > 0) {
384 /* done */
385 return 0;
386 }
387 }
388
389 return 0;
390}
391
Michal Vaskoa3881362020-01-21 15:57:35 +0100392static LY_ERR
393lyd_validate_unique(const struct lysc_node *snode, struct lysc_node_leaf ***uniques, struct lyd_node *sibling)
394{
Michal Vasko14654712020-02-06 08:35:21 +0100395 struct lyd_node *diter;
396 struct ly_set *set;
397 uint32_t i, j, n = 0;
398 LY_ERR ret = LY_SUCCESS;
399 uint32_t hash, u, usize = 0;
400 int dynamic;
401 const char *str;
402 struct hash_table **uniqtables = NULL;
403 struct lyd_value *val;
404 struct ly_ctx *ctx = snode->module->ctx;
405
406 assert(uniques);
407
408 /* get all list instances */
Michal Vasko9b368d32020-02-14 13:53:31 +0100409 set = ly_set_new();
410 LY_CHECK_ERR_RET(!set, LOGMEM(ctx), LY_EMEM);
411 LY_LIST_FOR(sibling, diter) {
412 if (diter->schema == snode) {
413 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
414 }
415 }
Michal Vasko14654712020-02-06 08:35:21 +0100416
417 if (set->count == 2) {
418 /* simple comparison */
419 if (lyd_val_uniq_list_equal(&set->objs[0], &set->objs[1], 0, (void *)0)) {
420 /* instance duplication */
421 ret = LY_EVALID;
422 goto cleanup;
423 }
424 } else if (set->count > 2) {
425 /* use hashes for comparison */
426 /* first, allocate the table, the size depends on number of items in the set */
427 for (u = 31; u > 0; u--) {
428 usize = set->count << u;
429 usize = usize >> u;
430 if (usize == set->count) {
431 break;
432 }
433 }
434 LY_CHECK_ERR_GOTO(!u, LOGINT(ctx); ret = LY_EINT, cleanup);
435 u = 32 - u;
436 usize = 1 << u;
437
438 uniqtables = malloc(LY_ARRAY_SIZE(uniques) * sizeof *uniqtables);
439 LY_CHECK_ERR_GOTO(!uniqtables, LOGMEM(ctx); ret = LY_EMEM, cleanup);
440 n = LY_ARRAY_SIZE(uniques);
441 for (j = 0; j < n; j++) {
442 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyd_val_uniq_list_equal, (void *)(j + 1L), 0);
443 LY_CHECK_ERR_GOTO(!uniqtables[j], LOGMEM(ctx); ret = LY_EMEM, cleanup);
444 }
445
446 for (u = 0; u < set->count; u++) {
447 /* loop for unique - get the hash for the instances */
448 for (i = 0; i < n; i++) {
449 val = NULL;
450 for (j = hash = 0; j < LY_ARRAY_SIZE(uniques[i]); j++) {
451 diter = lyd_val_uniq_find_leaf(uniques[i][j], set->objs[u]);
452 if (diter) {
453 val = &((struct lyd_node_term *)diter)->value;
454 } else {
455 /* use default value */
456 val = uniques[i][j]->dflt;
457 }
458 if (!val) {
459 /* unique item not present nor has default value */
460 break;
461 }
462
463 /* get canonical string value */
464 str = val->realtype->plugin->print(val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
465 hash = dict_hash_multi(hash, str, strlen(str));
466 if (dynamic) {
467 free((char *)str);
468 }
469 }
470 if (!val) {
471 /* skip this list instance since its unique set is incomplete */
472 continue;
473 }
474
475 /* finish the hash value */
476 hash = dict_hash_multi(hash, NULL, 0);
477
478 /* insert into the hashtable */
479 ret = lyht_insert(uniqtables[i], &set->objs[u], hash, NULL);
480 if (ret == LY_EEXIST) {
481 /* instance duplication */
482 ret = LY_EVALID;
483 }
484 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
485 }
486 }
487 }
488
489cleanup:
490 ly_set_free(set, NULL);
491 for (j = 0; j < n; j++) {
492 if (!uniqtables[j]) {
493 /* failed when allocating uniquetables[j], following j are not allocated */
494 break;
495 }
496 lyht_free(uniqtables[j]);
497 }
498 free(uniqtables);
499
500 return ret;
Michal Vaskoa3881362020-01-21 15:57:35 +0100501}
502
503static LY_ERR
504lyd_validate_cases(const struct lysc_node_case *cases, struct lyd_node *sibling)
505{
506 /* TODO check there are nodes only from a single case,
507 * what if not? validation error or autodelete */
508 return LY_SUCCESS;
509}
510
511static LY_ERR
Michal Vaskoacd83e72020-02-04 14:12:01 +0100512lyd_validate_siblings_schema_r(struct lyd_node *sibling, const struct lysc_node *sparent, const struct lysc_module *mod,
513 int options)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100514{
Michal Vaskocde73ac2019-11-14 16:10:27 +0100515 const struct lysc_node *snode = NULL;
Michal Vaskoa3881362020-01-21 15:57:35 +0100516 struct lysc_node_list *slist;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100517
Michal Vaskoa3881362020-01-21 15:57:35 +0100518 /* disabled nodes are skipped by lys_getnext */
519 while ((snode = lys_getnext(snode, sparent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
Michal Vaskoa3881362020-01-21 15:57:35 +0100520 /* check min-elements and max-elements */
521 if (snode->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
522 slist = (struct lysc_node_list *)snode;
523 if (slist->min || slist->max) {
524 LY_CHECK_RET(lyd_validate_minmax(snode, slist->min, slist->max, sibling));
525 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100526
527 /* check generic mandatory existence */
528 } else if (snode->flags & LYS_MAND_TRUE) {
529 LY_CHECK_RET(lyd_validate_mandatory(snode, sibling));
Michal Vaskoa3881362020-01-21 15:57:35 +0100530 }
531
532 /* check unique */
533 if (snode->nodetype == LYS_LIST) {
534 slist = (struct lysc_node_list *)snode;
535 if (slist->uniques) {
536 LY_CHECK_RET(lyd_validate_unique(snode, slist->uniques, sibling));
537 }
538 }
539
540 /* check case duplicites */
541 if (snode->nodetype == LYS_CHOICE) {
542 LY_CHECK_RET(lyd_validate_cases(((struct lysc_node_choice *)snode)->cases, sibling));
543 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100544
545 if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
546 /* go recursively for schema-only nodes */
547 LY_CHECK_RET(lyd_validate_siblings_schema_r(sibling, snode, mod, options));
548 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100549 }
550
Michal Vaskoacd83e72020-02-04 14:12:01 +0100551 return LY_SUCCESS;
552}
553
554static LY_ERR
555lyd_validate_siblings_r(struct lyd_node *sibling, const struct lysc_node *sparent, const struct lysc_module *mod, int options)
556{
557 struct lyd_node *node;
558
Michal Vasko14654712020-02-06 08:35:21 +0100559 /* validate all restrictions of nodes themselves */
Michal Vaskoacd83e72020-02-04 14:12:01 +0100560 LY_LIST_FOR(sibling, node) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100561 /* TODO node instance duplicities */
Michal Vaskocde73ac2019-11-14 16:10:27 +0100562 /* TODO node's must */
Michal Vaskocde73ac2019-11-14 16:10:27 +0100563 /* TODO node status */
Michal Vaskoa3881362020-01-21 15:57:35 +0100564 /* TODO node's if-features */
565 /* TODO node list keys */
566 /* node value including if-feature is checked by plugins */
Michal Vasko14654712020-02-06 08:35:21 +0100567 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100568
Michal Vasko14654712020-02-06 08:35:21 +0100569 /* validate schema-based restrictions */
570 LY_CHECK_RET(lyd_validate_siblings_schema_r(sibling, sparent, mod, options));
571
572 LY_LIST_FOR(sibling, node) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100573 /* this sibling is valid */
574 node->flags &= ~LYD_NEW;
575
Michal Vasko14654712020-02-06 08:35:21 +0100576 /* validate all children recursively */
577 LY_CHECK_RET(lyd_validate_siblings_r((struct lyd_node *)lyd_node_children(node), node->schema, mod, options));
Michal Vaskocde73ac2019-11-14 16:10:27 +0100578 }
579
580 return LY_SUCCESS;
581}
582
583LY_ERR
Michal Vaskoacd83e72020-02-04 14:12:01 +0100584lyd_validate_data(const struct lyd_node **trees, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
Michal Vasko9b368d32020-02-14 13:53:31 +0100585 int val_opts)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100586{
Michal Vaskocde73ac2019-11-14 16:10:27 +0100587 uint32_t i = 0, j;
588 const struct lys_module *mod;
589 struct lyd_node *tree;
590
Michal Vasko9b368d32020-02-14 13:53:31 +0100591 if (val_opts & LYD_VALOPT_DATA_ONLY) {
Michal Vaskocde73ac2019-11-14 16:10:27 +0100592 if (trees) {
593 for (j = 0; j < LY_ARRAY_SIZE(trees); ++j) {
Michal Vaskoa3881362020-01-21 15:57:35 +0100594 tree = (struct lyd_node *)trees[j];
595
596 /* validate all top-level nodes and then inner nodes recursively */
Michal Vasko9b368d32020-02-14 13:53:31 +0100597 LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, tree->schema->module->compiled, val_opts));
Michal Vaskocde73ac2019-11-14 16:10:27 +0100598 }
599 }
Michal Vaskoa3881362020-01-21 15:57:35 +0100600 } else {
601 while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
602 if (!mod->implemented) {
603 continue;
604 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100605
Michal Vaskoa3881362020-01-21 15:57:35 +0100606 /* find data of this module, if any */
607 tree = NULL;
608 if (trees) {
609 for (j = 0; j < LY_ARRAY_SIZE(trees); ++j) {
610 if (trees[j]->schema->module == mod) {
611 tree = (struct lyd_node *)trees[j];
612 break;
613 }
614 }
615 }
616
617 /* validate all top-level nodes and then inner nodes recursively */
Michal Vasko9b368d32020-02-14 13:53:31 +0100618 LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, mod->compiled, val_opts));
619 }
620 }
621
622 return LY_SUCCESS;
623}
624
625LY_ERR
626lyd_validate_defaults_r(struct lyd_node_inner *parent, struct lyd_node **first, const struct lysc_node *schema,
627 const struct lysc_module *mod, struct ly_set *node_types, struct ly_set *node_when)
628{
629 const struct lysc_node *iter = NULL;
630 struct lyd_node *node;
631 struct lyd_value **dflts;
632 size_t i;
633
634 assert(first && (schema || mod) && node_types && node_when);
635
636 while ((iter = lys_getnext(iter, schema, mod, LYS_GETNEXT_WITHCHOICE))) {
637 switch (iter->nodetype) {
638 case LYS_CHOICE:
639 if (((struct lysc_node_choice *)iter)->dflt && !lyd_val_has_choice_data(iter, *first)) {
640 /* create default case data */
641 LY_CHECK_RET(lyd_validate_defaults_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
642 NULL, node_types, node_when));
643 }
644 break;
645 case LYS_CONTAINER:
646 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
647 /* create default NP container (default flag automatically set) */
648 LY_CHECK_RET(lyd_create_inner(iter, &node));
649 lyd_insert_node((struct lyd_node *)parent, first, node);
650
651 if (iter->when) {
652 /* remember to resolve when */
653 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
654 }
655 }
656 break;
657 case LYS_LEAF:
658 if (((struct lysc_node_leaf *)iter)->dflt && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
659 /* create default leaf */
660 LY_CHECK_RET(lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node));
661 node->flags |= LYD_DEFAULT;
662 lyd_insert_node((struct lyd_node *)parent, first, node);
663
664 if (iter->when) {
665 /* remember to resolve when */
666 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
667 }
668 }
669 break;
670 case LYS_LEAFLIST:
671 if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_next2(*first, iter, NULL, 0, NULL)) {
672 /* create all default leaf-lists */
673 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
674 LY_ARRAY_FOR(dflts, i) {
675 LY_CHECK_RET(lyd_create_term2(iter, dflts[i], &node));
676 node->flags |= LYD_DEFAULT;
677 lyd_insert_node((struct lyd_node *)parent, first, node);
678
679 if (iter->when) {
680 /* remember to resolve when */
681 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
682 }
683 }
684 }
685 break;
686 default:
687 /* without defaults */
688 break;
689 }
690 }
691
692 return LY_SUCCESS;
693}
694
695LY_ERR
696lyd_validate_defaults_top(struct lyd_node **first, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
697 struct ly_set *node_types, struct ly_set *node_when, int val_opts)
698{
699 uint32_t i = 0;
700 const struct lys_module *mod;
701 struct lyd_node *sibling;
702
703 assert(node_types && node_when);
704
705 if (val_opts & LYD_VALOPT_DATA_ONLY) {
706 mod = NULL;
707 LY_LIST_FOR(*first, sibling) {
708 if (lyd_top_node_module(sibling) != mod) {
709 /* remember this module */
710 mod = lyd_top_node_module(sibling);
711
712 /* add all top-level defaults for this module */
713 LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
714 }
715 }
716 } else {
717 while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
718 if (!mod->implemented) {
719 continue;
720 }
721
722 /* add all top-level defaults for this module */
723 LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
Michal Vaskoa3881362020-01-21 15:57:35 +0100724 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100725 }
726
727 return LY_SUCCESS;
728}