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