1 /**
2 * @file validation.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Data tree validation functions
5 *
6 * Copyright (c) 2015 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 <stdlib.h>
17 #include <string.h>
18
19 #include "common.h"
20 #include "validation.h"
21 #include "libyang.h"
22 #include "xpath.h"
23 #include "parser.h"
24 #include "resolve.h"
25 #include "tree_internal.h"
26 #include "xml_internal.h"
27
28 static int
lyv_keys(const struct lyd_node * list)29 lyv_keys(const struct lyd_node *list)
30 {
31 struct lyd_node *child;
32 struct lys_node_list *schema = (struct lys_node_list *)list->schema; /* shortcut */
33 int i;
34
35 for (i = 0, child = list->child; i < schema->keys_size; i++, child = child->next) {
36 if (!child || child->schema != (struct lys_node *)schema->keys[i]) {
37 /* key not found on the correct place */
38 LOGVAL(schema->module->ctx, LYE_MISSELEM, LY_VLOG_LYD, list, schema->keys[i]->name, schema->name);
39 for ( ; child; child = child->next) {
40 if (child->schema == (struct lys_node *)schema->keys[i]) {
41 LOGVAL(schema->module->ctx, LYE_SPEC, LY_VLOG_LYD, child, "Invalid position of the key element.");
42 break;
43 }
44 }
45 return 1;
46 }
47 }
48 return 0;
49 }
50
51 int
lyv_data_context(struct lyd_node * node,int options,int check_node_order,struct unres_data * unres)52 lyv_data_context(struct lyd_node *node, int options, int check_node_order, struct unres_data *unres)
53 {
54 const struct lys_node *siter = NULL;
55 struct lys_node *sparent, *op;
56 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
57 struct ly_ctx *ctx = node->schema->module->ctx;
58
59 assert(node);
60 assert(unres);
61
62 /* check if the node instance is enabled by if-feature */
63 if (lys_is_disabled(node->schema, 2)) {
64 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
65 return 1;
66 }
67
68 /* find (nested) operation node */
69 for (op = node->schema; op && !(op->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); op = lys_parent(op));
70
71 if (!(options & (LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
72 && (!(options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) || op)) {
73 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
74 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
75 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
76 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
77 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
78 return 1;
79 }
80 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) {
81 /* always retry validation on unres leafrefs, if again not possible, the correct flags should
82 * be set and the leafref will be kept unresolved */
83 leaf->value_flags &= ~LY_VALUE_UNRES;
84
85 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
86 return 1;
87 }
88 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
89 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
90 return 1;
91 }
92 }
93 }
94 }
95
96 /* check all relevant when conditions */
97 if (!(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
98 if (node->when_status & LYD_WHEN) {
99 if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF | LYD_OPT_NOTIF_FILTER)) && !op) {
100 /* we are validating an operation but are still on its parents (nested operation), parse them as trusted */
101 node->when_status |= LYD_WHEN_TRUE;
102 } else if (options & LYD_OPT_TRUSTED) {
103 node->when_status |= LYD_WHEN_TRUE;
104 } else if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
105 return 1;
106 }
107 }
108 }
109
110 /* check for (non-)presence of status data in edit-config data */
111 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
112 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
113 return 1;
114 }
115
116 /* check elements order in case of RPC's input and output */
117 if (check_node_order && !(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER)) &&
118 (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) && (node->validity & LYD_VAL_MAND) && op) {
119 if ((node->prev != node) && node->prev->next) {
120 /* find schema data parent */
121 for (sparent = lys_parent(node->schema);
122 sparent && (sparent->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE));
123 sparent = lys_parent(sparent));
124 for (siter = lys_getnext(node->schema, sparent, lyd_node_module(node), 0);
125 siter;
126 siter = lys_getnext(siter, sparent, lyd_node_module(node), 0)) {
127 if (siter == node->prev->schema) {
128 /* data predecessor has the schema node after
129 * the schema node of the data node being checked */
130 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
131 return 1;
132 }
133 }
134
135 }
136 }
137
138 return 0;
139 }
140
141 /*
142 * actions (cb_data):
143 * 0 - compare all uniques
144 * n - compare n-th unique
145 */
146 static int
lyv_list_uniq_equal(void * val1_p,void * val2_p,int UNUSED (mod),void * cb_data)147 lyv_list_uniq_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
148 {
149 struct ly_ctx *ctx;
150 struct lys_node_list *slist;
151 struct lyd_node *diter, *first, *second;
152 const char *val1, *val2;
153 char *path1, *path2, *uniq_str;
154 uint16_t idx_uniq;
155 int i, j, r, action;
156
157 assert(val1_p && val2_p);
158
159 first = *((struct lyd_node **)val1_p);
160 second = *((struct lyd_node **)val2_p);
161 action = (intptr_t)cb_data;
162
163 assert(first && (first->schema->nodetype == LYS_LIST));
164 assert(second && (second->schema == first->schema));
165
166 ctx = first->schema->module->ctx;
167
168 slist = (struct lys_node_list *)first->schema;
169
170 /* compare unique leaves */
171 if (action > 0) {
172 i = action - 1;
173 if (i < slist->unique_size) {
174 goto uniquecheck;
175 }
176 }
177 for (i = 0; i < slist->unique_size; i++) {
178 uniquecheck:
179 for (j = 0; j < slist->unique[i].expr_size; j++) {
180 /* first */
181 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], first->child);
182 if (diter) {
183 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
184 } else {
185 /* use default value */
186 if (lyd_get_unique_default(slist->unique[i].expr[j], first, &val1)) {
187 return 1;
188 }
189 }
190
191 /* second */
192 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], second->child);
193 if (diter) {
194 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
195 } else {
196 /* use default value */
197 if (lyd_get_unique_default(slist->unique[i].expr[j], second, &val2)) {
198 return 1;
199 }
200 }
201
202 if (!val1 || !val2 || !ly_strequal(val1, val2, 1)) {
203 /* values differ or either one is not set */
204 break;
205 }
206 }
207 if (j && (j == slist->unique[i].expr_size)) {
208 /* all unique leafs are the same in this set, create this nice error */
209 ly_vlog_build_path(LY_VLOG_LYD, first, &path1, 0, 0);
210 ly_vlog_build_path(LY_VLOG_LYD, second, &path2, 0, 0);
211
212 /* use buffer to rebuild the unique string */
213 uniq_str = malloc(1024);
214 idx_uniq = 0;
215 for (j = 0; j < slist->unique[i].expr_size; ++j) {
216 if (j) {
217 uniq_str[idx_uniq++] = ' ';
218 }
219 r = lyd_build_relative_data_path(lys_node_module((struct lys_node *)slist), first,
220 slist->unique[i].expr[j], &uniq_str[idx_uniq]);
221 if (r == -1) {
222 goto unique_errmsg_cleanup;
223 }
224 idx_uniq += r;
225 }
226
227 LOGVAL(ctx, LYE_NOUNIQ, LY_VLOG_LYD, second, uniq_str, path1, path2);
228 unique_errmsg_cleanup:
229 free(path1);
230 free(path2);
231 free(uniq_str);
232 return 1;
233 }
234
235 if (action > 0) {
236 /* done */
237 return 0;
238 }
239 }
240
241 return 0;
242 }
243
244 int
lyv_data_unique(struct lyd_node * list)245 lyv_data_unique(struct lyd_node *list)
246 {
247 struct lyd_node *diter;
248 struct ly_set *set;
249 uint32_t i, j, n = 0;
250 int ret = 0;
251 uint32_t hash, u, usize = 0;
252 struct hash_table **uniqtables = NULL;
253 const char *id;
254 char *path;
255 struct lys_node_list *slist;
256 struct ly_ctx *ctx = list->schema->module->ctx;
257
258 if (!(list->validity & LYD_VAL_UNIQUE)) {
259 /* validated sa part of another instance validation */
260 return 0;
261 }
262
263 slist = (struct lys_node_list *)list->schema;
264
265 /* get all list instances */
266 if (ly_vlog_build_path(LY_VLOG_LYD, list, &path, 0, 1)) {
267 return -1;
268 }
269 set = lyd_find_path(list, path);
270 free(path);
271 if (!set) {
272 return -1;
273 }
274
275 for (i = 0; i < set->number; ++i) {
276 /* remove the flag */
277 set->set.d[i]->validity &= ~LYD_VAL_UNIQUE;
278 }
279
280 if (set->number == 2) {
281 /* simple comparison */
282 if (lyv_list_uniq_equal(&set->set.d[0], &set->set.d[1], 0, (void *)0)) {
283 /* instance duplication */
284 ly_set_free(set);
285 return 1;
286 }
287 } else if (set->number > 2) {
288 /* use hashes for comparison */
289 /* first, allocate the table, the size depends on number of items in the set */
290 for (u = 31; u > 0; u--) {
291 usize = set->number << u;
292 usize = usize >> u;
293 if (usize == set->number) {
294 break;
295 }
296 }
297 if (u == 0) {
298 LOGINT(ctx);
299 ret = -1;
300 goto cleanup;
301 } else {
302 u = 32 - u;
303 usize = 1 << u;
304 }
305
306 n = slist->unique_size;
307 uniqtables = malloc(n * sizeof *uniqtables);
308 if (!uniqtables) {
309 LOGMEM(ctx);
310 ret = -1;
311 n = 0;
312 goto cleanup;
313 }
314 for (j = 0; j < n; j++) {
315 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_uniq_equal, (void *)(j + 1L), 0);
316 if (!uniqtables[j]) {
317 LOGMEM(ctx);
318 ret = -1;
319 goto cleanup;
320 }
321 }
322
323 for (u = 0; u < set->number; u++) {
324 /* loop for unique - get the hash for the instances */
325 for (j = 0; j < n; j++) {
326 id = NULL;
327 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
328 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
329 if (diter) {
330 id = ((struct lyd_node_leaf_list *)diter)->value_str;
331 } else {
332 /* use default value */
333 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
334 ret = -1;
335 goto cleanup;
336 }
337 }
338 if (!id) {
339 /* unique item not present nor has default value */
340 break;
341 }
342 hash = dict_hash_multi(hash, id, strlen(id));
343 }
344 if (!id) {
345 /* skip this list instance since its unique set is incomplete */
346 continue;
347 }
348
349 /* finish the hash value */
350 hash = dict_hash_multi(hash, NULL, 0);
351
352 /* insert into the hashtable */
353 if (lyht_insert(uniqtables[j], &set->set.d[u], hash, NULL)) {
354 ret = 1;
355 goto cleanup;
356 }
357 }
358 }
359 }
360
361 cleanup:
362 ly_set_free(set);
363 for (j = 0; j < n; j++) {
364 if (!uniqtables[j]) {
365 /* failed when allocating uniquetables[j], following j are not allocated */
366 break;
367 }
368 lyht_free(uniqtables[j]);
369 }
370 free(uniqtables);
371
372 return ret;
373 }
374
375 static int
lyv_list_equal(void * val1_p,void * val2_p,int UNUSED (mod),void * UNUSED (cb_data))376 lyv_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
377 {
378 struct ly_ctx *ctx;
379 struct lys_node_list *slist;
380 const struct lys_node *snode = NULL;
381 struct lyd_node *diter, *first, *second;
382 const char *val1, *val2;
383 int i;
384
385 assert(val1_p && val2_p);
386
387 first = *((struct lyd_node **)val1_p);
388 second = *((struct lyd_node **)val2_p);
389
390 assert(first && (first->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
391 assert(second && (second->schema == first->schema));
392
393 ctx = first->schema->module->ctx;
394
395 switch (first->schema->nodetype) {
396 case LYS_LEAFLIST:
397 if (!(first->schema->flags & LYS_CONFIG_W) && (first->schema->module->version >= LYS_VERSION_1_1)) {
398 /* same values are allowed for non-configuration data */
399 return 0;
400 }
401 /* compare values */
402 if (ly_strequal(((struct lyd_node_leaf_list *)first)->value_str,
403 ((struct lyd_node_leaf_list *)second)->value_str, 1)) {
404 LOGVAL(ctx, LYE_DUPLEAFLIST, LY_VLOG_LYD, second, second->schema->name,
405 ((struct lyd_node_leaf_list *)second)->value_str);
406 return 1;
407 }
408 return 0;
409 case LYS_LIST:
410 slist = (struct lys_node_list *)first->schema;
411
412 /* compare keys */
413 if (!slist->keys_size) {
414 /* status lists without keys */
415 return 0;
416 } else {
417 for (i = 0; i < slist->keys_size; i++) {
418 snode = (struct lys_node *)slist->keys[i];
419 val1 = val2 = NULL;
420 LY_TREE_FOR(first->child, diter) {
421 if (diter->schema == snode) {
422 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
423 break;
424 }
425 }
426 LY_TREE_FOR(second->child, diter) {
427 if (diter->schema == snode) {
428 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
429 break;
430 }
431 }
432 if (!ly_strequal(val1, val2, 1)) {
433 return 0;
434 }
435 }
436 }
437
438 LOGVAL(ctx, LYE_DUPLIST, LY_VLOG_LYD, second, second->schema->name);
439 return 1;
440
441 default:
442 LOGINT(ctx);
443 return 1;
444 }
445 }
446
447 int
lyv_data_dup(struct lyd_node * node,struct lyd_node * start)448 lyv_data_dup(struct lyd_node *node, struct lyd_node *start)
449 {
450 struct lyd_node *diter, *key;
451 struct ly_set *set;
452 int i, ret = 0;
453 uint32_t hash, u, usize = 0;
454 struct hash_table *keystable = NULL;
455 const char *id;
456 struct ly_ctx *ctx = node->schema->module->ctx;
457
458 /* get the first list/leaflist instance sibling */
459 if (!start) {
460 start = lyd_first_sibling(node);
461 }
462
463 /* check uniqueness of the list/leaflist instances (compare values) */
464 set = ly_set_new();
465 for (diter = start; diter; diter = diter->next) {
466 if (diter->schema != node->schema) {
467 /* check only instances of the same list/leaflist */
468 continue;
469 }
470
471 /* remove the flag */
472 diter->validity &= ~LYD_VAL_DUP;
473
474 /* store for comparison */
475 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
476 }
477
478 if (set->number == 2) {
479 /* simple comparison */
480 if (lyv_list_equal(&set->set.d[0], &set->set.d[1], 0, 0)) {
481 /* instance duplication */
482 ly_set_free(set);
483 return 1;
484 }
485 } else if (set->number > 2) {
486 /* use hashes for comparison */
487 /* first, allocate the table, the size depends on number of items in the set */
488 for (u = 31; u > 0; u--) {
489 usize = set->number << u;
490 usize = usize >> u;
491 if (usize == set->number) {
492 break;
493 }
494 }
495 if (u == 0) {
496 LOGINT(ctx);
497 ret = 1;
498 goto cleanup;
499 } else {
500 u = 32 - u;
501 usize = 1 << u;
502 }
503 keystable = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, 0, 0);
504 if (!keystable) {
505 LOGMEM(ctx);
506 ret = 1;
507 goto cleanup;
508 }
509
510 for (u = 0; u < set->number; u++) {
511 /* get the hash for the instance - keys */
512 if (node->schema->nodetype == LYS_LEAFLIST) {
513 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
514 hash = dict_hash_multi(0, id, strlen(id));
515 } else { /* LYS_LIST */
516 for (hash = i = 0, key = set->set.d[u]->child;
517 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
518 i++, key = key->next) {
519 id = ((struct lyd_node_leaf_list *)key)->value_str;
520 hash = dict_hash_multi(hash, id, strlen(id));
521 }
522 }
523 /* finish the hash value */
524 hash = dict_hash_multi(hash, NULL, 0);
525
526 /* insert into the hashtable */
527 if (lyht_insert(keystable, &set->set.d[u], hash, NULL)) {
528 ret = 1;
529 goto cleanup;
530 }
531 }
532 }
533
534 cleanup:
535 ly_set_free(set);
536 lyht_free(keystable);
537
538 return ret;
539 }
540
541 static struct lys_type *
find_orig_type(struct lys_type * par_type,LY_DATA_TYPE base_type)542 find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
543 {
544 struct lys_type *type, *prev_type, *tmp_type;
545 int found;
546
547 /* go through typedefs */
548 for (type = par_type; type->der->type.der; type = &type->der->type);
549
550 if (type->base == base_type) {
551 /* we have the result */
552 return type;
553 } else if ((type->base == LY_TYPE_LEAFREF) && !(type->value_flags & LY_VALUE_UNRES)) {
554 /* go through the leafref */
555 assert(type->info.lref.target);
556 return find_orig_type(&((struct lys_node_leaf *)type->info.lref.target)->type, base_type);
557 } else if (type->base == LY_TYPE_UNION) {
558 /* go through all the union types */
559 prev_type = NULL;
560 found = 0;
561 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
562 tmp_type = find_orig_type(prev_type, base_type);
563 if (tmp_type) {
564 return tmp_type;
565 }
566 found = 0;
567 }
568 }
569
570 /* not found */
571 return NULL;
572 }
573
574 static int
lyv_extension(struct lys_ext_instance ** ext,uint8_t size,struct lyd_node * node)575 lyv_extension(struct lys_ext_instance **ext, uint8_t size, struct lyd_node *node)
576 {
577 uint i;
578
579 for (i = 0; i < size; ++i) {
580 if ((ext[i]->flags & LYEXT_OPT_VALID) && ext[i]->def->plugin->valid_data) {
581 if (ext[i]->def->plugin->valid_data(ext[i], node)) {
582 return EXIT_FAILURE;
583 }
584 }
585 }
586 return 0;
587 }
588
589 static int
lyv_type_extension(struct lyd_node_leaf_list * leaf,struct lys_type * type,int first_type)590 lyv_type_extension(struct lyd_node_leaf_list *leaf, struct lys_type *type, int first_type)
591 {
592 struct lyd_node *node = (struct lyd_node *)leaf;
593 unsigned int i;
594
595 switch (type->base) {
596 case LY_TYPE_ENUM:
597 if (first_type && lyv_extension(leaf->value.enm->ext, leaf->value.enm->ext_size, node)) {
598 return EXIT_FAILURE;
599 }
600 break;
601 case LY_TYPE_STRING:
602 if (type->info.str.length &&
603 lyv_extension(type->info.str.length->ext, type->info.str.length->ext_size, node)) {
604 return EXIT_FAILURE;
605 }
606 for(i = 0; i < type->info.str.pat_count; ++i) {
607 if (lyv_extension(type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size, node)) {
608 return EXIT_FAILURE;
609 }
610 }
611 break;
612 case LY_TYPE_DEC64:
613 if (type->info.dec64.range &&
614 lyv_extension(type->info.dec64.range->ext, type->info.dec64.range->ext_size, node)) {
615 return EXIT_FAILURE;
616 }
617 break;
618 case LY_TYPE_INT8:
619 case LY_TYPE_INT16:
620 case LY_TYPE_INT32:
621 case LY_TYPE_INT64:
622 case LY_TYPE_UINT8:
623 case LY_TYPE_UINT16:
624 case LY_TYPE_UINT32:
625 case LY_TYPE_UINT64:
626 if (type->info.num.range &&
627 lyv_extension(type->info.num.range->ext, type->info.num.range->ext_size, node)) {
628 return EXIT_FAILURE;
629 }
630 break;
631 case LY_TYPE_BITS:
632 if (first_type) {
633 /* get the count of bits */
634 type = find_orig_type(&((struct lys_node_leaf *) leaf->schema)->type, LY_TYPE_BITS);
635 for (i = 0; i < type->info.bits.count; ++i) {
636 if (!leaf->value.bit[i]) {
637 continue;
638 }
639 if (lyv_extension(leaf->value.bit[i]->ext, leaf->value.bit[i]->ext_size, node)) {
640 return EXIT_FAILURE;
641 }
642 }
643 }
644 break;
645 case LY_TYPE_UNION:
646 for (i = 0; i < type->info.uni.count; ++i) {
647 if (type->info.uni.types[i].base == leaf->value_type) {
648 break;
649 }
650 }
651 if (i < type->info.uni.count &&
652 lyv_type_extension(leaf, &type->info.uni.types[i], first_type)) {
653 return EXIT_FAILURE;
654 }
655 break;
656 default:
657 break;
658 }
659
660
661 if (lyv_extension(type->ext, type->ext_size, node)) {
662 return EXIT_FAILURE;
663 }
664
665 while (type->der->type.der) {
666 type = &type->der->type;
667 if ((type->parent->flags & LYS_VALID_EXT)) {
668 if (lyv_type_extension(leaf, type, 0) || lyv_extension(type->parent->ext, type->parent->ext_size, node)) {
669 return EXIT_FAILURE;
670 }
671 }
672 }
673
674 return EXIT_SUCCESS;
675 }
676
677 int
lyv_data_content(struct lyd_node * node,int options,struct unres_data * unres)678 lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
679 {
680 const struct lys_node *schema, *siter, *parent;
681 struct lyd_node *diter, *start = NULL;
682 struct lys_ident *ident;
683 struct lys_tpdf *tpdf;
684 struct lys_type *type = NULL;
685 struct lyd_node_leaf_list *leaf;
686 unsigned int i, j = 0;
687 uint8_t iff_size;
688 struct lys_iffeature *iff;
689 const char *id, *idname;
690 struct ly_ctx *ctx;
691
692 assert(node);
693 assert(node->schema);
694 assert(unres);
695
696 schema = node->schema; /* shortcut */
697 ctx = schema->module->ctx;
698
699 if (!(node->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
700 for (diter = node->parent; diter; diter = diter->parent) {
701 if (diter->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
702 break;
703 }
704 }
705 if (!diter && (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF))) {
706 /* validating parent of a nested notification/action, skip most checks */
707 options |= LYD_OPT_TRUSTED;
708 }
709 }
710
711 if (node->validity & LYD_VAL_MAND) {
712 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
713 /* check presence and correct order of all keys in case of list */
714 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
715 if (lyv_keys(node)) {
716 return 1;
717 }
718 }
719
720 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
721 /* check number of instances (similar to list uniqueness) for non-list nodes */
722
723 /* find duplicity */
724 start = lyd_first_sibling(node);
725 for (diter = start; diter; diter = diter->next) {
726 if (diter->schema == schema && diter != node) {
727 parent = lys_parent(schema);
728 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
729 parent ? (parent->nodetype == LYS_EXT) ? ((struct lys_ext_instance *)parent)->arg_value : parent->name : "data tree");
730 return 1;
731 }
732 }
733 }
734
735 if (options & LYD_OPT_OBSOLETE) {
736 /* status - of the node's schema node itself and all its parents that
737 * cannot have their own instance (like a choice statement) */
738 siter = node->schema;
739 do {
740 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
741 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
742 return 1;
743 }
744 siter = lys_parent(siter);
745 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
746
747 /* status of the identity value */
748 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
749 if (options & LYD_OPT_OBSOLETE) {
750 /* check that we are not instantiating obsolete type */
751 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
752 while (tpdf) {
753 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
754 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
755 return 1;
756 }
757 tpdf = tpdf->type.der;
758 }
759 }
760 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
761 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
762 if (lyp_check_status(schema->flags, schema->module, schema->name,
763 ident->flags, ident->module, ident->name, NULL)) {
764 LOGPATH(ctx, LY_VLOG_LYD, node);
765 return 1;
766 }
767 }
768 }
769 }
770 }
771
772 /* check validation function for extension */
773 if (schema->flags & LYS_VALID_EXT) {
774 // check extension in node
775 if (lyv_extension(schema->ext, schema->ext_size, node)) {
776 return EXIT_FAILURE;
777 }
778
779 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
780 type = &((struct lys_node_leaf *) schema)->type;
781 leaf = (struct lyd_node_leaf_list *) node;
782 if (lyv_type_extension(leaf, type, 1)) {
783 return EXIT_FAILURE;
784 }
785 }
786 }
787
788 /* remove the flag */
789 node->validity &= ~LYD_VAL_MAND;
790 }
791
792 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
793 siter = NULL;
794 while ((siter = lys_getnext(siter, schema, NULL, 0))) {
795 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
796 LY_TREE_FOR(node->child, diter) {
797 if (diter->schema == siter && (diter->validity & LYD_VAL_DUP)) {
798 /* skip key uniqueness check in case of get/get-config data */
799 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
800 if (lyv_data_dup(diter, node->child)) {
801 return 1;
802 }
803 } else {
804 /* always remove the flag */
805 diter->validity &= ~LYD_VAL_DUP;
806 }
807 /* all schema instances checked, continue with another schema node */
808 break;
809 }
810 }
811 }
812 }
813 }
814
815 if (node->validity & LYD_VAL_UNIQUE) {
816 if (options & LYD_OPT_TRUSTED) {
817 /* just remove flag */
818 node->validity &= ~LYD_VAL_UNIQUE;
819 } else {
820 /* check the unique constraint at the end (once the parsing is done) */
821 if (unres_data_add(unres, node, UNRES_UNIQ_LEAVES)) {
822 return 1;
823 }
824 }
825 }
826
827 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
828 /* since feature can be enabled/disabled, do this check despite the validity flag,
829 * - check if the type value (enum, bit, identity) is disabled via feature */
830 leaf = (struct lyd_node_leaf_list *)node;
831 switch (leaf->value_type) {
832 case LY_TYPE_BITS:
833 id = "Bit";
834 /* get the count of bits */
835 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
836 for (j = iff_size = 0; j < type->info.bits.count; j++) {
837 if (!leaf->value.bit[j]) {
838 continue;
839 }
840 idname = leaf->value.bit[j]->name;
841 iff_size = leaf->value.bit[j]->iffeature_size;
842 iff = leaf->value.bit[j]->iffeature;
843 break;
844 nextbit:
845 iff_size = 0;
846 }
847 break;
848 case LY_TYPE_ENUM:
849 id = "Enum";
850 idname = leaf->value_str;
851 iff_size = leaf->value.enm->iffeature_size;
852 iff = leaf->value.enm->iffeature;
853 break;
854 case LY_TYPE_IDENT:
855 id = "Identity";
856 idname = leaf->value_str;
857 iff_size = leaf->value.ident->iffeature_size;
858 iff = leaf->value.ident->iffeature;
859 break;
860 default:
861 iff_size = 0;
862 break;
863 }
864
865 if (iff_size) {
866 for (i = 0; i < iff_size; i++) {
867 if (!resolve_iffeature(&iff[i])) {
868 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
869 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its %d. if-feature condition.",
870 id, idname, i);
871 return 1;
872 }
873 }
874 if (leaf->value_type == LY_TYPE_BITS) {
875 goto nextbit;
876 }
877 }
878 }
879
880 /* check must conditions */
881 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
882 i = resolve_applies_must(node);
883 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
884 return 1;
885 }
886 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
887 return 1;
888 }
889 }
890
891 return 0;
892 }
893
894 int
lyv_multicases(struct lyd_node * node,struct lys_node * schemanode,struct lyd_node ** first_sibling,int autodelete,struct lyd_node * nodel)895 lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
896 int autodelete, struct lyd_node *nodel)
897 {
898 struct lys_node *sparent, *schoice, *scase, *saux;
899 struct lyd_node *next, *iter;
900 assert(node || schemanode);
901
902 if (!schemanode) {
903 schemanode = node->schema;
904 }
905
906 for (sparent = lys_parent(schemanode); sparent && (sparent->nodetype == LYS_USES); sparent = lys_parent(sparent));
907 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
908 /* node is not under any choice */
909 return 0;
910 } else if (!first_sibling || !(*first_sibling)) {
911 /* nothing to check */
912 return 0;
913 }
914
915 /* remember which case to skip in which choice */
916 if (sparent->nodetype == LYS_CHOICE) {
917 schoice = sparent;
918 scase = schemanode;
919 } else {
920 schoice = lys_parent(sparent);
921 scase = sparent;
922 }
923
924 autodelete:
925 /* remove all nodes from other cases than 'sparent' */
926 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
927 if (schemanode == iter->schema) {
928 continue;
929 }
930
931 for (sparent = lys_parent(iter->schema); sparent && (sparent->nodetype == LYS_USES); sparent = lys_parent(sparent));
932 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
933 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
934 ) {
935 if (autodelete) {
936 if (iter == nodel) {
937 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
938 return 2;
939 }
940 if (iter == *first_sibling) {
941 *first_sibling = next;
942 }
943 lyd_free(iter);
944 } else {
945 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
946 return 1;
947 }
948 }
949 }
950
951 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
952 /* go recursively in case of nested choices */
953 schoice = lys_parent(saux);
954 scase = saux;
955 goto autodelete;
956 }
957
958 return 0;
959 }
960