blob: 37925d58fd39fbea99582a2d416f796b8f111aed [file] [log] [blame]
Radek Krejcib1c12512015-08-11 11:22:04 +02001/**
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 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * 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
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejcib1c12512015-08-11 11:22:04 +020013 */
14
Radek Krejcieab784a2015-08-27 09:56:53 +020015#include <assert.h>
Radek Krejcib1c12512015-08-11 11:22:04 +020016#include <stdlib.h>
Michal Vaskocf024702015-10-08 15:01:42 +020017#include <string.h>
Radek Krejcib1c12512015-08-11 11:22:04 +020018
Radek Krejcieab784a2015-08-27 09:56:53 +020019#include "common.h"
Michal Vaskocf024702015-10-08 15:01:42 +020020#include "validation.h"
Radek Krejcib1c12512015-08-11 11:22:04 +020021#include "libyang.h"
Michal Vaskocf024702015-10-08 15:01:42 +020022#include "xpath.h"
Radek Krejcicf509982015-12-15 09:22:44 +010023#include "parser.h"
Michal Vaskocf024702015-10-08 15:01:42 +020024#include "resolve.h"
25#include "tree_internal.h"
Michal Vaskofc5744d2015-10-22 12:09:34 +020026#include "xml_internal.h"
Radek Krejcib1c12512015-08-11 11:22:04 +020027
Radek Krejcib45b3082016-09-09 16:08:51 +020028static int
Radek Krejci48464ed2016-03-17 15:44:09 +010029lyv_keys(const struct lyd_node *list)
Radek Krejcib1c12512015-08-11 11:22:04 +020030{
Radek Krejci702deb82016-03-09 12:37:57 +010031 struct lyd_node *child;
32 struct lys_node_list *schema = (struct lys_node_list *)list->schema; /* shortcut */
Radek Krejcib1c12512015-08-11 11:22:04 +020033 int i;
34
Radek Krejci702deb82016-03-09 12:37:57 +010035 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 */
Michal Vasko53b7da02018-02-13 15:28:42 +010038 LOGVAL(schema->module->ctx, LYE_MISSELEM, LY_VLOG_LYD, list, schema->keys[i]->name, schema->name);
Radek Krejci702deb82016-03-09 12:37:57 +010039 for ( ; child; child = child->next) {
40 if (child->schema == (struct lys_node *)schema->keys[i]) {
Michal Vasko53b7da02018-02-13 15:28:42 +010041 LOGVAL(schema->module->ctx, LYE_SPEC, LY_VLOG_LYD, child, "Invalid position of the key element.");
Radek Krejci702deb82016-03-09 12:37:57 +010042 break;
43 }
Radek Krejcib1c12512015-08-11 11:22:04 +020044 }
Michal Vasko53b7da02018-02-13 15:28:42 +010045 return 1;
Radek Krejcib1c12512015-08-11 11:22:04 +020046 }
47 }
Michal Vasko53b7da02018-02-13 15:28:42 +010048 return 0;
Radek Krejcib1c12512015-08-11 11:22:04 +020049}
Radek Krejcieab784a2015-08-27 09:56:53 +020050
51int
Michal Vasko1f394492020-01-30 09:37:04 +010052lyv_data_context(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +020053{
Radek Krejci6baaa9a2016-02-23 16:07:12 +010054 const struct lys_node *siter = NULL;
Michal Vaskoe48303c2019-12-03 14:03:54 +010055 struct lys_node *sparent, *op;
Radek Krejcib1f318b2016-08-22 16:18:37 +020056 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
Michal Vasko53b7da02018-02-13 15:28:42 +010057 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci4a49bdf2016-01-12 17:17:01 +010058
Michal Vaskocf024702015-10-08 15:01:42 +020059 assert(node);
Radek Krejci03b71f72016-03-16 11:10:09 +010060 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +020061
62 /* check if the node instance is enabled by if-feature */
Michal Vaskocf024702015-10-08 15:01:42 +020063 if (lys_is_disabled(node->schema, 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010064 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
65 return 1;
Michal Vaskocf024702015-10-08 15:01:42 +020066 }
67
Michal Vaskoe48303c2019-12-03 14:03:54 +010068 /* find (nested) operation node */
Michal Vasko1640f922020-03-04 08:18:05 +010069 for (op = node->schema; op && !(op->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT)); op = lys_parent(op));
Michal Vaskoe48303c2019-12-03 14:03:54 +010070
71 if (!(options & (LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
Michal Vaskof54f97f2019-12-13 11:44:02 +010072 && (!(options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) || op)) {
Michal Vasko0bc2c672018-12-18 13:14:33 +010073 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 }
Michal Vasko1544f482020-01-03 14:16:55 +010080 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) {
Michal Vaskod0826ca2018-12-19 16:31:10 +010081 /* 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;
Michal Vaskod0826ca2018-12-19 16:31:10 +010084
Michal Vasko0bc2c672018-12-18 13:14:33 +010085 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 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010092 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020093 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010094
Michal Vasko0bc2c672018-12-18 13:14:33 +010095 /* check all relevant when conditions */
96 if (node->when_status & LYD_WHEN) {
Michal Vasko1f394492020-01-30 09:37:04 +010097 if (options & LYD_OPT_TRUSTED) {
98 node->when_status |= LYD_WHEN_TRUE;
99 } else if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko0bc2c672018-12-18 13:14:33 +0100100 return 1;
101 }
Michal Vasko0d182ba2015-10-09 09:29:14 +0200102 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200103 }
104
105 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100106 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100107 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
108 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200109 }
110
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100111 /* check elements order in case of RPC's input and output */
Michal Vaskoe48303c2019-12-03 14:03:54 +0100112 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER)) && (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY))
113 && (node->validity & LYD_VAL_MAND) && op) {
Michal Vasko15e0bab2016-02-24 13:58:21 +0100114 if ((node->prev != node) && node->prev->next) {
Michal Vaskof1f278d2018-10-11 12:07:21 +0200115 /* find schema data parent */
116 for (sparent = lys_parent(node->schema);
117 sparent && (sparent->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE));
118 sparent = lys_parent(sparent));
119 for (siter = lys_getnext(node->schema, sparent, lyd_node_module(node), 0);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100120 siter;
Michal Vaskof1f278d2018-10-11 12:07:21 +0200121 siter = lys_getnext(siter, sparent, lyd_node_module(node), 0)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100122 if (siter == node->prev->schema) {
123 /* data predecessor has the schema node after
124 * the schema node of the data node being checked */
Michal Vasko53b7da02018-02-13 15:28:42 +0100125 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
126 return 1;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100127 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100128 }
129
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100130 }
131 }
132
Michal Vasko53b7da02018-02-13 15:28:42 +0100133 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200134}
Michal Vaskocf024702015-10-08 15:01:42 +0200135
Michal Vasko185b5272018-09-13 14:26:12 +0200136/*
137 * actions (cb_data):
138 * 0 - compare all uniques
139 * n - compare n-th unique
140 */
141static int
142lyv_list_uniq_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
143{
144 struct ly_ctx *ctx;
145 struct lys_node_list *slist;
146 struct lyd_node *diter, *first, *second;
147 const char *val1, *val2;
148 char *path1, *path2, *uniq_str;
149 uint16_t idx_uniq;
150 int i, j, r, action;
151
152 assert(val1_p && val2_p);
153
154 first = *((struct lyd_node **)val1_p);
155 second = *((struct lyd_node **)val2_p);
156 action = (intptr_t)cb_data;
157
158 assert(first && (first->schema->nodetype == LYS_LIST));
159 assert(second && (second->schema == first->schema));
160
161 ctx = first->schema->module->ctx;
162
163 slist = (struct lys_node_list *)first->schema;
164
165 /* compare unique leaves */
166 if (action > 0) {
167 i = action - 1;
168 if (i < slist->unique_size) {
169 goto uniquecheck;
170 }
171 }
172 for (i = 0; i < slist->unique_size; i++) {
173uniquecheck:
174 for (j = 0; j < slist->unique[i].expr_size; j++) {
175 /* first */
176 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], first->child);
177 if (diter) {
178 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
179 } else {
180 /* use default value */
181 if (lyd_get_unique_default(slist->unique[i].expr[j], first, &val1)) {
182 return 1;
183 }
184 }
185
186 /* second */
187 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], second->child);
188 if (diter) {
189 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
190 } else {
191 /* use default value */
192 if (lyd_get_unique_default(slist->unique[i].expr[j], second, &val2)) {
193 return 1;
194 }
195 }
196
197 if (!val1 || !val2 || !ly_strequal(val1, val2, 1)) {
198 /* values differ or either one is not set */
199 break;
200 }
201 }
202 if (j && (j == slist->unique[i].expr_size)) {
203 /* all unique leafs are the same in this set, create this nice error */
204 ly_vlog_build_path(LY_VLOG_LYD, first, &path1, 0, 0);
205 ly_vlog_build_path(LY_VLOG_LYD, second, &path2, 0, 0);
206
207 /* use buffer to rebuild the unique string */
208 uniq_str = malloc(1024);
209 idx_uniq = 0;
210 for (j = 0; j < slist->unique[i].expr_size; ++j) {
211 if (j) {
212 uniq_str[idx_uniq++] = ' ';
213 }
214 r = lyd_build_relative_data_path(lys_node_module((struct lys_node *)slist), first,
215 slist->unique[i].expr[j], &uniq_str[idx_uniq]);
216 if (r == -1) {
217 goto unique_errmsg_cleanup;
218 }
219 idx_uniq += r;
220 }
221
222 LOGVAL(ctx, LYE_NOUNIQ, LY_VLOG_LYD, second, uniq_str, path1, path2);
223unique_errmsg_cleanup:
224 free(path1);
225 free(path2);
226 free(uniq_str);
227 return 1;
228 }
229
230 if (action > 0) {
231 /* done */
232 return 0;
233 }
234 }
235
236 return 0;
237}
238
Radek Krejci63b79c82016-08-10 10:09:33 +0200239int
Michal Vasko185b5272018-09-13 14:26:12 +0200240lyv_data_unique(struct lyd_node *list)
241{
242 struct lyd_node *diter;
243 struct ly_set *set;
244 uint32_t i, j, n = 0;
245 int ret = 0;
246 uint32_t hash, u, usize = 0;
247 struct hash_table **uniqtables = NULL;
248 const char *id;
249 char *path;
250 struct lys_node_list *slist;
251 struct ly_ctx *ctx = list->schema->module->ctx;
252
253 if (!(list->validity & LYD_VAL_UNIQUE)) {
254 /* validated sa part of another instance validation */
255 return 0;
256 }
257
258 slist = (struct lys_node_list *)list->schema;
259
260 /* get all list instances */
261 if (ly_vlog_build_path(LY_VLOG_LYD, list, &path, 0, 1)) {
262 return -1;
263 }
264 set = lyd_find_path(list, path);
265 free(path);
266 if (!set) {
267 return -1;
268 }
269
270 for (i = 0; i < set->number; ++i) {
271 /* remove the flag */
272 set->set.d[i]->validity &= ~LYD_VAL_UNIQUE;
273 }
274
275 if (set->number == 2) {
276 /* simple comparison */
277 if (lyv_list_uniq_equal(&set->set.d[0], &set->set.d[1], 0, (void *)0)) {
278 /* instance duplication */
279 ly_set_free(set);
280 return 1;
281 }
282 } else if (set->number > 2) {
283 /* use hashes for comparison */
284 /* first, allocate the table, the size depends on number of items in the set */
285 for (u = 31; u > 0; u--) {
286 usize = set->number << u;
287 usize = usize >> u;
288 if (usize == set->number) {
289 break;
290 }
291 }
292 if (u == 0) {
293 LOGINT(ctx);
294 ret = -1;
295 goto cleanup;
296 } else {
297 u = 32 - u;
298 usize = 1 << u;
299 }
300
301 n = slist->unique_size;
302 uniqtables = malloc(n * sizeof *uniqtables);
303 if (!uniqtables) {
304 LOGMEM(ctx);
305 ret = -1;
306 n = 0;
307 goto cleanup;
308 }
309 for (j = 0; j < n; j++) {
310 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_uniq_equal, (void *)(j + 1L), 0);
311 if (!uniqtables[j]) {
312 LOGMEM(ctx);
313 ret = -1;
314 goto cleanup;
315 }
316 }
317
318 for (u = 0; u < set->number; u++) {
319 /* loop for unique - get the hash for the instances */
320 for (j = 0; j < n; j++) {
321 id = NULL;
322 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
323 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
324 if (diter) {
325 id = ((struct lyd_node_leaf_list *)diter)->value_str;
326 } else {
327 /* use default value */
328 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
329 ret = -1;
330 goto cleanup;
331 }
332 }
333 if (!id) {
334 /* unique item not present nor has default value */
335 break;
336 }
337 hash = dict_hash_multi(hash, id, strlen(id));
338 }
339 if (!id) {
340 /* skip this list instance since its unique set is incomplete */
341 continue;
342 }
343
344 /* finish the hash value */
345 hash = dict_hash_multi(hash, NULL, 0);
346
347 /* insert into the hashtable */
348 if (lyht_insert(uniqtables[j], &set->set.d[u], hash, NULL)) {
349 ret = 1;
350 goto cleanup;
351 }
352 }
353 }
354 }
355
356cleanup:
357 ly_set_free(set);
358 for (j = 0; j < n; j++) {
359 if (!uniqtables[j]) {
360 /* failed when allocating uniquetables[j], following j are not allocated */
361 break;
362 }
363 lyht_free(uniqtables[j]);
364 }
365 free(uniqtables);
366
367 return ret;
368}
369
370static int
371lyv_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
372{
373 struct ly_ctx *ctx;
374 struct lys_node_list *slist;
375 const struct lys_node *snode = NULL;
376 struct lyd_node *diter, *first, *second;
377 const char *val1, *val2;
378 int i;
379
380 assert(val1_p && val2_p);
381
382 first = *((struct lyd_node **)val1_p);
383 second = *((struct lyd_node **)val2_p);
384
385 assert(first && (first->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
386 assert(second && (second->schema == first->schema));
387
388 ctx = first->schema->module->ctx;
389
390 switch (first->schema->nodetype) {
391 case LYS_LEAFLIST:
392 if ((first->schema->flags & LYS_CONFIG_R) && first->schema->module->version >= LYS_VERSION_1_1) {
393 /* same values are allowed for status data */
394 return 0;
395 }
396 /* compare values */
397 if (ly_strequal(((struct lyd_node_leaf_list *)first)->value_str,
398 ((struct lyd_node_leaf_list *)second)->value_str, 1)) {
399 LOGVAL(ctx, LYE_DUPLEAFLIST, LY_VLOG_LYD, second, second->schema->name,
400 ((struct lyd_node_leaf_list *)second)->value_str);
401 return 1;
402 }
403 return 0;
404 case LYS_LIST:
405 slist = (struct lys_node_list *)first->schema;
406
407 /* compare keys */
408 if (!slist->keys_size) {
409 /* status lists without keys */
410 return 0;
411 } else {
412 for (i = 0; i < slist->keys_size; i++) {
413 snode = (struct lys_node *)slist->keys[i];
414 val1 = val2 = NULL;
415 LY_TREE_FOR(first->child, diter) {
416 if (diter->schema == snode) {
417 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
418 break;
419 }
420 }
421 LY_TREE_FOR(second->child, diter) {
422 if (diter->schema == snode) {
423 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
424 break;
425 }
426 }
427 if (!ly_strequal(val1, val2, 1)) {
428 return 0;
429 }
430 }
431 }
432
433 LOGVAL(ctx, LYE_DUPLIST, LY_VLOG_LYD, second, second->schema->name);
434 return 1;
435
436 default:
437 LOGINT(ctx);
438 return 1;
439 }
440}
441
442int
443lyv_data_dup(struct lyd_node *node, struct lyd_node *start)
Radek Krejci63b79c82016-08-10 10:09:33 +0200444{
445 struct lyd_node *diter, *key;
Radek Krejci63b79c82016-08-10 10:09:33 +0200446 struct ly_set *set;
Michal Vasko185b5272018-09-13 14:26:12 +0200447 int i, ret = 0;
Michal Vasko6c810702018-03-14 16:23:21 +0100448 uint32_t hash, u, usize = 0;
Michal Vasko185b5272018-09-13 14:26:12 +0200449 struct hash_table *keystable = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200450 const char *id;
Michal Vasko53b7da02018-02-13 15:28:42 +0100451 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci63b79c82016-08-10 10:09:33 +0200452
453 /* get the first list/leaflist instance sibling */
454 if (!start) {
455 start = lyd_first_sibling(node);
456 }
457
458 /* check uniqueness of the list/leaflist instances (compare values) */
459 set = ly_set_new();
460 for (diter = start; diter; diter = diter->next) {
461 if (diter->schema != node->schema) {
462 /* check only instances of the same list/leaflist */
463 continue;
464 }
465
466 /* remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200467 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200468
469 /* store for comparison */
470 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
471 }
472
473 if (set->number == 2) {
474 /* simple comparison */
Michal Vasko185b5272018-09-13 14:26:12 +0200475 if (lyv_list_equal(&set->set.d[0], &set->set.d[1], 0, 0)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200476 /* instance duplication */
477 ly_set_free(set);
Michal Vasko53b7da02018-02-13 15:28:42 +0100478 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200479 }
480 } else if (set->number > 2) {
481 /* use hashes for comparison */
482 /* first, allocate the table, the size depends on number of items in the set */
483 for (u = 31; u > 0; u--) {
484 usize = set->number << u;
485 usize = usize >> u;
486 if (usize == set->number) {
487 break;
488 }
489 }
490 if (u == 0) {
Michal Vasko6c810702018-03-14 16:23:21 +0100491 LOGINT(ctx);
Michal Vaskod60a1a32018-05-23 16:31:22 +0200492 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200493 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200494 } else {
495 u = 32 - u;
496 usize = 1 << u;
Radek Krejci63b79c82016-08-10 10:09:33 +0200497 }
Michal Vasko419fce02018-03-21 11:55:09 +0100498 keystable = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, 0, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200499 if (!keystable) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100500 LOGMEM(ctx);
501 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200502 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200503 }
504
505 for (u = 0; u < set->number; u++) {
506 /* get the hash for the instance - keys */
507 if (node->schema->nodetype == LYS_LEAFLIST) {
508 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
509 hash = dict_hash_multi(0, id, strlen(id));
510 } else { /* LYS_LIST */
511 for (hash = i = 0, key = set->set.d[u]->child;
512 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
513 i++, key = key->next) {
514 id = ((struct lyd_node_leaf_list *)key)->value_str;
515 hash = dict_hash_multi(hash, id, strlen(id));
516 }
517 }
518 /* finish the hash value */
Michal Vasko6c810702018-03-14 16:23:21 +0100519 hash = dict_hash_multi(hash, NULL, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200520
521 /* insert into the hashtable */
David Sedlák83b1faf2018-08-09 10:52:04 +0200522 if (lyht_insert(keystable, &set->set.d[u], hash, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100523 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200524 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200525 }
526 }
527 }
528
Michal Vasko185b5272018-09-13 14:26:12 +0200529cleanup:
Radek Krejci63b79c82016-08-10 10:09:33 +0200530 ly_set_free(set);
Michal Vasko6c810702018-03-14 16:23:21 +0100531 lyht_free(keystable);
Radek Krejci63b79c82016-08-10 10:09:33 +0200532
533 return ret;
534}
535
Michal Vasko91ff4592017-05-24 15:41:49 +0200536static struct lys_type *
537find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
538{
539 struct lys_type *type, *prev_type, *tmp_type;
540 int found;
541
542 /* go through typedefs */
543 for (type = par_type; type->der->type.der; type = &type->der->type);
544
545 if (type->base == base_type) {
546 /* we have the result */
547 return type;
Michal Vasko101658e2018-06-05 15:05:54 +0200548 } else if ((type->base == LY_TYPE_LEAFREF) && !(type->value_flags & LY_VALUE_UNRES)) {
Michal Vasko70bf8e52018-03-26 11:32:33 +0200549 /* go through the leafref */
550 assert(type->info.lref.target);
551 return find_orig_type(&((struct lys_node_leaf *)type->info.lref.target)->type, base_type);
Michal Vasko91ff4592017-05-24 15:41:49 +0200552 } else if (type->base == LY_TYPE_UNION) {
553 /* go through all the union types */
554 prev_type = NULL;
555 found = 0;
556 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
557 tmp_type = find_orig_type(prev_type, base_type);
558 if (tmp_type) {
559 return tmp_type;
560 }
561 found = 0;
562 }
563 }
564
565 /* not found */
566 return NULL;
567}
568
PavolVican556559e2017-12-12 13:39:36 +0100569static int
570lyv_extension(struct lys_ext_instance **ext, uint8_t size, struct lyd_node *node)
571{
572 uint i;
573
574 for (i = 0; i < size; ++i) {
575 if ((ext[i]->flags & LYEXT_OPT_VALID) && ext[i]->def->plugin->valid_data) {
576 if (ext[i]->def->plugin->valid_data(ext[i], node)) {
577 return EXIT_FAILURE;
578 }
579 }
580 }
581 return 0;
582}
583
584static int
585lyv_type_extension(struct lyd_node_leaf_list *leaf, struct lys_type *type, int first_type)
586{
587 struct lyd_node *node = (struct lyd_node *)leaf;
588 unsigned int i;
589
590 switch (type->base) {
591 case LY_TYPE_ENUM:
592 if (first_type && lyv_extension(leaf->value.enm->ext, leaf->value.enm->ext_size, node)) {
593 return EXIT_FAILURE;
594 }
595 break;
596 case LY_TYPE_STRING:
597 if (type->info.str.length &&
598 lyv_extension(type->info.str.length->ext, type->info.str.length->ext_size, node)) {
599 return EXIT_FAILURE;
600 }
601 for(i = 0; i < type->info.str.pat_count; ++i) {
602 if (lyv_extension(type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size, node)) {
603 return EXIT_FAILURE;
604 }
605 }
606 break;
607 case LY_TYPE_DEC64:
608 if (type->info.dec64.range &&
609 lyv_extension(type->info.dec64.range->ext, type->info.dec64.range->ext_size, node)) {
610 return EXIT_FAILURE;
611 }
612 break;
613 case LY_TYPE_INT8:
614 case LY_TYPE_INT16:
615 case LY_TYPE_INT32:
616 case LY_TYPE_INT64:
617 case LY_TYPE_UINT8:
618 case LY_TYPE_UINT16:
619 case LY_TYPE_UINT32:
620 case LY_TYPE_UINT64:
621 if (type->info.num.range &&
622 lyv_extension(type->info.num.range->ext, type->info.num.range->ext_size, node)) {
623 return EXIT_FAILURE;
624 }
625 break;
626 case LY_TYPE_BITS:
627 if (first_type) {
628 /* get the count of bits */
629 type = find_orig_type(&((struct lys_node_leaf *) leaf->schema)->type, LY_TYPE_BITS);
630 for (i = 0; i < type->info.bits.count; ++i) {
631 if (!leaf->value.bit[i]) {
632 continue;
633 }
634 if (lyv_extension(leaf->value.bit[i]->ext, leaf->value.bit[i]->ext_size, node)) {
635 return EXIT_FAILURE;
636 }
637 }
638 }
639 break;
640 case LY_TYPE_UNION:
641 for (i = 0; i < type->info.uni.count; ++i) {
642 if (type->info.uni.types[i].base == leaf->value_type) {
643 break;
644 }
645 }
646 if (i < type->info.uni.count &&
647 lyv_type_extension(leaf, &type->info.uni.types[i], first_type)) {
648 return EXIT_FAILURE;
649 }
650 break;
651 default:
652 break;
653 }
654
655
656 if (lyv_extension(type->ext, type->ext_size, node)) {
657 return EXIT_FAILURE;
658 }
659
660 while (type->der->type.der) {
661 type = &type->der->type;
Michal Vasko1bdfd432018-03-09 09:30:19 +0100662 if ((type->parent->flags & LYS_VALID_EXT)) {
663 if (lyv_type_extension(leaf, type, 0) || lyv_extension(type->parent->ext, type->parent->ext_size, node)) {
PavolVican556559e2017-12-12 13:39:36 +0100664 return EXIT_FAILURE;
665 }
666 }
667 }
668
669 return EXIT_SUCCESS;
670}
671
Radek Krejcieab784a2015-08-27 09:56:53 +0200672int
Radek Krejci48464ed2016-03-17 15:44:09 +0100673lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200674{
PavolVican832f5432018-02-21 00:54:45 +0100675 const struct lys_node *schema, *siter, *parent;
Radek Krejcid788a522016-07-25 14:57:38 +0200676 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100677 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100678 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200679 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200680 struct lyd_node_leaf_list *leaf;
Radek Krejcidce5f972017-09-12 15:47:49 +0200681 unsigned int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200682 uint8_t iff_size;
683 struct lys_iffeature *iff;
684 const char *id, *idname;
Michal Vasko53b7da02018-02-13 15:28:42 +0100685 struct ly_ctx *ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200686
687 assert(node);
688 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100689 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200690
691 schema = node->schema; /* shortcut */
Michal Vasko53b7da02018-02-13 15:28:42 +0100692 ctx = schema->module->ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200693
Michal Vasko1e1be2f2019-04-16 15:52:35 +0200694 if (!(node->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
695 for (diter = node->parent; diter; diter = diter->parent) {
696 if (diter->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
697 break;
698 }
699 }
Michal Vaskof54f97f2019-12-13 11:44:02 +0100700 if (!diter && (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF))) {
Michal Vasko1e1be2f2019-04-16 15:52:35 +0200701 /* validating parent of a nested notification/action, skip most checks */
702 options |= LYD_OPT_TRUSTED;
703 }
704 }
705
Michal Vasko091dd842017-02-08 14:07:32 +0100706 if (node->validity & LYD_VAL_MAND) {
707 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
708 /* check presence and correct order of all keys in case of list */
709 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
710 if (lyv_keys(node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100711 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200712 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200713 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200714
Michal Vasko091dd842017-02-08 14:07:32 +0100715 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
716 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100717
Michal Vasko091dd842017-02-08 14:07:32 +0100718 /* find duplicity */
719 start = lyd_first_sibling(node);
720 for (diter = start; diter; diter = diter->next) {
721 if (diter->schema == schema && diter != node) {
PavolVican832f5432018-02-21 00:54:45 +0100722 parent = lys_parent(schema);
Michal Vasko53b7da02018-02-13 15:28:42 +0100723 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
PavolVican832f5432018-02-21 00:54:45 +0100724 parent ? (parent->nodetype == LYS_EXT) ? ((struct lys_ext_instance *)parent)->arg_value : parent->name : "data tree");
Michal Vasko53b7da02018-02-13 15:28:42 +0100725 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100726 }
727 }
Michal Vasko091dd842017-02-08 14:07:32 +0100728 }
729
730 if (options & LYD_OPT_OBSOLETE) {
731 /* status - of the node's schema node itself and all its parents that
732 * cannot have their own instance (like a choice statement) */
733 siter = node->schema;
734 do {
735 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100736 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
737 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100738 }
Michal Vasko091dd842017-02-08 14:07:32 +0100739 siter = lys_parent(siter);
740 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
741
742 /* status of the identity value */
743 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
744 if (options & LYD_OPT_OBSOLETE) {
745 /* check that we are not instantiating obsolete type */
746 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
747 while (tpdf) {
748 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100749 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
750 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100751 }
752 tpdf = tpdf->type.der;
753 }
754 }
755 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
756 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
757 if (lyp_check_status(schema->flags, schema->module, schema->name,
758 ident->flags, ident->module, ident->name, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100759 LOGPATH(ctx, LY_VLOG_LYD, node);
760 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100761 }
762 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100763 }
764 }
765 }
766
PavolVican556559e2017-12-12 13:39:36 +0100767 /* check validation function for extension */
Michal Vasko1bdfd432018-03-09 09:30:19 +0100768 if (schema->flags & LYS_VALID_EXT) {
PavolVican556559e2017-12-12 13:39:36 +0100769 // check extension in node
770 if (lyv_extension(schema->ext, schema->ext_size, node)) {
771 return EXIT_FAILURE;
772 }
773
774 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
775 type = &((struct lys_node_leaf *) schema)->type;
776 leaf = (struct lyd_node_leaf_list *) node;
777 if (lyv_type_extension(leaf, type, 1)) {
778 return EXIT_FAILURE;
779 }
780 }
PavolVican556559e2017-12-12 13:39:36 +0100781 }
782
Radek Krejcid788a522016-07-25 14:57:38 +0200783 /* remove the flag */
784 node->validity &= ~LYD_VAL_MAND;
785 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100786
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200787 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
Michal Vasko0c59e822018-09-13 09:32:02 +0200788 siter = NULL;
789 while ((siter = lys_getnext(siter, schema, NULL, 0))) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200790 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
791 LY_TREE_FOR(node->child, diter) {
Michal Vasko185b5272018-09-13 14:26:12 +0200792 if (diter->schema == siter && (diter->validity & LYD_VAL_DUP)) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200793 /* skip key uniqueness check in case of get/get-config data */
794 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Michal Vasko185b5272018-09-13 14:26:12 +0200795 if (lyv_data_dup(diter, node->child)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100796 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200797 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200798 } else {
799 /* always remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200800 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200801 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200802 /* all schema instances checked, continue with another schema node */
803 break;
Radek Krejci63b79c82016-08-10 10:09:33 +0200804 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100805 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100806 }
807 }
Radek Krejcid788a522016-07-25 14:57:38 +0200808 }
809
Michal Vasko185b5272018-09-13 14:26:12 +0200810 if (node->validity & LYD_VAL_UNIQUE) {
Michal Vasko02340262018-11-30 09:11:52 +0100811 if (options & LYD_OPT_TRUSTED) {
812 /* just remove flag */
813 node->validity &= ~LYD_VAL_UNIQUE;
814 } else {
815 /* check the unique constraint at the end (once the parsing is done) */
816 if (unres_data_add(unres, node, UNRES_UNIQ_LEAVES)) {
817 return 1;
818 }
Michal Vasko185b5272018-09-13 14:26:12 +0200819 }
820 }
821
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200822 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
823 /* since feature can be enabled/disabled, do this check despite the validity flag,
824 * - check if the type value (enum, bit, identity) is disabled via feature */
825 leaf = (struct lyd_node_leaf_list *)node;
826 switch (leaf->value_type) {
827 case LY_TYPE_BITS:
828 id = "Bit";
829 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200830 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200831 for (j = iff_size = 0; j < type->info.bits.count; j++) {
832 if (!leaf->value.bit[j]) {
833 continue;
834 }
835 idname = leaf->value.bit[j]->name;
836 iff_size = leaf->value.bit[j]->iffeature_size;
837 iff = leaf->value.bit[j]->iffeature;
838 break;
839nextbit:
840 iff_size = 0;
841 }
842 break;
843 case LY_TYPE_ENUM:
844 id = "Enum";
845 idname = leaf->value_str;
846 iff_size = leaf->value.enm->iffeature_size;
847 iff = leaf->value.enm->iffeature;
848 break;
849 case LY_TYPE_IDENT:
850 id = "Identity";
851 idname = leaf->value_str;
852 iff_size = leaf->value.ident->iffeature_size;
853 iff = leaf->value.ident->iffeature;
854 break;
855 default:
856 iff_size = 0;
857 break;
858 }
859
860 if (iff_size) {
861 for (i = 0; i < iff_size; i++) {
862 if (!resolve_iffeature(&iff[i])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100863 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
Michal Vasko83cea222020-09-11 15:50:43 +0200864 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its %d. if-feature condition.",
865 id, idname, i);
Michal Vasko53b7da02018-02-13 15:28:42 +0100866 return 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200867 }
868 }
869 if (leaf->value_type == LY_TYPE_BITS) {
870 goto nextbit;
871 }
872 }
873 }
874
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100875 /* check must conditions */
876 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Michal Vasko4b5b6252016-10-11 12:18:00 +0000877 i = resolve_applies_must(node);
Michal Vasko53b7da02018-02-13 15:28:42 +0100878 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
879 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000880 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100881 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
882 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000883 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200884 }
885
Michal Vasko53b7da02018-02-13 15:28:42 +0100886 return 0;
887}
888
889int
890lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
891 int autodelete, struct lyd_node *nodel)
892{
893 struct lys_node *sparent, *schoice, *scase, *saux;
894 struct lyd_node *next, *iter;
895 assert(node || schemanode);
896
897 if (!schemanode) {
898 schemanode = node->schema;
899 }
900
Michal Vaskoa1abd3c2019-04-23 15:58:26 +0200901 for (sparent = lys_parent(schemanode); sparent && (sparent->nodetype == LYS_USES); sparent = lys_parent(sparent));
Michal Vasko53b7da02018-02-13 15:28:42 +0100902 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
903 /* node is not under any choice */
904 return 0;
905 } else if (!first_sibling || !(*first_sibling)) {
906 /* nothing to check */
907 return 0;
908 }
909
910 /* remember which case to skip in which choice */
911 if (sparent->nodetype == LYS_CHOICE) {
912 schoice = sparent;
913 scase = schemanode;
914 } else {
915 schoice = lys_parent(sparent);
916 scase = sparent;
917 }
918
919autodelete:
920 /* remove all nodes from other cases than 'sparent' */
921 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
922 if (schemanode == iter->schema) {
923 continue;
924 }
925
Michal Vaskoa1abd3c2019-04-23 15:58:26 +0200926 for (sparent = lys_parent(iter->schema); sparent && (sparent->nodetype == LYS_USES); sparent = lys_parent(sparent));
Michal Vasko53b7da02018-02-13 15:28:42 +0100927 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
928 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
929 ) {
930 if (autodelete) {
931 if (iter == nodel) {
932 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
933 return 2;
934 }
935 if (iter == *first_sibling) {
936 *first_sibling = next;
937 }
938 lyd_free(iter);
939 } else {
Michal Vaskoaf8ec362018-03-28 09:08:09 +0200940 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
Michal Vasko53b7da02018-02-13 15:28:42 +0100941 return 1;
942 }
943 }
944 }
945
946 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
947 /* go recursively in case of nested choices */
948 schoice = lys_parent(saux);
949 scase = saux;
950 goto autodelete;
951 }
952
953 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200954}