blob: eb28b7c09314e83bb5fd90175413423b09aa2cac [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 *
Michal Vaskob1b5c262020-03-05 14:29:47 +010077 * @param[in,out] tree Data tree, is updated if some nodes are autodeleted.
Michal Vaskocde73ac2019-11-14 16:10:27 +010078 * @param[in] node Node whose existence depends on this when.
Michal Vaskob1b5c262020-03-05 14:29:47 +010079 * @param[in] when When to evaluate.
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 Vaskoc193ce92020-03-06 11:04:48 +010083lyd_validate_when(struct lyd_node **tree, struct lyd_node *node, struct lysc_when *when)
Michal Vaskocde73ac2019-11-14 16:10:27 +010084{
Michal Vaskob1b5c262020-03-05 14:29:47 +010085 LY_ERR ret = LY_SUCCESS;
Michal Vaskocde73ac2019-11-14 16:10:27 +010086 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 Vaskob1b5c262020-03-05 14:29:47 +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 */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100110 if (LYD_DEL_IS_ROOT(*tree, node)) {
111 *tree = (*tree)->next;
112 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100113 lyd_free_tree(node);
114 } else {
115 /* invalid data */
116 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOWHEN, when->cond->expr);
117 ret = LY_EVALID;
118 }
119 } else {
120 /* remember that when evaluated to true */
121 node->flags |= LYD_WHEN_TRUE;
122 }
123
124 return ret;
125}
126
127LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100128lyd_validate_unres(struct lyd_node **tree, struct ly_set *node_when, struct ly_set *node_types, struct ly_set *attr_types,
129 LYD_FORMAT format, ly_clb_resolve_prefix get_prefix_clb, void *parser_data)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100130{
131 LY_ERR ret = LY_SUCCESS;
132 uint32_t u;
133
Michal Vaskob1b5c262020-03-05 14:29:47 +0100134 if (node_when) {
135 /* evaluate all when conditions */
136 uint32_t prev_count;
137 do {
138 prev_count = node_when->count;
139 u = 0;
140 while (u < node_when->count) {
141 /* evaluate all when expressions that affect this node's existence */
142 struct lyd_node *node = (struct lyd_node *)node_when->objs[u];
143 const struct lysc_node *schema = node->schema;
144 int unres_when = 0;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100145
Michal Vaskob1b5c262020-03-05 14:29:47 +0100146 do {
147 uint32_t i;
148 LY_ARRAY_FOR(schema->when, i) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100149 ret = lyd_validate_when(tree, node, schema->when[i]);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100150 if (ret) {
151 break;
152 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100153 }
Michal Vaskob1b5c262020-03-05 14:29:47 +0100154 if (ret == LY_EINCOMPLETE) {
155 /* could not evaluate this when */
156 unres_when = 1;
157 break;
158 } else if (ret) {
159 /* error */
160 return ret;
161 }
162 schema = schema->parent;
163 } while (schema && (schema->nodetype & (LYS_CASE | LYS_CHOICE)));
Michal Vaskocde73ac2019-11-14 16:10:27 +0100164
Michal Vaskob1b5c262020-03-05 14:29:47 +0100165 if (unres_when) {
166 /* keep in set and go to the next node */
167 ++u;
168 } else {
169 /* remove this node from the set */
170 ly_set_rm_index(node_when, u, NULL);
171 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100172 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100173
Michal Vaskob1b5c262020-03-05 14:29:47 +0100174 /* there must have been some when conditions resolved */
175 } while (prev_count > node_when->count);
Michal Vaskocde73ac2019-11-14 16:10:27 +0100176
Michal Vaskob1b5c262020-03-05 14:29:47 +0100177 /* there could have been no cyclic when dependencies, checked during compilation */
178 assert(!node_when->count);
179 }
180
181 if (node_types && node_types->count) {
182 /* finish incompletely validated terminal values (traverse from the end for efficient set removal) */
183 u = node_types->count;
184 do {
185 --u;
186
187 struct lyd_node_term *node = (struct lyd_node_term *)node_types->objs[u];
188
189 /* validate and store the value of the node */
190 ret = lyd_value_parse(node, node->value.original, strlen(node->value.original), 0, 1, get_prefix_clb,
191 parser_data, format, *tree);
192 LY_CHECK_RET(ret);
193
194 /* remove this node from the set */
195 ly_set_rm_index(node_types, u, NULL);
196 } while (u);
197 }
198
199 if (attr_types && attr_types->count) {
200 /* ... and attribute values */
201 u = attr_types->count;
202 do {
203 --u;
204
205 struct lyd_attr *attr = (struct lyd_attr *)attr_types->objs[u];
206
207 /* validate and store the value of the node */
208 ret = lyd_value_parse_attr(attr->parent->schema->module->ctx, attr, attr->value.original,
209 strlen(attr->value.original), 0, 1, get_prefix_clb, parser_data, format, NULL, *tree);
210 LY_CHECK_RET(ret);
211
212 /* remove this attr from the set */
213 ly_set_rm_index(attr_types, u, NULL);
214 } while (u);
215 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100216
217 return ret;
218}
219
Michal Vaskob1b5c262020-03-05 14:29:47 +0100220static LY_ERR
221lyd_validate_duplicates(const struct lyd_node *first, const struct lyd_node *node)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100222{
Michal Vaskob1b5c262020-03-05 14:29:47 +0100223 struct lyd_node **match_p;
224 int fail = 0;
225
226 if ((node->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) && (node->schema->flags & LYS_CONFIG_R)) {
227 /* duplicate instances allowed */
228 return LY_SUCCESS;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100229 }
230
Michal Vaskob1b5c262020-03-05 14:29:47 +0100231 /* find exactly the same next instance using hashes if possible */
232 if (node->parent && node->parent->children_ht) {
233 if (!lyht_find_next(node->parent->children_ht, &node, node->hash, (void **)&match_p)) {
234 fail = 1;
235 }
236 } else {
237 for (; first; first = first->next) {
238 if (first == node) {
239 continue;
240 }
241
242 if (node->schema->nodetype & (LYD_NODE_ANY | LYS_LEAF)) {
243 if (first->schema == node->schema) {
244 fail = 1;
245 break;
246 }
247 } else if (!lyd_compare(first, node, 0)) {
248 fail = 1;
249 break;
250 }
251 }
252 }
253
254 if (fail) {
255 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_DUP, node->schema->name);
256 return LY_EVALID;
257 }
258 return LY_SUCCESS;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100259}
260
261static LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100262lyd_validate_cases(struct lyd_node **first, const struct lysc_node_choice *choic)
263{
264 const struct lysc_node *scase, *iter, *old_case = NULL, *new_case = NULL;
265 struct lyd_node *match, *to_del;
266 int found;
267
268 LY_LIST_FOR((struct lysc_node *)choic->cases, scase) {
269 found = 0;
270 iter = NULL;
271 match = NULL;
272 while ((match = lys_getnext_data(match, *first, &iter, scase, NULL))) {
273 if (match->flags & LYD_NEW) {
274 /* a new case data found, nothing more to look for */
275 found = 2;
276 break;
277 } else {
278 /* and old case data found */
279 if (found == 0) {
280 found = 1;
281 }
282 }
283 }
284
285 if (found == 1) {
286 /* there should not be 2 old cases */
287 if (old_case) {
288 /* old data from 2 cases */
289 LOGVAL(choic->module->ctx, LY_VLOG_LYSC, choic, LY_VCODE_DUPCASE, old_case->name, scase->name);
290 return LY_EVALID;
291 }
292
293 /* remember an old existing case */
294 old_case = scase;
295 } else if (found == 2) {
296 if (new_case) {
297 /* new data from 2 cases */
298 LOGVAL(choic->module->ctx, LY_VLOG_LYSC, choic, LY_VCODE_DUPCASE, new_case->name, scase->name);
299 return LY_EVALID;
300 }
301
302 /* remember a new existing case */
303 new_case = scase;
304 }
305 }
306
307 if (old_case && new_case) {
308 /* auto-delete old case */
309 iter = NULL;
310 match = NULL;
311 to_del = NULL;
312 while ((match = lys_getnext_data(match, *first, &iter, old_case, NULL))) {
313 if (LYD_DEL_IS_ROOT(*first, to_del)) {
314 *first = (*first)->next;
315 }
316 lyd_free_tree(to_del);
317 to_del = match;
318 }
319 if (LYD_DEL_IS_ROOT(*first, to_del)) {
320 *first = (*first)->next;
321 }
322 lyd_free_tree(to_del);
323 }
324
325 return LY_SUCCESS;
326}
327
328static int
329lyd_val_has_default(const struct lysc_node *schema)
330{
331 switch (schema->nodetype) {
332 case LYS_LEAF:
333 if (((struct lysc_node_leaf *)schema)->dflt) {
334 return 1;
335 }
336 break;
337 case LYS_LEAFLIST:
338 if (((struct lysc_node_leaflist *)schema)->dflts) {
339 return 1;
340 }
341 break;
342 case LYS_CONTAINER:
343 if (!(schema->flags & LYS_PRESENCE)) {
344 return 1;
345 }
346 break;
347 default:
348 break;
349 }
350
351 return 0;
352}
353
354static void
355lyd_validate_autodel_dup(struct lyd_node **first, struct lyd_node *node, struct lyd_node **next_p)
356{
357 struct lyd_node *match, *next;
358
359 if (lyd_val_has_default(node->schema)) {
360 assert(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER));
361 if (node->schema->nodetype == LYS_LEAFLIST) {
362 lyd_find_sibling_next2(*first, node->schema, NULL, 0, &match);
363 } else {
364 lyd_find_sibling_val(*first, node->schema, NULL, 0, &match);
365 }
366
367 while (match) {
368 next = match->next;
369 if ((match->flags & LYD_DEFAULT) && !(match->flags & LYD_NEW)) {
370 /* default instance found, remove it */
371 if (LYD_DEL_IS_ROOT(*first, match)) {
372 *first = (*first)->next;
373 }
374 if (match == *next_p) {
375 *next_p = (*next_p)->next;
376 }
377 lyd_free_tree(match);
378
379 /* remove only a single container/leaf default instance, if there are more, it is an error */
380 if (node->schema->nodetype & (LYS_LEAF | LYS_CONTAINER)) {
381 break;
382 }
383 }
384
385 lyd_find_sibling_next2(next, node->schema, NULL, 0, &match);
386 }
387 }
388}
389
390LY_ERR
391lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod)
392{
393 struct lyd_node *next, *node;
394 const struct lysc_node *snode = NULL;
395
396 assert(first && (sparent || mod));
397
398 while (*first && (snode = lys_getnext(snode, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
399 /* check case duplicites */
400 if (snode->nodetype == LYS_CHOICE) {
401 LY_CHECK_RET(lyd_validate_cases(first, (struct lysc_node_choice *)snode));
402 }
403 }
404
405 LY_LIST_FOR_SAFE(*first, next, node) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100406 if (mod && (lyd_owner_module(node) != mod)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100407 /* all top-level data from this module checked */
408 break;
409 }
410
411 if (!(node->flags & LYD_NEW)) {
412 /* check only new nodes */
413 continue;
414 }
415
416 /* remove old default(s) if it exists */
417 lyd_validate_autodel_dup(first, node, &next);
418
419 /* then check new node instance duplicities */
420 LY_CHECK_RET(lyd_validate_duplicates(*first, node));
421
422 /* this node is valid */
423 node->flags &= ~LYD_NEW;
424 }
425
426 return LY_SUCCESS;
427}
428
429static LY_ERR
430lyd_validate_mandatory(const struct lyd_node *first, const struct lysc_node *snode)
Michal Vaskoa3881362020-01-21 15:57:35 +0100431{
Michal Vaskoa3881362020-01-21 15:57:35 +0100432 if (snode->nodetype == LYS_CHOICE) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100433 /* some data of a choice case exist */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100434 if (lys_getnext_data(NULL, first, NULL, snode, NULL)) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100435 return LY_SUCCESS;
436 }
437 } else {
438 assert(snode->nodetype & (LYS_LEAF | LYS_CONTAINER | LYD_NODE_ANY));
Michal Vaskoa3881362020-01-21 15:57:35 +0100439
Michal Vaskob1b5c262020-03-05 14:29:47 +0100440 if (!lyd_find_sibling_val(first, snode, NULL, 0, NULL)) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100441 /* data instance found */
442 return LY_SUCCESS;
Michal Vaskoa3881362020-01-21 15:57:35 +0100443 }
444 }
445
446 /* node instance not found */
447 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAND, snode->name);
448 return LY_EVALID;
449}
450
451static LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100452lyd_validate_minmax(const struct lyd_node *first, const struct lysc_node *snode, uint32_t min, uint32_t max)
Michal Vaskoa3881362020-01-21 15:57:35 +0100453{
Michal Vaskoacd83e72020-02-04 14:12:01 +0100454 uint32_t count = 0;
Michal Vaskob1b5c262020-03-05 14:29:47 +0100455 const struct lyd_node *iter;
Michal Vaskoacd83e72020-02-04 14:12:01 +0100456
Michal Vasko9b368d32020-02-14 13:53:31 +0100457 assert(min || max);
458
Michal Vaskob1b5c262020-03-05 14:29:47 +0100459 LY_LIST_FOR(first, iter) {
Michal Vaskoacd83e72020-02-04 14:12:01 +0100460 if (iter->schema == snode) {
461 ++count;
Michal Vasko9b368d32020-02-14 13:53:31 +0100462
463 if (min && (count == min)) {
464 /* satisfied */
465 min = 0;
466 if (!max) {
467 /* nothing more to check */
468 break;
469 }
470 }
471 if (max && (count > max)) {
472 /* not satisifed */
473 break;
474 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100475 }
476 }
477
Michal Vasko9b368d32020-02-14 13:53:31 +0100478 if (min) {
479 assert(count < min);
Michal Vaskoacd83e72020-02-04 14:12:01 +0100480 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMIN, snode->name);
481 return LY_EVALID;
482 } else if (max && (count > max)) {
483 LOGVAL(snode->module->ctx, LY_VLOG_LYSC, snode, LY_VCODE_NOMAX, snode->name);
484 return LY_EVALID;
485 }
486
Michal Vaskoa3881362020-01-21 15:57:35 +0100487 return LY_SUCCESS;
488}
489
Michal Vasko14654712020-02-06 08:35:21 +0100490static struct lyd_node *
491lyd_val_uniq_find_leaf(const struct lysc_node_leaf *uniq_leaf, struct lyd_node *list)
492{
Michal Vasko9b368d32020-02-14 13:53:31 +0100493 struct lyd_node *node;
494 const struct lysc_node *iter;
495 size_t depth = 0, i;
Michal Vasko14654712020-02-06 08:35:21 +0100496
Michal Vasko9b368d32020-02-14 13:53:31 +0100497 /* get leaf depth */
498 for (iter = (struct lysc_node *)uniq_leaf; iter && (iter != list->schema); iter = iter->parent) {
499 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
500 ++depth;
501 }
Michal Vasko14654712020-02-06 08:35:21 +0100502 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100503
504 node = list;
505 while (node && depth) {
506 /* find schema node with this depth */
507 for (i = depth - 1, iter = (struct lysc_node *)uniq_leaf; i; iter = iter->parent) {
508 if (!(iter->nodetype & (LYS_CHOICE | LYS_CASE))) {
509 --i;
510 }
511 }
512
513 /* find iter instance in children */
514 assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
515 lyd_find_sibling_val(lyd_node_children(node), iter, NULL, 0, &node);
516 --depth;
517 }
518
Michal Vasko14654712020-02-06 08:35:21 +0100519 return node;
520}
521
522/*
523 * actions (cb_data):
524 * 0 - compare all uniques
525 * n - compare n-th unique
526 */
527static int
528lyd_val_uniq_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
529{
530 struct ly_ctx *ctx;
531 struct lysc_node_list *slist;
532 struct lyd_node *diter, *first, *second;
533 struct lyd_value *val1, *val2;
534 char *path1, *path2, *uniq_str, *ptr;
535 uint32_t i, j, action;
536
537 assert(val1_p && val2_p);
538
539 first = *((struct lyd_node **)val1_p);
540 second = *((struct lyd_node **)val2_p);
541 action = (uintptr_t)cb_data;
542
543 assert(first && (first->schema->nodetype == LYS_LIST));
544 assert(second && (second->schema == first->schema));
545
546 ctx = first->schema->module->ctx;
547
548 slist = (struct lysc_node_list *)first->schema;
549
550 /* compare unique leaves */
551 if (action > 0) {
552 i = action - 1;
553 if (i < LY_ARRAY_SIZE(slist->uniques)) {
554 goto uniquecheck;
555 }
556 }
557 LY_ARRAY_FOR(slist->uniques, i) {
558uniquecheck:
559 LY_ARRAY_FOR(slist->uniques[i], j) {
560 /* first */
561 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], first);
562 if (diter) {
563 val1 = &((struct lyd_node_term *)diter)->value;
564 } else {
565 /* use default value */
566 val1 = slist->uniques[i][j]->dflt;
567 }
568
569 /* second */
570 diter = lyd_val_uniq_find_leaf(slist->uniques[i][j], second);
571 if (diter) {
572 val2 = &((struct lyd_node_term *)diter)->value;
573 } else {
574 /* use default value */
575 val2 = slist->uniques[i][j]->dflt;
576 }
577
578 if (!val1 || !val2 || val1->realtype->plugin->compare(val1, val2)) {
579 /* values differ or either one is not set */
580 break;
581 }
582 }
583 if (j && (j == LY_ARRAY_SIZE(slist->uniques[i]))) {
584 /* all unique leafs are the same in this set, create this nice error */
585 path1 = lyd_path(first, LYD_PATH_LOG, NULL, 0);
586 path2 = lyd_path(second, LYD_PATH_LOG, NULL, 0);
587
588 /* use buffer to rebuild the unique string */
589 uniq_str = malloc(1024);
590 uniq_str[0] = '\0';
591 ptr = uniq_str;
592 LY_ARRAY_FOR(slist->uniques[i], j) {
593 if (j) {
594 strcpy(ptr, " ");
595 ++ptr;
596 }
597 ptr = lysc_path_until((struct lysc_node *)slist->uniques[i][j], (struct lysc_node *)slist, LYSC_PATH_LOG,
598 ptr, 1024 - (ptr - uniq_str));
599 if (!ptr) {
600 /* path will be incomplete, whatever */
601 break;
602 }
603
604 ptr += strlen(ptr);
605 }
606 LOGVAL(ctx, LY_VLOG_LYD, second, LY_VCODE_NOUNIQ, uniq_str, path1, path2);
607
608 free(path1);
609 free(path2);
610 free(uniq_str);
611 return 1;
612 }
613
614 if (action > 0) {
615 /* done */
616 return 0;
617 }
618 }
619
620 return 0;
621}
622
Michal Vaskoa3881362020-01-21 15:57:35 +0100623static LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100624lyd_validate_unique(const struct lyd_node *first, const struct lysc_node *snode, struct lysc_node_leaf ***uniques)
Michal Vaskoa3881362020-01-21 15:57:35 +0100625{
Michal Vaskob1b5c262020-03-05 14:29:47 +0100626 const struct lyd_node *diter;
Michal Vasko14654712020-02-06 08:35:21 +0100627 struct ly_set *set;
628 uint32_t i, j, n = 0;
629 LY_ERR ret = LY_SUCCESS;
630 uint32_t hash, u, usize = 0;
631 int dynamic;
632 const char *str;
633 struct hash_table **uniqtables = NULL;
634 struct lyd_value *val;
635 struct ly_ctx *ctx = snode->module->ctx;
636
637 assert(uniques);
638
639 /* get all list instances */
Michal Vasko9b368d32020-02-14 13:53:31 +0100640 set = ly_set_new();
641 LY_CHECK_ERR_RET(!set, LOGMEM(ctx), LY_EMEM);
Michal Vaskob1b5c262020-03-05 14:29:47 +0100642 LY_LIST_FOR(first, diter) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100643 if (diter->schema == snode) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100644 ly_set_add(set, (void *)diter, LY_SET_OPT_USEASLIST);
Michal Vasko9b368d32020-02-14 13:53:31 +0100645 }
646 }
Michal Vasko14654712020-02-06 08:35:21 +0100647
648 if (set->count == 2) {
649 /* simple comparison */
650 if (lyd_val_uniq_list_equal(&set->objs[0], &set->objs[1], 0, (void *)0)) {
651 /* instance duplication */
652 ret = LY_EVALID;
653 goto cleanup;
654 }
655 } else if (set->count > 2) {
656 /* use hashes for comparison */
657 /* first, allocate the table, the size depends on number of items in the set */
658 for (u = 31; u > 0; u--) {
659 usize = set->count << u;
660 usize = usize >> u;
661 if (usize == set->count) {
662 break;
663 }
664 }
665 LY_CHECK_ERR_GOTO(!u, LOGINT(ctx); ret = LY_EINT, cleanup);
666 u = 32 - u;
667 usize = 1 << u;
668
669 uniqtables = malloc(LY_ARRAY_SIZE(uniques) * sizeof *uniqtables);
670 LY_CHECK_ERR_GOTO(!uniqtables, LOGMEM(ctx); ret = LY_EMEM, cleanup);
671 n = LY_ARRAY_SIZE(uniques);
672 for (j = 0; j < n; j++) {
673 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyd_val_uniq_list_equal, (void *)(j + 1L), 0);
674 LY_CHECK_ERR_GOTO(!uniqtables[j], LOGMEM(ctx); ret = LY_EMEM, cleanup);
675 }
676
677 for (u = 0; u < set->count; u++) {
678 /* loop for unique - get the hash for the instances */
679 for (i = 0; i < n; i++) {
680 val = NULL;
681 for (j = hash = 0; j < LY_ARRAY_SIZE(uniques[i]); j++) {
682 diter = lyd_val_uniq_find_leaf(uniques[i][j], set->objs[u]);
683 if (diter) {
684 val = &((struct lyd_node_term *)diter)->value;
685 } else {
686 /* use default value */
687 val = uniques[i][j]->dflt;
688 }
689 if (!val) {
690 /* unique item not present nor has default value */
691 break;
692 }
693
694 /* get canonical string value */
695 str = val->realtype->plugin->print(val, LYD_JSON, json_print_get_prefix, NULL, &dynamic);
696 hash = dict_hash_multi(hash, str, strlen(str));
697 if (dynamic) {
698 free((char *)str);
699 }
700 }
701 if (!val) {
702 /* skip this list instance since its unique set is incomplete */
703 continue;
704 }
705
706 /* finish the hash value */
707 hash = dict_hash_multi(hash, NULL, 0);
708
709 /* insert into the hashtable */
710 ret = lyht_insert(uniqtables[i], &set->objs[u], hash, NULL);
711 if (ret == LY_EEXIST) {
712 /* instance duplication */
713 ret = LY_EVALID;
714 }
715 LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
716 }
717 }
718 }
719
720cleanup:
721 ly_set_free(set, NULL);
722 for (j = 0; j < n; j++) {
723 if (!uniqtables[j]) {
724 /* failed when allocating uniquetables[j], following j are not allocated */
725 break;
726 }
727 lyht_free(uniqtables[j]);
728 }
729 free(uniqtables);
730
731 return ret;
Michal Vaskoa3881362020-01-21 15:57:35 +0100732}
733
734static LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100735lyd_validate_siblings_schema_r(const struct lyd_node *first, const struct lysc_node *sparent, const struct lysc_module *mod)
Michal Vaskocde73ac2019-11-14 16:10:27 +0100736{
Michal Vaskocde73ac2019-11-14 16:10:27 +0100737 const struct lysc_node *snode = NULL;
Michal Vaskoa3881362020-01-21 15:57:35 +0100738 struct lysc_node_list *slist;
Michal Vaskocde73ac2019-11-14 16:10:27 +0100739
Michal Vaskoa3881362020-01-21 15:57:35 +0100740 /* disabled nodes are skipped by lys_getnext */
741 while ((snode = lys_getnext(snode, sparent, mod, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHCASE))) {
Michal Vaskoa3881362020-01-21 15:57:35 +0100742 /* check min-elements and max-elements */
743 if (snode->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
744 slist = (struct lysc_node_list *)snode;
745 if (slist->min || slist->max) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100746 LY_CHECK_RET(lyd_validate_minmax(first, snode, slist->min, slist->max));
Michal Vaskoa3881362020-01-21 15:57:35 +0100747 }
Michal Vaskoacd83e72020-02-04 14:12:01 +0100748
749 /* check generic mandatory existence */
750 } else if (snode->flags & LYS_MAND_TRUE) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100751 LY_CHECK_RET(lyd_validate_mandatory(first, snode));
Michal Vaskoa3881362020-01-21 15:57:35 +0100752 }
753
754 /* check unique */
755 if (snode->nodetype == LYS_LIST) {
756 slist = (struct lysc_node_list *)snode;
757 if (slist->uniques) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100758 LY_CHECK_RET(lyd_validate_unique(first, snode, slist->uniques));
Michal Vaskoa3881362020-01-21 15:57:35 +0100759 }
760 }
761
Michal Vaskoacd83e72020-02-04 14:12:01 +0100762 if (snode->nodetype & (LYS_CHOICE | LYS_CASE)) {
763 /* go recursively for schema-only nodes */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100764 LY_CHECK_RET(lyd_validate_siblings_schema_r(first, snode, mod));
Michal Vaskoacd83e72020-02-04 14:12:01 +0100765 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100766 }
767
Michal Vaskoacd83e72020-02-04 14:12:01 +0100768 return LY_SUCCESS;
769}
770
Michal Vaskob1b5c262020-03-05 14:29:47 +0100771LY_ERR
772lyd_validate_siblings_r(struct lyd_node *first, const struct lysc_node *sparent, const struct lys_module *mod,
773 int val_opts)
Michal Vaskoacd83e72020-02-04 14:12:01 +0100774{
Michal Vaskob1b5c262020-03-05 14:29:47 +0100775 struct lyd_node *next, *node;
Michal Vaskoc193ce92020-03-06 11:04:48 +0100776 const struct lysc_node *snode;
Michal Vaskoacd83e72020-02-04 14:12:01 +0100777
Michal Vasko14654712020-02-06 08:35:21 +0100778 /* validate all restrictions of nodes themselves */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100779 LY_LIST_FOR_SAFE(first, next, node) {
Michal Vaskoc193ce92020-03-06 11:04:48 +0100780 if (mod && (lyd_owner_module(node) != mod)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100781 /* all top-level data from this module checked */
782 break;
Michal Vaskof03ed032020-03-04 13:31:44 +0100783 }
784
Michal Vaskoc193ce92020-03-06 11:04:48 +0100785 /* node's schema if-features */
786 if ((snode = lysc_node_is_disabled(node->schema, 1))) {
787 LOGVAL(node->schema->module->ctx, LY_VLOG_LYD, node, LY_VCODE_NOIFF, snode->name);
788 return LY_EVALID;
789 }
790
Michal Vaskocde73ac2019-11-14 16:10:27 +0100791 /* TODO node's must */
Michal Vaskocde73ac2019-11-14 16:10:27 +0100792 /* TODO node status */
Michal Vaskof03ed032020-03-04 13:31:44 +0100793 /* TODO list all keys existence */
Michal Vaskoa3881362020-01-21 15:57:35 +0100794 /* node value including if-feature is checked by plugins */
Michal Vasko14654712020-02-06 08:35:21 +0100795 }
Michal Vaskocde73ac2019-11-14 16:10:27 +0100796
Michal Vasko14654712020-02-06 08:35:21 +0100797 /* validate schema-based restrictions */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100798 LY_CHECK_RET(lyd_validate_siblings_schema_r(first, sparent, mod ? mod->compiled : NULL));
Michal Vasko14654712020-02-06 08:35:21 +0100799
Michal Vaskob1b5c262020-03-05 14:29:47 +0100800 LY_LIST_FOR(first, node) {
Michal Vasko14654712020-02-06 08:35:21 +0100801 /* validate all children recursively */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100802 LY_CHECK_RET(lyd_validate_siblings_r((struct lyd_node *)lyd_node_children(node), node->schema, NULL, val_opts));
Michal Vaskocde73ac2019-11-14 16:10:27 +0100803
Michal Vaskob1b5c262020-03-05 14:29:47 +0100804 /* set default for containers */
805 if ((node->schema->nodetype == LYS_CONTAINER) && !(node->schema->flags & LYS_PRESENCE)) {
806 LY_LIST_FOR((struct lyd_node *)lyd_node_children(node), next) {
807 if (!(next->flags & LYD_DEFAULT)) {
808 break;
809 }
Michal Vaskoa3881362020-01-21 15:57:35 +0100810 }
Michal Vaskob1b5c262020-03-05 14:29:47 +0100811 if (!next) {
812 node->flags |= LYD_DEFAULT;
813 }
Michal Vasko9b368d32020-02-14 13:53:31 +0100814 }
815 }
816
817 return LY_SUCCESS;
818}
819
820LY_ERR
Michal Vaskob1b5c262020-03-05 14:29:47 +0100821lyd_validate_defaults_r(struct lyd_node *parent, struct lyd_node **first, const struct lysc_node *sparent,
822 const struct lys_module *mod, struct ly_set *node_types, struct ly_set *node_when)
Michal Vasko9b368d32020-02-14 13:53:31 +0100823{
Michal Vaskob1b5c262020-03-05 14:29:47 +0100824 LY_ERR ret;
Michal Vasko9b368d32020-02-14 13:53:31 +0100825 const struct lysc_node *iter = NULL;
826 struct lyd_node *node;
827 struct lyd_value **dflts;
828 size_t i;
829
Michal Vaskob1b5c262020-03-05 14:29:47 +0100830 assert(first && (parent || sparent || mod) && node_types && node_when);
Michal Vasko9b368d32020-02-14 13:53:31 +0100831
Michal Vaskob1b5c262020-03-05 14:29:47 +0100832 if (!sparent && parent) {
833 sparent = parent->schema;
834 }
835
836 while ((iter = lys_getnext(iter, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100837 switch (iter->nodetype) {
838 case LYS_CHOICE:
Michal Vaskof03ed032020-03-04 13:31:44 +0100839 if (((struct lysc_node_choice *)iter)->dflt && !lys_getnext_data(NULL, *first, NULL, iter, NULL)) {
Michal Vasko9b368d32020-02-14 13:53:31 +0100840 /* create default case data */
841 LY_CHECK_RET(lyd_validate_defaults_r(parent, first, (struct lysc_node *)((struct lysc_node_choice *)iter)->dflt,
842 NULL, node_types, node_when));
843 }
844 break;
845 case LYS_CONTAINER:
846 if (!(iter->flags & LYS_PRESENCE) && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100847 /* create default NP container */
Michal Vasko9b368d32020-02-14 13:53:31 +0100848 LY_CHECK_RET(lyd_create_inner(iter, &node));
Michal Vaskob1b5c262020-03-05 14:29:47 +0100849 node->flags = LYD_DEFAULT;
850 lyd_insert_node(parent, first, node);
Michal Vasko9b368d32020-02-14 13:53:31 +0100851
852 if (iter->when) {
853 /* remember to resolve when */
854 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
855 }
Michal Vaskob1b5c262020-03-05 14:29:47 +0100856
857 /* create any default children */
858 LY_CHECK_RET(lyd_validate_defaults_r(node, lyd_node_children_p(node), NULL, NULL, node_types, node_when));
Michal Vasko9b368d32020-02-14 13:53:31 +0100859 }
860 break;
861 case LYS_LEAF:
862 if (((struct lysc_node_leaf *)iter)->dflt && lyd_find_sibling_val(*first, iter, NULL, 0, NULL)) {
863 /* create default leaf */
Michal Vaskob1b5c262020-03-05 14:29:47 +0100864 ret = lyd_create_term2(iter, ((struct lysc_node_leaf *)iter)->dflt, &node);
865 if (ret == LY_EINCOMPLETE) {
866 /* remember to resolve type */
867 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
868 } else if (ret) {
869 return ret;
870 }
871 node->flags = LYD_DEFAULT;
872 lyd_insert_node(parent, first, node);
Michal Vasko9b368d32020-02-14 13:53:31 +0100873
874 if (iter->when) {
875 /* remember to resolve when */
876 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
877 }
878 }
879 break;
880 case LYS_LEAFLIST:
881 if (((struct lysc_node_leaflist *)iter)->dflts && lyd_find_sibling_next2(*first, iter, NULL, 0, NULL)) {
882 /* create all default leaf-lists */
883 dflts = ((struct lysc_node_leaflist *)iter)->dflts;
884 LY_ARRAY_FOR(dflts, i) {
Michal Vaskob1b5c262020-03-05 14:29:47 +0100885 ret = lyd_create_term2(iter, dflts[i], &node);
886 if (ret == LY_EINCOMPLETE) {
887 /* remember to resolve type */
888 ly_set_add(node_types, node, LY_SET_OPT_USEASLIST);
889 } else if (ret) {
890 return ret;
891 }
892 node->flags = LYD_DEFAULT;
893 lyd_insert_node(parent, first, node);
Michal Vasko9b368d32020-02-14 13:53:31 +0100894
895 if (iter->when) {
896 /* remember to resolve when */
897 ly_set_add(node_when, node, LY_SET_OPT_USEASLIST);
898 }
899 }
900 }
901 break;
902 default:
903 /* without defaults */
904 break;
905 }
906 }
907
908 return LY_SUCCESS;
909}
910
Michal Vaskob1b5c262020-03-05 14:29:47 +0100911static LY_ERR
912_lyd_validate(struct lyd_node **tree, const struct lys_module **modules, int mod_count, const struct ly_ctx *ctx,
913 int val_opts)
Michal Vaskof03ed032020-03-04 13:31:44 +0100914{
915 LY_ERR ret = LY_SUCCESS;
Michal Vaskob1b5c262020-03-05 14:29:47 +0100916 struct lyd_node *first, *next, *node, **first2;
917 const struct lys_module *mod;
Michal Vaskof03ed032020-03-04 13:31:44 +0100918 const struct lyd_attr *attr;
919 struct ly_set type_check = {0}, type_attr_check = {0}, when_check = {0};
Michal Vaskob1b5c262020-03-05 14:29:47 +0100920 uint32_t i = 0;
Michal Vaskof03ed032020-03-04 13:31:44 +0100921
Michal Vaskob1b5c262020-03-05 14:29:47 +0100922 LY_CHECK_ARG_RET(NULL, tree, *tree || ctx || (modules && mod_count), LY_EINVAL);
Michal Vaskof03ed032020-03-04 13:31:44 +0100923
Michal Vaskob1b5c262020-03-05 14:29:47 +0100924 next = *tree;
925 while (1) {
926 if (val_opts & LYD_VALOPT_DATA_ONLY) {
927 mod = lyd_data_next_module(&next, &first);
928 } else {
929 mod = lyd_mod_next_module(next, modules, mod_count, ctx, &i, &first);
Michal Vaskof03ed032020-03-04 13:31:44 +0100930 }
Michal Vaskob1b5c262020-03-05 14:29:47 +0100931 if (!mod) {
932 break;
933 }
934 if (first == *tree) {
935 /* make sure first2 changes are carried to tree */
936 first2 = tree;
937 } else {
938 first2 = &first;
939 }
940
941 /* validate new top-level nodes of this module, autodelete */
942 ret = lyd_validate_new(first2, NULL, mod);
943 LY_CHECK_GOTO(ret, cleanup);
944
945 /* add all top-level defaults for this module */
946 ret = lyd_validate_defaults_r(NULL, first2, NULL, mod, &type_check, &when_check);
947 LY_CHECK_GOTO(ret, cleanup);
948
949 /* process nested nodes */
950 LY_LIST_FOR(*first2, first) {
951 LYD_TREE_DFS_BEGIN(first, next, node) {
952 /* skip added default nodes */
953 if ((node->flags & (LYD_DEFAULT | LYD_NEW)) != (LYD_DEFAULT | LYD_NEW)) {
954 LY_LIST_FOR(node->attr, attr) {
955 /* attribute type resolution */
956 ly_set_add(&type_attr_check, (void *)attr, LY_SET_OPT_USEASLIST);
957 }
958
959 if (node->schema->nodetype & LYD_NODE_TERM) {
960 /* node type resolution */
961 ly_set_add(&type_check, (void *)node, LY_SET_OPT_USEASLIST);
962 } else if (node->schema->nodetype & LYD_NODE_INNER) {
963 /* new node validation, autodelete */
964 ret = lyd_validate_new(lyd_node_children_p((struct lyd_node *)node), node->schema, NULL);
965 LY_CHECK_GOTO(ret, cleanup);
966
967 /* add nested defaults */
968 ret = lyd_validate_defaults_r(node, lyd_node_children_p((struct lyd_node *)node), NULL, NULL, &type_check,
969 &when_check);
970 LY_CHECK_GOTO(ret, cleanup);
971 }
972
973 if (!(node->schema->nodetype & (LYS_ACTION | LYS_NOTIF)) && node->schema->when) {
974 /* when evaluation */
975 ly_set_add(&when_check, (void *)node, LY_SET_OPT_USEASLIST);
976 }
977 }
978
979 LYD_TREE_DFS_END(first, next, node);
980 }
981 }
982
983 /* finish incompletely validated terminal values/attributes and when conditions */
984 ret = lyd_validate_unres(tree, &when_check, &type_check, &type_attr_check, LYD_JSON, lydjson_resolve_prefix, NULL);
985 LY_CHECK_GOTO(ret, cleanup);
986
987 /* perform final validation that assumes the data tree is final */
988 ret = lyd_validate_siblings_r(*first2, NULL, mod, val_opts);
989 LY_CHECK_GOTO(ret, cleanup);
Michal Vaskof03ed032020-03-04 13:31:44 +0100990 }
991
Michal Vaskof03ed032020-03-04 13:31:44 +0100992cleanup:
993 ly_set_erase(&type_check, NULL);
994 ly_set_erase(&type_attr_check, NULL);
995 ly_set_erase(&when_check, NULL);
996 return ret;
997}
Michal Vaskob1b5c262020-03-05 14:29:47 +0100998
999API LY_ERR
1000lyd_validate(struct lyd_node **tree, const struct ly_ctx *ctx, int val_opts)
1001{
1002 return _lyd_validate(tree, NULL, 0, ctx, val_opts);
1003}
1004
1005API LY_ERR
1006lyd_validate_modules(struct lyd_node **tree, const struct lys_module **modules, int mod_count, int val_opts)
1007{
1008 return _lyd_validate(tree, modules, mod_count, NULL, val_opts);
1009}