blob: 620cc07d57f4c9257c4f1c27f3ae25309c04561b [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;
Radek Krejcib1f318b2016-08-22 16:18:37 +020055 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
Michal Vasko53b7da02018-02-13 15:28:42 +010056 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci4a49bdf2016-01-12 17:17:01 +010057
Michal Vaskocf024702015-10-08 15:01:42 +020058 assert(node);
Radek Krejci03b71f72016-03-16 11:10:09 +010059 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +020060
61 /* check if the node instance is enabled by if-feature */
Michal Vaskocf024702015-10-08 15:01:42 +020062 if (lys_is_disabled(node->schema, 2)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010063 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
64 return 1;
Michal Vaskocf024702015-10-08 15:01:42 +020065 }
66
Radek Krejcib1f318b2016-08-22 16:18:37 +020067 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +010068 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
69 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
70 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
71 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010072 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +010073 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +010074 } else if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) && (leaf->validity & LYD_VAL_LEAFREF)) {
75 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010076 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +010077 }
78 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
79 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010080 return 1;
Radek Krejci0b7704f2016-03-18 12:16:14 +010081 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020082 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010083 }
84
Michal Vaskocf024702015-10-08 15:01:42 +020085 /* check all relevant when conditions */
Michal Vaskoebf7df22017-03-28 16:08:07 +020086 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
87 && (node->when_status & LYD_WHEN)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +010088 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010089 return 1;
Michal Vasko0d182ba2015-10-09 09:29:14 +020090 }
Radek Krejcieab784a2015-08-27 09:56:53 +020091 }
92
93 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +010094 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Michal Vasko53b7da02018-02-13 15:28:42 +010095 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
96 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +020097 }
98
Radek Krejci4a49bdf2016-01-12 17:17:01 +010099 /* check elements order in case of RPC's input and output */
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100100 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 +0100101 if ((node->prev != node) && node->prev->next) {
Michal Vasko9e780492017-03-28 14:48:31 +0200102 for (siter = lys_getnext(node->schema, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100103 siter;
Michal Vasko9e780492017-03-28 14:48:31 +0200104 siter = lys_getnext(siter, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100105 if (siter == node->prev->schema) {
106 /* data predecessor has the schema node after
107 * the schema node of the data node being checked */
Michal Vasko53b7da02018-02-13 15:28:42 +0100108 LOGVAL(ctx, LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
109 return 1;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100110 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100111 }
112
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100113 }
114 }
115
Michal Vasko53b7da02018-02-13 15:28:42 +0100116 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200117}
Michal Vaskocf024702015-10-08 15:01:42 +0200118
Radek Krejci63b79c82016-08-10 10:09:33 +0200119struct eq_item {
120 struct lyd_node *node;
121 uint32_t hash;
122 uint32_t over;
123};
124
125static int
126eq_table_insert(struct eq_item *table, struct lyd_node *node, uint32_t hash, uint32_t tablesize, int action)
127{
128 uint32_t i, c;
129
130 if (table[hash].node) {
131 /* is it collision or is the cell just filled by an overflow item? */
132 for (i = hash; table[i].node && table[i].hash != hash; i = (i + 1) % tablesize);
133 if (!table[i].node) {
134 goto first;
135 }
136
137 /* collision or instance duplication */
138 c = table[i].over;
139 do {
140 if (table[i].hash != hash) {
141 i = (i + 1) % tablesize;
142 continue;
143 }
144
145 /* compare nodes */
Michal Vasko53b7da02018-02-13 15:28:42 +0100146 if (lyd_list_equal(node, table[i].node, action, 0)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200147 /* instance duplication */
Michal Vasko53b7da02018-02-13 15:28:42 +0100148 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200149 }
150 } while (c--);
151
152 /* collision, insert item into next free cell */
153 table[hash].over++;
154 for (i = (i + 1) % tablesize; table[i].node; i = (i + 1) % tablesize);
155 table[i].hash = hash;
156 table[i].node = node;
157 } else {
158first:
159 /* first hash instance */
160 table[hash].node = node;
161 table[hash].hash = hash;
162 }
163
Michal Vasko53b7da02018-02-13 15:28:42 +0100164 return 0;
Radek Krejci63b79c82016-08-10 10:09:33 +0200165}
166
167int
168lyv_data_unique(struct lyd_node *node, struct lyd_node *start)
169{
170 struct lyd_node *diter, *key;
171 struct lys_node_list *slist;
172 struct ly_set *set;
Michal Vasko53b7da02018-02-13 15:28:42 +0100173 int i, j, n = 0, ret = 0;
Radek Krejci63b79c82016-08-10 10:09:33 +0200174 uint32_t hash, u, usize = 0, hashmask;
175 struct eq_item *keystable = NULL, **uniquetables = NULL;
176 const char *id;
Michal Vasko53b7da02018-02-13 15:28:42 +0100177 struct ly_ctx *ctx = node->schema->module->ctx;
Radek Krejci63b79c82016-08-10 10:09:33 +0200178
179 /* get the first list/leaflist instance sibling */
180 if (!start) {
181 start = lyd_first_sibling(node);
182 }
183
184 /* check uniqueness of the list/leaflist instances (compare values) */
185 set = ly_set_new();
186 for (diter = start; diter; diter = diter->next) {
187 if (diter->schema != node->schema) {
188 /* check only instances of the same list/leaflist */
189 continue;
190 }
191
192 /* remove the flag */
193 diter->validity &= ~LYD_VAL_UNIQUE;
194
195 /* store for comparison */
196 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
197 }
198
199 if (set->number == 2) {
200 /* simple comparison */
Michal Vasko53b7da02018-02-13 15:28:42 +0100201 if (lyd_list_equal(set->set.d[0], set->set.d[1], -1, 0)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200202 /* instance duplication */
203 ly_set_free(set);
Michal Vasko53b7da02018-02-13 15:28:42 +0100204 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200205 }
206 } else if (set->number > 2) {
207 /* use hashes for comparison */
208 /* first, allocate the table, the size depends on number of items in the set */
209 for (u = 31; u > 0; u--) {
210 usize = set->number << u;
211 usize = usize >> u;
212 if (usize == set->number) {
213 break;
214 }
215 }
216 if (u == 0) {
217 usize = hashmask = 0xffffffff;
218 } else {
219 u = 32 - u;
220 usize = 1 << u;
221 hashmask = usize - 1;
222 }
223 keystable = calloc(usize, sizeof *keystable);
224 if (!keystable) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100225 LOGMEM(ctx);
226 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200227 goto unique_cleanup;
228 }
229 n = 0;
230 if (node->schema->nodetype == LYS_LIST) {
231 n = ((struct lys_node_list *)node->schema)->unique_size;
232 uniquetables = malloc(n * sizeof *uniquetables);
233 if (!uniquetables) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100234 LOGMEM(ctx);
235 ret = 1;
Radek Krejci70292d22016-08-15 09:39:22 +0200236 n = 0;
Radek Krejci63b79c82016-08-10 10:09:33 +0200237 goto unique_cleanup;
238 }
239 for (j = 0; j < n; j++) {
240 uniquetables[j] = calloc(usize, sizeof **uniquetables);
241 if (!uniquetables[j]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100242 LOGMEM(ctx);
243 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200244 goto unique_cleanup;
245 }
246 }
247 }
248
249 for (u = 0; u < set->number; u++) {
250 /* get the hash for the instance - keys */
251 if (node->schema->nodetype == LYS_LEAFLIST) {
252 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
253 hash = dict_hash_multi(0, id, strlen(id));
254 } else { /* LYS_LIST */
255 for (hash = i = 0, key = set->set.d[u]->child;
256 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
257 i++, key = key->next) {
258 id = ((struct lyd_node_leaf_list *)key)->value_str;
259 hash = dict_hash_multi(hash, id, strlen(id));
260 }
261 }
262 /* finish the hash value */
263 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
264
265 /* insert into the hashtable */
266 if (eq_table_insert(keystable, set->set.d[u], hash, usize, 0)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100267 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200268 goto unique_cleanup;
269 }
270
271 /* and the same loop for unique (n is !0 only in case of list) - get the hash for the instances */
272 for (j = 0; j < n; j++) {
273 slist = (struct lys_node_list *)node->schema;
Radek Krejci50dc7ae2016-09-01 09:56:37 +0200274 id = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200275 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
276 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
277 if (diter) {
278 id = ((struct lyd_node_leaf_list *)diter)->value_str;
279 } else {
280 /* use default value */
Michal Vasko53b7da02018-02-13 15:28:42 +0100281 if (lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u], &id)) {
282 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200283 goto unique_cleanup;
284 }
285 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200286 if (!id) {
287 /* unique item not present nor has default value */
288 break;
289 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200290 hash = dict_hash_multi(hash, id, strlen(id));
291 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200292 if (!id) {
293 /* skip this list instance since its unique set is incomplete */
294 continue;
295 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200296
297 /* finish the hash value */
298 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
299
300 /* insert into the hashtable */
301 if (eq_table_insert(uniquetables[j], set->set.d[u], hash, usize, j + 1)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100302 ret = 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200303 goto unique_cleanup;
304 }
305 }
306 }
307 }
308
309unique_cleanup:
310 /* cleanup */
311 ly_set_free(set);
312 free(keystable);
313 for (j = 0; j < n; j++) {
314 if (!uniquetables[j]) {
315 /* failed when allocating uniquetables[j], following j are not allocated */
316 break;
317 }
318 free(uniquetables[j]);
319 }
320 free(uniquetables);
321
322 return ret;
323}
324
Michal Vasko91ff4592017-05-24 15:41:49 +0200325static struct lys_type *
326find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
327{
328 struct lys_type *type, *prev_type, *tmp_type;
329 int found;
330
331 /* go through typedefs */
332 for (type = par_type; type->der->type.der; type = &type->der->type);
333
334 if (type->base == base_type) {
335 /* we have the result */
336 return type;
337 } else if (type->base == LY_TYPE_UNION) {
338 /* go through all the union types */
339 prev_type = NULL;
340 found = 0;
341 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
342 tmp_type = find_orig_type(prev_type, base_type);
343 if (tmp_type) {
344 return tmp_type;
345 }
346 found = 0;
347 }
348 }
349
350 /* not found */
351 return NULL;
352}
353
Radek Krejcieab784a2015-08-27 09:56:53 +0200354int
Radek Krejci48464ed2016-03-17 15:44:09 +0100355lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200356{
Michal Vasko1e62a092015-12-01 12:27:20 +0100357 const struct lys_node *schema, *siter;
Radek Krejcid788a522016-07-25 14:57:38 +0200358 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100359 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100360 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200361 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200362 struct lyd_node_leaf_list *leaf;
Radek Krejcidce5f972017-09-12 15:47:49 +0200363 unsigned int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200364 uint8_t iff_size;
365 struct lys_iffeature *iff;
366 const char *id, *idname;
Michal Vasko53b7da02018-02-13 15:28:42 +0100367 struct ly_ctx *ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200368
369 assert(node);
370 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100371 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200372
373 schema = node->schema; /* shortcut */
Michal Vasko53b7da02018-02-13 15:28:42 +0100374 ctx = schema->module->ctx;
Radek Krejcieab784a2015-08-27 09:56:53 +0200375
Michal Vasko091dd842017-02-08 14:07:32 +0100376 if (node->validity & LYD_VAL_MAND) {
377 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
378 /* check presence and correct order of all keys in case of list */
379 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
380 if (lyv_keys(node)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100381 return 1;
Radek Krejcieab784a2015-08-27 09:56:53 +0200382 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200383 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200384
Michal Vasko091dd842017-02-08 14:07:32 +0100385 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
386 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100387
Michal Vasko091dd842017-02-08 14:07:32 +0100388 /* find duplicity */
389 start = lyd_first_sibling(node);
390 for (diter = start; diter; diter = diter->next) {
391 if (diter->schema == schema && diter != node) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100392 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
Michal Vasko091dd842017-02-08 14:07:32 +0100393 lys_parent(schema) ? lys_parent(schema)->name : "data tree");
Michal Vasko53b7da02018-02-13 15:28:42 +0100394 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100395 }
396 }
Michal Vasko091dd842017-02-08 14:07:32 +0100397 }
398
399 if (options & LYD_OPT_OBSOLETE) {
400 /* status - of the node's schema node itself and all its parents that
401 * cannot have their own instance (like a choice statement) */
402 siter = node->schema;
403 do {
404 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100405 LOGVAL(ctx, LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
406 return 1;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100407 }
Michal Vasko091dd842017-02-08 14:07:32 +0100408 siter = lys_parent(siter);
409 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
410
411 /* status of the identity value */
412 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
413 if (options & LYD_OPT_OBSOLETE) {
414 /* check that we are not instantiating obsolete type */
415 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
416 while (tpdf) {
417 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100418 LOGVAL(ctx, LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
419 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100420 }
421 tpdf = tpdf->type.der;
422 }
423 }
424 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
425 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
426 if (lyp_check_status(schema->flags, schema->module, schema->name,
427 ident->flags, ident->module, ident->name, NULL)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100428 LOGPATH(ctx, LY_VLOG_LYD, node);
429 return 1;
Michal Vasko091dd842017-02-08 14:07:32 +0100430 }
431 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100432 }
433 }
434 }
435
Radek Krejcid788a522016-07-25 14:57:38 +0200436 /* remove the flag */
437 node->validity &= ~LYD_VAL_MAND;
438 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100439
Michal Vaskob1bc1d92017-01-05 11:47:41 +0100440 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200441 /* skip key uniqueness check in case of get/get-config data */
442 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER)) {
443 LY_TREE_FOR(schema->child, siter) {
444 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
445 LY_TREE_FOR(node->child, diter) {
446 if (diter->schema == siter && (diter->validity & LYD_VAL_UNIQUE)) {
447 if (lyv_data_unique(diter, node->child)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100448 return 1;
Radek Krejci63b79c82016-08-10 10:09:33 +0200449 }
450 /* all schema instances checked, continue with another schema node */
451 break;
452 }
453 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100454 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100455 }
456 }
Radek Krejcid788a522016-07-25 14:57:38 +0200457 }
458
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200459 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
460 /* since feature can be enabled/disabled, do this check despite the validity flag,
461 * - check if the type value (enum, bit, identity) is disabled via feature */
462 leaf = (struct lyd_node_leaf_list *)node;
463 switch (leaf->value_type) {
464 case LY_TYPE_BITS:
465 id = "Bit";
466 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200467 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200468 for (j = iff_size = 0; j < type->info.bits.count; j++) {
469 if (!leaf->value.bit[j]) {
470 continue;
471 }
472 idname = leaf->value.bit[j]->name;
473 iff_size = leaf->value.bit[j]->iffeature_size;
474 iff = leaf->value.bit[j]->iffeature;
475 break;
476nextbit:
477 iff_size = 0;
478 }
479 break;
480 case LY_TYPE_ENUM:
481 id = "Enum";
482 idname = leaf->value_str;
483 iff_size = leaf->value.enm->iffeature_size;
484 iff = leaf->value.enm->iffeature;
485 break;
486 case LY_TYPE_IDENT:
487 id = "Identity";
488 idname = leaf->value_str;
489 iff_size = leaf->value.ident->iffeature_size;
490 iff = leaf->value.ident->iffeature;
491 break;
492 default:
493 iff_size = 0;
494 break;
495 }
496
497 if (iff_size) {
498 for (i = 0; i < iff_size; i++) {
499 if (!resolve_iffeature(&iff[i])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100500 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
501 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its if-feature condition.",
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200502 id, idname);
Michal Vasko53b7da02018-02-13 15:28:42 +0100503 return 1;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200504 }
505 }
506 if (leaf->value_type == LY_TYPE_BITS) {
507 goto nextbit;
508 }
509 }
510 }
511
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100512 /* check must conditions */
513 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 +0000514 i = resolve_applies_must(node);
Michal Vasko53b7da02018-02-13 15:28:42 +0100515 if ((i & 0x1) && unres_data_add(unres, node, UNRES_MUST)) {
516 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000517 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100518 if ((i & 0x2) && unres_data_add(unres, node, UNRES_MUST_INOUT)) {
519 return 1;
Michal Vasko4b5b6252016-10-11 12:18:00 +0000520 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200521 }
522
Michal Vasko53b7da02018-02-13 15:28:42 +0100523 return 0;
524}
525
526int
527lyv_multicases(struct lyd_node *node, struct lys_node *schemanode, struct lyd_node **first_sibling,
528 int autodelete, struct lyd_node *nodel)
529{
530 struct lys_node *sparent, *schoice, *scase, *saux;
531 struct lyd_node *next, *iter;
532 assert(node || schemanode);
533
534 if (!schemanode) {
535 schemanode = node->schema;
536 }
537
538 sparent = lys_parent(schemanode);
539 if (!sparent || !(sparent->nodetype & (LYS_CHOICE | LYS_CASE))) {
540 /* node is not under any choice */
541 return 0;
542 } else if (!first_sibling || !(*first_sibling)) {
543 /* nothing to check */
544 return 0;
545 }
546
547 /* remember which case to skip in which choice */
548 if (sparent->nodetype == LYS_CHOICE) {
549 schoice = sparent;
550 scase = schemanode;
551 } else {
552 schoice = lys_parent(sparent);
553 scase = sparent;
554 }
555
556autodelete:
557 /* remove all nodes from other cases than 'sparent' */
558 LY_TREE_FOR_SAFE(*first_sibling, next, iter) {
559 if (schemanode == iter->schema) {
560 continue;
561 }
562
563 sparent = lys_parent(iter->schema);
564 if (sparent && ((sparent->nodetype == LYS_CHOICE && sparent == schoice) /* another implicit case */
565 || (sparent->nodetype == LYS_CASE && sparent != scase && lys_parent(sparent) == schoice)) /* another case */
566 ) {
567 if (autodelete) {
568 if (iter == nodel) {
569 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, LY_VLOG_LYD, iter, schoice->name);
570 return 2;
571 }
572 if (iter == *first_sibling) {
573 *first_sibling = next;
574 }
575 lyd_free(iter);
576 } else {
577 LOGVAL(schemanode->module->ctx, LYE_MCASEDATA, node ? LY_VLOG_LYD : LY_VLOG_NONE, node, schoice->name);
578 return 1;
579 }
580 }
581 }
582
583 if (*first_sibling && (saux = lys_parent(schoice)) && (saux->nodetype & LYS_CASE)) {
584 /* go recursively in case of nested choices */
585 schoice = lys_parent(saux);
586 scase = saux;
587 goto autodelete;
588 }
589
590 return 0;
Radek Krejcieab784a2015-08-27 09:56:53 +0200591}