blob: ea2c367addf2eeba290a5d0765564a53726997b8 [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 Vican021488a2016-01-25 23:56:12 +010016#include "parser_yang.h"
Pavol Vican8e7110b2016-03-22 17:00:26 +010017#include "parser_yang_lex.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010018#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010019#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010020
Michal Vaskofe7e5a72016-05-02 14:49:23 +020021static int
Pavol Vican0adf01d2016-03-22 12:29:33 +010022yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +010023{
Pavol Vicanbf805472016-01-26 14:24:56 +010024 if (*target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +010025 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010026 free(value);
27 return 1;
28 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010029 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010030 return 0;
31 }
32}
33
Pavol Vican810892e2016-07-12 16:55:34 +020034static int
35yang_check_typedef_identif(struct lys_node *root, struct lys_node *node, char *id)
36{
37 struct lys_node *child, *next;
38 int size;
39 struct lys_tpdf *tpdf;
40
Pavol Vican810892e2016-07-12 16:55:34 +020041 if (root) {
42 node = root;
43 }
44
45 do {
46 LY_TREE_DFS_BEGIN(node, next, child) {
47 if (child->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_GROUPING | LYS_RPC | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
48 switch (child->nodetype) {
49 case LYS_CONTAINER:
50 tpdf = ((struct lys_node_container *)child)->tpdf;
51 size = ((struct lys_node_container *)child)->tpdf_size;
52 break;
53 case LYS_LIST:
54 tpdf = ((struct lys_node_list *)child)->tpdf;
55 size = ((struct lys_node_list *)child)->tpdf_size;
56 break;
57 case LYS_GROUPING:
58 tpdf = ((struct lys_node_grp *)child)->tpdf;
59 size = ((struct lys_node_grp *)child)->tpdf_size;
60 break;
61 case LYS_RPC:
Radek Krejci71d51832016-07-14 15:59:06 +020062 tpdf = ((struct lys_node_rpc_action *)child)->tpdf;
63 size = ((struct lys_node_rpc_action *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020064 break;
65 case LYS_INPUT:
66 case LYS_OUTPUT:
Radek Krejci71d51832016-07-14 15:59:06 +020067 tpdf = ((struct lys_node_inout *)child)->tpdf;
68 size = ((struct lys_node_inout *)child)->tpdf_size;
Pavol Vican810892e2016-07-12 16:55:34 +020069 break;
70 case LYS_NOTIF:
71 tpdf = ((struct lys_node_notif *)child)->tpdf;
72 size = ((struct lys_node_notif *)child)->tpdf_size;
73 break;
74 default:
75 size = 0;
76 break;
77 }
Radek Krejcifc824a42016-07-14 15:48:38 +020078 if (size && dup_typedef_check(id, tpdf, size)) {
Pavol Vican810892e2016-07-12 16:55:34 +020079 LOGVAL(LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
80 return EXIT_FAILURE;
81 }
Michal Vasko3767fb22016-07-21 12:10:57 +020082 }
Pavol Vican810892e2016-07-12 16:55:34 +020083 LY_TREE_DFS_END(node, next, child)}
84 } while (root && (node = node->next));
85 return EXIT_SUCCESS;
86}
87
Michal Vaskofe7e5a72016-05-02 14:49:23 +020088int
Pavol Vican5f0316a2016-04-05 21:21:11 +020089yang_read_common(struct lys_module *module, char *value, enum yytokentype type)
Pavol Vican2a064652016-02-02 22:54:34 +010090{
Pavol Vican6eb14e82016-02-03 12:27:13 +010091 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010092
93 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010094 case MODULE_KEYWORD:
95 module->name = lydict_insert_zc(module->ctx, value);
96 break;
97 case NAMESPACE_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +010098 ret = yang_check_string(module, &module->ns, "namespace", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +010099 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +0100100 case ORGANIZATION_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100101 ret = yang_check_string(module, &module->org, "organization", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100102 break;
103 case CONTACT_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100104 ret = yang_check_string(module, &module->contact, "contact", "module", value);
Pavol Vican1ca072c2016-02-03 13:03:56 +0100105 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200106 default:
107 free(value);
108 LOGINT;
109 ret = EXIT_FAILURE;
110 break;
Pavol Vican2a064652016-02-02 22:54:34 +0100111 }
112
Pavol Vican021488a2016-01-25 23:56:12 +0100113 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +0100114}
115
Michal Vaskofe7e5a72016-05-02 14:49:23 +0200116int
Pavol Vicand0b64c12016-07-15 09:56:19 +0200117yang_check_version(struct lys_module *module, struct lys_submodule *submodule, char *value, int repeat)
118{
119 int ret = EXIT_SUCCESS;
120
121 if (repeat) {
Michal Vasko3767fb22016-07-21 12:10:57 +0200122 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module");
123 ret = EXIT_FAILURE;
Pavol Vicand0b64c12016-07-15 09:56:19 +0200124 } else {
125 if (!strcmp(value, "1")) {
126 if (submodule) {
127 if (module->version > 1) {
128 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
129 ret = EXIT_FAILURE;
130 }
131 } else {
132 module->version = 1;
133 }
134 } else if (!strcmp(value, "1.1")) {
135 if (submodule) {
136 if (module->version != 2) {
137 LOGVAL(LYE_INVER, LY_VLOG_NONE, NULL);
138 ret = EXIT_FAILURE;
139 }
140 } else {
141 module->version = 2;
142 }
143 } else {
144 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "yang-version");
145 ret = EXIT_FAILURE;
Michal Vasko3767fb22016-07-21 12:10:57 +0200146 }
Pavol Vicand0b64c12016-07-15 09:56:19 +0200147 }
148 free(value);
149 return ret;
150}
151
152int
Pavol Vicane024ab72016-07-27 14:27:43 +0200153yang_read_prefix(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican2a064652016-02-02 22:54:34 +0100154{
Pavol Vican6eb14e82016-02-03 12:27:13 +0100155 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +0100156
Pavol Vican0adf01d2016-03-22 12:29:33 +0100157 if (lyp_check_identifier(value, LY_IDENT_PREFIX, module, NULL)) {
Pavol Vican6eb14e82016-02-03 12:27:13 +0100158 free(value);
159 return EXIT_FAILURE;
160 }
Pavol Vicane024ab72016-07-27 14:27:43 +0200161
162 if (imp) {
163 ret = yang_check_string(module, &imp->prefix, "prefix", "import", value);
164 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100165 ret = yang_check_string(module, &module->prefix, "prefix", "module", value);
Pavol Vican2a064652016-02-02 22:54:34 +0100166 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100167
Pavol Vicanbf805472016-01-26 14:24:56 +0100168 return ret;
169}
Pavol Vican6eb14e82016-02-03 12:27:13 +0100170
Pavol Vican6eb14e82016-02-03 12:27:13 +0100171int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100172yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value)
Pavol Vican6eb14e82016-02-03 12:27:13 +0100173{
Pavol Vican0da132e2016-03-21 12:03:03 +0100174 const char *exp;
Radek Krejci4dcd3392016-06-22 10:28:40 +0200175 int rc;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100176
Pavol Vicane024ab72016-07-27 14:27:43 +0200177 if (!imp->prefix) {
178 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "import");
179 return EXIT_FAILURE;
180 }
Pavol Vican0da132e2016-03-21 12:03:03 +0100181 exp = lydict_insert_zc(module->ctx, value);
Pavol Vican0adf01d2016-03-22 12:29:33 +0100182 rc = lyp_check_import(module, exp, imp);
Pavol Vican0da132e2016-03-21 12:03:03 +0100183 lydict_remove(module->ctx, exp);
Radek Krejci4dcd3392016-06-22 10:28:40 +0200184 module->imp_size++;
Pavol Vican0da132e2016-03-21 12:03:03 +0100185 if (rc) {
Radek Krejci4dcd3392016-06-22 10:28:40 +0200186 return EXIT_FAILURE;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100187 }
Pavol Vican6eb14e82016-02-03 12:27:13 +0100188
Pavol Vican6eb14e82016-02-03 12:27:13 +0100189 return EXIT_SUCCESS;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100190}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100191
192int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100193yang_read_description(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100194{
195 int ret;
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100196 char *dsc = "description";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100197
198 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100199 ret = yang_check_string(module, &module->dsc, dsc, "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100200 } else {
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100201 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100202 ret = yang_check_string(module, &((struct lys_revision *)node)->dsc, dsc, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200203 } else if (!strcmp("import", where)){
204 ret = yang_check_string(module, &((struct lys_import *)node)->dsc, dsc, where, value);
205 } else if (!strcmp("include", where)){
206 ret = yang_check_string(module, &((struct lys_include *)node)->dsc, dsc, where, value);
Pavol Vican9bcd7c62016-03-17 19:36:35 +0100207 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100208 ret = yang_check_string(module, &((struct lys_node *)node)->dsc, dsc, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100209 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100210 }
211 return ret;
212}
213
214int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100215yang_read_reference(struct lys_module *module, void *node, char *value, char *where)
Pavol Vican1ca072c2016-02-03 13:03:56 +0100216{
217 int ret;
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100218 char *ref = "reference";
Pavol Vican1ca072c2016-02-03 13:03:56 +0100219
220 if (!node) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100221 ret = yang_check_string(module, &module->ref, "reference", "module", value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100222 } else {
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100223 if (!strcmp("revision", where)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100224 ret = yang_check_string(module, &((struct lys_revision *)node)->ref, ref, where, value);
Pavol Vicane024ab72016-07-27 14:27:43 +0200225 } else if (!strcmp("import", where)){
226 ret = yang_check_string(module, &((struct lys_import *)node)->ref, ref, where, value);
227 } else if (!strcmp("include", where)){
228 ret = yang_check_string(module, &((struct lys_include *)node)->ref, ref, where, value);
Pavol Vicanf5fe9662016-03-17 20:00:16 +0100229 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100230 ret = yang_check_string(module, &((struct lys_node *)node)->ref, ref, where, value);
Pavol Vicanbedff692016-02-03 14:29:17 +0100231 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100232 }
233 return ret;
234}
Pavol Vicanbedff692016-02-03 14:29:17 +0100235
236void *
237yang_read_revision(struct lys_module *module, char *value)
238{
239 struct lys_revision *retval;
240
Pavol Vican1eeb1992016-02-09 11:10:45 +0100241 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100242
243 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100244 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100245 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
246 memcpy(module->rev[0].date, value, LY_REV_SIZE);
247 retval->dsc = module->rev[0].dsc;
248 retval->ref = module->rev[0].ref;
249 retval = module->rev;
250 retval->dsc = NULL;
251 retval->ref = NULL;
252 } else {
253 memcpy(retval->date, value, LY_REV_SIZE);
254 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100255 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100256 free(value);
257 return retval;
258}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100259
260int
Pavol Vicana1827962016-02-29 15:39:42 +0100261yang_add_elem(struct lys_node_array **node, uint32_t *size)
Pavol Vican1eeb1992016-02-09 11:10:45 +0100262{
Pavol Vican45ccc592016-03-09 18:53:48 +0100263 if (!(*size % LY_ARRAY_SIZE)) {
Pavol Vican1eeb1992016-02-09 11:10:45 +0100264 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
265 LOGMEM;
266 return EXIT_FAILURE;
267 } else {
Pavol Vican45ccc592016-03-09 18:53:48 +0100268 memset(*node + *size, 0, LY_ARRAY_SIZE * sizeof **node);
Pavol Vican1eeb1992016-02-09 11:10:45 +0100269 }
270 }
271 (*size)++;
272 return EXIT_SUCCESS;
273}
Pavol Vicane1354e92016-02-09 14:02:09 +0100274
275void *
Pavol Vican0adf01d2016-03-22 12:29:33 +0100276yang_read_feature(struct lys_module *module, char *value)
Pavol Vicane1354e92016-02-09 14:02:09 +0100277{
278 struct lys_feature *retval;
279
280 /* check uniqueness of feature's names */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100281 if (lyp_check_identifier(value, LY_IDENT_FEATURE, module, NULL)) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100282 goto error;
283 }
284 retval = &module->features[module->features_size];
285 retval->name = lydict_insert_zc(module->ctx, value);
286 retval->module = module;
287 module->features_size++;
288 return retval;
289
290error:
291 free(value);
292 return NULL;
293}
294
295int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200296yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, enum yytokentype type)
Pavol Vicane1354e92016-02-09 14:02:09 +0100297{
298 const char *exp;
299 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100300 struct lys_feature *f;
Pavol Vican4df80542016-08-08 09:37:55 +0200301 struct lys_ident *i;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100302 struct lys_node *n;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200303 struct lys_type_enum *e;
304 struct lys_type_bit *b;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200305 struct lys_refine *r;
Pavol Vicane1354e92016-02-09 14:02:09 +0100306
Michal Vasko97b32be2016-07-25 10:59:53 +0200307 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
308 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
309 free(value);
310 return EXIT_FAILURE;
311 }
312
Pavol Vican0adf01d2016-03-22 12:29:33 +0100313 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100314 free(value);
315 return EXIT_FAILURE;
316 }
317 free(value);
318
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200319 switch (type) {
320 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100321 f = (struct lys_feature *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200322 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200323 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200324 break;
325 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200326 i = (struct lys_ident *) ptr;
327 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, unres);
328 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200329 break;
330 case ENUM_KEYWORD:
331 e = &((struct yang_type *)ptr)->type->info.enums.enm[((struct yang_type *)ptr)->type->info.enums.count - 1];
332 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
333 e->iffeature_size++;
334 break;
335 case BIT_KEYWORD:
336 b = &((struct yang_type *)ptr)->type->info.bits.bit[((struct yang_type *)ptr)->type->info.bits.count - 1];
337 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
338 b->iffeature_size++;
339 break;
Pavol Vicand2daf2d2016-09-27 21:58:47 +0200340 case REFINE_KEYWORD:
341 r = &((struct lys_node_uses *)ptr)->refine[((struct lys_node_uses *)ptr)->refine_size - 1];
342 ret = resolve_iffeature_compile(&r->iffeature[r->iffeature_size], exp, (struct lys_node *) ptr, unres);
343 r->iffeature_size++;
344 break;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200345 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100346 n = (struct lys_node *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200347 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200348 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200349 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100350 }
Radek Krejci9ff0a922016-07-14 13:08:05 +0200351 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100352
Radek Krejci9ff0a922016-07-14 13:08:05 +0200353 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100354 return EXIT_FAILURE;
355 }
356 return EXIT_SUCCESS;
357}
358
Pavol Vican4fb66c92016-03-17 10:32:27 +0100359int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200360yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100361{
362 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100363 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100364 return EXIT_FAILURE;
365 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200366 if (shortint) {
367 *((uint8_t *)flags) |= (uint8_t)value;
368 } else {
369 *flags |= value;
370 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100371 return EXIT_SUCCESS;
372 }
373}
374
Pavol Vicanbbdef532016-02-09 14:52:12 +0100375void *
376yang_read_identity(struct lys_module *module, char *value)
377{
378 struct lys_ident *ret;
379
380 ret = &module->ident[module->ident_size];
381 ret->name = lydict_insert_zc(module->ctx, value);
382 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200383 if (dup_identities_check(ret->name, module)) {
384 lydict_remove(module->ctx, ret->name);
385 return NULL;
386 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100387 module->ident_size++;
388 return ret;
389}
390
391int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100392yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100393{
394 const char *exp;
395
Pavol Vican0adf01d2016-03-22 12:29:33 +0100396 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100397 free(value);
398 if (!exp) {
399 return EXIT_FAILURE;
400 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200401
402 /* temporarily decrement identity_size due to resolve base */
403 module->ident_size--;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100404 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100405 lydict_remove(module->ctx, exp);
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200406 /* undo change identity_size */
407 module->ident_size++;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100408 return EXIT_FAILURE;
409 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200410 /* undo change identity_size */
411 module->ident_size++;
Pavol Vican44dde2c2016-02-10 11:18:14 +0100412
Pavol Vicanbbdef532016-02-09 14:52:12 +0100413 lydict_remove(module->ctx, exp);
414 return EXIT_SUCCESS;
415}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100416
417void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200418yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100419{
420 struct lys_restr *retval;
421
422 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100423 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100424 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100425 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200426 case ANYDATA_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100427 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200428 retval = &((struct lys_node_anydata *)node)->must[((struct lys_node_anydata *)node)->must_size++];
Pavol Vican096c6db2016-02-11 15:08:10 +0100429 break;
430 case LEAF_KEYWORD:
431 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100432 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100433 case LEAF_LIST_KEYWORD:
434 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
435 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100436 case LIST_KEYWORD:
437 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
438 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100439 case REFINE_KEYWORD:
440 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
441 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100442 case ADD_KEYWORD:
443 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
444 memset(retval, 0, sizeof *retval);
445 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100446 case DELETE_KEYWORD:
447 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
448 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200449 case NOTIFICATION_KEYWORD:
450 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
451 break;
452 case INPUT_KEYWORD:
453 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
454 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200455 default:
456 goto error;
457 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100458 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100459 retval->expr = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200460 if (!retval->expr) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100461 goto error;
462 }
463 free(value);
464 return retval;
465
466error:
467 free(value);
468 return NULL;
469}
470
471int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100472yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100473{
474 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100475
Pavol Vicandde090a2016-08-30 15:12:14 +0200476 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100477 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100478 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200479 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100480 }
481 return ret;
482}
Pavol Vicanb5687112016-02-09 22:35:59 +0100483
484int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100485yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100486{
487 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100488 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100489 free(value);
490 return EXIT_FAILURE;
491 } else {
492 cont->presence = lydict_insert_zc(module->ctx, value);
493 return EXIT_SUCCESS;
494 }
495}
496
Pavol Vican235dbd42016-02-10 10:34:19 +0100497void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200498yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100499{
500 struct lys_when *retval;
501
502 retval = calloc(1, sizeof *retval);
503 if (!retval) {
504 LOGMEM;
505 free(value);
506 return NULL;
507 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100508 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200509 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100510 goto error;
511 }
512 switch (type) {
513 case CONTAINER_KEYWORD:
514 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100515 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100516 goto error;
517 }
518 ((struct lys_node_container *)node)->when = retval;
519 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200520 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100521 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200522 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200523 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100524 goto error;
525 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200526 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100527 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100528 case CHOICE_KEYWORD:
529 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100530 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100531 goto error;
532 }
533 ((struct lys_node_choice *)node)->when = retval;
534 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100535 case CASE_KEYWORD:
536 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100537 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100538 goto error;
539 }
540 ((struct lys_node_case *)node)->when = retval;
541 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100542 case LEAF_KEYWORD:
543 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100544 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100545 goto error;
546 }
547 ((struct lys_node_leaf *)node)->when = retval;
548 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100549 case LEAF_LIST_KEYWORD:
550 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100551 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100552 goto error;
553 }
554 ((struct lys_node_leaflist *)node)->when = retval;
555 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100556 case LIST_KEYWORD:
557 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100558 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100559 goto error;
560 }
561 ((struct lys_node_list *)node)->when = retval;
562 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100563 case USES_KEYWORD:
564 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100565 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100566 goto error;
567 }
568 ((struct lys_node_uses *)node)->when = retval;
569 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100570 case AUGMENT_KEYWORD:
571 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100572 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100573 goto error;
574 }
575 ((struct lys_node_augment *)node)->when = retval;
576 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200577 default:
578 goto error;
579 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100580 }
581 free(value);
582 return retval;
583
584error:
585 free(value);
586 lys_when_free(module->ctx, retval);
587 return NULL;
588}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100589
590void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100591yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100592{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100593 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100594
Pavol Vican7cadfe72016-02-11 12:33:34 +0100595 node = calloc(1, sizeof_struct);
596 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100597 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100598 LOGMEM;
599 return NULL;
600 }
Pavol Vican531a9132016-03-03 10:10:09 +0100601 if (value) {
602 node->name = lydict_insert_zc(module->ctx, value);
603 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100604 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100605 node->nodetype = nodetype;
606 node->prev = node;
607
608 /* insert the node into the schema tree */
609 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100610 if (value) {
611 lydict_remove(module->ctx, node->name);
612 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100613 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100614 return NULL;
615 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100616 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100617}
618
Pavol Vican8c793992016-07-15 10:44:57 +0200619void *
620yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
621{
622 struct lys_node *node;
623
Michal Vaskobb174852016-07-25 11:00:21 +0200624 if (module->version != 2) {
625 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
626 return NULL;
627 }
628
Pavol Vican8c793992016-07-15 10:44:57 +0200629 for (node = parent; node; node = lys_parent(node)) {
630 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
Pavol Vicanbbe77822016-07-15 12:53:07 +0200631 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200632 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
633 return NULL;
634 }
635 }
636 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
637}
638
Pavol Vican8c82fa82016-02-10 13:13:24 +0100639int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200640yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100641{
642 int ret;
643
644 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100645 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100646 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100647 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100648 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100649 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100650 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200651 default:
652 free(value);
653 LOGINT;
654 ret = EXIT_FAILURE;
655 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100656 }
657 return ret;
658}
659
660int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200661yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100662{
663 int ret;
664
665 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100666 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100667 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100668 break;
669 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100670 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100671 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100672 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100673 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100674 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200675 default:
676 free(value);
677 LOGINT;
678 ret = EXIT_FAILURE;
679 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100680 }
681 return ret;
682}
Pavol Vican5de33492016-02-22 14:03:24 +0100683
684int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100685yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100686{
687 char *exp, *value;
688
689 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200690 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100691 while ((value = strpbrk(value, " \t\n"))) {
692 list->keys_size++;
693 while (isspace(*value)) {
694 value++;
695 }
696 }
697 list->keys_size++;
698 list->keys = calloc(list->keys_size, sizeof *list->keys);
699 if (!list->keys) {
700 LOGMEM;
701 goto error;
702 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100703 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100704 goto error;
705 }
706 free(exp);
707 return EXIT_SUCCESS;
708
709error:
710 free(exp);
711 return EXIT_FAILURE;
712}
713
714int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100715yang_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 +0100716{
717 int i, j;
718 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200719 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100720
721 /* count the number of unique leafs in the value */
722 vaux = value;
723 while ((vaux = strpbrk(vaux, " \t\n"))) {
724 unique->expr_size++;
725 while (isspace(*vaux)) {
726 vaux++;
727 }
728 }
729 unique->expr_size++;
730 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
731 if (!unique->expr) {
732 LOGMEM;
733 goto error;
734 }
735
736 for (i = 0; i < unique->expr_size; i++) {
737 vaux = strpbrk(value, " \t\n");
738 if (!vaux) {
739 /* the last token, lydict_insert() will count its size on its own */
740 vaux = value;
741 }
742
743 /* store token into unique structure */
744 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
745
746 /* check that the expression does not repeat */
747 for (j = 0; j < i; j++) {
748 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100749 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
750 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100751 goto error;
752 }
753 }
754 /* try to resolve leaf */
755 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200756 unique_info = malloc(sizeof *unique_info);
757 unique_info->list = (struct lys_node *)list;
758 unique_info->expr = unique->expr[i];
759 unique_info->trg_type = &unique->trg_type;
760 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200761 goto error;
762 }
Pavol Vican85f12022016-03-05 16:30:35 +0100763 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200764 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100765 goto error;
766 }
767 }
768
769 /* move to next token */
770 value = vaux;
771 while(isspace(*value)) {
772 value++;
773 }
774 }
775
776 return EXIT_SUCCESS;
777
778error:
779 return EXIT_FAILURE;
780}
781
782int
Pavol Vican5de33492016-02-22 14:03:24 +0100783yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
784{
785 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100786 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100787
788 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100789 str = (char *)list->unique[k].expr;
790 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100791 goto error;
792 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100793 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100794 }
795 return EXIT_SUCCESS;
796
797error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100798 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100799 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100800}
801
Pavol Vican07f220f2016-09-02 13:04:37 +0200802int
Pavol Vican81344ac2016-09-02 14:23:06 +0200803yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
804{
805 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
806 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
807 goto error;
808 }
809 if (stype->type->info.lref.path) {
810 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
811 goto error;
812 }
813 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
814 stype->base = LY_TYPE_LEAFREF;
815 return EXIT_SUCCESS;
816
817error:
818 free(value);
819 return EXIT_FAILURE;
820}
821
822int
823yang_read_require_instance(struct yang_type *stype, int req)
824{
825 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
826 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
827 return EXIT_FAILURE;
828 }
829 if (stype->type->info.lref.req) {
830 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
831 return EXIT_FAILURE;
832 }
833 stype->type->info.lref.req = req;
834 stype->base = LY_TYPE_LEAFREF;
835 return EXIT_SUCCESS;
836}
837
838int
Pavol Vican07f220f2016-09-02 13:04:37 +0200839yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100840{
Pavol Vican07f220f2016-09-02 13:04:37 +0200841 const char *value;
842 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100843
Pavol Vican07f220f2016-09-02 13:04:37 +0200844 if (stype->base && stype->base != LY_TYPE_IDENT) {
845 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
846 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100847 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200848
849 stype->base = LY_TYPE_IDENT;
850 /* store in the JSON format */
851 value = transform_schema2json(module, expr);
852 free(expr);
853
854 if (!value) {
855 return EXIT_FAILURE;
856 }
857 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100858 lydict_remove(module->ctx, value);
859
860 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200861 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100862 }
863
Pavol Vican07f220f2016-09-02 13:04:37 +0200864 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100865}
866
Pavol Vican73e7c992016-02-24 12:18:05 +0100867int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200868yang_check_type(struct lys_module *module, struct lys_node *parent, struct yang_type *typ, int tpdftype, struct unres_schema *unres)
Pavol Vican73e7c992016-02-24 12:18:05 +0100869{
Pavol Vican81344ac2016-09-02 14:23:06 +0200870 int i, j, rc, ret = -1;
871 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100872 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200873 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200874 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200875 struct lys_type *dertype;
876 struct lys_type_enum *enms_sc = NULL;
877 struct lys_type_bit *bits_sc = NULL;
878 struct lys_type_bit bit_tmp;
879
Pavol Vican0adf01d2016-03-22 12:29:33 +0100880 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100881 if (!value) {
882 goto error;
883 }
884
885 i = parse_identifier(value);
886 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100887 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100888 lydict_remove(module->ctx, value);
889 goto error;
890 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200891 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100892 name = value;
893 if (value[i]) {
894 typ->type->module_name = lydict_insert(module->ctx, value, i);
895 name += i;
896 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100897 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100898 lydict_remove(module->ctx, value);
899 goto error;
900 }
901 ++name;
902 }
903
904 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100905 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100906 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200907 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100908 goto error;
909
Michal Vasko01c6fd22016-05-20 11:43:05 +0200910 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100911 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200912 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200913 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100914 ret = EXIT_FAILURE;
915 goto error;
916 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200917 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200918
Radek Krejci9b6aad22016-09-20 15:55:51 +0200919 if (typ->type->base == LY_TYPE_ERR) {
Radek Krejcic13db382016-08-16 10:52:42 +0200920 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
Radek Krejci9b6aad22016-09-20 15:55:51 +0200921 * 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 +0200922 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
923 if (siter) {
924 if (!((struct lys_node_grp *)siter)->nacm) {
925 LOGINT;
926 goto error;
927 }
928 ((struct lys_node_grp *)siter)->nacm--;
929 } else {
930 LOGINT;
931 goto error;
932 }
933 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200934
935 /* check status */
936 if (lyp_check_status(typ->type->parent->flags, typ->type->parent->module, typ->type->parent->name,
937 typ->type->der->flags, typ->type->der->module, typ->type->der->name, parent)) {
938 goto error;
939 }
940
Pavol Vican8bd72e42016-08-29 09:53:05 +0200941 base = typ->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100942 typ->type->base = typ->type->der->type.base;
943 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100944 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100945 }
946 switch (base) {
947 case LY_TYPE_STRING:
948 if (typ->type->base == LY_TYPE_BINARY) {
949 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100950 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100951 goto error;
952 }
953 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100954 if (typ->type->info.binary.length && lyp_check_length_range(typ->type->info.binary.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100955 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100956 goto error;
957 }
958 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100959 if (typ->type->info.str.length && lyp_check_length_range(typ->type->info.str.length->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100960 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100961 goto error;
962 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100963 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200964 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100965 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100966 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100967 break;
968 case LY_TYPE_DEC64:
969 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100970 /* mandatory sub-statement(s) check */
971 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
972 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100973 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100974 goto error;
975 }
976 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
977 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100979 goto error;
980 }
Radek Krejcib51d5932016-09-08 14:02:52 +0200981
982 /* copy fraction-digits specification from parent type for easier internal use */
983 if (typ->type->der->type.der) {
984 typ->type->info.dec64.dig = typ->type->der->type.info.dec64.dig;
985 typ->type->info.dec64.div = typ->type->der->type.info.dec64.div;
986 }
Pavol Vican3c8ee2b2016-09-29 13:18:13 +0200987 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
988 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
989 goto error;
990 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100991 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
992 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100993 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100994 goto error;
995 }
996 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100997 if (typ->type->info.num.range && lyp_check_length_range(typ->type->info.num.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100998 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100999 goto error;
1000 }
1001 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001002 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +01001003 goto error;
1004 }
1005 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001006 case LY_TYPE_ENUM:
1007 if (typ->type->base != LY_TYPE_ENUM) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001008 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001009 goto error;
1010 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001011 dertype = &typ->type->der->type;
1012
1013 if (!dertype->der) {
1014 if (!typ->type->info.enums.count) {
1015 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1016 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
1017 goto error;
1018 }
1019 } else {
1020 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1021 if (module->version < 2 && typ->type->info.enums.count) {
1022 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
1023 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
1024 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
1025 goto error;
1026 }
1027
1028 /* restricted enumeration type - the name MUST be used in the base type */
1029 enms_sc = dertype->info.enums.enm;
1030 for(i = 0; i < typ->type->info.enums.count; i++) {
1031 for (j = 0; j < dertype->info.enums.count; j++) {
1032 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
1033 break;
1034 }
1035 }
1036 if (j == dertype->info.enums.count) {
1037 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1038 goto error;
1039 }
1040
1041 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
1042 /* automatically assign value from base type */
1043 typ->type->info.enums.enm[i].value = enms_sc[j].value;
1044 } else {
1045 /* check that the assigned value corresponds to the original
1046 * value of the enum in the base type */
1047 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
1048 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
1049 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1050 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
1051 typ->type->info.enums.enm[i].name, enms_sc[j].value);
1052 goto error;
1053 }
1054 }
1055 }
Pavol Vican79a763d2016-02-25 15:41:27 +01001056 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001057 break;
Pavol Vican03a59442016-03-21 15:23:45 +01001058 case LY_TYPE_BITS:
1059 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001060 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +01001061 goto error;
1062 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001063 dertype = &typ->type->der->type;
1064
1065 if (!dertype->der) {
1066 if (!typ->type->info.bits.count) {
1067 /* type is derived directly from buit-in bits type and bit statement is required */
1068 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1069 goto error;
1070 }
1071 } else {
1072 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1073 if (module->version < 2 && typ->type->info.bits.count) {
1074 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1075 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1076 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1077 goto error;
1078 }
1079
1080 bits_sc = dertype->info.bits.bit;
1081 for (i = 0; i < typ->type->info.bits.count; i++) {
1082 for (j = 0; j < dertype->info.bits.count; j++) {
1083 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
1084 break;
1085 }
1086 }
1087 if (j == dertype->info.bits.count) {
1088 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1089 goto error;
1090 }
1091
1092 /* restricted bits type */
1093 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1094 /* automatically assign position from base type */
1095 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1096 } else {
1097 /* check that the assigned position corresponds to the original
1098 * position of the bit in the base type */
1099 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1100 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1101 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1102 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1103 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1104 goto error;
1105 }
1106 }
1107 }
Pavol Vican03a59442016-03-21 15:23:45 +01001108 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001109
1110 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1111 j = i;
1112
1113 /* keep them ordered by position */
1114 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1115 /* switch them */
1116 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1117 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1118 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1119 j--;
1120 }
Pavol Vican03a59442016-03-21 15:23:45 +01001121 }
1122 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001123 case LY_TYPE_LEAFREF:
Pavol Vican81344ac2016-09-02 14:23:06 +02001124 if (typ->type->base == LY_TYPE_INST) {
1125 if (typ->type->info.lref.path) {
1126 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1127 goto error;
1128 }
1129 if ((req = typ->type->info.lref.req)) {
1130 typ->type->info.inst.req = req;
1131 }
1132 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Pavol Vican92626d72016-09-21 09:36:09 +02001133 /* require-instance only YANG 1.1 */
1134 if (typ->type->info.lref.req && (module->version < 2)) {
1135 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
1136 goto error;
1137 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001138 /* flag resolving for later use */
1139 if (!tpdftype) {
1140 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1141 if (siter) {
1142 /* just a flag - do not resolve */
1143 tpdftype = 1;
1144 }
1145 }
1146
Pavol Vican6b072512016-04-04 10:50:21 +02001147 if (typ->type->info.lref.path) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001148 if (typ->type->der->type.der) {
1149 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1150 goto error;
1151 }
Pavol Vican191613a2016-02-26 16:21:32 +01001152 value = typ->type->info.lref.path;
1153 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001154 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001155 lydict_remove(module->ctx, value);
1156 if (!typ->type->info.lref.path) {
1157 goto error;
1158 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001159 /* try to resolve leafref path only when this is instantiated
1160 * leaf, so it is not:
1161 * - typedef's type,
1162 * - in grouping definition,
1163 * - just instantiated in a grouping definition,
1164 * because in those cases the nodes referenced in path might not be present
1165 * and it is not a bug. */
1166 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001167 goto error;
1168 }
Pavol Vican6b072512016-04-04 10:50:21 +02001169 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001170 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001171 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001172 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001173 /* copy leafref definition into the derived type */
1174 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1175 /* and resolve the path at the place we are (if not in grouping/typedef) */
1176 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001177 goto error;
1178 }
Radek Krejci742be352016-07-17 12:18:54 +02001179
Michal Vasko01c6fd22016-05-20 11:43:05 +02001180 /* add pointer to leafref target, only on leaves (not in typedefs) */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001181 if (typ->type->info.lref.target && lys_leaf_add_leafref_target(typ->type->info.lref.target, (struct lys_node *)typ->type->parent)) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001182 goto error;
1183 }
Pavol Vican191613a2016-02-26 16:21:32 +01001184 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001185 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001186 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001187 goto error;
1188 }
1189 break;
1190 case LY_TYPE_IDENT:
Pavol Vican07f220f2016-09-02 13:04:37 +02001191 if (typ->type->base != LY_TYPE_IDENT) {
1192 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001193 goto error;
1194 }
Pavol Vican07f220f2016-09-02 13:04:37 +02001195 if (typ->type->der->type.der) {
1196 if (typ->type->info.ident.ref) {
1197 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1198 goto error;
1199 }
1200 } else {
1201 if (!typ->type->info.ident.ref) {
1202 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1203 goto error;
1204 }
1205 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001206 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001207 case LY_TYPE_UNION:
1208 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001209 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001210 goto error;
1211 }
1212 if (!typ->type->info.uni.types) {
1213 if (typ->type->der->type.der) {
1214 /* this is just a derived type with no additional type specified/required */
1215 break;
1216 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001217 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001218 goto error;
1219 }
1220 for (i = 0; i < typ->type->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001221 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001222 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001223 goto error;
1224 }
Pavol Vican8e00e7a2016-09-20 11:07:48 +02001225 if (module->version < 2) {
1226 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
1227 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
1228 goto error;
1229 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
1230 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
1231 goto error;
1232 }
Pavol Vicana4f045a2016-02-29 15:01:20 +01001233 }
1234 }
1235 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001236
1237 default:
1238 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1239 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001240 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001241 goto error;
1242 }
1243 } else {
1244 LOGINT;
1245 goto error;
1246 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001247 }
1248 return EXIT_SUCCESS;
1249
1250error:
1251 if (typ->type->module_name) {
1252 lydict_remove(module->ctx, typ->type->module_name);
1253 typ->type->module_name = NULL;
1254 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001255 if (base) {
1256 typ->type->base = base;
1257 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001258 return ret;
1259}
1260
1261void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001262yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001263{
1264 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001265 struct type_deviation *dev;
1266 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001267
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001268 typ = calloc(1, sizeof *typ);
1269 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001270 LOGMEM;
1271 return NULL;
1272 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001273
1274 typ->flags = LY_YANG_STRUCTURE_FLAG;
1275 switch (type) {
1276 case LEAF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001277 if (((struct lys_node_leaf *)parent)->type.der) {
1278 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf");
1279 goto error;
1280 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001281 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1282 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1283 typ->type = &((struct lys_node_leaf *)parent)->type;
1284 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001285 case LEAF_LIST_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001286 if (((struct lys_node_leaflist *)parent)->type.der) {
1287 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, parent, "type", "leaf-list");
1288 goto error;
1289 }
Pavol Vicana55992a2016-03-01 13:37:17 +01001290 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1291 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1292 typ->type = &((struct lys_node_leaflist *)parent)->type;
1293 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001294 case UNION_KEYWORD:
1295 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1296 typ->type = (struct lys_type *)parent;
1297 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001298 case TYPEDEF_KEYWORD:
Pavol Vican85427f02016-09-26 15:21:05 +02001299 if (((struct lys_tpdf *)parent)->type.der) {
1300 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "typedef");
1301 goto error;
1302 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001303 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1304 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001305 break;
1306 case REPLACE_KEYWORD:
1307 /* deviation replace type*/
1308 dev = (struct type_deviation *)parent;
1309 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001310 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001311 goto error;
1312 }
1313 /* check target node type */
1314 if (dev->target->nodetype == LYS_LEAF) {
1315 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1316 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1317 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1318 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001319 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1320 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001321 goto error;
1322 }
1323
1324 /* remove type and initialize it */
1325 lys_type_free(module->ctx, typ->type);
1326 tmp_parent = typ->type->parent;
1327 memset(typ->type, 0, sizeof *typ->type);
1328 typ->type->parent = tmp_parent;
1329
1330 /* replace it with the value specified in deviation */
1331 /* HACK for unres */
1332 typ->type->der = (struct lys_tpdf *)typ;
1333 dev->deviate->type = typ->type;
1334 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001335 default:
1336 goto error;
1337 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001338 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001339 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001340 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001341
1342error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001343 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001344 free(typ);
1345 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001346}
1347
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001348void
1349yang_delete_type(struct lys_module *module, struct yang_type *stype)
1350{
1351 int i;
1352
Pavol Vican85427f02016-09-26 15:21:05 +02001353 if (!stype) {
1354 return;
1355 }
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001356 stype->type->base = stype->base;
1357 stype->type->der = NULL;
1358 lydict_remove(module->ctx, stype->name);
1359 if (stype->base == LY_TYPE_UNION) {
1360 for (i = 0; i < stype->type->info.uni.count; i++) {
1361 if (stype->type->info.uni.types[i].der) {
1362 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1363 }
1364 }
1365 }
1366 free(stype);
1367}
1368
Pavol Vican73e7c992016-02-24 12:18:05 +01001369void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001370yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001371{
1372 struct lys_restr **length;
1373
Pavol Vican6b072512016-04-04 10:50:21 +02001374 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001375 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001376 typ->base = LY_TYPE_STRING;
1377 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001378 length = &typ->type->info.binary.length;
1379 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001380 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001381 goto error;
1382 }
1383
1384 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001385 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001386 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001387 }
1388 *length = calloc(1, sizeof **length);
1389 if (!*length) {
1390 LOGMEM;
1391 goto error;
1392 }
1393 (*length)->expr = lydict_insert_zc(module->ctx, value);
1394 return *length;
1395
1396error:
1397 free(value);
1398 return NULL;
1399
1400}
Pavol Vican1c203db2016-02-24 14:05:23 +01001401
Pavol Vican6eecf302016-08-10 11:09:05 +02001402int
1403yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001404{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001405 char *buf;
1406 size_t len;
1407
Michal Vasko0aee5c12016-06-17 14:27:26 +02001408 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001409 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001410 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001411 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001412
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001413 len = strlen(value);
1414 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001415
1416 if (!buf) {
1417 LOGMEM;
1418 free(value);
1419 return EXIT_FAILURE;
1420 }
1421
1422 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001423 strcpy(&buf[1], value);
1424 free(value);
1425
Pavol Vican6eecf302016-08-10 11:09:05 +02001426 pattern->expr = lydict_insert_zc(module->ctx, buf);
1427 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001428}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001429
1430void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001431yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001432{
Pavol Vican6b072512016-04-04 10:50:21 +02001433 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001434 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001435 goto error;
1436 }
Pavol Vican6b072512016-04-04 10:50:21 +02001437 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001438 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001439 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001440 goto error;
1441 }
1442 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1443 if (!typ->type->info.dec64.range) {
1444 LOGMEM;
1445 goto error;
1446 }
1447 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1448 return typ->type->info.dec64.range;
1449
1450error:
1451 free(value);
1452 return NULL;
1453}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001454
1455int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001456yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001457{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001458 unsigned int i;
1459
Pavol Vican6b072512016-04-04 10:50:21 +02001460 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1461 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001462 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001463 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001464 goto error;
1465 }
1466 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001467 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001468 goto error;
1469 }
1470 /* range check */
1471 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001472 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001473 goto error;
1474 }
1475 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001476 typ->type->info.dec64.div = 10;
1477 for (i = 1; i < value; i++) {
1478 typ->type->info.dec64.div *= 10;
1479 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001480 return EXIT_SUCCESS;
1481
1482error:
1483 return EXIT_FAILURE;
1484}
Pavol Vican79a763d2016-02-25 15:41:27 +01001485
1486void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001487yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001488{
1489 struct lys_type_enum *enm;
1490 int i;
1491
Pavol Vicanc6662412016-08-30 08:06:28 +02001492 if (!value[0]) {
1493 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1494 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1495 free(value);
1496 goto error;
1497 }
1498
Pavol Vican79a763d2016-02-25 15:41:27 +01001499 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1500 enm->name = lydict_insert_zc(module->ctx, value);
1501
1502 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1503 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001504 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001505 goto error;
1506 }
1507
1508 /* check the name uniqueness */
1509 for (i = 0; i < typ->type->info.enums.count; i++) {
1510 if (!strcmp(typ->type->info.enums.enm[i].name, typ->type->info.enums.enm[typ->type->info.enums.count].name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001511 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001512 goto error;
1513 }
1514 }
1515
1516 typ->type->info.enums.count++;
1517 return enm;
1518
1519error:
1520 typ->type->info.enums.count++;
1521 return NULL;
1522}
1523
1524int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001525yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001526{
1527 int i, j;
1528
1529 if (!assign) {
1530 /* assign value automatically */
1531 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001532 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001533 goto error;
1534 }
1535 enm->value = *value;
1536 enm->flags |= LYS_AUTOASSIGNED;
1537 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001538 } else if (typ->type->info.enums.enm == enm) {
1539 /* change value, which is assigned automatically, if first enum has value. */
1540 *value = typ->type->info.enums.enm[0].value;
1541 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001542 }
1543
1544 /* check that the value is unique */
1545 j = typ->type->info.enums.count-1;
1546 for (i = 0; i < j; i++) {
1547 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001548 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001549 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1550 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001551 goto error;
1552 }
1553 }
1554
1555 return EXIT_SUCCESS;
1556
1557error:
1558 return EXIT_FAILURE;
1559}
Pavol Vican9887c682016-02-29 11:32:01 +01001560
1561void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001562yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001563{
1564 int i;
1565 struct lys_type_bit *bit;
1566
1567 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001568 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001569 free(value);
1570 goto error;
1571 }
1572 bit->name = lydict_insert_zc(module->ctx, value);
1573
1574 /* check the name uniqueness */
1575 for (i = 0; i < typ->type->info.bits.count; i++) {
1576 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001577 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001578 typ->type->info.bits.count++;
1579 goto error;
1580 }
1581 }
1582 typ->type->info.bits.count++;
1583 return bit;
1584
1585error:
1586 return NULL;
1587}
1588
1589int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001590yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001591{
1592 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001593
1594 if (!assign) {
1595 /* assign value automatically */
1596 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001597 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001598 goto error;
1599 }
1600 bit->pos = (uint32_t)*value;
1601 bit->flags |= LYS_AUTOASSIGNED;
1602 (*value)++;
1603 }
1604
1605 j = typ->type->info.bits.count - 1;
1606 /* check that the value is unique */
1607 for (i = 0; i < j; i++) {
1608 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001609 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 +01001610 goto error;
1611 }
1612 }
1613
Pavol Vican9887c682016-02-29 11:32:01 +01001614 return EXIT_SUCCESS;
1615
1616error:
1617 return EXIT_FAILURE;
1618}
Pavol Vican0df02b02016-03-01 10:28:50 +01001619
1620void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001621yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001622{
1623 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001624 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001625
Pavol Vican810892e2016-07-12 16:55:34 +02001626 root = (parent) ? NULL : lys_main_module(module)->data;
1627 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001628 free(value);
1629 return NULL;
1630 }
Pavol Vican810892e2016-07-12 16:55:34 +02001631
Pavol Vican0df02b02016-03-01 10:28:50 +01001632 if (!parent) {
1633 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001634 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001635 } else {
1636 switch (parent->nodetype) {
1637 case LYS_GROUPING:
1638 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001639 ((struct lys_node_grp *)parent)->tpdf_size++;
1640 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001641 case LYS_CONTAINER:
1642 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1643 ((struct lys_node_container *)parent)->tpdf_size++;
1644 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001645 case LYS_LIST:
1646 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1647 ((struct lys_node_list *)parent)->tpdf_size++;
1648 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001649 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001650 case LYS_ACTION:
1651 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1652 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001653 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001654 case LYS_INPUT:
1655 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001656 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1657 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001658 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001659 case LYS_NOTIF:
1660 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1661 ((struct lys_node_notif *)parent)->tpdf_size++;
1662 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001663 default:
1664 /* another type of nodetype is error*/
1665 LOGINT;
1666 free(value);
1667 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001668 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001669 }
1670
Pavol Vican79436472016-04-04 11:22:02 +02001671 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001672 ret->name = lydict_insert_zc(module->ctx, value);
1673 ret->module = module;
1674 return ret;
1675}
Pavol Vican1003ead2016-03-02 12:24:52 +01001676
1677void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001678yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001679{
1680 struct lys_refine *rfn;
1681
1682 rfn = &uses->refine[uses->refine_size];
1683 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001684 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001685 free(value);
1686 if (!rfn->target_name) {
1687 return NULL;
1688 }
1689 return rfn;
1690}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001691
1692void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001693yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001694{
1695 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001696
1697 if (parent) {
1698 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1699 } else {
1700 aug = &module->augment[module->augment_size];
1701 }
1702 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001703 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001704 free(value);
1705 if (!aug->target_name) {
1706 return NULL;
1707 }
1708 aug->parent = parent;
1709 aug->module = module;
1710 if (parent) {
1711 ((struct lys_node_uses *)parent)->augment_size++;
1712 } else {
1713 module->augment_size++;
1714 }
1715 return aug;
1716}
Pavol Vican220e5a12016-03-03 14:19:43 +01001717
1718void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001719yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001720{
Pavol Vican1d714f32016-09-29 13:43:40 +02001721 struct lys_node *dev_target = NULL;
Pavol Vican220e5a12016-03-03 14:19:43 +01001722 struct lys_deviation *dev;
1723 struct type_deviation *deviation = NULL;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001724 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001725
Pavol Vican220e5a12016-03-03 14:19:43 +01001726 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001727 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001728 free(value);
1729 if (!dev->target_name) {
1730 goto error;
1731 }
1732
Pavol Vican974377b2016-03-23 00:38:53 +01001733 deviation = calloc(1, sizeof *deviation);
1734 if (!deviation) {
1735 LOGMEM;
1736 goto error;
1737 }
1738
Pavol Vican220e5a12016-03-03 14:19:43 +01001739 /* resolve target node */
1740 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1741 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001742 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001743 goto error;
1744 }
Radek Krejcic4283442016-04-22 09:19:27 +02001745 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001746 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1747 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001748 goto error;
1749 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001750
Pavol Vican220e5a12016-03-03 14:19:43 +01001751 /*save pointer to the deviation and deviated target*/
1752 deviation->deviation = dev;
1753 deviation->target = dev_target;
1754
Pavol Vican38321d02016-08-16 14:56:02 +02001755 deviation->dflt_check = ly_set_new();
1756 if (!deviation->dflt_check) {
1757 LOGMEM;
1758 goto error;
1759 }
1760
Pavol Vican220e5a12016-03-03 14:19:43 +01001761 return deviation;
1762
1763error:
1764 free(deviation);
1765 lydict_remove(module->ctx, dev->target_name);
1766 return NULL;
1767}
Pavol Vican4c90c642016-03-03 15:06:47 +01001768
1769int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001770yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001771{
1772 int i;
1773
1774 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001775 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001776 return EXIT_FAILURE;
1777 }
1778 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1779
1780 /* you cannot remove a key leaf */
1781 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1782 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1783 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001784 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1785 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001786 return EXIT_FAILURE;
1787 }
1788 }
1789 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001790
Pavol Vican4c90c642016-03-03 15:06:47 +01001791 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001792 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001793 dev->deviation->orig_node = dev->target;
1794
1795 dev->deviation->deviate_size = 1;
1796 return EXIT_SUCCESS;
1797}
Pavol Vican85f12022016-03-05 16:30:35 +01001798
1799int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001800yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001801{
1802 struct unres_schema tmp_unres;
1803
1804 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1805 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1806 dev->deviation->deviate_size++;
Pavol Vican33884462016-09-27 21:04:26 +02001807 dev->trg_must_size = NULL;
Pavol Vican85f12022016-03-05 16:30:35 +01001808 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001809 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1810 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001811 return EXIT_FAILURE;
1812 }
1813
1814 /* store a shallow copy of the original node */
1815 if (!dev->deviation->orig_node) {
1816 memset(&tmp_unres, 0, sizeof tmp_unres);
Michal Vaskoe022a562016-09-27 14:24:15 +02001817 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, &tmp_unres, 1);
Pavol Vican85f12022016-03-05 16:30:35 +01001818 /* just to be safe */
1819 if (tmp_unres.count) {
1820 LOGINT;
1821 return EXIT_FAILURE;
1822 }
1823 }
1824
1825 return EXIT_SUCCESS;
1826}
1827
1828int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001829yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001830{
1831 const char **stritem;
1832
1833 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001834 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001835 free(value);
1836 goto error;
1837 }
1838
1839 /* check target node type */
1840 if (dev->target->nodetype == LYS_LEAFLIST) {
1841 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1842 } else if (dev->target->nodetype == LYS_LEAF) {
1843 stritem = &((struct lys_node_leaf *)dev->target)->units;
1844 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001845 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1846 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001847 free(value);
1848 goto error;
1849 }
1850
1851 dev->deviate->units = lydict_insert_zc(ctx, value);
1852
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001853 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1854 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001855 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001856 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1857 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001858 goto error;
1859 }
1860 /* remove current units value of the target */
1861 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001862 } else {
1863 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1864 /* check that there is no current value */
1865 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001866 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1867 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001868 goto error;
1869 }
1870 } else { /* replace */
1871 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001872 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1873 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001874 goto error;
1875 }
1876 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001877 /* remove current units value of the target ... */
1878 lydict_remove(ctx, *stritem);
1879
1880 /* ... and replace it with the value specified in deviation */
1881 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1882 }
1883
Pavol Vican85f12022016-03-05 16:30:35 +01001884 return EXIT_SUCCESS;
1885
1886error:
1887 return EXIT_FAILURE;
1888}
1889
1890int
Pavol Vican974377b2016-03-23 00:38:53 +01001891yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001892{
Pavol Vican85f12022016-03-05 16:30:35 +01001893 /* check target node type */
1894 switch (dev->target->nodetype) {
1895 case LYS_LEAF:
1896 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1897 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1898 break;
1899 case LYS_CONTAINER:
1900 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1901 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1902 break;
1903 case LYS_LEAFLIST:
1904 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1905 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1906 break;
1907 case LYS_LIST:
1908 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1909 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1910 break;
1911 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001912 case LYS_ANYDATA:
1913 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1914 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001915 break;
1916 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001917 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1918 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001919 goto error;
1920 }
1921
Michal Vasko508a50d2016-09-07 14:50:33 +02001922 /* flag will be checked again, clear it for now */
1923 dev->target->flags &= ~LYS_XPATH_DEP;
1924
Pavol Vican85f12022016-03-05 16:30:35 +01001925 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1926 /* reallocate the must array of the target */
1927 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1928 if (!dev->deviate->must) {
1929 LOGMEM;
1930 goto error;
1931 }
1932 *dev->trg_must = dev->deviate->must;
1933 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1934 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001935 } else {
1936 /* LY_DEVIATE_DEL */
1937 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1938 if (!dev->deviate->must) {
1939 LOGMEM;
1940 goto error;
1941 }
Pavol Vican85f12022016-03-05 16:30:35 +01001942 }
1943
1944 return EXIT_SUCCESS;
1945
1946error:
1947 return EXIT_FAILURE;
1948}
1949
1950int
Pavol Vican974377b2016-03-23 00:38:53 +01001951yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001952{
Pavol Vican85f12022016-03-05 16:30:35 +01001953 struct lys_node_list *list;
1954
1955 /* check target node type */
1956 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001957 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1958 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001959 goto error;
1960 }
1961
1962 list = (struct lys_node_list *)dev->target;
1963 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1964 /* reallocate the unique array of the target */
1965 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1966 if (!dev->deviate->unique) {
1967 LOGMEM;
1968 goto error;
1969 }
1970 list->unique = dev->deviate->unique;
1971 dev->deviate->unique = &list->unique[list->unique_size];
1972 dev->deviate->unique_size = c_uniq;
1973 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001974 } else {
1975 /* LY_DEVIATE_DEL */
1976 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1977 if (!dev->deviate->unique) {
1978 LOGMEM;
1979 goto error;
1980 }
Pavol Vican85f12022016-03-05 16:30:35 +01001981 }
1982
1983 return EXIT_SUCCESS;
1984
1985error:
1986 return EXIT_FAILURE;
1987}
1988
1989int
Pavol Vican38321d02016-08-16 14:56:02 +02001990yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001991{
Pavol Vican38321d02016-08-16 14:56:02 +02001992 int i;
1993 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001994
Pavol Vican38321d02016-08-16 14:56:02 +02001995 /* check target node type */
1996 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1997 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1998 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1999 goto error;
2000 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
2001 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2002 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
2003 goto error;
2004 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
2005 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2006 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002007 goto error;
2008 }
2009
Pavol Vican38321d02016-08-16 14:56:02 +02002010 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2011 /* check that there is no current value */
2012 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
2013 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
2014 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2015 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002016 goto error;
2017 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002018
Pavol Vican38321d02016-08-16 14:56:02 +02002019 /* check collision with mandatory/min-elements */
2020 if ((dev->target->flags & LYS_MAND_TRUE) ||
2021 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
2022 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
2023 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2024 "Adding the \"default\" statement is forbidden on %s statement.",
2025 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2026 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01002027 }
Pavol Vican38321d02016-08-16 14:56:02 +02002028 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2029 /* check that there was a value before */
2030 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
2031 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
2032 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2033 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2034 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002035 }
Pavol Vican38321d02016-08-16 14:56:02 +02002036 }
2037
2038 if (dev->target->nodetype == LYS_LEAFLIST) {
2039 /* reallocate default list in the target */
2040 llist = (struct lys_node_leaflist *)dev->target;
2041 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2042 /* reallocate (enlarge) the unique array of the target */
2043 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
2044 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2045 /* reallocate (replace) the unique array of the target */
2046 for (i = 0; i < llist->dflt_size; i++) {
2047 lydict_remove(llist->module->ctx, llist->dflt[i]);
2048 }
2049 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
2050 llist->dflt_size = 0;
2051 }
2052 }
2053
2054 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
2055 if (!dev->deviate->dflt) {
2056 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01002057 goto error;
2058 }
2059
2060 return EXIT_SUCCESS;
2061
2062error:
2063 return EXIT_FAILURE;
2064}
2065
2066int
Pavol Vican38321d02016-08-16 14:56:02 +02002067yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
2068{
2069 struct lys_node *node;
2070 struct lys_node_choice *choice;
2071 struct lys_node_leaf *leaf;
2072 struct lys_node_leaflist *llist;
2073 int rc, i;
2074 unsigned int u;
2075 const char *value;
2076
2077 value = lydict_insert_zc(ctx, exp);
2078 u = strlen(value);
2079 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
2080
2081 if (dev->target->nodetype == LYS_CHOICE) {
2082 choice = (struct lys_node_choice *)dev->target;
2083 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2084 if (rc || !node) {
2085 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2086 goto error;
2087 }
2088 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2089 if (!choice->dflt || (choice->dflt != node)) {
2090 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2091 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2092 goto error;
2093 }
2094 } else { /* add or replace */
2095 choice->dflt = node;
2096 if (!choice->dflt) {
2097 /* default branch not found */
2098 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2099 goto error;
2100 }
2101 }
2102 } else if (dev->target->nodetype == LYS_LEAF) {
2103 leaf = (struct lys_node_leaf *)dev->target;
2104 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2105 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2106 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2107 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2108 goto error;
2109 }
2110 /* remove value */
2111 lydict_remove(ctx, leaf->dflt);
2112 leaf->dflt = NULL;
2113 } else { /* add (already checked) and replace */
2114 /* remove value */
2115 lydict_remove(ctx, leaf->dflt);
2116
2117 /* set new value */
2118 leaf->dflt = lydict_insert(ctx, value, u);
2119
2120 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2121 ly_set_add(dev->dflt_check, dev->target, 0);
2122 }
2123 } else { /* LYS_LEAFLIST */
2124 llist = (struct lys_node_leaflist *)dev->target;
2125 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2126 /* find and remove the value in target list */
2127 for (i = 0; i < llist->dflt_size; i++) {
2128 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2129 /* match, remove the value */
2130 lydict_remove(llist->module->ctx, llist->dflt[i]);
2131 llist->dflt[i] = NULL;
2132 break;
2133 }
2134 }
2135 if (i == llist->dflt_size) {
2136 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2137 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2138 goto error;
2139 }
2140 } else {
2141 /* add or replace, anyway we place items into the deviate's list
2142 which propagates to the target */
2143 /* we just want to check that the value isn't already in the list */
2144 for (i = 0; i < llist->dflt_size; i++) {
2145 if (ly_strequal(llist->dflt[i], value, 1)) {
2146 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2147 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2148 goto error;
2149 }
2150 }
2151 /* store it in target node */
2152 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
2153
2154 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2155 ly_set_add(dev->dflt_check, dev->target, 0);
2156 }
2157 }
2158
2159 return EXIT_SUCCESS;
2160error:
2161 return EXIT_FAILURE;
2162}
2163
2164
2165int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002166yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002167{
2168 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002169 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002170 goto error;
2171 }
2172
2173 /* for we deviate from RFC 6020 and allow config property even it is/is not
2174 * specified in the target explicitly since config property inherits. So we expect
2175 * that config is specified in every node. But for delete, we check that the value
2176 * is the same as here in deviation
2177 */
2178 dev->deviate->flags |= value;
2179
2180 /* add and replace are the same in this case */
2181 /* remove current config value of the target ... */
2182 dev->target->flags &= ~LYS_CONFIG_MASK;
2183
2184 /* ... and replace it with the value specified in deviation */
2185 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2186
2187 return EXIT_SUCCESS;
2188
2189error:
2190 return EXIT_FAILURE;
2191}
2192
2193int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002194yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002195{
Radek Krejcie00d2312016-08-12 15:27:49 +02002196 struct lys_node *parent;
2197
Pavol Vican85f12022016-03-05 16:30:35 +01002198 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002199 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002200 goto error;
2201 }
2202
2203 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002204 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002205 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2206 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002207 goto error;
2208 }
2209
2210 dev->deviate->flags |= value;
2211
2212 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2213 /* check that there is no current value */
2214 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002215 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2216 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002217 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002218 } else {
2219 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2220 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2221 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2222 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2223 goto error;
2224 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2225 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2226 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2227 goto error;
2228 }
Pavol Vican85f12022016-03-05 16:30:35 +01002229 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002230 } else { /* replace */
2231 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002232 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2233 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002234 goto error;
2235 }
Pavol Vican85f12022016-03-05 16:30:35 +01002236 }
2237
Pavol Vican85f12022016-03-05 16:30:35 +01002238 /* remove current mandatory value of the target ... */
2239 dev->target->flags &= ~LYS_MAND_MASK;
2240
2241 /* ... and replace it with the value specified in deviation */
2242 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2243
Radek Krejcie00d2312016-08-12 15:27:49 +02002244 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2245 for (parent = dev->target->parent;
2246 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2247 parent = parent->parent) {
2248 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2249 /* stop also on presence containers */
2250 break;
2251 }
2252 }
2253 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2254 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2255 if (lyp_check_mandatory_choice(parent)) {
2256 goto error;
2257 }
2258 }
2259
Pavol Vican85f12022016-03-05 16:30:35 +01002260 return EXIT_SUCCESS;
2261
2262error:
2263 return EXIT_FAILURE;
2264}
2265
2266int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002267yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002268{
Pavol Vican09adcc32016-08-25 10:51:36 +02002269 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002270
2271 /* check target node type */
2272 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002273 max = &((struct lys_node_leaflist *)dev->target)->max;
2274 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002275 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002276 max = &((struct lys_node_list *)dev->target)->max;
2277 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002278 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002279 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2280 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 +01002281 goto error;
2282 }
2283
2284 if (type) {
2285 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002286 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002287 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002288 } else {
2289 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002290 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002291 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002292 }
2293
2294 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2295 /* check that there is no current value */
2296 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002297 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2298 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002299 goto error;
2300 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002301 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2302 /* unfortunately, there is no way to check reliably that there
2303 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002304 }
2305
2306 /* add (already checked) and replace */
2307 /* set new value specified in deviation */
2308 *ui32val = value;
2309
Pavol Vican09adcc32016-08-25 10:51:36 +02002310 /* check min-elements is smaller than max-elements */
2311 if (*max && *min > *max) {
2312 if (type) {
2313 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2314 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2315 } else {
2316 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2317 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2318 }
2319 goto error;
2320 }
2321
Pavol Vican85f12022016-03-05 16:30:35 +01002322 return EXIT_SUCCESS;
2323
2324error:
2325 return EXIT_FAILURE;
2326}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002327
2328int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002329yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002330{
2331 int i;
2332
2333 /* find must to delete, we are ok with just matching conditions */
2334 for (i = 0; i < *dev->trg_must_size; i++) {
2335 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2336 /* we have a match, free the must structure ... */
2337 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2338 /* ... and maintain the array */
2339 (*dev->trg_must_size)--;
2340 if (i != *dev->trg_must_size) {
2341 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2342 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2343 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2344 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2345 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2346 }
2347 if (!(*dev->trg_must_size)) {
2348 free(*dev->trg_must);
2349 *dev->trg_must = NULL;
2350 } else {
2351 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2352 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2353 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2354 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2355 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2356 }
2357
2358 i = -1; /* set match flag */
2359 break;
2360 }
2361 }
2362 if (i != -1) {
2363 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002364 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2365 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002366 return EXIT_FAILURE;
2367 }
2368
2369 return EXIT_SUCCESS;
2370}
2371
2372int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002373yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002374{
2375 struct lys_node_list *list;
2376 int i, j;
2377
2378 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002379 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002380 dev->deviate->unique_size++;
2381 goto error;
2382 }
2383
2384 /* find unique structures to delete */
2385 for (i = 0; i < list->unique_size; i++) {
2386 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2387 continue;
2388 }
2389
2390 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2391 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2392 break;
2393 }
2394 }
2395
2396 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2397 /* we have a match, free the unique structure ... */
2398 for (j = 0; j < list->unique[i].expr_size; j++) {
2399 lydict_remove(module->ctx, list->unique[i].expr[j]);
2400 }
2401 free(list->unique[i].expr);
2402 /* ... and maintain the array */
2403 list->unique_size--;
2404 if (i != list->unique_size) {
2405 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2406 list->unique[i].expr = list->unique[list->unique_size].expr;
2407 }
2408
2409 if (!list->unique_size) {
2410 free(list->unique);
2411 list->unique = NULL;
2412 } else {
2413 list->unique[list->unique_size].expr_size = 0;
2414 list->unique[list->unique_size].expr = NULL;
2415 }
2416
2417 i = -1; /* set match flag */
2418 break;
2419 }
2420 }
2421 dev->deviate->unique_size++;
2422
2423 if (i != -1) {
2424 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002425 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2426 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002427 goto error;
2428 }
2429
2430 free(value);
2431 return EXIT_SUCCESS;
2432
2433error:
2434 free(value);
2435 return EXIT_FAILURE;
2436}
Pavol Vicane92421d2016-03-08 10:12:33 +01002437
2438int
Pavol Vican38321d02016-08-16 14:56:02 +02002439yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002440{
2441 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002442 unsigned int u;
2443 const char *value, *target_name;
2444 struct lys_node_leaflist *llist;
2445 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002446
Pavol Vican38321d02016-08-16 14:56:02 +02002447 /* now check whether default value, if any, matches the type */
2448 for (u = 0; u < dflt_check->number; ++u) {
2449 value = NULL;
2450 rc = EXIT_SUCCESS;
2451 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2452 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2453 target_name = leaf->name;
2454 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2455 } else { /* LYS_LEAFLIST */
2456 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2457 target_name = llist->name;
2458 for (i = 0; i < llist->dflt_size; i++) {
2459 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[i]);
2460 if (rc == -1) {
Pavol Vicane92421d2016-03-08 10:12:33 +01002461 break;
2462 }
2463 }
2464 }
Pavol Vican38321d02016-08-16 14:56:02 +02002465 if (rc == -1) {
2466 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2467 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2468 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2469 target_name);
2470 return EXIT_FAILURE;
2471 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002472 }
Pavol Vican38321d02016-08-16 14:56:02 +02002473
Pavol Vicane92421d2016-03-08 10:12:33 +01002474 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002475
Pavol Vican9b89dda2016-03-09 15:36:55 +01002476}
2477
2478int
2479yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vicane024ab72016-07-27 14:27:43 +02002480 struct lys_include *inc, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002481{
Pavol Vican9b89dda2016-03-09 15:36:55 +01002482 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002483 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002484 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002485 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002486
Pavol Vican55870412016-03-10 12:36:21 +01002487 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002488 trg = (submodule) ? (struct lys_module *)submodule : module;
Pavol Vicane024ab72016-07-27 14:27:43 +02002489 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002490 if (!rc) {
2491 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002492 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002493 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002494 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002495 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002496 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002497
Pavol Vican55870412016-03-10 12:36:21 +01002498 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002499 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002500}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002501
2502int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002503yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002504{
2505 char *prefix;
2506 char *identif;
2507 const char *ns = NULL;
2508 int i;
2509
Pavol Vicanf4717e62016-03-16 11:30:01 +01002510 /* check to the same pointer */
2511 if (data_node != actual) {
2512 return EXIT_SUCCESS;
2513 }
2514
Pavol Vicana302aa62016-03-17 10:45:35 +01002515 prefix = strdup(value);
2516 if (!prefix) {
2517 LOGMEM;
2518 goto error;
2519 }
2520 /* find prefix anf identificator*/
2521 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002522 if (!identif) {
2523 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2524 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2525 goto error;
2526 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002527 *identif = '\0';
2528 identif++;
2529
Pavol Vicanf4717e62016-03-16 11:30:01 +01002530 for(i = 0; i < module->imp_size; ++i) {
2531 if (!strcmp(module->imp[i].prefix, prefix)) {
2532 ns = module->imp[i].module->ns;
2533 break;
2534 }
2535 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002536 if (!ns && !strcmp(module->prefix, prefix)) {
2537 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2538 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002539 if (ns && !strcmp(ns, LY_NSNACM)) {
2540 if (!strcmp(identif, "default-deny-write")) {
2541 data_node->nacm |= LYS_NACM_DENYW;
2542 } else if (!strcmp(identif, "default-deny-all")) {
2543 data_node->nacm |= LYS_NACM_DENYA;
2544 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002545 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002546 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002547 }
2548 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002549 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002550 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002551
2552error:
2553 free(prefix);
2554 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002555}
2556
2557void
2558nacm_inherit(struct lys_module *module)
2559{
Pavol Vican10ffba52016-04-04 12:21:22 +02002560 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002561
2562 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002563 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002564 if (elem->parent) {
2565 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002566 case LYS_GROUPING:
2567 /* extension nacm not inherited*/
2568 break;
2569 case LYS_CHOICE:
2570 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002571 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002572 case LYS_USES:
2573 if (elem->parent->nodetype != LYS_GROUPING) {
2574 elem->nacm |= elem->parent->nacm;
2575 }
2576 break;
2577 case LYS_CONTAINER:
2578 case LYS_LIST:
2579 case LYS_CASE:
2580 case LYS_NOTIF:
2581 case LYS_RPC:
2582 case LYS_INPUT:
2583 case LYS_OUTPUT:
2584 case LYS_AUGMENT:
2585 elem->nacm |= elem->parent->nacm;
2586 break;
2587 case LYS_LEAF:
2588 case LYS_LEAFLIST:
2589 tmp_node = elem;
2590 tmp_child = elem->child;
2591 elem->child = NULL;
2592 default:
2593 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002594 }
2595 }
2596 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002597 if (tmp_node) {
2598 tmp_node->child = tmp_child;
2599 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002600 }
2601}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002602
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002603int
Pavol Vican1dac40c2016-09-28 11:39:26 +02002604store_flags(struct lys_node *node, uint8_t flags, int config_opt)
Pavol Vican4fb66c92016-03-17 10:32:27 +01002605{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002606 struct lys_node *elem;
2607
Pavol Vican1dac40c2016-09-28 11:39:26 +02002608 node->flags |= (config_opt == CONFIG_IGNORE) ? flags & (~(LYS_CONFIG_MASK | LYS_CONFIG_SET)): flags;
2609 if (config_opt == CONFIG_INHERIT_ENABLE) {
2610 if (!(node->flags & LYS_CONFIG_MASK)) {
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002611 /* get config flag from parent */
Pavol Vicanb5071382016-09-30 14:54:23 +02002612 if (node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2613 node->flags |= LYS_CONFIG_R;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002614 } else {
2615 /* default config is true */
2616 node->flags |= LYS_CONFIG_W;
2617 }
Pavol Vican1dac40c2016-09-28 11:39:26 +02002618 } else {
2619 /* do we even care about config flags? */
2620 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002621
Pavol Vican1dac40c2016-09-28 11:39:26 +02002622 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2623 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2624 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2625 return EXIT_FAILURE;
2626 }
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002627 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002628 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002629
2630 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002631}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002632
Pavol Vican1938d882016-04-10 13:36:31 +02002633static int
2634yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2635 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002636{
2637 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002638 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002639 int ret = EXIT_SUCCESS;
2640
2641 yylex_init(&scanner);
2642 bp = yy_scan_buffer((char *)data, size, scanner);
2643 yy_switch_to_buffer(bp, scanner);
2644 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2645 ret = EXIT_FAILURE;
2646 }
2647 yy_delete_buffer(bp, scanner);
2648 yylex_destroy(scanner);
2649 return ret;
2650}
2651
2652int
2653yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2654{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002655 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002656 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002657 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002658
2659 size_arrays = calloc(1, sizeof *size_arrays);
2660 if (!size_arrays) {
2661 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002662 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002663 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002664 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002665 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2666 if (!ret) {
2667 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002668 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002669 free(size_arrays->node);
2670 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002671 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002672}
2673
2674struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002675yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002676{
2677
Pavol Vican10ffba52016-04-04 12:21:22 +02002678 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002679 struct unres_schema *unres = NULL;
2680
2681 unres = calloc(1, sizeof *unres);
2682 if (!unres) {
2683 LOGMEM;
2684 goto error;
2685 }
2686
2687 module = calloc(1, sizeof *module);
2688 if (!module) {
2689 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002690 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002691 }
2692
2693 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002694 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002695 module->type = 0;
2696 module->implemented = (implement ? 1 : 0);
2697
2698 if (yang_parse_mem(module, NULL, unres, data, size)) {
2699 goto error;
2700 }
2701
2702 if (module && unres->count && resolve_unres_schema(module, unres)) {
2703 goto error;
2704 }
2705
2706 if (revision) {
2707 /* check revision of the parsed model */
2708 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2709 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2710 module->name, module->rev[0].date, revision);
2711 goto error;
2712 }
2713 }
2714
Pavol Vican10ffba52016-04-04 12:21:22 +02002715 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002716 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002717 goto error;
2718 }
2719
Pavol Vican10ffba52016-04-04 12:21:22 +02002720 if (module == tmp_module) {
2721 nacm_inherit(module);
2722 }
2723
Radek Krejci27fe55e2016-09-13 17:13:35 +02002724 if (module->deviation_size && !module->implemented) {
2725 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2726 /* deviations always causes target to be made implemented,
2727 * but augents and leafrefs not, so we have to apply them now */
2728 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002729 goto error;
2730 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002731 }
2732
Pavol Vican8e7110b2016-03-22 17:00:26 +01002733 unres_schema_free(NULL, &unres);
2734 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2735 return module;
2736
2737error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002738 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002739 unres_schema_free(module, &unres);
2740 if (!module || !module->name) {
2741 free(module);
2742 LOGERR(ly_errno, "Module parsing failed.");
2743 return NULL;
2744 }
2745
2746 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002747
2748 lys_sub_module_remove_devs_augs(module);
2749 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002750 return NULL;
2751}
2752
2753struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002754yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002755{
2756 struct lys_submodule *submodule;
2757
2758 submodule = calloc(1, sizeof *submodule);
2759 if (!submodule) {
2760 LOGMEM;
2761 goto error;
2762 }
2763
2764 submodule->ctx = module->ctx;
2765 submodule->type = 1;
2766 submodule->belongsto = module;
2767
2768 if (yang_parse_mem(module, submodule, unres, data, size)) {
2769 goto error;
2770 }
2771
Pavol Vican8e7110b2016-03-22 17:00:26 +01002772 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002773 return submodule;
2774
2775error:
2776 /* cleanup */
2777 unres_schema_free((struct lys_module *)submodule, &unres);
2778
2779 if (!submodule || !submodule->name) {
2780 free(submodule);
2781 LOGERR(ly_errno, "Submodule parsing failed.");
2782 return NULL;
2783 }
2784
2785 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2786
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002787 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2788 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002789 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002790 return NULL;
2791}
Pavol Vican8760bb72016-04-07 09:44:01 +02002792
2793static int
Pavol Vican8760bb72016-04-07 09:44:01 +02002794read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2795{
2796 int k = 0, j;
2797
2798 while (in_index < size) {
2799 if (input[in_index] == ' ') {
2800 k++;
2801 } else if (input[in_index] == '\t') {
2802 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2803 k += 8;
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002804 } else if (input[in_index] == '\\' && input[in_index + 1] == 't') {
2805 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2806 k += 8;
2807 ++in_index;
Pavol Vican8760bb72016-04-07 09:44:01 +02002808 } else {
2809 break;
2810 }
2811 ++in_index;
2812 if (k >= indent) {
2813 for (j = k - indent; j > 0; --j) {
2814 output[*out_index] = ' ';
2815 ++(*out_index);
2816 }
2817 break;
2818 }
2819 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002820 return in_index - 1;
Pavol Vican8760bb72016-04-07 09:44:01 +02002821}
2822
Pavol Vican3f598892016-09-28 15:41:07 +02002823char *
2824yang_read_string(const char *input, char *output, int size, int offset, int indent, int version) {
2825 int i = 0, out_index = offset, space = 0;
Pavol Vican8760bb72016-04-07 09:44:01 +02002826
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002827 while (i < size) {
2828 switch (input[i]) {
2829 case '\n':
2830 out_index -= space;
2831 output[out_index] = '\n';
2832 space = 0;
2833 i = read_indent(input, indent, size, i + 1, &out_index, output);
2834 break;
2835 case ' ':
2836 case '\t':
2837 output[out_index] = input[i];
2838 ++space;
2839 break;
2840 case '\\':
2841 if (input[i + 1] == 'n') {
2842 out_index -= space;
2843 output[out_index] = '\n';
2844 space = 0;
2845 i = read_indent(input, indent, size, i + 2, &out_index, output);
2846 } else if (input[i + 1] == 't') {
2847 output[out_index] = '\t';
2848 ++i;
2849 ++space;
2850 } else if (input[i + 1] == '\\') {
2851 output[out_index] = '\\';
2852 ++i;
2853 } else if ((i + 1) != size && input[i + 1] == '"') {
2854 output[out_index] = '"';
2855 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002856 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002857 if (version < 2) {
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002858 output[out_index] = input[i];
Pavol Vican677b0132016-08-09 15:44:58 +02002859 } else {
2860 /* YANG 1.1 backslash must not be followed by any other character */
2861 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
Pavol Vican3f598892016-09-28 15:41:07 +02002862 return NULL;
Pavol Vican677b0132016-08-09 15:44:58 +02002863 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002864 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002865 break;
2866 default:
2867 output[out_index] = input[i];
2868 space = 0;
2869 break;
Pavol Vican8760bb72016-04-07 09:44:01 +02002870 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002871 ++i;
Pavol Vican8760bb72016-04-07 09:44:01 +02002872 ++out_index;
2873 }
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002874 output[out_index] = '\0';
2875 if (size != out_index) {
Pavol Vican3f598892016-09-28 15:41:07 +02002876 output = realloc(output, out_index + 1);
Pavol Vican0fbb57b2016-09-27 21:46:12 +02002877 if (!output) {
2878 LOGMEM;
Pavol Vican3f598892016-09-28 15:41:07 +02002879 return NULL;
Pavol Vican8760bb72016-04-07 09:44:01 +02002880 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002881 }
Pavol Vican3f598892016-09-28 15:41:07 +02002882 return output;
Pavol Vican8760bb72016-04-07 09:44:01 +02002883}