blob: 78eb87d21138256080d4c954ffe96681a5c25552 [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
Michal Vaskob1b19442016-07-13 12:26:01 +020028int
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 Krejci4a49bdf2016-01-12 17:17:01 +010055
Michal Vaskocf024702015-10-08 15:01:42 +020056 assert(node);
Radek Krejci03b71f72016-03-16 11:10:09 +010057 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +020058
59 /* check if the node instance is enabled by if-feature */
Michal Vaskocf024702015-10-08 15:01:42 +020060 if (lys_is_disabled(node->schema, 2)) {
Radek Krejci48464ed2016-03-17 15:44:09 +010061 LOGVAL(LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
Michal Vaskocf024702015-10-08 15:01:42 +020062 return EXIT_FAILURE;
63 }
64
Radek Krejci0b7704f2016-03-18 12:16:14 +010065 /* check leafref/instance-identifier */
66 if ((node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) &&
Radek Krejci92ece002016-04-04 15:45:05 +020067 !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Radek Krejci0b7704f2016-03-18 12:16:14 +010068 /* remove possible unres flags from type */
69 ((struct lyd_node_leaf_list *)node)->value_type &= LY_DATA_TYPE_MASK;
70
71 /* if leafref or instance-identifier, store the node for later resolving */
Radek Krejci0562dbc2016-04-18 14:18:26 +020072 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_LEAFREF &&
73 !((struct lyd_node_leaf_list *)node)->value.leafref) {
Radek Krejci0b7704f2016-03-18 12:16:14 +010074 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
75 return EXIT_FAILURE;
76 }
77 } else if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_INST) {
78 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
79 return EXIT_FAILURE;
80 }
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 */
Radek Krejci0b7704f2016-03-18 12:16:14 +010085 if ((!(options & LYD_OPT_TYPEMASK) || (options & LYD_OPT_CONFIG)) && (node->when_status & LYD_WHEN)) {
86 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_WHEN)) {
Michal Vasko0d182ba2015-10-09 09:29:14 +020087 return EXIT_FAILURE;
88 }
Radek Krejcieab784a2015-08-27 09:56:53 +020089 }
90
91 /* check for (non-)presence of status data in edit-config data */
Radek Krejci4a49bdf2016-01-12 17:17:01 +010092 if ((options & (LYD_OPT_EDIT | LYD_OPT_GETCONFIG | LYD_OPT_CONFIG)) && (node->schema->flags & LYS_CONFIG_R)) {
Radek Krejci48464ed2016-03-17 15:44:09 +010093 LOGVAL(LYE_INELEM, LY_VLOG_LYD, node, node->schema->name);
Radek Krejcieab784a2015-08-27 09:56:53 +020094 return EXIT_FAILURE;
95 }
96
Radek Krejci4a49bdf2016-01-12 17:17:01 +010097 /* check elements order in case of RPC's input and output */
Michal Vaskob1b19442016-07-13 12:26:01 +020098 if (node->validity && lyp_is_rpc_action(node->schema)) {
Michal Vasko15e0bab2016-02-24 13:58:21 +010099 if ((node->prev != node) && node->prev->next) {
Michal Vaskodcf98e62016-05-05 17:53:53 +0200100 for (siter = lys_getnext(node->schema, lys_parent(node->schema), node->schema->module, 0);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100101 siter;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200102 siter = lys_getnext(siter, lys_parent(siter), siter->module, 0)) {
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100103 if (siter == node->prev->schema) {
104 /* data predecessor has the schema node after
105 * the schema node of the data node being checked */
Radek Krejci48464ed2016-03-17 15:44:09 +0100106 LOGVAL(LYE_INORDER, LY_VLOG_LYD, node, node->schema->name, siter->name);
Radek Krejci6baaa9a2016-02-23 16:07:12 +0100107 return EXIT_FAILURE;
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100108 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100109 }
110
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100111 }
112 }
113
Radek Krejcieab784a2015-08-27 09:56:53 +0200114 return EXIT_SUCCESS;
115}
Michal Vaskocf024702015-10-08 15:01:42 +0200116
Radek Krejci63b79c82016-08-10 10:09:33 +0200117struct eq_item {
118 struct lyd_node *node;
119 uint32_t hash;
120 uint32_t over;
121};
122
123static int
124eq_table_insert(struct eq_item *table, struct lyd_node *node, uint32_t hash, uint32_t tablesize, int action)
125{
126 uint32_t i, c;
127
128 if (table[hash].node) {
129 /* is it collision or is the cell just filled by an overflow item? */
130 for (i = hash; table[i].node && table[i].hash != hash; i = (i + 1) % tablesize);
131 if (!table[i].node) {
132 goto first;
133 }
134
135 /* collision or instance duplication */
136 c = table[i].over;
137 do {
138 if (table[i].hash != hash) {
139 i = (i + 1) % tablesize;
140 continue;
141 }
142
143 /* compare nodes */
144 if (lyd_list_equal(node, table[i].node, action, 1)) {
145 /* instance duplication */
146 return EXIT_FAILURE;
147 }
148 } while (c--);
149
150 /* collision, insert item into next free cell */
151 table[hash].over++;
152 for (i = (i + 1) % tablesize; table[i].node; i = (i + 1) % tablesize);
153 table[i].hash = hash;
154 table[i].node = node;
155 } else {
156first:
157 /* first hash instance */
158 table[hash].node = node;
159 table[hash].hash = hash;
160 }
161
162 return EXIT_SUCCESS;
163}
164
165int
166lyv_data_unique(struct lyd_node *node, struct lyd_node *start)
167{
168 struct lyd_node *diter, *key;
169 struct lys_node_list *slist;
170 struct ly_set *set;
171 int i, j, n = 0, ret = EXIT_SUCCESS;
172 uint32_t hash, u, usize = 0, hashmask;
173 struct eq_item *keystable = NULL, **uniquetables = NULL;
174 const char *id;
175
176 /* get the first list/leaflist instance sibling */
177 if (!start) {
178 start = lyd_first_sibling(node);
179 }
180
181 /* check uniqueness of the list/leaflist instances (compare values) */
182 set = ly_set_new();
183 for (diter = start; diter; diter = diter->next) {
184 if (diter->schema != node->schema) {
185 /* check only instances of the same list/leaflist */
186 continue;
187 }
188
189 /* remove the flag */
190 diter->validity &= ~LYD_VAL_UNIQUE;
191
192 /* store for comparison */
193 ly_set_add(set, diter, LY_SET_OPT_USEASLIST);
194 }
195
196 if (set->number == 2) {
197 /* simple comparison */
198 if (lyd_list_equal(set->set.d[0], set->set.d[1], -1, 1)) {
199 /* instance duplication */
200 ly_set_free(set);
201 return EXIT_FAILURE;
202 }
203 } else if (set->number > 2) {
204 /* use hashes for comparison */
205 /* first, allocate the table, the size depends on number of items in the set */
206 for (u = 31; u > 0; u--) {
207 usize = set->number << u;
208 usize = usize >> u;
209 if (usize == set->number) {
210 break;
211 }
212 }
213 if (u == 0) {
214 usize = hashmask = 0xffffffff;
215 } else {
216 u = 32 - u;
217 usize = 1 << u;
218 hashmask = usize - 1;
219 }
220 keystable = calloc(usize, sizeof *keystable);
221 if (!keystable) {
222 LOGMEM;
223 ret = EXIT_FAILURE;
224 goto unique_cleanup;
225 }
226 n = 0;
227 if (node->schema->nodetype == LYS_LIST) {
228 n = ((struct lys_node_list *)node->schema)->unique_size;
229 uniquetables = malloc(n * sizeof *uniquetables);
230 if (!uniquetables) {
231 LOGMEM;
232 ret = EXIT_FAILURE;
233 goto unique_cleanup;
234 }
235 for (j = 0; j < n; j++) {
236 uniquetables[j] = calloc(usize, sizeof **uniquetables);
237 if (!uniquetables[j]) {
238 LOGMEM;
239 ret = EXIT_FAILURE;
240 goto unique_cleanup;
241 }
242 }
243 }
244
245 for (u = 0; u < set->number; u++) {
246 /* get the hash for the instance - keys */
247 if (node->schema->nodetype == LYS_LEAFLIST) {
248 id = ((struct lyd_node_leaf_list *)set->set.d[u])->value_str;
249 hash = dict_hash_multi(0, id, strlen(id));
250 } else { /* LYS_LIST */
251 for (hash = i = 0, key = set->set.d[u]->child;
252 i < ((struct lys_node_list *)set->set.d[u]->schema)->keys_size;
253 i++, key = key->next) {
254 id = ((struct lyd_node_leaf_list *)key)->value_str;
255 hash = dict_hash_multi(hash, id, strlen(id));
256 }
257 }
258 /* finish the hash value */
259 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
260
261 /* insert into the hashtable */
262 if (eq_table_insert(keystable, set->set.d[u], hash, usize, 0)) {
263 ret = EXIT_FAILURE;
264 goto unique_cleanup;
265 }
266
267 /* and the same loop for unique (n is !0 only in case of list) - get the hash for the instances */
268 for (j = 0; j < n; j++) {
269 slist = (struct lys_node_list *)node->schema;
270 for (i = hash = 0; i < slist->unique[j].expr_size; i++) {
271 diter = resolve_data_descendant_schema_nodeid(slist->unique[j].expr[i], set->set.d[u]->child);
272 if (diter) {
273 id = ((struct lyd_node_leaf_list *)diter)->value_str;
274 } else {
275 /* use default value */
276 id = lyd_get_default(slist->unique[i].expr[j], set->set.d[u]);
277 if (ly_errno) {
278 ret = EXIT_FAILURE;
279 goto unique_cleanup;
280 }
281 }
282 hash = dict_hash_multi(hash, id, strlen(id));
283 }
284
285 /* finish the hash value */
286 hash = dict_hash_multi(hash, NULL, 0) & hashmask;
287
288 /* insert into the hashtable */
289 if (eq_table_insert(uniquetables[j], set->set.d[u], hash, usize, j + 1)) {
290 ret = EXIT_FAILURE;
291 goto unique_cleanup;
292 }
293 }
294 }
295 }
296
297unique_cleanup:
298 /* cleanup */
299 ly_set_free(set);
300 free(keystable);
301 for (j = 0; j < n; j++) {
302 if (!uniquetables[j]) {
303 /* failed when allocating uniquetables[j], following j are not allocated */
304 break;
305 }
306 free(uniquetables[j]);
307 }
308 free(uniquetables);
309
310 return ret;
311}
312
Radek Krejcieab784a2015-08-27 09:56:53 +0200313int
Radek Krejci48464ed2016-03-17 15:44:09 +0100314lyv_data_content(struct lyd_node *node, int options, struct unres_data *unres)
Radek Krejcieab784a2015-08-27 09:56:53 +0200315{
Michal Vasko1e62a092015-12-01 12:27:20 +0100316 const struct lys_node *schema, *siter;
Radek Krejcid788a522016-07-25 14:57:38 +0200317 struct lyd_node *diter, *start = NULL;
Radek Krejcicf509982015-12-15 09:22:44 +0100318 struct lys_ident *ident;
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100319 struct lys_tpdf *tpdf;
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200320 struct lys_type *type;
321 struct lyd_node_leaf_list *leaf;
322 int i, j;
323 uint8_t iff_size;
324 struct lys_iffeature *iff;
325 const char *id, *idname;
Radek Krejcieab784a2015-08-27 09:56:53 +0200326
327 assert(node);
328 assert(node->schema);
Radek Krejci0b7704f2016-03-18 12:16:14 +0100329 assert(unres);
Radek Krejcieab784a2015-08-27 09:56:53 +0200330
331 schema = node->schema; /* shortcut */
332
Radek Krejcid788a522016-07-25 14:57:38 +0200333 if (node->validity & LYD_VAL_MAND) {
Radek Krejci702deb82016-03-09 12:37:57 +0100334 /* check presence and correct order of all keys in case of list */
Radek Krejci92ece002016-04-04 15:45:05 +0200335 if (schema->nodetype == LYS_LIST && !(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100336 if (lyv_keys(node)) {
Radek Krejcica7efb72016-01-18 13:06:01 +0100337 return EXIT_FAILURE;
Radek Krejcieab784a2015-08-27 09:56:53 +0200338 }
339 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200340
Radek Krejcid788a522016-07-25 14:57:38 +0200341 /* check for mandatory children */
Radek Krejcica7efb72016-01-18 13:06:01 +0100342 if ((schema->nodetype & (LYS_CONTAINER | LYS_LIST))
Michal Vaskob1b19442016-07-13 12:26:01 +0200343 && !(options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG | LYD_OPT_ACTION))) {
Michal Vasko98a5a742016-05-11 11:02:56 +0200344 if (ly_check_mandatory(node, NULL, (options & LYD_OPT_TYPEMASK) ? 0 : 1, (options & LYD_OPT_RPCREPLY) ? 1 : 0)) {
Radek Krejcica7efb72016-01-18 13:06:01 +0100345 return EXIT_FAILURE;
Radek Krejci3e0addb2015-08-27 16:37:59 +0200346 }
Radek Krejcid788a522016-07-25 14:57:38 +0200347 } else if (schema->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_ANYXML)) {
348 /* check number of instances (similar to list uniqueness) for non-list nodes */
Radek Krejci3e0addb2015-08-27 16:37:59 +0200349
Radek Krejcica7efb72016-01-18 13:06:01 +0100350 /* find duplicity */
Radek Krejcid788a522016-07-25 14:57:38 +0200351 start = lyd_first_sibling(node);
Radek Krejcica7efb72016-01-18 13:06:01 +0100352 for (diter = start; diter; diter = diter->next) {
353 if (diter->schema == schema && diter != node) {
Radek Krejci92ece002016-04-04 15:45:05 +0200354 LOGVAL(LYE_TOOMANY, LY_VLOG_LYD, node, schema->name,
Michal Vaskodcf98e62016-05-05 17:53:53 +0200355 lys_parent(schema) ? lys_parent(schema)->name : "data tree");
Radek Krejci92ece002016-04-04 15:45:05 +0200356 return EXIT_FAILURE;
Radek Krejcieab784a2015-08-27 09:56:53 +0200357 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200358 }
Radek Krejcid788a522016-07-25 14:57:38 +0200359 }
Radek Krejcieab784a2015-08-27 09:56:53 +0200360
Radek Krejcid788a522016-07-25 14:57:38 +0200361 /* remove the flag */
362 node->validity &= ~LYD_VAL_MAND;
363 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100364
Radek Krejci63b79c82016-08-10 10:09:33 +0200365 if (!(options & (LYD_OPT_GET | LYD_OPT_GETCONFIG))) {
366 /* skip key uniqueness check in case of get/get-config data */
367 if (schema->nodetype & (LYS_LIST | LYS_CONTAINER)) {
368 LY_TREE_FOR(schema->child, siter) {
369 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
370 LY_TREE_FOR(node->child, diter) {
371 if (diter->schema == siter && (diter->validity & LYD_VAL_UNIQUE)) {
372 if (lyv_data_unique(diter, node->child)) {
373 return EXIT_FAILURE;
374 }
375 /* all schema instances checked, continue with another schema node */
376 break;
377 }
378 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100379 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100380 }
381 }
Radek Krejcid788a522016-07-25 14:57:38 +0200382 }
383
384 if (node->validity) {
Radek Krejcica7efb72016-01-18 13:06:01 +0100385 /* status - of the node's schema node itself and all its parents that
386 * cannot have their own instance (like a choice statement) */
387 siter = node->schema;
388 do {
389 if (((siter->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) && (options & LYD_OPT_OBSOLETE)) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100390 LOGVAL(LYE_OBSDATA, LY_VLOG_LYD, node, schema->name);
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100391 return EXIT_FAILURE;
392 }
Michal Vaskodcf98e62016-05-05 17:53:53 +0200393 siter = lys_parent(siter);
394 } while (siter && !(siter->nodetype & (LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_ANYXML)));
Radek Krejcica7efb72016-01-18 13:06:01 +0100395
396 /* status of the identity value */
397 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
398 if (options & LYD_OPT_OBSOLETE) {
399 /* check that we are not instantiating obsolete type */
400 tpdf = ((struct lys_node_leaf *)node->schema)->type.der;
Michal Vaskodcf98e62016-05-05 17:53:53 +0200401 while (tpdf) {
Radek Krejcica7efb72016-01-18 13:06:01 +0100402 if ((tpdf->flags & LYS_STATUS_MASK) == LYS_STATUS_OBSLT) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100403 LOGVAL(LYE_OBSTYPE, LY_VLOG_LYD, node, schema->name, tpdf->name);
Radek Krejcica7efb72016-01-18 13:06:01 +0100404 return EXIT_FAILURE;
405 }
406 tpdf = tpdf->type.der;
407 }
408 }
409 if (((struct lyd_node_leaf_list *)node)->value_type == LY_TYPE_IDENT) {
410 ident = ((struct lyd_node_leaf_list *)node)->value.ident;
Radek Krejcic6556022016-01-27 15:16:45 +0100411 if (lyp_check_status(schema->flags, schema->module, schema->name,
Radek Krejci3cc10962016-04-13 15:03:27 +0200412 ident->flags, ident->module, ident->name, NULL)) {
413 LOGPATH(LY_VLOG_LYD, node);
Radek Krejcica7efb72016-01-18 13:06:01 +0100414 return EXIT_FAILURE;
415 }
416 }
Radek Krejci4eaf5a82015-12-15 15:10:38 +0100417 }
Radek Krejcicf509982015-12-15 09:22:44 +0100418 }
419
Radek Krejcif1ee2e22016-08-02 16:36:48 +0200420 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
421 /* since feature can be enabled/disabled, do this check despite the validity flag,
422 * - check if the type value (enum, bit, identity) is disabled via feature */
423 leaf = (struct lyd_node_leaf_list *)node;
424 switch (leaf->value_type) {
425 case LY_TYPE_BITS:
426 id = "Bit";
427 /* get the count of bits */
428 for (type = &((struct lys_node_leaf *)leaf->schema)->type; !type->info.bits.count; type = &type->der->type);
429 for (j = iff_size = 0; j < type->info.bits.count; j++) {
430 if (!leaf->value.bit[j]) {
431 continue;
432 }
433 idname = leaf->value.bit[j]->name;
434 iff_size = leaf->value.bit[j]->iffeature_size;
435 iff = leaf->value.bit[j]->iffeature;
436 break;
437nextbit:
438 iff_size = 0;
439 }
440 break;
441 case LY_TYPE_ENUM:
442 id = "Enum";
443 idname = leaf->value_str;
444 iff_size = leaf->value.enm->iffeature_size;
445 iff = leaf->value.enm->iffeature;
446 break;
447 case LY_TYPE_IDENT:
448 id = "Identity";
449 idname = leaf->value_str;
450 iff_size = leaf->value.ident->iffeature_size;
451 iff = leaf->value.ident->iffeature;
452 break;
453 default:
454 iff_size = 0;
455 break;
456 }
457
458 if (iff_size) {
459 for (i = 0; i < iff_size; i++) {
460 if (!resolve_iffeature(&iff[i])) {
461 LOGVAL(LYE_INVAL, LY_VLOG_LYD, node, leaf->value_str, schema->name);
462 LOGVAL(LYE_SPEC, LY_VLOG_LYD, node, "%s \"%s\" is disabled by its if-feature condition.",
463 id, idname);
464 return EXIT_FAILURE;
465 }
466 }
467 if (leaf->value_type == LY_TYPE_BITS) {
468 goto nextbit;
469 }
470 }
471 }
472
Michal Vaskobf19d252015-10-08 15:39:17 +0200473 /* check must conditions */
Radek Krejci01696bf2016-03-18 13:19:36 +0100474 if (resolve_applies_must(node) && unres_data_add(unres, node, UNRES_MUST) == -1) {
Radek Krejci0b7704f2016-03-18 12:16:14 +0100475 return EXIT_FAILURE;
Michal Vaskobf19d252015-10-08 15:39:17 +0200476 }
477
Radek Krejcieab784a2015-08-27 09:56:53 +0200478 return EXIT_SUCCESS;
479}