blob: 96246cd91a86f7c96e2875bcb2f056524d308108 [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
Michal Vaskof03ed032020-03-04 13:31:44 +010023static struct lyd_node *
24lys_getnext_data(const struct lyd_node *last, const struct lyd_node *sibling, const struct lysc_node **slast,
25 const struct lysc_node *parent, const struct lysc_module *module)
26{
27 const struct lysc_node *siter = NULL;
28 struct lyd_node *match = NULL;
29
30 assert(parent || module);
31 assert(!last || (slast && *slast));
32
33 if (slast) {
34 siter = *slast;
35 }
36
37 if (last && last->next) {
38 /* find next data instance */
39 lyd_find_sibling_next2(last->next, siter, NULL, 0, &match);
40 if (match) {
41 return match;
42 }
43 }
44
45 /* find next schema node data instance */
46 while ((siter = lys_getnext(siter, parent, module, 0))) {
47 switch (siter->nodetype) {
48 case LYS_CONTAINER:
49 case LYS_ANYXML:
50 case LYS_ANYDATA:
51 case LYS_LEAF:
52 lyd_find_sibling_val(sibling, siter, NULL, 0, &match);
53 break;
54 case LYS_LIST:
55 case LYS_LEAFLIST:
56 lyd_find_sibling_next2(sibling, siter, NULL, 0, &match);
57 break;
58 default:
59 assert(0);
60 LOGINT(NULL);
61 }
62
63 if (match) {
64 break;
65 }
66 }
67
68 if (slast) {
69 *slast = siter;
70 }
71 return match;
72}
73
Michal Vaskocde73ac2019-11-14 16:10:27 +010074/**
75 * @brief Evaluate a single "when" condition.
76 *
77 * @param[in] when When to evaluate.
78 * @param[in] node Node whose existence depends on this when.
Michal Vaskof03ed032020-03-04 13:31:44 +010079 * @param[in] tree Data tree.
Michal Vaskocde73ac2019-11-14 16:10:27 +010080 * @return LY_ERR value (LY_EINCOMPLETE if a referenced node does not have its when evaluated)
81 */
82static LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +010083lyd_val_when(struct lysc_when *when, struct lyd_node *node, const struct lyd_node *tree)
Michal Vaskocde73ac2019-11-14 16:10:27 +010084{
85 LY_ERR ret;
86 const struct lyd_node *ctx_node;
87 struct lyxp_set xp_set;
88
89 memset(&xp_set, 0, sizeof xp_set);
90
91 if (when->context == node->schema) {
92 ctx_node = node;
93 } else {
94 assert((!when->context && !node->parent) || (when->context == node->parent->schema));
95 ctx_node = (struct lyd_node *)node->parent;
96 }
97
98 /* evaluate when */
99 ret = lyxp_eval(when->cond, LYD_UNKNOWN, when->module, ctx_node, ctx_node ? LYXP_NODE_ELEM : LYXP_NODE_ROOT_CONFIG,
Michal Vaskof03ed032020-03-04 13:31:44 +0100100 tree, &xp_set, LYXP_SCHEMA);
Michal Vaskocde73ac2019-11-14 16:10:27 +0100101 lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
102
103 /* return error or LY_EINCOMPLETE for dependant unresolved when */
104 LY_CHECK_RET(ret);
105
106 /* take action based on the result */
107 if (!xp_set.val.bool) {
108 if (node->flags & LYD_WHEN_TRUE) {
109 /* autodelete */
110 lyd_free_tree(node);
111 } else {
112 /* invalid data */
113 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOWHEN, when->cond->expr);
114 ret = LY_EVALID;
115 }
116 } else {
117 /* remember that when evaluated to true */
118 node->flags |= LYD_WHEN_TRUE;
119 }
120
121 return ret;
122}
123
124LY_ERR
125lyd_validate_unres(struct ly_set *node_types, struct ly_set *attr_types, struct ly_set *node_when, LYD_FORMAT format,
Michal Vaskof03ed032020-03-04 13:31:44 +0100126 ly_clb_resolve_prefix get_prefix_clb, void *parser_data, const struct lyd_node *tree)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100127{
128 LY_ERR ret = LY_SUCCESS;
129 uint32_t u;
130
131 /* finish incompletely validated terminal values */
132 for (u = 0; node_types && (u < node_types->count); u++) {
133 struct lyd_node_term *node = (struct lyd_node_term *)node_types->objs[u];
134
135 /* validate and store the value of the node */
136 ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1, get_prefix_clb,
Michal Vaskof03ed032020-03-04 13:31:44 +0100137 parser_data, format, tree);
Michal Vaskocde73ac2019-11-14 16:10:27 +0100138 LY_CHECK_RET(ret);
139 }
140
141 /* ... and attribute values */
142 for (u = 0; attr_types && (u < attr_types->count); u++) {
143 struct lyd_attr *attr = (struct lyd_attr *)attr_types->objs[u];
144
145 /* validate and store the value of the node */
Michal Vasko8d544252020-03-02 10:19:52 +0100146 ret = lyd_value_parse_attr(attr->parent->schema->module->ctx, attr, attr->value.original,
Michal Vaskof03ed032020-03-04 13:31:44 +0100147 strlen(attr->value.original), 0, 1, get_prefix_clb, parser_data, format, NULL, tree);
Michal Vaskocde73ac2019-11-14 16:10:27 +0100148 LY_CHECK_RET(ret);
149 }
150
151 /* no when conditions */
152 if (!node_when || !node_when->count) {
153 return ret;
154 }
155
156 /* evaluate all when conditions */
157 uint32_t prev_count;
158 do {
159 prev_count = node_when->count;
160 u = 0;
161 while (u < node_when->count) {
162 /* evaluate all when expressions that affect this node's existence */
163 struct lyd_node *node = (struct lyd_node *)node_when->objs[u];
164 const struct lysc_node *schema = node->schema;
165 int unres_when = 0;
166
167 do {
168 uint32_t i;
169 LY_ARRAY_FOR(schema->when, i) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100170 ret = lyd_val_when(schema->when[i], node, tree);
Michal Vaskocde73ac2019-11-14 16:10:27 +0100171 if (ret) {
172 break;
173 }
174 }
175 if (ret == LY_EINCOMPLETE) {
176 /* could not evaluate this when */
177 unres_when = 1;
178 break;
179 } else if (ret) {
180 /* error */
181 return ret;
182 }
183 schema = schema->parent;
184 } while (schema && (schema->nodetype & (LYS_CASE | LYS_CHOICE)));
185
186 if (unres_when) {
187 /* keep in set and go to the next node */
188 ++u;
189 } else {
190 /* remove this node from the set */
191 ly_set_rm_index(node_when, u, NULL);
192 }
193 }
194
195 /* there must have been some when conditions resolved */
196 } while (prev_count > node_when->count);
197
198 /* there could have been no cyclic when dependencies, checked during compilation */
199 assert(!node_when->count);
200
201 return ret;
202}
203
204static const struct lys_module *
205lyd_val_next_module(const struct lys_module **modules, int mod_count, struct ly_ctx *ctx, uint32_t *i)
206{
207 if (modules && mod_count) {
208 return modules[(*i)++];
209 }
210
211 return ly_ctx_get_module_iter(ctx, i);
212}
213
214static LY_ERR
Michal Vaskoa3881362020-01-21 15:57:35 +0100215lyd_validate_mandatory(const struct lysc_node *snode, struct lyd_node *sibling)
216{
Michal Vaskoa3881362020-01-21 15:57:35 +0100217 if (snode->nodetype == LYS_CHOICE) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100218 /* some data of a choice case exist */
Michal Vaskof03ed032020-03-04 13:31:44 +0100219 if (lys_getnext_data(NULL, sibling, NULL, snode, NULL)) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100220 return LY_SUCCESS;
221 }
222 } else {
223 assert(snode->nodetype & (LYS_LEAF | LYS_CONTAINER | LYD_NODE_ANY));
Michal Vaskoa3881362020-01-21 15:57:35 +0100224
Michal Vasko9b368d32020-02-14 13:53:31 +0100225 if (!lyd_find_sibling_val(sibling, snode, NULL, 0, NULL)) {
226 /* data instance found */
227 return LY_SUCCESS;
Michal Vaskoa3881362020-01-21 15:57:35 +0100228 }
229 }
230
231 /* node instance not found */
232 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAND, snode->name);
233 return LY_EVALID;
234}
235
236static LY_ERR
237lyd_validate_minmax(const struct lysc_node *snode, uint32_t min, uint32_t max, struct lyd_node *sibling)
238{
Michal Vaskoacd83e72020-02-04 14:12:01 +0100239 uint32_t count = 0;
240 struct lyd_node *iter;
241
Michal Vasko9b368d32020-02-14 13:53:31 +0100242 assert(min || max);
243
Michal Vaskoacd83e72020-02-04 14:12:01 +0100244 LY_LIST_FOR(sibling, iter) {
245 if (iter->schema == snode) {
246 ++count;
Michal Vasko9b368d32020-02-14 13:53:31 +0100247
248 if (min && (count == min)) {
249 /* satisfied */
250 min = 0;
251 if (!max) {
252 /* nothing more to check */
253 break;
254 }
255 }
256 if (max && (count > max)) {
257 /* not satisifed */
258 break;
259 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100260 }
261 }
262
Michal Vasko9b368d32020-02-14 13:53:31 +0100263 if (min) {
264 assert(count < min);
Michal Vaskoacd83e72020-02-04 14:12:01 +0100265 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMIN, snode->name);
266 return LY_EVALID;
267 } else if (max && (count > max)) {
268 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAX, snode->name);
269 return LY_EVALID;
270 }
271
Michal Vaskoa3881362020-01-21 15:57:35 +0100272 return LY_SUCCESS;
273}
274
Michal Vasko14654712020-02-06 08:35:21 +0100275static struct lyd_node *
276lyd_val_uniq_find_leaf(const struct lysc_node_leaf *uniq_leaf, struct lyd_node *list)
277{
Michal Vasko9b368d32020-02-14 13:53:31 +0100278 struct lyd_node *node;
279 const struct lysc_node *iter;
280 size_t depth = 0, i;
Michal Vasko14654712020-02-06 08:35:21 +0100281
Michal Vasko9b368d32020-02-14 13:53:31 +0100282 /* get leaf depth */
283 for (iter = (struct lysc_node *)uniq_leaf; iter && (iter != list->schema); iter = iter->parent) {
284 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
285 ++depth;
286 }
Michal Vasko14654712020-02-06 08:35:21 +0100287 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100288
289 node = list;
290 while (node && depth) {
291 /* find schema node with this depth */
292 for (i = depth - 1, iter = (struct lysc_node *)uniq_leaf; i; iter = iter->parent) {
293 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
294 --i;
295 }
296 }
297
298 /* find iter instance in children */
299 assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
300 lyd_find_sibling_val(lyd_node_children(node), iter, NULL, 0, &node);
301 --depth;
302 }
303
Michal Vasko14654712020-02-06 08:35:21 +0100304 return node;
305}
306
307/*
308 * actions (cb_data):
309 * 0 - compare all uniques
310 * n - compare n-th unique
311 */
312static int
313lyd_val_uniq_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
314{
315 struct ly_ctx *ctx;
316 struct lysc_node_list *slist;
317 struct lyd_node *diter, *first, *second;
318 struct lyd_value *val1, *val2;
319 char *path1, *path2, *uniq_str, *ptr;
320 uint32_t i, j, action;
321
322 assert(val1_p && val2_p);
323
324 first = *((struct lyd_node **)val1_p);
325 second = *((struct lyd_node **)val2_p);
326 action = (uintptr_t)cb_data;
327
328 assert(first && (first->schema->nodetype == LYS_LIST));
329 assert(second && (second->schema == first->schema));
330
331 ctx = first->schema->module->ctx;
332
333 slist = (struct lysc_node_list *)first->schema;
334
335 /* compare unique leaves */
336 if (action > 0) {
337 i = action - 1;
338 if (i < LY_ARRAY_SIZE(slist->uniques)) {
339 goto uniquecheck;
340 }
341 }
342 LY_ARRAY_FOR(slist->uniques, i) {
343uniquecheck:
344 LY_ARRAY_FOR(slist->uniques[i], j) {
345 /* first */
346 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], first);
347 if (diter) {
348 val1 = &((struct lyd_node_term *)diter)->value;
349 } else {
350 /* use default value */
351 val1 = slist->uniques[i][j]->dflt;
352 }
353
354 /* second */
355 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], second);
356 if (diter) {
357 val2 = &((struct lyd_node_term *)diter)->value;
358 } else {
359 /* use default value */
360 val2 = slist->uniques[i][j]->dflt;
361 }
362
363 if (!val1 || !val2 || val1->realtype->plugin->compare(val1, val2)) {
364 /* values differ or either one is not set */
365 break;
366 }
367 }
368 if (j && (j == LY_ARRAY_SIZE(slist->uniques[i]))) {
369 /* all unique leafs are the same in this set, create this nice error */
370 path1 = lyd_path(first, LYD_PATH_LOG, NULL, 0);
371 path2 = lyd_path(second, LYD_PATH_LOG, NULL, 0);
372
373 /* use buffer to rebuild the unique string */
374 uniq_str = malloc(1024);
375 uniq_str[0] = '\0';
376 ptr = uniq_str;
377 LY_ARRAY_FOR(slist->uniques[i], j) {
378 if (j) {
379 strcpy(ptr, " ");
380 ++ptr;
381 }
382 ptr = lysc_path_until((struct lysc_node *)slist->uniques[i][j], (struct lysc_node *)slist, LYSC_PATH_LOG,
383 ptr, 1024 - (ptr - uniq_str));
384 if (!ptr) {
385 /* path will be incomplete, whatever */
386 break;
387 }
388
389 ptr += strlen(ptr);
390 }
391 LOGVAL(ctx, LY_VLOG_LYD, second, LY_VCODE_NOUNIQ, uniq_str, path1, path2);
392
393 free(path1);
394 free(path2);
395 free(uniq_str);
396 return 1;
397 }
398
399 if (action > 0) {
400 /* done */
401 return 0;
402 }
403 }
404
405 return 0;
406}
407
Michal Vaskoa3881362020-01-21 15:57:35 +0100408static LY_ERR
409lyd_validate_unique(const struct lysc_node *snode, struct lysc_node_leaf ***uniques, struct lyd_node *sibling)
410{
Michal Vasko14654712020-02-06 08:35:21 +0100411 struct lyd_node *diter;
412 struct ly_set *set;
413 uint32_t i, j, n = 0;
414 LY_ERR ret = LY_SUCCESS;
415 uint32_t hash, u, usize = 0;
416 int dynamic;
417 const char *str;
418 struct hash_table **uniqtables = NULL;
419 struct lyd_value *val;
420 struct ly_ctx *ctx = snode->module->ctx;
421
422 assert(uniques);
423
424 /* get all list instances */
Michal Vasko9b368d32020-02-14 13:53:31 +0100425 set = ly_set_new();
426 LY_CHECK_ERR_RET(!set, LOGMEM(ctx), LY_EMEM);
427 LY_LIST_FOR(sibling, diter) {
428 if (diter->schema == snode) {
429 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
430 }
431 }
Michal Vasko14654712020-02-06 08:35:21 +0100432
433 if (set->count == 2) {
434 /* simple comparison */
435 if (lyd_val_uniq_list_equal(&set->objs[0], &set->objs[1], 0, (void *)0)) {
436 /* instance duplication */
437 ret = LY_EVALID;
438 goto cleanup;
439 }
440 } else if (set->count > 2) {
441 /* use hashes for comparison */
442 /* first, allocate the table, the size depends on number of items in the set */
443 for (u = 31; u > 0; u--) {
444 usize = set->count << u;
445 usize = usize >> u;
446 if (usize == set->count) {
447 break;
448 }
449 }
450 LY_CHECK_ERR_GOTO(!u, LOGINT(ctx); ret = LY_EINT, cleanup);
451 u = 32 - u;
452 usize = 1 << u;
453
454 uniqtables = malloc(LY_ARRAY_SIZE(uniques) * sizeof *uniqtables);
455 LY_CHECK_ERR_GOTO(!uniqtables, LOGMEM(ctx); ret = LY_EMEM, cleanup);
456 n = LY_ARRAY_SIZE(uniques);
457 for (j = 0; j < n; j++) {
458 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyd_val_uniq_list_equal, (void *)(j + 1L), 0);
459 LY_CHECK_ERR_GOTO(!uniqtables[j], LOGMEM(ctx); ret = LY_EMEM, cleanup);
460 }
461
462 for (u = 0; u < set->count; u++) {
463 /* loop for unique - get the hash for the instances */
464 for (i = 0; i < n; i++) {
465 val = NULL;
466 for (j = hash = 0; j < LY_ARRAY_SIZE(uniques[i]); j++) {
467 diter = lyd_val_uniq_find_leaf(uniques[i][j], set->objs[u]);
468 if (diter) {
469 val = &((struct lyd_node_term *)diter)->value;
470 } else {
471 /* use default value */
472 val = uniques[i][j]->dflt;
473 }
474 if (!val) {
475 /* unique item not present nor has default value */
476 break;
477 }
478
479 /* get canonical string value */
480 str = val->realtype->plugin->print(val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
481 hash = dict_hash_multi(hash, str, strlen(str));
482 if (dynamic) {
483 free((char *)str);
484 }
485 }
486 if (!val) {
487 /* skip this list instance since its unique set is incomplete */
488 continue;
489 }
490
491 /* finish the hash value */
492 hash = dict_hash_multi(hash, NULL, 0);
493
494 /* insert into the hashtable */
495 ret = lyht_insert(uniqtables[i], &set->objs[u], hash, NULL);
496 if (ret == LY_EEXIST) {
497 /* instance duplication */
498 ret = LY_EVALID;
499 }
500 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
501 }
502 }
503 }
504
505cleanup:
506 ly_set_free(set, NULL);
507 for (j = 0; j < n; j++) {
508 if (!uniqtables[j]) {
509 /* failed when allocating uniquetables[j], following j are not allocated */
510 break;
511 }
512 lyht_free(uniqtables[j]);
513 }
514 free(uniqtables);
515
516 return ret;
Michal Vaskoa3881362020-01-21 15:57:35 +0100517}
518
519static LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +0100520lyd_validate_cases(const struct lysc_node_choice *choic, struct lyd_node **sibling)
Michal Vaskoa3881362020-01-21 15:57:35 +0100521{
Michal Vaskof03ed032020-03-04 13:31:44 +0100522 const struct lysc_node *scase, *iter, *old_case = NULL, *new_case = NULL;
523 struct lyd_node *match, *to_del;
524 int found;
525
526 LY_LIST_FOR((struct lysc_node *)choic->cases, scase) {
527 found = 0;
528 iter = NULL;
529 match = NULL;
530 while ((match = lys_getnext_data(match, *sibling, &iter, scase, NULL))) {
531 if (match->flags & LYD_NEW) {
532 /* a new case data found, nothing more to look for */
533 found = 2;
534 break;
535 } else {
536 /* and old case data found */
537 if (found == 0) {
538 found = 1;
539 }
540 }
541 }
542
543 if (found == 1) {
544 /* there cannot be 2 old cases */
545 assert(!old_case);
546
547 /* remember an old existing case */
548 old_case = scase;
549 } else if (found == 2) {
550 if (new_case) {
551 /* new data from 2 cases */
552 LOGVAL(choic->module->ctx, LY_VLOG_LYSC, choic, LY_VCODE_DUPCASE, new_case->name, scase->name);
553 return LY_EVALID;
554 }
555
556 /* remember a new existing case */
557 new_case = scase;
558 }
559 }
560
561 if (old_case && new_case) {
562 /* auto-delete old case */
563 iter = NULL;
564 match = NULL;
565 to_del = NULL;
566 while ((match = lys_getnext_data(match, *sibling, &iter, old_case, NULL))) {
567 if ((*sibling == to_del) && !(*sibling)->parent) {
568 *sibling = (*sibling)->next;
569 }
570 lyd_free_tree(to_del);
571 to_del = match;
572 }
573 if ((*sibling == to_del) && !(*sibling)->parent) {
574 *sibling = (*sibling)->next;
575 }
576 lyd_free_tree(to_del);
577 }
578
Michal Vaskoa3881362020-01-21 15:57:35 +0100579 return LY_SUCCESS;
580}
581
582static LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +0100583lyd_validate_siblings_schema_r(struct lyd_node **sibling, const struct lysc_node *sparent, const struct lysc_module *mod,
Michal Vaskoacd83e72020-02-04 14:12:01 +0100584 int options)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100585{
Michal Vaskocde73ac2019-11-14 16:10:27 +0100586 const struct lysc_node *snode = NULL;
Michal Vaskoa3881362020-01-21 15:57:35 +0100587 struct lysc_node_list *slist;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100588
Michal Vaskoa3881362020-01-21 15:57:35 +0100589 /* disabled nodes are skipped by lys_getnext */
590 while ((snode = lys_getnext(snode, sparent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
Michal Vaskoa3881362020-01-21 15:57:35 +0100591 /* check min-elements and max-elements */
592 if (snode->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
593 slist = (struct lysc_node_list *)snode;
594 if (slist->min || slist->max) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100595 LY_CHECK_RET(lyd_validate_minmax(snode, slist->min, slist->max, *sibling));
Michal Vaskoa3881362020-01-21 15:57:35 +0100596 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100597
598 /* check generic mandatory existence */
599 } else if (snode->flags & LYS_MAND_TRUE) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100600 LY_CHECK_RET(lyd_validate_mandatory(snode, *sibling));
Michal Vaskoa3881362020-01-21 15:57:35 +0100601 }
602
603 /* check unique */
604 if (snode->nodetype == LYS_LIST) {
605 slist = (struct lysc_node_list *)snode;
606 if (slist->uniques) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100607 LY_CHECK_RET(lyd_validate_unique(snode, slist->uniques, *sibling));
Michal Vaskoa3881362020-01-21 15:57:35 +0100608 }
609 }
610
611 /* check case duplicites */
612 if (snode->nodetype == LYS_CHOICE) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100613 LY_CHECK_RET(lyd_validate_cases((struct lysc_node_choice *)snode, sibling));
Michal Vaskoa3881362020-01-21 15:57:35 +0100614 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100615
616 if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
617 /* go recursively for schema-only nodes */
618 LY_CHECK_RET(lyd_validate_siblings_schema_r(sibling, snode, mod, options));
619 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100620 }
621
Michal Vaskoacd83e72020-02-04 14:12:01 +0100622 return LY_SUCCESS;
623}
624
625static LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +0100626lyd_validate_dup_nodes(struct lyd_node *sibling, struct lyd_node *node)
Michal Vaskoacd83e72020-02-04 14:12:01 +0100627{
Michal Vaskof03ed032020-03-04 13:31:44 +0100628 struct lyd_node **match_p;
629 int fail = 0;
630
631 if ((node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && (node->schema->flags & LYS_CONFIG_R)) {
632 /* duplicate instances allowed */
633 return LY_SUCCESS;
634 }
635
636 /* find exactly the same next instance using hashes if possible */
637 if (node->parent && node->parent->children_ht) {
638 if (!lyht_find_next(node->parent->children_ht, &node, node->hash, (void **)&match_p)) {
639 fail = 1;
640 }
641 } else {
642 for (; sibling; sibling = sibling->next) {
643 if (sibling == node) {
644 continue;
645 }
646
647 if (node->schema->nodetype & (LYD_NODE_ANY | LYS_LEAF)) {
648 if (sibling->schema == node->schema) {
649 fail = 1;
650 break;
651 }
652 } else if (!lyd_compare(sibling, node, 0)) {
653 fail = 1;
654 break;
655 }
656 }
657 }
658
659 if (fail) {
660 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_DUP, node->schema->name);
661 return LY_EVALID;
662 }
663 return LY_SUCCESS;
664}
665
666static LY_ERR
667lyd_validate_siblings_r(struct lyd_node **sibling, const struct lysc_node *sparent, const struct lysc_module *mod, int options)
668{
669 struct lyd_node *next, *node, *match;
670
671 assert(sibling);
Michal Vaskoacd83e72020-02-04 14:12:01 +0100672
Michal Vasko14654712020-02-06 08:35:21 +0100673 /* validate all restrictions of nodes themselves */
Michal Vaskof03ed032020-03-04 13:31:44 +0100674 LY_LIST_FOR_SAFE(*sibling, next, node) {
675 if (node->flags & LYD_NEW) {
676 /* new node instance duplicities */
677 LY_CHECK_RET(lyd_validate_dup_nodes(*sibling, node));
678 } else if (node->flags & LYD_DEFAULT) {
679 /* remove default if there is an explicit instance */
680 assert(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER));
681 if (node->schema->nodetype == LYS_LEAFLIST) {
682 lyd_find_sibling_next2(*sibling, node->schema, NULL, 0, &match);
683 } else {
684 lyd_find_sibling_val(*sibling, node->schema, NULL, 0, &match);
685 }
686 while (match && (match->flags & LYD_DEFAULT) && !(match->flags & LYD_NEW)) {
687 lyd_find_sibling_next2(match->next, node->schema, NULL, 0, &match);
688 }
689
690 if (match) {
691 /* non-default (or at least new for container) instance found, remove the default one */
692 if ((*sibling == node) && !(*sibling)->parent) {
693 *sibling = (*sibling)->next;
694 }
695 lyd_free_tree(node);
696 continue;
697 }
698 }
699
Michal Vaskocde73ac2019-11-14 16:10:27 +0100700 /* TODO node's must */
Michal Vaskocde73ac2019-11-14 16:10:27 +0100701 /* TODO node status */
Michal Vaskoa3881362020-01-21 15:57:35 +0100702 /* TODO node's if-features */
Michal Vaskof03ed032020-03-04 13:31:44 +0100703 /* TODO list all keys existence */
Michal Vaskoa3881362020-01-21 15:57:35 +0100704 /* node value including if-feature is checked by plugins */
Michal Vasko14654712020-02-06 08:35:21 +0100705 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100706
Michal Vasko14654712020-02-06 08:35:21 +0100707 /* validate schema-based restrictions */
708 LY_CHECK_RET(lyd_validate_siblings_schema_r(sibling, sparent, mod, options));
709
Michal Vaskof03ed032020-03-04 13:31:44 +0100710 LY_LIST_FOR(*sibling, node) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100711 /* this sibling is valid */
712 node->flags &= ~LYD_NEW;
713
Michal Vasko14654712020-02-06 08:35:21 +0100714 /* validate all children recursively */
Michal Vaskof03ed032020-03-04 13:31:44 +0100715 if (node->schema->nodetype & LYD_NODE_INNER) {
716 LY_CHECK_RET(lyd_validate_siblings_r(lyd_node_children_p(node), node->schema, mod, options));
717 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100718 }
719
720 return LY_SUCCESS;
721}
722
723LY_ERR
Michal Vaskof03ed032020-03-04 13:31:44 +0100724lyd_validate_data(struct lyd_node **tree, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
Michal Vasko9b368d32020-02-14 13:53:31 +0100725 int val_opts)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100726{
Michal Vaskof03ed032020-03-04 13:31:44 +0100727 uint32_t i = 0;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100728 const struct lys_module *mod;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100729
Michal Vasko9b368d32020-02-14 13:53:31 +0100730 if (val_opts & LYD_VALOPT_DATA_ONLY) {
Michal Vaskof03ed032020-03-04 13:31:44 +0100731 if (*tree) {
732 /* TODO all modules, not just first */
733 /* validate all top-level nodes and then inner nodes recursively */
734 LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, (*tree)->schema->module->compiled, val_opts));
Michal Vaskocde73ac2019-11-14 16:10:27 +0100735 }
Michal Vaskoa3881362020-01-21 15:57:35 +0100736 } else {
737 while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
738 if (!mod->implemented) {
739 continue;
740 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100741
Michal Vaskoa3881362020-01-21 15:57:35 +0100742 /* validate all top-level nodes and then inner nodes recursively */
Michal Vasko9b368d32020-02-14 13:53:31 +0100743 LY_CHECK_RET(lyd_validate_siblings_r(tree, NULL, mod->compiled, val_opts));
744 }
745 }
746
747 return LY_SUCCESS;
748}
749
750LY_ERR
751lyd_validate_defaults_r(struct lyd_node_inner *parent, struct lyd_node **first, const struct lysc_node *schema,
752 const struct lysc_module *mod, struct ly_set *node_types, struct ly_set *node_when)
753{
754 const struct lysc_node *iter = NULL;
755 struct lyd_node *node;
756 struct lyd_value **dflts;
757 size_t i;
758
759 assert(first && (schema || mod) && node_types && node_when);
760
761 while ((iter = lys_getnext(iter, schema, mod, LYS_GETNEXT_WITHCHOICE))) {
762 switch (iter->nodetype) {
763 case LYS_CHOICE:
Michal Vaskof03ed032020-03-04 13:31:44 +0100764 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100765 /* create default case data */
766 LY_CHECK_RET(lyd_validate_defaults_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
767 NULL, node_types, node_when));
768 }
769 break;
770 case LYS_CONTAINER:
771 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
772 /* create default NP container (default flag automatically set) */
773 LY_CHECK_RET(lyd_create_inner(iter, &node));
774 lyd_insert_node((struct lyd_node *)parent, first, node);
775
776 if (iter->when) {
777 /* remember to resolve when */
778 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
779 }
780 }
781 break;
782 case LYS_LEAF:
783 if (((struct lysc_node_leaf *)iter)->dflt && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
784 /* create default leaf */
785 LY_CHECK_RET(lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node));
786 node->flags |= LYD_DEFAULT;
787 lyd_insert_node((struct lyd_node *)parent, first, node);
788
789 if (iter->when) {
790 /* remember to resolve when */
791 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
792 }
793 }
794 break;
795 case LYS_LEAFLIST:
796 if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_next2(*first, iter, NULL, 0, NULL)) {
797 /* create all default leaf-lists */
798 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
799 LY_ARRAY_FOR(dflts, i) {
800 LY_CHECK_RET(lyd_create_term2(iter, dflts[i], &node));
801 node->flags |= LYD_DEFAULT;
802 lyd_insert_node((struct lyd_node *)parent, first, node);
803
804 if (iter->when) {
805 /* remember to resolve when */
806 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
807 }
808 }
809 }
810 break;
811 default:
812 /* without defaults */
813 break;
814 }
815 }
816
817 return LY_SUCCESS;
818}
819
820LY_ERR
821lyd_validate_defaults_top(struct lyd_node **first, const struct lys_module **modules, int mod_count, struct ly_ctx *ctx,
822 struct ly_set *node_types, struct ly_set *node_when, int val_opts)
823{
824 uint32_t i = 0;
825 const struct lys_module *mod;
826 struct lyd_node *sibling;
827
828 assert(node_types && node_when);
829
830 if (val_opts & LYD_VALOPT_DATA_ONLY) {
831 mod = NULL;
832 LY_LIST_FOR(*first, sibling) {
833 if (lyd_top_node_module(sibling) != mod) {
834 /* remember this module */
835 mod = lyd_top_node_module(sibling);
836
837 /* add all top-level defaults for this module */
838 LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
839 }
840 }
841 } else {
842 while ((mod = lyd_val_next_module(modules, mod_count, ctx, &i))) {
843 if (!mod->implemented) {
844 continue;
845 }
846
847 /* add all top-level defaults for this module */
848 LY_CHECK_RET(lyd_validate_defaults_r(NULL, first, NULL, mod->compiled, node_types, node_when));
Michal Vaskoa3881362020-01-21 15:57:35 +0100849 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100850 }
851
852 return LY_SUCCESS;
853}
Michal Vaskof03ed032020-03-04 13:31:44 +0100854
855API LY_ERR
856lyd_validate(const struct ly_ctx *ctx, struct lyd_node **tree, int val_opts)
857{
858 LY_ERR ret = LY_SUCCESS;
859 struct lyd_node *root, *next, *elem;
860 const struct lyd_attr *attr;
861 struct ly_set type_check = {0}, type_attr_check = {0}, when_check = {0};
862
863 LY_CHECK_ARG_RET(ctx, tree, ctx || *tree, LY_EINVAL);
864
865 if (!ctx) {
866 ctx = (*tree)->schema->module->ctx;
867 }
868
869 /* add nested defaults, collect all types and nodes with when condition */
870 LY_LIST_FOR(*tree, root) {
871 LYD_TREE_DFS_BEGIN(root, next, elem) {
872 LY_LIST_FOR(elem->attr, attr) {
873 ly_set_add(&type_attr_check, (void *)attr, LY_SET_OPT_USEASLIST);
874 }
875 if (elem->schema->nodetype & LYD_NODE_TERM) {
876 ly_set_add(&type_check, (void *)elem, LY_SET_OPT_USEASLIST);
877 } else if (elem->schema->nodetype & LYD_NODE_INNER) {
878 ret = lyd_validate_defaults_r((struct lyd_node_inner *)elem, lyd_node_children_p((struct lyd_node *)elem),
879 elem->schema, NULL, &type_check, &when_check);
880 LY_CHECK_GOTO(ret, cleanup);
881 }
882 if (!(elem->schema->nodetype & (LYS_ACTION | LYS_NOTIF)) && elem->schema->when) {
883 ly_set_add(&when_check, (void *)elem, LY_SET_OPT_USEASLIST);
884 }
885
886 LYD_TREE_DFS_END(root, next, elem);
887 }
888 }
889
890 /* add top-level default nodes */
891 ret = lyd_validate_defaults_top(tree, NULL, 0, (struct ly_ctx *)ctx, &type_check, &when_check, val_opts);
892 LY_CHECK_GOTO(ret, cleanup);
893
894 /* finish incompletely validated terminal values/attributes and when conditions */
895 ret = lyd_validate_unres(&type_check, &type_attr_check, &when_check, LYD_JSON, lydjson_resolve_prefix, NULL,
896 (const struct lyd_node *)tree);
897 LY_CHECK_GOTO(ret, cleanup);
898
899 /* context node and other validation tasks that depend on other data nodes */
900 ret = lyd_validate_data(tree, NULL, 0, (struct ly_ctx *)ctx, val_opts);
901 LY_CHECK_GOTO(ret, cleanup);
902
903cleanup:
904 ly_set_erase(&type_check, NULL);
905 ly_set_erase(&type_attr_check, NULL);
906 ly_set_erase(&when_check, NULL);
907 return ret;
908}