blob: f1fe1cdec4f49eae210b835f80d0c160fc3f7b0a [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 */
Radek Krejci48464ed2016-03-17 15:44:09 +010038 LOGVAL(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]) {
Radek Krejci48464ed2016-03-17 15:44:09 +010041 LOGVAL(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 }
Radek Krejci702deb82016-03-09 12:37:57 +010045 return EXIT_FAILURE;
Radek Krejcib1c12512015-08-11 11:22:04 +020046 }
47 }
Radek Krejcib1c12512015-08-11 11:22:04 +020048 return EXIT_SUCCESS;
49}
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;
Radek Krejci4a49bdf2016-01-12 17:17:01 +010056
Michal Vaskocf024702015-10-08 15:01:42 +020057 assert(node);
Radek Krejci03b71f72016-03-16 11:10:09 +010058 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +020059
60 /* check if the node instance is enabled by if-feature */
Michal Vaskocf024702015-10-08 15:01:42 +020061 if (lys_is_disabled(node->schema, 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +010062 LOGVAL(LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
Michal Vaskocf024702015-10-08 15:01:42 +020063 return EXIT_FAILURE;
64 }
65
Radek Krejcib1f318b2016-08-22 16:18:37 +020066 if (node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +010067 /* if union with leafref/intsid, leafref itself (invalid) or instance-identifier, store the node for later resolving */
68 if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_UNION)
69 && ((struct lys_node_leaf *)leaf->schema)->type.info.uni.has_ptr_type) {
70 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
71 return EXIT_FAILURE;
Radek Krejci0b7704f2016-03-18 12:16:14 +010072 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +010073 } else if ((((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_LEAFREF) && (leaf->validity & LYD_VAL_LEAFREF)) {
74 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
75 return EXIT_FAILURE;
76 }
77 } else if (((struct lys_node_leaf *)leaf->schema)->type.base == LY_TYPE_INST) {
78 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
79 return EXIT_FAILURE;
Radek Krejci0b7704f2016-03-18 12:16:14 +010080 }
Michal Vasko0d182ba2015-10-09 09:29:14 +020081 }
Radek Krejci0b7704f2016-03-18 12:16:14 +010082 }
83
Michal Vaskocf024702015-10-08 15:01:42 +020084 /* check all relevant when conditions */
Michal Vaskoebf7df22017-03-28 16:08:07 +020085 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))
86 && (node->when_status & LYD_WHEN)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +010087 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko0d182ba2015-10-09 09:29:14 +020088 return EXIT_FAILURE;
89 }
Radek Krejcieab784a2015-08-27 09:56:53 +020090 }
91
92 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +010093 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Radek Krejci48464ed2016-03-17 15:44:09 +010094 LOGVAL(LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
Radek Krejcieab784a2015-08-27 09:56:53 +020095 return EXIT_FAILURE;
96 }
97
Radek Krejci4a49bdf2016-01-12 17:17:01 +010098 /* check elements order in case of RPC's input and output */
Michal Vaskoad2e44a2017-01-03 10:31:35 +010099 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 +0100100 if ((node->prev != node) && node->prev->next) {
Michal Vasko9e780492017-03-28 14:48:31 +0200101 for (siter = lys_getnext(node->schema, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100102 siter;
Michal Vasko9e780492017-03-28 14:48:31 +0200103 siter = lys_getnext(siter, lys_parent(node->schema), lyd_node_module(node), LYS_GETNEXT_PARENTUSES)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100104 if (siter == node->prev->schema) {
105 /* data predecessor has the schema node after
106 * the schema node of the data node being checked */
Radek Krejci48464ed2016-03-17 15:44:09 +0100107 LOGVAL(LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100108 return EXIT_FAILURE;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100109 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100110 }
111
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100112 }
113 }
114
Radek Krejcieab784a2015-08-27 09:56:53 +0200115 return EXIT_SUCCESS;
116}
Michal Vaskocf024702015-10-08 15:01:42 +0200117
Radek Krejci63b79c82016-08-10 10:09:33 +0200118struct eq_item {
119 struct lyd_node *node;
120 uint32_t hash;
121 uint32_t over;
122};
123
124static int
125eq_table_insert(struct eq_item *table, struct lyd_node *node, uint32_t hash, uint32_t tablesize, int action)
126{
127 uint32_t i, c;
128
129 if (table[hash].node) {
130 /* is it collision or is the cell just filled by an overflow item? */
131 for (i = hash; table[i].node && table[i].hash != hash; i = (i + 1) % tablesize);
132 if (!table[i].node) {
133 goto first;
134 }
135
136 /* collision or instance duplication */
137 c = table[i].over;
138 do {
139 if (table[i].hash != hash) {
140 i = (i + 1) % tablesize;
141 continue;
142 }
143
144 /* compare nodes */
Michal Vaskoe6ff4282017-02-07 15:13:36 +0100145 if (lyd_list_equal(node, table[i].node, action, 0, 1)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200146 /* instance duplication */
147 return EXIT_FAILURE;
148 }
149 } while (c--);
150
151 /* collision, insert item into next free cell */
152 table[hash].over++;
153 for (i = (i + 1) % tablesize; table[i].node; i = (i + 1) % tablesize);
154 table[i].hash = hash;
155 table[i].node = node;
156 } else {
157first:
158 /* first hash instance */
159 table[hash].node = node;
160 table[hash].hash = hash;
161 }
162
163 return EXIT_SUCCESS;
164}
165
166int
167lyv_data_unique(struct lyd_node *node, struct lyd_node *start)
168{
169 struct lyd_node *diter, *key;
170 struct lys_node_list *slist;
171 struct ly_set *set;
172 int i, j, n = 0, ret = EXIT_SUCCESS;
173 uint32_t hash, u, usize = 0, hashmask;
174 struct eq_item *keystable = NULL, **uniquetables = NULL;
175 const char *id;
176
177 /* get the first list/leaflist instance sibling */
178 if (!start) {
179 start = lyd_first_sibling(node);
180 }
181
182 /* check uniqueness of the list/leaflist instances (compare values) */
183 set = ly_set_new();
184 for (diter = start; diter; diter = diter->next) {
185 if (diter->schema != node->schema) {
186 /* check only instances of the same list/leaflist */
187 continue;
188 }
189
190 /* remove the flag */
191 diter->validity &= ~LYD_VAL_UNIQUE;
192
193 /* store for comparison */
194 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
195 }
196
197 if (set->number == 2) {
198 /* simple comparison */
Michal Vaskoe6ff4282017-02-07 15:13:36 +0100199 if (lyd_list_equal(set->set.d[0], set->set.d[1], -1, 0, 1)) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200200 /* instance duplication */
201 ly_set_free(set);
202 return EXIT_FAILURE;
203 }
204 } else if (set->number > 2) {
205 /* use hashes for comparison */
206 /* first, allocate the table, the size depends on number of items in the set */
207 for (u = 31; u > 0; u--) {
208 usize = set->number << u;
209 usize = usize >> u;
210 if (usize == set->number) {
211 break;
212 }
213 }
214 if (u == 0) {
215 usize = hashmask = 0xffffffff;
216 } else {
217 u = 32 - u;
218 usize = 1 << u;
219 hashmask = usize - 1;
220 }
221 keystable = calloc(usize, sizeof *keystable);
222 if (!keystable) {
223 LOGMEM;
224 ret = EXIT_FAILURE;
225 goto unique_cleanup;
226 }
227 n = 0;
228 if (node->schema->nodetype == LYS_LIST) {
229 n = ((struct lys_node_list *)node->schema)->unique_size;
230 uniquetables = malloc(n * sizeof *uniquetables);
231 if (!uniquetables) {
232 LOGMEM;
233 ret = EXIT_FAILURE;
Radek Krejci70292d22016-08-15 09:39:22 +0200234 n = 0;
Radek Krejci63b79c82016-08-10 10:09:33 +0200235 goto unique_cleanup;
236 }
237 for (j = 0; j < n; j++) {
238 uniquetables[j] = calloc(usize, sizeof **uniquetables);
239 if (!uniquetables[j]) {
240 LOGMEM;
241 ret = EXIT_FAILURE;
242 goto unique_cleanup;
243 }
244 }
245 }
246
247 for (u = 0; u < set->number; u++) {
248 /* get the hash for the instance - keys */
249 if (node->schema->nodetype == LYS_LEAFLIST) {
250 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
251 hash = dict_hash_multi(0, id, strlen(id));
252 } else { /* LYS_LIST */
253 for (hash = i = 0, key = set->set.d[u]->child;
254 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
255 i++, key = key->next) {
256 id = ((struct lyd_node_leaf_list *)key)->value_str;
257 hash = dict_hash_multi(hash, id, strlen(id));
258 }
259 }
260 /* finish the hash value */
261 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
262
263 /* insert into the hashtable */
264 if (eq_table_insert(keystable, set->set.d[u], hash, usize, 0)) {
265 ret = EXIT_FAILURE;
266 goto unique_cleanup;
267 }
268
269 /* and the same loop for unique (n is !0 only in case of list) - get the hash for the instances */
270 for (j = 0; j < n; j++) {
271 slist = (struct lys_node_list *)node->schema;
Radek Krejci50dc7ae2016-09-01 09:56:37 +0200272 id = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +0200273 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
274 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
275 if (diter) {
276 id = ((struct lyd_node_leaf_list *)diter)->value_str;
277 } else {
278 /* use default value */
Radek Krejcid5a5c282016-08-15 15:38:08 +0200279 id = lyd_get_unique_default(slist->unique[j].expr[i], set->set.d[u]);
Radek Krejci63b79c82016-08-10 10:09:33 +0200280 if (ly_errno) {
281 ret = EXIT_FAILURE;
282 goto unique_cleanup;
283 }
284 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200285 if (!id) {
286 /* unique item not present nor has default value */
287 break;
288 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200289 hash = dict_hash_multi(hash, id, strlen(id));
290 }
Radek Krejci2a5f52b2016-08-15 09:14:36 +0200291 if (!id) {
292 /* skip this list instance since its unique set is incomplete */
293 continue;
294 }
Radek Krejci63b79c82016-08-10 10:09:33 +0200295
296 /* finish the hash value */
297 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
298
299 /* insert into the hashtable */
300 if (eq_table_insert(uniquetables[j], set->set.d[u], hash, usize, j + 1)) {
301 ret = EXIT_FAILURE;
302 goto unique_cleanup;
303 }
304 }
305 }
306 }
307
308unique_cleanup:
309 /* cleanup */
310 ly_set_free(set);
311 free(keystable);
312 for (j = 0; j < n; j++) {
313 if (!uniquetables[j]) {
314 /* failed when allocating uniquetables[j], following j are not allocated */
315 break;
316 }
317 free(uniquetables[j]);
318 }
319 free(uniquetables);
320
321 return ret;
322}
323
Michal Vasko91ff4592017-05-24 15:41:49 +0200324static struct lys_type *
325find_orig_type(struct lys_type *par_type, LY_DATA_TYPE base_type)
326{
327 struct lys_type *type, *prev_type, *tmp_type;
328 int found;
329
330 /* go through typedefs */
331 for (type = par_type; type->der->type.der; type = &type->der->type);
332
333 if (type->base == base_type) {
334 /* we have the result */
335 return type;
336 } else if (type->base == LY_TYPE_UNION) {
337 /* go through all the union types */
338 prev_type = NULL;
339 found = 0;
340 while ((prev_type = lyp_get_next_union_type(type, prev_type, &found))) {
341 tmp_type = find_orig_type(prev_type, base_type);
342 if (tmp_type) {
343 return tmp_type;
344 }
345 found = 0;
346 }
347 }
348
349 /* not found */
350 return NULL;
351}
352
Radek Krejcieab784a2015-08-27 09:56:53 +0200353int
Radek Krejci48464ed2016-03-17 15:44:09 +0100354lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200355{
Michal Vasko1e62a092015-12-01 12:27:20 +0100356 const struct lys_node *schema, *siter;
Radek Krejcid788a522016-07-25 14:57:38 +0200357 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100358 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100359 struct lys_tpdf *tpdf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200360 struct lys_type *type = NULL;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200361 struct lyd_node_leaf_list *leaf;
Radek Krejcie6a71b52016-08-10 15:11:16 +0200362 int i, j = 0;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200363 uint8_t iff_size;
364 struct lys_iffeature *iff;
365 const char *id, *idname;
Radek Krejcieab784a2015-08-27 09:56:53 +0200366
367 assert(node);
368 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100369 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200370
371 schema = node->schema; /* shortcut */
372
Michal Vasko091dd842017-02-08 14:07:32 +0100373 if (node->validity & LYD_VAL_MAND) {
374 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))) {
375 /* check presence and correct order of all keys in case of list */
376 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
377 if (lyv_keys(node)) {
Radek Krejci92ece002016-04-04 15:45:05 +0200378 return EXIT_FAILURE;
Radek Krejcieab784a2015-08-27 09:56:53 +0200379 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200380 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200381
Michal Vasko091dd842017-02-08 14:07:32 +0100382 if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYDATA)) {
383 /* check number of instances (similar to list uniqueness) for non-list nodes */
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100384
Michal Vasko091dd842017-02-08 14:07:32 +0100385 /* find duplicity */
386 start = lyd_first_sibling(node);
387 for (diter = start; diter; diter = diter->next) {
388 if (diter->schema == schema && diter != node) {
389 LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
390 lys_parent(schema) ? lys_parent(schema)->name : "data tree");
391 return EXIT_FAILURE;
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100392 }
393 }
Michal Vasko091dd842017-02-08 14:07:32 +0100394 }
395
396 if (options & LYD_OPT_OBSOLETE) {
397 /* status - of the node's schema node itself and all its parents that
398 * cannot have their own instance (like a choice statement) */
399 siter = node->schema;
400 do {
401 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
402 LOGVAL(LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100403 return EXIT_FAILURE;
404 }
Michal Vasko091dd842017-02-08 14:07:32 +0100405 siter = lys_parent(siter);
406 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYDATA)));
407
408 /* status of the identity value */
409 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
410 if (options & LYD_OPT_OBSOLETE) {
411 /* check that we are not instantiating obsolete type */
412 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
413 while (tpdf) {
414 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
415 LOGVAL(LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
416 return EXIT_FAILURE;
417 }
418 tpdf = tpdf->type.der;
419 }
420 }
421 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
422 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
423 if (lyp_check_status(schema->flags, schema->module, schema->name,
424 ident->flags, ident->module, ident->name, NULL)) {
425 LOGPATH(LY_VLOG_LYD, node);
426 return EXIT_FAILURE;
427 }
428 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +0100429 }
430 }
431 }
432
Radek Krejcid788a522016-07-25 14:57:38 +0200433 /* remove the flag */
434 node->validity &= ~LYD_VAL_MAND;
435 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100436
Michal Vaskob1bc1d92017-01-05 11:47:41 +0100437 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Radek Krejci63b79c82016-08-10 10:09:33 +0200438 /* skip key uniqueness check in case of get/get-config data */
439 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER)) {
440 LY_TREE_FOR(schema->child, siter) {
441 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
442 LY_TREE_FOR(node->child, diter) {
443 if (diter->schema == siter && (diter->validity & LYD_VAL_UNIQUE)) {
444 if (lyv_data_unique(diter, node->child)) {
445 return EXIT_FAILURE;
446 }
447 /* all schema instances checked, continue with another schema node */
448 break;
449 }
450 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100451 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100452 }
453 }
Radek Krejcid788a522016-07-25 14:57:38 +0200454 }
455
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200456 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
457 /* since feature can be enabled/disabled, do this check despite the validity flag,
458 * - check if the type value (enum, bit, identity) is disabled via feature */
459 leaf = (struct lyd_node_leaf_list *)node;
460 switch (leaf->value_type) {
461 case LY_TYPE_BITS:
462 id = "Bit";
463 /* get the count of bits */
Michal Vasko91ff4592017-05-24 15:41:49 +0200464 type = find_orig_type(&((struct lys_node_leaf *)leaf->schema)->type, LY_TYPE_BITS);
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200465 for (j = iff_size = 0; j < type->info.bits.count; j++) {
466 if (!leaf->value.bit[j]) {
467 continue;
468 }
469 idname = leaf->value.bit[j]->name;
470 iff_size = leaf->value.bit[j]->iffeature_size;
471 iff = leaf->value.bit[j]->iffeature;
472 break;
473nextbit:
474 iff_size = 0;
475 }
476 break;
477 case LY_TYPE_ENUM:
478 id = "Enum";
479 idname = leaf->value_str;
480 iff_size = leaf->value.enm->iffeature_size;
481 iff = leaf->value.enm->iffeature;
482 break;
483 case LY_TYPE_IDENT:
484 id = "Identity";
485 idname = leaf->value_str;
486 iff_size = leaf->value.ident->iffeature_size;
487 iff = leaf->value.ident->iffeature;
488 break;
489 default:
490 iff_size = 0;
491 break;
492 }
493
494 if (iff_size) {
495 for (i = 0; i < iff_size; i++) {
496 if (!resolve_iffeature(&iff[i])) {
497 LOGVAL(LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
Michal Vasko51e5c582017-01-19 14:16:39 +0100498 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "%s \"%s\" is disabled by its if-feature condition.",
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200499 id, idname);
500 return EXIT_FAILURE;
501 }
502 }
503 if (leaf->value_type == LY_TYPE_BITS) {
504 goto nextbit;
505 }
506 }
507 }
508
Michal Vaskoad2e44a2017-01-03 10:31:35 +0100509 /* check must conditions */
510 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 +0000511 i = resolve_applies_must(node);
512 if ((i & 0x1) && (unres_data_add(unres, node, UNRES_MUST) == -1)) {
513 return EXIT_FAILURE;
514 }
515 if ((i & 0x2) && (unres_data_add(unres, node, UNRES_MUST_INOUT) == -1)) {
516 return EXIT_FAILURE;
517 }
Michal Vaskobf19d252015-10-08 15:39:17 +0200518 }
519
Radek Krejcieab784a2015-08-27 09:56:53 +0200520 return EXIT_SUCCESS;
521}