blob: d300452d26a538e0fc4b0289daf9cc1972aa1944 [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
Radek Krejci48464ed2016-03-17 15:44:09 +010052lyv_data_context(const 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 Vaskof1f278d2018-10-11 12:07:21 +020055 struct lys_node *sparent;
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 Vasko0bc2c672018-12-18 13:14:33 +010068 if (!(options & (LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
69 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
70 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
71 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
72 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
73 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
74 return 1;
75 }
Michal Vaskod0826ca2018-12-19 16:31:10 +010076 } else if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF)
77 && ((leaf->validity & LYD_VAL_LEAFREF) || (leaf->value_flags & LY_VALUE_UNRES))) {
78 /* always retry validation on unres leafrefs, if again not possible, the correct flags should
79 * be set and the leafref will be kept unresolved */
80 leaf->value_flags &= ~LY_VALUE_UNRES;
81 leaf->validity |= LYD_VAL_LEAFREF;
82
Michal Vasko0bc2c672018-12-18 13:14:33 +010083 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
84 return 1;
85 }
86 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
87 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
88 return 1;
89 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010090 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020091 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010092
Michal Vasko0bc2c672018-12-18 13:14:33 +010093 /* check all relevant when conditions */
94 if (node->when_status & LYD_WHEN) {
95 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
96 return 1;
97 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020098 }
Michal Vaskoc2a25242018-12-19 08:52:28 +010099 } else if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
100 /* just remove the flag if it was set */
101 leaf->validity &= ~LYD_VAL_LEAFREF;
Radek Krejcieab784a2015-08-27 09:56:53 +0200102 }
103
104 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100105 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100106 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
107 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200108 }
109
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100110 /* check elements order in case of RPC's input and output */
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100111 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER)) && (node->validity & LYD_VAL_MAND) && lyp_is_rpc_action(node->schema)) {
Michal Vasko15e0bab2016-02-24 13:58:21 +0100112 if ((node->prev != node) && node->prev->next) {
Michal Vaskof1f278d2018-10-11 12:07:21 +0200113 /* find schema data parent */
114 for (sparent = lys_parent(node->schema);
115 sparent && (sparent->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE));
116 sparent = lys_parent(sparent));
117 for (siter = lys_getnext(node->schema, sparent, lyd_node_module(node), 0);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100118 siter;
Michal Vaskof1f278d2018-10-11 12:07:21 +0200119 siter = lys_getnext(siter, sparent, lyd_node_module(node), 0)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100120 if (siter == node->prev->schema) {
121 /* data predecessor has the schema node after
122 * the schema node of the data node being checked */
Michal Vasko53b7da02018-02-13 15:28:42 +0100123 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
124 return 1;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100125 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100126 }
127
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100128 }
129 }
130
Michal Vasko53b7da02018-02-13 15:28:42 +0100131 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200132}
Michal Vaskocf024702015-10-08 15:01:42 +0200133
Michal Vasko185b5272018-09-13 14:26:12 +0200134/*
135 * actions (cb_data):
136 * 0 - compare all uniques
137 * n - compare n-th unique
138 */
139static int
140lyv_list_uniq_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
141{
142 struct ly_ctx *ctx;
143 struct lys_node_list *slist;
144 struct lyd_node *diter, *first, *second;
145 const char *val1, *val2;
146 char *path1, *path2, *uniq_str;
147 uint16_t idx_uniq;
148 int i, j, r, action;
149
150 assert(val1_p && val2_p);
151
152 first = *((struct lyd_node **)val1_p);
153 second = *((struct lyd_node **)val2_p);
154 action = (intptr_t)cb_data;
155
156 assert(first && (first->schema->nodetype == LYS_LIST));
157 assert(second && (second->schema == first->schema));
158
159 ctx = first->schema->module->ctx;
160
161 slist = (struct lys_node_list *)first->schema;
162
163 /* compare unique leaves */
164 if (action > 0) {
165 i = action - 1;
166 if (i < slist->unique_size) {
167 goto uniquecheck;
168 }
169 }
170 for (i = 0; i < slist->unique_size; i++) {
171uniquecheck:
172 for (j = 0; j < slist->unique[i].expr_size; j++) {
173 /* first */
174 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], first->child);
175 if (diter) {
176 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
177 } else {
178 /* use default value */
179 if (lyd_get_unique_default(slist->unique[i].expr[j], first, &val1)) {
180 return 1;
181 }
182 }
183
184 /* second */
185 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], second->child);
186 if (diter) {
187 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
188 } else {
189 /* use default value */
190 if (lyd_get_unique_default(slist->unique[i].expr[j], second, &val2)) {
191 return 1;
192 }
193 }
194
195 if (!val1 || !val2 || !ly_strequal(val1, val2, 1)) {
196 /* values differ or either one is not set */
197 break;
198 }
199 }
200 if (j && (j == slist->unique[i].expr_size)) {
201 /* all unique leafs are the same in this set, create this nice error */
202 ly_vlog_build_path(LY_VLOG_LYD, first, &path1, 0, 0);
203 ly_vlog_build_path(LY_VLOG_LYD, second, &path2, 0, 0);
204
205 /* use buffer to rebuild the unique string */
206 uniq_str = malloc(1024);
207 idx_uniq = 0;
208 for (j = 0; j < slist->unique[i].expr_size; ++j) {
209 if (j) {
210 uniq_str[idx_uniq++] = ' ';
211 }
212 r = lyd_build_relative_data_path(lys_node_module((struct lys_node *)slist), first,
213 slist->unique[i].expr[j], &uniq_str[idx_uniq]);
214 if (r == -1) {
215 goto unique_errmsg_cleanup;
216 }
217 idx_uniq += r;
218 }
219
220 LOGVAL(ctx, LYE_NOUNIQ, LY_VLOG_LYD, second, uniq_str, path1, path2);
221unique_errmsg_cleanup:
222 free(path1);
223 free(path2);
224 free(uniq_str);
225 return 1;
226 }
227
228 if (action > 0) {
229 /* done */
230 return 0;
231 }
232 }
233
234 return 0;
235}
236
Radek Krejci63b79c82016-08-10 10:09:33 +0200237int
Michal Vasko185b5272018-09-13 14:26:12 +0200238lyv_data_unique(struct lyd_node *list)
239{
240 struct lyd_node *diter;
241 struct ly_set *set;
242 uint32_t i, j, n = 0;
243 int ret = 0;
244 uint32_t hash, u, usize = 0;
245 struct hash_table **uniqtables = NULL;
246 const char *id;
247 char *path;
248 struct lys_node_list *slist;
249 struct ly_ctx *ctx = list->schema->module->ctx;
250
251 if (!(list->validity & LYD_VAL_UNIQUE)) {
252 /* validated sa part of another instance validation */
253 return 0;
254 }
255
256 slist = (struct lys_node_list *)list->schema;
257
258 /* get all list instances */
259 if (ly_vlog_build_path(LY_VLOG_LYD, list, &path, 0, 1)) {
260 return -1;
261 }
262 set = lyd_find_path(list, path);
263 free(path);
264 if (!set) {
265 return -1;
266 }
267
268 for (i = 0; i < set->number; ++i) {
269 /* remove the flag */
270 set->set.d[i]->validity &= ~LYD_VAL_UNIQUE;
271 }
272
273 if (set->number == 2) {
274 /* simple comparison */
275 if (lyv_list_uniq_equal(&set->set.d[0], &set->set.d[1], 0, (void *)0)) {
276 /* instance duplication */
277 ly_set_free(set);
278 return 1;
279 }
280 } else if (set->number > 2) {
281 /* use hashes for comparison */
282 /* first, allocate the table, the size depends on number of items in the set */
283 for (u = 31; u > 0; u--) {
284 usize = set->number << u;
285 usize = usize >> u;
286 if (usize == set->number) {
287 break;
288 }
289 }
290 if (u == 0) {
291 LOGINT(ctx);
292 ret = -1;
293 goto cleanup;
294 } else {
295 u = 32 - u;
296 usize = 1 << u;
297 }
298
299 n = slist->unique_size;
300 uniqtables = malloc(n * sizeof *uniqtables);
301 if (!uniqtables) {
302 LOGMEM(ctx);
303 ret = -1;
304 n = 0;
305 goto cleanup;
306 }
307 for (j = 0; j < n; j++) {
308 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_uniq_equal, (void *)(j + 1L), 0);
309 if (!uniqtables[j]) {
310 LOGMEM(ctx);
311 ret = -1;
312 goto cleanup;
313 }
314 }
315
316 for (u = 0; u < set->number; u++) {
317 /* loop for unique - get the hash for the instances */
318 for (j = 0; j < n; j++) {
319 id = NULL;
320 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
321 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
322 if (diter) {
323 id = ((struct lyd_node_leaf_list *)diter)->value_str;
324 } else {
325 /* use default value */
326 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
327 ret = -1;
328 goto cleanup;
329 }
330 }
331 if (!id) {
332 /* unique item not present nor has default value */
333 break;
334 }
335 hash = dict_hash_multi(hash, id, strlen(id));
336 }
337 if (!id) {
338 /* skip this list instance since its unique set is incomplete */
339 continue;
340 }
341
342 /* finish the hash value */
343 hash = dict_hash_multi(hash, NULL, 0);
344
345 /* insert into the hashtable */
346 if (lyht_insert(uniqtables[j], &set->set.d[u], hash, NULL)) {
347 ret = 1;
348 goto cleanup;
349 }
350 }
351 }
352 }
353
354cleanup:
355 ly_set_free(set);
356 for (j = 0; j < n; j++) {
357 if (!uniqtables[j]) {
358 /* failed when allocating uniquetables[j], following j are not allocated */
359 break;
360 }
361 lyht_free(uniqtables[j]);
362 }
363 free(uniqtables);
364
365 return ret;
366}
367
368static int
369lyv_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
370{
371 struct ly_ctx *ctx;
372 struct lys_node_list *slist;
373 const struct lys_node *snode = NULL;
374 struct lyd_node *diter, *first, *second;
375 const char *val1, *val2;
376 int i;
377
378 assert(val1_p && val2_p);
379
380 first = *((struct lyd_node **)val1_p);
381 second = *((struct lyd_node **)val2_p);
382
383 assert(first && (first->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
384 assert(second && (second->schema == first->schema));
385
386 ctx = first->schema->module->ctx;
387
388 switch (first->schema->nodetype) {
389 case LYS_LEAFLIST:
390 if ((first->schema->flags & LYS_CONFIG_R) && first->schema->module->version >= LYS_VERSION_1_1) {
391 /* same values are allowed for status data */
392 return 0;
393 }
394 /* compare values */
395 if (ly_strequal(((struct lyd_node_leaf_list *)first)->value_str,
396 ((struct lyd_node_leaf_list *)second)->value_str, 1)) {
397 LOGVAL(ctx, LYE_DUPLEAFLIST, LY_VLOG_LYD, second, second->schema->name,
398 ((struct lyd_node_leaf_list *)second)->value_str);
399 return 1;
400 }
401 return 0;
402 case LYS_LIST:
403 slist = (struct lys_node_list *)first->schema;
404
405 /* compare keys */
406 if (!slist->keys_size) {
407 /* status lists without keys */
408 return 0;
409 } else {
410 for (i = 0; i < slist->keys_size; i++) {
411 snode = (struct lys_node *)slist->keys[i];
412 val1 = val2 = NULL;
413 LY_TREE_FOR(first->child, diter) {
414 if (diter->schema == snode) {
415 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
416 break;
417 }
418 }
419 LY_TREE_FOR(second->child, diter) {
420 if (diter->schema == snode) {
421 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
422 break;
423 }
424 }
425 if (!ly_strequal(val1, val2, 1)) {
426 return 0;
427 }
428 }
429 }
430
431 LOGVAL(ctx, LYE_DUPLIST, LY_VLOG_LYD, second, second->schema->name);
432 return 1;
433
434 default:
435 LOGINT(ctx);
436 return 1;
437 }
438}
439
440int
441lyv_data_dup(struct lyd_node *node, struct lyd_node *start)
Radek Krejci63b79c82016-08-10 10:09:33 +0200442{
443 struct lyd_node *diter, *key;
Radek Krejci63b79c82016-08-10 10:09:33 +0200444 struct ly_set *set;
Michal Vasko185b5272018-09-13 14:26:12 +0200445 int i, ret = 0;
Michal Vasko6c810702018-03-14 16:23:21 +0100446 uint32_t hash, u, usize = 0;
Michal Vasko185b5272018-09-13 14:26:12 +0200447 struct hash_table *keystable = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200448 const char *id;
Michal Vasko53b7da02018-02-13 15:28:42 +0100449 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci63b79c82016-08-10 10:09:33 +0200450
451 /* get the first list/leaflist instance sibling */
452 if (!start) {
453 start = lyd_first_sibling(node);
454 }
455
456 /* check uniqueness of the list/leaflist instances (compare values) */
457 set = ly_set_new();
458 for (diter = start; diter; diter = diter->next) {
459 if (diter->schema != node->schema) {
460 /* check only instances of the same list/leaflist */
461 continue;
462 }
463
464 /* remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200465 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200466
467 /* store for comparison */
468 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
469 }
470
471 if (set->number == 2) {
472 /* simple comparison */
Michal Vasko185b5272018-09-13 14:26:12 +0200473 if (lyv_list_equal(&set->set.d[0], &set->set.d[1], 0, 0)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200474 /* instance duplication */
475 ly_set_free(set);
Michal Vasko53b7da02018-02-13 15:28:42 +0100476 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200477 }
478 } else if (set->number > 2) {
479 /* use hashes for comparison */
480 /* first, allocate the table, the size depends on number of items in the set */
481 for (u = 31; u > 0; u--) {
482 usize = set->number << u;
483 usize = usize >> u;
484 if (usize == set->number) {
485 break;
486 }
487 }
488 if (u == 0) {
Michal Vasko6c810702018-03-14 16:23:21 +0100489 LOGINT(ctx);
Michal Vaskod60a1a32018-05-23 16:31:22 +0200490 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200491 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200492 } else {
493 u = 32 - u;
494 usize = 1 << u;
Radek Krejci63b79c82016-08-10 10:09:33 +0200495 }
Michal Vasko419fce02018-03-21 11:55:09 +0100496 keystable = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, 0, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200497 if (!keystable) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100498 LOGMEM(ctx);
499 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200500 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200501 }
502
503 for (u = 0; u < set->number; u++) {
504 /* get the hash for the instance - keys */
505 if (node->schema->nodetype == LYS_LEAFLIST) {
506 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
507 hash = dict_hash_multi(0, id, strlen(id));
508 } else { /* LYS_LIST */
509 for (hash = i = 0, key = set->set.d[u]->child;
510 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
511 i++, key = key->next) {
512 id = ((struct lyd_node_leaf_list *)key)->value_str;
513 hash = dict_hash_multi(hash, id, strlen(id));
514 }
515 }
516 /* finish the hash value */
Michal Vasko6c810702018-03-14 16:23:21 +0100517 hash = dict_hash_multi(hash, NULL, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200518
519 /* insert into the hashtable */
David Sedlák83b1faf2018-08-09 10:52:04 +0200520 if (lyht_insert(keystable, &set->set.d[u], hash, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100521 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200522 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200523 }
524 }
525 }
526
Michal Vasko185b5272018-09-13 14:26:12 +0200527cleanup:
Radek Krejci63b79c82016-08-10 10:09:33 +0200528 ly_set_free(set);
Michal Vasko6c810702018-03-14 16:23:21 +0100529 lyht_free(keystable);
Radek Krejci63b79c82016-08-10 10:09:33 +0200530
531 return ret;
532}
533
Michal Vasko91ff4592017-05-24 15:41:49 +0200534static struct lys_type *
535find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
536{
537 struct lys_type *type, *prev_type, *tmp_type;
538 int found;
539
540 /* go through typedefs */
541 for (type = par_type; type->der->type.der; type = &type->der->type);
542
543 if (type->base == base_type) {
544 /* we have the result */
545 return type;
Michal Vasko101658e2018-06-05 15:05:54 +0200546 } else if ((type->base == LY_TYPE_LEAFREF) && !(type->value_flags & LY_VALUE_UNRES)) {
Michal Vasko70bf8e52018-03-26 11:32:33 +0200547 /* go through the leafref */
548 assert(type->info.lref.target);
549 return find_orig_type(&((struct lys_node_leaf *)type->info.lref.target)->type, base_type);
Michal Vasko91ff4592017-05-24 15:41:49 +0200550 } else if (type->base == LY_TYPE_UNION) {
551 /* go through all the union types */
552 prev_type = NULL;
553 found = 0;
554 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
555 tmp_type = find_orig_type(prev_type, base_type);
556 if (tmp_type) {
557 return tmp_type;
558 }
559 found = 0;
560 }
561 }
562
563 /* not found */
564 return NULL;
565}
566
PavolVican556559e2017-12-12 13:39:36 +0100567static int
568lyv_extension(struct lys_ext_instance **ext, uint8_t size, struct lyd_node *node)
569{
570 uint i;
571
572 for (i = 0; i < size; ++i) {
573 if ((ext[i]->flags & LYEXT_OPT_VALID) && ext[i]->def->plugin->valid_data) {
574 if (ext[i]->def->plugin->valid_data(ext[i], node)) {
575 return EXIT_FAILURE;
576 }
577 }
578 }
579 return 0;
580}
581
582static int
583lyv_type_extension(struct lyd_node_leaf_list *leaf, struct lys_type *type, int first_type)
584{
585 struct lyd_node *node = (struct lyd_node *)leaf;
586 unsigned int i;
587
588 switch (type->base) {
589 case LY_TYPE_ENUM:
590 if (first_type && lyv_extension(leaf->value.enm->ext, leaf->value.enm->ext_size, node)) {
591 return EXIT_FAILURE;
592 }
593 break;
594 case LY_TYPE_STRING:
595 if (type->info.str.length &&
596 lyv_extension(type->info.str.length->ext, type->info.str.length->ext_size, node)) {
597 return EXIT_FAILURE;
598 }
599 for(i = 0; i < type->info.str.pat_count; ++i) {
600 if (lyv_extension(type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size, node)) {
601 return EXIT_FAILURE;
602 }
603 }
604 break;
605 case LY_TYPE_DEC64:
606 if (type->info.dec64.range &&
607 lyv_extension(type->info.dec64.range->ext, type->info.dec64.range->ext_size, node)) {
608 return EXIT_FAILURE;
609 }
610 break;
611 case LY_TYPE_INT8:
612 case LY_TYPE_INT16:
613 case LY_TYPE_INT32:
614 case LY_TYPE_INT64:
615 case LY_TYPE_UINT8:
616 case LY_TYPE_UINT16:
617 case LY_TYPE_UINT32:
618 case LY_TYPE_UINT64:
619 if (type->info.num.range &&
620 lyv_extension(type->info.num.range->ext, type->info.num.range->ext_size, node)) {
621 return EXIT_FAILURE;
622 }
623 break;
624 case LY_TYPE_BITS:
625 if (first_type) {
626 /* get the count of bits */
627 type = find_orig_type(&((struct lys_node_leaf *) leaf->schema)->type, LY_TYPE_BITS);
628 for (i = 0; i < type->info.bits.count; ++i) {
629 if (!leaf->value.bit[i]) {
630 continue;
631 }
632 if (lyv_extension(leaf->value.bit[i]->ext, leaf->value.bit[i]->ext_size, node)) {
633 return EXIT_FAILURE;
634 }
635 }
636 }
637 break;
638 case LY_TYPE_UNION:
639 for (i = 0; i < type->info.uni.count; ++i) {
640 if (type->info.uni.types[i].base == leaf->value_type) {
641 break;
642 }
643 }
644 if (i < type->info.uni.count &&
645 lyv_type_extension(leaf, &type->info.uni.types[i], first_type)) {
646 return EXIT_FAILURE;
647 }
648 break;
649 default:
650 break;
651 }
652
653
654 if (lyv_extension(type->ext, type->ext_size, node)) {
655 return EXIT_FAILURE;
656 }
657
658 while (type->der->type.der) {
659 type = &type->der->type;
Michal Vasko1bdfd432018-03-09 09:30:19 +0100660 if ((type->parent->flags & LYS_VALID_EXT)) {
661 if (lyv_type_extension(leaf, type, 0) || lyv_extension(type->parent->ext, type->parent->ext_size, node)) {
PavolVican556559e2017-12-12 13:39:36 +0100662 return EXIT_FAILURE;
663 }
664 }
665 }
666
667 return EXIT_SUCCESS;
668}
669
Radek Krejcieab784a2015-08-27 09:56:53 +0200670int
Radek Krejci48464ed2016-03-17 15:44:09 +0100671lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200672{
PavolVican832f5432018-02-21 00:54:45 +0100673 const struct lys_node *schema, *siter, *parent;
Radek Krejcid788a522016-07-25 14:57:38 +0200674 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100675 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100676 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200677 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200678 struct lyd_node_leaf_list *leaf;
Radek Krejcidce5f972017-09-12 15:47:49 +0200679 unsigned int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200680 uint8_t iff_size;
681 struct lys_iffeature *iff;
682 const char *id, *idname;
Michal Vasko53b7da02018-02-13 15:28:42 +0100683 struct ly_ctx *ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200684
685 assert(node);
686 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100687 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200688
689 schema = node->schema; /* shortcut */
Michal Vasko53b7da02018-02-13 15:28:42 +0100690 ctx = schema->module->ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200691
Michal Vasko1e1be2f2019-04-16 15:52:35 +0200692 if (!(node->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION))) {
693 for (diter = node->parent; diter; diter = diter->parent) {
694 if (diter->schema->nodetype & (LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
695 break;
696 }
697 }
698 if (!diter && (options & (LYD_OPT_NOTIF | LYD_OPT_RPC))) {
699 /* validating parent of a nested notification/action, skip most checks */
700 options |= LYD_OPT_TRUSTED;
701 }
702 }
703
Michal Vasko091dd842017-02-08 14:07:32 +0100704 if (node->validity & LYD_VAL_MAND) {
705 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
706 /* check presence and correct order of all keys in case of list */
707 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
708 if (lyv_keys(node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100709 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200710 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200711 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200712
Michal Vasko091dd842017-02-08 14:07:32 +0100713 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
714 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100715
Michal Vasko091dd842017-02-08 14:07:32 +0100716 /* find duplicity */
717 start = lyd_first_sibling(node);
718 for (diter = start; diter; diter = diter->next) {
719 if (diter->schema == schema && diter != node) {
PavolVican832f5432018-02-21 00:54:45 +0100720 parent = lys_parent(schema);
Michal Vasko53b7da02018-02-13 15:28:42 +0100721 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
PavolVican832f5432018-02-21 00:54:45 +0100722 parent ? (parent->nodetype == LYS_EXT) ? ((struct lys_ext_instance *)parent)->arg_value : parent->name : "data tree");
Michal Vasko53b7da02018-02-13 15:28:42 +0100723 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100724 }
725 }
Michal Vasko091dd842017-02-08 14:07:32 +0100726 }
727
728 if (options & LYD_OPT_OBSOLETE) {
729 /* status - of the node's schema node itself and all its parents that
730 * cannot have their own instance (like a choice statement) */
731 siter = node->schema;
732 do {
733 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100734 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
735 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100736 }
Michal Vasko091dd842017-02-08 14:07:32 +0100737 siter = lys_parent(siter);
738 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
739
740 /* status of the identity value */
741 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
742 if (options & LYD_OPT_OBSOLETE) {
743 /* check that we are not instantiating obsolete type */
744 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
745 while (tpdf) {
746 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100747 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
748 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100749 }
750 tpdf = tpdf->type.der;
751 }
752 }
753 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
754 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
755 if (lyp_check_status(schema->flags, schema->module, schema->name,
756 ident->flags, ident->module, ident->name, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100757 LOGPATH(ctx, LY_VLOG_LYD, node);
758 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100759 }
760 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100761 }
762 }
763 }
764
PavolVican556559e2017-12-12 13:39:36 +0100765 /* check validation function for extension */
Michal Vasko1bdfd432018-03-09 09:30:19 +0100766 if (schema->flags & LYS_VALID_EXT) {
PavolVican556559e2017-12-12 13:39:36 +0100767 // check extension in node
768 if (lyv_extension(schema->ext, schema->ext_size, node)) {
769 return EXIT_FAILURE;
770 }
771
772 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
773 type = &((struct lys_node_leaf *) schema)->type;
774 leaf = (struct lyd_node_leaf_list *) node;
775 if (lyv_type_extension(leaf, type, 1)) {
776 return EXIT_FAILURE;
777 }
778 }
PavolVican556559e2017-12-12 13:39:36 +0100779 }
780
Radek Krejcid788a522016-07-25 14:57:38 +0200781 /* remove the flag */
782 node->validity &= ~LYD_VAL_MAND;
783 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100784
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200785 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
Michal Vasko0c59e822018-09-13 09:32:02 +0200786 siter = NULL;
787 while ((siter = lys_getnext(siter, schema, NULL, 0))) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200788 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
789 LY_TREE_FOR(node->child, diter) {
Michal Vasko185b5272018-09-13 14:26:12 +0200790 if (diter->schema == siter && (diter->validity & LYD_VAL_DUP)) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200791 /* skip key uniqueness check in case of get/get-config data */
792 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Michal Vasko185b5272018-09-13 14:26:12 +0200793 if (lyv_data_dup(diter, node->child)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100794 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200795 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200796 } else {
797 /* always remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200798 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200799 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200800 /* all schema instances checked, continue with another schema node */
801 break;
Radek Krejci63b79c82016-08-10 10:09:33 +0200802 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100803 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100804 }
805 }
Radek Krejcid788a522016-07-25 14:57:38 +0200806 }
807
Michal Vasko185b5272018-09-13 14:26:12 +0200808 if (node->validity & LYD_VAL_UNIQUE) {
Michal Vasko02340262018-11-30 09:11:52 +0100809 if (options & LYD_OPT_TRUSTED) {
810 /* just remove flag */
811 node->validity &= ~LYD_VAL_UNIQUE;
812 } else {
813 /* check the unique constraint at the end (once the parsing is done) */
814 if (unres_data_add(unres, node, UNRES_UNIQ_LEAVES)) {
815 return 1;
816 }
Michal Vasko185b5272018-09-13 14:26:12 +0200817 }
818 }
819
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200820 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
821 /* since feature can be enabled/disabled, do this check despite the validity flag,
822 * - check if the type value (enum, bit, identity) is disabled via feature */
823 leaf = (struct lyd_node_leaf_list *)node;
824 switch (leaf->value_type) {
825 case LY_TYPE_BITS:
826 id = "Bit";
827 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200828 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200829 for (j = iff_size = 0; j < type->info.bits.count; j++) {
830 if (!leaf->value.bit[j]) {
831 continue;
832 }
833 idname = leaf->value.bit[j]->name;
834 iff_size = leaf->value.bit[j]->iffeature_size;
835 iff = leaf->value.bit[j]->iffeature;
836 break;
837nextbit:
838 iff_size = 0;
839 }
840 break;
841 case LY_TYPE_ENUM:
842 id = "Enum";
843 idname = leaf->value_str;
844 iff_size = leaf->value.enm->iffeature_size;
845 iff = leaf->value.enm->iffeature;
846 break;
847 case LY_TYPE_IDENT:
848 id = "Identity";
849 idname = leaf->value_str;
850 iff_size = leaf->value.ident->iffeature_size;
851 iff = leaf->value.ident->iffeature;
852 break;
853 default:
854 iff_size = 0;
855 break;
856 }
857
858 if (iff_size) {
859 for (i = 0; i < iff_size; i++) {
860 if (!resolve_iffeature(&iff[i])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100861 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
862 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its if-feature condition.",
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200863 id, idname);
Michal Vasko53b7da02018-02-13 15:28:42 +0100864 return 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200865 }
866 }
867 if (leaf->value_type == LY_TYPE_BITS) {
868 goto nextbit;
869 }
870 }
871 }
872
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100873 /* check must conditions */
874 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 +0000875 i = resolve_applies_must(node);
Michal Vasko53b7da02018-02-13 15:28:42 +0100876 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
877 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000878 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100879 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
880 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000881 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200882 }
883
Michal Vasko53b7da02018-02-13 15:28:42 +0100884 return 0;
885}
886
887int
888lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
889 int autodelete, struct lyd_node *nodel)
890{
891 struct lys_node *sparent, *schoice, *scase, *saux;
892 struct lyd_node *next, *iter;
893 assert(node || schemanode);
894
895 if (!schemanode) {
896 schemanode = node->schema;
897 }
898
899 sparent = lys_parent(schemanode);
900 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
901 /* node is not under any choice */
902 return 0;
903 } else if (!first_sibling || !(*first_sibling)) {
904 /* nothing to check */
905 return 0;
906 }
907
908 /* remember which case to skip in which choice */
909 if (sparent->nodetype == LYS_CHOICE) {
910 schoice = sparent;
911 scase = schemanode;
912 } else {
913 schoice = lys_parent(sparent);
914 scase = sparent;
915 }
916
917autodelete:
918 /* remove all nodes from other cases than 'sparent' */
919 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
920 if (schemanode == iter->schema) {
921 continue;
922 }
923
924 sparent = lys_parent(iter->schema);
925 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
926 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
927 ) {
928 if (autodelete) {
929 if (iter == nodel) {
930 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
931 return 2;
932 }
933 if (iter == *first_sibling) {
934 *first_sibling = next;
935 }
936 lyd_free(iter);
937 } else {
Michal Vaskoaf8ec362018-03-28 09:08:09 +0200938 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
Michal Vasko53b7da02018-02-13 15:28:42 +0100939 return 1;
940 }
941 }
942 }
943
944 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
945 /* go recursively in case of nested choices */
946 schoice = lys_parent(saux);
947 scase = saux;
948 goto autodelete;
949 }
950
951 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200952}