blob: 189e35f900ee0e1481b70173d27fa0e9e88f845f [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
Radek Krejcib1f318b2016-08-22 16:18:37 +020068 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +010069 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
70 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
71 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
72 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010073 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +010074 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +010075 } else if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) && (leaf->validity & LYD_VAL_LEAFREF)) {
76 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010077 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +010078 }
79 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
80 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010081 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +010082 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020083 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010084 }
85
Michal Vaskocf024702015-10-08 15:01:42 +020086 /* check all relevant when conditions */
Michal Vasko85a4fb62018-06-14 09:24:16 +020087 if (!(options & (LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
Michal Vaskoebf7df22017-03-28 16:08:07 +020088 && (node->when_status & LYD_WHEN)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +010089 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010090 return 1;
Michal Vasko0d182ba2015-10-09 09:29:14 +020091 }
Radek Krejcieab784a2015-08-27 09:56:53 +020092 }
93
94 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +010095 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010096 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
97 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +020098 }
99
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100100 /* check elements order in case of RPC's input and output */
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100101 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 +0100102 if ((node->prev != node) && node->prev->next) {
Michal Vaskof1f278d2018-10-11 12:07:21 +0200103 /* find schema data parent */
104 for (sparent = lys_parent(node->schema);
105 sparent && (sparent->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE));
106 sparent = lys_parent(sparent));
107 for (siter = lys_getnext(node->schema, sparent, lyd_node_module(node), 0);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100108 siter;
Michal Vaskof1f278d2018-10-11 12:07:21 +0200109 siter = lys_getnext(siter, sparent, lyd_node_module(node), 0)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100110 if (siter == node->prev->schema) {
111 /* data predecessor has the schema node after
112 * the schema node of the data node being checked */
Michal Vasko53b7da02018-02-13 15:28:42 +0100113 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
114 return 1;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100115 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100116 }
117
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100118 }
119 }
120
Michal Vasko53b7da02018-02-13 15:28:42 +0100121 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200122}
Michal Vaskocf024702015-10-08 15:01:42 +0200123
Michal Vasko185b5272018-09-13 14:26:12 +0200124/*
125 * actions (cb_data):
126 * 0 - compare all uniques
127 * n - compare n-th unique
128 */
129static int
130lyv_list_uniq_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *cb_data)
131{
132 struct ly_ctx *ctx;
133 struct lys_node_list *slist;
134 struct lyd_node *diter, *first, *second;
135 const char *val1, *val2;
136 char *path1, *path2, *uniq_str;
137 uint16_t idx_uniq;
138 int i, j, r, action;
139
140 assert(val1_p && val2_p);
141
142 first = *((struct lyd_node **)val1_p);
143 second = *((struct lyd_node **)val2_p);
144 action = (intptr_t)cb_data;
145
146 assert(first && (first->schema->nodetype == LYS_LIST));
147 assert(second && (second->schema == first->schema));
148
149 ctx = first->schema->module->ctx;
150
151 slist = (struct lys_node_list *)first->schema;
152
153 /* compare unique leaves */
154 if (action > 0) {
155 i = action - 1;
156 if (i < slist->unique_size) {
157 goto uniquecheck;
158 }
159 }
160 for (i = 0; i < slist->unique_size; i++) {
161uniquecheck:
162 for (j = 0; j < slist->unique[i].expr_size; j++) {
163 /* first */
164 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], first->child);
165 if (diter) {
166 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
167 } else {
168 /* use default value */
169 if (lyd_get_unique_default(slist->unique[i].expr[j], first, &val1)) {
170 return 1;
171 }
172 }
173
174 /* second */
175 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], second->child);
176 if (diter) {
177 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
178 } else {
179 /* use default value */
180 if (lyd_get_unique_default(slist->unique[i].expr[j], second, &val2)) {
181 return 1;
182 }
183 }
184
185 if (!val1 || !val2 || !ly_strequal(val1, val2, 1)) {
186 /* values differ or either one is not set */
187 break;
188 }
189 }
190 if (j && (j == slist->unique[i].expr_size)) {
191 /* all unique leafs are the same in this set, create this nice error */
192 ly_vlog_build_path(LY_VLOG_LYD, first, &path1, 0, 0);
193 ly_vlog_build_path(LY_VLOG_LYD, second, &path2, 0, 0);
194
195 /* use buffer to rebuild the unique string */
196 uniq_str = malloc(1024);
197 idx_uniq = 0;
198 for (j = 0; j < slist->unique[i].expr_size; ++j) {
199 if (j) {
200 uniq_str[idx_uniq++] = ' ';
201 }
202 r = lyd_build_relative_data_path(lys_node_module((struct lys_node *)slist), first,
203 slist->unique[i].expr[j], &uniq_str[idx_uniq]);
204 if (r == -1) {
205 goto unique_errmsg_cleanup;
206 }
207 idx_uniq += r;
208 }
209
210 LOGVAL(ctx, LYE_NOUNIQ, LY_VLOG_LYD, second, uniq_str, path1, path2);
211unique_errmsg_cleanup:
212 free(path1);
213 free(path2);
214 free(uniq_str);
215 return 1;
216 }
217
218 if (action > 0) {
219 /* done */
220 return 0;
221 }
222 }
223
224 return 0;
225}
226
Radek Krejci63b79c82016-08-10 10:09:33 +0200227int
Michal Vasko185b5272018-09-13 14:26:12 +0200228lyv_data_unique(struct lyd_node *list)
229{
230 struct lyd_node *diter;
231 struct ly_set *set;
232 uint32_t i, j, n = 0;
233 int ret = 0;
234 uint32_t hash, u, usize = 0;
235 struct hash_table **uniqtables = NULL;
236 const char *id;
237 char *path;
238 struct lys_node_list *slist;
239 struct ly_ctx *ctx = list->schema->module->ctx;
240
241 if (!(list->validity & LYD_VAL_UNIQUE)) {
242 /* validated sa part of another instance validation */
243 return 0;
244 }
245
246 slist = (struct lys_node_list *)list->schema;
247
248 /* get all list instances */
249 if (ly_vlog_build_path(LY_VLOG_LYD, list, &path, 0, 1)) {
250 return -1;
251 }
252 set = lyd_find_path(list, path);
253 free(path);
254 if (!set) {
255 return -1;
256 }
257
258 for (i = 0; i < set->number; ++i) {
259 /* remove the flag */
260 set->set.d[i]->validity &= ~LYD_VAL_UNIQUE;
261 }
262
263 if (set->number == 2) {
264 /* simple comparison */
265 if (lyv_list_uniq_equal(&set->set.d[0], &set->set.d[1], 0, (void *)0)) {
266 /* instance duplication */
267 ly_set_free(set);
268 return 1;
269 }
270 } else if (set->number > 2) {
271 /* use hashes for comparison */
272 /* first, allocate the table, the size depends on number of items in the set */
273 for (u = 31; u > 0; u--) {
274 usize = set->number << u;
275 usize = usize >> u;
276 if (usize == set->number) {
277 break;
278 }
279 }
280 if (u == 0) {
281 LOGINT(ctx);
282 ret = -1;
283 goto cleanup;
284 } else {
285 u = 32 - u;
286 usize = 1 << u;
287 }
288
289 n = slist->unique_size;
290 uniqtables = malloc(n * sizeof *uniqtables);
291 if (!uniqtables) {
292 LOGMEM(ctx);
293 ret = -1;
294 n = 0;
295 goto cleanup;
296 }
297 for (j = 0; j < n; j++) {
298 uniqtables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_uniq_equal, (void *)(j + 1L), 0);
299 if (!uniqtables[j]) {
300 LOGMEM(ctx);
301 ret = -1;
302 goto cleanup;
303 }
304 }
305
306 for (u = 0; u < set->number; u++) {
307 /* loop for unique - get the hash for the instances */
308 for (j = 0; j < n; j++) {
309 id = NULL;
310 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
311 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
312 if (diter) {
313 id = ((struct lyd_node_leaf_list *)diter)->value_str;
314 } else {
315 /* use default value */
316 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
317 ret = -1;
318 goto cleanup;
319 }
320 }
321 if (!id) {
322 /* unique item not present nor has default value */
323 break;
324 }
325 hash = dict_hash_multi(hash, id, strlen(id));
326 }
327 if (!id) {
328 /* skip this list instance since its unique set is incomplete */
329 continue;
330 }
331
332 /* finish the hash value */
333 hash = dict_hash_multi(hash, NULL, 0);
334
335 /* insert into the hashtable */
336 if (lyht_insert(uniqtables[j], &set->set.d[u], hash, NULL)) {
337 ret = 1;
338 goto cleanup;
339 }
340 }
341 }
342 }
343
344cleanup:
345 ly_set_free(set);
346 for (j = 0; j < n; j++) {
347 if (!uniqtables[j]) {
348 /* failed when allocating uniquetables[j], following j are not allocated */
349 break;
350 }
351 lyht_free(uniqtables[j]);
352 }
353 free(uniqtables);
354
355 return ret;
356}
357
358static int
359lyv_list_equal(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
360{
361 struct ly_ctx *ctx;
362 struct lys_node_list *slist;
363 const struct lys_node *snode = NULL;
364 struct lyd_node *diter, *first, *second;
365 const char *val1, *val2;
366 int i;
367
368 assert(val1_p && val2_p);
369
370 first = *((struct lyd_node **)val1_p);
371 second = *((struct lyd_node **)val2_p);
372
373 assert(first && (first->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
374 assert(second && (second->schema == first->schema));
375
376 ctx = first->schema->module->ctx;
377
378 switch (first->schema->nodetype) {
379 case LYS_LEAFLIST:
380 if ((first->schema->flags & LYS_CONFIG_R) && first->schema->module->version >= LYS_VERSION_1_1) {
381 /* same values are allowed for status data */
382 return 0;
383 }
384 /* compare values */
385 if (ly_strequal(((struct lyd_node_leaf_list *)first)->value_str,
386 ((struct lyd_node_leaf_list *)second)->value_str, 1)) {
387 LOGVAL(ctx, LYE_DUPLEAFLIST, LY_VLOG_LYD, second, second->schema->name,
388 ((struct lyd_node_leaf_list *)second)->value_str);
389 return 1;
390 }
391 return 0;
392 case LYS_LIST:
393 slist = (struct lys_node_list *)first->schema;
394
395 /* compare keys */
396 if (!slist->keys_size) {
397 /* status lists without keys */
398 return 0;
399 } else {
400 for (i = 0; i < slist->keys_size; i++) {
401 snode = (struct lys_node *)slist->keys[i];
402 val1 = val2 = NULL;
403 LY_TREE_FOR(first->child, diter) {
404 if (diter->schema == snode) {
405 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
406 break;
407 }
408 }
409 LY_TREE_FOR(second->child, diter) {
410 if (diter->schema == snode) {
411 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
412 break;
413 }
414 }
415 if (!ly_strequal(val1, val2, 1)) {
416 return 0;
417 }
418 }
419 }
420
421 LOGVAL(ctx, LYE_DUPLIST, LY_VLOG_LYD, second, second->schema->name);
422 return 1;
423
424 default:
425 LOGINT(ctx);
426 return 1;
427 }
428}
429
430int
431lyv_data_dup(struct lyd_node *node, struct lyd_node *start)
Radek Krejci63b79c82016-08-10 10:09:33 +0200432{
433 struct lyd_node *diter, *key;
Radek Krejci63b79c82016-08-10 10:09:33 +0200434 struct ly_set *set;
Michal Vasko185b5272018-09-13 14:26:12 +0200435 int i, ret = 0;
Michal Vasko6c810702018-03-14 16:23:21 +0100436 uint32_t hash, u, usize = 0;
Michal Vasko185b5272018-09-13 14:26:12 +0200437 struct hash_table *keystable = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200438 const char *id;
Michal Vasko53b7da02018-02-13 15:28:42 +0100439 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci63b79c82016-08-10 10:09:33 +0200440
441 /* get the first list/leaflist instance sibling */
442 if (!start) {
443 start = lyd_first_sibling(node);
444 }
445
446 /* check uniqueness of the list/leaflist instances (compare values) */
447 set = ly_set_new();
448 for (diter = start; diter; diter = diter->next) {
449 if (diter->schema != node->schema) {
450 /* check only instances of the same list/leaflist */
451 continue;
452 }
453
454 /* remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200455 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200456
457 /* store for comparison */
458 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
459 }
460
461 if (set->number == 2) {
462 /* simple comparison */
Michal Vasko185b5272018-09-13 14:26:12 +0200463 if (lyv_list_equal(&set->set.d[0], &set->set.d[1], 0, 0)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200464 /* instance duplication */
465 ly_set_free(set);
Michal Vasko53b7da02018-02-13 15:28:42 +0100466 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200467 }
468 } else if (set->number > 2) {
469 /* use hashes for comparison */
470 /* first, allocate the table, the size depends on number of items in the set */
471 for (u = 31; u > 0; u--) {
472 usize = set->number << u;
473 usize = usize >> u;
474 if (usize == set->number) {
475 break;
476 }
477 }
478 if (u == 0) {
Michal Vasko6c810702018-03-14 16:23:21 +0100479 LOGINT(ctx);
Michal Vaskod60a1a32018-05-23 16:31:22 +0200480 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200481 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200482 } else {
483 u = 32 - u;
484 usize = 1 << u;
Radek Krejci63b79c82016-08-10 10:09:33 +0200485 }
Michal Vasko419fce02018-03-21 11:55:09 +0100486 keystable = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, 0, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200487 if (!keystable) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100488 LOGMEM(ctx);
489 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200490 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200491 }
492
493 for (u = 0; u < set->number; u++) {
494 /* get the hash for the instance - keys */
495 if (node->schema->nodetype == LYS_LEAFLIST) {
496 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
497 hash = dict_hash_multi(0, id, strlen(id));
498 } else { /* LYS_LIST */
499 for (hash = i = 0, key = set->set.d[u]->child;
500 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
501 i++, key = key->next) {
502 id = ((struct lyd_node_leaf_list *)key)->value_str;
503 hash = dict_hash_multi(hash, id, strlen(id));
504 }
505 }
506 /* finish the hash value */
Michal Vasko6c810702018-03-14 16:23:21 +0100507 hash = dict_hash_multi(hash, NULL, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200508
509 /* insert into the hashtable */
David Sedlák83b1faf2018-08-09 10:52:04 +0200510 if (lyht_insert(keystable, &set->set.d[u], hash, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100511 ret = 1;
Michal Vasko185b5272018-09-13 14:26:12 +0200512 goto cleanup;
Radek Krejci63b79c82016-08-10 10:09:33 +0200513 }
514 }
515 }
516
Michal Vasko185b5272018-09-13 14:26:12 +0200517cleanup:
Radek Krejci63b79c82016-08-10 10:09:33 +0200518 ly_set_free(set);
Michal Vasko6c810702018-03-14 16:23:21 +0100519 lyht_free(keystable);
Radek Krejci63b79c82016-08-10 10:09:33 +0200520
521 return ret;
522}
523
Michal Vasko91ff4592017-05-24 15:41:49 +0200524static struct lys_type *
525find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
526{
527 struct lys_type *type, *prev_type, *tmp_type;
528 int found;
529
530 /* go through typedefs */
531 for (type = par_type; type->der->type.der; type = &type->der->type);
532
533 if (type->base == base_type) {
534 /* we have the result */
535 return type;
Michal Vasko101658e2018-06-05 15:05:54 +0200536 } else if ((type->base == LY_TYPE_LEAFREF) && !(type->value_flags & LY_VALUE_UNRES)) {
Michal Vasko70bf8e52018-03-26 11:32:33 +0200537 /* go through the leafref */
538 assert(type->info.lref.target);
539 return find_orig_type(&((struct lys_node_leaf *)type->info.lref.target)->type, base_type);
Michal Vasko91ff4592017-05-24 15:41:49 +0200540 } else if (type->base == LY_TYPE_UNION) {
541 /* go through all the union types */
542 prev_type = NULL;
543 found = 0;
544 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
545 tmp_type = find_orig_type(prev_type, base_type);
546 if (tmp_type) {
547 return tmp_type;
548 }
549 found = 0;
550 }
551 }
552
553 /* not found */
554 return NULL;
555}
556
PavolVican556559e2017-12-12 13:39:36 +0100557static int
558lyv_extension(struct lys_ext_instance **ext, uint8_t size, struct lyd_node *node)
559{
560 uint i;
561
562 for (i = 0; i < size; ++i) {
563 if ((ext[i]->flags & LYEXT_OPT_VALID) && ext[i]->def->plugin->valid_data) {
564 if (ext[i]->def->plugin->valid_data(ext[i], node)) {
565 return EXIT_FAILURE;
566 }
567 }
568 }
569 return 0;
570}
571
572static int
573lyv_type_extension(struct lyd_node_leaf_list *leaf, struct lys_type *type, int first_type)
574{
575 struct lyd_node *node = (struct lyd_node *)leaf;
576 unsigned int i;
577
578 switch (type->base) {
579 case LY_TYPE_ENUM:
580 if (first_type && lyv_extension(leaf->value.enm->ext, leaf->value.enm->ext_size, node)) {
581 return EXIT_FAILURE;
582 }
583 break;
584 case LY_TYPE_STRING:
585 if (type->info.str.length &&
586 lyv_extension(type->info.str.length->ext, type->info.str.length->ext_size, node)) {
587 return EXIT_FAILURE;
588 }
589 for(i = 0; i < type->info.str.pat_count; ++i) {
590 if (lyv_extension(type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size, node)) {
591 return EXIT_FAILURE;
592 }
593 }
594 break;
595 case LY_TYPE_DEC64:
596 if (type->info.dec64.range &&
597 lyv_extension(type->info.dec64.range->ext, type->info.dec64.range->ext_size, node)) {
598 return EXIT_FAILURE;
599 }
600 break;
601 case LY_TYPE_INT8:
602 case LY_TYPE_INT16:
603 case LY_TYPE_INT32:
604 case LY_TYPE_INT64:
605 case LY_TYPE_UINT8:
606 case LY_TYPE_UINT16:
607 case LY_TYPE_UINT32:
608 case LY_TYPE_UINT64:
609 if (type->info.num.range &&
610 lyv_extension(type->info.num.range->ext, type->info.num.range->ext_size, node)) {
611 return EXIT_FAILURE;
612 }
613 break;
614 case LY_TYPE_BITS:
615 if (first_type) {
616 /* get the count of bits */
617 type = find_orig_type(&((struct lys_node_leaf *) leaf->schema)->type, LY_TYPE_BITS);
618 for (i = 0; i < type->info.bits.count; ++i) {
619 if (!leaf->value.bit[i]) {
620 continue;
621 }
622 if (lyv_extension(leaf->value.bit[i]->ext, leaf->value.bit[i]->ext_size, node)) {
623 return EXIT_FAILURE;
624 }
625 }
626 }
627 break;
628 case LY_TYPE_UNION:
629 for (i = 0; i < type->info.uni.count; ++i) {
630 if (type->info.uni.types[i].base == leaf->value_type) {
631 break;
632 }
633 }
634 if (i < type->info.uni.count &&
635 lyv_type_extension(leaf, &type->info.uni.types[i], first_type)) {
636 return EXIT_FAILURE;
637 }
638 break;
639 default:
640 break;
641 }
642
643
644 if (lyv_extension(type->ext, type->ext_size, node)) {
645 return EXIT_FAILURE;
646 }
647
648 while (type->der->type.der) {
649 type = &type->der->type;
Michal Vasko1bdfd432018-03-09 09:30:19 +0100650 if ((type->parent->flags & LYS_VALID_EXT)) {
651 if (lyv_type_extension(leaf, type, 0) || lyv_extension(type->parent->ext, type->parent->ext_size, node)) {
PavolVican556559e2017-12-12 13:39:36 +0100652 return EXIT_FAILURE;
653 }
654 }
655 }
656
657 return EXIT_SUCCESS;
658}
659
Radek Krejcieab784a2015-08-27 09:56:53 +0200660int
Radek Krejci48464ed2016-03-17 15:44:09 +0100661lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200662{
PavolVican832f5432018-02-21 00:54:45 +0100663 const struct lys_node *schema, *siter, *parent;
Radek Krejcid788a522016-07-25 14:57:38 +0200664 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100665 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100666 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200667 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200668 struct lyd_node_leaf_list *leaf;
Radek Krejcidce5f972017-09-12 15:47:49 +0200669 unsigned int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200670 uint8_t iff_size;
671 struct lys_iffeature *iff;
672 const char *id, *idname;
Michal Vasko53b7da02018-02-13 15:28:42 +0100673 struct ly_ctx *ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200674
675 assert(node);
676 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100677 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200678
679 schema = node->schema; /* shortcut */
Michal Vasko53b7da02018-02-13 15:28:42 +0100680 ctx = schema->module->ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200681
Michal Vasko091dd842017-02-08 14:07:32 +0100682 if (node->validity & LYD_VAL_MAND) {
683 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
684 /* check presence and correct order of all keys in case of list */
685 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
686 if (lyv_keys(node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100687 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200688 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200689 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200690
Michal Vasko091dd842017-02-08 14:07:32 +0100691 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
692 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100693
Michal Vasko091dd842017-02-08 14:07:32 +0100694 /* find duplicity */
695 start = lyd_first_sibling(node);
696 for (diter = start; diter; diter = diter->next) {
697 if (diter->schema == schema && diter != node) {
PavolVican832f5432018-02-21 00:54:45 +0100698 parent = lys_parent(schema);
Michal Vasko53b7da02018-02-13 15:28:42 +0100699 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
PavolVican832f5432018-02-21 00:54:45 +0100700 parent ? (parent->nodetype == LYS_EXT) ? ((struct lys_ext_instance *)parent)->arg_value : parent->name : "data tree");
Michal Vasko53b7da02018-02-13 15:28:42 +0100701 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100702 }
703 }
Michal Vasko091dd842017-02-08 14:07:32 +0100704 }
705
706 if (options & LYD_OPT_OBSOLETE) {
707 /* status - of the node's schema node itself and all its parents that
708 * cannot have their own instance (like a choice statement) */
709 siter = node->schema;
710 do {
711 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100712 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
713 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100714 }
Michal Vasko091dd842017-02-08 14:07:32 +0100715 siter = lys_parent(siter);
716 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
717
718 /* status of the identity value */
719 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
720 if (options & LYD_OPT_OBSOLETE) {
721 /* check that we are not instantiating obsolete type */
722 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
723 while (tpdf) {
724 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100725 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
726 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100727 }
728 tpdf = tpdf->type.der;
729 }
730 }
731 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
732 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
733 if (lyp_check_status(schema->flags, schema->module, schema->name,
734 ident->flags, ident->module, ident->name, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100735 LOGPATH(ctx, LY_VLOG_LYD, node);
736 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100737 }
738 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100739 }
740 }
741 }
742
PavolVican556559e2017-12-12 13:39:36 +0100743 /* check validation function for extension */
Michal Vasko1bdfd432018-03-09 09:30:19 +0100744 if (schema->flags & LYS_VALID_EXT) {
PavolVican556559e2017-12-12 13:39:36 +0100745 // check extension in node
746 if (lyv_extension(schema->ext, schema->ext_size, node)) {
747 return EXIT_FAILURE;
748 }
749
750 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
751 type = &((struct lys_node_leaf *) schema)->type;
752 leaf = (struct lyd_node_leaf_list *) node;
753 if (lyv_type_extension(leaf, type, 1)) {
754 return EXIT_FAILURE;
755 }
756 }
PavolVican556559e2017-12-12 13:39:36 +0100757 }
758
Radek Krejcid788a522016-07-25 14:57:38 +0200759 /* remove the flag */
760 node->validity &= ~LYD_VAL_MAND;
761 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100762
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200763 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
Michal Vasko0c59e822018-09-13 09:32:02 +0200764 siter = NULL;
765 while ((siter = lys_getnext(siter, schema, NULL, 0))) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200766 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
767 LY_TREE_FOR(node->child, diter) {
Michal Vasko185b5272018-09-13 14:26:12 +0200768 if (diter->schema == siter && (diter->validity & LYD_VAL_DUP)) {
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200769 /* skip key uniqueness check in case of get/get-config data */
770 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Michal Vasko185b5272018-09-13 14:26:12 +0200771 if (lyv_data_dup(diter, node->child)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100772 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200773 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200774 } else {
775 /* always remove the flag */
Michal Vasko185b5272018-09-13 14:26:12 +0200776 diter->validity &= ~LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +0200777 }
Michal Vasko4d1e7b02018-08-08 16:28:02 +0200778 /* all schema instances checked, continue with another schema node */
779 break;
Radek Krejci63b79c82016-08-10 10:09:33 +0200780 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100781 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100782 }
783 }
Radek Krejcid788a522016-07-25 14:57:38 +0200784 }
785
Michal Vasko185b5272018-09-13 14:26:12 +0200786 if (node->validity & LYD_VAL_UNIQUE) {
Michal Vasko02340262018-11-30 09:11:52 +0100787 if (options & LYD_OPT_TRUSTED) {
788 /* just remove flag */
789 node->validity &= ~LYD_VAL_UNIQUE;
790 } else {
791 /* check the unique constraint at the end (once the parsing is done) */
792 if (unres_data_add(unres, node, UNRES_UNIQ_LEAVES)) {
793 return 1;
794 }
Michal Vasko185b5272018-09-13 14:26:12 +0200795 }
796 }
797
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200798 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
799 /* since feature can be enabled/disabled, do this check despite the validity flag,
800 * - check if the type value (enum, bit, identity) is disabled via feature */
801 leaf = (struct lyd_node_leaf_list *)node;
802 switch (leaf->value_type) {
803 case LY_TYPE_BITS:
804 id = "Bit";
805 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200806 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200807 for (j = iff_size = 0; j < type->info.bits.count; j++) {
808 if (!leaf->value.bit[j]) {
809 continue;
810 }
811 idname = leaf->value.bit[j]->name;
812 iff_size = leaf->value.bit[j]->iffeature_size;
813 iff = leaf->value.bit[j]->iffeature;
814 break;
815nextbit:
816 iff_size = 0;
817 }
818 break;
819 case LY_TYPE_ENUM:
820 id = "Enum";
821 idname = leaf->value_str;
822 iff_size = leaf->value.enm->iffeature_size;
823 iff = leaf->value.enm->iffeature;
824 break;
825 case LY_TYPE_IDENT:
826 id = "Identity";
827 idname = leaf->value_str;
828 iff_size = leaf->value.ident->iffeature_size;
829 iff = leaf->value.ident->iffeature;
830 break;
831 default:
832 iff_size = 0;
833 break;
834 }
835
836 if (iff_size) {
837 for (i = 0; i < iff_size; i++) {
838 if (!resolve_iffeature(&iff[i])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100839 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
840 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its if-feature condition.",
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200841 id, idname);
Michal Vasko53b7da02018-02-13 15:28:42 +0100842 return 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200843 }
844 }
845 if (leaf->value_type == LY_TYPE_BITS) {
846 goto nextbit;
847 }
848 }
849 }
850
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100851 /* check must conditions */
852 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 +0000853 i = resolve_applies_must(node);
Michal Vasko53b7da02018-02-13 15:28:42 +0100854 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
855 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000856 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100857 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
858 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000859 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200860 }
861
Michal Vasko53b7da02018-02-13 15:28:42 +0100862 return 0;
863}
864
865int
866lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
867 int autodelete, struct lyd_node *nodel)
868{
869 struct lys_node *sparent, *schoice, *scase, *saux;
870 struct lyd_node *next, *iter;
871 assert(node || schemanode);
872
873 if (!schemanode) {
874 schemanode = node->schema;
875 }
876
877 sparent = lys_parent(schemanode);
878 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
879 /* node is not under any choice */
880 return 0;
881 } else if (!first_sibling || !(*first_sibling)) {
882 /* nothing to check */
883 return 0;
884 }
885
886 /* remember which case to skip in which choice */
887 if (sparent->nodetype == LYS_CHOICE) {
888 schoice = sparent;
889 scase = schemanode;
890 } else {
891 schoice = lys_parent(sparent);
892 scase = sparent;
893 }
894
895autodelete:
896 /* remove all nodes from other cases than 'sparent' */
897 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
898 if (schemanode == iter->schema) {
899 continue;
900 }
901
902 sparent = lys_parent(iter->schema);
903 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
904 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
905 ) {
906 if (autodelete) {
907 if (iter == nodel) {
908 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
909 return 2;
910 }
911 if (iter == *first_sibling) {
912 *first_sibling = next;
913 }
914 lyd_free(iter);
915 } else {
Michal Vaskoaf8ec362018-03-28 09:08:09 +0200916 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
Michal Vasko53b7da02018-02-13 15:28:42 +0100917 return 1;
918 }
919 }
920 }
921
922 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
923 /* go recursively in case of nested choices */
924 schoice = lys_parent(saux);
925 scase = saux;
926 goto autodelete;
927 }
928
929 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200930}