blob: c8c4566600223fbf1384ccedabc5c32750441a80 [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_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001461{
1462 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001463
1464 if (parent) {
1465 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1466 } else {
1467 aug = &module->augment[module->augment_size];
1468 }
1469 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001470 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001471 free(value);
1472 if (!aug->target_name) {
1473 return NULL;
1474 }
1475 aug->parent = parent;
1476 aug->module = module;
1477 if (parent) {
1478 ((struct lys_node_uses *)parent)->augment_size++;
1479 } else {
1480 module->augment_size++;
1481 }
1482 return aug;
1483}
Pavol Vican220e5a12016-03-03 14:19:43 +01001484
1485void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001486yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001487{
1488 struct lys_node *dev_target = NULL;
1489 struct lys_deviation *dev;
1490 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001491 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001492
Pavol Vican220e5a12016-03-03 14:19:43 +01001493 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001494 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001495 free(value);
1496 if (!dev->target_name) {
1497 goto error;
1498 }
1499
Pavol Vican974377b2016-03-23 00:38:53 +01001500 deviation = calloc(1, sizeof *deviation);
1501 if (!deviation) {
1502 LOGMEM;
1503 goto error;
1504 }
1505
Pavol Vican220e5a12016-03-03 14:19:43 +01001506 /* resolve target node */
Radek Krejcidf46e222016-11-08 11:57:37 +01001507 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
Pavol Vican220e5a12016-03-03 14:19:43 +01001508 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001509 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001510 goto error;
1511 }
Radek Krejcic4283442016-04-22 09:19:27 +02001512 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001513 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1514 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001515 goto error;
1516 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001517
Pavol Vican220e5a12016-03-03 14:19:43 +01001518 /*save pointer to the deviation and deviated target*/
1519 deviation->deviation = dev;
1520 deviation->target = dev_target;
1521
Pavol Vican38321d02016-08-16 14:56:02 +02001522 deviation->dflt_check = ly_set_new();
1523 if (!deviation->dflt_check) {
1524 LOGMEM;
1525 goto error;
1526 }
1527
Pavol Vican220e5a12016-03-03 14:19:43 +01001528 return deviation;
1529
1530error:
1531 free(deviation);
1532 lydict_remove(module->ctx, dev->target_name);
1533 return NULL;
1534}
Pavol Vican4c90c642016-03-03 15:06:47 +01001535
1536int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001537yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001538{
1539 int i;
1540
1541 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001542 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001543 return EXIT_FAILURE;
1544 }
1545 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1546
1547 /* you cannot remove a key leaf */
1548 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1549 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1550 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001551 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1552 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001553 return EXIT_FAILURE;
1554 }
1555 }
1556 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001557
Pavol Vican4c90c642016-03-03 15:06:47 +01001558 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001559 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001560 dev->deviation->orig_node = dev->target;
1561
1562 dev->deviation->deviate_size = 1;
1563 return EXIT_SUCCESS;
1564}
Pavol Vican85f12022016-03-05 16:30:35 +01001565
1566int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001567yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001568{
1569 struct unres_schema tmp_unres;
1570
1571 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1572 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1573 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001574 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001575 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001576 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1577 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001578 return EXIT_FAILURE;
1579 }
1580
1581 /* store a shallow copy of the original node */
1582 if (!dev->deviation->orig_node) {
1583 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001584 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001585 /* just to be safe */
1586 if (tmp_unres.count) {
1587 LOGINT;
1588 return EXIT_FAILURE;
1589 }
1590 }
1591
1592 return EXIT_SUCCESS;
1593}
1594
1595int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001596yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001597{
1598 const char **stritem;
1599
1600 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001601 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001602 free(value);
1603 goto error;
1604 }
1605
1606 /* check target node type */
1607 if (dev->target->nodetype == LYS_LEAFLIST) {
1608 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1609 } else if (dev->target->nodetype == LYS_LEAF) {
1610 stritem = &((struct lys_node_leaf *)dev->target)->units;
1611 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001612 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1613 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001614 free(value);
1615 goto error;
1616 }
1617
1618 dev->deviate->units = lydict_insert_zc(ctx, value);
1619
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001620 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1621 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001622 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001623 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1624 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001625 goto error;
1626 }
1627 /* remove current units value of the target */
1628 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001629 } else {
1630 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1631 /* check that there is no current value */
1632 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001633 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1634 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001635 goto error;
1636 }
1637 } else { /* replace */
1638 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001639 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1640 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001641 goto error;
1642 }
1643 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001644 /* remove current units value of the target ... */
1645 lydict_remove(ctx, *stritem);
1646
1647 /* ... and replace it with the value specified in deviation */
1648 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1649 }
1650
Pavol Vican85f12022016-03-05 16:30:35 +01001651 return EXIT_SUCCESS;
1652
1653error:
1654 return EXIT_FAILURE;
1655}
1656
1657int
Pavol Vican974377b2016-03-23 00:38:53 +01001658yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001659{
Pavol Vican85f12022016-03-05 16:30:35 +01001660 /* check target node type */
1661 switch (dev->target->nodetype) {
1662 case LYS_LEAF:
1663 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1664 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1665 break;
1666 case LYS_CONTAINER:
1667 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1668 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1669 break;
1670 case LYS_LEAFLIST:
1671 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1672 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1673 break;
1674 case LYS_LIST:
1675 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1676 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1677 break;
1678 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001679 case LYS_ANYDATA:
1680 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1681 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001682 break;
1683 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001684 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1685 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001686 goto error;
1687 }
1688
Michal Vasko508a50d2016-09-07 14:50:33 +02001689 /* flag will be checked again, clear it for now */
Michal Vaskoe9914d12016-10-07 14:32:37 +02001690 dev->target->flags &= ~LYS_VALID_DEP;
Michal Vasko508a50d2016-09-07 14:50:33 +02001691
Pavol Vican85f12022016-03-05 16:30:35 +01001692 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1693 /* reallocate the must array of the target */
1694 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1695 if (!dev->deviate->must) {
1696 LOGMEM;
1697 goto error;
1698 }
1699 *dev->trg_must = dev->deviate->must;
1700 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1701 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001702 } else {
1703 /* LY_DEVIATE_DEL */
1704 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1705 if (!dev->deviate->must) {
1706 LOGMEM;
1707 goto error;
1708 }
Pavol Vican85f12022016-03-05 16:30:35 +01001709 }
1710
1711 return EXIT_SUCCESS;
1712
1713error:
1714 return EXIT_FAILURE;
1715}
1716
1717int
Pavol Vican974377b2016-03-23 00:38:53 +01001718yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001719{
Pavol Vican85f12022016-03-05 16:30:35 +01001720 struct lys_node_list *list;
1721
1722 /* check target node type */
1723 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001724 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1725 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001726 goto error;
1727 }
1728
1729 list = (struct lys_node_list *)dev->target;
1730 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1731 /* reallocate the unique array of the target */
1732 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1733 if (!dev->deviate->unique) {
1734 LOGMEM;
1735 goto error;
1736 }
1737 list->unique = dev->deviate->unique;
1738 dev->deviate->unique = &list->unique[list->unique_size];
1739 dev->deviate->unique_size = c_uniq;
1740 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001741 } else {
1742 /* LY_DEVIATE_DEL */
1743 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1744 if (!dev->deviate->unique) {
1745 LOGMEM;
1746 goto error;
1747 }
Pavol Vican85f12022016-03-05 16:30:35 +01001748 }
1749
1750 return EXIT_SUCCESS;
1751
1752error:
1753 return EXIT_FAILURE;
1754}
1755
1756int
Pavol Vican38321d02016-08-16 14:56:02 +02001757yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001758{
Pavol Vican38321d02016-08-16 14:56:02 +02001759 int i;
1760 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001761
Pavol Vican38321d02016-08-16 14:56:02 +02001762 /* check target node type */
1763 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1764 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1765 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1766 goto error;
1767 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1768 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1769 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1770 goto error;
1771 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1772 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1773 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001774 goto error;
1775 }
1776
Pavol Vican38321d02016-08-16 14:56:02 +02001777 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1778 /* check that there is no current value */
1779 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
1780 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
1781 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1782 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001783 goto error;
1784 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001785
Pavol Vican38321d02016-08-16 14:56:02 +02001786 /* check collision with mandatory/min-elements */
1787 if ((dev->target->flags & LYS_MAND_TRUE) ||
1788 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
1789 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1790 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1791 "Adding the \"default\" statement is forbidden on %s statement.",
1792 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1793 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01001794 }
Pavol Vican38321d02016-08-16 14:56:02 +02001795 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1796 /* check that there was a value before */
1797 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
1798 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
1799 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1800 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1801 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001802 }
Pavol Vican38321d02016-08-16 14:56:02 +02001803 }
1804
1805 if (dev->target->nodetype == LYS_LEAFLIST) {
1806 /* reallocate default list in the target */
1807 llist = (struct lys_node_leaflist *)dev->target;
1808 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1809 /* reallocate (enlarge) the unique array of the target */
1810 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
1811 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
1812 /* reallocate (replace) the unique array of the target */
1813 for (i = 0; i < llist->dflt_size; i++) {
1814 lydict_remove(llist->module->ctx, llist->dflt[i]);
1815 }
1816 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
1817 llist->dflt_size = 0;
1818 }
1819 }
1820
1821 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
1822 if (!dev->deviate->dflt) {
1823 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01001824 goto error;
1825 }
1826
1827 return EXIT_SUCCESS;
1828
1829error:
1830 return EXIT_FAILURE;
1831}
1832
1833int
Pavol Vican38321d02016-08-16 14:56:02 +02001834yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
1835{
1836 struct lys_node *node;
1837 struct lys_node_choice *choice;
1838 struct lys_node_leaf *leaf;
1839 struct lys_node_leaflist *llist;
1840 int rc, i;
1841 unsigned int u;
1842 const char *value;
1843
1844 value = lydict_insert_zc(ctx, exp);
1845 u = strlen(value);
1846 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
1847
1848 if (dev->target->nodetype == LYS_CHOICE) {
1849 choice = (struct lys_node_choice *)dev->target;
1850 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1851 if (rc || !node) {
1852 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1853 goto error;
1854 }
1855 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1856 if (!choice->dflt || (choice->dflt != node)) {
1857 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1858 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1859 goto error;
1860 }
1861 } else { /* add or replace */
1862 choice->dflt = node;
1863 if (!choice->dflt) {
1864 /* default branch not found */
1865 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1866 goto error;
1867 }
1868 }
1869 } else if (dev->target->nodetype == LYS_LEAF) {
1870 leaf = (struct lys_node_leaf *)dev->target;
1871 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1872 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1873 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1874 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1875 goto error;
1876 }
1877 /* remove value */
1878 lydict_remove(ctx, leaf->dflt);
1879 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001880 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001881 } else { /* add (already checked) and replace */
1882 /* remove value */
1883 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001884 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001885
1886 /* set new value */
1887 leaf->dflt = lydict_insert(ctx, value, u);
1888
1889 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1890 ly_set_add(dev->dflt_check, dev->target, 0);
1891 }
1892 } else { /* LYS_LEAFLIST */
1893 llist = (struct lys_node_leaflist *)dev->target;
1894 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1895 /* find and remove the value in target list */
1896 for (i = 0; i < llist->dflt_size; i++) {
1897 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1898 /* match, remove the value */
1899 lydict_remove(llist->module->ctx, llist->dflt[i]);
1900 llist->dflt[i] = NULL;
1901 break;
1902 }
1903 }
1904 if (i == llist->dflt_size) {
1905 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1906 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1907 goto error;
1908 }
1909 } else {
1910 /* add or replace, anyway we place items into the deviate's list
1911 which propagates to the target */
1912 /* we just want to check that the value isn't already in the list */
1913 for (i = 0; i < llist->dflt_size; i++) {
1914 if (ly_strequal(llist->dflt[i], value, 1)) {
1915 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1916 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1917 goto error;
1918 }
1919 }
1920 /* store it in target node */
1921 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1922
1923 /* remember to check it later (it may not fit now, but the type can be deviated too) */
1924 ly_set_add(dev->dflt_check, dev->target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001925 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001926 }
1927 }
1928
1929 return EXIT_SUCCESS;
1930error:
1931 return EXIT_FAILURE;
1932}
1933
1934
1935int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001936yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001937{
1938 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001939 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001940 goto error;
1941 }
1942
1943 /* for we deviate from RFC 6020 and allow config property even it is/is not
1944 * specified in the target explicitly since config property inherits. So we expect
1945 * that config is specified in every node. But for delete, we check that the value
1946 * is the same as here in deviation
1947 */
1948 dev->deviate->flags |= value;
1949
1950 /* add and replace are the same in this case */
1951 /* remove current config value of the target ... */
1952 dev->target->flags &= ~LYS_CONFIG_MASK;
1953
1954 /* ... and replace it with the value specified in deviation */
1955 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
1956
1957 return EXIT_SUCCESS;
1958
1959error:
1960 return EXIT_FAILURE;
1961}
1962
1963int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001964yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01001965{
Radek Krejcie00d2312016-08-12 15:27:49 +02001966 struct lys_node *parent;
1967
Pavol Vican85f12022016-03-05 16:30:35 +01001968 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001969 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001970 goto error;
1971 }
1972
1973 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02001974 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001975 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1976 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001977 goto error;
1978 }
1979
1980 dev->deviate->flags |= value;
1981
1982 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1983 /* check that there is no current value */
1984 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001985 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1986 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001987 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001988 } else {
1989 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
1990 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1991 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1992 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1993 goto error;
1994 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
1995 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1996 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1997 goto error;
1998 }
Pavol Vican85f12022016-03-05 16:30:35 +01001999 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002000 } else { /* replace */
2001 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002002 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2003 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002004 goto error;
2005 }
Pavol Vican85f12022016-03-05 16:30:35 +01002006 }
2007
Pavol Vican85f12022016-03-05 16:30:35 +01002008 /* remove current mandatory value of the target ... */
2009 dev->target->flags &= ~LYS_MAND_MASK;
2010
2011 /* ... and replace it with the value specified in deviation */
2012 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2013
Radek Krejcie00d2312016-08-12 15:27:49 +02002014 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2015 for (parent = dev->target->parent;
2016 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2017 parent = parent->parent) {
2018 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2019 /* stop also on presence containers */
2020 break;
2021 }
2022 }
2023 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2024 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2025 if (lyp_check_mandatory_choice(parent)) {
2026 goto error;
2027 }
2028 }
2029
Pavol Vican85f12022016-03-05 16:30:35 +01002030 return EXIT_SUCCESS;
2031
2032error:
2033 return EXIT_FAILURE;
2034}
2035
2036int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002037yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002038{
Pavol Vican09adcc32016-08-25 10:51:36 +02002039 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002040
2041 /* check target node type */
2042 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002043 max = &((struct lys_node_leaflist *)dev->target)->max;
2044 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002045 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002046 max = &((struct lys_node_list *)dev->target)->max;
2047 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002048 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002049 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2050 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 +01002051 goto error;
2052 }
2053
2054 if (type) {
2055 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002056 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002057 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002058 } else {
2059 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002060 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002061 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002062 }
2063
2064 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2065 /* check that there is no current value */
2066 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002067 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2068 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002069 goto error;
2070 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002071 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2072 /* unfortunately, there is no way to check reliably that there
2073 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002074 }
2075
2076 /* add (already checked) and replace */
2077 /* set new value specified in deviation */
2078 *ui32val = value;
2079
Pavol Vican09adcc32016-08-25 10:51:36 +02002080 /* check min-elements is smaller than max-elements */
2081 if (*max && *min > *max) {
2082 if (type) {
2083 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2084 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2085 } else {
2086 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2087 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2088 }
2089 goto error;
2090 }
2091
Pavol Vican85f12022016-03-05 16:30:35 +01002092 return EXIT_SUCCESS;
2093
2094error:
2095 return EXIT_FAILURE;
2096}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002097
2098int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002099yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002100{
2101 int i;
2102
2103 /* find must to delete, we are ok with just matching conditions */
2104 for (i = 0; i < *dev->trg_must_size; i++) {
2105 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2106 /* we have a match, free the must structure ... */
2107 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2108 /* ... and maintain the array */
2109 (*dev->trg_must_size)--;
2110 if (i != *dev->trg_must_size) {
2111 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2112 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2113 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2114 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2115 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2116 }
2117 if (!(*dev->trg_must_size)) {
2118 free(*dev->trg_must);
2119 *dev->trg_must = NULL;
2120 } else {
2121 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2122 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2123 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2124 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2125 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2126 }
2127
2128 i = -1; /* set match flag */
2129 break;
2130 }
2131 }
2132 if (i != -1) {
2133 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002134 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2135 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002136 return EXIT_FAILURE;
2137 }
2138
2139 return EXIT_SUCCESS;
2140}
2141
2142int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002143yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002144{
2145 struct lys_node_list *list;
2146 int i, j;
2147
2148 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002149 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002150 dev->deviate->unique_size++;
2151 goto error;
2152 }
2153
2154 /* find unique structures to delete */
2155 for (i = 0; i < list->unique_size; i++) {
2156 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2157 continue;
2158 }
2159
2160 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2161 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2162 break;
2163 }
2164 }
2165
2166 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2167 /* we have a match, free the unique structure ... */
2168 for (j = 0; j < list->unique[i].expr_size; j++) {
2169 lydict_remove(module->ctx, list->unique[i].expr[j]);
2170 }
2171 free(list->unique[i].expr);
2172 /* ... and maintain the array */
2173 list->unique_size--;
2174 if (i != list->unique_size) {
2175 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2176 list->unique[i].expr = list->unique[list->unique_size].expr;
2177 }
2178
2179 if (!list->unique_size) {
2180 free(list->unique);
2181 list->unique = NULL;
2182 } else {
2183 list->unique[list->unique_size].expr_size = 0;
2184 list->unique[list->unique_size].expr = NULL;
2185 }
2186
2187 i = -1; /* set match flag */
2188 break;
2189 }
2190 }
2191 dev->deviate->unique_size++;
2192
2193 if (i != -1) {
2194 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002195 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2196 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002197 goto error;
2198 }
2199
2200 free(value);
2201 return EXIT_SUCCESS;
2202
2203error:
2204 free(value);
2205 return EXIT_FAILURE;
2206}
Pavol Vicane92421d2016-03-08 10:12:33 +01002207
2208int
Pavol Vican38321d02016-08-16 14:56:02 +02002209yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002210{
2211 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002212 unsigned int u;
2213 const char *value, *target_name;
2214 struct lys_node_leaflist *llist;
2215 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002216
Pavol Vican38321d02016-08-16 14:56:02 +02002217 /* now check whether default value, if any, matches the type */
2218 for (u = 0; u < dflt_check->number; ++u) {
2219 value = NULL;
2220 rc = EXIT_SUCCESS;
2221 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2222 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2223 target_name = leaf->name;
Radek Krejci51673202016-11-01 17:00:32 +01002224 value = leaf->dflt;
2225 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
Pavol Vican38321d02016-08-16 14:56:02 +02002226 } else { /* LYS_LEAFLIST */
2227 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2228 target_name = llist->name;
2229 for (i = 0; i < llist->dflt_size; i++) {
Radek Krejci51673202016-11-01 17:00:32 +01002230 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
2231 (struct lys_node *)(&llist->dflt[i]));
Pavol Vican38321d02016-08-16 14:56:02 +02002232 if (rc == -1) {
Radek Krejci51673202016-11-01 17:00:32 +01002233 value = llist->dflt[i];
Pavol Vicane92421d2016-03-08 10:12:33 +01002234 break;
2235 }
2236 }
2237 }
Pavol Vican38321d02016-08-16 14:56:02 +02002238 if (rc == -1) {
2239 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2240 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2241 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2242 target_name);
2243 return EXIT_FAILURE;
2244 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002245 }
Pavol Vican38321d02016-08-16 14:56:02 +02002246
Pavol Vicane92421d2016-03-08 10:12:33 +01002247 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002248
Pavol Vican9b89dda2016-03-09 15:36:55 +01002249}
2250
Pavol Vicanec423c92016-10-24 21:33:43 +02002251static int
2252yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2253 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002254{
Pavol Vicanec423c92016-10-24 21:33:43 +02002255 struct lys_submodule *submodule;
2256 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002257 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002258 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002259 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002260
Pavol Vicanec423c92016-10-24 21:33:43 +02002261 str = lydict_insert_zc(trg->ctx, value);
2262 if (trg->version) {
2263 submodule = (struct lys_submodule *)trg;
2264 module = ((struct lys_submodule *)trg)->belongsto;
2265 } else {
2266 submodule = NULL;
2267 module = trg;
2268 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002269 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002270 if (!rc) {
2271 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002272 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002273 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002274 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002275 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002276 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002277
Pavol Vicanec423c92016-10-24 21:33:43 +02002278 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002279 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002280}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002281
2282int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002283yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002284{
2285 char *prefix;
2286 char *identif;
2287 const char *ns = NULL;
2288 int i;
2289
Pavol Vicanf4717e62016-03-16 11:30:01 +01002290 /* check to the same pointer */
2291 if (data_node != actual) {
2292 return EXIT_SUCCESS;
2293 }
2294
Pavol Vicana302aa62016-03-17 10:45:35 +01002295 prefix = strdup(value);
2296 if (!prefix) {
2297 LOGMEM;
2298 goto error;
2299 }
2300 /* find prefix anf identificator*/
2301 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002302 if (!identif) {
2303 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2304 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2305 goto error;
2306 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002307 *identif = '\0';
2308 identif++;
2309
Pavol Vicanf4717e62016-03-16 11:30:01 +01002310 for(i = 0; i < module->imp_size; ++i) {
2311 if (!strcmp(module->imp[i].prefix, prefix)) {
2312 ns = module->imp[i].module->ns;
2313 break;
2314 }
2315 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002316 if (!ns && !strcmp(module->prefix, prefix)) {
2317 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2318 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002319 if (ns && !strcmp(ns, LY_NSNACM)) {
2320 if (!strcmp(identif, "default-deny-write")) {
2321 data_node->nacm |= LYS_NACM_DENYW;
2322 } else if (!strcmp(identif, "default-deny-all")) {
2323 data_node->nacm |= LYS_NACM_DENYA;
2324 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002325 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002326 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002327 }
2328 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002329 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002330 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002331
2332error:
2333 free(prefix);
2334 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002335}
2336
2337void
2338nacm_inherit(struct lys_module *module)
2339{
Pavol Vican10ffba52016-04-04 12:21:22 +02002340 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002341
2342 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002343 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002344 if (elem->parent) {
2345 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002346 case LYS_GROUPING:
2347 /* extension nacm not inherited*/
2348 break;
2349 case LYS_CHOICE:
2350 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002351 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002352 case LYS_USES:
2353 if (elem->parent->nodetype != LYS_GROUPING) {
2354 elem->nacm |= elem->parent->nacm;
2355 }
2356 break;
2357 case LYS_CONTAINER:
2358 case LYS_LIST:
2359 case LYS_CASE:
2360 case LYS_NOTIF:
2361 case LYS_RPC:
2362 case LYS_INPUT:
2363 case LYS_OUTPUT:
2364 case LYS_AUGMENT:
2365 elem->nacm |= elem->parent->nacm;
2366 break;
2367 case LYS_LEAF:
2368 case LYS_LEAFLIST:
2369 tmp_node = elem;
2370 tmp_child = elem->child;
2371 elem->child = NULL;
2372 default:
2373 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002374 }
2375 }
2376 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002377 if (tmp_node) {
2378 tmp_node->child = tmp_child;
2379 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002380 }
2381}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002382
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002383int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002384store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002385{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002386 struct lys_node *elem;
2387
Pavol Vican1dac40c2016-09-28 11:39:26 +02002388 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2389 if (config_opt == CONFIG_INHERIT_ENABLE) {
2390 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002391 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002392 if (node->parent) {
2393 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002394 } else {
2395 /* default config is true */
2396 node->flags |= LYS_CONFIG_W;
2397 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002398 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002399 /* do we even care about config flags? */
2400 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002401
Pavol Vican1dac40c2016-09-28 11:39:26 +02002402 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2403 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2404 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2405 return EXIT_FAILURE;
2406 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002407 }
2408 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002409
2410 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002411}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002412
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002413void
2414store_config_flag(struct lys_node *node, int config_opt)
2415{
2416 if (config_opt == CONFIG_IGNORE) {
2417 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
2418 } else if (config_opt == CONFIG_INHERIT_ENABLE) {
2419 if (!(node->flags & LYS_CONFIG_MASK)) {
2420 /* get config flag from parent */
2421 if (node->parent) {
2422 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2423 } else {
2424 /* default config is true */
2425 node->flags |= LYS_CONFIG_W;
2426 }
2427 }
2428 }
2429}
2430
Pavol Vican9d50a772016-10-14 22:23:36 +02002431int
2432yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2433 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002434{
Pavol Vican9d50a772016-10-14 22:23:36 +02002435 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002436 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002437 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002438 int ret = EXIT_SUCCESS, remove_import = 1;
2439 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002440
Pavol Vican9d50a772016-10-14 22:23:36 +02002441 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002442 yylex_init(&scanner);
2443 bp = yy_scan_buffer((char *)data, size, scanner);
2444 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002445 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2446 if (remove_import) {
2447 trg = (submodule) ? (struct lys_module *)submodule : module;
2448 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2449 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2450 trg->inc_size = 0;
2451 trg->imp_size = 0;
2452 }
Pavol Vican1938d882016-04-10 13:36:31 +02002453 ret = EXIT_FAILURE;
2454 }
2455 yy_delete_buffer(bp, scanner);
2456 yylex_destroy(scanner);
2457 return ret;
2458}
2459
Pavol Vican8e7110b2016-03-22 17:00:26 +01002460struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002461yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002462{
2463
Pavol Vican10ffba52016-04-04 12:21:22 +02002464 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002465 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002466 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002467
2468 unres = calloc(1, sizeof *unres);
2469 if (!unres) {
2470 LOGMEM;
2471 goto error;
2472 }
2473
2474 module = calloc(1, sizeof *module);
2475 if (!module) {
2476 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002477 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002478 }
2479
2480 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002481 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002482 module->type = 0;
2483 module->implemented = (implement ? 1 : 0);
2484
Pavol Vican9d50a772016-10-14 22:23:36 +02002485 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002486 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002487 goto error;
2488 }
2489
2490 if (yang_check_sub_module(module, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002491 goto error;
2492 }
2493
2494 if (module && unres->count && resolve_unres_schema(module, unres)) {
2495 goto error;
2496 }
2497
2498 if (revision) {
2499 /* check revision of the parsed model */
2500 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2501 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2502 module->name, module->rev[0].date, revision);
2503 goto error;
2504 }
2505 }
2506
Pavol Vican10ffba52016-04-04 12:21:22 +02002507 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002508 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002509 goto error;
2510 }
2511
Pavol Vican10ffba52016-04-04 12:21:22 +02002512 if (module == tmp_module) {
2513 nacm_inherit(module);
2514 }
2515
Radek Krejci27fe55e2016-09-13 17:13:35 +02002516 if (module->deviation_size && !module->implemented) {
2517 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2518 /* deviations always causes target to be made implemented,
2519 * but augents and leafrefs not, so we have to apply them now */
2520 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002521 goto error;
2522 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002523 }
2524
Pavol Vican8e7110b2016-03-22 17:00:26 +01002525 unres_schema_free(NULL, &unres);
2526 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2527 return module;
2528
2529error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002530 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002531 unres_schema_free(module, &unres);
2532 if (!module || !module->name) {
2533 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002534 if (ly_vecode != LYVE_SUBMODULE) {
2535 LOGERR(ly_errno, "Module parsing failed.");
2536 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002537 return NULL;
2538 }
2539
2540 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002541
2542 lys_sub_module_remove_devs_augs(module);
2543 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002544 return NULL;
2545}
2546
2547struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002548yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002549{
2550 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002551 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002552
2553 submodule = calloc(1, sizeof *submodule);
2554 if (!submodule) {
2555 LOGMEM;
2556 goto error;
2557 }
2558
2559 submodule->ctx = module->ctx;
2560 submodule->type = 1;
2561 submodule->belongsto = module;
2562
Pavol Vican9d50a772016-10-14 22:23:36 +02002563 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002564 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002565 goto error;
2566 }
2567
2568 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002569 goto error;
2570 }
2571
Pavol Vican8e7110b2016-03-22 17:00:26 +01002572 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002573 return submodule;
2574
2575error:
2576 /* cleanup */
2577 unres_schema_free((struct lys_module *)submodule, &unres);
2578
2579 if (!submodule || !submodule->name) {
2580 free(submodule);
2581 LOGERR(ly_errno, "Submodule parsing failed.");
2582 return NULL;
2583 }
2584
2585 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2586
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002587 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2588 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002589 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002590 return NULL;
2591}
Pavol Vican8760bb72016-04-07 09:44:01 +02002592
2593static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002594read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2595{
2596 int k = 0, j;
2597
2598 while (in_index < size) {
2599 if (input[in_index] == ' ') {
2600 k++;
2601 } else if (input[in_index] == '\t') {
2602 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2603 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002604 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2605 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2606 k += 8;
2607 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002608 } else {
2609 break;
2610 }
2611 ++in_index;
2612 if (k >= indent) {
2613 for (j = k - indent; j > 0; --j) {
2614 output[*out_index] = ' ';
2615 ++(*out_index);
2616 }
2617 break;
2618 }
2619 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002620 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002621}
2622
2623char *
Pavol Vican3f598892016-09-28 15:41:07 +02002624yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2625 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002626
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002627 while (i < size) {
2628 switch (input[i]) {
2629 case '\n':
2630 out_index -= space;
2631 output[out_index] = '\n';
2632 space = 0;
2633 i = read_indent(input, indent, size, i + 1, &out_index, output);
2634 break;
2635 case ' ':
2636 case '\t':
2637 output[out_index] = input[i];
2638 ++space;
2639 break;
2640 case '\\':
2641 if (input[i + 1] == 'n') {
2642 out_index -= space;
2643 output[out_index] = '\n';
2644 space = 0;
2645 i = read_indent(input, indent, size, i + 2, &out_index, output);
2646 } else if (input[i + 1] == 't') {
2647 output[out_index] = '\t';
2648 ++i;
2649 ++space;
2650 } else if (input[i + 1] == '\\') {
2651 output[out_index] = '\\';
2652 ++i;
2653 } else if ((i + 1) != size && input[i + 1] == '"') {
2654 output[out_index] = '"';
2655 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002656 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002657 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002658 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002659 } else {
2660 /* YANG 1.1 backslash must not be followed by any other character */
2661 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002662 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002663 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002664 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002665 break;
2666 default:
2667 output[out_index] = input[i];
2668 space = 0;
2669 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002670 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002671 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002672 ++out_index;
2673 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002674 output[out_index] = '\0';
2675 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002676 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002677 if (!output) {
2678 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002679 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002680 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002681 }
Pavol Vican3f598892016-09-28 15:41:07 +02002682 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002683}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002684
2685/* free function */
2686
Pavol Vican7313fc02016-11-14 01:10:31 +01002687static void yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
2688{
2689 struct yang_type *stype = (struct yang_type *)type->der;
2690 int i;
2691
2692 if (!stype) {
2693 return ;
2694 }
2695 lydict_remove(ctx, stype->name);
2696 type->base = stype->base;
2697 if (type->base == LY_TYPE_IDENT) {
2698 for (i = 0; i < type->info.ident.count; ++i) {
2699 free(type->info.ident.ref[i]);
2700 }
2701 }
2702 lys_type_free(ctx, type);
Pavol Vican36aff862016-11-26 17:07:05 +01002703 type->base = LY_TYPE_DER;
Pavol Vican7313fc02016-11-14 01:10:31 +01002704 free(stype);
2705}
2706
2707static void
2708yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2709{
2710 uint8_t i;
2711
2712 assert(ctx);
2713 if (!tpdf) {
2714 return;
2715 }
2716
2717 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002718 lydict_remove(ctx, tpdf[i].name);
2719 lydict_remove(ctx, tpdf[i].dsc);
2720 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002721
Pavol Vicancee10802016-11-22 15:48:35 +01002722 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002723
Pavol Vicancee10802016-11-22 15:48:35 +01002724 lydict_remove(ctx, tpdf[i].units);
2725 lydict_remove(ctx, tpdf[i].dflt);
Pavol Vican7313fc02016-11-14 01:10:31 +01002726 }
2727}
2728
Pavol Vican1cc4e192016-10-24 16:38:31 +02002729static void
2730yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2731{
2732 uint8_t i;
2733
2734 for (i = start; i < size; ++i){
2735 free((char *)imp[i].module);
2736 lydict_remove(ctx, imp[i].prefix);
2737 lydict_remove(ctx, imp[i].dsc);
2738 lydict_remove(ctx, imp[i].ref);
2739 }
2740}
2741
Pavol Vicanec423c92016-10-24 21:33:43 +02002742static void
2743yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2744{
2745 uint8_t i;
2746
2747 for (i = start; i < size; ++i){
2748 free((char *)inc[i].submodule);
2749 lydict_remove(ctx, inc[i].dsc);
2750 lydict_remove(ctx, inc[i].ref);
2751 }
2752}
2753
Pavol Vican36e27272016-11-22 15:47:28 +01002754static void
2755yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2756{
2757 uint32_t i;
2758 uint8_t j;
2759
2760 /* free base name */
2761 for (i = start; i < size; ++i) {
2762 for (j = 0; j < ident[i].base_size; ++j) {
2763 free(ident[i].base[j]);
2764 }
2765 }
2766}
2767
Pavol Vican05810b62016-11-23 14:07:22 +01002768static void
2769yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2770{
2771 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2772 free(grp->tpdf);
2773}
2774
2775static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002776yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2777{
2778 uint8_t i;
2779
2780 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2781 free(cont->tpdf);
2782 lydict_remove(ctx, cont->presence);
2783
2784 for (i = 0; cont->must_size; ++i) {
2785 lys_restr_free(ctx, &cont->must[i]);
2786 }
2787 free(cont->must);
2788
2789 lys_when_free(ctx, cont->when);
2790}
2791
2792static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002793yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2794{
2795 uint8_t i;
2796
2797 for (i = 0; i < leaf->must_size; i++) {
2798 lys_restr_free(ctx, &leaf->must[i]);
2799 }
2800 free(leaf->must);
2801
2802 lys_when_free(ctx, leaf->when);
2803
2804 yang_type_free(ctx, &leaf->type);
2805 lydict_remove(ctx, leaf->units);
2806 lydict_remove(ctx, leaf->dflt);
2807}
2808
2809static void
Pavol Vican36aff862016-11-26 17:07:05 +01002810yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2811{
2812 uint8_t i;
2813
2814 for (i = 0; i < leaflist->must_size; i++) {
2815 lys_restr_free(ctx, &leaflist->must[i]);
2816 }
2817 free(leaflist->must);
2818
2819 for (i = 0; i < leaflist->dflt_size; i++) {
2820 lydict_remove(ctx, leaflist->dflt[i]);
2821 }
2822 free(leaflist->dflt);
2823
2824 lys_when_free(ctx, leaflist->when);
2825
2826 yang_type_free(ctx, &leaflist->type);
2827 lydict_remove(ctx, leaflist->units);
2828}
2829
2830static void
Pavol Vicand8136a42016-11-27 13:28:04 +01002831yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
2832{
2833 uint8_t i;
2834
2835 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
2836 free(list->tpdf);
2837
2838 for (i = 0; i < list->must_size; ++i) {
2839 lys_restr_free(ctx, &list->must[i]);
2840 }
2841 free(list->must);
2842
2843 lys_when_free(ctx, list->when);
2844
2845 for (i = 0; i < list->unique_size; ++i) {
2846 free(list->unique[i].expr);
2847 }
2848 free(list->unique);
2849
2850 free(list->keys);
2851}
2852
2853static void
Pavol Vican36ace102016-11-28 11:46:59 +01002854yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
2855{
2856 free(choice->dflt);
2857 lys_when_free(ctx, choice->when);
2858}
2859
2860static void
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002861yang_free_anydata(struct ly_ctx *ctx, struct lys_node_anydata *anydata)
2862{
2863 uint8_t i;
2864
2865 for (i = 0; i < anydata->must_size; ++i) {
2866 lys_restr_free(ctx, &anydata->must[i]);
2867 }
2868 free(anydata->must);
2869
2870 lys_when_free(ctx, anydata->when);
2871}
2872
2873static void
Pavol Vican78729392016-11-28 17:18:22 +01002874yang_free_inout(struct ly_ctx *ctx, struct lys_node_inout *inout)
2875{
2876 uint8_t i;
2877
2878 yang_tpdf_free(ctx, inout->tpdf, 0, inout->tpdf_size);
2879 free(inout->tpdf);
2880
2881 for (i = 0; i < inout->must_size; ++i) {
2882 lys_restr_free(ctx, &inout->must[i]);
2883 }
2884 free(inout->must);
2885}
2886
2887static void
Pavol Vican29bf8802016-11-28 20:44:57 +01002888yang_free_notif(struct ly_ctx *ctx, struct lys_node_notif *notif)
2889{
2890 uint8_t i;
2891
2892 yang_tpdf_free(ctx, notif->tpdf, 0, notif->tpdf_size);
2893 free(notif->tpdf);
2894
2895 for (i = 0; i < notif->must_size; ++i) {
2896 lys_restr_free(ctx, &notif->must[i]);
2897 }
2898 free(notif->must);
2899}
2900
2901static void
Pavol Vican3b5e82a2016-11-29 21:41:56 +01002902yang_free_uses(struct ly_ctx *ctx, struct lys_node_uses *uses)
2903{
2904 int i, j;
2905
2906 for (i = 0; i < uses->refine_size; i++) {
2907 lydict_remove(ctx, uses->refine[i].target_name);
2908 lydict_remove(ctx, uses->refine[i].dsc);
2909 lydict_remove(ctx, uses->refine[i].ref);
2910
2911 for (j = 0; j < uses->refine[i].must_size; j++) {
2912 lys_restr_free(ctx, &uses->refine[i].must[j]);
2913 }
2914 free(uses->refine[i].must);
2915
2916 for (j = 0; j < uses->refine[i].dflt_size; j++) {
2917 lydict_remove(ctx, uses->refine[i].dflt[j]);
2918 }
2919 free(uses->refine[i].dflt);
2920
2921 if (uses->refine[i].target_type & LYS_CONTAINER) {
2922 lydict_remove(ctx, uses->refine[i].mod.presence);
2923 }
2924 }
2925 free(uses->refine);
2926
2927 lys_when_free(ctx, uses->when);
2928}
2929
2930
2931static void
Pavol Vican05810b62016-11-23 14:07:22 +01002932yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
2933{
2934 struct lys_node *tmp, *child, *sibling;
2935
2936 if (!node) {
2937 return;
2938 }
2939 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01002940
2941 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002942 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01002943 sibling = tmp->next;
2944 /* common part */
2945 lydict_remove(ctx, tmp->name);
2946 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002947 lys_iffeature_free(tmp->iffeature, tmp->iffeature_size);
2948 lydict_remove(ctx, tmp->dsc);
2949 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01002950 }
2951
2952 switch (tmp->nodetype) {
2953 case LYS_GROUPING:
Pavol Vicanebc9ef82016-11-28 16:46:49 +01002954 case LYS_RPC:
2955 case LYS_ACTION:
Pavol Vican05810b62016-11-23 14:07:22 +01002956 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
2957 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002958 case LYS_CONTAINER:
2959 yang_free_container(ctx, (struct lys_node_container *)tmp);
2960 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01002961 case LYS_LEAF:
2962 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
2963 break;
Pavol Vican36aff862016-11-26 17:07:05 +01002964 case LYS_LEAFLIST:
2965 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
2966 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01002967 case LYS_LIST:
2968 yang_free_list(ctx, (struct lys_node_list *)tmp);
2969 break;
Pavol Vican36ace102016-11-28 11:46:59 +01002970 case LYS_CHOICE:
2971 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
2972 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01002973 case LYS_CASE:
2974 lys_when_free(ctx, ((struct lys_node_case *)tmp)->when);
2975 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002976 case LYS_ANYXML:
2977 case LYS_ANYDATA:
2978 yang_free_anydata(ctx, (struct lys_node_anydata *)tmp);
2979 break;
Pavol Vican78729392016-11-28 17:18:22 +01002980 case LYS_INPUT:
2981 case LYS_OUTPUT:
2982 yang_free_inout(ctx, (struct lys_node_inout *)tmp);
2983 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01002984 case LYS_NOTIF:
2985 yang_free_notif(ctx, (struct lys_node_notif *)tmp);
2986 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01002987 case LYS_USES:
2988 yang_free_uses(ctx, (struct lys_node_uses *)tmp);
2989 break;
Pavol Vican05810b62016-11-23 14:07:22 +01002990 default:
2991 break;
2992 }
2993
2994 yang_free_nodes(ctx, child);
2995 free(tmp);
2996 tmp = sibling;
2997 }
2998}
2999
Pavol Vican7313fc02016-11-14 01:10:31 +01003000/* free common item from module and submodule */
3001static void
Pavol Vican05810b62016-11-23 14:07:22 +01003002free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01003003{
3004 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
3005 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01003006 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01003007 yang_free_nodes(module->ctx, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01003008}
3009
Pavol Vican1cc4e192016-10-24 16:38:31 +02003010/* check function*/
3011
3012int
Pavol Vicanec423c92016-10-24 21:33:43 +02003013yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02003014{
3015 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02003016 struct lys_include *inc;
3017 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003018 size_t size;
3019 char *s;
3020
3021 imp = module->imp;
3022 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02003023 inc = module->inc;
3024 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003025
3026 if (imp_size) {
3027 size = (imp_size * sizeof *module->imp) + sizeof(void*);
3028 module->imp_size = 0;
3029 module->imp = calloc(1, size);
3030 if (!module->imp) {
3031 LOGMEM;
3032 goto error;
3033 }
3034 /* set stop block for possible realloc */
3035 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02003036 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02003037
Pavol Vicanec423c92016-10-24 21:33:43 +02003038 if (inc_size) {
3039 size = (inc_size * sizeof *module->inc) + sizeof(void*);
3040 module->inc_size = 0;
3041 module->inc = calloc(1, size);
3042 if (!module->inc) {
3043 LOGMEM;
3044 goto error;
3045 }
3046 /* set stop block for possible realloc */
3047 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02003048 }
3049
3050 for (i = 0; i < imp_size; ++i) {
3051 s = (char *) imp[i].module;
3052 imp[i].module = NULL;
3053 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
3054 ++i;
3055 goto error;
3056 }
3057 }
Pavol Vicanec423c92016-10-24 21:33:43 +02003058 for (j = 0; j < inc_size; ++j) {
3059 s = (char *) inc[i].submodule;
3060 inc[i].submodule = NULL;
3061 if (yang_fill_include(module, s, &inc[i], unres)) {
3062 ++i;
3063 goto error;
3064 }
3065 }
3066 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003067 free(imp);
3068
3069 return EXIT_SUCCESS;
3070
3071error:
3072 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02003073 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003074 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02003075 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02003076 return EXIT_FAILURE;
3077}
Pavol Vican7313fc02016-11-14 01:10:31 +01003078
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003079static int
3080yang_check_type_iffeature(struct lys_module *module, struct unres_schema *unres, struct lys_type *type)
3081{
3082 uint i, j, size;
3083 uint8_t iffeature_size;
3084 LY_DATA_TYPE stype;
3085
3086 if (((struct yang_type *)type->der)->base == LY_TYPE_ENUM) {
3087 stype = LY_TYPE_ENUM;
3088 size = type->info.enums.count;
3089 } else if (((struct yang_type *)type->der)->base == LY_TYPE_BITS) {
3090 stype = LY_TYPE_ENUM;
3091 size = type->info.enums.count;
3092 } else {
3093 return EXIT_SUCCESS;
3094 }
3095
3096 for (i = 0; i < size; ++i) {
3097 if (stype == LY_TYPE_ENUM) {
3098 iffeature_size = type->info.enums.enm[i].iffeature_size;
3099 type->info.enums.enm[i].iffeature_size = 0;
3100 for (j = 0; j < iffeature_size; ++j) {
3101 if (yang_read_if_feature(module, &type->info.enums.enm[i], type->parent,
3102 (char *)type->info.enums.enm[i].iffeature[j].features, unres, ENUM_KEYWORD)) {
3103 goto error;
3104 }
3105 }
3106 } else {
3107 iffeature_size = type->info.bits.bit[i].iffeature_size;
3108 type->info.bits.bit[i].iffeature_size = 0;
3109 for (j = 0; j < iffeature_size; ++j) {
3110 if (yang_read_if_feature(module, &type->info.bits.bit[i], type->parent,
3111 (char *)type->info.bits.bit[i].iffeature[j].features, unres, BIT_KEYWORD)) {
3112 goto error;
3113 }
3114 }
3115 }
3116 }
3117
3118 return EXIT_SUCCESS;
3119error:
3120 return EXIT_FAILURE;
3121}
3122
Pavol Vican7313fc02016-11-14 01:10:31 +01003123int
3124yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3125{
3126 struct lys_tpdf *tpdf;
3127 uint8_t i, tpdf_size, *ptr_tpdf_size;
3128 int ret = EXIT_SUCCESS;
3129
3130 if (!parent) {
3131 tpdf = module->tpdf;
3132 ptr_tpdf_size = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003133 } else {
3134 switch (parent->nodetype) {
3135 case LYS_GROUPING:
3136 tpdf = ((struct lys_node_grp *)parent)->tpdf;
3137 ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
3138 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003139 case LYS_CONTAINER:
3140 tpdf = ((struct lys_node_container *)parent)->tpdf;
3141 ptr_tpdf_size = &((struct lys_node_container *)parent)->tpdf_size;
3142 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003143 case LYS_LIST:
3144 tpdf = ((struct lys_node_list *)parent)->tpdf;
3145 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3146 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003147 case LYS_RPC:
3148 case LYS_ACTION:
3149 tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
3150 ptr_tpdf_size = &((struct lys_node_rpc_action *)parent)->tpdf_size;
3151 break;
Pavol Vican78729392016-11-28 17:18:22 +01003152 case LYS_INPUT:
3153 case LYS_OUTPUT:
3154 tpdf = ((struct lys_node_inout *)parent)->tpdf;
3155 ptr_tpdf_size = &((struct lys_node_inout *)parent)->tpdf_size;
3156 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003157 case LYS_NOTIF:
3158 tpdf = ((struct lys_node_notif *)parent)->tpdf;
3159 ptr_tpdf_size = &((struct lys_node_notif *)parent)->tpdf_size;
3160 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003161 default:
3162 LOGINT;
3163 return EXIT_FAILURE;
3164 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003165 }
3166
3167 tpdf_size = *ptr_tpdf_size;
3168 *ptr_tpdf_size = 0;
3169
3170 for (i = 0; i < tpdf_size; ++i) {
3171 tpdf[i].type.parent = &tpdf[i];
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003172 if (yang_check_type_iffeature(module, unres, &tpdf[i].type)) {
3173 ret = EXIT_FAILURE;
3174 break;
3175 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003176 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
3177 ret = EXIT_FAILURE;
3178 break;
3179 }
3180
3181 /* check default value*/
3182 if (tpdf[i].dflt && unres_schema_add_str(module, unres, &tpdf[i].type, UNRES_TYPE_DFLT, tpdf[i].dflt) == -1) {
3183 ++i;
3184 ret = EXIT_FAILURE;
3185 break;
3186 }
3187 (*ptr_tpdf_size)++;
3188 }
3189 if (i < tpdf_size) {
3190 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3191 }
3192
3193 return ret;
3194}
3195
3196static int
Pavol Vican36e27272016-11-22 15:47:28 +01003197yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3198{
3199 uint32_t i, size, base_size;
3200 uint8_t j;
3201
3202 size = module->ident_size;
3203 module->ident_size = 0;
3204 for (i = 0; i < size; ++i) {
3205 base_size = module->ident[i].base_size;
3206 module->ident[i].base_size = 0;
3207 for (j = 0; j < base_size; ++j) {
3208 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3209 ++j;
3210 module->ident_size = size;
3211 goto error;
3212 }
3213 }
3214 module->ident_size++;
3215 }
3216
3217 return EXIT_SUCCESS;
3218
3219error:
3220 for (; j< module->ident[i].base_size; ++j) {
3221 free(module->ident[i].base[j]);
3222 }
3223 yang_free_ident_base(module->ident, i + 1, size);
3224 return EXIT_FAILURE;
3225}
3226
3227static int
Pavol Vican05810b62016-11-23 14:07:22 +01003228yang_check_grouping(struct lys_module *module, struct lys_node_grp *node, struct unres_schema *unres)
3229{
3230 uint8_t i, size;
3231
3232 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3233 goto error;
3234 }
3235
3236 size = node->iffeature_size;
3237 node->iffeature_size = 0;
3238 for (i = 0; i < size; ++i) {
3239 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, GROUPING_KEYWORD)) {
3240 node->iffeature_size = size;
3241 goto error;
3242 }
3243 }
3244
3245 return EXIT_SUCCESS;
3246
3247error:
3248 return EXIT_FAILURE;
3249}
3250
3251static int
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003252yang_check_container(struct lys_module *module, struct lys_node_container *node, struct unres_schema *unres)
3253{
3254 uint8_t i, size;
3255
3256 if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
3257 goto error;
3258 }
3259
3260 size = node->iffeature_size;
3261 node->iffeature_size = 0;
3262 for (i = 0; i < size; ++i) {
3263 if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, CONTAINER_KEYWORD)) {
3264 node->iffeature_size = size;
3265 goto error;
3266 }
3267 }
3268
3269 /* check XPath dependencies */
3270 if ((node->when || node->must_size) && (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3271 goto error;
3272 }
3273
3274 return EXIT_SUCCESS;
3275error:
3276 return EXIT_FAILURE;
3277}
3278
3279static int
Pavol Vicana69aff22016-11-24 18:23:50 +01003280yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, struct unres_schema *unres)
3281{
3282 uint8_t i, size;
3283
3284 if (yang_check_type_iffeature(module, unres, &leaf->type)) {
3285 yang_type_free(module->ctx, &leaf->type);
3286 goto error;
3287 }
3288
3289 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaf) == -1) {
3290 yang_type_free(module->ctx, &leaf->type);
3291 goto error;
3292 }
3293
3294 if (leaf->dflt && unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)leaf->dflt) == -1) {
3295 goto error;
3296 }
3297
3298 size = leaf->iffeature_size;
3299 leaf->iffeature_size = 0;
3300 for (i = 0; i < size; ++i) {
3301 if (yang_read_if_feature(module, leaf, NULL, (char *)leaf->iffeature[i].features, unres, LEAF_KEYWORD)) {
3302 leaf->iffeature_size = size;
3303 goto error;
3304 }
3305 }
3306
3307 /* check XPath dependencies */
3308 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1)) {
3309 goto error;
3310 }
3311
3312 return EXIT_SUCCESS;
3313error:
3314 return EXIT_FAILURE;
3315}
3316
3317static int
Pavol Vican36aff862016-11-26 17:07:05 +01003318yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, struct unres_schema *unres)
3319{
3320 uint8_t i, size;
3321
3322 if (yang_check_type_iffeature(module, unres, &leaflist->type)) {
3323 yang_type_free(module->ctx, &leaflist->type);
3324 goto error;
3325 }
3326
3327 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)leaflist) == -1) {
3328 yang_type_free(module->ctx, &leaflist->type);
3329 goto error;
3330 }
3331
3332 /* check default value (if not defined, there still could be some restrictions
3333 * that need to be checked against a default value from a derived type) */
3334 for (i = 0; i < leaflist->dflt_size; ++i) {
3335 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaflist->dflt[i])) == -1) {
3336 goto error;
3337 }
3338 }
3339
3340 size = leaflist->iffeature_size;
3341 leaflist->iffeature_size = 0;
3342 for (i = 0; i < size; ++i) {
3343 if (yang_read_if_feature(module, leaflist, NULL, (char *)leaflist->iffeature[i].features, unres, LEAF_LIST_KEYWORD)) {
3344 leaflist->iffeature_size = size;
3345 goto error;
3346 }
3347 }
3348
3349 /* check XPath dependencies */
3350 if ((leaflist->when || leaflist->must_size) && (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1)) {
3351 goto error;
3352 }
3353
3354 return EXIT_SUCCESS;
3355error:
3356 return EXIT_FAILURE;
3357}
3358
3359static int
Pavol Vicand8136a42016-11-27 13:28:04 +01003360yang_check_list(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
3361{
3362 uint8_t size, i;
3363
3364 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3365 goto error;
3366 }
3367
3368 size = list->iffeature_size;
3369 list->iffeature_size = 0;
3370 for (i = 0; i < size; ++i) {
3371 if (yang_read_if_feature(module, list, NULL, (char *)list->iffeature[i].features, unres, LIST_KEYWORD)) {
3372 list->iffeature_size = size;
3373 goto error;
3374 }
3375 }
3376
3377 if (list->keys && yang_read_key(module, list, unres)) {
3378 goto error;
3379 }
3380
3381 if (yang_read_unique(module, list, unres)) {
3382 goto error;
3383 }
3384
3385 /* check XPath dependencies */
3386 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1)) {
3387 goto error;
3388 }
3389
3390 return EXIT_SUCCESS;
3391error:
3392 return EXIT_FAILURE;
3393}
3394
3395static int
Pavol Vican36ace102016-11-28 11:46:59 +01003396yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct unres_schema *unres)
3397{
3398 char *value;
3399 uint8_t size, i;
3400
3401 if (choice->dflt) {
3402 value = (char *)choice->dflt;
3403 choice->dflt = NULL;
3404 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3405 free(value);
3406 goto error;
3407 }
3408 free(value);
3409 }
3410
3411 size = choice->iffeature_size;
3412 choice->iffeature_size = 0;
3413 for (i = 0; i < size; ++i) {
3414 if (yang_read_if_feature(module, choice, NULL, (char *)choice->iffeature[i].features, unres, CHOICE_KEYWORD)) {
3415 choice->iffeature_size = size;
3416 goto error;
3417 }
3418 }
3419
3420 /* check XPath dependencies */
3421 if ((choice->when) && (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1)) {
3422 goto error;
3423 }
3424
3425 return EXIT_SUCCESS;
3426error:
3427 return EXIT_FAILURE;
3428}
3429
3430static int
Pavol Vicana420bac2016-11-28 14:51:54 +01003431yang_check_case(struct lys_module *module, struct lys_node_case *cs, struct unres_schema *unres)
3432{
3433 uint8_t size, i;
3434
3435 size = cs->iffeature_size;
3436 cs->iffeature_size = 0;
3437 for (i = 0; i < size; ++i) {
3438 if (yang_read_if_feature(module, cs, NULL, (char *)cs->iffeature[i].features, unres, CASE_KEYWORD)) {
3439 cs->iffeature_size = size;
3440 return EXIT_FAILURE;
3441 }
3442 }
3443 return EXIT_SUCCESS;
3444}
3445
3446static int
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003447yang_check_anydata(struct lys_module *module, struct lys_node_anydata *anydata, struct unres_schema *unres)
3448{
3449 uint8_t size, i;
3450
3451 size = anydata->iffeature_size;
3452 anydata->iffeature_size = 0;
3453 for (i = 0; i < size; ++i) {
3454 if (yang_read_if_feature(module, anydata, NULL, (char *)anydata->iffeature[i].features, unres, ANYXML_KEYWORD)) {
3455 anydata->iffeature_size = size;
3456 goto error;
3457 }
3458 }
3459
3460 /* check XPath dependencies */
3461 if ((anydata->when) && (unres_schema_add_node(module, unres, anydata, UNRES_XPATH, NULL) == -1)) {
3462 goto error;
3463 }
3464
3465 return EXIT_SUCCESS;
3466error:
3467 return EXIT_FAILURE;
3468}
3469
3470static int
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003471yang_check_rpc_action(struct lys_module *module, struct lys_node_rpc_action *rpc, struct unres_schema *unres)
3472{
3473 uint8_t size, i;
3474 struct lys_node *node;
3475
3476 if (rpc->nodetype == LYS_ACTION) {
3477 for (node = rpc->parent; node; node = lys_parent(node)) {
3478 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
3479 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
3480 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
3481 goto error;
3482 }
3483 }
3484 }
3485 if (yang_check_typedef(module, (struct lys_node *)rpc, unres)) {
3486 goto error;
3487 }
3488
3489 size = rpc->iffeature_size;
3490 rpc->iffeature_size = 0;
3491 for (i = 0; i < size; ++i) {
3492 if (yang_read_if_feature(module, rpc, NULL, (char *)rpc->iffeature[i].features, unres, RPC_KEYWORD)) {
3493 rpc->iffeature_size = size;
3494 goto error;
3495 }
3496 }
3497
3498 return EXIT_SUCCESS;
3499error:
3500 return EXIT_FAILURE;
3501}
3502
3503static int
Pavol Vican29bf8802016-11-28 20:44:57 +01003504yang_check_notif(struct lys_module *module, struct lys_node_notif *notif, struct unres_schema *unres)
3505{
3506 uint8_t size, i;
3507
3508 if (yang_check_typedef(module, (struct lys_node *)notif, unres)) {
3509 goto error;
3510 }
3511
3512 size = notif->iffeature_size;
3513 notif->iffeature_size = 0;
3514 for (i = 0; i < size; ++i) {
3515 if (yang_read_if_feature(module, notif, NULL, (char *)notif->iffeature[i].features, unres, NOTIFICATION_KEYWORD)) {
3516 notif->iffeature_size = size;
3517 goto error;
3518 }
3519 }
3520
3521 /* check XPath dependencies */
3522 if ((notif->must_size) && (unres_schema_add_node(module, unres, notif, UNRES_XPATH, NULL) == -1)) {
3523 goto error;
3524 }
3525
3526 return EXIT_SUCCESS;
3527error:
3528 return EXIT_FAILURE;
3529}
3530
3531static int
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003532yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, struct unres_schema *unres)
3533{
3534 uint8_t size, i, j;
3535
3536 size = uses->iffeature_size;
3537 uses->iffeature_size = 0;
3538 for (i = 0; i < size; ++i) {
3539 if (yang_read_if_feature(module, uses, NULL, (char *)uses->iffeature[i].features, unres, USES_KEYWORD)) {
3540 uses->iffeature_size = size;
3541 goto error;
3542 }
3543 }
3544
3545 for (j = 0; uses->refine_size; ++j) {
3546 size = uses->refine[j].iffeature_size;
3547 uses->refine[j].iffeature_size = 0;
3548 for (i = 0; i < size; ++i) {
3549 if (yang_read_if_feature(module, uses, NULL, (char *)uses->refine[j].iffeature[i].features, unres, REFINE_KEYWORD)) {
3550 uses->refine[j].iffeature_size = size;
3551 goto error;
3552 }
3553 }
3554 }
3555
3556 if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
3557 goto error;
3558 }
3559
3560 /* check XPath dependencies */
3561 if (uses->when && (unres_schema_add_node(module, unres, uses, UNRES_XPATH, NULL) == -1)) {
3562 goto error;
3563 }
3564
3565 return EXIT_SUCCESS;
3566error:
3567 return EXIT_FAILURE;
3568}
3569
3570static int
Pavol Vican05810b62016-11-23 14:07:22 +01003571yang_check_nodes(struct lys_module *module, struct lys_node *nodes, struct unres_schema *unres)
3572{
Pavol Vican24ba7f62016-11-28 12:15:20 +01003573 struct lys_node *node = nodes, *sibling, *child, *parent;
Pavol Vican05810b62016-11-23 14:07:22 +01003574
3575 while (node) {
3576 sibling = node->next;
3577 child = node->child;
Pavol Vican24ba7f62016-11-28 12:15:20 +01003578 parent = node->parent;
Pavol Vican05810b62016-11-23 14:07:22 +01003579 node->next = NULL;
3580 node->child = NULL;
Pavol Vican24ba7f62016-11-28 12:15:20 +01003581 node->parent = NULL;
Pavol Vican05810b62016-11-23 14:07:22 +01003582 node->prev = node;
3583
Pavol Vican24ba7f62016-11-28 12:15:20 +01003584 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
3585 lys_node_unlink(node);
3586 node->next = sibling;
Pavol Vican05810b62016-11-23 14:07:22 +01003587 sibling = node;
Pavol Vican05810b62016-11-23 14:07:22 +01003588 goto error;
3589 }
3590 switch (node->nodetype) {
3591 case LYS_GROUPING:
3592 if (yang_check_grouping(module, (struct lys_node_grp *)node, unres)) {
3593 goto error;
3594 }
3595 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003596 case LYS_CONTAINER:
3597 if (yang_check_container(module, (struct lys_node_container *)node, unres)) {
3598 goto error;
3599 }
3600 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003601 case LYS_LEAF:
3602 if (yang_check_leaf(module, (struct lys_node_leaf *)node, unres)) {
3603 goto error;
3604 }
3605 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003606 case LYS_LEAFLIST:
3607 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, unres)) {
3608 goto error;
3609 }
3610 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003611 case LYS_LIST:
3612 if (yang_check_list(module, (struct lys_node_list *)node, unres)) {
3613 goto error;
3614 }
3615 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003616 case LYS_CHOICE:
3617 if (yang_check_choice(module, (struct lys_node_choice *)node, unres)) {
3618 goto error;
3619 }
3620 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01003621 case LYS_CASE:
3622 if (yang_check_case(module, (struct lys_node_case *)node, unres)) {
3623 goto error;
3624 }
3625 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003626 case LYS_ANYDATA:
3627 case LYS_ANYXML:
3628 if (yang_check_anydata(module, (struct lys_node_anydata *)node, unres)) {
3629 goto error;
3630 }
3631 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003632 case LYS_RPC:
3633 case LYS_ACTION:
3634 if (yang_check_rpc_action(module, (struct lys_node_rpc_action *)node, unres)){
3635 goto error;
3636 }
3637 break;
Pavol Vican78729392016-11-28 17:18:22 +01003638 case LYS_INPUT:
3639 case LYS_OUTPUT:
3640 /* check XPath dependencies */
3641 if (((struct lys_node_inout *)node)->must_size &&
3642 (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3643 goto error;
3644 }
3645 if (yang_check_typedef(module, node, unres)) {
3646 goto error;
3647 }
3648 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003649 case LYS_NOTIF:
3650 if (yang_check_notif(module, (struct lys_node_notif *)node, unres)) {
3651 goto error;
3652 }
3653 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003654 case LYS_USES:
3655 if (yang_check_uses(module, (struct lys_node_uses *)node, unres)) {
3656 goto error;
3657 }
3658 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003659 default:
3660 LOGINT;
3661 sibling = node;
3662 child = NULL;
3663 goto error;
3664 }
3665 if (yang_check_nodes(module, child, unres)) {
3666 child = NULL;
3667 goto error;
3668 }
3669 node = sibling;
3670 }
3671
3672 return EXIT_SUCCESS;
3673error:
3674 yang_free_nodes(module->ctx, sibling);
3675 yang_free_nodes(module->ctx, child);
3676 return EXIT_FAILURE;
3677}
3678
3679static int
Pavol Vican7313fc02016-11-14 01:10:31 +01003680yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
3681{
Pavol Vican05810b62016-11-23 14:07:22 +01003682 uint8_t i, j, size, erase_identities = 1, erase_nodes = 1;
Pavol Vican7a7916f2016-11-21 23:38:30 +01003683 struct lys_feature *feature; /* shortcut */
3684 char *s;
3685
Pavol Vican7313fc02016-11-14 01:10:31 +01003686 if (yang_check_typedef(module, NULL, unres)) {
3687 goto error;
3688 }
3689
Pavol Vican7a7916f2016-11-21 23:38:30 +01003690 /* check features */
3691 for (i = 0; i < module->features_size; ++i) {
3692 feature = &module->features[i];
3693 size = feature->iffeature_size;
3694 feature->iffeature_size = 0;
3695 for (j = 0; j < size; ++j) {
3696 s = (char *)feature->iffeature[j].features;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003697 if (yang_read_if_feature(module, feature, NULL, s, unres, FEATURE_KEYWORD)) {
Pavol Vican7a7916f2016-11-21 23:38:30 +01003698 goto error;
3699 }
3700 if (unres_schema_add_node(module, unres, feature, UNRES_FEATURE, NULL) == -1) {
3701 goto error;
3702 }
3703 }
3704 }
Pavol Vican36e27272016-11-22 15:47:28 +01003705 erase_identities = 0;
3706 if (yang_check_identities(module, unres)) {
3707 goto error;
3708 }
Pavol Vican05810b62016-11-23 14:07:22 +01003709 erase_nodes = 0;
3710 if (yang_check_nodes(module, node, unres)) {
3711 goto error;
3712 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01003713
Pavol Vican7313fc02016-11-14 01:10:31 +01003714 return EXIT_SUCCESS;
3715error:
Pavol Vican36e27272016-11-22 15:47:28 +01003716 if (erase_identities) {
3717 yang_free_ident_base(module->ident, 0, module->ident_size);
3718 }
Pavol Vican05810b62016-11-23 14:07:22 +01003719 if (erase_nodes) {
3720 yang_free_nodes(module->ctx, node);
3721 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003722 return EXIT_FAILURE;
3723}