blob: 3d35193e7684304128fd9a80afc2fe6daacc0e0f [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);
Pavol Vican3ad50f82016-12-04 15:00:36 +010026static int yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
27 int config_opt, struct unres_schema *unres);
Pavol Vican05810b62016-11-23 14:07:22 +010028void lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size);
Pavol Vican082afd02016-10-25 12:39:15 +020029
Michal Vaskofe7e5a72016-05-02 14:49:23 +020030static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010031yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010032{
Pavol Vicanbf805472016-01-26 14:24:56 +010033 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010034 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010035 free(value);
36 return 1;
37 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010038 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010039 return 0;
40 }
41}
42
Michal Vaskofe7e5a72016-05-02 14:49:23 +020043int
Pavol Vican5f0316a2016-04-05 21:21:11 +020044yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010045{
Pavol Vican6eb14e82016-02-03 12:27:13 +010046 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010047
48 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010049 case MODULE_KEYWORD:
50 module->name = lydict_insert_zc(module->ctx, value);
51 break;
52 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010053 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010054 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010055 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010056 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010057 break;
58 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010059 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +010060 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +020061 default:
62 free(value);
63 LOGINT;
64 ret = EXIT_FAILURE;
65 break;
Pavol Vican2a064652016-02-02 22:54:34 +010066 }
67
Pavol Vican021488a2016-01-25 23:56:12 +010068 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010069}
70
Michal Vaskofe7e5a72016-05-02 14:49:23 +020071int
Pavol Vicand0b64c12016-07-15 09:56:19 +020072yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
73{
74 int ret = EXIT_SUCCESS;
75
76 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +020077 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
78 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +020079 } else {
80 if (!strcmp(value, "1")) {
81 if (submodule) {
82 if (module->version > 1) {
83 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
84 ret = EXIT_FAILURE;
85 }
86 } else {
87 module->version = 1;
88 }
89 } else if (!strcmp(value, "1.1")) {
90 if (submodule) {
91 if (module->version != 2) {
92 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
93 ret = EXIT_FAILURE;
94 }
95 } else {
96 module->version = 2;
97 }
98 } else {
99 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
100 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200101 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200102 }
103 free(value);
104 return ret;
105}
106
107int
Pavol Vicane024ab72016-07-27 14:27:43 +0200108yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100109{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100110 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100111
Pavol Vican1cc4e192016-10-24 16:38:31 +0200112 if (!imp && lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100113 free(value);
114 return EXIT_FAILURE;
115 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200116
117 if (imp) {
118 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
119 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100120 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100121 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100122
Pavol Vicanbf805472016-01-26 14:24:56 +0100123 return ret;
124}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100125
Pavol Vican1cc4e192016-10-24 16:38:31 +0200126static int
127yang_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 +0100128{
Pavol Vican0da132e2016-03-21 12:03:03 +0100129 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200130 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100131
Pavol Vican1cc4e192016-10-24 16:38:31 +0200132 if (!imp_old->prefix) {
Pavol Vicane024ab72016-07-27 14:27:43 +0200133 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
Pavol Vican1cc4e192016-10-24 16:38:31 +0200134 goto error;
135 } else {
136 if (lyp_check_identifier(imp_old->prefix, LY_IDENT_PREFIX, module, NULL)) {
137 goto error;
138 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200139 }
Pavol Vican1cc4e192016-10-24 16:38:31 +0200140 memcpy(imp_new, imp_old, sizeof *imp_old);
Pavol Vican0da132e2016-03-21 12:03:03 +0100141 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican1cc4e192016-10-24 16:38:31 +0200142 rc = lyp_check_import(module, exp, imp_new);
Pavol Vican0da132e2016-03-21 12:03:03 +0100143 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200144 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100145 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200146 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100147 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100148
Pavol Vican6eb14e82016-02-03 12:27:13 +0100149 return EXIT_SUCCESS;
Pavol Vican1cc4e192016-10-24 16:38:31 +0200150
151error:
152 free(value);
153 lydict_remove(module->ctx, imp_old->dsc);
154 lydict_remove(module->ctx, imp_old->ref);
155 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100156}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100157
158int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100159yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100160{
161 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100162 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100163
164 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100166 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100167 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100168 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200169 } else if (!strcmp("import", where)){
170 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
171 } else if (!strcmp("include", where)){
172 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100173 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100174 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100175 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100176 }
177 return ret;
178}
179
180int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100181yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100182{
183 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100184 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100185
186 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100187 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100188 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100189 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100190 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200191 } else if (!strcmp("import", where)){
192 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
193 } else if (!strcmp("include", where)){
194 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100195 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100196 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100197 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100198 }
199 return ret;
200}
Pavol Vicanbedff692016-02-03 14:29:17 +0100201
Pavol Vican866d9912016-10-25 09:13:30 +0200202void
203yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval)
Pavol Vicanbedff692016-02-03 14:29:17 +0100204{
Pavol Vicanbedff692016-02-03 14:29:17 +0100205 /* first member of array is last revision */
Pavol Vican866d9912016-10-25 09:13:30 +0200206 if ((module->rev_size - 1) && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100207 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
208 memcpy(module->rev[0].date, value, LY_REV_SIZE);
209 retval->dsc = module->rev[0].dsc;
210 retval->ref = module->rev[0].ref;
211 retval = module->rev;
212 retval->dsc = NULL;
213 retval->ref = NULL;
214 } else {
215 memcpy(retval->date, value, LY_REV_SIZE);
216 }
Pavol Vicanbedff692016-02-03 14:29:17 +0100217 free(value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100218}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100219
220int
Pavol Vicana1827962016-02-29 15:39:42 +0100221yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100222{
Pavol Vican45ccc592016-03-09 18:53:48 +0100223 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100224 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
225 LOGMEM;
226 return EXIT_FAILURE;
227 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100228 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100229 }
230 }
231 (*size)++;
232 return EXIT_SUCCESS;
233}
Pavol Vicane1354e92016-02-09 14:02:09 +0100234
Pavol Vicane1354e92016-02-09 14:02:09 +0100235int
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100236yang_fill_iffeature(struct lys_module *module, struct lys_iffeature *iffeature, void *parent,
237 char *value, struct unres_schema *unres, int parent_is_feature)
Pavol Vicane1354e92016-02-09 14:02:09 +0100238{
239 const char *exp;
240 int ret;
241
Michal Vasko97b32be2016-07-25 10:59:53 +0200242 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
243 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
244 free(value);
245 return EXIT_FAILURE;
246 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100247
Michal Vasko56d082c2016-10-25 14:00:42 +0200248 if (!(exp = transform_iffeat_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100249 free(value);
250 return EXIT_FAILURE;
251 }
252 free(value);
253
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100254 ret = resolve_iffeature_compile(iffeature, exp, (struct lys_node *)parent, parent_is_feature, unres);
Pavol Vicane1354e92016-02-09 14:02:09 +0100255 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100256
Pavol Vicandf9a95c2016-12-02 23:34:51 +0100257 return (ret) ? EXIT_FAILURE : EXIT_SUCCESS;
Pavol Vicane1354e92016-02-09 14:02:09 +0100258}
259
Pavol Vican4fb66c92016-03-17 10:32:27 +0100260int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200261yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100262{
263 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100264 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100265 return EXIT_FAILURE;
266 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200267 if (shortint) {
268 *((uint8_t *)flags) |= (uint8_t)value;
269 } else {
270 *flags |= value;
271 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100272 return EXIT_SUCCESS;
273 }
274}
275
Pavol Vicanbbdef532016-02-09 14:52:12 +0100276int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100277yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100278{
279 const char *exp;
280
Pavol Vican0adf01d2016-03-22 12:29:33 +0100281 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100282 free(value);
283 if (!exp) {
284 return EXIT_FAILURE;
285 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200286
Pavol Vican0adf01d2016-03-22 12:29:33 +0100287 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100288 lydict_remove(module->ctx, exp);
289 return EXIT_FAILURE;
290 }
Pavol Vican44dde2c2016-02-10 11:18:14 +0100291
Pavol Vicanbbdef532016-02-09 14:52:12 +0100292 lydict_remove(module->ctx, exp);
293 return EXIT_SUCCESS;
294}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100295
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100296int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100297yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100298{
299 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100300
Pavol Vicandde090a2016-08-30 15:12:14 +0200301 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100302 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100303 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200304 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100305 }
306 return ret;
307}
Pavol Vicanb5687112016-02-09 22:35:59 +0100308
309int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100310yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100311{
312 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100313 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100314 free(value);
315 return EXIT_FAILURE;
316 } else {
317 cont->presence = lydict_insert_zc(module->ctx, value);
318 return EXIT_SUCCESS;
319 }
320}
321
Pavol Vican235dbd42016-02-10 10:34:19 +0100322void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200323yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100324{
325 struct lys_when *retval;
326
327 retval = calloc(1, sizeof *retval);
328 if (!retval) {
329 LOGMEM;
330 free(value);
331 return NULL;
332 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100333 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200334 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100335 goto error;
336 }
337 switch (type) {
338 case CONTAINER_KEYWORD:
339 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100340 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100341 goto error;
342 }
343 ((struct lys_node_container *)node)->when = retval;
344 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200345 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100346 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200347 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200348 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100349 goto error;
350 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200351 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100352 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100353 case CHOICE_KEYWORD:
354 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100355 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100356 goto error;
357 }
358 ((struct lys_node_choice *)node)->when = retval;
359 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100360 case CASE_KEYWORD:
361 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100362 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100363 goto error;
364 }
365 ((struct lys_node_case *)node)->when = retval;
366 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100367 case LEAF_KEYWORD:
368 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100369 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100370 goto error;
371 }
372 ((struct lys_node_leaf *)node)->when = retval;
373 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100374 case LEAF_LIST_KEYWORD:
375 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100376 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100377 goto error;
378 }
379 ((struct lys_node_leaflist *)node)->when = retval;
380 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100381 case LIST_KEYWORD:
382 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100383 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100384 goto error;
385 }
386 ((struct lys_node_list *)node)->when = retval;
387 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100388 case USES_KEYWORD:
389 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100390 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100391 goto error;
392 }
393 ((struct lys_node_uses *)node)->when = retval;
394 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100395 case AUGMENT_KEYWORD:
396 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100397 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100398 goto error;
399 }
400 ((struct lys_node_augment *)node)->when = retval;
401 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200402 default:
403 goto error;
404 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100405 }
406 free(value);
407 return retval;
408
409error:
410 free(value);
411 lys_when_free(module->ctx, retval);
412 return NULL;
413}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100414
415void *
Pavol Vican05810b62016-11-23 14:07:22 +0100416yang_read_node(struct lys_module *module, struct lys_node *parent, struct lys_node **root,
417 char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100418{
Pavol Vican05810b62016-11-23 14:07:22 +0100419 struct lys_node *node, **child;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100420
Pavol Vican7cadfe72016-02-11 12:33:34 +0100421 node = calloc(1, sizeof_struct);
422 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100423 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100424 LOGMEM;
425 return NULL;
426 }
Pavol Vican531a9132016-03-03 10:10:09 +0100427 if (value) {
428 node->name = lydict_insert_zc(module->ctx, value);
429 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100430 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100431 node->nodetype = nodetype;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100432
433 /* insert the node into the schema tree */
Pavol Vican05810b62016-11-23 14:07:22 +0100434 child = (parent) ? &parent->child : root;
435 if (*child) {
436 (*child)->prev->next = node;
437 (*child)->prev = node;
438 } else {
439 *child = node;
440 node->prev = node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100441 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100442 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100443}
444
445int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200446yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100447{
448 int ret;
449
450 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100451 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100452 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100453 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100454 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100455 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100456 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200457 default:
458 free(value);
459 LOGINT;
460 ret = EXIT_FAILURE;
461 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100462 }
463 return ret;
464}
465
466int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200467yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100468{
469 int ret;
470
471 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100472 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100473 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100474 break;
475 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100476 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100477 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100478 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100479 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100480 break;
PavolVican75af21d2016-12-29 20:04:07 +0100481 case ADD_KEYWORD:
482 case REPLACE_KEYWORD:
483 ret = yang_check_string(module, &((struct lys_deviate *) node)->units, "units", "deviate", value);
484 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200485 default:
486 free(value);
487 LOGINT;
488 ret = EXIT_FAILURE;
489 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100490 }
491 return ret;
492}
Pavol Vican5de33492016-02-22 14:03:24 +0100493
494int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100495yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100496{
497 char *exp, *value;
Radek Krejci5c08a992016-11-02 13:30:04 +0100498 struct lys_node *node;
Pavol Vican5de33492016-02-22 14:03:24 +0100499
500 exp = value = (char *) list->keys;
501 while ((value = strpbrk(value, " \t\n"))) {
502 list->keys_size++;
503 while (isspace(*value)) {
504 value++;
505 }
506 }
507 list->keys_size++;
Radek Krejci5c08a992016-11-02 13:30:04 +0100508
509 list->keys_str = lydict_insert_zc(module->ctx, exp);
Pavol Vican5de33492016-02-22 14:03:24 +0100510 list->keys = calloc(list->keys_size, sizeof *list->keys);
511 if (!list->keys) {
512 LOGMEM;
Radek Krejci5c08a992016-11-02 13:30:04 +0100513 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100514 }
Radek Krejci5c08a992016-11-02 13:30:04 +0100515 for (node = list->parent; node && node->nodetype != LYS_GROUPING; node = lys_parent(node));
516 if (!node && unres_schema_add_node(module, unres, list, UNRES_LIST_KEYS, NULL) == -1) {
517 return EXIT_FAILURE;
Pavol Vican5de33492016-02-22 14:03:24 +0100518 }
Pavol Vican5de33492016-02-22 14:03:24 +0100519 return EXIT_SUCCESS;
Pavol Vican5de33492016-02-22 14:03:24 +0100520}
521
522int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100523yang_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 +0100524{
525 int i, j;
526 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200527 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100528
529 /* count the number of unique leafs in the value */
530 vaux = value;
531 while ((vaux = strpbrk(vaux, " \t\n"))) {
532 unique->expr_size++;
533 while (isspace(*vaux)) {
534 vaux++;
535 }
536 }
537 unique->expr_size++;
538 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
539 if (!unique->expr) {
540 LOGMEM;
541 goto error;
542 }
543
544 for (i = 0; i < unique->expr_size; i++) {
545 vaux = strpbrk(value, " \t\n");
546 if (!vaux) {
547 /* the last token, lydict_insert() will count its size on its own */
548 vaux = value;
549 }
550
551 /* store token into unique structure */
552 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
553
554 /* check that the expression does not repeat */
555 for (j = 0; j < i; j++) {
556 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100557 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
558 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100559 goto error;
560 }
561 }
562 /* try to resolve leaf */
563 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200564 unique_info = malloc(sizeof *unique_info);
565 unique_info->list = (struct lys_node *)list;
566 unique_info->expr = unique->expr[i];
567 unique_info->trg_type = &unique->trg_type;
568 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200569 goto error;
570 }
Pavol Vican85f12022016-03-05 16:30:35 +0100571 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200572 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100573 goto error;
574 }
575 }
576
577 /* move to next token */
578 value = vaux;
579 while(isspace(*value)) {
580 value++;
581 }
582 }
583
584 return EXIT_SUCCESS;
585
586error:
587 return EXIT_FAILURE;
588}
589
590int
Pavol Vican5de33492016-02-22 14:03:24 +0100591yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
592{
593 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100594 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100595
596 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100597 str = (char *)list->unique[k].expr;
598 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100599 goto error;
600 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100601 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100602 }
603 return EXIT_SUCCESS;
604
605error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100606 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100607 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100608}
609
Pavol Vican07f220f2016-09-02 13:04:37 +0200610int
Pavol Vican81344ac2016-09-02 14:23:06 +0200611yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100612{
Pavol Vican81344ac2016-09-02 14:23:06 +0200613 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
614 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
615 goto error;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100616 }
Pavol Vican81344ac2016-09-02 14:23:06 +0200617 if (stype->type->info.lref.path) {
618 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
619 goto error;
620 }
621 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
622 stype->base = LY_TYPE_LEAFREF;
623 return EXIT_SUCCESS;
624
625error:
626 free(value);
627 return EXIT_FAILURE;
628}
629
630int
631yang_read_require_instance(struct yang_type *stype, int req)
632{
633 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
634 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
635 return EXIT_FAILURE;
636 }
637 if (stype->type->info.lref.req) {
638 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
639 return EXIT_FAILURE;
640 }
641 stype->type->info.lref.req = req;
642 stype->base = LY_TYPE_LEAFREF;
643 return EXIT_SUCCESS;
644}
645
646int
Pavol Vican7313fc02016-11-14 01:10:31 +0100647yang_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 +0100648{
Pavol Vican81344ac2016-09-02 14:23:06 +0200649 int i, j, rc, ret = -1;
650 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100651 const char *name, *value;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100652 LY_DATA_TYPE base = 0, base_tmp;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200653 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200654 struct lys_type *dertype;
655 struct lys_type_enum *enms_sc = NULL;
656 struct lys_type_bit *bits_sc = NULL;
657 struct lys_type_bit bit_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +0100658 struct yang_type *yang;
Pavol Vican73e7c992016-02-24 12:18:05 +0100659
Pavol Vican0adf01d2016-03-22 12:29:33 +0100660 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100661 if (!value) {
662 goto error;
663 }
664
665 i = parse_identifier(value);
666 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100667 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100668 lydict_remove(module->ctx, value);
669 goto error;
670 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200671 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100672 name = value;
673 if (value[i]) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100674 type->module_name = lydict_insert(module->ctx, value, i);
Pavol Vican73e7c992016-02-24 12:18:05 +0100675 name += i;
676 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100677 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100678 lydict_remove(module->ctx, value);
679 goto error;
680 }
681 ++name;
682 }
683
Pavol Vican7313fc02016-11-14 01:10:31 +0100684 rc = resolve_superior_type(name, type->module_name, module, parent, &type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100685 if (rc == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100686 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200687 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100688 goto error;
689
Michal Vasko01c6fd22016-05-20 11:43:05 +0200690 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100691 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200692 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200693 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100694 ret = EXIT_FAILURE;
695 goto error;
696 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200697 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200698
Pavol Vican7313fc02016-11-14 01:10:31 +0100699 if (type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200700 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200701 * 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 +0200702 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
703 if (siter) {
704 if (!((struct lys_node_grp *)siter)->nacm) {
705 LOGINT;
706 goto error;
707 }
708 ((struct lys_node_grp *)siter)->nacm--;
709 } else {
710 LOGINT;
711 goto error;
712 }
713 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200714
715 /* check status */
Pavol Vican7313fc02016-11-14 01:10:31 +0100716 if (lyp_check_status(type->parent->flags, type->parent->module, type->parent->name,
717 type->der->flags, type->der->module, type->der->name, parent)) {
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200718 goto error;
719 }
720
Pavol Vican8bd72e42016-08-29 09:53:05 +0200721 base = typ->base;
PavolVicane87cb932016-12-30 15:36:18 +0100722 base_tmp = type->base;
Pavol Vican7313fc02016-11-14 01:10:31 +0100723 type->base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100724 if (base == 0) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100725 base = type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100726 }
727 switch (base) {
728 case LY_TYPE_STRING:
Pavol Vican7313fc02016-11-14 01:10:31 +0100729 if (type->base == LY_TYPE_BINARY) {
730 if (type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100731 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100732 goto error;
733 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100734 type->info.binary.length = type->info.str.length;
735 if (type->info.binary.length && lyp_check_length_range(type->info.binary.length->expr, type)) {
736 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100737 goto error;
738 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100739 } else if (type->base == LY_TYPE_STRING) {
740 if (type->info.str.length && lyp_check_length_range(type->info.str.length->expr, type)) {
741 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100742 goto error;
743 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100744 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100745 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100746 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100747 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100748 break;
749 case LY_TYPE_DEC64:
Pavol Vican7313fc02016-11-14 01:10:31 +0100750 if (type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100751 /* mandatory sub-statement(s) check */
Pavol Vican7313fc02016-11-14 01:10:31 +0100752 if (!type->info.dec64.dig && !type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100753 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100754 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100755 goto error;
756 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100757 if (type->info.dec64.dig && type->der->type.der) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100758 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100759 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100760 goto error;
761 }
Radek Krejci4800f652016-09-08 14:02:52 +0200762
763 /* copy fraction-digits specification from parent type for easier internal use */
Pavol Vican7313fc02016-11-14 01:10:31 +0100764 if (type->der->type.der) {
765 type->info.dec64.dig = type->der->type.info.dec64.dig;
766 type->info.dec64.div = type->der->type.info.dec64.div;
Radek Krejci4800f652016-09-08 14:02:52 +0200767 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100768 if (type->info.dec64.range && lyp_check_length_range(type->info.dec64.range->expr, type)) {
769 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.dec64.range->expr, "range");
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200770 goto error;
771 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100772 } else if (type->base >= LY_TYPE_INT8 && type->base <=LY_TYPE_UINT64) {
773 if (type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100774 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100775 goto error;
776 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100777 type->info.num.range = type->info.dec64.range;
778 if (type->info.num.range && lyp_check_length_range(type->info.num.range->expr, type)) {
779 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100780 goto error;
781 }
782 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100783 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100784 goto error;
785 }
786 break;
Pavol Vican79a763d2016-02-25 15:41:27 +0100787 case LY_TYPE_ENUM:
Pavol Vican7313fc02016-11-14 01:10:31 +0100788 if (type->base != LY_TYPE_ENUM) {
789 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +0100790 goto error;
791 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100792 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200793
794 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100795 if (!type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200796 /* type is derived directly from buit-in enumeartion type and enum statement is required */
797 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
798 goto error;
799 }
800 } else {
801 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100802 if (module->version < 2 && type->info.enums.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200803 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
804 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
805 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
806 goto error;
807 }
808
809 /* restricted enumeration type - the name MUST be used in the base type */
810 enms_sc = dertype->info.enums.enm;
Pavol Vican7313fc02016-11-14 01:10:31 +0100811 for(i = 0; i < type->info.enums.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200812 for (j = 0; j < dertype->info.enums.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100813 if (ly_strequal(enms_sc[j].name, type->info.enums.enm[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200814 break;
815 }
816 }
817 if (j == dertype->info.enums.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100818 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, type->info.enums.enm[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200819 goto error;
820 }
821
Pavol Vican7313fc02016-11-14 01:10:31 +0100822 if (type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200823 /* automatically assign value from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100824 type->info.enums.enm[i].value = enms_sc[j].value;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200825 } else {
826 /* check that the assigned value corresponds to the original
827 * value of the enum in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100828 if (type->info.enums.enm[i].value != enms_sc[j].value) {
829 /* type->info.enums.enm[i].value - assigned value in restricted enum
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200830 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100831 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, type->info.enums.enm[i].value,
832 type->info.enums.enm[i].name, enms_sc[j].value);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200833 goto error;
834 }
835 }
836 }
Pavol Vican79a763d2016-02-25 15:41:27 +0100837 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100838 break;
Pavol Vican03a59442016-03-21 15:23:45 +0100839 case LY_TYPE_BITS:
Pavol Vican7313fc02016-11-14 01:10:31 +0100840 if (type->base != LY_TYPE_BITS) {
841 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +0100842 goto error;
843 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100844 dertype = &type->der->type;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200845
846 if (!dertype->der) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100847 if (!type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200848 /* type is derived directly from buit-in bits type and bit statement is required */
849 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
850 goto error;
851 }
852 } else {
853 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
Pavol Vican7313fc02016-11-14 01:10:31 +0100854 if (module->version < 2 && type->info.bits.count) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200855 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
856 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
857 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
858 goto error;
859 }
860
861 bits_sc = dertype->info.bits.bit;
Pavol Vican7313fc02016-11-14 01:10:31 +0100862 for (i = 0; i < type->info.bits.count; i++) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200863 for (j = 0; j < dertype->info.bits.count; j++) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100864 if (ly_strequal(bits_sc[j].name, type->info.bits.bit[i].name, 1)) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200865 break;
866 }
867 }
868 if (j == dertype->info.bits.count) {
Pavol Vican7313fc02016-11-14 01:10:31 +0100869 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, type->info.bits.bit[i].name);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200870 goto error;
871 }
872
873 /* restricted bits type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100874 if (type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200875 /* automatically assign position from base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100876 type->info.bits.bit[i].pos = bits_sc[j].pos;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200877 } else {
878 /* check that the assigned position corresponds to the original
879 * position of the bit in the base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100880 if (type->info.bits.bit[i].pos != bits_sc[j].pos) {
881 /* type->info.bits.bit[i].pos - assigned position in restricted bits
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200882 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100883 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, type->info.bits.bit[i].pos,
884 type->info.bits.bit[i].name, bits_sc[j].pos);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200885 goto error;
886 }
887 }
888 }
Pavol Vican03a59442016-03-21 15:23:45 +0100889 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200890
Pavol Vican7313fc02016-11-14 01:10:31 +0100891 for (i = type->info.bits.count - 1; i > 0; i--) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200892 j = i;
893
894 /* keep them ordered by position */
Pavol Vican7313fc02016-11-14 01:10:31 +0100895 while (j && type->info.bits.bit[j - 1].pos > type->info.bits.bit[j].pos) {
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200896 /* switch them */
Pavol Vican7313fc02016-11-14 01:10:31 +0100897 memcpy(&bit_tmp, &type->info.bits.bit[j], sizeof bit_tmp);
898 memcpy(&type->info.bits.bit[j], &type->info.bits.bit[j - 1], sizeof bit_tmp);
899 memcpy(&type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200900 j--;
901 }
Pavol Vican03a59442016-03-21 15:23:45 +0100902 }
903 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100904 case LY_TYPE_LEAFREF:
Pavol Vican7313fc02016-11-14 01:10:31 +0100905 if (type->base == LY_TYPE_INST) {
906 if (type->info.lref.path) {
Pavol Vican81344ac2016-09-02 14:23:06 +0200907 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
Pavol Vican1ff0e222016-02-26 12:27:01 +0100908 goto error;
909 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100910 if ((req = type->info.lref.req)) {
911 type->info.inst.req = req;
Pavol Vican81344ac2016-09-02 14:23:06 +0200912 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100913 } else if (type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +0200914 /* require-instance only YANG 1.1 */
Pavol Vican7313fc02016-11-14 01:10:31 +0100915 if (type->info.lref.req && (module->version < 2)) {
Pavol Vican92626d72016-09-21 09:36:09 +0200916 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
917 goto error;
918 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200919 /* flag resolving for later use */
920 if (!tpdftype) {
921 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
922 if (siter) {
923 /* just a flag - do not resolve */
924 tpdftype = 1;
925 }
926 }
927
Pavol Vican7313fc02016-11-14 01:10:31 +0100928 if (type->info.lref.path) {
929 if (type->der->type.der) {
Pavol Vican894ee0f2016-08-30 15:29:46 +0200930 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
931 goto error;
932 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100933 value = type->info.lref.path;
Pavol Vican191613a2016-02-26 16:21:32 +0100934 /* store in the JSON format */
Pavol Vican7313fc02016-11-14 01:10:31 +0100935 type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +0100936 lydict_remove(module->ctx, value);
Pavol Vican7313fc02016-11-14 01:10:31 +0100937 if (!type->info.lref.path) {
Pavol Vican191613a2016-02-26 16:21:32 +0100938 goto error;
939 }
Radek Krejci3a5501d2016-07-18 22:03:34 +0200940 /* try to resolve leafref path only when this is instantiated
941 * leaf, so it is not:
942 * - typedef's type,
943 * - in grouping definition,
944 * - just instantiated in a grouping definition,
945 * because in those cases the nodes referenced in path might not be present
946 * and it is not a bug. */
Pavol Vican7313fc02016-11-14 01:10:31 +0100947 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +0100948 goto error;
949 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100950 } else if (!type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100951 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +0100952 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +0200953 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +0200954 /* copy leafref definition into the derived type */
Pavol Vican7313fc02016-11-14 01:10:31 +0100955 type->info.lref.path = lydict_insert(module->ctx, type->der->type.info.lref.path, 0);
Radek Krejci3a5501d2016-07-18 22:03:34 +0200956 /* and resolve the path at the place we are (if not in grouping/typedef) */
Pavol Vican7313fc02016-11-14 01:10:31 +0100957 if (!tpdftype && unres_schema_add_node(module, unres, type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200958 goto error;
959 }
Radek Krejci742be352016-07-17 12:18:54 +0200960
Radek Krejci3a5501d2016-07-18 22:03:34 +0200961 /* add pointer to leafref target, only on leaves (not in typedefs) */
Pavol Vican7313fc02016-11-14 01:10:31 +0100962 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 +0200963 goto error;
Radek Krejci742be352016-07-17 12:18:54 +0200964 }
Pavol Vican191613a2016-02-26 16:21:32 +0100965 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100966 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100967 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100968 goto error;
969 }
970 break;
971 case LY_TYPE_IDENT:
Pavol Vican7313fc02016-11-14 01:10:31 +0100972 if (type->base != LY_TYPE_IDENT) {
973 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100974 goto error;
975 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100976 if (type->der->type.der) {
977 if (type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
979 goto error;
980 }
981 } else {
Pavol Vican7313fc02016-11-14 01:10:31 +0100982 if (!type->info.ident.ref) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200983 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
984 goto error;
985 }
986 }
Pavol Vican1ff0e222016-02-26 12:27:01 +0100987 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +0100988 case LY_TYPE_UNION:
Pavol Vican7313fc02016-11-14 01:10:31 +0100989 if (type->base != LY_TYPE_UNION) {
990 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +0100991 goto error;
992 }
Pavol Vican7313fc02016-11-14 01:10:31 +0100993 if (!type->info.uni.types) {
994 if (type->der->type.der) {
Pavol Vicana4f045a2016-02-29 15:01:20 +0100995 /* this is just a derived type with no additional type specified/required */
996 break;
997 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100998 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +0100999 goto error;
1000 }
Pavol Vican7313fc02016-11-14 01:10:31 +01001001 for (i = 0; i < type->info.uni.count; i++) {
PavolVican811f03b2016-12-29 23:03:20 +01001002 dertype = &type->info.uni.types[i];
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001003 if (dertype->base == LY_TYPE_DER || dertype->base == LY_TYPE_ERR) {
1004 yang = (struct yang_type *)dertype->der;
1005 dertype->der = NULL;
PavolVicane87cb932016-12-30 15:36:18 +01001006 dertype->parent = type->parent;
1007 if (yang_check_type(module, parent, yang, dertype, tpdftype, unres)) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001008 dertype->der = (struct lys_tpdf *)yang;
1009 ret = EXIT_FAILURE;
PavolVican811f03b2016-12-29 23:03:20 +01001010 type->base = base_tmp;
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001011 base = 0;
1012 goto error;
1013 } else {
1014 lydict_remove(module->ctx, yang->name);
1015 free(yang);
1016 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001017 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001018 if (module->version < 2) {
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001019 if (dertype->base == LY_TYPE_EMPTY) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001020 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1021 goto error;
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001022 } else if (dertype->base == LY_TYPE_LEAFREF) {
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001023 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1024 goto error;
1025 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001026 }
1027 }
1028 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001029
1030 default:
1031 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
Pavol Vican7313fc02016-11-14 01:10:31 +01001032 if (type->base != base) {
1033 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001034 goto error;
1035 }
1036 } else {
1037 LOGINT;
1038 goto error;
1039 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001040 }
1041 return EXIT_SUCCESS;
1042
1043error:
Pavol Vican7313fc02016-11-14 01:10:31 +01001044 if (type->module_name) {
1045 lydict_remove(module->ctx, type->module_name);
1046 type->module_name = NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001047 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001048 if (base) {
PavolVicane87cb932016-12-30 15:36:18 +01001049 type->base = base_tmp;
Pavol Vican8bd72e42016-08-29 09:53:05 +02001050 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001051 return ret;
1052}
1053
Pavol Vicancf2af4d2016-12-21 14:13:06 +01001054void
1055yang_free_type_union(struct ly_ctx *ctx, struct lys_type *type)
1056{
1057 struct lys_type *stype;
1058 struct yang_type *yang;
1059 int i;
1060
1061 for (i = 0; i < type->info.uni.count; ++i) {
1062 stype = &type->info.uni.types[i];
1063 if (stype->base == LY_TYPE_DER || stype->base == LY_TYPE_ERR) {
1064 yang = (struct yang_type *)stype->der;
1065 stype->base = yang->base;
1066 lydict_remove(ctx, yang->name);
1067 free(yang);
1068 } else if (stype->base == LY_TYPE_UNION) {
1069 yang_free_type_union(ctx, stype);
1070 }
1071 }
1072}
1073
Pavol Vican73e7c992016-02-24 12:18:05 +01001074void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001075yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001076{
1077 struct yang_type *typ;
PavolVican75af21d2016-12-29 20:04:07 +01001078 struct lys_deviate *dev;
Pavol Vican73e7c992016-02-24 12:18:05 +01001079
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001080 typ = calloc(1, sizeof *typ);
1081 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001082 LOGMEM;
1083 return NULL;
1084 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001085
1086 typ->flags = LY_YANG_STRUCTURE_FLAG;
1087 switch (type) {
1088 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001089 if (((struct lys_node_leaf *)parent)->type.der) {
1090 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1091 goto error;
1092 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001093 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1094 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1095 typ->type = &((struct lys_node_leaf *)parent)->type;
1096 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001097 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001098 if (((struct lys_node_leaflist *)parent)->type.der) {
1099 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1100 goto error;
1101 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001102 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1103 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1104 typ->type = &((struct lys_node_leaflist *)parent)->type;
1105 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001106 case UNION_KEYWORD:
1107 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1108 typ->type = (struct lys_type *)parent;
1109 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001110 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001111 if (((struct lys_tpdf *)parent)->type.der) {
1112 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1113 goto error;
1114 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001115 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1116 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001117 break;
1118 case REPLACE_KEYWORD:
1119 /* deviation replace type*/
PavolVican75af21d2016-12-29 20:04:07 +01001120 dev = (struct lys_deviate *)parent;
1121 if (dev->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001123 goto error;
1124 }
PavolVican75af21d2016-12-29 20:04:07 +01001125 dev->type = calloc(1, sizeof *dev->type);
1126 if (!dev->type) {
1127 LOGMEM;
Pavol Vican4766aca2016-03-07 12:42:36 +01001128 goto error;
1129 }
PavolVican75af21d2016-12-29 20:04:07 +01001130 dev->type->der = (struct lys_tpdf *)typ;
1131 typ->type = dev->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001132 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001133 default:
1134 goto error;
1135 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001136 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001137 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001138 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001139
1140error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001141 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001142 free(typ);
1143 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001144}
1145
1146void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001147yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001148{
1149 struct lys_restr **length;
1150
Pavol Vican6b072512016-04-04 10:50:21 +02001151 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001152 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001153 typ->base = LY_TYPE_STRING;
1154 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001155 length = &typ->type->info.binary.length;
1156 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001157 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001158 goto error;
1159 }
1160
1161 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001162 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001163 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001164 }
1165 *length = calloc(1, sizeof **length);
1166 if (!*length) {
1167 LOGMEM;
1168 goto error;
1169 }
1170 (*length)->expr = lydict_insert_zc(module->ctx, value);
1171 return *length;
1172
1173error:
1174 free(value);
1175 return NULL;
1176
1177}
Pavol Vican1c203db2016-02-24 14:05:23 +01001178
Pavol Vican6eecf302016-08-10 11:09:05 +02001179int
1180yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001181{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001182 char *buf;
1183 size_t len;
1184
Michal Vasko0aee5c12016-06-17 14:27:26 +02001185 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001186 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001187 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001188 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001189
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001190 len = strlen(value);
1191 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001192
1193 if (!buf) {
1194 LOGMEM;
1195 free(value);
1196 return EXIT_FAILURE;
1197 }
1198
1199 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001200 strcpy(&buf[1], value);
1201 free(value);
1202
Pavol Vican6eecf302016-08-10 11:09:05 +02001203 pattern->expr = lydict_insert_zc(module->ctx, buf);
1204 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001205}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001206
1207void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001208yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001209{
Pavol Vican6b072512016-04-04 10:50:21 +02001210 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001211 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001212 goto error;
1213 }
Pavol Vican6b072512016-04-04 10:50:21 +02001214 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001215 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001216 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001217 goto error;
1218 }
1219 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1220 if (!typ->type->info.dec64.range) {
1221 LOGMEM;
1222 goto error;
1223 }
1224 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1225 return typ->type->info.dec64.range;
1226
1227error:
1228 free(value);
1229 return NULL;
1230}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001231
1232int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001233yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001234{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001235 unsigned int i;
1236
Pavol Vican6b072512016-04-04 10:50:21 +02001237 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1238 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001239 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001240 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001241 goto error;
1242 }
1243 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001244 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001245 goto error;
1246 }
1247 /* range check */
1248 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001249 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001250 goto error;
1251 }
1252 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001253 typ->type->info.dec64.div = 10;
1254 for (i = 1; i < value; i++) {
1255 typ->type->info.dec64.div *= 10;
1256 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001257 return EXIT_SUCCESS;
1258
1259error:
1260 return EXIT_FAILURE;
1261}
Pavol Vican79a763d2016-02-25 15:41:27 +01001262
Pavol Vican874715f2016-10-25 14:52:08 +02001263int
1264yang_read_enum(struct lys_module *module, struct yang_type *typ, struct lys_type_enum *enm, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001265{
Pavol Vican874715f2016-10-25 14:52:08 +02001266 int i, j;
Pavol Vican79a763d2016-02-25 15:41:27 +01001267
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01001268 typ->base = LY_TYPE_ENUM;
Pavol Vicanc6662412016-08-30 08:06:28 +02001269 if (!value[0]) {
1270 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1271 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1272 free(value);
1273 goto error;
1274 }
1275
Pavol Vican79a763d2016-02-25 15:41:27 +01001276 enm->name = lydict_insert_zc(module->ctx, value);
1277
1278 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1279 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001280 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001281 goto error;
1282 }
1283
Pavol Vican874715f2016-10-25 14:52:08 +02001284 j = typ->type->info.enums.count - 1;
Pavol Vican79a763d2016-02-25 15:41:27 +01001285 /* check the name uniqueness */
Pavol Vican874715f2016-10-25 14:52:08 +02001286 for (i = 0; i < j; i++) {
1287 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[j].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001288 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001289 goto error;
1290 }
1291 }
1292
Pavol Vican874715f2016-10-25 14:52:08 +02001293 return EXIT_SUCCESS;
Pavol Vican79a763d2016-02-25 15:41:27 +01001294
1295error:
Pavol Vican874715f2016-10-25 14:52:08 +02001296 return EXIT_FAILURE;
Pavol Vican79a763d2016-02-25 15:41:27 +01001297}
1298
1299int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001300yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001301{
1302 int i, j;
1303
1304 if (!assign) {
1305 /* assign value automatically */
1306 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001307 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001308 goto error;
1309 }
1310 enm->value = *value;
1311 enm->flags |= LYS_AUTOASSIGNED;
1312 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001313 } else if (typ->type->info.enums.enm == enm) {
1314 /* change value, which is assigned automatically, if first enum has value. */
1315 *value = typ->type->info.enums.enm[0].value;
1316 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001317 }
1318
1319 /* check that the value is unique */
1320 j = typ->type->info.enums.count-1;
1321 for (i = 0; i < j; i++) {
1322 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001323 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001324 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1325 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001326 goto error;
1327 }
1328 }
1329
1330 return EXIT_SUCCESS;
1331
1332error:
1333 return EXIT_FAILURE;
1334}
Pavol Vican9887c682016-02-29 11:32:01 +01001335
Pavol Vican59e8dee2016-10-25 15:29:38 +02001336int
1337yang_read_bit(struct lys_module *module, struct yang_type *typ, struct lys_type_bit *bit, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001338{
Pavol Vican59e8dee2016-10-25 15:29:38 +02001339 int i, j;
Pavol Vican9887c682016-02-29 11:32:01 +01001340
PavolVicane87cb932016-12-30 15:36:18 +01001341 typ->base = LY_TYPE_BITS;
Pavol Vican59e8dee2016-10-25 15:29:38 +02001342 bit->name = lydict_insert_zc(module->ctx, value);
1343 if (lyp_check_identifier(bit->name, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001344 free(value);
1345 goto error;
1346 }
Pavol Vican9887c682016-02-29 11:32:01 +01001347
Pavol Vican59e8dee2016-10-25 15:29:38 +02001348 j = typ->type->info.bits.count - 1;
Pavol Vican9887c682016-02-29 11:32:01 +01001349 /* check the name uniqueness */
Pavol Vican59e8dee2016-10-25 15:29:38 +02001350 for (i = 0; i < j; i++) {
Pavol Vican9887c682016-02-29 11:32:01 +01001351 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001352 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001353 goto error;
1354 }
1355 }
Pavol Vican59e8dee2016-10-25 15:29:38 +02001356 return EXIT_SUCCESS;
Pavol Vican9887c682016-02-29 11:32:01 +01001357
1358error:
Pavol Vican59e8dee2016-10-25 15:29:38 +02001359 return EXIT_FAILURE;
Pavol Vican9887c682016-02-29 11:32:01 +01001360}
1361
1362int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001363yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001364{
1365 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001366
1367 if (!assign) {
1368 /* assign value automatically */
1369 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001370 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001371 goto error;
1372 }
1373 bit->pos = (uint32_t)*value;
1374 bit->flags |= LYS_AUTOASSIGNED;
1375 (*value)++;
1376 }
1377
1378 j = typ->type->info.bits.count - 1;
1379 /* check that the value is unique */
1380 for (i = 0; i < j; i++) {
1381 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001382 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 +01001383 goto error;
1384 }
1385 }
1386
Pavol Vican9887c682016-02-29 11:32:01 +01001387 return EXIT_SUCCESS;
1388
1389error:
1390 return EXIT_FAILURE;
1391}
Pavol Vican0df02b02016-03-01 10:28:50 +01001392
Pavol Vican3ad50f82016-12-04 15:00:36 +01001393int
1394yang_read_augment(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *aug, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001395{
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001396 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001397 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001398 free(value);
1399 if (!aug->target_name) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01001400 return EXIT_FAILURE;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001401 }
1402 aug->parent = parent;
1403 aug->module = module;
Pavol Vican3ad50f82016-12-04 15:00:36 +01001404 return EXIT_SUCCESS;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001405}
Pavol Vican220e5a12016-03-03 14:19:43 +01001406
Pavol Vican4c90c642016-03-03 15:06:47 +01001407int
PavolVican75af21d2016-12-29 20:04:07 +01001408yang_read_deviate_unsupported(struct lys_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001409{
PavolVican75af21d2016-12-29 20:04:07 +01001410 if (dev->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001411 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001412 return EXIT_FAILURE;
1413 }
PavolVican75af21d2016-12-29 20:04:07 +01001414 dev->deviate = calloc(1, sizeof *dev->deviate);
1415 dev->deviate[dev->deviate_size].mod = LY_DEVIATE_NO;
1416 dev->deviate_size = 1;
Pavol Vican4c90c642016-03-03 15:06:47 +01001417 return EXIT_SUCCESS;
1418}
Pavol Vican85f12022016-03-05 16:30:35 +01001419
PavolVican75af21d2016-12-29 20:04:07 +01001420void *
1421yang_read_deviate(struct lys_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001422{
PavolVican75af21d2016-12-29 20:04:07 +01001423 struct lys_deviate *deviate;
Pavol Vican85f12022016-03-05 16:30:35 +01001424
PavolVican75af21d2016-12-29 20:04:07 +01001425 if (dev->deviate && dev->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001426 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1427 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
PavolVican75af21d2016-12-29 20:04:07 +01001428 return NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001429 }
PavolVican75af21d2016-12-29 20:04:07 +01001430 if (!(dev->deviate_size % LY_YANG_ARRAY_SIZE)) {
1431 deviate = realloc(dev->deviate, (LY_YANG_ARRAY_SIZE + dev->deviate_size) * sizeof *deviate);
1432 if (!deviate) {
1433 LOGMEM;
1434 return NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001435 }
PavolVican75af21d2016-12-29 20:04:07 +01001436 memset(deviate + dev->deviate_size, 0, LY_YANG_ARRAY_SIZE * sizeof *deviate);
1437 dev->deviate = deviate;
Pavol Vican85f12022016-03-05 16:30:35 +01001438 }
PavolVican75af21d2016-12-29 20:04:07 +01001439 dev->deviate[dev->deviate_size].mod = mod;
1440 return &dev->deviate[dev->deviate_size++];
Pavol Vican85f12022016-03-05 16:30:35 +01001441}
1442
1443int
PavolVican75af21d2016-12-29 20:04:07 +01001444yang_read_deviate_units(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001445{
1446 const char **stritem;
1447
Pavol Vican85f12022016-03-05 16:30:35 +01001448 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001449 if (dev_target->nodetype == LYS_LEAFLIST) {
1450 stritem = &((struct lys_node_leaflist *)dev_target)->units;
1451 } else if (dev_target->nodetype == LYS_LEAF) {
1452 stritem = &((struct lys_node_leaf *)dev_target)->units;
Pavol Vican85f12022016-03-05 16:30:35 +01001453 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001454 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1455 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001456 goto error;
1457 }
1458
PavolVican75af21d2016-12-29 20:04:07 +01001459 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001460 /* check values */
PavolVican75af21d2016-12-29 20:04:07 +01001461 if (!ly_strequal(*stritem, deviate->units, 1)) {
1462 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->units, "units");
Pavol Vican0adf01d2016-03-22 12:29:33 +01001463 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001464 goto error;
1465 }
1466 /* remove current units value of the target */
1467 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001468 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001469 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001470 /* check that there is no current value */
1471 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001472 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1473 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001474 goto error;
1475 }
1476 } else { /* replace */
1477 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001478 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1479 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001480 goto error;
1481 }
1482 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001483 /* remove current units value of the target ... */
1484 lydict_remove(ctx, *stritem);
1485
1486 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001487 *stritem = lydict_insert(ctx, deviate->units, 0);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001488 }
1489
Pavol Vican85f12022016-03-05 16:30:35 +01001490 return EXIT_SUCCESS;
1491
1492error:
1493 return EXIT_FAILURE;
1494}
1495
1496int
PavolVican75af21d2016-12-29 20:04:07 +01001497yang_read_deviate_unique(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001498{
Pavol Vican85f12022016-03-05 16:30:35 +01001499 struct lys_node_list *list;
PavolVican75af21d2016-12-29 20:04:07 +01001500 struct lys_unique *unique;
Pavol Vican85f12022016-03-05 16:30:35 +01001501
1502 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001503 if (dev_target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001504 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1505 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001506 goto error;
1507 }
1508
PavolVican75af21d2016-12-29 20:04:07 +01001509 list = (struct lys_node_list *)dev_target;
1510 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001511 /* reallocate the unique array of the target */
PavolVican75af21d2016-12-29 20:04:07 +01001512 unique = ly_realloc(list->unique, (deviate->unique_size + list->unique_size) * sizeof *unique);
1513 if (!unique) {
Pavol Vican85f12022016-03-05 16:30:35 +01001514 LOGMEM;
1515 goto error;
1516 }
PavolVican75af21d2016-12-29 20:04:07 +01001517 list->unique = unique;
1518 memset(unique + list->unique_size, 0, deviate->unique_size * sizeof *unique);
Pavol Vican85f12022016-03-05 16:30:35 +01001519 }
1520
1521 return EXIT_SUCCESS;
1522
1523error:
1524 return EXIT_FAILURE;
1525}
1526
1527int
PavolVican75af21d2016-12-29 20:04:07 +01001528yang_fill_deviate_default(struct ly_ctx *ctx, struct lys_deviate *deviate, struct lys_node *dev_target,
1529 struct ly_set *dflt_check, const char *value)
Pavol Vican38321d02016-08-16 14:56:02 +02001530{
1531 struct lys_node *node;
1532 struct lys_node_choice *choice;
1533 struct lys_node_leaf *leaf;
1534 struct lys_node_leaflist *llist;
1535 int rc, i;
1536 unsigned int u;
Pavol Vican38321d02016-08-16 14:56:02 +02001537
Pavol Vican38321d02016-08-16 14:56:02 +02001538 u = strlen(value);
PavolVican75af21d2016-12-29 20:04:07 +01001539 if (dev_target->nodetype == LYS_CHOICE) {
1540 choice = (struct lys_node_choice *)dev_target;
Pavol Vican38321d02016-08-16 14:56:02 +02001541 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
1542 if (rc || !node) {
1543 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1544 goto error;
1545 }
PavolVican75af21d2016-12-29 20:04:07 +01001546 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001547 if (!choice->dflt || (choice->dflt != node)) {
1548 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1549 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1550 goto error;
1551 }
1552 } else { /* add or replace */
1553 choice->dflt = node;
1554 if (!choice->dflt) {
1555 /* default branch not found */
1556 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1557 goto error;
1558 }
1559 }
PavolVican75af21d2016-12-29 20:04:07 +01001560 } else if (dev_target->nodetype == LYS_LEAF) {
1561 leaf = (struct lys_node_leaf *)dev_target;
1562 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001563 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
1564 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1565 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
1566 goto error;
1567 }
1568 /* remove value */
1569 lydict_remove(ctx, leaf->dflt);
1570 leaf->dflt = NULL;
Radek Krejcibd117f02016-11-04 16:28:08 +01001571 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001572 } else { /* add (already checked) and replace */
1573 /* remove value */
1574 lydict_remove(ctx, leaf->dflt);
Radek Krejcibd117f02016-11-04 16:28:08 +01001575 leaf->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001576
1577 /* set new value */
1578 leaf->dflt = lydict_insert(ctx, value, u);
1579
1580 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001581 ly_set_add(dflt_check, dev_target, 0);
Pavol Vican38321d02016-08-16 14:56:02 +02001582 }
1583 } else { /* LYS_LEAFLIST */
PavolVican75af21d2016-12-29 20:04:07 +01001584 llist = (struct lys_node_leaflist *)dev_target;
1585 if (deviate->mod == LY_DEVIATE_DEL) {
Pavol Vican38321d02016-08-16 14:56:02 +02001586 /* find and remove the value in target list */
1587 for (i = 0; i < llist->dflt_size; i++) {
1588 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
1589 /* match, remove the value */
1590 lydict_remove(llist->module->ctx, llist->dflt[i]);
1591 llist->dflt[i] = NULL;
1592 break;
1593 }
1594 }
1595 if (i == llist->dflt_size) {
1596 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1597 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
1598 goto error;
1599 }
1600 } else {
1601 /* add or replace, anyway we place items into the deviate's list
1602 which propagates to the target */
1603 /* we just want to check that the value isn't already in the list */
1604 for (i = 0; i < llist->dflt_size; i++) {
1605 if (ly_strequal(llist->dflt[i], value, 1)) {
1606 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
1607 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
1608 goto error;
1609 }
1610 }
1611 /* store it in target node */
1612 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
1613
1614 /* remember to check it later (it may not fit now, but the type can be deviated too) */
PavolVican75af21d2016-12-29 20:04:07 +01001615 ly_set_add(dflt_check, dev_target, 0);
Radek Krejcibd117f02016-11-04 16:28:08 +01001616 llist->flags &= ~LYS_DFLTJSON;
Pavol Vican38321d02016-08-16 14:56:02 +02001617 }
1618 }
1619
1620 return EXIT_SUCCESS;
1621error:
1622 return EXIT_FAILURE;
1623}
1624
Pavol Vican38321d02016-08-16 14:56:02 +02001625int
PavolVican75af21d2016-12-29 20:04:07 +01001626yang_read_deviate_default(struct lys_module *module, struct lys_deviate *deviate,
1627 struct lys_node *dev_target, struct ly_set * dflt_check)
Pavol Vican85f12022016-03-05 16:30:35 +01001628{
PavolVican75af21d2016-12-29 20:04:07 +01001629 int i;
1630 struct lys_node_leaflist *llist;
1631 const char **dflt;
1632
1633 /* check target node type */
1634 if (module->version < 2 && dev_target->nodetype == LYS_LEAFLIST) {
1635 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1636 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1637 goto error;
1638 } else if (deviate->dflt_size > 1 && dev_target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1639 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1640 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1641 goto error;
1642 } else if (!(dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1643 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1644 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001645 goto error;
1646 }
1647
PavolVican75af21d2016-12-29 20:04:07 +01001648 if (deviate->mod == LY_DEVIATE_ADD) {
1649 /* check that there is no current value */
1650 if ((dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) ||
1651 (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt)) {
1652 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1653 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
1654 goto error;
1655 }
Pavol Vican85f12022016-03-05 16:30:35 +01001656
PavolVican75af21d2016-12-29 20:04:07 +01001657 /* check collision with mandatory/min-elements */
1658 if ((dev_target->flags & LYS_MAND_TRUE) ||
1659 (dev_target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev_target)->min)) {
1660 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
1661 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
1662 "Adding the \"default\" statement is forbidden on %s statement.",
1663 (dev_target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
1664 goto error;
1665 }
1666 } else if (deviate->mod == LY_DEVIATE_RPL) {
1667 /* check that there was a value before */
1668 if (((dev_target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev_target)->dflt) ||
1669 (dev_target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev_target)->dflt)) {
1670 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1671 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
1672 goto error;
1673 }
1674 }
Pavol Vican85f12022016-03-05 16:30:35 +01001675
PavolVican75af21d2016-12-29 20:04:07 +01001676 if (dev_target->nodetype == LYS_LEAFLIST) {
1677 /* reallocate default list in the target */
1678 llist = (struct lys_node_leaflist *)dev_target;
1679 if (deviate->mod == LY_DEVIATE_ADD) {
1680 /* reallocate (enlarge) the unique array of the target */
1681 dflt = realloc(llist->dflt, (deviate->dflt_size + llist->dflt_size) * sizeof *dflt);
1682 if (!dflt) {
1683 LOGMEM;
1684 goto error;
1685 }
1686 llist->dflt = dflt;
1687 } else if (deviate->mod == LY_DEVIATE_RPL) {
1688 /* reallocate (replace) the unique array of the target */
1689 for (i = 0; i < llist->dflt_size; i++) {
1690 lydict_remove(llist->module->ctx, llist->dflt[i]);
1691 }
1692 dflt = realloc(llist->dflt, deviate->dflt_size * sizeof *dflt);
1693 if (!dflt) {
1694 LOGMEM;
1695 goto error;
1696 }
1697 llist->dflt = dflt;
1698 llist->dflt_size = 0;
1699 }
1700 }
1701
1702 for (i = 0; i < deviate->dflt_size; ++i) {
1703 if (yang_fill_deviate_default(module->ctx, deviate, dev_target, dflt_check, deviate->dflt[i])) {
1704 goto error;
1705 }
1706 }
Pavol Vican85f12022016-03-05 16:30:35 +01001707
1708 return EXIT_SUCCESS;
1709
1710error:
1711 return EXIT_FAILURE;
1712}
1713
1714int
PavolVican75af21d2016-12-29 20:04:07 +01001715yang_check_deviate_mandatory(struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vican85f12022016-03-05 16:30:35 +01001716{
Radek Krejcie00d2312016-08-12 15:27:49 +02001717 struct lys_node *parent;
1718
Pavol Vican85f12022016-03-05 16:30:35 +01001719 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001720 if (!(dev_target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001721 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1722 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001723 goto error;
1724 }
1725
PavolVican75af21d2016-12-29 20:04:07 +01001726 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001727 /* check that there is no current value */
PavolVican75af21d2016-12-29 20:04:07 +01001728 if (dev_target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001729 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1730 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001731 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02001732 } else {
PavolVican75af21d2016-12-29 20:04:07 +01001733 if (dev_target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001734 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
1735 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
1736 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
1737 goto error;
PavolVican75af21d2016-12-29 20:04:07 +01001738 } else if (dev_target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev_target)->dflt) {
Pavol Vican321a02e2016-04-05 16:11:59 +02001739 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
1740 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
1741 goto error;
1742 }
Pavol Vican85f12022016-03-05 16:30:35 +01001743 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001744 } else { /* replace */
PavolVican75af21d2016-12-29 20:04:07 +01001745 if (!(dev_target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001746 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
1747 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001748 goto error;
1749 }
Pavol Vican85f12022016-03-05 16:30:35 +01001750 }
1751
Pavol Vican85f12022016-03-05 16:30:35 +01001752 /* remove current mandatory value of the target ... */
PavolVican75af21d2016-12-29 20:04:07 +01001753 dev_target->flags &= ~LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001754
1755 /* ... and replace it with the value specified in deviation */
PavolVican75af21d2016-12-29 20:04:07 +01001756 dev_target->flags |= deviate->flags & LYS_MAND_MASK;
Pavol Vican85f12022016-03-05 16:30:35 +01001757
Radek Krejcie00d2312016-08-12 15:27:49 +02001758 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
PavolVican75af21d2016-12-29 20:04:07 +01001759 for (parent = dev_target->parent;
Radek Krejcie00d2312016-08-12 15:27:49 +02001760 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
1761 parent = parent->parent) {
1762 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
1763 /* stop also on presence containers */
1764 break;
1765 }
1766 }
1767 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
1768 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
1769 if (lyp_check_mandatory_choice(parent)) {
1770 goto error;
1771 }
1772 }
1773
Pavol Vican85f12022016-03-05 16:30:35 +01001774 return EXIT_SUCCESS;
1775
1776error:
1777 return EXIT_FAILURE;
1778}
1779
1780int
PavolVican75af21d2016-12-29 20:04:07 +01001781yang_read_deviate_minmax(struct lys_deviate *deviate, struct lys_node *dev_target, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01001782{
Pavol Vican09adcc32016-08-25 10:51:36 +02001783 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01001784
1785 /* check target node type */
PavolVican75af21d2016-12-29 20:04:07 +01001786 if (dev_target->nodetype == LYS_LEAFLIST) {
1787 max = &((struct lys_node_leaflist *)dev_target)->max;
1788 min = &((struct lys_node_leaflist *)dev_target)->min;
1789 } else if (dev_target->nodetype == LYS_LIST) {
1790 max = &((struct lys_node_list *)dev_target)->max;
1791 min = &((struct lys_node_list *)dev_target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01001792 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001793 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1794 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 +01001795 goto error;
1796 }
1797
PavolVican75af21d2016-12-29 20:04:07 +01001798 ui32val = (type) ? max : min;
1799 if (deviate->mod == LY_DEVIATE_ADD) {
Pavol Vican85f12022016-03-05 16:30:35 +01001800 /* check that there is no current value */
1801 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001802 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
1803 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001804 goto error;
1805 }
PavolVican75af21d2016-12-29 20:04:07 +01001806 } else if (deviate->mod == LY_DEVIATE_RPL) {
Pavol Vican4766aca2016-03-07 12:42:36 +01001807 /* unfortunately, there is no way to check reliably that there
1808 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01001809 }
1810
1811 /* add (already checked) and replace */
1812 /* set new value specified in deviation */
1813 *ui32val = value;
1814
Pavol Vican09adcc32016-08-25 10:51:36 +02001815 /* check min-elements is smaller than max-elements */
1816 if (*max && *min > *max) {
1817 if (type) {
1818 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
1819 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
1820 } else {
1821 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
1822 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
1823 }
1824 goto error;
1825 }
1826
Pavol Vican85f12022016-03-05 16:30:35 +01001827 return EXIT_SUCCESS;
1828
1829error:
1830 return EXIT_FAILURE;
1831}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001832
1833int
PavolVican75af21d2016-12-29 20:04:07 +01001834yang_check_deviate_must(struct lys_module *module, struct unres_schema *unres,
1835 struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001836{
PavolVican75af21d2016-12-29 20:04:07 +01001837 int i, j, erase_must = 1;
1838 struct lys_restr **trg_must, *must;
1839 uint8_t *trg_must_size, must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001840
PavolVican75af21d2016-12-29 20:04:07 +01001841 /* check target node type */
1842 switch (dev_target->nodetype) {
1843 case LYS_LEAF:
1844 trg_must = &((struct lys_node_leaf *)dev_target)->must;
1845 trg_must_size = &((struct lys_node_leaf *)dev_target)->must_size;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001846 break;
PavolVican75af21d2016-12-29 20:04:07 +01001847 case LYS_CONTAINER:
1848 trg_must = &((struct lys_node_container *)dev_target)->must;
1849 trg_must_size = &((struct lys_node_container *)dev_target)->must_size;
1850 break;
1851 case LYS_LEAFLIST:
1852 trg_must = &((struct lys_node_leaflist *)dev_target)->must;
1853 trg_must_size = &((struct lys_node_leaflist *)dev_target)->must_size;
1854 break;
1855 case LYS_LIST:
1856 trg_must = &((struct lys_node_list *)dev_target)->must;
1857 trg_must_size = &((struct lys_node_list *)dev_target)->must_size;
1858 break;
1859 case LYS_ANYXML:
1860 case LYS_ANYDATA:
1861 trg_must = &((struct lys_node_anydata *)dev_target)->must;
1862 trg_must_size = &((struct lys_node_anydata *)dev_target)->must_size;
1863 break;
1864 default:
1865 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1866 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
1867 goto error;
1868 }
1869
1870 /* flag will be checked again, clear it for now */
1871 dev_target->flags &= ~LYS_VALID_DEP;
1872
1873 if (deviate->mod == LY_DEVIATE_ADD) {
1874 /* reallocate the must array of the target */
1875 must = ly_realloc(*trg_must, (deviate->must_size + *trg_must_size) * sizeof *must);
1876 if (!must) {
1877 LOGMEM;
1878 goto error;
1879 }
1880 *trg_must = must;
1881 must_size = *trg_must_size;
1882 for (i = 0; i < deviate->must_size; ++i) {
1883 (*trg_must)[must_size].expr = deviate->must[i].expr;
1884 (*trg_must)[must_size].dsc = deviate->must[i].dsc;
1885 (*trg_must)[must_size].ref = deviate->must[i].ref;
1886 (*trg_must)[must_size].emsg = deviate->must[i].emsg;
1887 (*trg_must)[must_size].eapptag = deviate->must[i].eapptag;
1888 ++must_size;
1889 }
1890 free(deviate->must);
1891 deviate->must = &must[*trg_must_size];
1892 *trg_must_size = must_size;
1893 erase_must = 0;
1894 } else if (deviate->mod == LY_DEVIATE_DEL) {
1895 /* find must to delete, we are ok with just matching conditions */
1896 for (j = 0; j < deviate->must_size; ++j) {
1897 for (i = 0; i < *trg_must_size; i++) {
1898 if (ly_strequal(deviate->must[j].expr, (*trg_must)[i].expr, 1)) {
1899 /* we have a match, free the must structure ... */
1900 lys_restr_free(module->ctx, &((*trg_must)[i]));
1901 /* ... and maintain the array */
1902 (*trg_must_size)--;
1903 if (i != *trg_must_size) {
1904 (*trg_must)[i].expr = (*trg_must)[*trg_must_size].expr;
1905 (*trg_must)[i].dsc = (*trg_must)[*trg_must_size].dsc;
1906 (*trg_must)[i].ref = (*trg_must)[*trg_must_size].ref;
1907 (*trg_must)[i].eapptag = (*trg_must)[*trg_must_size].eapptag;
1908 (*trg_must)[i].emsg = (*trg_must)[*trg_must_size].emsg;
1909 }
1910 if (!(*trg_must_size)) {
1911 free(*trg_must);
1912 *trg_must = NULL;
1913 } else {
1914 (*trg_must)[*trg_must_size].expr = NULL;
1915 (*trg_must)[*trg_must_size].dsc = NULL;
1916 (*trg_must)[*trg_must_size].ref = NULL;
1917 (*trg_must)[*trg_must_size].eapptag = NULL;
1918 (*trg_must)[*trg_must_size].emsg = NULL;
1919 }
1920
1921 i = -1; /* set match flag */
1922 break;
1923 }
1924 }
1925 if (i != -1) {
1926 /* no match found */
1927 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, deviate->must[j].expr, "must");
1928 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
1929 goto error;
1930 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001931 }
1932 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001933
PavolVican75af21d2016-12-29 20:04:07 +01001934 /* check XPath dependencies */
1935 if (*trg_must_size && unres_schema_add_node(module, unres, dev_target, UNRES_XPATH, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001936 goto error;
1937 }
1938
PavolVican75af21d2016-12-29 20:04:07 +01001939 return EXIT_SUCCESS;
1940error:
1941 if (deviate->mod == LY_DEVIATE_ADD && erase_must) {
1942 for (i = 0; i < deviate->must_size; ++i) {
1943 lys_restr_free(module->ctx, &deviate->must[i]);
1944 }
1945 free(deviate->must);
1946 }
1947 return EXIT_FAILURE;
1948}
1949
1950int
1951yang_deviate_delete_unique(struct lys_module *module, struct lys_deviate *deviate,
1952 struct lys_node_list *list, int index, char * value)
1953{
1954 int i, j;
1955
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001956 /* find unique structures to delete */
1957 for (i = 0; i < list->unique_size; i++) {
PavolVican75af21d2016-12-29 20:04:07 +01001958 if (list->unique[i].expr_size != deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001959 continue;
1960 }
1961
PavolVican75af21d2016-12-29 20:04:07 +01001962 for (j = 0; j < deviate->unique[index].expr_size; j++) {
1963 if (!ly_strequal(list->unique[i].expr[j], deviate->unique[index].expr[j], 1)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001964 break;
1965 }
1966 }
1967
PavolVican75af21d2016-12-29 20:04:07 +01001968 if (j == deviate->unique[index].expr_size) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001969 /* we have a match, free the unique structure ... */
1970 for (j = 0; j < list->unique[i].expr_size; j++) {
1971 lydict_remove(module->ctx, list->unique[i].expr[j]);
1972 }
1973 free(list->unique[i].expr);
1974 /* ... and maintain the array */
1975 list->unique_size--;
1976 if (i != list->unique_size) {
1977 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
1978 list->unique[i].expr = list->unique[list->unique_size].expr;
1979 }
1980
1981 if (!list->unique_size) {
1982 free(list->unique);
1983 list->unique = NULL;
1984 } else {
1985 list->unique[list->unique_size].expr_size = 0;
1986 list->unique[list->unique_size].expr = NULL;
1987 }
1988
1989 i = -1; /* set match flag */
1990 break;
1991 }
1992 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001993
1994 if (i != -1) {
1995 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001996 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
1997 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
PavolVican75af21d2016-12-29 20:04:07 +01001998 return EXIT_FAILURE;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001999 }
2000
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002001 return EXIT_SUCCESS;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002002}
Pavol Vicane92421d2016-03-08 10:12:33 +01002003
PavolVican75af21d2016-12-29 20:04:07 +01002004int yang_check_deviate_unique(struct lys_module *module, struct lys_deviate *deviate, struct lys_node *dev_target)
Pavol Vicane92421d2016-03-08 10:12:33 +01002005{
PavolVican75af21d2016-12-29 20:04:07 +01002006 struct lys_node_list *list;
2007 char *str;
2008 uint i;
2009 struct lys_unique *last_unique;
Pavol Vicane92421d2016-03-08 10:12:33 +01002010
PavolVican75af21d2016-12-29 20:04:07 +01002011 if (yang_read_deviate_unique(deviate, dev_target)) {
2012 goto error;
2013 }
2014 list = (struct lys_node_list *)dev_target;
2015 last_unique = &list->unique[list->unique_size];
2016 for (i = 0; i < deviate->unique_size; ++i) {
2017 str = (char *) deviate->unique[i].expr;
2018 if (deviate->mod == LY_DEVIATE_ADD) {
2019 if (yang_fill_unique(module, list, &list->unique[list->unique_size], str, NULL)) {
2020 free(str);
2021 goto error;
2022 }
2023 list->unique_size++;
2024 } else if (deviate->mod == LY_DEVIATE_DEL) {
2025 if (yang_fill_unique(module, list, &deviate->unique[i], str, NULL)) {
2026 free(str);
2027 goto error;
2028 }
2029 if (yang_deviate_delete_unique(module, deviate, list, i, str)) {
2030 free(str);
2031 goto error;
Pavol Vicane92421d2016-03-08 10:12:33 +01002032 }
2033 }
PavolVican75af21d2016-12-29 20:04:07 +01002034 free(str);
2035 }
2036 if (deviate->mod == LY_DEVIATE_ADD) {
2037 free(deviate->unique);
2038 deviate->unique = last_unique;
Pavol Vicane92421d2016-03-08 10:12:33 +01002039 }
Pavol Vican38321d02016-08-16 14:56:02 +02002040
Pavol Vican38321d02016-08-16 14:56:02 +02002041
PavolVican75af21d2016-12-29 20:04:07 +01002042 return EXIT_SUCCESS;
2043error:
2044 if (deviate->mod == LY_DEVIATE_ADD) {
2045 for (i = i + 1; i < deviate->unique_size; ++i) {
2046 free(deviate->unique[i].expr);
2047 }
2048 free(deviate->unique);
2049 deviate->unique = last_unique;
2050
2051 }
2052 return EXIT_FAILURE;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002053}
2054
Pavol Vicanec423c92016-10-24 21:33:43 +02002055static int
2056yang_fill_include(struct lys_module *trg, char *value, struct lys_include *inc,
2057 struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002058{
Pavol Vicanec423c92016-10-24 21:33:43 +02002059 struct lys_submodule *submodule;
2060 struct lys_module *module;
Pavol Vican55870412016-03-10 12:36:21 +01002061 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002062 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002063 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002064
Pavol Vicanec423c92016-10-24 21:33:43 +02002065 str = lydict_insert_zc(trg->ctx, value);
Pavol Vicanfda8c802016-12-03 02:00:42 +01002066 if (trg->type) {
Pavol Vicanec423c92016-10-24 21:33:43 +02002067 submodule = (struct lys_submodule *)trg;
2068 module = ((struct lys_submodule *)trg)->belongsto;
2069 } else {
2070 submodule = NULL;
2071 module = trg;
2072 }
Pavol Vicane024ab72016-07-27 14:27:43 +02002073 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002074 if (!rc) {
2075 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002076 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002077 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002078 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002079 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002080 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002081
Pavol Vicanec423c92016-10-24 21:33:43 +02002082 lydict_remove(trg->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002083 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002084}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002085
2086int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002087yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002088{
2089 char *prefix;
2090 char *identif;
2091 const char *ns = NULL;
2092 int i;
2093
Pavol Vicanf4717e62016-03-16 11:30:01 +01002094 /* check to the same pointer */
2095 if (data_node != actual) {
2096 return EXIT_SUCCESS;
2097 }
2098
Pavol Vicana302aa62016-03-17 10:45:35 +01002099 prefix = strdup(value);
2100 if (!prefix) {
2101 LOGMEM;
2102 goto error;
2103 }
2104 /* find prefix anf identificator*/
2105 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002106 if (!identif) {
2107 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2108 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2109 goto error;
2110 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002111 *identif = '\0';
2112 identif++;
2113
Pavol Vicanf4717e62016-03-16 11:30:01 +01002114 for(i = 0; i < module->imp_size; ++i) {
2115 if (!strcmp(module->imp[i].prefix, prefix)) {
2116 ns = module->imp[i].module->ns;
2117 break;
2118 }
2119 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002120 if (!ns && !strcmp(module->prefix, prefix)) {
2121 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2122 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002123 if (ns && !strcmp(ns, LY_NSNACM)) {
2124 if (!strcmp(identif, "default-deny-write")) {
2125 data_node->nacm |= LYS_NACM_DENYW;
2126 } else if (!strcmp(identif, "default-deny-all")) {
2127 data_node->nacm |= LYS_NACM_DENYA;
2128 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002129 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002130 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002131 }
2132 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002133 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002134 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002135
2136error:
2137 free(prefix);
2138 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002139}
2140
2141void
2142nacm_inherit(struct lys_module *module)
2143{
Pavol Vican10ffba52016-04-04 12:21:22 +02002144 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002145
2146 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002147 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002148 if (elem->parent) {
2149 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002150 case LYS_GROUPING:
2151 /* extension nacm not inherited*/
2152 break;
2153 case LYS_CHOICE:
2154 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002155 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002156 case LYS_USES:
2157 if (elem->parent->nodetype != LYS_GROUPING) {
2158 elem->nacm |= elem->parent->nacm;
2159 }
2160 break;
2161 case LYS_CONTAINER:
2162 case LYS_LIST:
2163 case LYS_CASE:
2164 case LYS_NOTIF:
2165 case LYS_RPC:
2166 case LYS_INPUT:
2167 case LYS_OUTPUT:
2168 case LYS_AUGMENT:
2169 elem->nacm |= elem->parent->nacm;
2170 break;
2171 case LYS_LEAF:
2172 case LYS_LEAFLIST:
2173 tmp_node = elem;
2174 tmp_child = elem->child;
2175 elem->child = NULL;
2176 default:
2177 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002178 }
2179 }
2180 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002181 if (tmp_node) {
2182 tmp_node->child = tmp_child;
2183 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002184 }
2185}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002186
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002187int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002188store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002189{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002190 struct lys_node *elem;
2191
Pavol Vican1dac40c2016-09-28 11:39:26 +02002192 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2193 if (config_opt == CONFIG_INHERIT_ENABLE) {
2194 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002195 /* get config flag from parent */
Radek Krejcif71f48f2016-10-25 16:37:24 +02002196 if (node->parent) {
2197 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002198 } else {
2199 /* default config is true */
2200 node->flags |= LYS_CONFIG_W;
2201 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002202 } else {
Pavol Vican1dac40c2016-09-28 11:39:26 +02002203 /* do we even care about config flags? */
2204 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002205
Pavol Vican1dac40c2016-09-28 11:39:26 +02002206 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2207 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2208 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2209 return EXIT_FAILURE;
2210 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002211 }
2212 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002213
2214 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002215}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002216
Pavol Vicanec598812016-11-30 14:13:38 +01002217int
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002218store_config_flag(struct lys_node *node, int config_opt)
2219{
Pavol Vicanec598812016-11-30 14:13:38 +01002220 int ret = config_opt;
2221
2222 switch (node->nodetype) {
2223 case LYS_CONTAINER:
2224 case LYS_LEAF:
2225 case LYS_LEAFLIST:
2226 case LYS_LIST:
2227 case LYS_CHOICE:
2228 case LYS_ANYDATA:
2229 case LYS_ANYXML:
2230 if (config_opt == CONFIG_IGNORE) {
2231 node->flags |= node->flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET));
2232 } else if (config_opt == CONFIG_INHERIT_ENABLE) {
2233 if (!(node->flags & LYS_CONFIG_MASK)) {
2234 /* get config flag from parent */
2235 if (node->parent) {
2236 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2237 } else {
2238 /* default config is true */
2239 node->flags |= LYS_CONFIG_W;
2240 }
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002241 }
2242 }
Pavol Vicanec598812016-11-30 14:13:38 +01002243 break;
2244 case LYS_CASE:
2245 if (config_opt == CONFIG_INHERIT_ENABLE) {
2246 if (!(node->flags & LYS_CONFIG_MASK)) {
2247 /* get config flag from parent */
2248 if (node->parent) {
2249 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2250 } else {
2251 /* default config is true */
2252 node->flags |= LYS_CONFIG_W;
2253 }
2254 }
2255 }
2256 break;
2257 case LYS_RPC:
2258 case LYS_ACTION:
2259 case LYS_NOTIF:
2260 ret = CONFIG_IGNORE;
2261 break;
2262 default:
2263 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002264 }
Pavol Vicanec598812016-11-30 14:13:38 +01002265
2266 return ret;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002267}
2268
Pavol Vican9d50a772016-10-14 22:23:36 +02002269int
2270yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres,
2271 const char *data, unsigned int size_data, struct lys_node **node)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002272{
Pavol Vican9d50a772016-10-14 22:23:36 +02002273 unsigned int size;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002274 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002275 yyscan_t scanner = NULL;
Pavol Vican082afd02016-10-25 12:39:15 +02002276 int ret = EXIT_SUCCESS, remove_import = 1;
2277 struct lys_module *trg;
Pavol Vican1938d882016-04-10 13:36:31 +02002278
Pavol Vican9d50a772016-10-14 22:23:36 +02002279 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002280 yylex_init(&scanner);
2281 bp = yy_scan_buffer((char *)data, size, scanner);
2282 yy_switch_to_buffer(bp, scanner);
Pavol Vican082afd02016-10-25 12:39:15 +02002283 if (yyparse(scanner, NULL, module, submodule, unres, node, &remove_import)) {
2284 if (remove_import) {
2285 trg = (submodule) ? (struct lys_module *)submodule : module;
2286 yang_free_import(trg->ctx, trg->imp, 0, trg->imp_size);
2287 yang_free_include(trg->ctx, trg->inc, 0, trg->inc_size);
2288 trg->inc_size = 0;
2289 trg->imp_size = 0;
2290 }
Pavol Vican1938d882016-04-10 13:36:31 +02002291 ret = EXIT_FAILURE;
2292 }
2293 yy_delete_buffer(bp, scanner);
2294 yylex_destroy(scanner);
2295 return ret;
2296}
2297
Pavol Vican8e7110b2016-03-22 17:00:26 +01002298struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002299yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002300{
2301
Pavol Vican10ffba52016-04-04 12:21:22 +02002302 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002303 struct unres_schema *unres = NULL;
Pavol Vican9d50a772016-10-14 22:23:36 +02002304 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002305
2306 unres = calloc(1, sizeof *unres);
2307 if (!unres) {
2308 LOGMEM;
2309 goto error;
2310 }
2311
2312 module = calloc(1, sizeof *module);
2313 if (!module) {
2314 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002315 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002316 }
2317
2318 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002319 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002320 module->type = 0;
2321 module->implemented = (implement ? 1 : 0);
2322
Pavol Vican9d50a772016-10-14 22:23:36 +02002323 if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002324 free_yang_common(module, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002325 goto error;
2326 }
2327
2328 if (yang_check_sub_module(module, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002329 goto error;
2330 }
2331
2332 if (module && unres->count && resolve_unres_schema(module, unres)) {
2333 goto error;
2334 }
2335
2336 if (revision) {
2337 /* check revision of the parsed model */
2338 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2339 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2340 module->name, module->rev[0].date, revision);
2341 goto error;
2342 }
2343 }
2344
Pavol Vican10ffba52016-04-04 12:21:22 +02002345 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002346 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002347 goto error;
2348 }
2349
Pavol Vican10ffba52016-04-04 12:21:22 +02002350 if (module == tmp_module) {
2351 nacm_inherit(module);
2352 }
2353
Radek Krejci27fe55e2016-09-13 17:13:35 +02002354 if (module->deviation_size && !module->implemented) {
2355 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2356 /* deviations always causes target to be made implemented,
2357 * but augents and leafrefs not, so we have to apply them now */
2358 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002359 goto error;
2360 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002361 }
2362
Pavol Vican8e7110b2016-03-22 17:00:26 +01002363 unres_schema_free(NULL, &unres);
2364 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2365 return module;
2366
2367error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002368 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002369 unres_schema_free(module, &unres);
2370 if (!module || !module->name) {
2371 free(module);
Radek Krejci48cfa0f2016-11-08 19:18:34 +01002372 if (ly_vecode != LYVE_SUBMODULE) {
2373 LOGERR(ly_errno, "Module parsing failed.");
2374 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002375 return NULL;
2376 }
2377
2378 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002379
2380 lys_sub_module_remove_devs_augs(module);
2381 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002382 return NULL;
2383}
2384
2385struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002386yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002387{
2388 struct lys_submodule *submodule;
Pavol Vican9d50a772016-10-14 22:23:36 +02002389 struct lys_node *node = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002390
2391 submodule = calloc(1, sizeof *submodule);
2392 if (!submodule) {
2393 LOGMEM;
2394 goto error;
2395 }
2396
2397 submodule->ctx = module->ctx;
2398 submodule->type = 1;
2399 submodule->belongsto = module;
2400
Pavol Vican9d50a772016-10-14 22:23:36 +02002401 if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
Pavol Vican05810b62016-11-23 14:07:22 +01002402 free_yang_common((struct lys_module *)submodule, node);
Pavol Vican7313fc02016-11-14 01:10:31 +01002403 goto error;
2404 }
2405
2406 if (yang_check_sub_module((struct lys_module *)submodule, unres, node)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002407 goto error;
2408 }
2409
Pavol Vican8e7110b2016-03-22 17:00:26 +01002410 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002411 return submodule;
2412
2413error:
2414 /* cleanup */
2415 unres_schema_free((struct lys_module *)submodule, &unres);
2416
2417 if (!submodule || !submodule->name) {
2418 free(submodule);
2419 LOGERR(ly_errno, "Submodule parsing failed.");
2420 return NULL;
2421 }
2422
2423 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2424
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002425 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2426 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002427 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002428 return NULL;
2429}
Pavol Vican8760bb72016-04-07 09:44:01 +02002430
2431static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002432read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2433{
2434 int k = 0, j;
2435
2436 while (in_index < size) {
2437 if (input[in_index] == ' ') {
2438 k++;
2439 } else if (input[in_index] == '\t') {
2440 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2441 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002442 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2443 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2444 k += 8;
2445 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002446 } else {
2447 break;
2448 }
2449 ++in_index;
2450 if (k >= indent) {
2451 for (j = k - indent; j > 0; --j) {
2452 output[*out_index] = ' ';
Pavol Vicana7bf3372016-12-01 15:58:18 +01002453 if (j > 1) {
2454 ++(*out_index);
2455 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002456 }
2457 break;
2458 }
2459 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002460 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002461}
2462
2463char *
Pavol Vican3f598892016-09-28 15:41:07 +02002464yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2465 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002466
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002467 while (i < size) {
2468 switch (input[i]) {
2469 case '\n':
2470 out_index -= space;
2471 output[out_index] = '\n';
2472 space = 0;
2473 i = read_indent(input, indent, size, i + 1, &out_index, output);
2474 break;
2475 case ' ':
2476 case '\t':
2477 output[out_index] = input[i];
2478 ++space;
2479 break;
2480 case '\\':
2481 if (input[i + 1] == 'n') {
2482 out_index -= space;
2483 output[out_index] = '\n';
2484 space = 0;
2485 i = read_indent(input, indent, size, i + 2, &out_index, output);
2486 } else if (input[i + 1] == 't') {
2487 output[out_index] = '\t';
2488 ++i;
2489 ++space;
2490 } else if (input[i + 1] == '\\') {
2491 output[out_index] = '\\';
2492 ++i;
2493 } else if ((i + 1) != size && input[i + 1] == '"') {
2494 output[out_index] = '"';
2495 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002496 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002497 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002498 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002499 } else {
2500 /* YANG 1.1 backslash must not be followed by any other character */
2501 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002502 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002503 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002504 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002505 break;
2506 default:
2507 output[out_index] = input[i];
2508 space = 0;
2509 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002510 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002511 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002512 ++out_index;
2513 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002514 output[out_index] = '\0';
2515 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002516 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002517 if (!output) {
2518 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002519 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002520 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002521 }
Pavol Vican3f598892016-09-28 15:41:07 +02002522 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002523}
Pavol Vican1cc4e192016-10-24 16:38:31 +02002524
2525/* free function */
2526
Pavol Vican7313fc02016-11-14 01:10:31 +01002527static void yang_type_free(struct ly_ctx *ctx, struct lys_type *type)
2528{
2529 struct yang_type *stype = (struct yang_type *)type->der;
2530 int i;
2531
2532 if (!stype) {
2533 return ;
2534 }
PavolVicane87cb932016-12-30 15:36:18 +01002535 if (type->base == LY_TYPE_DER || type->base == LY_TYPE_ERR || type->base == LY_TYPE_UNION) {
2536 lydict_remove(ctx, stype->name);
2537 if (stype->base == LY_TYPE_IDENT && (!(stype->flags & LYS_NO_ERASE_IDENTITY))) {
2538 for (i = 0; i < type->info.ident.count; ++i) {
2539 free(type->info.ident.ref[i]);
2540 }
Pavol Vican7313fc02016-11-14 01:10:31 +01002541 }
PavolVicane87cb932016-12-30 15:36:18 +01002542 if (stype->base == LY_TYPE_UNION) {
2543 for (i = 0; i < type->info.uni.count; ++i) {
2544 yang_type_free(ctx, &type->info.uni.types[i]);
2545 }
2546 free(type->info.uni.types);
2547 type->base = LY_TYPE_DER;
2548 } else {
2549 type->base = stype->base;
2550 }
2551 free(stype);
2552 type->der = NULL;
Pavol Vican7313fc02016-11-14 01:10:31 +01002553 }
2554 lys_type_free(ctx, type);
Pavol Vican36aff862016-11-26 17:07:05 +01002555 type->base = LY_TYPE_DER;
Pavol Vican7313fc02016-11-14 01:10:31 +01002556}
2557
2558static void
2559yang_tpdf_free(struct ly_ctx *ctx, struct lys_tpdf *tpdf, uint8_t start, uint8_t size)
2560{
2561 uint8_t i;
2562
2563 assert(ctx);
2564 if (!tpdf) {
2565 return;
2566 }
2567
2568 for (i = start; i < size; ++i) {
Pavol Vicancee10802016-11-22 15:48:35 +01002569 lydict_remove(ctx, tpdf[i].name);
2570 lydict_remove(ctx, tpdf[i].dsc);
2571 lydict_remove(ctx, tpdf[i].ref);
Pavol Vican7313fc02016-11-14 01:10:31 +01002572
Pavol Vicancee10802016-11-22 15:48:35 +01002573 yang_type_free(ctx, &tpdf[i].type);
Pavol Vican7313fc02016-11-14 01:10:31 +01002574
Pavol Vicancee10802016-11-22 15:48:35 +01002575 lydict_remove(ctx, tpdf[i].units);
2576 lydict_remove(ctx, tpdf[i].dflt);
Pavol Vican7313fc02016-11-14 01:10:31 +01002577 }
2578}
2579
Pavol Vican1cc4e192016-10-24 16:38:31 +02002580static void
2581yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size)
2582{
2583 uint8_t i;
2584
2585 for (i = start; i < size; ++i){
2586 free((char *)imp[i].module);
2587 lydict_remove(ctx, imp[i].prefix);
2588 lydict_remove(ctx, imp[i].dsc);
2589 lydict_remove(ctx, imp[i].ref);
2590 }
2591}
2592
Pavol Vicanec423c92016-10-24 21:33:43 +02002593static void
2594yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size)
2595{
2596 uint8_t i;
2597
2598 for (i = start; i < size; ++i){
2599 free((char *)inc[i].submodule);
2600 lydict_remove(ctx, inc[i].dsc);
2601 lydict_remove(ctx, inc[i].ref);
2602 }
2603}
2604
Pavol Vican36e27272016-11-22 15:47:28 +01002605static void
2606yang_free_ident_base(struct lys_ident *ident, uint32_t start, uint32_t size)
2607{
2608 uint32_t i;
2609 uint8_t j;
2610
2611 /* free base name */
2612 for (i = start; i < size; ++i) {
2613 for (j = 0; j < ident[i].base_size; ++j) {
2614 free(ident[i].base[j]);
2615 }
2616 }
2617}
2618
Pavol Vican05810b62016-11-23 14:07:22 +01002619static void
2620yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
2621{
2622 yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
2623 free(grp->tpdf);
2624}
2625
2626static void
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002627yang_free_container(struct ly_ctx *ctx, struct lys_node_container * cont)
2628{
2629 uint8_t i;
2630
2631 yang_tpdf_free(ctx, cont->tpdf, 0, cont->tpdf_size);
2632 free(cont->tpdf);
2633 lydict_remove(ctx, cont->presence);
2634
Pavol Vicanfda8c802016-12-03 02:00:42 +01002635 for (i = 0; i < cont->must_size; ++i) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002636 lys_restr_free(ctx, &cont->must[i]);
2637 }
2638 free(cont->must);
2639
2640 lys_when_free(ctx, cont->when);
2641}
2642
2643static void
Pavol Vicana69aff22016-11-24 18:23:50 +01002644yang_free_leaf(struct ly_ctx *ctx, struct lys_node_leaf *leaf)
2645{
2646 uint8_t i;
2647
2648 for (i = 0; i < leaf->must_size; i++) {
2649 lys_restr_free(ctx, &leaf->must[i]);
2650 }
2651 free(leaf->must);
2652
2653 lys_when_free(ctx, leaf->when);
2654
2655 yang_type_free(ctx, &leaf->type);
2656 lydict_remove(ctx, leaf->units);
2657 lydict_remove(ctx, leaf->dflt);
2658}
2659
2660static void
Pavol Vican36aff862016-11-26 17:07:05 +01002661yang_free_leaflist(struct ly_ctx *ctx, struct lys_node_leaflist *leaflist)
2662{
2663 uint8_t i;
2664
2665 for (i = 0; i < leaflist->must_size; i++) {
2666 lys_restr_free(ctx, &leaflist->must[i]);
2667 }
2668 free(leaflist->must);
2669
2670 for (i = 0; i < leaflist->dflt_size; i++) {
2671 lydict_remove(ctx, leaflist->dflt[i]);
2672 }
2673 free(leaflist->dflt);
2674
2675 lys_when_free(ctx, leaflist->when);
2676
2677 yang_type_free(ctx, &leaflist->type);
2678 lydict_remove(ctx, leaflist->units);
2679}
2680
2681static void
Pavol Vicand8136a42016-11-27 13:28:04 +01002682yang_free_list(struct ly_ctx *ctx, struct lys_node_list *list)
2683{
2684 uint8_t i;
2685
2686 yang_tpdf_free(ctx, list->tpdf, 0, list->tpdf_size);
2687 free(list->tpdf);
2688
2689 for (i = 0; i < list->must_size; ++i) {
2690 lys_restr_free(ctx, &list->must[i]);
2691 }
2692 free(list->must);
2693
2694 lys_when_free(ctx, list->when);
2695
2696 for (i = 0; i < list->unique_size; ++i) {
2697 free(list->unique[i].expr);
2698 }
2699 free(list->unique);
2700
2701 free(list->keys);
2702}
2703
2704static void
Pavol Vican36ace102016-11-28 11:46:59 +01002705yang_free_choice(struct ly_ctx *ctx, struct lys_node_choice *choice)
2706{
2707 free(choice->dflt);
2708 lys_when_free(ctx, choice->when);
2709}
2710
2711static void
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002712yang_free_anydata(struct ly_ctx *ctx, struct lys_node_anydata *anydata)
2713{
2714 uint8_t i;
2715
2716 for (i = 0; i < anydata->must_size; ++i) {
2717 lys_restr_free(ctx, &anydata->must[i]);
2718 }
2719 free(anydata->must);
2720
2721 lys_when_free(ctx, anydata->when);
2722}
2723
2724static void
Pavol Vican78729392016-11-28 17:18:22 +01002725yang_free_inout(struct ly_ctx *ctx, struct lys_node_inout *inout)
2726{
2727 uint8_t i;
2728
2729 yang_tpdf_free(ctx, inout->tpdf, 0, inout->tpdf_size);
2730 free(inout->tpdf);
2731
2732 for (i = 0; i < inout->must_size; ++i) {
2733 lys_restr_free(ctx, &inout->must[i]);
2734 }
2735 free(inout->must);
2736}
2737
2738static void
Pavol Vican29bf8802016-11-28 20:44:57 +01002739yang_free_notif(struct ly_ctx *ctx, struct lys_node_notif *notif)
2740{
2741 uint8_t i;
2742
2743 yang_tpdf_free(ctx, notif->tpdf, 0, notif->tpdf_size);
2744 free(notif->tpdf);
2745
2746 for (i = 0; i < notif->must_size; ++i) {
2747 lys_restr_free(ctx, &notif->must[i]);
2748 }
2749 free(notif->must);
2750}
2751
2752static void
Pavol Vican3b5e82a2016-11-29 21:41:56 +01002753yang_free_uses(struct ly_ctx *ctx, struct lys_node_uses *uses)
2754{
2755 int i, j;
2756
2757 for (i = 0; i < uses->refine_size; i++) {
2758 lydict_remove(ctx, uses->refine[i].target_name);
2759 lydict_remove(ctx, uses->refine[i].dsc);
2760 lydict_remove(ctx, uses->refine[i].ref);
2761
2762 for (j = 0; j < uses->refine[i].must_size; j++) {
2763 lys_restr_free(ctx, &uses->refine[i].must[j]);
2764 }
2765 free(uses->refine[i].must);
2766
2767 for (j = 0; j < uses->refine[i].dflt_size; j++) {
2768 lydict_remove(ctx, uses->refine[i].dflt[j]);
2769 }
2770 free(uses->refine[i].dflt);
2771
2772 if (uses->refine[i].target_type & LYS_CONTAINER) {
2773 lydict_remove(ctx, uses->refine[i].mod.presence);
2774 }
2775 }
2776 free(uses->refine);
2777
2778 lys_when_free(ctx, uses->when);
2779}
2780
Pavol Vican3b5e82a2016-11-29 21:41:56 +01002781static void
Pavol Vican05810b62016-11-23 14:07:22 +01002782yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
2783{
2784 struct lys_node *tmp, *child, *sibling;
2785
2786 if (!node) {
2787 return;
2788 }
2789 tmp = node;
Pavol Vican05810b62016-11-23 14:07:22 +01002790
2791 while (tmp) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002792 child = tmp->child;
Pavol Vican05810b62016-11-23 14:07:22 +01002793 sibling = tmp->next;
2794 /* common part */
2795 lydict_remove(ctx, tmp->name);
2796 if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
Pavol Vicane87ff8d2016-11-24 18:25:01 +01002797 lys_iffeature_free(tmp->iffeature, tmp->iffeature_size);
2798 lydict_remove(ctx, tmp->dsc);
2799 lydict_remove(ctx, tmp->ref);
Pavol Vican05810b62016-11-23 14:07:22 +01002800 }
2801
2802 switch (tmp->nodetype) {
2803 case LYS_GROUPING:
Pavol Vicanebc9ef82016-11-28 16:46:49 +01002804 case LYS_RPC:
2805 case LYS_ACTION:
Pavol Vican05810b62016-11-23 14:07:22 +01002806 yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
2807 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01002808 case LYS_CONTAINER:
2809 yang_free_container(ctx, (struct lys_node_container *)tmp);
2810 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01002811 case LYS_LEAF:
2812 yang_free_leaf(ctx, (struct lys_node_leaf *)tmp);
2813 break;
Pavol Vican36aff862016-11-26 17:07:05 +01002814 case LYS_LEAFLIST:
2815 yang_free_leaflist(ctx, (struct lys_node_leaflist *)tmp);
2816 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01002817 case LYS_LIST:
2818 yang_free_list(ctx, (struct lys_node_list *)tmp);
2819 break;
Pavol Vican36ace102016-11-28 11:46:59 +01002820 case LYS_CHOICE:
2821 yang_free_choice(ctx, (struct lys_node_choice *)tmp);
2822 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01002823 case LYS_CASE:
2824 lys_when_free(ctx, ((struct lys_node_case *)tmp)->when);
2825 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01002826 case LYS_ANYXML:
2827 case LYS_ANYDATA:
2828 yang_free_anydata(ctx, (struct lys_node_anydata *)tmp);
2829 break;
Pavol Vican78729392016-11-28 17:18:22 +01002830 case LYS_INPUT:
2831 case LYS_OUTPUT:
2832 yang_free_inout(ctx, (struct lys_node_inout *)tmp);
2833 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01002834 case LYS_NOTIF:
2835 yang_free_notif(ctx, (struct lys_node_notif *)tmp);
2836 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01002837 case LYS_USES:
2838 yang_free_uses(ctx, (struct lys_node_uses *)tmp);
2839 break;
Pavol Vican05810b62016-11-23 14:07:22 +01002840 default:
2841 break;
2842 }
2843
2844 yang_free_nodes(ctx, child);
2845 free(tmp);
2846 tmp = sibling;
2847 }
2848}
2849
Pavol Vican3ad50f82016-12-04 15:00:36 +01002850static void
2851yang_free_augment(struct ly_ctx *ctx, struct lys_node_augment *aug)
2852{
2853 lydict_remove(ctx, aug->target_name);
2854 lydict_remove(ctx, aug->dsc);
2855 lydict_remove(ctx, aug->ref);
2856
2857 lys_iffeature_free(aug->iffeature, aug->iffeature_size);
2858 lys_when_free(ctx, aug->when);
2859 yang_free_nodes(ctx, aug->child);
2860}
2861
PavolVican75af21d2016-12-29 20:04:07 +01002862static void
2863yang_free_deviate(struct ly_ctx *ctx, struct lys_deviation *dev, uint index)
2864{
2865 uint i, j;
2866
2867 for (i = index; i < dev->deviate_size; ++i) {
2868 lydict_remove(ctx, dev->deviate[i].units);
2869
2870 if (dev->deviate[i].type) {
2871 yang_type_free(ctx, dev->deviate[i].type);
2872 }
2873
2874 for (j = 0; j < dev->deviate[i].dflt_size; ++j) {
2875 lydict_remove(ctx, dev->deviate[i].dflt[j]);
2876 }
2877 free(dev->deviate[i].dflt);
2878
2879 for (j = 0; j < dev->deviate[i].must_size; ++j) {
2880 lys_restr_free(ctx, &dev->deviate[i].must[j]);
2881 }
2882 free(dev->deviate[i].must);
2883
2884 for (j = 0; j < dev->deviate[i].unique_size; ++j) {
2885 free(dev->deviate[i].unique[j].expr);
2886 }
2887 free(dev->deviate[i].unique);
2888 }
2889}
2890
Pavol Vican7313fc02016-11-14 01:10:31 +01002891/* free common item from module and submodule */
2892static void
Pavol Vican05810b62016-11-23 14:07:22 +01002893free_yang_common(struct lys_module *module, struct lys_node *node)
Pavol Vican7313fc02016-11-14 01:10:31 +01002894{
PavolVican75af21d2016-12-29 20:04:07 +01002895 uint i;
Pavol Vican7313fc02016-11-14 01:10:31 +01002896 yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
2897 module->tpdf_size = 0;
Pavol Vican36e27272016-11-22 15:47:28 +01002898 yang_free_ident_base(module->ident, 0, module->ident_size);
Pavol Vican05810b62016-11-23 14:07:22 +01002899 yang_free_nodes(module->ctx, node);
PavolVican75af21d2016-12-29 20:04:07 +01002900 for (i = 0; i < module->augment_size; ++i) {
2901 yang_free_augment(module->ctx, &module->augment[i]);
2902 }
2903 module->augment_size = 0;
2904 for (i = 0; i < module->deviation_size; ++i) {
2905 yang_free_deviate(module->ctx, &module->deviation[i], 0);
2906 free(module->deviation[i].deviate);
2907 }
2908 module->deviation_size = 0;
Pavol Vican7313fc02016-11-14 01:10:31 +01002909}
2910
Pavol Vican1cc4e192016-10-24 16:38:31 +02002911/* check function*/
2912
2913int
Pavol Vicanec423c92016-10-24 21:33:43 +02002914yang_check_imports(struct lys_module *module, struct unres_schema *unres)
Pavol Vican1cc4e192016-10-24 16:38:31 +02002915{
2916 struct lys_import *imp;
Pavol Vicanec423c92016-10-24 21:33:43 +02002917 struct lys_include *inc;
2918 uint8_t imp_size, inc_size, j = 0, i = 0;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002919 size_t size;
2920 char *s;
2921
2922 imp = module->imp;
2923 imp_size = module->imp_size;
Pavol Vicanec423c92016-10-24 21:33:43 +02002924 inc = module->inc;
2925 inc_size = module->inc_size;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002926
2927 if (imp_size) {
2928 size = (imp_size * sizeof *module->imp) + sizeof(void*);
2929 module->imp_size = 0;
2930 module->imp = calloc(1, size);
2931 if (!module->imp) {
2932 LOGMEM;
2933 goto error;
2934 }
2935 /* set stop block for possible realloc */
2936 module->imp[imp_size].module = (void*)0x1;
Pavol Vicanec423c92016-10-24 21:33:43 +02002937 }
Pavol Vican1cc4e192016-10-24 16:38:31 +02002938
Pavol Vicanec423c92016-10-24 21:33:43 +02002939 if (inc_size) {
2940 size = (inc_size * sizeof *module->inc) + sizeof(void*);
2941 module->inc_size = 0;
2942 module->inc = calloc(1, size);
2943 if (!module->inc) {
2944 LOGMEM;
2945 goto error;
2946 }
2947 /* set stop block for possible realloc */
2948 module->inc[inc_size].submodule = (void*)0x1;
Pavol Vican1cc4e192016-10-24 16:38:31 +02002949 }
2950
2951 for (i = 0; i < imp_size; ++i) {
2952 s = (char *) imp[i].module;
2953 imp[i].module = NULL;
2954 if (yang_fill_import(module, &imp[i], &module->imp[module->imp_size], s)) {
2955 ++i;
2956 goto error;
2957 }
2958 }
Pavol Vicanec423c92016-10-24 21:33:43 +02002959 for (j = 0; j < inc_size; ++j) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01002960 s = (char *) inc[j].submodule;
2961 inc[j].submodule = NULL;
2962 if (yang_fill_include(module, s, &inc[j], unres)) {
2963 ++j;
Pavol Vicanec423c92016-10-24 21:33:43 +02002964 goto error;
2965 }
2966 }
2967 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002968 free(imp);
2969
2970 return EXIT_SUCCESS;
2971
2972error:
2973 yang_free_import(module->ctx, imp, i, imp_size);
Pavol Vicanec423c92016-10-24 21:33:43 +02002974 yang_free_include(module->ctx, inc, j, inc_size);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002975 free(imp);
Pavol Vicanec423c92016-10-24 21:33:43 +02002976 free(inc);
Pavol Vican1cc4e192016-10-24 16:38:31 +02002977 return EXIT_FAILURE;
2978}
Pavol Vican7313fc02016-11-14 01:10:31 +01002979
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01002980static int
Pavol Vicandf9a95c2016-12-02 23:34:51 +01002981yang_check_iffeatures(struct lys_module *module, void *ptr, void *parent, enum yytokentype type, struct unres_schema *unres)
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01002982{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01002983 struct lys_iffeature *iffeature;
2984 uint8_t *ptr_size, size, i;
2985 char *s;
2986 int parent_is_feature = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01002987
Pavol Vicandf9a95c2016-12-02 23:34:51 +01002988 switch (type) {
2989 case FEATURE_KEYWORD:
2990 iffeature = ((struct lys_feature *)parent)->iffeature;
2991 size = ((struct lys_feature *)parent)->iffeature_size;
2992 ptr_size = &((struct lys_feature *)parent)->iffeature_size;
2993 parent_is_feature = 1;
2994 break;
2995 case IDENTITY_KEYWORD:
2996 iffeature = ((struct lys_ident *)parent)->iffeature;
2997 size = ((struct lys_ident *)parent)->iffeature_size;
2998 ptr_size = &((struct lys_ident *)parent)->iffeature_size;
2999 break;
3000 case ENUM_KEYWORD:
3001 iffeature = ((struct lys_type_enum *)ptr)->iffeature;
3002 size = ((struct lys_type_enum *)ptr)->iffeature_size;
3003 ptr_size = &((struct lys_type_enum *)ptr)->iffeature_size;
3004 break;
3005 case BIT_KEYWORD:
3006 iffeature = ((struct lys_type_bit *)ptr)->iffeature;
3007 size = ((struct lys_type_bit *)ptr)->iffeature_size;
3008 ptr_size = &((struct lys_type_bit *)ptr)->iffeature_size;
3009 break;
3010 case REFINE_KEYWORD:
3011 iffeature = ((struct lys_refine *)ptr)->iffeature;
3012 size = ((struct lys_refine *)ptr)->iffeature_size;
3013 ptr_size = &((struct lys_refine *)ptr)->iffeature_size;
3014 break;
3015 default:
3016 iffeature = ((struct lys_node *)parent)->iffeature;
3017 size = ((struct lys_node *)parent)->iffeature_size;
3018 ptr_size = &((struct lys_node *)parent)->iffeature_size;
3019 break;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003020 }
3021
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003022 *ptr_size = 0;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003023 for (i = 0; i < size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003024 s = (char *)iffeature[i].features;
3025 iffeature[i].features = NULL;
3026 if (yang_fill_iffeature(module, &iffeature[i], parent, s, unres, parent_is_feature)) {
3027 *ptr_size = size;
3028 return EXIT_FAILURE;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003029 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003030 (*ptr_size)++;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003031 }
3032
3033 return EXIT_SUCCESS;
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003034}
3035
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003036static int
3037yang_check_identityref(struct lys_module *module, struct lys_type *type, struct unres_schema *unres)
3038{
3039 uint size, i;
3040 int rc;
3041 struct lys_ident **ref;
3042 const char *value;
3043 char *expr;
3044
3045 ref = type->info.ident.ref;
3046 size = type->info.ident.count;
3047 type->info.ident.count = 0;
3048 type->info.ident.ref = NULL;
3049 ((struct yang_type *)type->der)->flags |= LYS_NO_ERASE_IDENTITY;
3050
3051 for (i = 0; i < size; ++i) {
3052 expr = (char *)ref[i];
3053 /* store in the JSON format */
3054 value = transform_schema2json(module, expr);
3055 free(expr);
3056
3057 if (!value) {
3058 goto error;
3059 }
3060 rc = unres_schema_add_str(module, unres, type, UNRES_TYPE_IDENTREF, value);
3061 lydict_remove(module->ctx, value);
3062
3063 if (rc == -1) {
3064 goto error;
3065 }
3066 }
3067 free(ref);
3068
3069 return EXIT_SUCCESS;
3070error:
3071 for (i = i+1; i < size; ++i) {
3072 free(ref[i]);
3073 }
3074 free(ref);
3075 return EXIT_FAILURE;
3076}
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003077
Pavol Vican7313fc02016-11-14 01:10:31 +01003078int
3079yang_check_typedef(struct lys_module *module, struct lys_node *parent, struct unres_schema *unres)
3080{
3081 struct lys_tpdf *tpdf;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003082 uint8_t j, i, tpdf_size, *ptr_tpdf_size;
3083 struct yang_type *stype;
Pavol Vican7313fc02016-11-14 01:10:31 +01003084
3085 if (!parent) {
3086 tpdf = module->tpdf;
3087 ptr_tpdf_size = &module->tpdf_size;
Pavol Vican05810b62016-11-23 14:07:22 +01003088 } else {
3089 switch (parent->nodetype) {
3090 case LYS_GROUPING:
3091 tpdf = ((struct lys_node_grp *)parent)->tpdf;
3092 ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
3093 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003094 case LYS_CONTAINER:
3095 tpdf = ((struct lys_node_container *)parent)->tpdf;
3096 ptr_tpdf_size = &((struct lys_node_container *)parent)->tpdf_size;
3097 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003098 case LYS_LIST:
3099 tpdf = ((struct lys_node_list *)parent)->tpdf;
3100 ptr_tpdf_size = &((struct lys_node_list *)parent)->tpdf_size;
3101 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003102 case LYS_RPC:
3103 case LYS_ACTION:
3104 tpdf = ((struct lys_node_rpc_action *)parent)->tpdf;
3105 ptr_tpdf_size = &((struct lys_node_rpc_action *)parent)->tpdf_size;
3106 break;
Pavol Vican78729392016-11-28 17:18:22 +01003107 case LYS_INPUT:
3108 case LYS_OUTPUT:
3109 tpdf = ((struct lys_node_inout *)parent)->tpdf;
3110 ptr_tpdf_size = &((struct lys_node_inout *)parent)->tpdf_size;
3111 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003112 case LYS_NOTIF:
3113 tpdf = ((struct lys_node_notif *)parent)->tpdf;
3114 ptr_tpdf_size = &((struct lys_node_notif *)parent)->tpdf_size;
3115 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003116 default:
3117 LOGINT;
3118 return EXIT_FAILURE;
3119 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003120 }
3121
3122 tpdf_size = *ptr_tpdf_size;
3123 *ptr_tpdf_size = 0;
3124
3125 for (i = 0; i < tpdf_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003126 if (lyp_check_identifier(tpdf[i].name, LY_IDENT_TYPE, module, parent)) {
3127 goto error;
3128 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003129 tpdf[i].type.parent = &tpdf[i];
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003130
3131 stype = (struct yang_type *)tpdf[i].type.der;
3132 if (stype->base == LY_TYPE_ENUM) {
3133 for (j = 0; j < tpdf[i].type.info.enums.count; ++j) {
3134 if (yang_check_iffeatures(module, &tpdf[i].type.info.enums.enm[j], &tpdf[i], ENUM_KEYWORD, unres)) {
3135 goto error;
3136 }
3137 }
3138 } else if (stype->base == LY_TYPE_BITS) {
3139 for (j = 0; j < tpdf[i].type.info.bits.count; ++j) {
3140 if (yang_check_iffeatures(module, &tpdf[i].type.info.bits.bit[j], &tpdf[i], BIT_KEYWORD, unres)) {
3141 goto error;
3142 }
3143 }
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003144 } else if (stype->base == LY_TYPE_IDENT) {
3145 if (yang_check_identityref(module, &tpdf[i].type, unres)) {
3146 goto error;
3147 }
Pavol Vican5c8a9ad2016-11-22 11:50:54 +01003148 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003149
Pavol Vican7313fc02016-11-14 01:10:31 +01003150 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DER_TPDF, parent) == -1) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003151 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003152 }
3153
PavolVicane87cb932016-12-30 15:36:18 +01003154 (*ptr_tpdf_size)++;
Pavol Vican7313fc02016-11-14 01:10:31 +01003155 /* check default value*/
Pavol Vicanfda8c802016-12-03 02:00:42 +01003156 if (unres_schema_add_node(module, unres, &tpdf[i].type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf[i].dflt)) == -1) {
Pavol Vican7313fc02016-11-14 01:10:31 +01003157 ++i;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003158 goto error;
Pavol Vican7313fc02016-11-14 01:10:31 +01003159 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003160 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003161
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003162 return EXIT_SUCCESS;
3163
3164error:
3165 yang_tpdf_free(module->ctx, tpdf, i, tpdf_size);
3166 return EXIT_FAILURE;
Pavol Vican7313fc02016-11-14 01:10:31 +01003167}
3168
3169static int
Pavol Vican36e27272016-11-22 15:47:28 +01003170yang_check_identities(struct lys_module *module, struct unres_schema *unres)
3171{
3172 uint32_t i, size, base_size;
3173 uint8_t j;
3174
3175 size = module->ident_size;
3176 module->ident_size = 0;
3177 for (i = 0; i < size; ++i) {
3178 base_size = module->ident[i].base_size;
3179 module->ident[i].base_size = 0;
3180 for (j = 0; j < base_size; ++j) {
3181 if (yang_read_base(module, &module->ident[i], (char *)module->ident[i].base[j], unres)) {
3182 ++j;
3183 module->ident_size = size;
3184 goto error;
3185 }
3186 }
3187 module->ident_size++;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003188 if (yang_check_iffeatures(module, NULL, &module->ident[i], IDENTITY_KEYWORD, unres)) {
3189 goto error;
3190 }
Pavol Vican36e27272016-11-22 15:47:28 +01003191 }
3192
3193 return EXIT_SUCCESS;
3194
3195error:
3196 for (; j< module->ident[i].base_size; ++j) {
3197 free(module->ident[i].base[j]);
3198 }
3199 yang_free_ident_base(module->ident, i + 1, size);
3200 return EXIT_FAILURE;
3201}
3202
3203static int
PavolVicane87cb932016-12-30 15:36:18 +01003204yang_check_container(struct lys_module *module, struct lys_node_container *cont, struct lys_node **child,
3205 int config_opt, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01003206{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003207 if (yang_check_typedef(module, (struct lys_node *)cont, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01003208 goto error;
3209 }
3210
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003211 if (yang_check_iffeatures(module, NULL, cont, CONTAINER_KEYWORD, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003212 goto error;
3213 }
3214
PavolVicane87cb932016-12-30 15:36:18 +01003215 if (yang_check_nodes(module, (struct lys_node *)cont, *child, config_opt, unres)) {
3216 *child = NULL;
3217 goto error;
3218 }
3219 *child = NULL;
3220
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003221 /* check XPath dependencies */
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003222 if ((cont->when || cont->must_size) && (unres_schema_add_node(module, unres, cont, UNRES_XPATH, NULL) == -1)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003223 goto error;
3224 }
3225
3226 return EXIT_SUCCESS;
3227error:
3228 return EXIT_FAILURE;
3229}
3230
3231static int
Pavol Vicana69aff22016-11-24 18:23:50 +01003232yang_check_leaf(struct lys_module *module, struct lys_node_leaf *leaf, struct unres_schema *unres)
3233{
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003234 int i;
3235 struct yang_type *stype;
Pavol Vicana69aff22016-11-24 18:23:50 +01003236
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003237 stype = (struct yang_type *)leaf->type.der;
3238 if (stype->base == LY_TYPE_ENUM) {
3239 for (i = 0; i < leaf->type.info.enums.count; ++i) {
3240 if (yang_check_iffeatures(module, &leaf->type.info.enums.enm[i], leaf, ENUM_KEYWORD, unres)) {
3241 yang_type_free(module->ctx, &leaf->type);
3242 goto error;
3243 }
3244 }
3245 } else if (stype->base == LY_TYPE_BITS) {
3246 for (i = 0; i < leaf->type.info.bits.count; ++i) {
3247 if (yang_check_iffeatures(module, &leaf->type.info.bits.bit[i], leaf, BIT_KEYWORD, unres)) {
3248 yang_type_free(module->ctx, &leaf->type);
3249 goto error;
3250 }
3251 }
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003252 } else if (stype->base == LY_TYPE_IDENT) {
3253 if (yang_check_identityref(module, &leaf->type, unres)) {
PavolVicana08d3652016-12-29 21:07:47 +01003254 yang_type_free(module->ctx, &leaf->type);
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003255 goto error;
3256 }
Pavol Vicana69aff22016-11-24 18:23:50 +01003257 }
3258
PavolVicana08d3652016-12-29 21:07:47 +01003259 if (yang_check_iffeatures(module, NULL, leaf, LEAF_KEYWORD, unres)) {
3260 yang_type_free(module->ctx, &leaf->type);
3261 goto error;
3262 }
3263
Pavol Vicanfda8c802016-12-03 02:00:42 +01003264 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DER, (struct lys_node *)leaf) == -1) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003265 yang_type_free(module->ctx, &leaf->type);
3266 goto error;
3267 }
3268
Pavol Vicanfda8c802016-12-03 02:00:42 +01003269 if (unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)&leaf->dflt) == -1) {
Pavol Vicana69aff22016-11-24 18:23:50 +01003270 goto error;
3271 }
3272
Pavol Vicana69aff22016-11-24 18:23:50 +01003273 /* check XPath dependencies */
3274 if ((leaf->when || leaf->must_size) && (unres_schema_add_node(module, unres, leaf, UNRES_XPATH, NULL) == -1)) {
3275 goto error;
3276 }
3277
3278 return EXIT_SUCCESS;
3279error:
3280 return EXIT_FAILURE;
3281}
3282
3283static int
Pavol Vican36aff862016-11-26 17:07:05 +01003284yang_check_leaflist(struct lys_module *module, struct lys_node_leaflist *leaflist, struct unres_schema *unres)
3285{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003286 int i, j;
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003287 struct yang_type *stype;
Pavol Vican36aff862016-11-26 17:07:05 +01003288
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003289 stype = (struct yang_type *)leaflist->type.der;
3290 if (stype->base == LY_TYPE_ENUM) {
3291 for (i = 0; i < leaflist->type.info.enums.count; ++i) {
3292 if (yang_check_iffeatures(module, &leaflist->type.info.enums.enm[i], leaflist, ENUM_KEYWORD, unres)) {
3293 yang_type_free(module->ctx, &leaflist->type);
3294 goto error;
3295 }
3296 }
3297 } else if (stype->base == LY_TYPE_BITS) {
3298 for (i = 0; i < leaflist->type.info.bits.count; ++i) {
3299 if (yang_check_iffeatures(module, &leaflist->type.info.bits.bit[i], leaflist, BIT_KEYWORD, unres)) {
3300 yang_type_free(module->ctx, &leaflist->type);
3301 goto error;
3302 }
3303 }
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003304 } else if (stype->base == LY_TYPE_IDENT) {
3305 if (yang_check_identityref(module, &leaflist->type, unres)) {
PavolVicana08d3652016-12-29 21:07:47 +01003306 yang_type_free(module->ctx, &leaflist->type);
Pavol Vicanb60a1d12016-12-03 01:56:55 +01003307 goto error;
3308 }
Pavol Vican36aff862016-11-26 17:07:05 +01003309 }
3310
PavolVicana08d3652016-12-29 21:07:47 +01003311 if (yang_check_iffeatures(module, NULL, leaflist, LEAF_LIST_KEYWORD, unres)) {
3312 yang_type_free(module->ctx, &leaflist->type);
3313 goto error;
3314 }
3315
Pavol Vicanfda8c802016-12-03 02:00:42 +01003316 if (unres_schema_add_node(module, unres, &leaflist->type, UNRES_TYPE_DER, (struct lys_node *)leaflist) == -1) {
Pavol Vican36aff862016-11-26 17:07:05 +01003317 yang_type_free(module->ctx, &leaflist->type);
3318 goto error;
3319 }
3320
Pavol Vican36aff862016-11-26 17:07:05 +01003321 for (i = 0; i < leaflist->dflt_size; ++i) {
Pavol Vicanfda8c802016-12-03 02:00:42 +01003322 /* check for duplicity in case of configuration data,
3323 * in case of status data duplicities are allowed */
3324 if (leaflist->flags & LYS_CONFIG_W) {
3325 for (j = i +1; j < leaflist->dflt_size; ++j) {
3326 if (ly_strequal(leaflist->dflt[i], leaflist->dflt[j], 1)) {
3327 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, leaflist->dflt[i], "default");
3328 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", leaflist->dflt[i]);
3329 goto error;
3330 }
3331 }
3332 }
3333 /* check default value (if not defined, there still could be some restrictions
3334 * that need to be checked against a default value from a derived type) */
Pavol Vican36aff862016-11-26 17:07:05 +01003335 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
Pavol Vican36aff862016-11-26 17:07:05 +01003340 /* check XPath dependencies */
3341 if ((leaflist->when || leaflist->must_size) && (unres_schema_add_node(module, unres, leaflist, UNRES_XPATH, NULL) == -1)) {
3342 goto error;
3343 }
3344
3345 return EXIT_SUCCESS;
3346error:
3347 return EXIT_FAILURE;
3348}
3349
3350static int
PavolVicane87cb932016-12-30 15:36:18 +01003351yang_check_list(struct lys_module *module, struct lys_node_list *list, struct lys_node **child,
3352 int config_opt, struct unres_schema *unres)
Pavol Vicand8136a42016-11-27 13:28:04 +01003353{
Pavol Vicanfda8c802016-12-03 02:00:42 +01003354 struct lys_node *node;
3355
Pavol Vicand8136a42016-11-27 13:28:04 +01003356 if (yang_check_typedef(module, (struct lys_node *)list, unres)) {
3357 goto error;
3358 }
3359
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003360 if (yang_check_iffeatures(module, NULL, list, LIST_KEYWORD, unres)) {
3361 goto error;
Pavol Vicand8136a42016-11-27 13:28:04 +01003362 }
3363
Pavol Vicanfda8c802016-12-03 02:00:42 +01003364 if (list->flags & LYS_CONFIG_R) {
3365 /* RFC 6020, 7.7.5 - ignore ordering when the list represents state data
3366 * ignore oredering MASK - 0x7F
3367 */
3368 list->flags &= 0x7F;
3369 }
3370 /* check - if list is configuration, key statement is mandatory
3371 * (but only if we are not in a grouping or augment, then the check is deferred) */
3372 for (node = (struct lys_node *)list; node && !(node->nodetype & (LYS_GROUPING | LYS_AUGMENT)); node = node->parent);
3373 if (!node && (list->flags & LYS_CONFIG_W) && !list->keys) {
3374 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, list, "key", "list");
3375 goto error;
3376 }
3377
PavolVicane87cb932016-12-30 15:36:18 +01003378 if (yang_check_nodes(module, (struct lys_node *)list, *child, config_opt, unres)) {
3379 *child = NULL;
3380 goto error;
3381 }
3382 *child = NULL;
3383
Pavol Vicand8136a42016-11-27 13:28:04 +01003384 if (list->keys && yang_read_key(module, list, unres)) {
3385 goto error;
3386 }
3387
3388 if (yang_read_unique(module, list, unres)) {
3389 goto error;
3390 }
3391
3392 /* check XPath dependencies */
3393 if ((list->when || list->must_size) && (unres_schema_add_node(module, unres, list, UNRES_XPATH, NULL) == -1)) {
3394 goto error;
3395 }
3396
3397 return EXIT_SUCCESS;
3398error:
3399 return EXIT_FAILURE;
3400}
3401
3402static int
PavolVicane87cb932016-12-30 15:36:18 +01003403yang_check_choice(struct lys_module *module, struct lys_node_choice *choice, struct lys_node **child,
3404 int config_opt, struct unres_schema *unres)
Pavol Vican36ace102016-11-28 11:46:59 +01003405{
3406 char *value;
Pavol Vican36ace102016-11-28 11:46:59 +01003407
PavolVicana08d3652016-12-29 21:07:47 +01003408 if (yang_check_iffeatures(module, NULL, choice, CHOICE_KEYWORD, unres)) {
3409 free(choice->dflt);
3410 choice->dflt = NULL;
3411 goto error;
3412 }
3413
PavolVicane87cb932016-12-30 15:36:18 +01003414 if (yang_check_nodes(module, (struct lys_node *)choice, *child, config_opt, unres)) {
3415 *child = NULL;
3416 free(choice->dflt);
3417 choice->dflt = NULL;
3418 goto error;
3419 }
3420 *child = NULL;
3421
Pavol Vican36ace102016-11-28 11:46:59 +01003422 if (choice->dflt) {
3423 value = (char *)choice->dflt;
3424 choice->dflt = NULL;
3425 if (unres_schema_add_str(module, unres, choice, UNRES_CHOICE_DFLT, value) == -1) {
3426 free(value);
3427 goto error;
3428 }
3429 free(value);
3430 }
3431
Pavol Vican36ace102016-11-28 11:46:59 +01003432 /* check XPath dependencies */
3433 if ((choice->when) && (unres_schema_add_node(module, unres, choice, UNRES_XPATH, NULL) == -1)) {
3434 goto error;
3435 }
3436
3437 return EXIT_SUCCESS;
3438error:
3439 return EXIT_FAILURE;
3440}
3441
3442static int
PavolVicane87cb932016-12-30 15:36:18 +01003443yang_check_rpc_action(struct lys_module *module, struct lys_node_rpc_action *rpc, struct lys_node **child,
3444 int config_opt, struct unres_schema *unres)
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003445{
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003446 struct lys_node *node;
3447
3448 if (rpc->nodetype == LYS_ACTION) {
3449 for (node = rpc->parent; node; node = lys_parent(node)) {
3450 if ((node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))
Pavol Vican73ff8032016-12-04 15:03:51 +01003451 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys)) {
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003452 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
3453 goto error;
3454 }
3455 }
3456 }
3457 if (yang_check_typedef(module, (struct lys_node *)rpc, unres)) {
3458 goto error;
3459 }
3460
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003461 if (yang_check_iffeatures(module, NULL, rpc, RPC_KEYWORD, unres)) {
3462 goto error;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003463 }
3464
PavolVicane87cb932016-12-30 15:36:18 +01003465 if (yang_check_nodes(module, (struct lys_node *)rpc, *child, config_opt, unres)) {
3466 *child = NULL;
3467 goto error;
3468 }
3469 *child = NULL;
3470
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003471 return EXIT_SUCCESS;
3472error:
3473 return EXIT_FAILURE;
3474}
3475
3476static int
PavolVicane87cb932016-12-30 15:36:18 +01003477yang_check_notif(struct lys_module *module, struct lys_node_notif *notif, struct lys_node **child,
3478 int config_opt, struct unres_schema *unres)
Pavol Vican29bf8802016-11-28 20:44:57 +01003479{
Pavol Vican29bf8802016-11-28 20:44:57 +01003480 if (yang_check_typedef(module, (struct lys_node *)notif, unres)) {
3481 goto error;
3482 }
3483
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003484 if (yang_check_iffeatures(module, NULL, notif, NOTIFICATION_KEYWORD, unres)) {
3485 goto error;
Pavol Vican29bf8802016-11-28 20:44:57 +01003486 }
3487
PavolVicane87cb932016-12-30 15:36:18 +01003488 if (yang_check_nodes(module, (struct lys_node *)notif, *child, config_opt, unres)) {
3489 *child = NULL;
3490 goto error;
3491 }
3492 *child = NULL;
3493
Pavol Vican29bf8802016-11-28 20:44:57 +01003494 /* check XPath dependencies */
3495 if ((notif->must_size) && (unres_schema_add_node(module, unres, notif, UNRES_XPATH, NULL) == -1)) {
3496 goto error;
3497 }
3498
3499 return EXIT_SUCCESS;
3500error:
3501 return EXIT_FAILURE;
3502}
3503
3504static int
Pavol Vican3ad50f82016-12-04 15:00:36 +01003505yang_check_augment(struct lys_module *module, struct lys_node_augment *augment, int config_opt, struct unres_schema *unres)
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003506{
Pavol Vican3ad50f82016-12-04 15:00:36 +01003507 struct lys_node *child;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003508
Pavol Vican3ad50f82016-12-04 15:00:36 +01003509 child = augment->child;
3510 augment->child = NULL;
3511
PavolVicana08d3652016-12-29 21:07:47 +01003512 if (yang_check_iffeatures(module, NULL, augment, AUGMENT_KEYWORD, unres)) {
3513 yang_free_nodes(module->ctx, child);
Pavol Vican3ad50f82016-12-04 15:00:36 +01003514 goto error;
3515 }
3516
PavolVicana08d3652016-12-29 21:07:47 +01003517 if (yang_check_nodes(module, (struct lys_node *)augment, child, config_opt, unres)) {
Pavol Vican3ad50f82016-12-04 15:00:36 +01003518 goto error;
3519 }
3520
3521 /* check XPath dependencies */
3522 if (augment->when && (unres_schema_add_node(module, unres, augment, UNRES_XPATH, NULL) == -1)) {
3523 goto error;
3524 }
3525
3526 return EXIT_SUCCESS;
3527error:
3528 return EXIT_FAILURE;
3529}
3530
3531static int
3532yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, int config_opt, struct unres_schema *unres)
3533{
3534 uint i, size;
3535
3536 size = uses->augment_size;
3537 uses->augment_size = 0;
3538
3539 if (yang_check_iffeatures(module, NULL, uses, USES_KEYWORD, unres)) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003540 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003541 }
3542
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003543 for (i = 0; i < uses->refine_size; ++i) {
3544 if (yang_check_iffeatures(module, &uses->refine[i], uses, REFINE_KEYWORD, unres)) {
3545 goto error;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003546 }
3547 }
3548
Pavol Vican3ad50f82016-12-04 15:00:36 +01003549 for (i = 0; i < size; ++i) {
3550 uses->augment_size++;
3551 if (yang_check_augment(module, &uses->augment[i], config_opt, unres)) {
3552 goto error;
3553 }
3554 }
3555
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003556 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:
Pavol Vican3ad50f82016-12-04 15:00:36 +01003567 for (i = uses->augment_size; i < size; ++i) {
3568 yang_free_augment(module->ctx, &uses->augment[i]);
3569 }
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003570 return EXIT_FAILURE;
3571}
3572
3573static int
Pavol Vican3ad50f82016-12-04 15:00:36 +01003574yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
3575 int config_opt, struct unres_schema *unres)
Pavol Vican05810b62016-11-23 14:07:22 +01003576{
Pavol Vican3ad50f82016-12-04 15:00:36 +01003577 struct lys_node *node = nodes, *sibling, *child;
Pavol Vican05810b62016-11-23 14:07:22 +01003578
3579 while (node) {
3580 sibling = node->next;
3581 child = node->child;
3582 node->next = NULL;
3583 node->child = NULL;
3584 node->prev = node;
3585
Pavol Vican24ba7f62016-11-28 12:15:20 +01003586 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
3587 lys_node_unlink(node);
3588 node->next = sibling;
Pavol Vican05810b62016-11-23 14:07:22 +01003589 sibling = node;
Pavol Vican05810b62016-11-23 14:07:22 +01003590 goto error;
3591 }
Pavol Vicanec598812016-11-30 14:13:38 +01003592 config_opt = store_config_flag(node, config_opt);
Pavol Vicanfda8c802016-12-03 02:00:42 +01003593
Pavol Vican05810b62016-11-23 14:07:22 +01003594 switch (node->nodetype) {
3595 case LYS_GROUPING:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003596 if (yang_check_typedef(module, node, unres)) {
3597 goto error;
3598 }
3599 if (yang_check_iffeatures(module, NULL, node, GROUPING_KEYWORD, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01003600 goto error;
3601 }
PavolVicane87cb932016-12-30 15:36:18 +01003602 if (yang_check_nodes(module, node, child, config_opt, unres)) {
3603 child = NULL;
3604 goto error;
3605 }
Pavol Vican05810b62016-11-23 14:07:22 +01003606 break;
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003607 case LYS_CONTAINER:
PavolVicane87cb932016-12-30 15:36:18 +01003608 if (yang_check_container(module, (struct lys_node_container *)node, &child, config_opt, unres)) {
Pavol Vicanc54a8f72016-11-23 16:45:55 +01003609 goto error;
3610 }
3611 break;
Pavol Vicana69aff22016-11-24 18:23:50 +01003612 case LYS_LEAF:
3613 if (yang_check_leaf(module, (struct lys_node_leaf *)node, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003614 child = NULL;
Pavol Vicana69aff22016-11-24 18:23:50 +01003615 goto error;
3616 }
3617 break;
Pavol Vican36aff862016-11-26 17:07:05 +01003618 case LYS_LEAFLIST:
3619 if (yang_check_leaflist(module, (struct lys_node_leaflist *)node, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003620 child = NULL;
Pavol Vican36aff862016-11-26 17:07:05 +01003621 goto error;
3622 }
3623 break;
Pavol Vicand8136a42016-11-27 13:28:04 +01003624 case LYS_LIST:
PavolVicane87cb932016-12-30 15:36:18 +01003625 if (yang_check_list(module, (struct lys_node_list *)node, &child, config_opt, unres)) {
Pavol Vicand8136a42016-11-27 13:28:04 +01003626 goto error;
3627 }
3628 break;
Pavol Vican36ace102016-11-28 11:46:59 +01003629 case LYS_CHOICE:
PavolVicane87cb932016-12-30 15:36:18 +01003630 if (yang_check_choice(module, (struct lys_node_choice *)node, &child, config_opt, unres)) {
Pavol Vican36ace102016-11-28 11:46:59 +01003631 goto error;
3632 }
3633 break;
Pavol Vicana420bac2016-11-28 14:51:54 +01003634 case LYS_CASE:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003635 if (yang_check_iffeatures(module, NULL, node, CASE_KEYWORD, unres)) {
Pavol Vicana420bac2016-11-28 14:51:54 +01003636 goto error;
3637 }
PavolVicane87cb932016-12-30 15:36:18 +01003638 if (yang_check_nodes(module, node, child, config_opt, unres)) {
3639 child = NULL;
3640 goto error;
3641 }
Pavol Vicana420bac2016-11-28 14:51:54 +01003642 break;
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003643 case LYS_ANYDATA:
3644 case LYS_ANYXML:
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003645 if (yang_check_iffeatures(module, NULL, node, CHOICE_KEYWORD, unres)) {
3646 goto error;
3647 }
PavolVicane87cb932016-12-30 15:36:18 +01003648 if (yang_check_nodes(module, node, child, config_opt, unres)) {
3649 child = NULL;
3650 goto error;
3651 }
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003652 /* check XPath dependencies */
3653 if ((((struct lys_node_anydata *)node)->when) && (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
Pavol Vicanbfa1a582016-11-28 15:35:59 +01003654 goto error;
3655 }
3656 break;
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003657 case LYS_RPC:
3658 case LYS_ACTION:
PavolVicane87cb932016-12-30 15:36:18 +01003659 if (yang_check_rpc_action(module, (struct lys_node_rpc_action *)node, &child, config_opt, unres)){
Pavol Vicanebc9ef82016-11-28 16:46:49 +01003660 goto error;
3661 }
3662 break;
Pavol Vican78729392016-11-28 17:18:22 +01003663 case LYS_INPUT:
3664 case LYS_OUTPUT:
PavolVicane87cb932016-12-30 15:36:18 +01003665 if (yang_check_typedef(module, node, unres)) {
3666 goto error;
3667 }
3668 if (yang_check_nodes(module, node, child, config_opt, unres)) {
3669 child = NULL;
3670 goto error;
3671 }
Pavol Vican78729392016-11-28 17:18:22 +01003672 /* check XPath dependencies */
3673 if (((struct lys_node_inout *)node)->must_size &&
3674 (unres_schema_add_node(module, unres, node, UNRES_XPATH, NULL) == -1)) {
3675 goto error;
3676 }
Pavol Vican78729392016-11-28 17:18:22 +01003677 break;
Pavol Vican29bf8802016-11-28 20:44:57 +01003678 case LYS_NOTIF:
PavolVicane87cb932016-12-30 15:36:18 +01003679 if (yang_check_notif(module, (struct lys_node_notif *)node, &child, config_opt, unres)) {
Pavol Vican29bf8802016-11-28 20:44:57 +01003680 goto error;
3681 }
3682 break;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003683 case LYS_USES:
Pavol Vican3ad50f82016-12-04 15:00:36 +01003684 if (yang_check_uses(module, (struct lys_node_uses *)node, config_opt, unres)) {
PavolVicane87cb932016-12-30 15:36:18 +01003685 child = NULL;
Pavol Vican3b5e82a2016-11-29 21:41:56 +01003686 goto error;
3687 }
3688 break;
Pavol Vican05810b62016-11-23 14:07:22 +01003689 default:
3690 LOGINT;
Pavol Vican05810b62016-11-23 14:07:22 +01003691 goto error;
3692 }
Pavol Vican05810b62016-11-23 14:07:22 +01003693 node = sibling;
3694 }
3695
3696 return EXIT_SUCCESS;
3697error:
3698 yang_free_nodes(module->ctx, sibling);
3699 yang_free_nodes(module->ctx, child);
3700 return EXIT_FAILURE;
3701}
3702
3703static int
PavolVican75af21d2016-12-29 20:04:07 +01003704yang_check_deviate(struct lys_module *module, struct unres_schema *unres, struct lys_deviate *deviate,
3705 struct lys_node *dev_target, struct ly_set *dflt_check)
3706{
3707 struct lys_node_leaflist *llist;
3708 struct lys_type *type;
3709 struct lys_tpdf *tmp_parent;
3710 int i, j;
3711
3712 if (deviate->must_size && yang_check_deviate_must(module, unres, deviate, dev_target)) {
3713 goto error;
3714 }
3715 if (deviate->unique && yang_check_deviate_unique(module, deviate, dev_target)) {
3716 goto error;
3717 }
3718 if (deviate->dflt_size) {
3719 if (yang_read_deviate_default(module, deviate, dev_target, dflt_check)) {
3720 goto error;
3721 }
3722 if (dev_target->nodetype == LYS_LEAFLIST && deviate->mod == LY_DEVIATE_DEL) {
3723 /* consolidate the final list in the target after removing items from it */
3724 llist = (struct lys_node_leaflist *)dev_target;
3725 for (i = j = 0; j < llist->dflt_size; j++) {
3726 llist->dflt[i] = llist->dflt[j];
3727 if (llist->dflt[i]) {
3728 i++;
3729 }
3730 }
3731 llist->dflt_size = i + 1;
3732 }
3733 }
3734
3735 if (deviate->max_set && yang_read_deviate_minmax(deviate, dev_target, deviate->max, 1)) {
3736 goto error;
3737 }
3738
3739 if (deviate->min_set && yang_read_deviate_minmax(deviate, dev_target, deviate->min, 0)) {
3740 goto error;
3741 }
3742
3743 if (deviate->units && yang_read_deviate_units(module->ctx, deviate, dev_target)) {
3744 goto error;
3745 }
3746
3747 if ((deviate->flags & LYS_CONFIG_MASK)) {
3748 /* add and replace are the same in this case */
3749 /* remove current config value of the target ... */
3750 dev_target->flags &= ~LYS_CONFIG_MASK;
3751
3752 /* ... and replace it with the value specified in deviation */
3753 dev_target->flags |= deviate->flags & LYS_CONFIG_MASK;
3754 }
3755
3756 if ((deviate->flags & LYS_MAND_MASK) && yang_check_deviate_mandatory(deviate, dev_target)) {
3757 goto error;
3758 }
3759
3760 if (deviate->type) {
3761 /* check target node type */
3762 if (dev_target->nodetype == LYS_LEAF) {
3763 type = &((struct lys_node_leaf *)dev_target)->type;
3764 } else if (dev_target->nodetype == LYS_LEAFLIST) {
3765 type = &((struct lys_node_leaflist *)dev_target)->type;
3766 } else {
3767 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
3768 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
3769 goto error;
3770 }
3771 /* remove type and initialize it */
3772 tmp_parent = type->parent;
3773 lys_type_free(module->ctx, type);
3774 memcpy(type, deviate->type, sizeof *deviate->type);
3775 free(deviate->type);
3776 deviate->type = type;
3777 deviate->type->parent = tmp_parent;
3778 if (unres_schema_add_node(module, unres, deviate->type, UNRES_TYPE_DER, dev_target) == -1) {
3779 goto error;
3780 }
3781 }
3782
3783 return EXIT_SUCCESS;
3784error:
3785 if (deviate->type) {
3786 yang_type_free(module->ctx, deviate->type);
3787 deviate->type = NULL;
3788 }
3789 return EXIT_FAILURE;
3790}
3791
3792static int
3793yang_check_deviation(struct lys_module *module, struct unres_schema *unres, struct lys_deviation *dev)
3794{
3795 int rc;
3796 uint i;
3797 struct lys_node *dev_target = NULL, *parent;
3798 struct ly_set *dflt_check = ly_set_new();
3799 unsigned int u;
3800 const char *value, *target_name;
3801 struct lys_node_leaflist *llist;
3802 struct lys_node_leaf *leaf;
3803 struct unres_schema tmp_unres;
3804 struct lys_module *mod;
3805
3806 /* resolve target node */
3807 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, 1, (const struct lys_node **)&dev_target);
3808 if (rc || !dev_target) {
3809 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
3810 goto error;
3811 }
3812 if (dev_target->module == lys_main_module(module)) {
3813 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
3814 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
3815 goto error;
3816 }
3817
3818 if (!dflt_check) {
3819 LOGMEM;
3820 goto error;
3821 }
3822
3823 if (dev->deviate[0].mod == LY_DEVIATE_NO) {
3824 /* you cannot remove a key leaf */
3825 if ((dev_target->nodetype == LYS_LEAF) && dev_target->parent && (dev_target->parent->nodetype == LYS_LIST)) {
3826 for (i = 0; i < ((struct lys_node_list *)dev_target->parent)->keys_size; ++i) {
3827 if (((struct lys_node_list *)dev_target->parent)->keys[i] == (struct lys_node_leaf *)dev_target) {
3828 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
3829 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
3830 return EXIT_FAILURE;
3831 }
3832 }
3833 }
3834 /* unlink and store the original node */
3835 lys_node_unlink(dev_target);
3836 dev->orig_node = dev_target;
3837 } else {
3838 /* store a shallow copy of the original node */
3839 memset(&tmp_unres, 0, sizeof tmp_unres);
3840 dev->orig_node = lys_node_dup(dev_target->module, NULL, dev_target, 0, &tmp_unres, 1);
3841 /* just to be safe */
3842 if (tmp_unres.count) {
3843 LOGINT;
3844 goto error;
3845 }
3846 }
3847
3848 for (i = 0; i < dev->deviate_size; ++i) {
3849 if (yang_check_deviate(module, unres, &dev->deviate[i], dev_target, dflt_check)) {
3850 yang_free_deviate(module->ctx, dev, i + 1);
3851 dev->deviate_size = i+1;
3852 goto error; // missing free unresolve type in deviate
3853 }
3854 }
3855 /* now check whether default value, if any, matches the type */
3856 for (u = 0; u < dflt_check->number; ++u) {
3857 value = NULL;
3858 rc = EXIT_SUCCESS;
3859 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
3860 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
3861 target_name = leaf->name;
3862 value = leaf->dflt;
3863 rc = unres_schema_add_node(module, unres, &leaf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&leaf->dflt));
3864 } else { /* LYS_LEAFLIST */
3865 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
3866 target_name = llist->name;
3867 for (i = 0; i < llist->dflt_size; i++) {
3868 rc = unres_schema_add_node(module, unres, &llist->type, UNRES_TYPE_DFLT,
3869 (struct lys_node *)(&llist->dflt[i]));
3870 if (rc == -1) {
3871 value = llist->dflt[i];
3872 break;
3873 }
3874 }
3875 }
3876 if (rc == -1) {
3877 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
3878 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
3879 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
3880 target_name);
3881 goto error;
3882 }
3883 }
3884 ly_set_free(dflt_check);
3885
3886 /* mark all the affected modules as deviated and implemented*/
3887 for(parent = dev_target; parent; parent = lys_parent(parent)) {
3888 mod = lys_node_module(parent);
3889 if (module != mod) {
3890 mod->deviated = 1;
3891 lys_set_implemented(mod);
3892 }
3893}
3894
3895 return EXIT_SUCCESS;
3896error:
3897 ly_set_free(dflt_check);
3898 return EXIT_FAILURE;
3899}
3900
3901static int
Pavol Vican7313fc02016-11-14 01:10:31 +01003902yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
3903{
PavolVican75af21d2016-12-29 20:04:07 +01003904 uint i, erase_identities = 1, erase_nodes = 1, aug_size, dev_size = 0;
Pavol Vican3ad50f82016-12-04 15:00:36 +01003905
3906 aug_size = module->augment_size;
3907 module->augment_size = 0;
PavolVican75af21d2016-12-29 20:04:07 +01003908 dev_size = module->deviation_size;
3909 module->deviation_size = 0;
Pavol Vican7a7916f2016-11-21 23:38:30 +01003910
Pavol Vican7313fc02016-11-14 01:10:31 +01003911 if (yang_check_typedef(module, NULL, unres)) {
3912 goto error;
3913 }
3914
Pavol Vican7a7916f2016-11-21 23:38:30 +01003915 /* check features */
3916 for (i = 0; i < module->features_size; ++i) {
Pavol Vicandf9a95c2016-12-02 23:34:51 +01003917 if (yang_check_iffeatures(module, NULL, &module->features[i], FEATURE_KEYWORD, unres)) {
3918 goto error;
3919 }
3920 /* check for circular dependencies */
3921 if (module->features[i].iffeature_size && (unres_schema_add_node(module, unres, &module->features[i], UNRES_FEATURE, NULL) == -1)) {
3922 goto error;
Pavol Vican7a7916f2016-11-21 23:38:30 +01003923 }
3924 }
Pavol Vican36e27272016-11-22 15:47:28 +01003925 erase_identities = 0;
3926 if (yang_check_identities(module, unres)) {
3927 goto error;
3928 }
Pavol Vican05810b62016-11-23 14:07:22 +01003929 erase_nodes = 0;
Pavol Vican3ad50f82016-12-04 15:00:36 +01003930 if (yang_check_nodes(module, NULL, node, CONFIG_INHERIT_ENABLE, unres)) {
Pavol Vican05810b62016-11-23 14:07:22 +01003931 goto error;
3932 }
Pavol Vican7a7916f2016-11-21 23:38:30 +01003933
PavolVican75af21d2016-12-29 20:04:07 +01003934 /* check deviation */
3935 for (i = 0; i < dev_size; ++i) {
3936 module->deviation_size++;
3937 if (yang_check_deviation(module, unres, &module->deviation[i])) {
3938 goto error;
3939 }
3940 }
3941
Pavol Vican3ad50f82016-12-04 15:00:36 +01003942 /* check augments */
3943 for (i = 0; i < aug_size; ++i) {
3944 module->augment_size++;
3945 if (yang_check_augment(module, &module->augment[i], CONFIG_INHERIT_ENABLE, unres)) {
3946 goto error;
3947 }
3948 if (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1) {
3949 goto error;
3950 }
3951 }
3952
Pavol Vican7313fc02016-11-14 01:10:31 +01003953 return EXIT_SUCCESS;
3954error:
Pavol Vican36e27272016-11-22 15:47:28 +01003955 if (erase_identities) {
3956 yang_free_ident_base(module->ident, 0, module->ident_size);
3957 }
Pavol Vican05810b62016-11-23 14:07:22 +01003958 if (erase_nodes) {
3959 yang_free_nodes(module->ctx, node);
3960 }
Pavol Vican3ad50f82016-12-04 15:00:36 +01003961 for (i = module->augment_size; i < aug_size; ++i) {
3962 yang_free_augment(module->ctx, &module->augment[i]);
3963 }
PavolVican75af21d2016-12-29 20:04:07 +01003964 for (i = module->deviation_size; i < dev_size; ++i) {
3965 yang_free_deviate(module->ctx, &module->deviation[i], 0);
3966 free(module->deviation[i].deviate);
3967 }
Pavol Vican7313fc02016-11-14 01:10:31 +01003968 return EXIT_FAILURE;
3969}