blob: ddb533cbb718d554c77369921ac49d001080bd9f [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 *
Pavol Vican9a3a7212016-03-23 10:04:00 +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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
Pavol Vican021488a2016-01-25 23:56:12 +010013 */
14
Pavol Vican5de33492016-02-22 14:03:24 +010015#include <ctype.h>
Pavol Vican7313fc02016-11-14 01:10:31 +010016#include <assert.h>
Pavol Vican021488a2016-01-25 23:56:12 +010017#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010018#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010019#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010020#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010021
Pavol Vican082afd02016-10-25 12:39:15 +020022static void yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size);
23static void yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size);
Pavol Vican7313fc02016-11-14 01:10:31 +010024static int yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node);
Pavol Vican05810b62016-11-23 14:07:22 +010025static void free_yang_common(struct lys_module *module, struct lys_node *node);
26void lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size);
Pavol Vican082afd02016-10-25 12:39:15 +020027
Michal Vaskofe7e5a72016-05-02 14:49:23 +020028static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010029yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010030{
Pavol Vicanbf805472016-01-26 14:24:56 +010031 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010032 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010033 free(value);
34 return 1;
35 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010036 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010037 return 0;
38 }
39}
40
Michal Vaskofe7e5a72016-05-02 14:49:23 +020041int
Pavol Vican5f0316a2016-04-05 21:21:11 +020042yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010043{
Pavol Vican6eb14e82016-02-03 12:27:13 +010044 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010045
46 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010047 case MODULE_KEYWORD:
48 module->name = lydict_insert_zc(module->ctx, value);
49 break;
50 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010051 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010052 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010053 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010054 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010055 break;
56 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010057 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010058 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020059 default:
60 free(value);
61 LOGINT;
62 ret = EXIT_FAILURE;
63 break;
Pavol Vican2a064652016-02-02 22:54:34 +010064 }
65
Pavol Vican021488a2016-01-25 23:56:12 +010066 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010067}
68
Michal Vaskofe7e5a72016-05-02 14:49:23 +020069int
Pavol Vicand0b64c12016-07-15 09:56:19 +020070yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
71{
72 int ret = EXIT_SUCCESS;
73
74 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +020075 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
76 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +020077 } else {
78 if (!strcmp(value, "1")) {
79 if (submodule) {
80 if (module->version > 1) {
81 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
82 ret = EXIT_FAILURE;
83 }
84 } else {
85 module->version = 1;
86 }
87 } else if (!strcmp(value, "1.1")) {
88 if (submodule) {
89 if (module->version != 2) {
90 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
91 ret = EXIT_FAILURE;
92 }
93 } else {
94 module->version = 2;
95 }
96 } else {
97 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
98 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +020099 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200100 }
101 free(value);
102 return ret;
103}
104
105int
Pavol Vicane024ab72016-07-27 14:27:43 +0200106yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100107{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100108 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100109
Pavol Vican1cc4e192016-10-24 16:38:31 +0200110 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100111 free(value);
112 return EXIT_FAILURE;
113 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200114
115 if (imp) {
116 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
117 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100118 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100119 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100120
Pavol Vicanbf805472016-01-26 14:24:56 +0100121 return ret;
122}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100123
Pavol Vican1cc4e192016-10-24 16:38:31 +0200124static int
125yang_fill_import(struct lys_module *module, struct lys_import *imp_old, struct lys_import *imp_new, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100126{
Pavol Vican0da132e2016-03-21 12:03:03 +0100127 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200128 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100129
Pavol Vican1cc4e192016-10-24 16:38:31 +0200130 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200131 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200132 goto error;
133 } else {
134 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
135 goto error;
136 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200137 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200138 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100139 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200140 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100141 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200142 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100143 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200144 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100145 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100146
Pavol Vican6eb14e82016-02-03 12:27:13 +0100147 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200148
149error:
150 free(value);
151 lydict_remove(module->ctx, imp_old->dsc);
152 lydict_remove(module->ctx, imp_old->ref);
153 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100154}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100155
156int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100157yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100158{
159 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100160 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100161
162 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100163 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100164 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100165 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100166 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200167 } else if (!strcmp("import", where)){
168 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
169 } else if (!strcmp("include", where)){
170 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100171 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100173 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100174 }
175 return ret;
176}
177
178int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100179yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100180{
181 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100182 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100183
184 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100185 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100186 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100187 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100188 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200189 } else if (!strcmp("import", where)){
190 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
191 } else if (!strcmp("include", where)){
192 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100193 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100194 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100195 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100196 }
197 return ret;
198}
Pavol Vicanbedff692016-02-03 14:29:17 +0100199
Pavol Vican866d9912016-10-25 09:13:30 +0200200void
201yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval)
Pavol Vicanbedff692016-02-03 14:29:17 +0100202{
Pavol Vicanbedff692016-02-03 14:29:17 +0100203 /* first member of array is last revision */
Pavol Vican866d9912016-10-25 09:13:30 +0200204 if ((module->rev_size - 1) && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100205 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
206 memcpy(module->rev[0].date, value, LY_REV_SIZE);
207 retval->dsc = module->rev[0].dsc;
208 retval->ref = module->rev[0].ref;
209 retval = module->rev;
210 retval->dsc = NULL;
211 retval->ref = NULL;
212 } else {
213 memcpy(retval->date, value, LY_REV_SIZE);
214 }
Pavol Vicanbedff692016-02-03 14:29:17 +0100215 free(value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100216}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100217
218int
Pavol Vicana1827962016-02-29 15:39:42 +0100219yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100220{
Pavol Vican45ccc592016-03-09 18:53:48 +0100221 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100222 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
223 LOGMEM;
224 return EXIT_FAILURE;
225 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100226 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100227 }
228 }
229 (*size)++;
230 return EXIT_SUCCESS;
231}
Pavol Vicane1354e92016-02-09 14:02:09 +0100232
Pavol Vicane1354e92016-02-09 14:02:09 +0100233int
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100234yang_read_if_feature(struct lys_module *module, void *ptr, void *parent, char *value,
235 struct unres_schema *unres, enum yytokentype type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100236{
237 const char *exp;
238 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100239 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200240 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100241 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200242 struct lys_type_enum *e;
243 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200244 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100245
Michal Vasko97b32be2016-07-25 10:59:53 +0200246 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
247 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
248 free(value);
249 return EXIT_FAILURE;
250 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100251
Michal Vasko56d082c2016-10-25 14:00:42 +0200252 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100253 free(value);
254 return EXIT_FAILURE;
255 }
256 free(value);
257
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200258 switch (type) {
259 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100260 f = (struct lys_feature *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200261 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, 1, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200262 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200263 break;
264 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200265 i = (struct lys_ident *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200266 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, 0, unres);
Pavol Vican4df80542016-08-08 09:37:55 +0200267 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200268 break;
269 case ENUM_KEYWORD:
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100270 e = (struct lys_type_enum *) ptr;
271 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *) parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200272 e->iffeature_size++;
273 break;
274 case BIT_KEYWORD:
Pavol Vican5c8a9ad2016-11-22 11:50:54 +0100275 b = (struct lys_type_bit *) ptr;
276 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *) parent, 0, unres);
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200277 b->iffeature_size++;
278 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200279 case REFINE_KEYWORD:
280 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
Radek Krejci9de2c042016-10-19 16:53:06 +0200281 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, 0, unres);
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200282 r->iffeature_size++;
283 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200284 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100285 n = (struct lys_node *) ptr;
Radek Krejci9de2c042016-10-19 16:53:06 +0200286 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, 0, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200287 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200288 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100289 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100290 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100291
Radek Krejci9ff0a922016-07-14 13:08:05 +0200292 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100293 return EXIT_FAILURE;
294 }
295 return EXIT_SUCCESS;
296}
297
Pavol Vican4fb66c92016-03-17 10:32:27 +0100298int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200299yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100300{
301 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100302 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100303 return EXIT_FAILURE;
304 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200305 if (shortint) {
306 *((uint8_t *)flags) |= (uint8_t)value;
307 } else {
308 *flags |= value;
309 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100310 return EXIT_SUCCESS;
311 }
312}
313
Pavol Vicanbbdef532016-02-09 14:52:12 +0100314int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100315yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100316{
317 const char *exp;
318
Pavol Vican0adf01d2016-03-22 12:29:33 +0100319 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100320 free(value);
321 if (!exp) {
322 return EXIT_FAILURE;
323 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200324
Pavol Vican0adf01d2016-03-22 12:29:33 +0100325 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100326 lydict_remove(module->ctx, exp);
327 return EXIT_FAILURE;
328 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100329
Pavol Vicanbbdef532016-02-09 14:52:12 +0100330 lydict_remove(module->ctx, exp);
331 return EXIT_SUCCESS;
332}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100333
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100334int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100335yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100336{
337 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100338
Pavol Vicandde090a2016-08-30 15:12:14 +0200339 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100340 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100341 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200342 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100343 }
344 return ret;
345}
Pavol Vicanb5687112016-02-09 22:35:59 +0100346
347int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100348yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100349{
350 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100351 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100352 free(value);
353 return EXIT_FAILURE;
354 } else {
355 cont->presence = lydict_insert_zc(module->ctx, value);
356 return EXIT_SUCCESS;
357 }
358}
359
Pavol Vican235dbd42016-02-10 10:34:19 +0100360void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200361yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100362{
363 struct lys_when *retval;
364
365 retval = calloc(1, sizeof *retval);
366 if (!retval) {
367 LOGMEM;
368 free(value);
369 return NULL;
370 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100371 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200372 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100373 goto error;
374 }
375 switch (type) {
376 case CONTAINER_KEYWORD:
377 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100378 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100379 goto error;
380 }
381 ((struct lys_node_container *)node)->when = retval;
382 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200383 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100384 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200385 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200386 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100387 goto error;
388 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200389 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100390 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100391 case CHOICE_KEYWORD:
392 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100393 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100394 goto error;
395 }
396 ((struct lys_node_choice *)node)->when = retval;
397 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100398 case CASE_KEYWORD:
399 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100400 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100401 goto error;
402 }
403 ((struct lys_node_case *)node)->when = retval;
404 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100405 case LEAF_KEYWORD:
406 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100407 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100408 goto error;
409 }
410 ((struct lys_node_leaf *)node)->when = retval;
411 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100412 case LEAF_LIST_KEYWORD:
413 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100414 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100415 goto error;
416 }
417 ((struct lys_node_leaflist *)node)->when = retval;
418 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100419 case LIST_KEYWORD:
420 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100421 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100422 goto error;
423 }
424 ((struct lys_node_list *)node)->when = retval;
425 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100426 case USES_KEYWORD:
427 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100428 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100429 goto error;
430 }
431 ((struct lys_node_uses *)node)->when = retval;
432 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100433 case AUGMENT_KEYWORD:
434 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100435 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100436 goto error;
437 }
438 ((struct lys_node_augment *)node)->when = retval;
439 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200440 default:
441 goto error;
442 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100443 }
444 free(value);
445 return retval;
446
447error:
448 free(value);
449 lys_when_free(module->ctx, retval);
450 return NULL;
451}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100452
453void *
Pavol Vican05810b62016-11-23 14:07:22 +0100454yang_read_node(struct lys_module *module, struct lys_node *parent, struct lys_node **root,
455 char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100456{
Pavol Vican05810b62016-11-23 14:07:22 +0100457 struct lys_node *node, **child;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100458
Pavol Vican7cadfe72016-02-11 12:33:34 +0100459 node = calloc(1, sizeof_struct);
460 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100461 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100462 LOGMEM;
463 return NULL;
464 }
Pavol Vican531a9132016-03-03 10:10:09 +0100465 if (value) {
466 node->name = lydict_insert_zc(module->ctx, value);
467 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100468 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100469 node->nodetype = nodetype;
Pavol Vicanc54a8f72016-11-23 16:45:55 +0100470 node->parent = parent;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100471
472 /* insert the node into the schema tree */
Pavol Vican05810b62016-11-23 14:07:22 +0100473 child = (parent) ? &parent->child : root;
474 if (*child) {
475 (*child)->prev->next = node;
476 (*child)->prev = node;
477 } else {
478 *child = node;
479 node->prev = node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100480 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100481 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100482}
483
484int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200485yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100486{
487 int ret;
488
489 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100490 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100491 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100492 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100493 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100494 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100495 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200496 default:
497 free(value);
498 LOGINT;
499 ret = EXIT_FAILURE;
500 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100501 }
502 return ret;
503}
504
505int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200506yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100507{
508 int ret;
509
510 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100511 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100512 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100513 break;
514 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100515 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100516 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100517 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100518 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100519 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200520 default:
521 free(value);
522 LOGINT;
523 ret = EXIT_FAILURE;
524 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100525 }
526 return ret;
527}
Pavol Vican5de33492016-02-22 14:03:24 +0100528
529int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100530yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100531{
532 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100533 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100534
535 exp = value = (char *) list->keys;
536 while ((value = strpbrk(value, " \t\n"))) {
537 list->keys_size++;
538 while (isspace(*value)) {
539 value++;
540 }
541 }
542 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100543
544 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100545 list->keys = calloc(list->keys_size, sizeof *list->keys);
546 if (!list->keys) {
547 LOGMEM;
Radek Krejci5c08a992016-11-02 13:30:04 +0100548 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100549 }
Radek Krejci5c08a992016-11-02 13:30:04 +0100550 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
551 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
552 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100553 }
Pavol Vican5de33492016-02-22 14:03:24 +0100554 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100555}
556
557int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100558yang_fill_unique(struct lys_module *module, struct lys_node_list *list, struct lys_unique *unique, char *value, struct unres_schema *unres)
Pavol Vican85f12022016-03-05 16:30:35 +0100559{
560 int i, j;
561 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200562 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100563
564 /* count the number of unique leafs in the value */
565 vaux = value;
566 while ((vaux = strpbrk(vaux, " \t\n"))) {
567 unique->expr_size++;
568 while (isspace(*vaux)) {
569 vaux++;
570 }
571 }
572 unique->expr_size++;
573 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
574 if (!unique->expr) {
575 LOGMEM;
576 goto error;
577 }
578
579 for (i = 0; i < unique->expr_size; i++) {
580 vaux = strpbrk(value, " \t\n");
581 if (!vaux) {
582 /* the last token, lydict_insert() will count its size on its own */
583 vaux = value;
584 }
585
586 /* store token into unique structure */
587 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
588
589 /* check that the expression does not repeat */
590 for (j = 0; j < i; j++) {
591 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100592 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
593 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100594 goto error;
595 }
596 }
597 /* try to resolve leaf */
598 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200599 unique_info = malloc(sizeof *unique_info);
600 unique_info->list = (struct lys_node *)list;
601 unique_info->expr = unique->expr[i];
602 unique_info->trg_type = &unique->trg_type;
603 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200604 goto error;
605 }
Pavol Vican85f12022016-03-05 16:30:35 +0100606 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200607 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100608 goto error;
609 }
610 }
611
612 /* move to next token */
613 value = vaux;
614 while(isspace(*value)) {
615 value++;
616 }
617 }
618
619 return EXIT_SUCCESS;
620
621error:
622 return EXIT_FAILURE;
623}
624
625int
Pavol Vican5de33492016-02-22 14:03:24 +0100626yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
627{
628 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100629 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100630
631 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100632 str = (char *)list->unique[k].expr;
633 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100634 goto error;
635 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100636 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100637 }
638 return EXIT_SUCCESS;
639
640error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100641 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100642 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100643}
644
Pavol Vican07f220f2016-09-02 13:04:37 +0200645int
Pavol Vican81344ac2016-09-02 14:23:06 +0200646yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100647{
Pavol Vican81344ac2016-09-02 14:23:06 +0200648 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
649 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
650 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100651 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200652 if (stype->type->info.lref.path) {
653 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
654 goto error;
655 }
656 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
657 stype->base = LY_TYPE_LEAFREF;
658 return EXIT_SUCCESS;
659
660error:
661 free(value);
662 return EXIT_FAILURE;
663}
664
665int
666yang_read_require_instance(struct yang_type *stype, int req)
667{
668 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
669 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
670 return EXIT_FAILURE;
671 }
672 if (stype->type->info.lref.req) {
673 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
674 return EXIT_FAILURE;
675 }
676 stype->type->info.lref.req = req;
677 stype->base = LY_TYPE_LEAFREF;
678 return EXIT_SUCCESS;
679}
680
681int
Pavol Vican07f220f2016-09-02 13:04:37 +0200682yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100683{
Pavol Vican07f220f2016-09-02 13:04:37 +0200684 const char *value;
685 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100686
Pavol Vican07f220f2016-09-02 13:04:37 +0200687 if (stype->base && stype->base != LY_TYPE_IDENT) {
688 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
689 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100690 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200691
692 stype->base = LY_TYPE_IDENT;
693 /* store in the JSON format */
694 value = transform_schema2json(module, expr);
695 free(expr);
696
697 if (!value) {
698 return EXIT_FAILURE;
699 }
700 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100701 lydict_remove(module->ctx, value);
702
703 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200704 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100705 }
706
Pavol Vican07f220f2016-09-02 13:04:37 +0200707 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100708}
709
Pavol Vican73e7c992016-02-24 12:18:05 +0100710int
Pavol Vican7313fc02016-11-14 01:10:31 +0100711yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, struct lys_type *type, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100712{
Pavol Vican81344ac2016-09-02 14:23:06 +0200713 int i, j, rc, ret = -1;
714 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100715 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200716 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200717 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200718 struct lys_type *dertype;
719 struct lys_type_enum *enms_sc = NULL;
720 struct lys_type_bit *bits_sc = NULL;
721 struct lys_type_bit bit_tmp;
Pavol Vican73e7c992016-02-24 12:18:05 +0100722
Pavol Vican0adf01d2016-03-22 12:29:33 +0100723 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100724 if (!value) {
725 goto error;
726 }
727
728 i = parse_identifier(value);
729 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100730 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100731 lydict_remove(module->ctx, value);
732 goto error;
733 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200734 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100735 name = value;
736 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100737 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100738 name += i;
739 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100740 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100741 lydict_remove(module->ctx, value);
742 goto error;
743 }
744 ++name;
745 }
746
Pavol Vican7313fc02016-11-14 01:10:31 +0100747 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100748 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100749 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200750 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100751 goto error;
752
Michal Vasko01c6fd22016-05-20 11:43:05 +0200753 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100754 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200755 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200756 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100757 ret = EXIT_FAILURE;
758 goto error;
759 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200760 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200761
Pavol Vican7313fc02016-11-14 01:10:31 +0100762 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200763 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200764 * unresolved item left inside the grouping, LY_TYPE_ERR used as a flag for types inside a grouping. */
Radek Krejcic13db382016-08-16 10:52:42 +0200765 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
766 if (siter) {
767 if (!((struct lys_node_grp *)siter)->nacm) {
768 LOGINT;
769 goto error;
770 }
771 ((struct lys_node_grp *)siter)->nacm--;
772 } else {
773 LOGINT;
774 goto error;
775 }
776 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200777
778 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100779 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
780 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200781 goto error;
782 }
783
Pavol Vican8bd72e42016-08-29 09:53:05 +0200784 base = typ->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100785 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100786 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100787 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100788 }
789 switch (base) {
790 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100791 if (type->base == LY_TYPE_BINARY) {
792 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100793 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100794 goto error;
795 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100796 type->info.binary.length = type->info.str.length;
797 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
798 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100799 goto error;
800 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100801 } else if (type->base == LY_TYPE_STRING) {
802 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
803 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100804 goto error;
805 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100806 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100807 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100808 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100809 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100810 break;
811 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100812 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100813 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100814 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100815 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100816 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100817 goto error;
818 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100819 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100820 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100821 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100822 goto error;
823 }
Radek Krejci4800f652016-09-08 14:02:52 +0200824
825 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100826 if (type->der->type.der) {
827 type->info.dec64.dig = type->der->type.info.dec64.dig;
828 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200829 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100830 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
831 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200832 goto error;
833 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100834 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
835 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100836 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100837 goto error;
838 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100839 type->info.num.range = type->info.dec64.range;
840 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
841 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100842 goto error;
843 }
844 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100845 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100846 goto error;
847 }
848 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100849 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100850 if (type->base != LY_TYPE_ENUM) {
851 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100852 goto error;
853 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100854 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200855
856 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100857 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200858 /* type is derived directly from buit-in enumeartion type and enum statement is required */
859 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
860 goto error;
861 }
862 } else {
863 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100864 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200865 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
866 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
867 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
868 goto error;
869 }
870
871 /* restricted enumeration type - the name MUST be used in the base type */
872 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100873 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200874 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100875 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200876 break;
877 }
878 }
879 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100880 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200881 goto error;
882 }
883
Pavol Vican7313fc02016-11-14 01:10:31 +0100884 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200885 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100886 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200887 } else {
888 /* check that the assigned value corresponds to the original
889 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100890 if (type->info.enums.enm[i].value != enms_sc[j].value) {
891 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200892 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100893 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
894 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200895 goto error;
896 }
897 }
898 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100899 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100900 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100901 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100902 if (type->base != LY_TYPE_BITS) {
903 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100904 goto error;
905 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100906 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200907
908 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100909 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200910 /* type is derived directly from buit-in bits type and bit statement is required */
911 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
912 goto error;
913 }
914 } else {
915 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100916 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200917 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
918 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
919 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
920 goto error;
921 }
922
923 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +0100924 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200925 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100926 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200927 break;
928 }
929 }
930 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100931 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200932 goto error;
933 }
934
935 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100936 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200937 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100938 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200939 } else {
940 /* check that the assigned position corresponds to the original
941 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100942 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
943 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200944 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100945 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
946 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200947 goto error;
948 }
949 }
950 }
Pavol Vican03a59442016-03-21 15:23:45 +0100951 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200952
Pavol Vican7313fc02016-11-14 01:10:31 +0100953 for (i = type->info.bits.count - 1; i > 0; i--) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200954 j = i;
955
956 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +0100957 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200958 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +0100959 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
960 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
961 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200962 j--;
963 }
Pavol Vican03a59442016-03-21 15:23:45 +0100964 }
965 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100966 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +0100967 if (type->base == LY_TYPE_INST) {
968 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +0200969 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100970 goto error;
971 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100972 if ((req = type->info.lref.req)) {
973 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +0200974 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100975 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +0200976 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +0100977 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +0200978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
979 goto error;
980 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200981 /* flag resolving for later use */
982 if (!tpdftype) {
983 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
984 if (siter) {
985 /* just a flag - do not resolve */
986 tpdftype = 1;
987 }
988 }
989
Pavol Vican7313fc02016-11-14 01:10:31 +0100990 if (type->info.lref.path) {
991 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +0200992 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
993 goto error;
994 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100995 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +0100996 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +0100997 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100998 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +0100999 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +01001000 goto error;
1001 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001002 /* try to resolve leafref path only when this is instantiated
1003 * leaf, so it is not:
1004 * - typedef's type,
1005 * - in grouping definition,
1006 * - just instantiated in a grouping definition,
1007 * because in those cases the nodes referenced in path might not be present
1008 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +01001009 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001010 goto error;
1011 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001012 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001013 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001014 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001015 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001016 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +01001017 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +02001018 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001019 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001020 goto error;
1021 }
Radek Krejci742be352016-07-17 12:18:54 +02001022
Radek Krejci3a5501d2016-07-18 22:03:34 +02001023 /* add pointer to leafref target, only on leaves (not in typedefs) */
Pavol Vican7313fc02016-11-14 01:10:31 +01001024 if (type->info.lref.target && lys_leaf_add_leafref_target(type->info.lref.target, (struct lys_node *)type->parent)) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001025 goto error;
Radek Krejci742be352016-07-17 12:18:54 +02001026 }
Pavol Vican191613a2016-02-26 16:21:32 +01001027 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001028 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001029 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001030 goto error;
1031 }
1032 break;
1033 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +01001034 if (type->base != LY_TYPE_IDENT) {
1035 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001036 goto error;
1037 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001038 if (type->der->type.der) {
1039 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001040 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1041 goto error;
1042 }
1043 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +01001044 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +02001045 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1046 goto error;
1047 }
1048 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001049 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001050 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +01001051 if (type->base != LY_TYPE_UNION) {
1052 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001053 goto error;
1054 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001055 if (!type->info.uni.types) {
1056 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001057 /* this is just a derived type with no additional type specified/required */
1058 break;
1059 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001060 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001061 goto error;
1062 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001063 for (i = 0; i < type->info.uni.count; i++) {
1064 type->info.uni.types[i].parent = type->parent;
1065 if (unres_schema_add_node(module, unres, &type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001066 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001067 goto error;
1068 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001069 if (module->version < 2) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001070 if (type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001071 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1072 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01001073 } else if (type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001074 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1075 goto error;
1076 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001077 }
1078 }
1079 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001080
1081 default:
1082 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001083 if (type->base != base) {
1084 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001085 goto error;
1086 }
1087 } else {
1088 LOGINT;
1089 goto error;
1090 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001091 }
1092 return EXIT_SUCCESS;
1093
1094error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001095 if (type->module_name) {
1096 lydict_remove(module->ctx, type->module_name);
1097 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001098 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001099 if (base) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001100 type->base = base;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001101 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001102 return ret;
1103}
1104
1105void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001106yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001107{
1108 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001109 struct type_deviation *dev;
1110 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001111
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001112 typ = calloc(1, sizeof *typ);
1113 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001114 LOGMEM;
1115 return NULL;
1116 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001117
1118 typ->flags = LY_YANG_STRUCTURE_FLAG;
1119 switch (type) {
1120 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001121 if (((struct lys_node_leaf *)parent)->type.der) {
1122 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1123 goto error;
1124 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001125 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1126 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1127 typ->type = &((struct lys_node_leaf *)parent)->type;
1128 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001129 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001130 if (((struct lys_node_leaflist *)parent)->type.der) {
1131 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1132 goto error;
1133 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001134 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1135 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1136 typ->type = &((struct lys_node_leaflist *)parent)->type;
1137 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001138 case UNION_KEYWORD:
1139 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1140 typ->type = (struct lys_type *)parent;
1141 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001142 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001143 if (((struct lys_tpdf *)parent)->type.der) {
1144 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1145 goto error;
1146 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001147 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1148 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001149 break;
1150 case REPLACE_KEYWORD:
1151 /* deviation replace type*/
1152 dev = (struct type_deviation *)parent;
1153 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001154 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001155 goto error;
1156 }
1157 /* check target node type */
1158 if (dev->target->nodetype == LYS_LEAF) {
1159 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1160 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1161 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1162 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001163 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1164 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001165 goto error;
1166 }
1167
1168 /* remove type and initialize it */
1169 lys_type_free(module->ctx, typ->type);
1170 tmp_parent = typ->type->parent;
1171 memset(typ->type, 0, sizeof *typ->type);
1172 typ->type->parent = tmp_parent;
1173
1174 /* replace it with the value specified in deviation */
1175 /* HACK for unres */
1176 typ->type->der = (struct lys_tpdf *)typ;
1177 dev->deviate->type = typ->type;
1178 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001179 default:
1180 goto error;
1181 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001182 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001183 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001184 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001185
1186error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001187 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001188 free(typ);
1189 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001190}
1191
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001192void
1193yang_delete_type(struct lys_module *module, struct yang_type *stype)
1194{
1195 int i;
1196
Pavol Vican77a95e52016-08-15 09:49:26 +02001197 if (!stype) {
1198 return;
1199 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001200 stype->type->base = stype->base;
1201 stype->type->der = NULL;
1202 lydict_remove(module->ctx, stype->name);
1203 if (stype->base == LY_TYPE_UNION) {
1204 for (i = 0; i < stype->type->info.uni.count; i++) {
1205 if (stype->type->info.uni.types[i].der) {
1206 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1207 }
1208 }
1209 }
1210 free(stype);
1211}
1212
Pavol Vican73e7c992016-02-24 12:18:05 +01001213void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001214yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001215{
1216 struct lys_restr **length;
1217
Pavol Vican6b072512016-04-04 10:50:21 +02001218 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001219 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001220 typ->base = LY_TYPE_STRING;
1221 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001222 length = &typ->type->info.binary.length;
1223 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001224 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001225 goto error;
1226 }
1227
1228 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001229 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001230 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001231 }
1232 *length = calloc(1, sizeof **length);
1233 if (!*length) {
1234 LOGMEM;
1235 goto error;
1236 }
1237 (*length)->expr = lydict_insert_zc(module->ctx, value);
1238 return *length;
1239
1240error:
1241 free(value);
1242 return NULL;
1243
1244}
Pavol Vican1c203db2016-02-24 14:05:23 +01001245
Pavol Vican6eecf302016-08-10 11:09:05 +02001246int
1247yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001248{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001249 char *buf;
1250 size_t len;
1251
Michal Vasko0aee5c12016-06-17 14:27:26 +02001252 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001253 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001254 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001255 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001256
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001257 len = strlen(value);
1258 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001259
1260 if (!buf) {
1261 LOGMEM;
1262 free(value);
1263 return EXIT_FAILURE;
1264 }
1265
1266 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001267 strcpy(&buf[1], value);
1268 free(value);
1269
Pavol Vican6eecf302016-08-10 11:09:05 +02001270 pattern->expr = lydict_insert_zc(module->ctx, buf);
1271 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001272}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001273
1274void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001275yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001276{
Pavol Vican6b072512016-04-04 10:50:21 +02001277 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001278 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001279 goto error;
1280 }
Pavol Vican6b072512016-04-04 10:50:21 +02001281 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001282 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001283 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001284 goto error;
1285 }
1286 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1287 if (!typ->type->info.dec64.range) {
1288 LOGMEM;
1289 goto error;
1290 }
1291 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1292 return typ->type->info.dec64.range;
1293
1294error:
1295 free(value);
1296 return NULL;
1297}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001298
1299int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001300yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001301{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001302 unsigned int i;
1303
Pavol Vican6b072512016-04-04 10:50:21 +02001304 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1305 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001306 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001307 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001308 goto error;
1309 }
1310 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001311 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001312 goto error;
1313 }
1314 /* range check */
1315 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001316 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001317 goto error;
1318 }
1319 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001320 typ->type->info.dec64.div = 10;
1321 for (i = 1; i < value; i++) {
1322 typ->type->info.dec64.div *= 10;
1323 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001324 return EXIT_SUCCESS;
1325
1326error:
1327 return EXIT_FAILURE;
1328}
Pavol Vican79a763d2016-02-25 15:41:27 +01001329
Pavol Vican874715f2016-10-25 14:52:08 +02001330int
1331yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001332{
Pavol Vican874715f2016-10-25 14:52:08 +02001333 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001334
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01001335 typ->base = LY_TYPE_ENUM;
Pavol Vicanc6662412016-08-30 08:06:28 +02001336 if (!value[0]) {
1337 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1338 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1339 free(value);
1340 goto error;
1341 }
1342
Pavol Vican79a763d2016-02-25 15:41:27 +01001343 enm->name = lydict_insert_zc(module->ctx, value);
1344
1345 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1346 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001347 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001348 goto error;
1349 }
1350
Pavol Vican874715f2016-10-25 14:52:08 +02001351 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001352 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001353 for (i = 0; i < j; i++) {
1354 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[j].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001355 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001356 goto error;
1357 }
1358 }
1359
Pavol Vican874715f2016-10-25 14:52:08 +02001360 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001361
1362error:
Pavol Vican874715f2016-10-25 14:52:08 +02001363 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001364}
1365
1366int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001367yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001368{
1369 int i, j;
1370
1371 if (!assign) {
1372 /* assign value automatically */
1373 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001374 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001375 goto error;
1376 }
1377 enm->value = *value;
1378 enm->flags |= LYS_AUTOASSIGNED;
1379 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001380 } else if (typ->type->info.enums.enm == enm) {
1381 /* change value, which is assigned automatically, if first enum has value. */
1382 *value = typ->type->info.enums.enm[0].value;
1383 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001384 }
1385
1386 /* check that the value is unique */
1387 j = typ->type->info.enums.count-1;
1388 for (i = 0; i < j; i++) {
1389 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001390 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001391 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1392 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001393 goto error;
1394 }
1395 }
1396
1397 return EXIT_SUCCESS;
1398
1399error:
1400 return EXIT_FAILURE;
1401}
Pavol Vican9887c682016-02-29 11:32:01 +01001402
Pavol Vican59e8dee2016-10-25 15:29:38 +02001403int
1404yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001405{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001406 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001407
Pavol Vican59e8dee2016-10-25 15:29:38 +02001408 bit->name = lydict_insert_zc(module->ctx, value);
1409 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001410 free(value);
1411 goto error;
1412 }
Pavol Vican9887c682016-02-29 11:32:01 +01001413
Pavol Vican59e8dee2016-10-25 15:29:38 +02001414 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001415 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001416 for (i = 0; i < j; i++) {
Pavol Vican9887c682016-02-29 11:32:01 +01001417 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001418 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001419 goto error;
1420 }
1421 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001422 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001423
1424error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001425 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001426}
1427
1428int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001429yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001430{
1431 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001432
1433 if (!assign) {
1434 /* assign value automatically */
1435 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001436 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001437 goto error;
1438 }
1439 bit->pos = (uint32_t)*value;
1440 bit->flags |= LYS_AUTOASSIGNED;
1441 (*value)++;
1442 }
1443
1444 j = typ->type->info.bits.count - 1;
1445 /* check that the value is unique */
1446 for (i = 0; i < j; i++) {
1447 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001448 LOGVAL(LYE_BITS_DUPVAL, LY_VLOG_NONE, NULL, bit->pos, bit->name, typ->type->info.bits.bit[i].name);
Pavol Vican9887c682016-02-29 11:32:01 +01001449 goto error;
1450 }
1451 }
1452
Pavol Vican9887c682016-02-29 11:32:01 +01001453 return EXIT_SUCCESS;
1454
1455error:
1456 return EXIT_FAILURE;
1457}
Pavol Vican0df02b02016-03-01 10:28:50 +01001458
1459void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001460yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001461{
1462 struct lys_refine *rfn;
1463
1464 rfn = &uses->refine[uses->refine_size];
1465 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001466 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001467 free(value);
1468 if (!rfn->target_name) {
1469 return NULL;
1470 }
1471 return rfn;
1472}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001473
1474void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001475yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001476{
1477 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001478
1479 if (parent) {
1480 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1481 } else {
1482 aug = &module->augment[module->augment_size];
1483 }
1484 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001485 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001486 free(value);
1487 if (!aug->target_name) {
1488 return NULL;
1489 }
1490 aug->parent = parent;
1491 aug->module = module;
1492 if (parent) {
1493 ((struct lys_node_uses *)parent)->augment_size++;
1494 } else {
1495 module->augment_size++;
1496 }
1497 return aug;
1498}
Pavol Vican220e5a12016-03-03 14:19:43 +01001499
1500void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001501yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001502{
1503 struct lys_node *dev_target = NULL;
1504 struct lys_deviation *dev;
1505 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001506 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001507
Pavol Vican220e5a12016-03-03 14:19:43 +01001508 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001509 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001510 free(value);
1511 if (!dev->target_name) {
1512 goto error;
1513 }
1514
Pavol Vican974377b2016-03-23 00:38:53 +01001515 deviation = calloc(1, sizeof *deviation);
1516 if (!deviation) {
1517 LOGMEM;
1518 goto error;
1519 }
1520
Pavol Vican220e5a12016-03-03 14:19:43 +01001521 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001522 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Pavol Vican220e5a12016-03-03 14:19:43 +01001523 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001524 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001525 goto error;
1526 }
Radek Krejcic4283442016-04-22 09:19:27 +02001527 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001528 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1529 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001530 goto error;
1531 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001532
Pavol Vican220e5a12016-03-03 14:19:43 +01001533 /*save pointer to the deviation and deviated target*/
1534 deviation->deviation = dev;
1535 deviation->target = dev_target;
1536
Pavol Vican38321d02016-08-16 14:56:02 +02001537 deviation->dflt_check = ly_set_new();
1538 if (!deviation->dflt_check) {
1539 LOGMEM;
1540 goto error;
1541 }
1542
Pavol Vican220e5a12016-03-03 14:19:43 +01001543 return deviation;
1544
1545error:
1546 free(deviation);
1547 lydict_remove(module->ctx, dev->target_name);
1548 return NULL;
1549}
Pavol Vican4c90c642016-03-03 15:06:47 +01001550
1551int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001552yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001553{
1554 int i;
1555
1556 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001557 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001558 return EXIT_FAILURE;
1559 }
1560 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1561
1562 /* you cannot remove a key leaf */
1563 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1564 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1565 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001566 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1567 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001568 return EXIT_FAILURE;
1569 }
1570 }
1571 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001572
Pavol Vican4c90c642016-03-03 15:06:47 +01001573 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001574 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001575 dev->deviation->orig_node = dev->target;
1576
1577 dev->deviation->deviate_size = 1;
1578 return EXIT_SUCCESS;
1579}
Pavol Vican85f12022016-03-05 16:30:35 +01001580
1581int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001582yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001583{
1584 struct unres_schema tmp_unres;
1585
1586 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1587 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1588 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001589 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001590 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001591 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1592 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001593 return EXIT_FAILURE;
1594 }
1595
1596 /* store a shallow copy of the original node */
1597 if (!dev->deviation->orig_node) {
1598 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001599 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001600 /* just to be safe */
1601 if (tmp_unres.count) {
1602 LOGINT;
1603 return EXIT_FAILURE;
1604 }
1605 }
1606
1607 return EXIT_SUCCESS;
1608}
1609
1610int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001611yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001612{
1613 const char **stritem;
1614
1615 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001616 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001617 free(value);
1618 goto error;
1619 }
1620
1621 /* check target node type */
1622 if (dev->target->nodetype == LYS_LEAFLIST) {
1623 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1624 } else if (dev->target->nodetype == LYS_LEAF) {
1625 stritem = &((struct lys_node_leaf *)dev->target)->units;
1626 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001627 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1628 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001629 free(value);
1630 goto error;
1631 }
1632
1633 dev->deviate->units = lydict_insert_zc(ctx, value);
1634
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001635 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1636 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001637 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001638 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1639 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001640 goto error;
1641 }
1642 /* remove current units value of the target */
1643 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001644 } else {
1645 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1646 /* check that there is no current value */
1647 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001648 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1649 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001650 goto error;
1651 }
1652 } else { /* replace */
1653 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001654 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1655 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001656 goto error;
1657 }
1658 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001659 /* remove current units value of the target ... */
1660 lydict_remove(ctx, *stritem);
1661
1662 /* ... and replace it with the value specified in deviation */
1663 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1664 }
1665
Pavol Vican85f12022016-03-05 16:30:35 +01001666 return EXIT_SUCCESS;
1667
1668error:
1669 return EXIT_FAILURE;
1670}
1671
1672int
Pavol Vican974377b2016-03-23 00:38:53 +01001673yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001674{
Pavol Vican85f12022016-03-05 16:30:35 +01001675 /* check target node type */
1676 switch (dev->target->nodetype) {
1677 case LYS_LEAF:
1678 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1679 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1680 break;
1681 case LYS_CONTAINER:
1682 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1683 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1684 break;
1685 case LYS_LEAFLIST:
1686 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1687 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1688 break;
1689 case LYS_LIST:
1690 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1691 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1692 break;
1693 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001694 case LYS_ANYDATA:
1695 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1696 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001697 break;
1698 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001699 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1700 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001701 goto error;
1702 }
1703
Michal Vasko508a50d2016-09-07 14:50:33 +02001704 /* flag will be checked again, clear it for now */
Michal Vaskoe9914d12016-10-07 14:32:37 +02001705 dev->target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001706
Pavol Vican85f12022016-03-05 16:30:35 +01001707 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1708 /* reallocate the must array of the target */
1709 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1710 if (!dev->deviate->must) {
1711 LOGMEM;
1712 goto error;
1713 }
1714 *dev->trg_must = dev->deviate->must;
1715 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1716 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001717 } else {
1718 /* LY_DEVIATE_DEL */
1719 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1720 if (!dev->deviate->must) {
1721 LOGMEM;
1722 goto error;
1723 }
Pavol Vican85f12022016-03-05 16:30:35 +01001724 }
1725
1726 return EXIT_SUCCESS;
1727
1728error:
1729 return EXIT_FAILURE;
1730}
1731
1732int
Pavol Vican974377b2016-03-23 00:38:53 +01001733yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001734{
Pavol Vican85f12022016-03-05 16:30:35 +01001735 struct lys_node_list *list;
1736
1737 /* check target node type */
1738 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001739 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1740 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001741 goto error;
1742 }
1743
1744 list = (struct lys_node_list *)dev->target;
1745 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1746 /* reallocate the unique array of the target */
1747 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1748 if (!dev->deviate->unique) {
1749 LOGMEM;
1750 goto error;
1751 }
1752 list->unique = dev->deviate->unique;
1753 dev->deviate->unique = &list->unique[list->unique_size];
1754 dev->deviate->unique_size = c_uniq;
1755 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001756 } else {
1757 /* LY_DEVIATE_DEL */
1758 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1759 if (!dev->deviate->unique) {
1760 LOGMEM;
1761 goto error;
1762 }
Pavol Vican85f12022016-03-05 16:30:35 +01001763 }
1764
1765 return EXIT_SUCCESS;
1766
1767error:
1768 return EXIT_FAILURE;
1769}
1770
1771int
Pavol Vican38321d02016-08-16 14:56:02 +02001772yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001773{
Pavol Vican38321d02016-08-16 14:56:02 +02001774 int i;
1775 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001776
Pavol Vican38321d02016-08-16 14:56:02 +02001777 /* check target node type */
1778 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1779 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1780 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1781 goto error;
1782 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1783 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1784 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1785 goto error;
1786 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1787 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1788 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001789 goto error;
1790 }
1791
Pavol Vican38321d02016-08-16 14:56:02 +02001792 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1793 /* check that there is no current value */
1794 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
1795 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
1796 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1797 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001798 goto error;
1799 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001800
Pavol Vican38321d02016-08-16 14:56:02 +02001801 /* check collision with mandatory/min-elements */
1802 if ((dev->target->flags & LYS_MAND_TRUE) ||
1803 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
1804 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1805 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1806 "Adding the \"default\" statement is forbidden on %s statement.",
1807 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1808 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01001809 }
Pavol Vican38321d02016-08-16 14:56:02 +02001810 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1811 /* check that there was a value before */
1812 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
1813 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
1814 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1815 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1816 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001817 }
Pavol Vican38321d02016-08-16 14:56:02 +02001818 }
1819
1820 if (dev->target->nodetype == LYS_LEAFLIST) {
1821 /* reallocate default list in the target */
1822 llist = (struct lys_node_leaflist *)dev->target;
1823 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1824 /* reallocate (enlarge) the unique array of the target */
1825 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
1826 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1827 /* reallocate (replace) the unique array of the target */
1828 for (i = 0; i < llist->dflt_size; i++) {
1829 lydict_remove(llist->module->ctx, llist->dflt[i]);
1830 }
1831 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
1832 llist->dflt_size = 0;
1833 }
1834 }
1835
1836 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
1837 if (!dev->deviate->dflt) {
1838 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01001839 goto error;
1840 }
1841
1842 return EXIT_SUCCESS;
1843
1844error:
1845 return EXIT_FAILURE;
1846}
1847
1848int
Pavol Vican38321d02016-08-16 14:56:02 +02001849yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
1850{
1851 struct lys_node *node;
1852 struct lys_node_choice *choice;
1853 struct lys_node_leaf *leaf;
1854 struct lys_node_leaflist *llist;
1855 int rc, i;
1856 unsigned int u;
1857 const char *value;
1858
1859 value = lydict_insert_zc(ctx, exp);
1860 u = strlen(value);
1861 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
1862
1863 if (dev->target->nodetype == LYS_CHOICE) {
1864 choice = (struct lys_node_choice *)dev->target;
1865 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1866 if (rc || !node) {
1867 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1868 goto error;
1869 }
1870 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1871 if (!choice->dflt || (choice->dflt != node)) {
1872 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1873 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1874 goto error;
1875 }
1876 } else { /* add or replace */
1877 choice->dflt = node;
1878 if (!choice->dflt) {
1879 /* default branch not found */
1880 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1881 goto error;
1882 }
1883 }
1884 } else if (dev->target->nodetype == LYS_LEAF) {
1885 leaf = (struct lys_node_leaf *)dev->target;
1886 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1887 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1888 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1889 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1890 goto error;
1891 }
1892 /* remove value */
1893 lydict_remove(ctx, leaf->dflt);
1894 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001895 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001896 } else { /* add (already checked) and replace */
1897 /* remove value */
1898 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001899 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001900
1901 /* set new value */
1902 leaf->dflt = lydict_insert(ctx, value, u);
1903
1904 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1905 ly_set_add(dev->dflt_check, dev->target, 0);
1906 }
1907 } else { /* LYS_LEAFLIST */
1908 llist = (struct lys_node_leaflist *)dev->target;
1909 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1910 /* find and remove the value in target list */
1911 for (i = 0; i < llist->dflt_size; i++) {
1912 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1913 /* match, remove the value */
1914 lydict_remove(llist->module->ctx, llist->dflt[i]);
1915 llist->dflt[i] = NULL;
1916 break;
1917 }
1918 }
1919 if (i == llist->dflt_size) {
1920 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1921 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1922 goto error;
1923 }
1924 } else {
1925 /* add or replace, anyway we place items into the deviate's list
1926 which propagates to the target */
1927 /* we just want to check that the value isn't already in the list */
1928 for (i = 0; i < llist->dflt_size; i++) {
1929 if (ly_strequal(llist->dflt[i], value, 1)) {
1930 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1931 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1932 goto error;
1933 }
1934 }
1935 /* store it in target node */
1936 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1937
1938 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1939 ly_set_add(dev->dflt_check, dev->target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001940 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001941 }
1942 }
1943
1944 return EXIT_SUCCESS;
1945error:
1946 return EXIT_FAILURE;
1947}
1948
1949
1950int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001951yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001952{
1953 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001954 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001955 goto error;
1956 }
1957
1958 /* for we deviate from RFC 6020 and allow config property even it is/is not
1959 * specified in the target explicitly since config property inherits. So we expect
1960 * that config is specified in every node. But for delete, we check that the value
1961 * is the same as here in deviation
1962 */
1963 dev->deviate->flags |= value;
1964
1965 /* add and replace are the same in this case */
1966 /* remove current config value of the target ... */
1967 dev->target->flags &= ~LYS_CONFIG_MASK;
1968
1969 /* ... and replace it with the value specified in deviation */
1970 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1971
1972 return EXIT_SUCCESS;
1973
1974error:
1975 return EXIT_FAILURE;
1976}
1977
1978int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001979yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001980{
Radek Krejcie00d2312016-08-12 15:27:49 +02001981 struct lys_node *parent;
1982
Pavol Vican85f12022016-03-05 16:30:35 +01001983 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001984 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001985 goto error;
1986 }
1987
1988 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001989 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001990 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1991 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001992 goto error;
1993 }
1994
1995 dev->deviate->flags |= value;
1996
1997 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1998 /* check that there is no current value */
1999 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002000 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2001 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002002 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002003 } else {
2004 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2005 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2006 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2007 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2008 goto error;
2009 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2010 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2011 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2012 goto error;
2013 }
Pavol Vican85f12022016-03-05 16:30:35 +01002014 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002015 } else { /* replace */
2016 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002017 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2018 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002019 goto error;
2020 }
Pavol Vican85f12022016-03-05 16:30:35 +01002021 }
2022
Pavol Vican85f12022016-03-05 16:30:35 +01002023 /* remove current mandatory value of the target ... */
2024 dev->target->flags &= ~LYS_MAND_MASK;
2025
2026 /* ... and replace it with the value specified in deviation */
2027 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2028
Radek Krejcie00d2312016-08-12 15:27:49 +02002029 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2030 for (parent = dev->target->parent;
2031 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2032 parent = parent->parent) {
2033 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2034 /* stop also on presence containers */
2035 break;
2036 }
2037 }
2038 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2039 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2040 if (lyp_check_mandatory_choice(parent)) {
2041 goto error;
2042 }
2043 }
2044
Pavol Vican85f12022016-03-05 16:30:35 +01002045 return EXIT_SUCCESS;
2046
2047error:
2048 return EXIT_FAILURE;
2049}
2050
2051int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002052yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002053{
Pavol Vican09adcc32016-08-25 10:51:36 +02002054 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002055
2056 /* check target node type */
2057 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002058 max = &((struct lys_node_leaflist *)dev->target)->max;
2059 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002060 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002061 max = &((struct lys_node_list *)dev->target)->max;
2062 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002063 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002064 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2065 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"%s\" property.", (type) ? "max-elements" : "min-elements");
Pavol Vican85f12022016-03-05 16:30:35 +01002066 goto error;
2067 }
2068
2069 if (type) {
2070 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002071 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002072 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002073 } else {
2074 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002075 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002076 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002077 }
2078
2079 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2080 /* check that there is no current value */
2081 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002082 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2083 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002084 goto error;
2085 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002086 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2087 /* unfortunately, there is no way to check reliably that there
2088 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002089 }
2090
2091 /* add (already checked) and replace */
2092 /* set new value specified in deviation */
2093 *ui32val = value;
2094
Pavol Vican09adcc32016-08-25 10:51:36 +02002095 /* check min-elements is smaller than max-elements */
2096 if (*max && *min > *max) {
2097 if (type) {
2098 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2099 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2100 } else {
2101 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2102 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2103 }
2104 goto error;
2105 }
2106
Pavol Vican85f12022016-03-05 16:30:35 +01002107 return EXIT_SUCCESS;
2108
2109error:
2110 return EXIT_FAILURE;
2111}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002112
2113int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002114yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002115{
2116 int i;
2117
2118 /* find must to delete, we are ok with just matching conditions */
2119 for (i = 0; i < *dev->trg_must_size; i++) {
2120 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2121 /* we have a match, free the must structure ... */
2122 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2123 /* ... and maintain the array */
2124 (*dev->trg_must_size)--;
2125 if (i != *dev->trg_must_size) {
2126 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2127 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2128 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2129 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2130 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2131 }
2132 if (!(*dev->trg_must_size)) {
2133 free(*dev->trg_must);
2134 *dev->trg_must = NULL;
2135 } else {
2136 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2137 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2138 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2139 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2140 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2141 }
2142
2143 i = -1; /* set match flag */
2144 break;
2145 }
2146 }
2147 if (i != -1) {
2148 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002149 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2150 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002151 return EXIT_FAILURE;
2152 }
2153
2154 return EXIT_SUCCESS;
2155}
2156
2157int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002158yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002159{
2160 struct lys_node_list *list;
2161 int i, j;
2162
2163 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002164 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002165 dev->deviate->unique_size++;
2166 goto error;
2167 }
2168
2169 /* find unique structures to delete */
2170 for (i = 0; i < list->unique_size; i++) {
2171 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2172 continue;
2173 }
2174
2175 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2176 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2177 break;
2178 }
2179 }
2180
2181 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2182 /* we have a match, free the unique structure ... */
2183 for (j = 0; j < list->unique[i].expr_size; j++) {
2184 lydict_remove(module->ctx, list->unique[i].expr[j]);
2185 }
2186 free(list->unique[i].expr);
2187 /* ... and maintain the array */
2188 list->unique_size--;
2189 if (i != list->unique_size) {
2190 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2191 list->unique[i].expr = list->unique[list->unique_size].expr;
2192 }
2193
2194 if (!list->unique_size) {
2195 free(list->unique);
2196 list->unique = NULL;
2197 } else {
2198 list->unique[list->unique_size].expr_size = 0;
2199 list->unique[list->unique_size].expr = NULL;
2200 }
2201
2202 i = -1; /* set match flag */
2203 break;
2204 }
2205 }
2206 dev->deviate->unique_size++;
2207
2208 if (i != -1) {
2209 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002210 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2211 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002212 goto error;
2213 }
2214
2215 free(value);
2216 return EXIT_SUCCESS;
2217
2218error:
2219 free(value);
2220 return EXIT_FAILURE;
2221}
Pavol Vicane92421d2016-03-08 10:12:33 +01002222
2223int
Pavol Vican38321d02016-08-16 14:56:02 +02002224yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002225{
2226 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002227 unsigned int u;
2228 const char *value, *target_name;
2229 struct lys_node_leaflist *llist;
2230 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002231
Pavol Vican38321d02016-08-16 14:56:02 +02002232 /* now check whether default value, if any, matches the type */
2233 for (u = 0; u < dflt_check->number; ++u) {
2234 value = NULL;
2235 rc = EXIT_SUCCESS;
2236 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2237 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2238 target_name = leaf->name;
Radek Krejci51673202016-11-01 17:00:32 +01002239 value = leaf->dflt;
2240 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Pavol Vican38321d02016-08-16 14:56:02 +02002241 } else { /* LYS_LEAFLIST */
2242 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2243 target_name = llist->name;
2244 for (i = 0; i < llist->dflt_size; i++) {
Radek Krejci51673202016-11-01 17:00:32 +01002245 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2246 (struct lys_node *)(&llist->dflt[i]));
Pavol Vican38321d02016-08-16 14:56:02 +02002247 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002248 value = llist->dflt[i];
Pavol Vicane92421d2016-03-08 10:12:33 +01002249 break;
2250 }
2251 }
2252 }
Pavol Vican38321d02016-08-16 14:56:02 +02002253 if (rc == -1) {
2254 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2255 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2256 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2257 target_name);
2258 return EXIT_FAILURE;
2259 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002260 }
Pavol Vican38321d02016-08-16 14:56:02 +02002261
Pavol Vicane92421d2016-03-08 10:12:33 +01002262 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002263
Pavol Vican9b89dda2016-03-09 15:36:55 +01002264}
2265
Pavol Vicanec423c92016-10-24 21:33:43 +02002266static int
2267yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2268 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002269{
Pavol Vicanec423c92016-10-24 21:33:43 +02002270 struct lys_submodule *submodule;
2271 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002272 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002273 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002274 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002275
Pavol Vicanec423c92016-10-24 21:33:43 +02002276 str = lydict_insert_zc(trg->ctx, value);
2277 if (trg->version) {
2278 submodule = (struct lys_submodule *)trg;
2279 module = ((struct lys_submodule *)trg)->belongsto;
2280 } else {
2281 submodule = NULL;
2282 module = trg;
2283 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002284 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002285 if (!rc) {
2286 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002287 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002288 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002289 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002290 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002291 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002292
Pavol Vicanec423c92016-10-24 21:33:43 +02002293 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002294 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002295}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002296
2297int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002298yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002299{
2300 char *prefix;
2301 char *identif;
2302 const char *ns = NULL;
2303 int i;
2304
Pavol Vicanf4717e62016-03-16 11:30:01 +01002305 /* check to the same pointer */
2306 if (data_node != actual) {
2307 return EXIT_SUCCESS;
2308 }
2309
Pavol Vicana302aa62016-03-17 10:45:35 +01002310 prefix = strdup(value);
2311 if (!prefix) {
2312 LOGMEM;
2313 goto error;
2314 }
2315 /* find prefix anf identificator*/
2316 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002317 if (!identif) {
2318 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2319 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2320 goto error;
2321 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002322 *identif = '\0';
2323 identif++;
2324
Pavol Vicanf4717e62016-03-16 11:30:01 +01002325 for(i = 0; i < module->imp_size; ++i) {
2326 if (!strcmp(module->imp[i].prefix, prefix)) {
2327 ns = module->imp[i].module->ns;
2328 break;
2329 }
2330 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002331 if (!ns && !strcmp(module->prefix, prefix)) {
2332 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2333 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002334 if (ns && !strcmp(ns, LY_NSNACM)) {
2335 if (!strcmp(identif, "default-deny-write")) {
2336 data_node->nacm |= LYS_NACM_DENYW;
2337 } else if (!strcmp(identif, "default-deny-all")) {
2338 data_node->nacm |= LYS_NACM_DENYA;
2339 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002340 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002341 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002342 }
2343 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002344 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002345 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002346
2347error:
2348 free(prefix);
2349 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002350}
2351
2352void
2353nacm_inherit(struct lys_module *module)
2354{
Pavol Vican10ffba52016-04-04 12:21:22 +02002355 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002356
2357 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002358 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002359 if (elem->parent) {
2360 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002361 case LYS_GROUPING:
2362 /* extension nacm not inherited*/
2363 break;
2364 case LYS_CHOICE:
2365 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002366 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002367 case LYS_USES:
2368 if (elem->parent->nodetype != LYS_GROUPING) {
2369 elem->nacm |= elem->parent->nacm;
2370 }
2371 break;
2372 case LYS_CONTAINER:
2373 case LYS_LIST:
2374 case LYS_CASE:
2375 case LYS_NOTIF:
2376 case LYS_RPC:
2377 case LYS_INPUT:
2378 case LYS_OUTPUT:
2379 case LYS_AUGMENT:
2380 elem->nacm |= elem->parent->nacm;
2381 break;
2382 case LYS_LEAF:
2383 case LYS_LEAFLIST:
2384 tmp_node = elem;
2385 tmp_child = elem->child;
2386 elem->child = NULL;
2387 default:
2388 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002389 }
2390 }
2391 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002392 if (tmp_node) {
2393 tmp_node->child = tmp_child;
2394 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002395 }
2396}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002397
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002398int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002399store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002400{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002401 struct lys_node *elem;
2402
Pavol Vican1dac40c2016-09-28 11:39:26 +02002403 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2404 if (config_opt == CONFIG_INHERIT_ENABLE) {
2405 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002406 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002407 if (node->parent) {
2408 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002409 } else {
2410 /* default config is true */
2411 node->flags |= LYS_CONFIG_W;
2412 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002413 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002414 /* do we even care about config flags? */
2415 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002416
Pavol Vican1dac40c2016-09-28 11:39:26 +02002417 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2418 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2419 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2420 return EXIT_FAILURE;
2421 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002422 }
2423 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002424
2425 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002426}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002427
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002428void
2429store_config_flag(struct lys_node *node, int config_opt)
2430{
2431 if (config_opt == CONFIG_IGNORE) {
2432 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
2433 } else if (config_opt == CONFIG_INHERIT_ENABLE) {
2434 if (!(node->flags & LYS_CONFIG_MASK)) {
2435 /* get config flag from parent */
2436 if (node->parent) {
2437 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2438 } else {
2439 /* default config is true */
2440 node->flags |= LYS_CONFIG_W;
2441 }
2442 }
2443 }
2444}
2445
Pavol Vican9d50a772016-10-14 22:23:36 +02002446int
2447yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2448 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002449{
Pavol Vican9d50a772016-10-14 22:23:36 +02002450 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002451 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002452 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002453 int ret = EXIT_SUCCESS, remove_import = 1;
2454 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002455
Pavol Vican9d50a772016-10-14 22:23:36 +02002456 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002457 yylex_init(&scanner);
2458 bp = yy_scan_buffer((char *)data, size, scanner);
2459 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002460 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2461 if (remove_import) {
2462 trg = (submodule) ? (struct lys_module *)submodule : module;
2463 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2464 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2465 trg->inc_size = 0;
2466 trg->imp_size = 0;
2467 }
Pavol Vican1938d882016-04-10 13:36:31 +02002468 ret = EXIT_FAILURE;
2469 }
2470 yy_delete_buffer(bp, scanner);
2471 yylex_destroy(scanner);
2472 return ret;
2473}
2474
Pavol Vican8e7110b2016-03-22 17:00:26 +01002475struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002476yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002477{
2478
Pavol Vican10ffba52016-04-04 12:21:22 +02002479 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002480 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002481 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002482
2483 unres = calloc(1, sizeof *unres);
2484 if (!unres) {
2485 LOGMEM;
2486 goto error;
2487 }
2488
2489 module = calloc(1, sizeof *module);
2490 if (!module) {
2491 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002492 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002493 }
2494
2495 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002496 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002497 module->type = 0;
2498 module->implemented = (implement ? 1 : 0);
2499
Pavol Vican9d50a772016-10-14 22:23:36 +02002500 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002501 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002502 goto error;
2503 }
2504
2505 if (yang_check_sub_module(module, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002506 goto error;
2507 }
2508
2509 if (module && unres->count && resolve_unres_schema(module, unres)) {
2510 goto error;
2511 }
2512
2513 if (revision) {
2514 /* check revision of the parsed model */
2515 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2516 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2517 module->name, module->rev[0].date, revision);
2518 goto error;
2519 }
2520 }
2521
Pavol Vican10ffba52016-04-04 12:21:22 +02002522 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002523 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002524 goto error;
2525 }
2526
Pavol Vican10ffba52016-04-04 12:21:22 +02002527 if (module == tmp_module) {
2528 nacm_inherit(module);
2529 }
2530
Radek Krejci27fe55e2016-09-13 17:13:35 +02002531 if (module->deviation_size && !module->implemented) {
2532 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2533 /* deviations always causes target to be made implemented,
2534 * but augents and leafrefs not, so we have to apply them now */
2535 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002536 goto error;
2537 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002538 }
2539
Pavol Vican8e7110b2016-03-22 17:00:26 +01002540 unres_schema_free(NULL, &unres);
2541 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2542 return module;
2543
2544error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002545 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002546 unres_schema_free(module, &unres);
2547 if (!module || !module->name) {
2548 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002549 if (ly_vecode != LYVE_SUBMODULE) {
2550 LOGERR(ly_errno, "Module parsing failed.");
2551 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002552 return NULL;
2553 }
2554
2555 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002556
2557 lys_sub_module_remove_devs_augs(module);
2558 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002559 return NULL;
2560}
2561
2562struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002563yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002564{
2565 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002566 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002567
2568 submodule = calloc(1, sizeof *submodule);
2569 if (!submodule) {
2570 LOGMEM;
2571 goto error;
2572 }
2573
2574 submodule->ctx = module->ctx;
2575 submodule->type = 1;
2576 submodule->belongsto = module;
2577
Pavol Vican9d50a772016-10-14 22:23:36 +02002578 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002579 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002580 goto error;
2581 }
2582
2583 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002584 goto error;
2585 }
2586
Pavol Vican8e7110b2016-03-22 17:00:26 +01002587 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002588 return submodule;
2589
2590error:
2591 /* cleanup */
2592 unres_schema_free((struct lys_module *)submodule, &unres);
2593
2594 if (!submodule || !submodule->name) {
2595 free(submodule);
2596 LOGERR(ly_errno, "Submodule parsing failed.");
2597 return NULL;
2598 }
2599
2600 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2601
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002602 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2603 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002604 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002605 return NULL;
2606}
Pavol Vican8760bb72016-04-07 09:44:01 +02002607
2608static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002609read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2610{
2611 int k = 0, j;
2612
2613 while (in_index < size) {
2614 if (input[in_index] == ' ') {
2615 k++;
2616 } else if (input[in_index] == '\t') {
2617 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2618 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002619 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2620 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2621 k += 8;
2622 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002623 } else {
2624 break;
2625 }
2626 ++in_index;
2627 if (k >= indent) {
2628 for (j = k - indent; j > 0; --j) {
2629 output[*out_index] = ' ';
2630 ++(*out_index);
2631 }
2632 break;
2633 }
2634 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002635 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002636}
2637
2638char *
Pavol Vican3f598892016-09-28 15:41:07 +02002639yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2640 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002641
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002642 while (i < size) {
2643 switch (input[i]) {
2644 case '\n':
2645 out_index -= space;
2646 output[out_index] = '\n';
2647 space = 0;
2648 i = read_indent(input, indent, size, i + 1, &out_index, output);
2649 break;
2650 case ' ':
2651 case '\t':
2652 output[out_index] = input[i];
2653 ++space;
2654 break;
2655 case '\\':
2656 if (input[i + 1] == 'n') {
2657 out_index -= space;
2658 output[out_index] = '\n';
2659 space = 0;
2660 i = read_indent(input, indent, size, i + 2, &out_index, output);
2661 } else if (input[i + 1] == 't') {
2662 output[out_index] = '\t';
2663 ++i;
2664 ++space;
2665 } else if (input[i + 1] == '\\') {
2666 output[out_index] = '\\';
2667 ++i;
2668 } else if ((i + 1) != size && input[i + 1] == '"') {
2669 output[out_index] = '"';
2670 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002671 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002672 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002673 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002674 } else {
2675 /* YANG 1.1 backslash must not be followed by any other character */
2676 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002677 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002678 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002679 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002680 break;
2681 default:
2682 output[out_index] = input[i];
2683 space = 0;
2684 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002685 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002686 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002687 ++out_index;
2688 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002689 output[out_index] = '\0';
2690 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002691 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002692 if (!output) {
2693 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002694 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002695 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002696 }
Pavol Vican3f598892016-09-28 15:41:07 +02002697 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002698}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002699
2700/* free function */
2701
Pavol Vican7313fc02016-11-14 01:10:31 +01002702static void yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
2703{
2704 struct yang_type *stype = (struct yang_type *)type->der;
2705 int i;
2706
2707 if (!stype) {
2708 return ;
2709 }
2710 lydict_remove(ctx, stype->name);
2711 type->base = stype->base;
2712 if (type->base == LY_TYPE_IDENT) {
2713 for (i = 0; i < type->info.ident.count; ++i) {
2714 free(type->info.ident.ref[i]);
2715 }
2716 }
2717 lys_type_free(ctx, type);
Pavol Vican36aff862016-11-26 17:07:05 +01002718 type->base = LY_TYPE_DER;
Pavol Vican7313fc02016-11-14 01:10:31 +01002719 free(stype);
2720}
2721
2722static void
2723yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2724{
2725 uint8_t i;
2726
2727 assert(ctx);
2728 if (!tpdf) {
2729 return;
2730 }
2731
2732 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002733 lydict_remove(ctx, tpdf[i].name);
2734 lydict_remove(ctx, tpdf[i].dsc);
2735 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002736
Pavol Vicancee10802016-11-22 15:48:35 +01002737 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002738
Pavol Vicancee10802016-11-22 15:48:35 +01002739 lydict_remove(ctx, tpdf[i].units);
2740 lydict_remove(ctx, tpdf[i].dflt);
Pavol Vican7313fc02016-11-14 01:10:31 +01002741 }
2742}
2743
Pavol Vican1cc4e192016-10-24 16:38:31 +02002744static void
2745yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2746{
2747 uint8_t i;
2748
2749 for (i = start; i < size; ++i){
2750 free((char *)imp[i].module);
2751 lydict_remove(ctx, imp[i].prefix);
2752 lydict_remove(ctx, imp[i].dsc);
2753 lydict_remove(ctx, imp[i].ref);
2754 }
2755}
2756
Pavol Vicanec423c92016-10-24 21:33:43 +02002757static void
2758yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2759{
2760 uint8_t i;
2761
2762 for (i = start; i < size; ++i){
2763 free((char *)inc[i].submodule);
2764 lydict_remove(ctx, inc[i].dsc);
2765 lydict_remove(ctx, inc[i].ref);
2766 }
2767}
2768
Pavol Vican36e27272016-11-22 15:47:28 +01002769static void
2770yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2771{
2772 uint32_t i;
2773 uint8_t j;
2774
2775 /* free base name */
2776 for (i = start; i < size; ++i) {
2777 for (j = 0; j < ident[i].base_size; ++j) {
2778 free(ident[i].base[j]);
2779 }
2780 }
2781}
2782
Pavol Vican05810b62016-11-23 14:07:22 +01002783static void
2784yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2785{
2786 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2787 free(grp->tpdf);
2788}
2789
2790static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002791yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2792{
2793 uint8_t i;
2794
2795 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2796 free(cont->tpdf);
2797 lydict_remove(ctx, cont->presence);
2798
2799 for (i = 0; cont->must_size; ++i) {
2800 lys_restr_free(ctx, &cont->must[i]);
2801 }
2802 free(cont->must);
2803
2804 lys_when_free(ctx, cont->when);
2805}
2806
2807static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002808yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2809{
2810 uint8_t i;
2811
2812 for (i = 0; i < leaf->must_size; i++) {
2813 lys_restr_free(ctx, &leaf->must[i]);
2814 }
2815 free(leaf->must);
2816
2817 lys_when_free(ctx, leaf->when);
2818
2819 yang_type_free(ctx, &leaf->type);
2820 lydict_remove(ctx, leaf->units);
2821 lydict_remove(ctx, leaf->dflt);
2822}
2823
2824static void
Pavol Vican36aff862016-11-26 17:07:05 +01002825yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2826{
2827 uint8_t i;
2828
2829 for (i = 0; i < leaflist->must_size; i++) {
2830 lys_restr_free(ctx, &leaflist->must[i]);
2831 }
2832 free(leaflist->must);
2833
2834 for (i = 0; i < leaflist->dflt_size; i++) {
2835 lydict_remove(ctx, leaflist->dflt[i]);
2836 }
2837 free(leaflist->dflt);
2838
2839 lys_when_free(ctx, leaflist->when);
2840
2841 yang_type_free(ctx, &leaflist->type);
2842 lydict_remove(ctx, leaflist->units);
2843}
2844
2845static void
Pavol Vicand8136a42016-11-27 13:28:04 +01002846yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
2847{
2848 uint8_t i;
2849
2850 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
2851 free(list->tpdf);
2852
2853 for (i = 0; i < list->must_size; ++i) {
2854 lys_restr_free(ctx, &list->must[i]);
2855 }
2856 free(list->must);
2857
2858 lys_when_free(ctx, list->when);
2859
2860 for (i = 0; i < list->unique_size; ++i) {
2861 free(list->unique[i].expr);
2862 }
2863 free(list->unique);
2864
2865 free(list->keys);
2866}
2867
2868static void
Pavol Vican36ace102016-11-28 11:46:59 +01002869yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
2870{
2871 free(choice->dflt);
2872 lys_when_free(ctx, choice->when);
2873}
2874
2875static void
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002876yang_free_anydata(struct ly_ctx *ctx, struct lys_node_anydata *anydata)
2877{
2878 uint8_t i;
2879
2880 for (i = 0; i < anydata->must_size; ++i) {
2881 lys_restr_free(ctx, &anydata->must[i]);
2882 }
2883 free(anydata->must);
2884
2885 lys_when_free(ctx, anydata->when);
2886}
2887
2888static void
Pavol Vican78729392016-11-28 17:18:22 +01002889yang_free_inout(struct ly_ctx *ctx, struct lys_node_inout *inout)
2890{
2891 uint8_t i;
2892
2893 yang_tpdf_free(ctx, inout->tpdf, 0, inout->tpdf_size);
2894 free(inout->tpdf);
2895
2896 for (i = 0; i < inout->must_size; ++i) {
2897 lys_restr_free(ctx, &inout->must[i]);
2898 }
2899 free(inout->must);
2900}
2901
2902static void
Pavol Vican05810b62016-11-23 14:07:22 +01002903yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
2904{
2905 struct lys_node *tmp, *child, *sibling;
2906
2907 if (!node) {
2908 return;
2909 }
2910 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01002911
2912 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002913 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01002914 sibling = tmp->next;
2915 /* common part */
2916 lydict_remove(ctx, tmp->name);
2917 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002918 lys_iffeature_free(tmp->iffeature, tmp->iffeature_size);
2919 lydict_remove(ctx, tmp->dsc);
2920 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01002921 }
2922
2923 switch (tmp->nodetype) {
2924 case LYS_GROUPING:
Pavol Vicanebc9ef82016-11-28 16:46:49 +01002925 case LYS_RPC:
2926 case LYS_ACTION:
Pavol Vican05810b62016-11-23 14:07:22 +01002927 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
2928 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002929 case LYS_CONTAINER:
2930 yang_free_container(ctx, (struct lys_node_container *)tmp);
2931 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01002932 case LYS_LEAF:
2933 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
2934 break;
Pavol Vican36aff862016-11-26 17:07:05 +01002935 case LYS_LEAFLIST:
2936 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
2937 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01002938 case LYS_LIST:
2939 yang_free_list(ctx, (struct lys_node_list *)tmp);
2940 break;
Pavol Vican36ace102016-11-28 11:46:59 +01002941 case LYS_CHOICE:
2942 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
2943 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01002944 case LYS_CASE:
2945 lys_when_free(ctx, ((struct lys_node_case *)tmp)->when);
2946 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002947 case LYS_ANYXML:
2948 case LYS_ANYDATA:
2949 yang_free_anydata(ctx, (struct lys_node_anydata *)tmp);
2950 break;
Pavol Vican78729392016-11-28 17:18:22 +01002951 case LYS_INPUT:
2952 case LYS_OUTPUT:
2953 yang_free_inout(ctx, (struct lys_node_inout *)tmp);
2954 break;
Pavol Vican05810b62016-11-23 14:07:22 +01002955 default:
2956 break;
2957 }
2958
2959 yang_free_nodes(ctx, child);
2960 free(tmp);
2961 tmp = sibling;
2962 }
2963}
2964
Pavol Vican7313fc02016-11-14 01:10:31 +01002965/* free common item from module and submodule */
2966static void
Pavol Vican05810b62016-11-23 14:07:22 +01002967free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01002968{
2969 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
2970 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01002971 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01002972 yang_free_nodes(module->ctx, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002973}
2974
Pavol Vican1cc4e192016-10-24 16:38:31 +02002975/* check function*/
2976
2977int
Pavol Vicanec423c92016-10-24 21:33:43 +02002978yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02002979{
2980 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02002981 struct lys_include *inc;
2982 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002983 size_t size;
2984 char *s;
2985
2986 imp = module->imp;
2987 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02002988 inc = module->inc;
2989 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002990
2991 if (imp_size) {
2992 size = (imp_size * sizeof *module->imp) + sizeof(void*);
2993 module->imp_size = 0;
2994 module->imp = calloc(1, size);
2995 if (!module->imp) {
2996 LOGMEM;
2997 goto error;
2998 }
2999 /* set stop block for possible realloc */
3000 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02003001 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02003002
Pavol Vicanec423c92016-10-24 21:33:43 +02003003 if (inc_size) {
3004 size = (inc_size * sizeof *module->inc) + sizeof(void*);
3005 module->inc_size = 0;
3006 module->inc = calloc(1, size);
3007 if (!module->inc) {
3008 LOGMEM;
3009 goto error;
3010 }
3011 /* set stop block for possible realloc */
3012 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003013 }
3014
3015 for (i = 0; i < imp_size; ++i) {
3016 s = (char *) imp[i].module;
3017 imp[i].module = NULL;
3018 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
3019 ++i;
3020 goto error;
3021 }
3022 }
Pavol Vicanec423c92016-10-24 21:33:43 +02003023 for (j = 0; j < inc_size; ++j) {
3024 s = (char *) inc[i].submodule;
3025 inc[i].submodule = NULL;
3026 if (yang_fill_include(module, s, &inc[i], unres)) {
3027 ++i;
3028 goto error;
3029 }
3030 }
3031 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003032 free(imp);
3033
3034 return EXIT_SUCCESS;
3035
3036error:
3037 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02003038 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003039 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02003040 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003041 return EXIT_FAILURE;
3042}
Pavol Vican7313fc02016-11-14 01:10:31 +01003043
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003044static int
3045yang_check_type_iffeature(struct lys_module *module, struct unres_schema *unres, struct lys_type *type)
3046{
3047 uint i, j, size;
3048 uint8_t iffeature_size;
3049 LY_DATA_TYPE stype;
3050
3051 if (((struct yang_type *)type->der)->base == LY_TYPE_ENUM) {
3052 stype = LY_TYPE_ENUM;
3053 size = type->info.enums.count;
3054 } else if (((struct yang_type *)type->der)->base == LY_TYPE_BITS) {
3055 stype = LY_TYPE_ENUM;
3056 size = type->info.enums.count;
3057 } else {
3058 return EXIT_SUCCESS;
3059 }
3060
3061 for (i = 0; i < size; ++i) {
3062 if (stype == LY_TYPE_ENUM) {
3063 iffeature_size = type->info.enums.enm[i].iffeature_size;
3064 type->info.enums.enm[i].iffeature_size = 0;
3065 for (j = 0; j < iffeature_size; ++j) {
3066 if (yang_read_if_feature(module, &type->info.enums.enm[i], type->parent,
3067 (char *)type->info.enums.enm[i].iffeature[j].features, unres, ENUM_KEYWORD)) {
3068 goto error;
3069 }
3070 }
3071 } else {
3072 iffeature_size = type->info.bits.bit[i].iffeature_size;
3073 type->info.bits.bit[i].iffeature_size = 0;
3074 for (j = 0; j < iffeature_size; ++j) {
3075 if (yang_read_if_feature(module, &type->info.bits.bit[i], type->parent,
3076 (char *)type->info.bits.bit[i].iffeature[j].features, unres, BIT_KEYWORD)) {
3077 goto error;
3078 }
3079 }
3080 }
3081 }
3082
3083 return EXIT_SUCCESS;
3084error:
3085 return EXIT_FAILURE;
3086}
3087
Pavol Vican7313fc02016-11-14 01:10:31 +01003088int
3089yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3090{
3091 struct lys_tpdf *tpdf;
3092 uint8_t i, tpdf_size, *ptr_tpdf_size;
3093 int ret = EXIT_SUCCESS;
3094
3095 if (!parent) {
3096 tpdf = module->tpdf;
3097 ptr_tpdf_size = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003098 } else {
3099 switch (parent->nodetype) {
3100 case LYS_GROUPING:
3101 tpdf = ((struct lys_node_grp *)parent)->tpdf;
3102 ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
3103 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003104 case LYS_CONTAINER:
3105 tpdf = ((struct lys_node_container *)parent)->tpdf;
3106 ptr_tpdf_size = &((struct lys_node_container *)parent)->tpdf_size;
3107 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003108 case LYS_LIST:
3109 tpdf = ((struct lys_node_list *)parent)->tpdf;
3110 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3111 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003112 case LYS_RPC:
3113 case LYS_ACTION:
3114 tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
3115 ptr_tpdf_size = &((struct lys_node_rpc_action *)parent)->tpdf_size;
3116 break;
Pavol Vican78729392016-11-28 17:18:22 +01003117 case LYS_INPUT:
3118 case LYS_OUTPUT:
3119 tpdf = ((struct lys_node_inout *)parent)->tpdf;
3120 ptr_tpdf_size = &((struct lys_node_inout *)parent)->tpdf_size;
3121 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003122 default:
3123 LOGINT;
3124 return EXIT_FAILURE;
3125 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003126 }
3127
3128 tpdf_size = *ptr_tpdf_size;
3129 *ptr_tpdf_size = 0;
3130
3131 for (i = 0; i < tpdf_size; ++i) {
3132 tpdf[i].type.parent = &tpdf[i];
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003133 if (yang_check_type_iffeature(module, unres, &tpdf[i].type)) {
3134 ret = EXIT_FAILURE;
3135 break;
3136 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003137 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
3138 ret = EXIT_FAILURE;
3139 break;
3140 }
3141
3142 /* check default value*/
3143 if (tpdf[i].dflt && unres_schema_add_str(module, unres, &tpdf[i].type, UNRES_TYPE_DFLT, tpdf[i].dflt) == -1) {
3144 ++i;
3145 ret = EXIT_FAILURE;
3146 break;
3147 }
3148 (*ptr_tpdf_size)++;
3149 }
3150 if (i < tpdf_size) {
3151 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3152 }
3153
3154 return ret;
3155}
3156
3157static int
Pavol Vican36e27272016-11-22 15:47:28 +01003158yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3159{
3160 uint32_t i, size, base_size;
3161 uint8_t j;
3162
3163 size = module->ident_size;
3164 module->ident_size = 0;
3165 for (i = 0; i < size; ++i) {
3166 base_size = module->ident[i].base_size;
3167 module->ident[i].base_size = 0;
3168 for (j = 0; j < base_size; ++j) {
3169 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3170 ++j;
3171 module->ident_size = size;
3172 goto error;
3173 }
3174 }
3175 module->ident_size++;
3176 }
3177
3178 return EXIT_SUCCESS;
3179
3180error:
3181 for (; j< module->ident[i].base_size; ++j) {
3182 free(module->ident[i].base[j]);
3183 }
3184 yang_free_ident_base(module->ident, i + 1, size);
3185 return EXIT_FAILURE;
3186}
3187
3188static int
Pavol Vican05810b62016-11-23 14:07:22 +01003189yang_check_grouping(struct lys_module *module, struct lys_node_grp *node, struct unres_schema *unres)
3190{
3191 uint8_t i, size;
3192
3193 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3194 goto error;
3195 }
3196
3197 size = node->iffeature_size;
3198 node->iffeature_size = 0;
3199 for (i = 0; i < size; ++i) {
3200 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, GROUPING_KEYWORD)) {
3201 node->iffeature_size = size;
3202 goto error;
3203 }
3204 }
3205
3206 return EXIT_SUCCESS;
3207
3208error:
3209 return EXIT_FAILURE;
3210}
3211
3212static int
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003213yang_check_container(struct lys_module *module, struct lys_node_container *node, struct unres_schema *unres)
3214{
3215 uint8_t i, size;
3216
3217 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3218 goto error;
3219 }
3220
3221 size = node->iffeature_size;
3222 node->iffeature_size = 0;
3223 for (i = 0; i < size; ++i) {
3224 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, CONTAINER_KEYWORD)) {
3225 node->iffeature_size = size;
3226 goto error;
3227 }
3228 }
3229
3230 /* check XPath dependencies */
3231 if ((node->when || node->must_size) && (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3232 goto error;
3233 }
3234
3235 return EXIT_SUCCESS;
3236error:
3237 return EXIT_FAILURE;
3238}
3239
3240static int
Pavol Vicana69aff22016-11-24 18:23:50 +01003241yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, struct unres_schema *unres)
3242{
3243 uint8_t i, size;
3244
3245 if (yang_check_type_iffeature(module, unres, &leaf->type)) {
3246 yang_type_free(module->ctx, &leaf->type);
3247 goto error;
3248 }
3249
3250 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaf) == -1) {
3251 yang_type_free(module->ctx, &leaf->type);
3252 goto error;
3253 }
3254
3255 if (leaf->dflt && unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)leaf->dflt) == -1) {
3256 goto error;
3257 }
3258
3259 size = leaf->iffeature_size;
3260 leaf->iffeature_size = 0;
3261 for (i = 0; i < size; ++i) {
3262 if (yang_read_if_feature(module, leaf, NULL, (char *)leaf->iffeature[i].features, unres, LEAF_KEYWORD)) {
3263 leaf->iffeature_size = size;
3264 goto error;
3265 }
3266 }
3267
3268 /* check XPath dependencies */
3269 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1)) {
3270 goto error;
3271 }
3272
3273 return EXIT_SUCCESS;
3274error:
3275 return EXIT_FAILURE;
3276}
3277
3278static int
Pavol Vican36aff862016-11-26 17:07:05 +01003279yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, struct unres_schema *unres)
3280{
3281 uint8_t i, size;
3282
3283 if (yang_check_type_iffeature(module, unres, &leaflist->type)) {
3284 yang_type_free(module->ctx, &leaflist->type);
3285 goto error;
3286 }
3287
3288 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaflist) == -1) {
3289 yang_type_free(module->ctx, &leaflist->type);
3290 goto error;
3291 }
3292
3293 /* check default value (if not defined, there still could be some restrictions
3294 * that need to be checked against a default value from a derived type) */
3295 for (i = 0; i < leaflist->dflt_size; ++i) {
3296 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaflist->dflt[i])) == -1) {
3297 goto error;
3298 }
3299 }
3300
3301 size = leaflist->iffeature_size;
3302 leaflist->iffeature_size = 0;
3303 for (i = 0; i < size; ++i) {
3304 if (yang_read_if_feature(module, leaflist, NULL, (char *)leaflist->iffeature[i].features, unres, LEAF_LIST_KEYWORD)) {
3305 leaflist->iffeature_size = size;
3306 goto error;
3307 }
3308 }
3309
3310 /* check XPath dependencies */
3311 if ((leaflist->when || leaflist->must_size) && (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1)) {
3312 goto error;
3313 }
3314
3315 return EXIT_SUCCESS;
3316error:
3317 return EXIT_FAILURE;
3318}
3319
3320static int
Pavol Vicand8136a42016-11-27 13:28:04 +01003321yang_check_list(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
3322{
3323 uint8_t size, i;
3324
3325 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3326 goto error;
3327 }
3328
3329 size = list->iffeature_size;
3330 list->iffeature_size = 0;
3331 for (i = 0; i < size; ++i) {
3332 if (yang_read_if_feature(module, list, NULL, (char *)list->iffeature[i].features, unres, LIST_KEYWORD)) {
3333 list->iffeature_size = size;
3334 goto error;
3335 }
3336 }
3337
3338 if (list->keys && yang_read_key(module, list, unres)) {
3339 goto error;
3340 }
3341
3342 if (yang_read_unique(module, list, unres)) {
3343 goto error;
3344 }
3345
3346 /* check XPath dependencies */
3347 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1)) {
3348 goto error;
3349 }
3350
3351 return EXIT_SUCCESS;
3352error:
3353 return EXIT_FAILURE;
3354}
3355
3356static int
Pavol Vican36ace102016-11-28 11:46:59 +01003357yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct unres_schema *unres)
3358{
3359 char *value;
3360 uint8_t size, i;
3361
3362 if (choice->dflt) {
3363 value = (char *)choice->dflt;
3364 choice->dflt = NULL;
3365 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3366 free(value);
3367 goto error;
3368 }
3369 free(value);
3370 }
3371
3372 size = choice->iffeature_size;
3373 choice->iffeature_size = 0;
3374 for (i = 0; i < size; ++i) {
3375 if (yang_read_if_feature(module, choice, NULL, (char *)choice->iffeature[i].features, unres, CHOICE_KEYWORD)) {
3376 choice->iffeature_size = size;
3377 goto error;
3378 }
3379 }
3380
3381 /* check XPath dependencies */
3382 if ((choice->when) && (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1)) {
3383 goto error;
3384 }
3385
3386 return EXIT_SUCCESS;
3387error:
3388 return EXIT_FAILURE;
3389}
3390
3391static int
Pavol Vicana420bac2016-11-28 14:51:54 +01003392yang_check_case(struct lys_module *module, struct lys_node_case *cs, struct unres_schema *unres)
3393{
3394 uint8_t size, i;
3395
3396 size = cs->iffeature_size;
3397 cs->iffeature_size = 0;
3398 for (i = 0; i < size; ++i) {
3399 if (yang_read_if_feature(module, cs, NULL, (char *)cs->iffeature[i].features, unres, CASE_KEYWORD)) {
3400 cs->iffeature_size = size;
3401 return EXIT_FAILURE;
3402 }
3403 }
3404 return EXIT_SUCCESS;
3405}
3406
3407static int
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003408yang_check_anydata(struct lys_module *module, struct lys_node_anydata *anydata, struct unres_schema *unres)
3409{
3410 uint8_t size, i;
3411
3412 size = anydata->iffeature_size;
3413 anydata->iffeature_size = 0;
3414 for (i = 0; i < size; ++i) {
3415 if (yang_read_if_feature(module, anydata, NULL, (char *)anydata->iffeature[i].features, unres, ANYXML_KEYWORD)) {
3416 anydata->iffeature_size = size;
3417 goto error;
3418 }
3419 }
3420
3421 /* check XPath dependencies */
3422 if ((anydata->when) && (unres_schema_add_node(module, unres, anydata, UNRES_XPATH, NULL) == -1)) {
3423 goto error;
3424 }
3425
3426 return EXIT_SUCCESS;
3427error:
3428 return EXIT_FAILURE;
3429}
3430
3431static int
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003432yang_check_rpc_action(struct lys_module *module, struct lys_node_rpc_action *rpc, struct unres_schema *unres)
3433{
3434 uint8_t size, i;
3435 struct lys_node *node;
3436
3437 if (rpc->nodetype == LYS_ACTION) {
3438 for (node = rpc->parent; node; node = lys_parent(node)) {
3439 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
3440 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
3441 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
3442 goto error;
3443 }
3444 }
3445 }
3446 if (yang_check_typedef(module, (struct lys_node *)rpc, unres)) {
3447 goto error;
3448 }
3449
3450 size = rpc->iffeature_size;
3451 rpc->iffeature_size = 0;
3452 for (i = 0; i < size; ++i) {
3453 if (yang_read_if_feature(module, rpc, NULL, (char *)rpc->iffeature[i].features, unres, RPC_KEYWORD)) {
3454 rpc->iffeature_size = size;
3455 goto error;
3456 }
3457 }
3458
3459 return EXIT_SUCCESS;
3460error:
3461 return EXIT_FAILURE;
3462}
3463
3464static int
Pavol Vican05810b62016-11-23 14:07:22 +01003465yang_check_nodes(struct lys_module *module, struct lys_node *nodes, struct unres_schema *unres)
3466{
Pavol Vican24ba7f62016-11-28 12:15:20 +01003467 struct lys_node *node = nodes, *sibling, *child, *parent;
Pavol Vican05810b62016-11-23 14:07:22 +01003468
3469 while (node) {
3470 sibling = node->next;
3471 child = node->child;
Pavol Vican24ba7f62016-11-28 12:15:20 +01003472 parent = node->parent;
Pavol Vican05810b62016-11-23 14:07:22 +01003473 node->next = NULL;
3474 node->child = NULL;
Pavol Vican24ba7f62016-11-28 12:15:20 +01003475 node->parent = NULL;
Pavol Vican05810b62016-11-23 14:07:22 +01003476 node->prev = node;
3477
Pavol Vican24ba7f62016-11-28 12:15:20 +01003478 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
3479 lys_node_unlink(node);
3480 node->next = sibling;
Pavol Vican05810b62016-11-23 14:07:22 +01003481 sibling = node;
Pavol Vican05810b62016-11-23 14:07:22 +01003482 goto error;
3483 }
3484 switch (node->nodetype) {
3485 case LYS_GROUPING:
3486 if (yang_check_grouping(module, (struct lys_node_grp *)node, unres)) {
3487 goto error;
3488 }
3489 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003490 case LYS_CONTAINER:
3491 if (yang_check_container(module, (struct lys_node_container *)node, unres)) {
3492 goto error;
3493 }
3494 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003495 case LYS_LEAF:
3496 if (yang_check_leaf(module, (struct lys_node_leaf *)node, unres)) {
3497 goto error;
3498 }
3499 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003500 case LYS_LEAFLIST:
3501 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, unres)) {
3502 goto error;
3503 }
3504 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003505 case LYS_LIST:
3506 if (yang_check_list(module, (struct lys_node_list *)node, unres)) {
3507 goto error;
3508 }
3509 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003510 case LYS_CHOICE:
3511 if (yang_check_choice(module, (struct lys_node_choice *)node, unres)) {
3512 goto error;
3513 }
3514 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01003515 case LYS_CASE:
3516 if (yang_check_case(module, (struct lys_node_case *)node, unres)) {
3517 goto error;
3518 }
3519 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003520 case LYS_ANYDATA:
3521 case LYS_ANYXML:
3522 if (yang_check_anydata(module, (struct lys_node_anydata *)node, unres)) {
3523 goto error;
3524 }
3525 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003526 case LYS_RPC:
3527 case LYS_ACTION:
3528 if (yang_check_rpc_action(module, (struct lys_node_rpc_action *)node, unres)){
3529 goto error;
3530 }
3531 break;
Pavol Vican78729392016-11-28 17:18:22 +01003532 case LYS_INPUT:
3533 case LYS_OUTPUT:
3534 /* check XPath dependencies */
3535 if (((struct lys_node_inout *)node)->must_size &&
3536 (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3537 goto error;
3538 }
3539 if (yang_check_typedef(module, node, unres)) {
3540 goto error;
3541 }
3542 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003543 default:
3544 LOGINT;
3545 sibling = node;
3546 child = NULL;
3547 goto error;
3548 }
3549 if (yang_check_nodes(module, child, unres)) {
3550 child = NULL;
3551 goto error;
3552 }
3553 node = sibling;
3554 }
3555
3556 return EXIT_SUCCESS;
3557error:
3558 yang_free_nodes(module->ctx, sibling);
3559 yang_free_nodes(module->ctx, child);
3560 return EXIT_FAILURE;
3561}
3562
3563static int
Pavol Vican7313fc02016-11-14 01:10:31 +01003564yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
3565{
Pavol Vican05810b62016-11-23 14:07:22 +01003566 uint8_t i, j, size, erase_identities = 1, erase_nodes = 1;
Pavol Vican7a7916f2016-11-21 23:38:30 +01003567 struct lys_feature *feature; /* shortcut */
3568 char *s;
3569
Pavol Vican7313fc02016-11-14 01:10:31 +01003570 if (yang_check_typedef(module, NULL, unres)) {
3571 goto error;
3572 }
3573
Pavol Vican7a7916f2016-11-21 23:38:30 +01003574 /* check features */
3575 for (i = 0; i < module->features_size; ++i) {
3576 feature = &module->features[i];
3577 size = feature->iffeature_size;
3578 feature->iffeature_size = 0;
3579 for (j = 0; j < size; ++j) {
3580 s = (char *)feature->iffeature[j].features;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003581 if (yang_read_if_feature(module, feature, NULL, s, unres, FEATURE_KEYWORD)) {
Pavol Vican7a7916f2016-11-21 23:38:30 +01003582 goto error;
3583 }
3584 if (unres_schema_add_node(module, unres, feature, UNRES_FEATURE, NULL) == -1) {
3585 goto error;
3586 }
3587 }
3588 }
Pavol Vican36e27272016-11-22 15:47:28 +01003589 erase_identities = 0;
3590 if (yang_check_identities(module, unres)) {
3591 goto error;
3592 }
Pavol Vican05810b62016-11-23 14:07:22 +01003593 erase_nodes = 0;
3594 if (yang_check_nodes(module, node, unres)) {
3595 goto error;
3596 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01003597
Pavol Vican7313fc02016-11-14 01:10:31 +01003598 return EXIT_SUCCESS;
3599error:
Pavol Vican36e27272016-11-22 15:47:28 +01003600 if (erase_identities) {
3601 yang_free_ident_base(module->ident, 0, module->ident_size);
3602 }
Pavol Vican05810b62016-11-23 14:07:22 +01003603 if (erase_nodes) {
3604 yang_free_nodes(module->ctx, node);
3605 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003606 return EXIT_FAILURE;
3607}