blob: 1b2fdb0738331809316f63df630f136014015e31 [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
Michal Vasko816f0f22018-03-14 09:56:37 +010051/*
52 * actions (only for list):
53 * -1 - compare keys and all uniques
54 * 0 - compare only keys
55 * n - compare n-th unique
56 */
57static int
Michal Vasko419fce02018-03-21 11:55:09 +010058lyv_list_equal(void *val1_p, void *val2_p, void *cb_data)
Michal Vasko816f0f22018-03-14 09:56:37 +010059{
60 struct ly_ctx *ctx;
61 struct lys_node_list *slist;
62 const struct lys_node *snode = NULL;
Michal Vasko6c810702018-03-14 16:23:21 +010063 struct lyd_node *diter, *first, *second;
Michal Vasko816f0f22018-03-14 09:56:37 +010064 const char *val1, *val2;
65 char *path1, *path2, *uniq_str;
66 uint16_t idx_uniq;
Michal Vasko6c810702018-03-14 16:23:21 +010067 int i, j, r, action;
Michal Vasko816f0f22018-03-14 09:56:37 +010068
Michal Vasko419fce02018-03-21 11:55:09 +010069 assert(val1_p && val2_p);
Michal Vasko6c810702018-03-14 16:23:21 +010070
Michal Vasko419fce02018-03-21 11:55:09 +010071 first = *((struct lyd_node **)val1_p);
72 second = *((struct lyd_node **)val2_p);
Michal Vasko6c810702018-03-14 16:23:21 +010073 action = (intptr_t)cb_data;
74
Michal Vasko419fce02018-03-21 11:55:09 +010075 assert(first && (first->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
76 assert(second && (second->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)));
Michal Vasko816f0f22018-03-14 09:56:37 +010077 assert(first->schema->nodetype == second->schema->nodetype);
78
79 ctx = first->schema->module->ctx;
80
81 if (first->schema != second->schema) {
82 return 0;
83 }
84
85 switch (first->schema->nodetype) {
86 case LYS_LEAFLIST:
87 if ((first->schema->flags & LYS_CONFIG_R) && first->schema->module->version >= 2) {
88 /* same values are allowed for status data */
89 return 0;
90 }
91 /* compare values */
92 if (ly_strequal(((struct lyd_node_leaf_list *)first)->value_str,
93 ((struct lyd_node_leaf_list *)second)->value_str, 1)) {
94 LOGVAL(ctx, LYE_DUPLEAFLIST, LY_VLOG_LYD, second, second->schema->name,
95 ((struct lyd_node_leaf_list *)second)->value_str);
96 return 1;
97 }
98 return 0;
99 case LYS_LIST:
100 slist = (struct lys_node_list *)first->schema;
101
102 /* compare unique leafs */
103 if (action) {
104 if (action > 0) {
105 i = action - 1;
106 if (i < slist->unique_size) {
107 goto uniquecheck;
108 }
109 }
110 for (i = 0; i < slist->unique_size; i++) {
111uniquecheck:
112 for (j = 0; j < slist->unique[i].expr_size; j++) {
113 /* first */
114 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], first->child);
115 if (diter) {
116 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
117 } else {
118 /* use default value */
119 if (lyd_get_unique_default(slist->unique[i].expr[j], first, &val1)) {
120 return 1;
121 }
122 }
123
124 /* second */
125 diter = resolve_data_descendant_schema_nodeid(slist->unique[i].expr[j], second->child);
126 if (diter) {
127 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
128 } else {
129 /* use default value */
130 if (lyd_get_unique_default(slist->unique[i].expr[j], second, &val2)) {
131 return 1;
132 }
133 }
134
135 if (!val1 || !val2 || !ly_strequal(val1, val2, 1)) {
136 /* values differ or either one is not set */
137 break;
138 }
139 }
140 if (j && (j == slist->unique[i].expr_size)) {
141 /* all unique leafs are the same in this set, create this nice error */
142 ly_vlog_build_path(LY_VLOG_LYD, first, &path1, 0);
143 ly_vlog_build_path(LY_VLOG_LYD, second, &path2, 0);
144
145 /* use buffer to rebuild the unique string */
146 uniq_str = malloc(1024);
147 idx_uniq = 0;
148 for (j = 0; j < slist->unique[i].expr_size; ++j) {
149 if (j) {
150 uniq_str[idx_uniq++] = ' ';
151 }
152 r = lyd_build_relative_data_path(lys_node_module((struct lys_node *)slist), first,
153 slist->unique[i].expr[j], &uniq_str[idx_uniq]);
154 if (r == -1) {
155 goto unique_errmsg_cleanup;
156 }
157 idx_uniq += r;
158 }
159
160 LOGVAL(ctx, LYE_NOUNIQ, LY_VLOG_LYD, second, uniq_str, path1, path2);
161unique_errmsg_cleanup:
162 free(path1);
163 free(path2);
164 free(uniq_str);
165 return 1;
166 }
167
168 if (action > 0) {
169 /* done */
170 return 0;
171 }
172 }
173 }
174
175 /* compare keys */
176 if (!slist->keys_size) {
177 /* status lists without keys */
178 return 0;
179 } else {
180 for (i = 0; i < slist->keys_size; i++) {
181 snode = (struct lys_node *)slist->keys[i];
182 val1 = val2 = NULL;
183 LY_TREE_FOR(first->child, diter) {
184 if (diter->schema == snode) {
185 val1 = ((struct lyd_node_leaf_list *)diter)->value_str;
186 break;
187 }
188 }
189 LY_TREE_FOR(second->child, diter) {
190 if (diter->schema == snode) {
191 val2 = ((struct lyd_node_leaf_list *)diter)->value_str;
192 break;
193 }
194 }
195 if (!ly_strequal(val1, val2, 1)) {
196 return 0;
197 }
198 }
199 }
200
201 LOGVAL(ctx, LYE_DUPLIST, LY_VLOG_LYD, second, second->schema->name);
202 return 1;
203
204 default:
205 LOGINT(ctx);
206 return 1;
207 }
208}
209
Radek Krejcieab784a2015-08-27 09:56:53 +0200210int
Radek Krejci48464ed2016-03-17 15:44:09 +0100211lyv_data_context(const struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200212{
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100213 const struct lys_node *siter = NULL;
Radek Krejcib1f318b2016-08-22 16:18:37 +0200214 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
Michal Vasko53b7da02018-02-13 15:28:42 +0100215 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100216
Michal Vaskocf024702015-10-08 15:01:42 +0200217 assert(node);
Radek Krejci03b71f72016-03-16 11:10:09 +0100218 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200219
220 /* check if the node instance is enabled by if-feature */
Michal Vaskocf024702015-10-08 15:01:42 +0200221 if (lys_is_disabled(node->schema, 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100222 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
223 return 1;
Michal Vaskocf024702015-10-08 15:01:42 +0200224 }
225
Radek Krejcib1f318b2016-08-22 16:18:37 +0200226 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100227 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
228 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
229 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
230 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100231 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +0100232 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100233 } else if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) && (leaf->validity & LYD_VAL_LEAFREF)) {
234 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100235 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100236 }
237 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
238 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100239 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +0100240 }
Michal Vasko0d182ba2015-10-09 09:29:14 +0200241 }
Radek Krejci0b7704f2016-03-18 12:16:14 +0100242 }
243
Michal Vaskocf024702015-10-08 15:01:42 +0200244 /* check all relevant when conditions */
Michal Vaskoebf7df22017-03-28 16:08:07 +0200245 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
246 && (node->when_status & LYD_WHEN)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +0100247 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100248 return 1;
Michal Vasko0d182ba2015-10-09 09:29:14 +0200249 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200250 }
251
252 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100253 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100254 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
255 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200256 }
257
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100258 /* check elements order in case of RPC's input and output */
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100259 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 +0100260 if ((node->prev != node) && node->prev->next) {
Michal Vasko9e780492017-03-28 14:48:31 +0200261 for (siter = lys_getnext(node->schema, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100262 siter;
Michal Vasko9e780492017-03-28 14:48:31 +0200263 siter = lys_getnext(siter, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100264 if (siter == node->prev->schema) {
265 /* data predecessor has the schema node after
266 * the schema node of the data node being checked */
Michal Vasko53b7da02018-02-13 15:28:42 +0100267 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
268 return 1;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100269 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100270 }
271
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100272 }
273 }
274
Michal Vasko53b7da02018-02-13 15:28:42 +0100275 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200276}
Michal Vaskocf024702015-10-08 15:01:42 +0200277
Radek Krejci63b79c82016-08-10 10:09:33 +0200278int
279lyv_data_unique(struct lyd_node *node, struct lyd_node *start)
280{
281 struct lyd_node *diter, *key;
282 struct lys_node_list *slist;
283 struct ly_set *set;
Michal Vasko53b7da02018-02-13 15:28:42 +0100284 int i, j, n = 0, ret = 0;
Michal Vasko6c810702018-03-14 16:23:21 +0100285 uint32_t hash, u, usize = 0;
286 struct hash_table *keystable = NULL, **uniquetables = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200287 const char *id;
Michal Vasko53b7da02018-02-13 15:28:42 +0100288 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci63b79c82016-08-10 10:09:33 +0200289
290 /* get the first list/leaflist instance sibling */
291 if (!start) {
292 start = lyd_first_sibling(node);
293 }
294
295 /* check uniqueness of the list/leaflist instances (compare values) */
296 set = ly_set_new();
297 for (diter = start; diter; diter = diter->next) {
298 if (diter->schema != node->schema) {
299 /* check only instances of the same list/leaflist */
300 continue;
301 }
302
303 /* remove the flag */
304 diter->validity &= ~LYD_VAL_UNIQUE;
305
306 /* store for comparison */
307 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
308 }
309
310 if (set->number == 2) {
311 /* simple comparison */
Michal Vasko419fce02018-03-21 11:55:09 +0100312 if (lyv_list_equal(&set->set.d[0], &set->set.d[1], (void *)-1)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200313 /* instance duplication */
314 ly_set_free(set);
Michal Vasko53b7da02018-02-13 15:28:42 +0100315 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200316 }
317 } else if (set->number > 2) {
318 /* use hashes for comparison */
319 /* first, allocate the table, the size depends on number of items in the set */
320 for (u = 31; u > 0; u--) {
321 usize = set->number << u;
322 usize = usize >> u;
323 if (usize == set->number) {
324 break;
325 }
326 }
327 if (u == 0) {
Michal Vasko6c810702018-03-14 16:23:21 +0100328 LOGINT(ctx);
329 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200330 } else {
331 u = 32 - u;
332 usize = 1 << u;
Radek Krejci63b79c82016-08-10 10:09:33 +0200333 }
Michal Vasko419fce02018-03-21 11:55:09 +0100334 keystable = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, 0, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200335 if (!keystable) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100336 LOGMEM(ctx);
337 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200338 goto unique_cleanup;
339 }
340 n = 0;
341 if (node->schema->nodetype == LYS_LIST) {
342 n = ((struct lys_node_list *)node->schema)->unique_size;
343 uniquetables = malloc(n * sizeof *uniquetables);
344 if (!uniquetables) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100345 LOGMEM(ctx);
346 ret = 1;
Radek Krejci70292d22016-08-15 09:39:22 +0200347 n = 0;
Radek Krejci63b79c82016-08-10 10:09:33 +0200348 goto unique_cleanup;
349 }
350 for (j = 0; j < n; j++) {
Michal Vasko419fce02018-03-21 11:55:09 +0100351 uniquetables[j] = lyht_new(usize, sizeof(struct lyd_node *), lyv_list_equal, (void *)(j + 1L), 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200352 if (!uniquetables[j]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100353 LOGMEM(ctx);
354 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200355 goto unique_cleanup;
356 }
357 }
358 }
359
360 for (u = 0; u < set->number; u++) {
361 /* get the hash for the instance - keys */
362 if (node->schema->nodetype == LYS_LEAFLIST) {
363 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
364 hash = dict_hash_multi(0, id, strlen(id));
365 } else { /* LYS_LIST */
366 for (hash = i = 0, key = set->set.d[u]->child;
367 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
368 i++, key = key->next) {
369 id = ((struct lyd_node_leaf_list *)key)->value_str;
370 hash = dict_hash_multi(hash, id, strlen(id));
371 }
372 }
373 /* finish the hash value */
Michal Vasko6c810702018-03-14 16:23:21 +0100374 hash = dict_hash_multi(hash, NULL, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200375
376 /* insert into the hashtable */
Michal Vasko419fce02018-03-21 11:55:09 +0100377 if (lyht_insert(keystable, &set->set.d[u], hash)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100378 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200379 goto unique_cleanup;
380 }
381
382 /* and the same loop for unique (n is !0 only in case of list) - get the hash for the instances */
383 for (j = 0; j < n; j++) {
384 slist = (struct lys_node_list *)node->schema;
Radek Krejci50dc7ae2016-09-01 09:56:37 +0200385 id = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200386 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
387 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
388 if (diter) {
389 id = ((struct lyd_node_leaf_list *)diter)->value_str;
390 } else {
391 /* use default value */
Michal Vasko53b7da02018-02-13 15:28:42 +0100392 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
393 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200394 goto unique_cleanup;
395 }
396 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200397 if (!id) {
398 /* unique item not present nor has default value */
399 break;
400 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200401 hash = dict_hash_multi(hash, id, strlen(id));
402 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200403 if (!id) {
404 /* skip this list instance since its unique set is incomplete */
405 continue;
406 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200407
408 /* finish the hash value */
Michal Vasko6c810702018-03-14 16:23:21 +0100409 hash = dict_hash_multi(hash, NULL, 0);
Radek Krejci63b79c82016-08-10 10:09:33 +0200410
411 /* insert into the hashtable */
Michal Vasko419fce02018-03-21 11:55:09 +0100412 if (lyht_insert(uniquetables[j], &set->set.d[u], hash)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100413 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200414 goto unique_cleanup;
415 }
416 }
417 }
418 }
419
420unique_cleanup:
421 /* cleanup */
422 ly_set_free(set);
Michal Vasko6c810702018-03-14 16:23:21 +0100423 lyht_free(keystable);
Radek Krejci63b79c82016-08-10 10:09:33 +0200424 for (j = 0; j < n; j++) {
425 if (!uniquetables[j]) {
426 /* failed when allocating uniquetables[j], following j are not allocated */
427 break;
428 }
Michal Vasko6c810702018-03-14 16:23:21 +0100429 lyht_free(uniquetables[j]);
Radek Krejci63b79c82016-08-10 10:09:33 +0200430 }
431 free(uniquetables);
432
433 return ret;
434}
435
Michal Vasko91ff4592017-05-24 15:41:49 +0200436static struct lys_type *
437find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
438{
439 struct lys_type *type, *prev_type, *tmp_type;
440 int found;
441
442 /* go through typedefs */
443 for (type = par_type; type->der->type.der; type = &type->der->type);
444
445 if (type->base == base_type) {
446 /* we have the result */
447 return type;
Michal Vasko70bf8e52018-03-26 11:32:33 +0200448 } else if ((type->base == LY_TYPE_LEAFREF) && !(type->flags & LYTYPE_UNRES)) {
449 /* go through the leafref */
450 assert(type->info.lref.target);
451 return find_orig_type(&((struct lys_node_leaf *)type->info.lref.target)->type, base_type);
Michal Vasko91ff4592017-05-24 15:41:49 +0200452 } else if (type->base == LY_TYPE_UNION) {
453 /* go through all the union types */
454 prev_type = NULL;
455 found = 0;
456 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
457 tmp_type = find_orig_type(prev_type, base_type);
458 if (tmp_type) {
459 return tmp_type;
460 }
461 found = 0;
462 }
463 }
464
465 /* not found */
466 return NULL;
467}
468
PavolVican556559e2017-12-12 13:39:36 +0100469static int
470lyv_extension(struct lys_ext_instance **ext, uint8_t size, struct lyd_node *node)
471{
472 uint i;
473
474 for (i = 0; i < size; ++i) {
475 if ((ext[i]->flags & LYEXT_OPT_VALID) && ext[i]->def->plugin->valid_data) {
476 if (ext[i]->def->plugin->valid_data(ext[i], node)) {
477 return EXIT_FAILURE;
478 }
479 }
480 }
481 return 0;
482}
483
484static int
485lyv_type_extension(struct lyd_node_leaf_list *leaf, struct lys_type *type, int first_type)
486{
487 struct lyd_node *node = (struct lyd_node *)leaf;
488 unsigned int i;
489
490 switch (type->base) {
491 case LY_TYPE_ENUM:
492 if (first_type && lyv_extension(leaf->value.enm->ext, leaf->value.enm->ext_size, node)) {
493 return EXIT_FAILURE;
494 }
495 break;
496 case LY_TYPE_STRING:
497 if (type->info.str.length &&
498 lyv_extension(type->info.str.length->ext, type->info.str.length->ext_size, node)) {
499 return EXIT_FAILURE;
500 }
501 for(i = 0; i < type->info.str.pat_count; ++i) {
502 if (lyv_extension(type->info.str.patterns[i].ext, type->info.str.patterns[i].ext_size, node)) {
503 return EXIT_FAILURE;
504 }
505 }
506 break;
507 case LY_TYPE_DEC64:
508 if (type->info.dec64.range &&
509 lyv_extension(type->info.dec64.range->ext, type->info.dec64.range->ext_size, node)) {
510 return EXIT_FAILURE;
511 }
512 break;
513 case LY_TYPE_INT8:
514 case LY_TYPE_INT16:
515 case LY_TYPE_INT32:
516 case LY_TYPE_INT64:
517 case LY_TYPE_UINT8:
518 case LY_TYPE_UINT16:
519 case LY_TYPE_UINT32:
520 case LY_TYPE_UINT64:
521 if (type->info.num.range &&
522 lyv_extension(type->info.num.range->ext, type->info.num.range->ext_size, node)) {
523 return EXIT_FAILURE;
524 }
525 break;
526 case LY_TYPE_BITS:
527 if (first_type) {
528 /* get the count of bits */
529 type = find_orig_type(&((struct lys_node_leaf *) leaf->schema)->type, LY_TYPE_BITS);
530 for (i = 0; i < type->info.bits.count; ++i) {
531 if (!leaf->value.bit[i]) {
532 continue;
533 }
534 if (lyv_extension(leaf->value.bit[i]->ext, leaf->value.bit[i]->ext_size, node)) {
535 return EXIT_FAILURE;
536 }
537 }
538 }
539 break;
540 case LY_TYPE_UNION:
541 for (i = 0; i < type->info.uni.count; ++i) {
542 if (type->info.uni.types[i].base == leaf->value_type) {
543 break;
544 }
545 }
546 if (i < type->info.uni.count &&
547 lyv_type_extension(leaf, &type->info.uni.types[i], first_type)) {
548 return EXIT_FAILURE;
549 }
550 break;
551 default:
552 break;
553 }
554
555
556 if (lyv_extension(type->ext, type->ext_size, node)) {
557 return EXIT_FAILURE;
558 }
559
560 while (type->der->type.der) {
561 type = &type->der->type;
Michal Vasko1bdfd432018-03-09 09:30:19 +0100562 if ((type->parent->flags & LYS_VALID_EXT)) {
563 if (lyv_type_extension(leaf, type, 0) || lyv_extension(type->parent->ext, type->parent->ext_size, node)) {
PavolVican556559e2017-12-12 13:39:36 +0100564 return EXIT_FAILURE;
565 }
566 }
567 }
568
569 return EXIT_SUCCESS;
570}
571
Radek Krejcieab784a2015-08-27 09:56:53 +0200572int
Radek Krejci48464ed2016-03-17 15:44:09 +0100573lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200574{
PavolVican832f5432018-02-21 00:54:45 +0100575 const struct lys_node *schema, *siter, *parent;
Radek Krejcid788a522016-07-25 14:57:38 +0200576 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100577 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100578 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200579 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200580 struct lyd_node_leaf_list *leaf;
Radek Krejcidce5f972017-09-12 15:47:49 +0200581 unsigned int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200582 uint8_t iff_size;
583 struct lys_iffeature *iff;
584 const char *id, *idname;
Michal Vasko53b7da02018-02-13 15:28:42 +0100585 struct ly_ctx *ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200586
587 assert(node);
588 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100589 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200590
591 schema = node->schema; /* shortcut */
Michal Vasko53b7da02018-02-13 15:28:42 +0100592 ctx = schema->module->ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200593
Michal Vasko091dd842017-02-08 14:07:32 +0100594 if (node->validity & LYD_VAL_MAND) {
595 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
596 /* check presence and correct order of all keys in case of list */
597 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
598 if (lyv_keys(node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100599 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200600 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200601 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200602
Michal Vasko091dd842017-02-08 14:07:32 +0100603 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
604 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100605
Michal Vasko091dd842017-02-08 14:07:32 +0100606 /* find duplicity */
607 start = lyd_first_sibling(node);
608 for (diter = start; diter; diter = diter->next) {
609 if (diter->schema == schema && diter != node) {
PavolVican832f5432018-02-21 00:54:45 +0100610 parent = lys_parent(schema);
Michal Vasko53b7da02018-02-13 15:28:42 +0100611 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
PavolVican832f5432018-02-21 00:54:45 +0100612 parent ? (parent->nodetype == LYS_EXT) ? ((struct lys_ext_instance *)parent)->arg_value : parent->name : "data tree");
Michal Vasko53b7da02018-02-13 15:28:42 +0100613 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100614 }
615 }
Michal Vasko091dd842017-02-08 14:07:32 +0100616 }
617
618 if (options & LYD_OPT_OBSOLETE) {
619 /* status - of the node's schema node itself and all its parents that
620 * cannot have their own instance (like a choice statement) */
621 siter = node->schema;
622 do {
623 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100624 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
625 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100626 }
Michal Vasko091dd842017-02-08 14:07:32 +0100627 siter = lys_parent(siter);
628 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
629
630 /* status of the identity value */
631 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
632 if (options & LYD_OPT_OBSOLETE) {
633 /* check that we are not instantiating obsolete type */
634 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
635 while (tpdf) {
636 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100637 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
638 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100639 }
640 tpdf = tpdf->type.der;
641 }
642 }
643 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
644 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
645 if (lyp_check_status(schema->flags, schema->module, schema->name,
646 ident->flags, ident->module, ident->name, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100647 LOGPATH(ctx, LY_VLOG_LYD, node);
648 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100649 }
650 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100651 }
652 }
653 }
654
PavolVican556559e2017-12-12 13:39:36 +0100655 /* check validation function for extension */
Michal Vasko1bdfd432018-03-09 09:30:19 +0100656 if (schema->flags & LYS_VALID_EXT) {
PavolVican556559e2017-12-12 13:39:36 +0100657 // check extension in node
658 if (lyv_extension(schema->ext, schema->ext_size, node)) {
659 return EXIT_FAILURE;
660 }
661
662 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
663 type = &((struct lys_node_leaf *) schema)->type;
664 leaf = (struct lyd_node_leaf_list *) node;
665 if (lyv_type_extension(leaf, type, 1)) {
666 return EXIT_FAILURE;
667 }
668 }
669
670
671 }
672
Radek Krejcid788a522016-07-25 14:57:38 +0200673 /* remove the flag */
674 node->validity &= ~LYD_VAL_MAND;
675 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100676
Michal Vaskob1bc1d92017-01-05 11:47:41 +0100677 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200678 /* skip key uniqueness check in case of get/get-config data */
679 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER)) {
680 LY_TREE_FOR(schema->child, siter) {
681 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
682 LY_TREE_FOR(node->child, diter) {
683 if (diter->schema == siter && (diter->validity & LYD_VAL_UNIQUE)) {
684 if (lyv_data_unique(diter, node->child)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100685 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200686 }
687 /* all schema instances checked, continue with another schema node */
688 break;
689 }
690 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100691 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100692 }
693 }
Radek Krejcid788a522016-07-25 14:57:38 +0200694 }
695
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200696 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
697 /* since feature can be enabled/disabled, do this check despite the validity flag,
698 * - check if the type value (enum, bit, identity) is disabled via feature */
699 leaf = (struct lyd_node_leaf_list *)node;
700 switch (leaf->value_type) {
701 case LY_TYPE_BITS:
702 id = "Bit";
703 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200704 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200705 for (j = iff_size = 0; j < type->info.bits.count; j++) {
706 if (!leaf->value.bit[j]) {
707 continue;
708 }
709 idname = leaf->value.bit[j]->name;
710 iff_size = leaf->value.bit[j]->iffeature_size;
711 iff = leaf->value.bit[j]->iffeature;
712 break;
713nextbit:
714 iff_size = 0;
715 }
716 break;
717 case LY_TYPE_ENUM:
718 id = "Enum";
719 idname = leaf->value_str;
720 iff_size = leaf->value.enm->iffeature_size;
721 iff = leaf->value.enm->iffeature;
722 break;
723 case LY_TYPE_IDENT:
724 id = "Identity";
725 idname = leaf->value_str;
726 iff_size = leaf->value.ident->iffeature_size;
727 iff = leaf->value.ident->iffeature;
728 break;
729 default:
730 iff_size = 0;
731 break;
732 }
733
734 if (iff_size) {
735 for (i = 0; i < iff_size; i++) {
736 if (!resolve_iffeature(&iff[i])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100737 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
738 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its if-feature condition.",
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200739 id, idname);
Michal Vasko53b7da02018-02-13 15:28:42 +0100740 return 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200741 }
742 }
743 if (leaf->value_type == LY_TYPE_BITS) {
744 goto nextbit;
745 }
746 }
747 }
748
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100749 /* check must conditions */
750 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 +0000751 i = resolve_applies_must(node);
Michal Vasko53b7da02018-02-13 15:28:42 +0100752 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
753 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000754 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100755 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
756 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000757 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200758 }
759
Michal Vasko53b7da02018-02-13 15:28:42 +0100760 return 0;
761}
762
763int
764lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
765 int autodelete, struct lyd_node *nodel)
766{
767 struct lys_node *sparent, *schoice, *scase, *saux;
768 struct lyd_node *next, *iter;
769 assert(node || schemanode);
770
771 if (!schemanode) {
772 schemanode = node->schema;
773 }
774
775 sparent = lys_parent(schemanode);
776 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
777 /* node is not under any choice */
778 return 0;
779 } else if (!first_sibling || !(*first_sibling)) {
780 /* nothing to check */
781 return 0;
782 }
783
784 /* remember which case to skip in which choice */
785 if (sparent->nodetype == LYS_CHOICE) {
786 schoice = sparent;
787 scase = schemanode;
788 } else {
789 schoice = lys_parent(sparent);
790 scase = sparent;
791 }
792
793autodelete:
794 /* remove all nodes from other cases than 'sparent' */
795 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
796 if (schemanode == iter->schema) {
797 continue;
798 }
799
800 sparent = lys_parent(iter->schema);
801 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
802 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
803 ) {
804 if (autodelete) {
805 if (iter == nodel) {
806 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
807 return 2;
808 }
809 if (iter == *first_sibling) {
810 *first_sibling = next;
811 }
812 lyd_free(iter);
813 } else {
Michal Vaskoaf8ec362018-03-28 09:08:09 +0200814 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
Michal Vasko53b7da02018-02-13 15:28:42 +0100815 return 1;
816 }
817 }
818 }
819
820 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
821 /* go recursively in case of nested choices */
822 schoice = lys_parent(saux);
823 scase = saux;
824 goto autodelete;
825 }
826
827 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200828}