blob: 9fbfb0e73567cd66c186f4fb268587b1902d7d41 [file] [log] [blame]
Pavol Vican021488a2016-01-25 23:56:12 +01001/**
2 * @file parser_yang.c
3 * @author Pavol Vican
4 * @brief YANG parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
Pavol Vican5de33492016-02-22 14:03:24 +010022#include <ctype.h>
Pavol Vican1c203db2016-02-24 14:05:23 +010023#include <pcre.h>
Pavol Vican021488a2016-01-25 23:56:12 +010024#include "parser_yang.h"
25#include "parser_yang_bis.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010026#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010027#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010028
Pavol Vican2a064652016-02-02 22:54:34 +010029static int
30yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value, int line)
31{
Pavol Vicanbf805472016-01-26 14:24:56 +010032 if (*target) {
Pavol Vicand72227c2016-02-21 20:29:52 +010033 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010034 free(value);
35 return 1;
36 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010037 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010038 return 0;
39 }
40}
41
Pavol Vican2a064652016-02-02 22:54:34 +010042int
43yang_read_common(struct lys_module *module, char *value, int type, int line)
44{
Pavol Vican6eb14e82016-02-03 12:27:13 +010045 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010046
47 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010048 case MODULE_KEYWORD:
49 module->name = lydict_insert_zc(module->ctx, value);
50 break;
51 case NAMESPACE_KEYWORD:
52 ret = yang_check_string(module, &module->ns, "namespace", "module", value, line);
53 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010054 case ORGANIZATION_KEYWORD:
55 ret = yang_check_string(module, &module->org, "organization", "module", value, line);
56 break;
57 case CONTACT_KEYWORD:
58 ret = yang_check_string(module, &module->contact, "contact", "module", value, line);
59 break;
Pavol Vican2a064652016-02-02 22:54:34 +010060 }
61
Pavol Vican021488a2016-01-25 23:56:12 +010062 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010063}
64
Pavol Vican2a064652016-02-02 22:54:34 +010065int
66yang_read_prefix(struct lys_module *module, void *save, char *value, int type, int line)
67{
Pavol Vican6eb14e82016-02-03 12:27:13 +010068 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010069
Pavol Vican6eb14e82016-02-03 12:27:13 +010070 if (lyp_check_identifier(value, LY_IDENT_PREFIX, line, module, NULL)) {
71 free(value);
72 return EXIT_FAILURE;
73 }
Pavol Vicanbf805472016-01-26 14:24:56 +010074 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +010075 case MODULE_KEYWORD:
76 ret = yang_check_string(module, &module->prefix, "prefix", "module", value, line);
77 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010078 case IMPORT_KEYWORD:
79 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
80 break;
Pavol Vican2a064652016-02-02 22:54:34 +010081 }
Pavol Vican6eb14e82016-02-03 12:27:13 +010082
Pavol Vicanbf805472016-01-26 14:24:56 +010083 return ret;
84}
Pavol Vican6eb14e82016-02-03 12:27:13 +010085
86void *
87yang_elem_of_array(void **ptr, uint8_t *act_size, int type, int sizeof_struct)
88{
89 void *retval;
90
91 if (!(*act_size % LY_ARRAY_SIZE) && !(*ptr = ly_realloc(*ptr, (*act_size + LY_ARRAY_SIZE) * sizeof_struct))) {
92 LOGMEM;
93 return NULL;
94 }
95 switch (type) {
96 case IMPORT_KEYWORD:
97 retval = &((struct lys_import *)(*ptr))[*act_size];
98 break;
Pavol Vicanbedff692016-02-03 14:29:17 +010099 case REVISION_KEYWORD:
100 retval = &((struct lys_revision *)(*ptr))[*act_size];
101 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100102 }
103 (*act_size)++;
104 memset(retval,0,sizeof_struct);
105 return retval;
106}
107
108int
109yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value, int line)
110{
Pavol Vican0da132e2016-03-21 12:03:03 +0100111 const char *exp;
112 int rc, i;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100113
Pavol Vican0da132e2016-03-21 12:03:03 +0100114 exp = lydict_insert_zc(module->ctx, value);
115 rc = lyp_check_import(module, exp, line, imp);
116 lydict_remove(module->ctx, exp);
117 if (rc) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100118 goto error;
119 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120
121 /* check duplicities in imported modules */
Pavol Vican0da132e2016-03-21 12:03:03 +0100122 for (i = 0; i < module->imp_size; i++) {
123 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size].module->name)) {
Pavol Vican723de602016-03-21 15:13:20 +0100124 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, module->imp[i].module->name, "import");
125 LOGVAL(LYE_SPEC, 0, 0, NULL, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
Pavol Vican6eb14e82016-02-03 12:27:13 +0100126 goto error;
127 }
128 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100129 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100130 return EXIT_SUCCESS;
131
Pavol Vican0da132e2016-03-21 12:03:03 +0100132error:
133 module->imp_size++;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100134 return EXIT_FAILURE;
135}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100136
137int
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100138yang_read_description(struct lys_module *module, void *node, char *value, char *where, int line)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100139{
140 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100141 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100142
143 if (!node) {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100144 ret = yang_check_string(module, &module->dsc, dsc, "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100145 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100146 if (!strcmp("revision", where)) {
147 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value, line);
148 } else {
149 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100150 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100151 }
152 return ret;
153}
154
155int
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100156yang_read_reference(struct lys_module *module, void *node, char *value, char *where, int line)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100157{
158 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100159 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100160
161 if (!node) {
162 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100163 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100164 if (!strcmp("revision", where)) {
165 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value, line);
166 } else {
167 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100168 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100169 }
170 return ret;
171}
Pavol Vicanbedff692016-02-03 14:29:17 +0100172
173void *
174yang_read_revision(struct lys_module *module, char *value)
175{
176 struct lys_revision *retval;
177
Pavol Vican1eeb1992016-02-09 11:10:45 +0100178 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100179
180 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100181 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100182 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
183 memcpy(module->rev[0].date, value, LY_REV_SIZE);
184 retval->dsc = module->rev[0].dsc;
185 retval->ref = module->rev[0].ref;
186 retval = module->rev;
187 retval->dsc = NULL;
188 retval->ref = NULL;
189 } else {
190 memcpy(retval->date, value, LY_REV_SIZE);
191 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100192 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100193 free(value);
194 return retval;
195}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100196
197int
Pavol Vicana1827962016-02-29 15:39:42 +0100198yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100199{
Pavol Vican45ccc592016-03-09 18:53:48 +0100200 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100201 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
202 LOGMEM;
203 return EXIT_FAILURE;
204 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100205 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100206 }
207 }
208 (*size)++;
209 return EXIT_SUCCESS;
210}
Pavol Vicane1354e92016-02-09 14:02:09 +0100211
212void *
213yang_read_feature(struct lys_module *module, char *value, int line)
214{
215 struct lys_feature *retval;
216
217 /* check uniqueness of feature's names */
218 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
219 goto error;
220 }
221 retval = &module->features[module->features_size];
222 retval->name = lydict_insert_zc(module->ctx, value);
223 retval->module = module;
224 module->features_size++;
225 return retval;
226
227error:
228 free(value);
229 return NULL;
230}
231
232int
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100233yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, int type, int line)
Pavol Vicane1354e92016-02-09 14:02:09 +0100234{
235 const char *exp;
236 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100237 struct lys_feature *f;
238 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100239
240 if (!(exp = transform_schema2json(module, value, line))) {
241 free(value);
242 return EXIT_FAILURE;
243 }
244 free(value);
245
246 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100247 if (type == FEATURE_KEYWORD) {
248 f = (struct lys_feature *) ptr;
249 f->features[f->features_size] = f;
250 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
251 f->features_size++;
252 } else {
253 n = (struct lys_node *) ptr;
254 n->features[n->features_size] = (struct lys_feature *) n;
255 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
256 n->features_size++;
257 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100258
259 lydict_remove(module->ctx, exp);
260 if (ret == -1) {
261
262 return EXIT_FAILURE;
263 }
264 return EXIT_SUCCESS;
265}
266
Pavol Vican4fb66c92016-03-17 10:32:27 +0100267int
Pavol Vicane1354e92016-02-09 14:02:09 +0100268yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
269{
270 if (*flags & mask) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100271 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100272 return EXIT_FAILURE;
273 } else {
Pavol Vican945187f2016-02-11 10:12:33 +0100274 *flags |= value;
Pavol Vicane1354e92016-02-09 14:02:09 +0100275 return EXIT_SUCCESS;
276 }
277}
278
Pavol Vicanbbdef532016-02-09 14:52:12 +0100279void *
280yang_read_identity(struct lys_module *module, char *value)
281{
282 struct lys_ident *ret;
283
284 ret = &module->ident[module->ident_size];
285 ret->name = lydict_insert_zc(module->ctx, value);
286 ret->module = module;
287 module->ident_size++;
288 return ret;
289}
290
291int
292yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
293{
294 const char *exp;
295
Pavol Vicane2368982016-03-19 14:37:56 +0100296 if (!value) {
297 /* base statement not found */
298 return EXIT_SUCCESS;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100299 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100300 exp = transform_schema2json(module, value, line);
301 free(value);
302 if (!exp) {
303 return EXIT_FAILURE;
304 }
305 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
306 lydict_remove(module->ctx, exp);
307 return EXIT_FAILURE;
308 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100309
Pavol Vicanbbdef532016-02-09 14:52:12 +0100310 lydict_remove(module->ctx, exp);
311 return EXIT_SUCCESS;
312}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100313
314void *
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100315yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
316{
317 struct lys_restr *retval;
318
319 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100320 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100321 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100322 break;
323 case ANYXML_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100324 retval = &((struct lys_node_anyxml *)node)->must[((struct lys_node_anyxml *)node)->must_size++];
325 break;
326 case LEAF_KEYWORD:
327 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100328 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100329 case LEAF_LIST_KEYWORD:
330 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
331 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100332 case LIST_KEYWORD:
333 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
334 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100335 case REFINE_KEYWORD:
336 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
337 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100338 case ADD_KEYWORD:
339 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
340 memset(retval, 0, sizeof *retval);
341 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100342 case DELETE_KEYWORD:
343 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
344 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100345 }
346 retval->expr = transform_schema2json(module, value, line);
347 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
348 goto error;
349 }
350 free(value);
351 return retval;
352
353error:
354 free(value);
355 return NULL;
356}
357
358int
Pavol Vicana3436942016-03-21 09:25:52 +0100359yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message, int line)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100360{
361 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100362
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100363 if (message==ERROR_APP_TAG_KEYWORD) {
Pavol Vicana3436942016-03-21 09:25:52 +0100364 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100365 } else {
Pavol Vicana3436942016-03-21 09:25:52 +0100366 ret = yang_check_string(module, &save->emsg, "error_app_tag", what, value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100367 }
368 return ret;
369}
Pavol Vicanb5687112016-02-09 22:35:59 +0100370
371int
372yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
373{
374 if (cont->presence) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100375 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100376 free(value);
377 return EXIT_FAILURE;
378 } else {
379 cont->presence = lydict_insert_zc(module->ctx, value);
380 return EXIT_SUCCESS;
381 }
382}
383
Pavol Vican235dbd42016-02-10 10:34:19 +0100384void *
385yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
386{
387 struct lys_when *retval;
388
389 retval = calloc(1, sizeof *retval);
390 if (!retval) {
391 LOGMEM;
392 free(value);
393 return NULL;
394 }
395 retval->cond = transform_schema2json(module, value, line);
396 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
397 goto error;
398 }
399 switch (type) {
400 case CONTAINER_KEYWORD:
401 if (((struct lys_node_container *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100402 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100403 goto error;
404 }
405 ((struct lys_node_container *)node)->when = retval;
406 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100407 case ANYXML_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100408 if (((struct lys_node_anyxml *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100409 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "anyxml");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100410 goto error;
411 }
412 ((struct lys_node_anyxml *)node)->when = retval;
413 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100414 case CHOICE_KEYWORD:
415 if (((struct lys_node_choice *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100416 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100417 goto error;
418 }
419 ((struct lys_node_choice *)node)->when = retval;
420 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100421 case CASE_KEYWORD:
422 if (((struct lys_node_case *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100423 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100424 goto error;
425 }
426 ((struct lys_node_case *)node)->when = retval;
427 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100428 case LEAF_KEYWORD:
429 if (((struct lys_node_leaf *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100430 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100431 goto error;
432 }
433 ((struct lys_node_leaf *)node)->when = retval;
434 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100435 case LEAF_LIST_KEYWORD:
436 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vicand72227c2016-02-21 20:29:52 +0100437 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100438 goto error;
439 }
440 ((struct lys_node_leaflist *)node)->when = retval;
441 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100442 case LIST_KEYWORD:
443 if (((struct lys_node_list *)node)->when) {
444 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "list");
445 goto error;
446 }
447 ((struct lys_node_list *)node)->when = retval;
448 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100449 case USES_KEYWORD:
450 if (((struct lys_node_uses *)node)->when) {
451 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "uses");
452 goto error;
453 }
454 ((struct lys_node_uses *)node)->when = retval;
455 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100456 case AUGMENT_KEYWORD:
457 if (((struct lys_node_augment *)node)->when) {
458 LOGVAL(LYE_TOOMANY, line, LY_VLOG_LYS, node, "when", "augment");
459 goto error;
460 }
461 ((struct lys_node_augment *)node)->when = retval;
462 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100463 }
464 free(value);
465 return retval;
466
467error:
468 free(value);
469 lys_when_free(module->ctx, retval);
470 return NULL;
471}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100472
473void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100474yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100475{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100476 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100477
Pavol Vican7cadfe72016-02-11 12:33:34 +0100478 node = calloc(1, sizeof_struct);
479 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100480 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100481 LOGMEM;
482 return NULL;
483 }
Pavol Vican531a9132016-03-03 10:10:09 +0100484 if (value) {
485 node->name = lydict_insert_zc(module->ctx, value);
486 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100487 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100488 node->nodetype = nodetype;
489 node->prev = node;
490
491 /* insert the node into the schema tree */
492 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100493 if (value) {
494 lydict_remove(module->ctx, node->name);
495 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100496 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100497 return NULL;
498 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100499 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100500}
501
502int
Pavol Vican096c6db2016-02-11 15:08:10 +0100503yang_read_default(struct lys_module *module, void *node, char *value, int type, int line)
504{
505 int ret;
506
507 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100508 case LEAF_KEYWORD:
509 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value, line);
510 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100511 case TYPEDEF_KEYWORD:
512 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value, line);
513 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100514 }
515 return ret;
516}
517
518int
519yang_read_units(struct lys_module *module, void *node, char *value, int type, int line)
520{
521 int ret;
522
523 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100524 case LEAF_KEYWORD:
525 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value, line);
526 break;
527 case LEAF_LIST_KEYWORD:
528 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value, line);
529 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100530 case TYPEDEF_KEYWORD:
531 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value, line);
532 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100533 }
534 return ret;
535}
Pavol Vican5de33492016-02-22 14:03:24 +0100536
537int
538yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres, int line)
539{
540 char *exp, *value;
541
542 exp = value = (char *) list->keys;
543 while ((value = strpbrk(value, " \t\n"))) {
544 list->keys_size++;
545 while (isspace(*value)) {
546 value++;
547 }
548 }
549 list->keys_size++;
550 list->keys = calloc(list->keys_size, sizeof *list->keys);
551 if (!list->keys) {
552 LOGMEM;
553 goto error;
554 }
555 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp, line) == -1) {
556 goto error;
557 }
558 free(exp);
559 return EXIT_SUCCESS;
560
561error:
562 free(exp);
563 return EXIT_FAILURE;
564}
565
566int
Pavol Vican85f12022016-03-05 16:30:35 +0100567yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres, int line)
568{
569 int i, j;
570 char *vaux;
571
572 /* count the number of unique leafs in the value */
573 vaux = value;
574 while ((vaux = strpbrk(vaux, " \t\n"))) {
575 unique->expr_size++;
576 while (isspace(*vaux)) {
577 vaux++;
578 }
579 }
580 unique->expr_size++;
581 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
582 if (!unique->expr) {
583 LOGMEM;
584 goto error;
585 }
586
587 for (i = 0; i < unique->expr_size; i++) {
588 vaux = strpbrk(value, " \t\n");
589 if (!vaux) {
590 /* the last token, lydict_insert() will count its size on its own */
591 vaux = value;
592 }
593
594 /* store token into unique structure */
595 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
596
597 /* check that the expression does not repeat */
598 for (j = 0; j < i; j++) {
599 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
600 LOGVAL(LYE_INARG, line, LY_VLOG_LYS, list, unique->expr[i], "unique");
601 LOGVAL(LYE_SPEC, 0, 0, NULL, "The identifier is not unique");
602 goto error;
603 }
604 }
605 /* try to resolve leaf */
606 if (unres) {
607 unres_schema_add_str(module, unres, (struct lys_node *)list, UNRES_LIST_UNIQ, unique->expr[i], line);
608 } else {
609 if (resolve_unique((struct lys_node *)list, unique->expr[i], 0, line)) {
610 goto error;
611 }
612 }
613
614 /* move to next token */
615 value = vaux;
616 while(isspace(*value)) {
617 value++;
618 }
619 }
620
621 return EXIT_SUCCESS;
622
623error:
624 return EXIT_FAILURE;
625}
626
627int
Pavol Vican5de33492016-02-22 14:03:24 +0100628yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
629{
630 uint8_t k;
Pavol Vican5de33492016-02-22 14:03:24 +0100631 struct type_ident *ident;
632
633 for(k=0; k<list->unique_size; k++) {
Pavol Vican5de33492016-02-22 14:03:24 +0100634 ident = (struct type_ident *)list->unique[k].expr;
Pavol Vican85f12022016-03-05 16:30:35 +0100635 if (yang_fill_unique(module, list, &list->unique[k], ident->s, unres, ident->line)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100636 goto error;
637 }
Pavol Vican5de33492016-02-22 14:03:24 +0100638 free(ident);
639 }
640 return EXIT_SUCCESS;
641
642error:
643 free(ident);
644 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100645}
646
Pavol Vican1ff0e222016-02-26 12:27:01 +0100647static int
648yang_read_identyref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres, int line)
649{
650 const char *value, *tmp;
651 int rc, ret = EXIT_FAILURE;
652
653 value = tmp = type->info.lref.path;
654 /* store in the JSON format */
655 value = transform_schema2json(module, value, line);
656 if (!value) {
657 goto end;
658 }
659 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value, line);
660 lydict_remove(module->ctx, value);
661
662 if (rc == -1) {
663 goto end;
664 }
665
666 ret = EXIT_SUCCESS;
667
668end:
669 lydict_remove(module->ctx, tmp);
670 return ret;
671}
672
Pavol Vican73e7c992016-02-24 12:18:05 +0100673int
674yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct unres_schema *unres)
675{
676 int i, rc;
677 int ret = -1;
678 const char *name, *value;
679 LY_DATA_TYPE base;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100680 struct yang_type *typ_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100681
Pavol Vican0df02b02016-03-01 10:28:50 +0100682 base = typ->type->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100683 value = transform_schema2json(module, typ->name, typ->line);
684 if (!value) {
685 goto error;
686 }
687
688 i = parse_identifier(value);
689 if (i < 1) {
690 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
691 lydict_remove(module->ctx, value);
692 goto error;
693 }
694 /* module name*/
695 name = value;
696 if (value[i]) {
697 typ->type->module_name = lydict_insert(module->ctx, value, i);
698 name += i;
699 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
700 LOGVAL(LYE_INCHAR, typ->line, LY_VLOG_NONE, NULL, name[0], name);
701 lydict_remove(module->ctx, value);
702 goto error;
703 }
704 ++name;
705 }
706
707 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
708 lydict_remove(module->ctx, value);
709 if (rc == -1) {
710 LOGVAL(LYE_INMOD, typ->line, LY_VLOG_NONE, NULL, typ->type->module_name);
711 goto error;
712
713 /* the type could not be resolved or it was resolved to an unresolved typedef*/
714 } else if (rc == EXIT_FAILURE) {
715 ret = EXIT_FAILURE;
716 goto error;
717 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100718 typ->type->base = typ->type->der->type.base;
719 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100720 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100721 }
722 switch (base) {
723 case LY_TYPE_STRING:
724 if (typ->type->base == LY_TYPE_BINARY) {
725 if (typ->type->info.str.pat_count) {
726 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100727 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100728 goto error;
729 }
730 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100731 if (typ->type->info.binary.length && lyp_check_length_range(typ->type->info.binary.length->expr, typ->type)) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100732 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
733 goto error;
734 }
735 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100736 if (typ->type->info.str.length && lyp_check_length_range(typ->type->info.str.length->expr, typ->type)) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100737 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
738 goto error;
739 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100740 } else {
741 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
742 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100743 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100744 break;
745 case LY_TYPE_DEC64:
746 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100747 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
Pavol Vicanaff5c802016-02-24 15:56:45 +0100748 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
749 goto error;
750 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100751 /* mandatory sub-statement(s) check */
752 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
753 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican723de602016-03-21 15:13:20 +0100754 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100755 goto error;
756 }
757 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
758 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
759 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "fraction-digits");
760 goto error;
761 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100762 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
763 if (typ->type->info.dec64.dig) {
764 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
765 typ->type->base = base;
766 goto error;
767 }
768 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100769 if (typ->type->info.num.range && lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
Pavol Vicanaff5c802016-02-24 15:56:45 +0100770 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
771 goto error;
772 }
773 } else {
774 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
775 goto error;
776 }
777 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100778 case LY_TYPE_ENUM:
779 if (typ->type->base != LY_TYPE_ENUM) {
780 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
781 goto error;
782 }
783 if (!typ->type->der->type.der && !typ->type->info.enums.count) {
784 /* type is derived directly from buit-in enumeartion type and enum statement is required */
Pavol Vican723de602016-03-21 15:13:20 +0100785 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "enum", "type");
Pavol Vican79a763d2016-02-25 15:41:27 +0100786 goto error;
787 }
788 if (typ->type->der->type.der && typ->type->info.enums.count) {
789 /* type is not directly derived from buit-in enumeration type and enum statement is prohibited */
790 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "enum");
791 goto error;
792 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100793 break;
794 case LY_TYPE_LEAFREF:
795 if (typ->type->base == LY_TYPE_IDENT && typ->flags & LYS_TYPE_BASE) {
796 if (yang_read_identyref(module, typ->type, unres, typ->line)) {
797 goto error;
798 }
Pavol Vican191613a2016-02-26 16:21:32 +0100799 } else if (typ->type->base == LY_TYPE_LEAFREF) {
800 if (typ->type->info.lref.path && !typ->type->der->type.der) {
801 value = typ->type->info.lref.path;
802 /* store in the JSON format */
803 typ->type->info.lref.path = transform_schema2json(module, value, typ->line);
804 lydict_remove(module->ctx, value);
805 if (!typ->type->info.lref.path) {
806 goto error;
807 }
808 if (unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent, typ->line) == -1) {
809 goto error;
810 }
811 } else if (!typ->type->info.lref.path && !typ->type->der->type.der) {
Pavol Vican723de602016-03-21 15:13:20 +0100812 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100813 goto error;
814 } else {
815 LOGVAL(LYE_INSTMT, typ->line, LY_VLOG_NONE, NULL, "path");
816 goto error;
817 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100818 } else {
819 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
820 goto error;
821 }
822 break;
823 case LY_TYPE_IDENT:
824 if (typ->type->der->type.der) {
825 /* this is just a derived type with no base specified/required */
826 break;
827 } else {
Pavol Vican723de602016-03-21 15:13:20 +0100828 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "base", "type");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100829 goto error;
830 }
831 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100832 case LY_TYPE_UNION:
833 if (typ->type->base != LY_TYPE_UNION) {
834 typ->type->base = LY_TYPE_UNION;
835 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
836 goto error;
837 }
838 if (!typ->type->info.uni.types) {
839 if (typ->type->der->type.der) {
840 /* this is just a derived type with no additional type specified/required */
841 break;
842 }
Pavol Vican723de602016-03-21 15:13:20 +0100843 LOGVAL(LYE_MISSCHILDSTMT, typ->line, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100844 goto error;
845 }
846 for (i = 0; i < typ->type->info.uni.count; i++) {
847 typ_tmp = (struct yang_type *)typ->type->info.uni.types[i].der;
848 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i], UNRES_TYPE_DER, parent, typ_tmp->line)) {
849 goto error;
850 }
851 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
852 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "empty", typ->name);
853 goto error;
854 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
855 LOGVAL(LYE_INARG, typ->line, LY_VLOG_NONE, NULL, "leafref", typ->name);
856 goto error;
857 }
858 }
859 break;
Pavol Vicana1827962016-02-29 15:39:42 +0100860
861 default:
862 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
863 if (typ->type->base != base) {
864 LOGVAL(LYE_SPEC, typ->line, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", parent->name);
865 goto error;
866 }
867 } else {
868 LOGINT;
869 goto error;
870 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100871 }
872 return EXIT_SUCCESS;
873
874error:
Pavol Vicana1827962016-02-29 15:39:42 +0100875 typ->type->base = base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100876 if (typ->type->module_name) {
877 lydict_remove(module->ctx, typ->type->module_name);
878 typ->type->module_name = NULL;
879 }
880 return ret;
881}
882
883void *
Pavol Vican4766aca2016-03-07 12:42:36 +0100884yang_read_type(struct lys_module *module, void *parent, char *value, int type, int line)
Pavol Vican73e7c992016-02-24 12:18:05 +0100885{
886 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100887 struct type_deviation *dev;
888 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +0100889
Pavol Vicand01d8ae2016-03-01 10:45:59 +0100890 typ = calloc(1, sizeof *typ);
891 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +0100892 LOGMEM;
893 return NULL;
894 }
Pavol Vican73e7c992016-02-24 12:18:05 +0100895
896 typ->flags = LY_YANG_STRUCTURE_FLAG;
897 switch (type) {
898 case LEAF_KEYWORD:
899 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
900 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
901 typ->type = &((struct lys_node_leaf *)parent)->type;
902 break;
Pavol Vicana55992a2016-03-01 13:37:17 +0100903 case LEAF_LIST_KEYWORD:
904 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
905 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
906 typ->type = &((struct lys_node_leaflist *)parent)->type;
907 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100908 case UNION_KEYWORD:
909 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
910 typ->type = (struct lys_type *)parent;
911 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100912 case TYPEDEF_KEYWORD:
913 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
914 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +0100915 break;
916 case REPLACE_KEYWORD:
917 /* deviation replace type*/
918 dev = (struct type_deviation *)parent;
919 if (dev->deviate->type) {
920 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "type", "deviation");
921 goto error;
922 }
923 /* check target node type */
924 if (dev->target->nodetype == LYS_LEAF) {
925 typ->type = &((struct lys_node_leaf *)dev->target)->type;
926 } else if (dev->target->nodetype == LYS_LEAFLIST) {
927 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
928 } else {
929 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "type");
930 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"type\" property.");
931 goto error;
932 }
933
934 /* remove type and initialize it */
935 lys_type_free(module->ctx, typ->type);
936 tmp_parent = typ->type->parent;
937 memset(typ->type, 0, sizeof *typ->type);
938 typ->type->parent = tmp_parent;
939
940 /* replace it with the value specified in deviation */
941 /* HACK for unres */
942 typ->type->der = (struct lys_tpdf *)typ;
943 dev->deviate->type = typ->type;
944 break;
Pavol Vican73e7c992016-02-24 12:18:05 +0100945 }
946 typ->name = value;
947 typ->line = line;
Pavol Vican73e7c992016-02-24 12:18:05 +0100948 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +0100949
950error:
951 free(typ);
952 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +0100953}
954
955void *
956yang_read_length(struct lys_module *module, struct yang_type *typ, char *value, int line)
957{
958 struct lys_restr **length;
959
960 if (typ->type->base == 0 || typ->type->base == LY_TYPE_STRING) {
961 length = &typ->type->info.str.length;
962 typ->type->base = LY_TYPE_STRING;
963 } else if (typ->type->base == LY_TYPE_BINARY) {
964 length = &typ->type->info.binary.length;
965 } else {
966 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected length statement.");
967 goto error;
968 }
969
970 if (*length) {
971 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "length", "type");
972 }
973 *length = calloc(1, sizeof **length);
974 if (!*length) {
975 LOGMEM;
976 goto error;
977 }
978 (*length)->expr = lydict_insert_zc(module->ctx, value);
979 return *length;
980
981error:
982 free(value);
983 return NULL;
984
985}
Pavol Vican1c203db2016-02-24 14:05:23 +0100986
987void *
988yang_read_pattern(struct lys_module *module, struct yang_type *typ, char *value, int line)
989{
990 pcre *precomp;
991 int err_offset;
992 const char *err_ptr;
993
994 /* check that the regex is valid */
995 precomp = pcre_compile(value, PCRE_NO_AUTO_CAPTURE, &err_ptr, &err_offset, NULL);
996 if (!precomp) {
997 LOGVAL(LYE_INREGEX, line, LY_VLOG_NONE, NULL, value, err_ptr);
998 free(value);
999 return NULL;
1000 }
1001 free(precomp);
1002
1003 typ->type->info.str.patterns[typ->type->info.str.pat_count].expr = lydict_insert_zc(module->ctx, value);
1004 typ->type->info.str.pat_count++;
1005 return &typ->type->info.str.patterns[typ->type->info.str.pat_count-1];
1006}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001007
1008void *
1009yang_read_range(struct lys_module *module, struct yang_type *typ, char *value, int line)
1010{
1011 if (typ->type->base != 0 && typ->type->base != LY_TYPE_DEC64) {
1012 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected range statement.");
1013 goto error;
1014 }
1015 typ->type->base = LY_TYPE_DEC64;
1016 if (typ->type->info.dec64.range) {
1017 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "range", "type");
1018 goto error;
1019 }
1020 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1021 if (!typ->type->info.dec64.range) {
1022 LOGMEM;
1023 goto error;
1024 }
1025 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1026 return typ->type->info.dec64.range;
1027
1028error:
1029 free(value);
1030 return NULL;
1031}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001032
1033int
1034yang_read_fraction(struct yang_type *typ, uint32_t value, int line)
1035{
1036 if (typ->type->base == 0 || typ->type->base == LY_TYPE_DEC64) {
1037 typ->type->base = LY_TYPE_DEC64;
1038 } else {
1039 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
1040 goto error;
1041 }
1042 if (typ->type->info.dec64.dig) {
1043 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "fraction-digits", "type");
1044 goto error;
1045 }
1046 /* range check */
1047 if (value < 1 || value > 18) {
1048 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
1049 goto error;
1050 }
1051 typ->type->info.dec64.dig = value;
1052 return EXIT_SUCCESS;
1053
1054error:
1055 return EXIT_FAILURE;
1056}
Pavol Vican79a763d2016-02-25 15:41:27 +01001057
1058void *
1059yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value, int line)
1060{
1061 struct lys_type_enum *enm;
1062 int i;
1063
1064 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1065 enm->name = lydict_insert_zc(module->ctx, value);
1066
1067 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1068 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
1069 LOGVAL(LYE_ENUM_WS, line, LY_VLOG_NONE, NULL, enm->name);
1070 goto error;
1071 }
1072
1073 /* check the name uniqueness */
1074 for (i = 0; i < typ->type->info.enums.count; i++) {
1075 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
1076 LOGVAL(LYE_ENUM_DUPNAME, line, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1077 goto error;
1078 }
1079 }
1080
1081 typ->type->info.enums.count++;
1082 return enm;
1083
1084error:
1085 typ->type->info.enums.count++;
1086 return NULL;
1087}
1088
1089int
1090yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign, int line)
1091{
1092 int i, j;
1093
1094 if (!assign) {
1095 /* assign value automatically */
1096 if (*value > INT32_MAX) {
1097 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
1098 goto error;
1099 }
1100 enm->value = *value;
1101 enm->flags |= LYS_AUTOASSIGNED;
1102 (*value)++;
1103 }
1104
1105 /* check that the value is unique */
1106 j = typ->type->info.enums.count-1;
1107 for (i = 0; i < j; i++) {
1108 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
1109 LOGVAL(LYE_ENUM_DUPVAL, line, LY_VLOG_NONE, NULL,
1110 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name);
1111 goto error;
1112 }
1113 }
1114
1115 return EXIT_SUCCESS;
1116
1117error:
1118 return EXIT_FAILURE;
1119}
Pavol Vican9887c682016-02-29 11:32:01 +01001120
1121void *
1122yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value, int line)
1123{
1124 int i;
1125 struct lys_type_bit *bit;
1126
1127 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
1128 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, line, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001129 free(value);
1130 goto error;
1131 }
1132 bit->name = lydict_insert_zc(module->ctx, value);
1133
1134 /* check the name uniqueness */
1135 for (i = 0; i < typ->type->info.bits.count; i++) {
1136 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
1137 LOGVAL(LYE_BITS_DUPNAME, line, LY_VLOG_NONE, NULL, bit->name);
1138 typ->type->info.bits.count++;
1139 goto error;
1140 }
1141 }
1142 typ->type->info.bits.count++;
1143 return bit;
1144
1145error:
1146 return NULL;
1147}
1148
1149int
1150yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign, int line)
1151{
1152 int i,j;
1153 struct lys_type_bit bit_tmp;
1154
1155 if (!assign) {
1156 /* assign value automatically */
1157 if (*value > UINT32_MAX) {
1158 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
1159 goto error;
1160 }
1161 bit->pos = (uint32_t)*value;
1162 bit->flags |= LYS_AUTOASSIGNED;
1163 (*value)++;
1164 }
1165
1166 j = typ->type->info.bits.count - 1;
1167 /* check that the value is unique */
1168 for (i = 0; i < j; i++) {
1169 if (typ->type->info.bits.bit[i].pos == bit->pos) {
1170 LOGVAL(LYE_BITS_DUPVAL, line, LY_VLOG_NONE, NULL, bit->pos, bit->name);
1171 goto error;
1172 }
1173 }
1174
1175 /* keep them ordered by position */
1176 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1177 /* switch them */
Pavol Vican9b032132016-02-29 15:18:38 +01001178 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1179 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1180 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican9887c682016-02-29 11:32:01 +01001181 j--;
1182 }
1183
1184 return EXIT_SUCCESS;
1185
1186error:
1187 return EXIT_FAILURE;
1188}
Pavol Vican0df02b02016-03-01 10:28:50 +01001189
1190void *
1191yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value, int line)
1192{
1193 struct lys_tpdf *ret;
1194
1195 if (lyp_check_identifier(value, LY_IDENT_TYPE, line, module, parent)) {
1196 free(value);
1197 return NULL;
1198 }
1199 if (!parent) {
1200 ret = &module->tpdf[module->tpdf_size];
1201 ret->type.parent = NULL;
1202 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001203 } else {
1204 switch (parent->nodetype) {
1205 case LYS_GROUPING:
1206 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001207 ((struct lys_node_grp *)parent)->tpdf_size++;
1208 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001209 case LYS_CONTAINER:
1210 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1211 ((struct lys_node_container *)parent)->tpdf_size++;
1212 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001213 case LYS_LIST:
1214 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1215 ((struct lys_node_list *)parent)->tpdf_size++;
1216 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001217 case LYS_RPC:
1218 ret = &((struct lys_node_rpc *)parent)->tpdf[((struct lys_node_rpc *)parent)->tpdf_size];
1219 ((struct lys_node_rpc *)parent)->tpdf_size++;
1220 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001221 case LYS_INPUT:
1222 case LYS_OUTPUT:
1223 ret = &((struct lys_node_rpc_inout *)parent)->tpdf[((struct lys_node_rpc_inout *)parent)->tpdf_size];
1224 ((struct lys_node_rpc_inout *)parent)->tpdf_size++;
1225 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001226 case LYS_NOTIF:
1227 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1228 ((struct lys_node_notif *)parent)->tpdf_size++;
1229 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001230 default:
1231 /* another type of nodetype is error*/
1232 LOGINT;
1233 free(value);
1234 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001235 }
Pavol Vican535d50e2016-03-01 13:05:33 +01001236 ret->type.parent = (struct lys_tpdf *)parent;
Pavol Vican0df02b02016-03-01 10:28:50 +01001237 }
1238
1239 ret->name = lydict_insert_zc(module->ctx, value);
1240 ret->module = module;
1241 return ret;
1242}
Pavol Vican1003ead2016-03-02 12:24:52 +01001243
1244void *
1245yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value, int line)
1246{
1247 struct lys_refine *rfn;
1248
1249 rfn = &uses->refine[uses->refine_size];
1250 uses->refine_size++;
1251 rfn->target_name = transform_schema2json(module, value, line);
1252 free(value);
1253 if (!rfn->target_name) {
1254 return NULL;
1255 }
1256 return rfn;
1257}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001258
1259void *
1260yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value, int line)
1261{
1262 struct lys_node_augment *aug;
1263 uint16_t *size;
1264
1265 if (parent) {
1266 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1267 } else {
1268 aug = &module->augment[module->augment_size];
1269 }
1270 aug->nodetype = LYS_AUGMENT;
1271 aug->target_name = transform_schema2json(module, value, line);
1272 free(value);
1273 if (!aug->target_name) {
1274 return NULL;
1275 }
1276 aug->parent = parent;
1277 aug->module = module;
1278 if (parent) {
1279 ((struct lys_node_uses *)parent)->augment_size++;
1280 } else {
1281 module->augment_size++;
1282 }
1283 return aug;
1284}
Pavol Vican220e5a12016-03-03 14:19:43 +01001285
1286void *
1287yang_read_deviation(struct lys_module *module, char *value, int line)
1288{
1289 struct lys_node *dev_target = NULL;
1290 struct lys_deviation *dev;
1291 struct type_deviation *deviation = NULL;
1292 int i, j, rc;
1293
1294 deviation = calloc(1, sizeof *deviation);
1295 if (!deviation) {
1296 LOGMEM;
1297 goto error;
1298 }
1299
1300 dev = &module->deviation[module->deviation_size];
1301 dev->target_name = transform_schema2json(module, value, line);
1302 free(value);
1303 if (!dev->target_name) {
1304 goto error;
1305 }
1306
1307 /* resolve target node */
1308 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1309 if (rc || !dev_target) {
1310 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviations");
1311 goto error;
1312 }
1313 if (dev_target->module == lys_module(module)) {
Pavol Vican723de602016-03-21 15:13:20 +01001314 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1315 LOGVAL(LYE_SPEC, 0, 0, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001316 goto error;
1317 }
1318 /*save pointer to the deviation and deviated target*/
1319 deviation->deviation = dev;
1320 deviation->target = dev_target;
1321
1322 /* mark the target module as deviated */
1323 dev_target->module->deviated = 1;
1324
1325 /* copy our imports to the deviated module (deviations may need them to work) */
1326 for (i = 0; i < module->imp_size; ++i) {
1327 for (j = 0; j < dev_target->module->imp_size; ++j) {
1328 if (module->imp[i].module == dev_target->module->imp[j].module) {
1329 break;
1330 }
1331 }
1332
1333 if (j < dev_target->module->imp_size) {
1334 /* import is already there */
1335 continue;
1336 }
1337
1338 /* copy the import, mark it as external */
1339 ++dev_target->module->imp_size;
1340 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1341 if (!dev_target->module->imp) {
1342 LOGMEM;
1343 goto error;
1344 }
1345 dev_target->module->imp[dev_target->module->imp_size - 1].module = module->imp[i].module;
1346 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->imp[i].prefix, 0);
1347 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->imp[i].rev, LY_REV_SIZE);
1348 dev_target->module->imp[dev_target->module->imp_size - 1].external = 1;
1349 }
1350
1351 /* copy ourselves to the deviated module as a special import (if we haven't yet, there could be more deviations of the same module) */
1352 for (i = 0; i < dev_target->module->imp_size; ++i) {
1353 if (dev_target->module->imp[i].module == module) {
1354 break;
1355 }
1356 }
1357
1358 if (i == dev_target->module->imp_size) {
1359 ++dev_target->module->imp_size;
1360 dev_target->module->imp = ly_realloc(dev_target->module->imp, dev_target->module->imp_size * sizeof *dev_target->module->imp);
1361 if (!dev_target->module->imp) {
1362 LOGMEM;
1363 goto error;
1364 }
1365 dev_target->module->imp[dev_target->module->imp_size - 1].module = module;
1366 dev_target->module->imp[dev_target->module->imp_size - 1].prefix = lydict_insert(module->ctx, module->prefix, 0);
1367 if (module->rev_size) {
1368 memcpy(dev_target->module->imp[dev_target->module->imp_size - 1].rev, module->rev[0].date, LY_REV_SIZE);
1369 } else {
1370 memset(dev_target->module->imp[dev_target->module->imp_size - 1].rev, 0, LY_REV_SIZE);
1371 }
1372 dev_target->module->imp[dev_target->module->imp_size - 1].external = 2;
1373 } else {
1374 /* it could have been added by another deviating module that imported this deviating module */
1375 dev_target->module->imp[i].external = 2;
1376 }
1377
1378
1379 return deviation;
1380
1381error:
1382 free(deviation);
1383 lydict_remove(module->ctx, dev->target_name);
1384 return NULL;
1385}
Pavol Vican4c90c642016-03-03 15:06:47 +01001386
1387int
1388yang_read_deviate_unsupported(struct type_deviation *dev, int line)
1389{
1390 int i;
1391
1392 if (dev->deviation->deviate_size) {
1393 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1394 return EXIT_FAILURE;
1395 }
1396 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1397
1398 /* you cannot remove a key leaf */
1399 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1400 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1401 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
1402 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1403 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot remove a list key.");
1404 return EXIT_FAILURE;
1405 }
1406 }
1407 }
1408
1409 /* unlink and store the original node */
1410 dev->deviation->orig_node = dev->target;
1411
1412 dev->deviation->deviate_size = 1;
1413 return EXIT_SUCCESS;
1414}
Pavol Vican85f12022016-03-05 16:30:35 +01001415
1416int
1417yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod, int line)
1418{
1419 struct unres_schema tmp_unres;
1420
1421 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1422 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1423 dev->deviation->deviate_size++;
1424 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
1425 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "not-supported");
1426 LOGVAL(LYE_SPEC, 0, 0, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
1427 return EXIT_FAILURE;
1428 }
1429
1430 /* store a shallow copy of the original node */
1431 if (!dev->deviation->orig_node) {
1432 memset(&tmp_unres, 0, sizeof tmp_unres);
1433 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1434 /* just to be safe */
1435 if (tmp_unres.count) {
1436 LOGINT;
1437 return EXIT_FAILURE;
1438 }
1439 }
1440
1441 return EXIT_SUCCESS;
1442}
1443
1444int
1445yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1446{
1447 const char **stritem;
1448
1449 if (dev->deviate->units) {
1450 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "units", "deviate");
1451 free(value);
1452 goto error;
1453 }
1454
1455 /* check target node type */
1456 if (dev->target->nodetype == LYS_LEAFLIST) {
1457 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1458 } else if (dev->target->nodetype == LYS_LEAF) {
1459 stritem = &((struct lys_node_leaf *)dev->target)->units;
1460 } else {
1461 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1462 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"units\" property.");
1463 free(value);
1464 goto error;
1465 }
1466
1467 dev->deviate->units = lydict_insert_zc(ctx, value);
1468
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001469 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1470 /* check values */
1471 if (*stritem != dev->deviate->units) {
1472 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1473 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1474 goto error;
1475 }
1476 /* remove current units value of the target */
1477 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001478 } else {
1479 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1480 /* check that there is no current value */
1481 if (*stritem) {
1482 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1483 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1484 goto error;
1485 }
1486 } else { /* replace */
1487 if (!*stritem) {
1488 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "units");
1489 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1490 goto error;
1491 }
1492 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001493 /* remove current units value of the target ... */
1494 lydict_remove(ctx, *stritem);
1495
1496 /* ... and replace it with the value specified in deviation */
1497 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1498 }
1499
Pavol Vican85f12022016-03-05 16:30:35 +01001500 return EXIT_SUCCESS;
1501
1502error:
1503 return EXIT_FAILURE;
1504}
1505
1506int
1507yang_read_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_must, int line)
1508{
1509 uint8_t i;
1510
1511 /* check target node type */
1512 switch (dev->target->nodetype) {
1513 case LYS_LEAF:
1514 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1515 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1516 break;
1517 case LYS_CONTAINER:
1518 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1519 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1520 break;
1521 case LYS_LEAFLIST:
1522 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1523 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1524 break;
1525 case LYS_LIST:
1526 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1527 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1528 break;
1529 case LYS_ANYXML:
1530 dev->trg_must = &((struct lys_node_anyxml *)dev->target)->must;
1531 dev->trg_must_size = &((struct lys_node_anyxml *)dev->target)->must_size;
1532 break;
1533 default:
1534 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "must");
1535 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"must\" property.");
1536 goto error;
1537 }
1538
1539 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1540 /* reallocate the must array of the target */
1541 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1542 if (!dev->deviate->must) {
1543 LOGMEM;
1544 goto error;
1545 }
1546 *dev->trg_must = dev->deviate->must;
1547 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1548 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001549 } else {
1550 /* LY_DEVIATE_DEL */
1551 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1552 if (!dev->deviate->must) {
1553 LOGMEM;
1554 goto error;
1555 }
Pavol Vican85f12022016-03-05 16:30:35 +01001556 }
1557
1558 return EXIT_SUCCESS;
1559
1560error:
1561 return EXIT_FAILURE;
1562}
1563
1564int
1565yang_read_deviate_unique(struct ly_ctx *ctx, struct type_deviation *dev, uint8_t c_uniq, int line)
1566{
1567 int i, j;
1568 struct lys_node_list *list;
1569
1570 /* check target node type */
1571 if (dev->target->nodetype != LYS_LIST) {
1572 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "unique");
1573 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"unique\" property.");
1574 goto error;
1575 }
1576
1577 list = (struct lys_node_list *)dev->target;
1578 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1579 /* reallocate the unique array of the target */
1580 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1581 if (!dev->deviate->unique) {
1582 LOGMEM;
1583 goto error;
1584 }
1585 list->unique = dev->deviate->unique;
1586 dev->deviate->unique = &list->unique[list->unique_size];
1587 dev->deviate->unique_size = c_uniq;
1588 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001589 } else {
1590 /* LY_DEVIATE_DEL */
1591 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1592 if (!dev->deviate->unique) {
1593 LOGMEM;
1594 goto error;
1595 }
Pavol Vican85f12022016-03-05 16:30:35 +01001596 }
1597
1598 return EXIT_SUCCESS;
1599
1600error:
1601 return EXIT_FAILURE;
1602}
1603
1604int
1605yang_read_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *value, int line)
1606{
1607 int rc;
1608 struct lys_node_choice *choice;
1609 struct lys_node_leaf *leaf;
1610 struct lys_node *node;
1611
1612 if (dev->deviate->dflt) {
1613 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "default", "deviate");
1614 free(value);
1615 goto error;
1616 }
1617
1618 dev->deviate->dflt = lydict_insert_zc(ctx, value);
1619
1620 if (dev->target->nodetype == LYS_CHOICE) {
1621 choice = (struct lys_node_choice *)dev->target;
1622
Pavol Vican85f12022016-03-05 16:30:35 +01001623 rc = resolve_choice_default_schema_nodeid(dev->deviate->dflt, choice->child, (const struct lys_node **)&node);
1624 if (rc || !node) {
1625 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1626 goto error;
1627 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001628 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1629 if (!choice->dflt || (choice->dflt != node)) {
1630 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1631 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1632 goto error;
1633 }
1634 choice->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001635 } else {
1636 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1637 /* check that there is no current value */
1638 if (choice->dflt) {
1639 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1640 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1641 goto error;
1642 }
1643 } else { /* replace*/
1644 if (!choice->dflt) {
1645 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1646 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1647 goto error;
1648 }
1649 }
1650
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001651 choice->dflt = node;
1652 if (!choice->dflt) {
1653 /* default branch not found */
1654 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1655 goto error;
1656 }
Pavol Vican85f12022016-03-05 16:30:35 +01001657 }
1658 } else if (dev->target->nodetype == LYS_LEAF) {
1659 leaf = (struct lys_node_leaf *)dev->target;
1660
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001661 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1662 if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
1663 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
1664 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1665 goto error;
1666 }
1667 /* remove value */
1668 lydict_remove(ctx, leaf->dflt);
1669 leaf->dflt = NULL;
Pavol Vican4766aca2016-03-07 12:42:36 +01001670 } else {
1671 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1672 /* check that there is no current value */
1673 if (leaf->dflt) {
1674 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1675 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1676 goto error;
1677 }
1678 } else { /* replace*/
1679 if (!leaf->dflt) {
1680 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1681 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1682 goto error;
1683 }
1684 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001685 /* remove value */
1686 lydict_remove(ctx, leaf->dflt);
Pavol Vican85f12022016-03-05 16:30:35 +01001687
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001688 /* set new value */
1689 leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
1690 }
Pavol Vican85f12022016-03-05 16:30:35 +01001691 } else {
1692 /* invalid target for default value */
1693 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
1694 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"default\" property.");
1695 goto error;
1696 }
1697
1698 return EXIT_SUCCESS;
1699
1700error:
1701 return EXIT_FAILURE;
1702}
1703
1704int
1705yang_read_deviate_config(struct type_deviation *dev, uint8_t value, int line)
1706{
1707 if (dev->deviate->flags & LYS_CONFIG_MASK) {
1708 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "config", "deviate");
1709 goto error;
1710 }
1711
1712 /* for we deviate from RFC 6020 and allow config property even it is/is not
1713 * specified in the target explicitly since config property inherits. So we expect
1714 * that config is specified in every node. But for delete, we check that the value
1715 * is the same as here in deviation
1716 */
1717 dev->deviate->flags |= value;
1718
1719 /* add and replace are the same in this case */
1720 /* remove current config value of the target ... */
1721 dev->target->flags &= ~LYS_CONFIG_MASK;
1722
1723 /* ... and replace it with the value specified in deviation */
1724 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1725
1726 return EXIT_SUCCESS;
1727
1728error:
1729 return EXIT_FAILURE;
1730}
1731
1732int
1733yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value, int line)
1734{
1735 if (dev->deviate->flags & LYS_MAND_MASK) {
1736 LOGVAL(LYE_TOOMANY, line, LY_VLOG_NONE, NULL, "mandatory", "deviate");
1737 goto error;
1738 }
1739
1740 /* check target node type */
1741 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML))) {
1742 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1743 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"mandatory\" property.");
1744 goto error;
1745 }
1746
1747 dev->deviate->flags |= value;
1748
1749 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1750 /* check that there is no current value */
1751 if (dev->target->flags & LYS_MAND_MASK) {
1752 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1753 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1754 goto error;
1755 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001756 } else { /* replace */
1757 if (!(dev->target->flags & LYS_MAND_MASK)) {
1758 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "mandatory");
1759 LOGVAL(LYE_SPEC, 0, 0, NULL, "Replacing a property that does not exist.");
1760 goto error;
1761 }
Pavol Vican85f12022016-03-05 16:30:35 +01001762 }
1763
Pavol Vican85f12022016-03-05 16:30:35 +01001764 /* remove current mandatory value of the target ... */
1765 dev->target->flags &= ~LYS_MAND_MASK;
1766
1767 /* ... and replace it with the value specified in deviation */
1768 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
1769
1770 return EXIT_SUCCESS;
1771
1772error:
1773 return EXIT_FAILURE;
1774}
1775
1776int
1777yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type, int line)
1778{
1779 uint32_t *ui32val;
1780
1781 /* check target node type */
1782 if (dev->target->nodetype == LYS_LEAFLIST) {
1783 if (type) {
1784 ui32val = &((struct lys_node_leaflist *)dev->target)->max;
1785 } else {
1786 ui32val = &((struct lys_node_leaflist *)dev->target)->min;
1787 }
1788 } else if (dev->target->nodetype == LYS_LIST) {
1789 if (type) {
1790 ui32val = &((struct lys_node_list *)dev->target)->max;
1791 } else {
1792 ui32val = &((struct lys_node_list *)dev->target)->min;
1793 }
1794 } else {
1795 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1796 LOGVAL(LYE_SPEC, 0, 0, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
1797 goto error;
1798 }
1799
1800 if (type) {
1801 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001802 dev->deviate->max_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001803 } else {
1804 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01001805 dev->deviate->min_set = 1;
Pavol Vican85f12022016-03-05 16:30:35 +01001806 }
1807
1808 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1809 /* check that there is no current value */
1810 if (*ui32val) {
1811 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1812 LOGVAL(LYE_SPEC, 0, 0, NULL, "Adding property that already exists.");
1813 goto error;
1814 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001815 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1816 /* unfortunately, there is no way to check reliably that there
1817 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001818 }
1819
1820 /* add (already checked) and replace */
1821 /* set new value specified in deviation */
1822 *ui32val = value;
1823
1824 return EXIT_SUCCESS;
1825
1826error:
1827 return EXIT_FAILURE;
1828}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001829
1830int
1831yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line)
1832{
1833 int i;
1834
1835 /* find must to delete, we are ok with just matching conditions */
1836 for (i = 0; i < *dev->trg_must_size; i++) {
1837 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
1838 /* we have a match, free the must structure ... */
1839 lys_restr_free(ctx, &((*dev->trg_must)[i]));
1840 /* ... and maintain the array */
1841 (*dev->trg_must_size)--;
1842 if (i != *dev->trg_must_size) {
1843 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
1844 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
1845 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
1846 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
1847 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
1848 }
1849 if (!(*dev->trg_must_size)) {
1850 free(*dev->trg_must);
1851 *dev->trg_must = NULL;
1852 } else {
1853 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
1854 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
1855 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
1856 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
1857 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
1858 }
1859
1860 i = -1; /* set match flag */
1861 break;
1862 }
1863 }
1864 if (i != -1) {
1865 /* no match found */
1866 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
1867 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
1868 return EXIT_FAILURE;
1869 }
1870
1871 return EXIT_SUCCESS;
1872}
1873
1874int
1875yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line)
1876{
1877 struct lys_node_list *list;
1878 int i, j;
1879
1880 list = (struct lys_node_list *)dev->target;
1881 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL, line)) {
1882 dev->deviate->unique_size++;
1883 goto error;
1884 }
1885
1886 /* find unique structures to delete */
1887 for (i = 0; i < list->unique_size; i++) {
1888 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1889 continue;
1890 }
1891
1892 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
1893 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
1894 break;
1895 }
1896 }
1897
1898 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
1899 /* we have a match, free the unique structure ... */
1900 for (j = 0; j < list->unique[i].expr_size; j++) {
1901 lydict_remove(module->ctx, list->unique[i].expr[j]);
1902 }
1903 free(list->unique[i].expr);
1904 /* ... and maintain the array */
1905 list->unique_size--;
1906 if (i != list->unique_size) {
1907 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1908 list->unique[i].expr = list->unique[list->unique_size].expr;
1909 }
1910
1911 if (!list->unique_size) {
1912 free(list->unique);
1913 list->unique = NULL;
1914 } else {
1915 list->unique[list->unique_size].expr_size = 0;
1916 list->unique[list->unique_size].expr = NULL;
1917 }
1918
1919 i = -1; /* set match flag */
1920 break;
1921 }
1922 }
1923 dev->deviate->unique_size++;
1924
1925 if (i != -1) {
1926 /* no match found */
1927 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, value, "unique");
1928 LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
1929 goto error;
1930 }
1931
1932 free(value);
1933 return EXIT_SUCCESS;
1934
1935error:
1936 free(value);
1937 return EXIT_FAILURE;
1938}
Pavol Vicane92421d2016-03-08 10:12:33 +01001939
1940int
1941yang_check_deviation(struct lys_module *module, struct type_deviation *dev, struct unres_schema *unres, int line)
1942{
1943 int i, rc;
1944
1945 if (dev->target->nodetype == LYS_LEAF) {
1946 for(i = 0; i < dev->deviation->deviate_size; ++i) {
1947 if (dev->deviation->deviate[i].mod != LY_DEVIATE_DEL) {
1948 if (dev->deviation->deviate[i].dflt || dev->deviation->deviate[i].type) {
1949 rc = unres_schema_add_str(module, unres, &((struct lys_node_leaf *)dev->target)->type, UNRES_TYPE_DFLT, ((struct lys_node_leaf *)dev->target)->dflt, 0);
1950 if (rc == -1) {
1951 return EXIT_FAILURE;
1952 } else if (rc == EXIT_FAILURE) {
1953 LOGVAL(LYE_SPEC, line, LY_VLOG_NONE, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->deviation->target_name);
1954 return EXIT_FAILURE;
1955 }
1956 break;
1957 }
1958 }
1959 }
1960 }
1961 return EXIT_SUCCESS;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001962}
1963
1964int
1965yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
1966 char *rev, int inc_size, struct unres_schema *unres, int line)
1967{
1968 struct lys_include inc;
1969 struct lys_module *trg;
1970 int i;
Pavol Vican55870412016-03-10 12:36:21 +01001971 const char *str;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001972
Pavol Vican55870412016-03-10 12:36:21 +01001973 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001974 trg = (submodule) ? (struct lys_module *)submodule : module;
1975 inc.submodule = NULL;
1976 inc.external = 0;
1977 memcpy(inc.rev, rev, LY_REV_SIZE);
Pavol Vican55870412016-03-10 12:36:21 +01001978 if (lyp_check_include(module, submodule, str, line, &inc, unres)) {
Pavol Vican9b89dda2016-03-09 15:36:55 +01001979 goto error;
1980 }
1981 memcpy(&trg->inc[inc_size], &inc, sizeof inc);
1982
1983 /* check duplications in include submodules */
1984 for (i = 0; i < inc_size; ++i) {
1985 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size].submodule->name)) {
Pavol Vican723de602016-03-21 15:13:20 +01001986 LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
1987 LOGVAL(LYE_SPEC, 0, 0, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
Pavol Vican55870412016-03-10 12:36:21 +01001988 trg->inc[inc_size].submodule = NULL;
Pavol Vican9b89dda2016-03-09 15:36:55 +01001989 goto error;
1990 }
1991 }
Pavol Vican55870412016-03-10 12:36:21 +01001992 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001993 return EXIT_SUCCESS;
1994
1995error:
Pavol Vican55870412016-03-10 12:36:21 +01001996 lydict_remove(module->ctx, str);
Pavol Vican9b89dda2016-03-09 15:36:55 +01001997 return EXIT_FAILURE;
1998}
Pavol Vicanf4717e62016-03-16 11:30:01 +01001999
2000int
2001yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value, int line)
2002{
2003 char *prefix;
2004 char *identif;
2005 const char *ns = NULL;
2006 int i;
2007
Pavol Vicanf4717e62016-03-16 11:30:01 +01002008 /* check to the same pointer */
2009 if (data_node != actual) {
2010 return EXIT_SUCCESS;
2011 }
2012
Pavol Vicana302aa62016-03-17 10:45:35 +01002013 prefix = strdup(value);
2014 if (!prefix) {
2015 LOGMEM;
2016 goto error;
2017 }
2018 /* find prefix anf identificator*/
2019 identif = strchr(prefix, ':');
2020 *identif = '\0';
2021 identif++;
2022
Pavol Vicanf4717e62016-03-16 11:30:01 +01002023 for(i = 0; i < module->imp_size; ++i) {
2024 if (!strcmp(module->imp[i].prefix, prefix)) {
2025 ns = module->imp[i].module->ns;
2026 break;
2027 }
2028 }
2029 if (ns && !strcmp(ns, LY_NSNACM)) {
2030 if (!strcmp(identif, "default-deny-write")) {
2031 data_node->nacm |= LYS_NACM_DENYW;
2032 } else if (!strcmp(identif, "default-deny-all")) {
2033 data_node->nacm |= LYS_NACM_DENYA;
2034 } else {
2035 LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002036 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002037 }
2038 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002039 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002040 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002041
2042error:
2043 free(prefix);
2044 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002045}
2046
2047void
2048nacm_inherit(struct lys_module *module)
2049{
2050 struct lys_node *next, *elem;
2051
2052 LY_TREE_DFS_BEGIN(module->data, next, elem) {
2053 if (elem->parent) {
2054 switch (elem->nodetype) {
2055 case LYS_GROUPING:
2056 /* extension nacm not inherited*/
2057 break;
2058 case LYS_CHOICE:
2059 case LYS_ANYXML:
2060 case LYS_USES:
2061 if (elem->parent->nodetype != LYS_GROUPING) {
2062 elem->nacm |= elem->parent->nacm;
2063 }
2064 break;
2065 default:
2066 elem->nacm |= elem->parent->nacm;
2067 break;
2068 }
2069 }
2070 LY_TREE_DFS_END(module->data, next, elem);
2071 }
2072}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002073
2074void
2075store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2076{
2077 node->flags |= flags;
2078 if (!(node->flags & LYS_CONFIG_MASK) && config_inherit) {
2079 /* get config flag from parent */
2080 if (node->parent) {
2081 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2082 } else {
2083 /* default config is true */
2084 node->flags |= LYS_CONFIG_W;
2085 }
2086 }
2087}