blob: a2f914be7d88abc4af31b650c24ae1035042c26f [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 Vicane1354e92016-02-09 14:02:09 +0100305
Michal Vasko97b32be2016-07-25 10:59:53 +0200306 if ((module->version != 2) && ((value[0] == '(') || strchr(value, ' '))) {
307 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "if-feature");
308 free(value);
309 return EXIT_FAILURE;
310 }
311
Pavol Vican0adf01d2016-03-22 12:29:33 +0100312 if (!(exp = transform_schema2json(module, value))) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100313 free(value);
314 return EXIT_FAILURE;
315 }
316 free(value);
317
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200318 switch (type) {
319 case FEATURE_KEYWORD:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100320 f = (struct lys_feature *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200321 ret = resolve_iffeature_compile(&f->iffeature[f->iffeature_size], exp, (struct lys_node *)f, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200322 f->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200323 break;
324 case IDENTITY_KEYWORD:
Pavol Vican4df80542016-08-08 09:37:55 +0200325 i = (struct lys_ident *) ptr;
326 ret = resolve_iffeature_compile(&i->iffeature[i->iffeature_size], exp, (struct lys_node *)i, unres);
327 i->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200328 break;
329 case ENUM_KEYWORD:
330 e = &((struct yang_type *)ptr)->type->info.enums.enm[((struct yang_type *)ptr)->type->info.enums.count - 1];
331 ret = resolve_iffeature_compile(&e->iffeature[e->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
332 e->iffeature_size++;
333 break;
334 case BIT_KEYWORD:
335 b = &((struct yang_type *)ptr)->type->info.bits.bit[((struct yang_type *)ptr)->type->info.bits.count - 1];
336 ret = resolve_iffeature_compile(&b->iffeature[b->iffeature_size], exp, (struct lys_node *)((struct yang_type *)ptr)->type->parent, unres);
337 b->iffeature_size++;
338 break;
339 default:
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100340 n = (struct lys_node *) ptr;
Radek Krejci9ff0a922016-07-14 13:08:05 +0200341 ret = resolve_iffeature_compile(&n->iffeature[n->iffeature_size], exp, n, unres);
Michal Vaskoc5c26b02016-06-29 11:10:29 +0200342 n->iffeature_size++;
Pavol Vican8ff0e2e2016-08-09 09:09:10 +0200343 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100344 }
Radek Krejci9ff0a922016-07-14 13:08:05 +0200345 lydict_remove(module->ctx, exp);
Pavol Vicane1354e92016-02-09 14:02:09 +0100346
Radek Krejci9ff0a922016-07-14 13:08:05 +0200347 if (ret) {
Pavol Vicane1354e92016-02-09 14:02:09 +0100348 return EXIT_FAILURE;
349 }
350 return EXIT_SUCCESS;
351}
352
Pavol Vican4fb66c92016-03-17 10:32:27 +0100353int
Radek Krejci4372b4e2016-04-14 17:42:16 +0200354yang_check_flags(uint16_t *flags, uint16_t mask, char *what, char *where, uint16_t value, int shortint)
Pavol Vicane1354e92016-02-09 14:02:09 +0100355{
356 if (*flags & mask) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100357 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, what, where);
Pavol Vicane1354e92016-02-09 14:02:09 +0100358 return EXIT_FAILURE;
359 } else {
Radek Krejci4372b4e2016-04-14 17:42:16 +0200360 if (shortint) {
361 *((uint8_t *)flags) |= (uint8_t)value;
362 } else {
363 *flags |= value;
364 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100365 return EXIT_SUCCESS;
366 }
367}
368
Pavol Vicanbbdef532016-02-09 14:52:12 +0100369void *
370yang_read_identity(struct lys_module *module, char *value)
371{
372 struct lys_ident *ret;
373
374 ret = &module->ident[module->ident_size];
375 ret->name = lydict_insert_zc(module->ctx, value);
376 ret->module = module;
Pavol Vicand6cda452016-07-13 15:08:29 +0200377 if (dup_identities_check(ret->name, module)) {
378 lydict_remove(module->ctx, ret->name);
379 return NULL;
380 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100381 module->ident_size++;
382 return ret;
383}
384
385int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100386yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres)
Pavol Vicanbbdef532016-02-09 14:52:12 +0100387{
388 const char *exp;
389
Pavol Vican0adf01d2016-03-22 12:29:33 +0100390 exp = transform_schema2json(module, value);
Pavol Vicanbbdef532016-02-09 14:52:12 +0100391 free(value);
392 if (!exp) {
393 return EXIT_FAILURE;
394 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200395
396 /* temporarily decrement identity_size due to resolve base */
397 module->ident_size--;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100398 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp) == -1) {
Pavol Vicanbbdef532016-02-09 14:52:12 +0100399 lydict_remove(module->ctx, exp);
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200400 /* undo change identity_size */
401 module->ident_size++;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100402 return EXIT_FAILURE;
403 }
Pavol Vican4ffd0ab2016-08-27 16:35:04 +0200404 /* undo change identity_size */
405 module->ident_size++;
Pavol Vican44dde2c2016-02-10 11:18:14 +0100406
Pavol Vicanbbdef532016-02-09 14:52:12 +0100407 lydict_remove(module->ctx, exp);
408 return EXIT_SUCCESS;
409}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100410
411void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200412yang_read_must(struct lys_module *module, struct lys_node *node, char *value, enum yytokentype type)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100413{
414 struct lys_restr *retval;
415
416 switch (type) {
Pavol Vican8c82fa82016-02-10 13:13:24 +0100417 case CONTAINER_KEYWORD:
Pavol Vican096c6db2016-02-11 15:08:10 +0100418 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100419 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200420 case ANYDATA_KEYWORD:
Pavol Vican8c82fa82016-02-10 13:13:24 +0100421 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200422 retval = &((struct lys_node_anydata *)node)->must[((struct lys_node_anydata *)node)->must_size++];
Pavol Vican096c6db2016-02-11 15:08:10 +0100423 break;
424 case LEAF_KEYWORD:
425 retval = &((struct lys_node_leaf *)node)->must[((struct lys_node_leaf *)node)->must_size++];
Pavol Vican8c82fa82016-02-10 13:13:24 +0100426 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100427 case LEAF_LIST_KEYWORD:
428 retval = &((struct lys_node_leaflist *)node)->must[((struct lys_node_leaflist *)node)->must_size++];
429 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100430 case LIST_KEYWORD:
431 retval = &((struct lys_node_list *)node)->must[((struct lys_node_list *)node)->must_size++];
432 break;
Pavol Vican1003ead2016-03-02 12:24:52 +0100433 case REFINE_KEYWORD:
434 retval = &((struct lys_refine *)node)->must[((struct lys_refine *)node)->must_size++];
435 break;
Pavol Vican85f12022016-03-05 16:30:35 +0100436 case ADD_KEYWORD:
437 retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
438 memset(retval, 0, sizeof *retval);
439 break;
Pavol Vicanc1f5a502016-03-06 16:51:26 +0100440 case DELETE_KEYWORD:
441 retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
442 break;
Pavol Vican9b14b492016-08-09 14:55:10 +0200443 case NOTIFICATION_KEYWORD:
444 retval = &((struct lys_node_notif *)node)->must[((struct lys_node_notif *)node)->must_size++];
445 break;
446 case INPUT_KEYWORD:
447 retval = &((struct lys_node_inout *)node)->must[((struct lys_node_inout *)node)->must_size++];
448 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200449 default:
450 goto error;
451 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100452 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100453 retval->expr = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200454 if (!retval->expr) {
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100455 goto error;
456 }
457 free(value);
458 return retval;
459
460error:
461 free(value);
462 return NULL;
463}
464
465int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100466yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message)
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100467{
468 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100469
Pavol Vicandde090a2016-08-30 15:12:14 +0200470 if (message == ERROR_APP_TAG_KEYWORD) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100471 ret = yang_check_string(module, &save->eapptag, "error_app_tag", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100472 } else {
Pavol Vicandde090a2016-08-30 15:12:14 +0200473 ret = yang_check_string(module, &save->emsg, "error_message", what, value);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100474 }
475 return ret;
476}
Pavol Vicanb5687112016-02-09 22:35:59 +0100477
478int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100479yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value)
Pavol Vicanb5687112016-02-09 22:35:59 +0100480{
481 if (cont->presence) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100482 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, cont, "presence", "container");
Pavol Vicanb5687112016-02-09 22:35:59 +0100483 free(value);
484 return EXIT_FAILURE;
485 } else {
486 cont->presence = lydict_insert_zc(module->ctx, value);
487 return EXIT_SUCCESS;
488 }
489}
490
Pavol Vican235dbd42016-02-10 10:34:19 +0100491void *
Pavol Vican5f0316a2016-04-05 21:21:11 +0200492yang_read_when(struct lys_module *module, struct lys_node *node, enum yytokentype type, char *value)
Pavol Vican235dbd42016-02-10 10:34:19 +0100493{
494 struct lys_when *retval;
495
496 retval = calloc(1, sizeof *retval);
497 if (!retval) {
498 LOGMEM;
499 free(value);
500 return NULL;
501 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100502 retval->cond = transform_schema2json(module, value);
Michal Vasko508a50d2016-09-07 14:50:33 +0200503 if (!retval->cond) {
Pavol Vican235dbd42016-02-10 10:34:19 +0100504 goto error;
505 }
506 switch (type) {
507 case CONTAINER_KEYWORD:
508 if (((struct lys_node_container *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100509 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "container");
Pavol Vican235dbd42016-02-10 10:34:19 +0100510 goto error;
511 }
512 ((struct lys_node_container *)node)->when = retval;
513 break;
Pavol Vicandb7489e2016-08-23 17:23:39 +0200514 case ANYDATA_KEYWORD:
Pavol Vican1f06ba82016-02-10 17:39:50 +0100515 case ANYXML_KEYWORD:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200516 if (((struct lys_node_anydata *)node)->when) {
Pavol Vicandb7489e2016-08-23 17:23:39 +0200517 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", (type == ANYXML_KEYWORD) ? "anyxml" : "anydata");
Pavol Vican8c82fa82016-02-10 13:13:24 +0100518 goto error;
519 }
Radek Krejcibf2abff2016-08-23 15:51:52 +0200520 ((struct lys_node_anydata *)node)->when = retval;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100521 break;
Pavol Vican1f06ba82016-02-10 17:39:50 +0100522 case CHOICE_KEYWORD:
523 if (((struct lys_node_choice *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100524 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "choice");
Pavol Vican1f06ba82016-02-10 17:39:50 +0100525 goto error;
526 }
527 ((struct lys_node_choice *)node)->when = retval;
528 break;
Pavol Vicanbd098132016-02-11 10:56:49 +0100529 case CASE_KEYWORD:
530 if (((struct lys_node_case *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100531 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "case");
Pavol Vicanbd098132016-02-11 10:56:49 +0100532 goto error;
533 }
534 ((struct lys_node_case *)node)->when = retval;
535 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100536 case LEAF_KEYWORD:
537 if (((struct lys_node_leaf *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100538 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaf");
Pavol Vican096c6db2016-02-11 15:08:10 +0100539 goto error;
540 }
541 ((struct lys_node_leaf *)node)->when = retval;
542 break;
Pavol Vican339d4ad2016-02-12 12:49:22 +0100543 case LEAF_LIST_KEYWORD:
544 if (((struct lys_node_leaflist *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100545 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "leaflist");
Pavol Vican339d4ad2016-02-12 12:49:22 +0100546 goto error;
547 }
548 ((struct lys_node_leaflist *)node)->when = retval;
549 break;
Pavol Vican5de33492016-02-22 14:03:24 +0100550 case LIST_KEYWORD:
551 if (((struct lys_node_list *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100552 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "list");
Pavol Vican5de33492016-02-22 14:03:24 +0100553 goto error;
554 }
555 ((struct lys_node_list *)node)->when = retval;
556 break;
Pavol Vican14b18562016-03-01 16:04:29 +0100557 case USES_KEYWORD:
558 if (((struct lys_node_uses *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100559 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "uses");
Pavol Vican14b18562016-03-01 16:04:29 +0100560 goto error;
561 }
562 ((struct lys_node_uses *)node)->when = retval;
563 break;
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100564 case AUGMENT_KEYWORD:
565 if (((struct lys_node_augment *)node)->when) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100566 LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, node, "when", "augment");
Pavol Vican92fa0dc2016-03-02 14:20:39 +0100567 goto error;
568 }
569 ((struct lys_node_augment *)node)->when = retval;
570 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200571 default:
572 goto error;
573 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100574 }
575 free(value);
576 return retval;
577
578error:
579 free(value);
580 lys_when_free(module->ctx, retval);
581 return NULL;
582}
Pavol Vican8c82fa82016-02-10 13:13:24 +0100583
584void *
Pavol Vican7cadfe72016-02-11 12:33:34 +0100585yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
Pavol Vican8c82fa82016-02-10 13:13:24 +0100586{
Pavol Vican7cadfe72016-02-11 12:33:34 +0100587 struct lys_node *node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100588
Pavol Vican7cadfe72016-02-11 12:33:34 +0100589 node = calloc(1, sizeof_struct);
590 if (!node) {
Pavol Vicand1dbfda2016-03-21 10:03:58 +0100591 free(value);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100592 LOGMEM;
593 return NULL;
594 }
Pavol Vican531a9132016-03-03 10:10:09 +0100595 if (value) {
596 node->name = lydict_insert_zc(module->ctx, value);
597 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100598 node->module = module;
Pavol Vican7cadfe72016-02-11 12:33:34 +0100599 node->nodetype = nodetype;
600 node->prev = node;
601
602 /* insert the node into the schema tree */
603 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
Pavol Vican531a9132016-03-03 10:10:09 +0100604 if (value) {
605 lydict_remove(module->ctx, node->name);
606 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100607 free(node);
Pavol Vican8c82fa82016-02-10 13:13:24 +0100608 return NULL;
609 }
Pavol Vican7cadfe72016-02-11 12:33:34 +0100610 return node;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100611}
612
Pavol Vican8c793992016-07-15 10:44:57 +0200613void *
614yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
615{
616 struct lys_node *node;
617
Michal Vaskobb174852016-07-25 11:00:21 +0200618 if (module->version != 2) {
619 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");
620 return NULL;
621 }
622
Pavol Vican8c793992016-07-15 10:44:57 +0200623 for (node = parent; node; node = lys_parent(node)) {
624 if (node->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)
Pavol Vicanbbe77822016-07-15 12:53:07 +0200625 || ((node->nodetype == LYS_LIST) && !((struct lys_node_list *)node)->keys_size)) {
Pavol Vican8c793992016-07-15 10:44:57 +0200626 LOGVAL(LYE_INPAR, LY_VLOG_NONE, NULL, strnodetype(node->nodetype), "action");
627 return NULL;
628 }
629 }
630 return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
631}
632
Pavol Vican8c82fa82016-02-10 13:13:24 +0100633int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200634yang_read_default(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100635{
636 int ret;
637
638 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100639 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100640 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->dflt, "default", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100641 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100642 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100643 ret = yang_check_string(module, &((struct lys_tpdf *) node)->dflt, "default", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100644 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200645 default:
646 free(value);
647 LOGINT;
648 ret = EXIT_FAILURE;
649 break;
Pavol Vican096c6db2016-02-11 15:08:10 +0100650 }
651 return ret;
652}
653
654int
Pavol Vican5f0316a2016-04-05 21:21:11 +0200655yang_read_units(struct lys_module *module, void *node, char *value, enum yytokentype type)
Pavol Vican096c6db2016-02-11 15:08:10 +0100656{
657 int ret;
658
659 switch (type) {
Pavol Vican339d4ad2016-02-12 12:49:22 +0100660 case LEAF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100661 ret = yang_check_string(module, &((struct lys_node_leaf *) node)->units, "units", "leaf", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100662 break;
663 case LEAF_LIST_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100664 ret = yang_check_string(module, &((struct lys_node_leaflist *) node)->units, "units", "leaflist", value);
Pavol Vican339d4ad2016-02-12 12:49:22 +0100665 break;
Pavol Vican0df02b02016-03-01 10:28:50 +0100666 case TYPEDEF_KEYWORD:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100667 ret = yang_check_string(module, &((struct lys_tpdf *) node)->units, "units", "typedef", value);
Pavol Vican0df02b02016-03-01 10:28:50 +0100668 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +0200669 default:
670 free(value);
671 LOGINT;
672 ret = EXIT_FAILURE;
673 break;
Pavol Vican8c82fa82016-02-10 13:13:24 +0100674 }
675 return ret;
676}
Pavol Vican5de33492016-02-22 14:03:24 +0100677
678int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100679yang_read_key(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
Pavol Vican5de33492016-02-22 14:03:24 +0100680{
681 char *exp, *value;
682
683 exp = value = (char *) list->keys;
Pavol Vicanbbe77822016-07-15 12:53:07 +0200684 list->keys_size = 0;
Pavol Vican5de33492016-02-22 14:03:24 +0100685 while ((value = strpbrk(value, " \t\n"))) {
686 list->keys_size++;
687 while (isspace(*value)) {
688 value++;
689 }
690 }
691 list->keys_size++;
692 list->keys = calloc(list->keys_size, sizeof *list->keys);
693 if (!list->keys) {
694 LOGMEM;
695 goto error;
696 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100697 if (unres_schema_add_str(module, unres, list, UNRES_LIST_KEYS, exp) == -1) {
Pavol Vican5de33492016-02-22 14:03:24 +0100698 goto error;
699 }
700 free(exp);
701 return EXIT_SUCCESS;
702
703error:
704 free(exp);
705 return EXIT_FAILURE;
706}
707
708int
Pavol Vican0adf01d2016-03-22 12:29:33 +0100709yang_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 +0100710{
711 int i, j;
712 char *vaux;
Radek Krejcid09d1a52016-08-11 14:05:45 +0200713 struct unres_list_uniq *unique_info;
Pavol Vican85f12022016-03-05 16:30:35 +0100714
715 /* count the number of unique leafs in the value */
716 vaux = value;
717 while ((vaux = strpbrk(vaux, " \t\n"))) {
718 unique->expr_size++;
719 while (isspace(*vaux)) {
720 vaux++;
721 }
722 }
723 unique->expr_size++;
724 unique->expr = calloc(unique->expr_size, sizeof *unique->expr);
725 if (!unique->expr) {
726 LOGMEM;
727 goto error;
728 }
729
730 for (i = 0; i < unique->expr_size; i++) {
731 vaux = strpbrk(value, " \t\n");
732 if (!vaux) {
733 /* the last token, lydict_insert() will count its size on its own */
734 vaux = value;
735 }
736
737 /* store token into unique structure */
738 unique->expr[i] = lydict_insert(module->ctx, value, vaux - value);
739
740 /* check that the expression does not repeat */
741 for (j = 0; j < i; j++) {
742 if (ly_strequal(unique->expr[j], unique->expr[i], 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100743 LOGVAL(LYE_INARG, LY_VLOG_LYS, list, unique->expr[i], "unique");
744 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The identifier is not unique");
Pavol Vican85f12022016-03-05 16:30:35 +0100745 goto error;
746 }
747 }
748 /* try to resolve leaf */
749 if (unres) {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200750 unique_info = malloc(sizeof *unique_info);
751 unique_info->list = (struct lys_node *)list;
752 unique_info->expr = unique->expr[i];
753 unique_info->trg_type = &unique->trg_type;
754 if (unres_schema_add_node(module, unres, unique_info, UNRES_LIST_UNIQ, NULL) == -1) {
Pavol Vican18b10212016-04-11 15:41:52 +0200755 goto error;
756 }
Pavol Vican85f12022016-03-05 16:30:35 +0100757 } else {
Radek Krejcid09d1a52016-08-11 14:05:45 +0200758 if (resolve_unique((struct lys_node *)list, unique->expr[i], &unique->trg_type)) {
Pavol Vican85f12022016-03-05 16:30:35 +0100759 goto error;
760 }
761 }
762
763 /* move to next token */
764 value = vaux;
765 while(isspace(*value)) {
766 value++;
767 }
768 }
769
770 return EXIT_SUCCESS;
771
772error:
773 return EXIT_FAILURE;
774}
775
776int
Pavol Vican5de33492016-02-22 14:03:24 +0100777yang_read_unique(struct lys_module *module, struct lys_node_list *list, struct unres_schema *unres)
778{
779 uint8_t k;
Pavol Vican0adf01d2016-03-22 12:29:33 +0100780 char *str;
Pavol Vican5de33492016-02-22 14:03:24 +0100781
782 for(k=0; k<list->unique_size; k++) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100783 str = (char *)list->unique[k].expr;
784 if (yang_fill_unique(module, list, &list->unique[k], str, unres)) {
Pavol Vican5de33492016-02-22 14:03:24 +0100785 goto error;
786 }
Pavol Vican0adf01d2016-03-22 12:29:33 +0100787 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100788 }
789 return EXIT_SUCCESS;
790
791error:
Pavol Vican0adf01d2016-03-22 12:29:33 +0100792 free(str);
Pavol Vican5de33492016-02-22 14:03:24 +0100793 return EXIT_FAILURE;
Pavol Vican73e7c992016-02-24 12:18:05 +0100794}
795
Pavol Vican07f220f2016-09-02 13:04:37 +0200796int
Pavol Vican81344ac2016-09-02 14:23:06 +0200797yang_read_leafref_path(struct lys_module *module, struct yang_type *stype, char *value)
798{
799 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
800 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
801 goto error;
802 }
803 if (stype->type->info.lref.path) {
804 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "path", "type");
805 goto error;
806 }
807 stype->type->info.lref.path = lydict_insert_zc(module->ctx, value);
808 stype->base = LY_TYPE_LEAFREF;
809 return EXIT_SUCCESS;
810
811error:
812 free(value);
813 return EXIT_FAILURE;
814}
815
816int
817yang_read_require_instance(struct yang_type *stype, int req)
818{
819 if (stype->base && (stype->base != LY_TYPE_LEAFREF)) {
820 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "require-instance");
821 return EXIT_FAILURE;
822 }
823 if (stype->type->info.lref.req) {
824 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "require-instance", "type");
825 return EXIT_FAILURE;
826 }
827 stype->type->info.lref.req = req;
828 stype->base = LY_TYPE_LEAFREF;
829 return EXIT_SUCCESS;
830}
831
832int
Pavol Vican07f220f2016-09-02 13:04:37 +0200833yang_read_identyref(struct lys_module *module, struct yang_type *stype, char *expr, struct unres_schema *unres)
Pavol Vican1ff0e222016-02-26 12:27:01 +0100834{
Pavol Vican07f220f2016-09-02 13:04:37 +0200835 const char *value;
836 int rc;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100837
Pavol Vican07f220f2016-09-02 13:04:37 +0200838 if (stype->base && stype->base != LY_TYPE_IDENT) {
839 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
840 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100841 }
Pavol Vican07f220f2016-09-02 13:04:37 +0200842
843 stype->base = LY_TYPE_IDENT;
844 /* store in the JSON format */
845 value = transform_schema2json(module, expr);
846 free(expr);
847
848 if (!value) {
849 return EXIT_FAILURE;
850 }
851 rc = unres_schema_add_str(module, unres, stype->type, UNRES_TYPE_IDENTREF, value);
Pavol Vican1ff0e222016-02-26 12:27:01 +0100852 lydict_remove(module->ctx, value);
853
854 if (rc == -1) {
Pavol Vican07f220f2016-09-02 13:04:37 +0200855 return EXIT_FAILURE;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100856 }
857
Pavol Vican07f220f2016-09-02 13:04:37 +0200858 return EXIT_SUCCESS;
Pavol Vican1ff0e222016-02-26 12:27:01 +0100859}
860
Pavol Vican73e7c992016-02-24 12:18:05 +0100861int
Radek Krejci3a5501d2016-07-18 22:03:34 +0200862yang_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 +0100863{
Pavol Vican81344ac2016-09-02 14:23:06 +0200864 int i, j, rc, ret = -1;
865 int8_t req;
Pavol Vican73e7c992016-02-24 12:18:05 +0100866 const char *name, *value;
Pavol Vican8bd72e42016-08-29 09:53:05 +0200867 LY_DATA_TYPE base = 0;
Radek Krejci3a5501d2016-07-18 22:03:34 +0200868 struct lys_node *siter;
Pavol Vican8ad2e0d2016-08-09 12:56:19 +0200869 struct lys_type *dertype;
870 struct lys_type_enum *enms_sc = NULL;
871 struct lys_type_bit *bits_sc = NULL;
872 struct lys_type_bit bit_tmp;
873
Pavol Vican0adf01d2016-03-22 12:29:33 +0100874 value = transform_schema2json(module, typ->name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100875 if (!value) {
876 goto error;
877 }
878
879 i = parse_identifier(value);
880 if (i < 1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100881 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, value[-i], &value[-i]);
Pavol Vican73e7c992016-02-24 12:18:05 +0100882 lydict_remove(module->ctx, value);
883 goto error;
884 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200885 /* module name */
Pavol Vican73e7c992016-02-24 12:18:05 +0100886 name = value;
887 if (value[i]) {
888 typ->type->module_name = lydict_insert(module->ctx, value, i);
889 name += i;
890 if ((name[0] != ':') || (parse_identifier(name + 1) < 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100891 LOGVAL(LYE_INCHAR, LY_VLOG_NONE, NULL, name[0], name);
Pavol Vican73e7c992016-02-24 12:18:05 +0100892 lydict_remove(module->ctx, value);
893 goto error;
894 }
895 ++name;
896 }
897
898 rc = resolve_superior_type(name, typ->type->module_name, module, parent, &typ->type->der);
Pavol Vican73e7c992016-02-24 12:18:05 +0100899 if (rc == -1) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100900 LOGVAL(LYE_INMOD, LY_VLOG_NONE, NULL, typ->type->module_name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200901 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100902 goto error;
903
Michal Vasko01c6fd22016-05-20 11:43:05 +0200904 /* the type could not be resolved or it was resolved to an unresolved typedef or leafref */
Pavol Vican73e7c992016-02-24 12:18:05 +0100905 } else if (rc == EXIT_FAILURE) {
Michal Vasko01c6fd22016-05-20 11:43:05 +0200906 LOGVAL(LYE_NORESOLV, LY_VLOG_NONE, NULL, "type", name);
Radek Krejci408ab2f2016-06-06 15:27:10 +0200907 lydict_remove(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +0100908 ret = EXIT_FAILURE;
909 goto error;
910 }
Radek Krejci408ab2f2016-06-06 15:27:10 +0200911 lydict_remove(module->ctx, value);
Radek Krejcic13db382016-08-16 10:52:42 +0200912
913 if (typ->type->base == LY_TYPE_INGRP) {
914 /* resolved type in grouping, decrease the grouping's nacm number to indicate that one less
915 * unresolved item left inside the grouping */
916 for (siter = parent; siter && (siter->nodetype != LYS_GROUPING); siter = lys_parent(siter));
917 if (siter) {
918 if (!((struct lys_node_grp *)siter)->nacm) {
919 LOGINT;
920 goto error;
921 }
922 ((struct lys_node_grp *)siter)->nacm--;
923 } else {
924 LOGINT;
925 goto error;
926 }
927 }
Pavol Vicanfdab9f92016-09-07 15:23:27 +0200928
929 /* check status */
930 if (lyp_check_status(typ->type->parent->flags, typ->type->parent->module, typ->type->parent->name,
931 typ->type->der->flags, typ->type->der->module, typ->type->der->name, parent)) {
932 goto error;
933 }
934
Pavol Vican8bd72e42016-08-29 09:53:05 +0200935 base = typ->base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100936 typ->type->base = typ->type->der->type.base;
937 if (base == 0) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100938 base = typ->type->der->type.base;
Pavol Vican73e7c992016-02-24 12:18:05 +0100939 }
940 switch (base) {
941 case LY_TYPE_STRING:
942 if (typ->type->base == LY_TYPE_BINARY) {
943 if (typ->type->info.str.pat_count) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100944 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Binary type could not include pattern statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +0100945 goto error;
946 }
947 typ->type->info.binary.length = typ->type->info.str.length;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100948 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 +0100949 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.binary.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100950 goto error;
951 }
952 } else if (typ->type->base == LY_TYPE_STRING) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100953 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 +0100954 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.str.length->expr, "length");
Pavol Vican73e7c992016-02-24 12:18:05 +0100955 goto error;
956 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100957 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200958 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100959 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +0100960 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100961 break;
962 case LY_TYPE_DEC64:
963 if (typ->type->base == LY_TYPE_DEC64) {
Pavol Vican07ea68d2016-02-25 12:01:37 +0100964 if (typ->type->info.dec64.range && lyp_check_length_range(typ->type->info.dec64.range->expr, typ->type)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100965 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.dec64.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100966 goto error;
967 }
Pavol Vican07ea68d2016-02-25 12:01:37 +0100968 /* mandatory sub-statement(s) check */
969 if (!typ->type->info.dec64.dig && !typ->type->der->type.der) {
970 /* decimal64 type directly derived from built-in type requires fraction-digits */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100971 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100972 goto error;
973 }
974 if (typ->type->info.dec64.dig && typ->type->der->type.der) {
975 /* type is not directly derived from buit-in type and fraction-digits statement is prohibited */
Pavol Vican0adf01d2016-03-22 12:29:33 +0100976 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +0100977 goto error;
978 }
Radek Krejcib51d5932016-09-08 14:02:52 +0200979
980 /* copy fraction-digits specification from parent type for easier internal use */
981 if (typ->type->der->type.der) {
982 typ->type->info.dec64.dig = typ->type->der->type.info.dec64.dig;
983 typ->type->info.dec64.div = typ->type->der->type.info.dec64.div;
984 }
Pavol Vicanaff5c802016-02-24 15:56:45 +0100985 } else if (typ->type->base >= LY_TYPE_INT8 && typ->type->base <=LY_TYPE_UINT64) {
986 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +0100987 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Numerical type could not include fraction statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100988 goto error;
989 }
990 typ->type->info.num.range = typ->type->info.dec64.range;
Pavol Vican07ea68d2016-02-25 12:01:37 +0100991 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 +0100992 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, typ->type->info.num.range->expr, "range");
Pavol Vicanaff5c802016-02-24 15:56:45 +0100993 goto error;
994 }
995 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +0200996 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicanaff5c802016-02-24 15:56:45 +0100997 goto error;
998 }
999 break;
Pavol Vican79a763d2016-02-25 15:41:27 +01001000 case LY_TYPE_ENUM:
1001 if (typ->type->base != LY_TYPE_ENUM) {
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 Vican79a763d2016-02-25 15:41:27 +01001003 goto error;
1004 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001005 dertype = &typ->type->der->type;
1006
1007 if (!dertype->der) {
1008 if (!typ->type->info.enums.count) {
1009 /* type is derived directly from buit-in enumeartion type and enum statement is required */
1010 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "enum", "type");
1011 goto error;
1012 }
1013 } else {
1014 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1015 if (module->version < 2 && typ->type->info.enums.count) {
1016 /* type is not directly derived from built-in enumeration type and enum statement is prohibited
1017 * in YANG 1.0, since YANG 1.1 enum statements can be used to restrict the base enumeration type */
1018 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "enum");
1019 goto error;
1020 }
1021
1022 /* restricted enumeration type - the name MUST be used in the base type */
1023 enms_sc = dertype->info.enums.enm;
1024 for(i = 0; i < typ->type->info.enums.count; i++) {
1025 for (j = 0; j < dertype->info.enums.count; j++) {
1026 if (ly_strequal(enms_sc[j].name, typ->type->info.enums.enm[i].name, 1)) {
1027 break;
1028 }
1029 }
1030 if (j == dertype->info.enums.count) {
1031 LOGVAL(LYE_ENUM_INNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
1032 goto error;
1033 }
1034
1035 if (typ->type->info.enums.enm[i].flags & LYS_AUTOASSIGNED) {
1036 /* automatically assign value from base type */
1037 typ->type->info.enums.enm[i].value = enms_sc[j].value;
1038 } else {
1039 /* check that the assigned value corresponds to the original
1040 * value of the enum in the base type */
1041 if (typ->type->info.enums.enm[i].value != enms_sc[j].value) {
1042 /* typ->type->info.enums.enm[i].value - assigned value in restricted enum
1043 * enms_sc[j].value - value assigned to the corresponding enum (detected above) in base type */
1044 LOGVAL(LYE_ENUM_INVAL, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].value,
1045 typ->type->info.enums.enm[i].name, enms_sc[j].value);
1046 goto error;
1047 }
1048 }
1049 }
Pavol Vican79a763d2016-02-25 15:41:27 +01001050 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001051 break;
Pavol Vican03a59442016-03-21 15:23:45 +01001052 case LY_TYPE_BITS:
1053 if (typ->type->base != LY_TYPE_BITS) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001054 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican03a59442016-03-21 15:23:45 +01001055 goto error;
1056 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001057 dertype = &typ->type->der->type;
1058
1059 if (!dertype->der) {
1060 if (!typ->type->info.bits.count) {
1061 /* type is derived directly from buit-in bits type and bit statement is required */
1062 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "bit", "type");
1063 goto error;
1064 }
1065 } else {
1066 for (; !dertype->info.enums.count; dertype = &dertype->der->type);
1067 if (module->version < 2 && typ->type->info.bits.count) {
1068 /* type is not directly derived from buit-in bits type and bit statement is prohibited,
1069 * since YANG 1.1 the bit statements can be used to restrict the base bits type */
1070 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "bit");
1071 goto error;
1072 }
1073
1074 bits_sc = dertype->info.bits.bit;
1075 for (i = 0; i < typ->type->info.bits.count; i++) {
1076 for (j = 0; j < dertype->info.bits.count; j++) {
1077 if (ly_strequal(bits_sc[j].name, typ->type->info.bits.bit[i].name, 1)) {
1078 break;
1079 }
1080 }
1081 if (j == dertype->info.bits.count) {
1082 LOGVAL(LYE_BITS_INNAME, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].name);
1083 goto error;
1084 }
1085
1086 /* restricted bits type */
1087 if (typ->type->info.bits.bit[i].flags & LYS_AUTOASSIGNED) {
1088 /* automatically assign position from base type */
1089 typ->type->info.bits.bit[i].pos = bits_sc[j].pos;
1090 } else {
1091 /* check that the assigned position corresponds to the original
1092 * position of the bit in the base type */
1093 if (typ->type->info.bits.bit[i].pos != bits_sc[j].pos) {
1094 /* typ->type->info.bits.bit[i].pos - assigned position in restricted bits
1095 * bits_sc[j].pos - position assigned to the corresponding bit (detected above) in base type */
1096 LOGVAL(LYE_BITS_INVAL, LY_VLOG_NONE, NULL, typ->type->info.bits.bit[i].pos,
1097 typ->type->info.bits.bit[i].name, bits_sc[j].pos);
1098 goto error;
1099 }
1100 }
1101 }
Pavol Vican03a59442016-03-21 15:23:45 +01001102 }
Pavol Vican8ad2e0d2016-08-09 12:56:19 +02001103
1104 for (i = typ->type->info.bits.count - 1; i > 0; i--) {
1105 j = i;
1106
1107 /* keep them ordered by position */
1108 while (j && typ->type->info.bits.bit[j - 1].pos > typ->type->info.bits.bit[j].pos) {
1109 /* switch them */
1110 memcpy(&bit_tmp, &typ->type->info.bits.bit[j], sizeof bit_tmp);
1111 memcpy(&typ->type->info.bits.bit[j], &typ->type->info.bits.bit[j - 1], sizeof bit_tmp);
1112 memcpy(&typ->type->info.bits.bit[j - 1], &bit_tmp, sizeof bit_tmp);
1113 j--;
1114 }
Pavol Vican03a59442016-03-21 15:23:45 +01001115 }
1116 break;
Pavol Vican1ff0e222016-02-26 12:27:01 +01001117 case LY_TYPE_LEAFREF:
Pavol Vican81344ac2016-09-02 14:23:06 +02001118 if (typ->type->base == LY_TYPE_INST) {
1119 if (typ->type->info.lref.path) {
1120 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1121 goto error;
1122 }
1123 if ((req = typ->type->info.lref.req)) {
1124 typ->type->info.inst.req = req;
1125 }
1126 } else if (typ->type->base == LY_TYPE_LEAFREF) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001127 /* flag resolving for later use */
1128 if (!tpdftype) {
1129 for (siter = parent; siter && siter->nodetype != LYS_GROUPING; siter = lys_parent(siter));
1130 if (siter) {
1131 /* just a flag - do not resolve */
1132 tpdftype = 1;
1133 }
1134 }
1135
Pavol Vican6b072512016-04-04 10:50:21 +02001136 if (typ->type->info.lref.path) {
Pavol Vican894ee0f2016-08-30 15:29:46 +02001137 if (typ->type->der->type.der) {
1138 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "path");
1139 goto error;
1140 }
Pavol Vican191613a2016-02-26 16:21:32 +01001141 value = typ->type->info.lref.path;
1142 /* store in the JSON format */
Pavol Vican0adf01d2016-03-22 12:29:33 +01001143 typ->type->info.lref.path = transform_schema2json(module, value);
Pavol Vican191613a2016-02-26 16:21:32 +01001144 lydict_remove(module->ctx, value);
1145 if (!typ->type->info.lref.path) {
1146 goto error;
1147 }
Radek Krejci3a5501d2016-07-18 22:03:34 +02001148 /* try to resolve leafref path only when this is instantiated
1149 * leaf, so it is not:
1150 * - typedef's type,
1151 * - in grouping definition,
1152 * - just instantiated in a grouping definition,
1153 * because in those cases the nodes referenced in path might not be present
1154 * and it is not a bug. */
1155 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Pavol Vican191613a2016-02-26 16:21:32 +01001156 goto error;
1157 }
Pavol Vican6b072512016-04-04 10:50:21 +02001158 } else if (!typ->type->der->type.der) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001159 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "path", "type");
Pavol Vican191613a2016-02-26 16:21:32 +01001160 goto error;
Michal Vasko01c6fd22016-05-20 11:43:05 +02001161 } else {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001162 /* copy leafref definition into the derived type */
1163 typ->type->info.lref.path = lydict_insert(module->ctx, typ->type->der->type.info.lref.path, 0);
1164 /* and resolve the path at the place we are (if not in grouping/typedef) */
1165 if (!tpdftype && unres_schema_add_node(module, unres, typ->type, UNRES_TYPE_LEAFREF, parent) == -1) {
Michal Vasko01c6fd22016-05-20 11:43:05 +02001166 goto error;
1167 }
Radek Krejci742be352016-07-17 12:18:54 +02001168
Michal Vasko01c6fd22016-05-20 11:43:05 +02001169 /* add pointer to leafref target, only on leaves (not in typedefs) */
Radek Krejci3a5501d2016-07-18 22:03:34 +02001170 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 +02001171 goto error;
1172 }
Pavol Vican191613a2016-02-26 16:21:32 +01001173 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001174 } else {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001175 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001176 goto error;
1177 }
1178 break;
1179 case LY_TYPE_IDENT:
Pavol Vican07f220f2016-09-02 13:04:37 +02001180 if (typ->type->base != LY_TYPE_IDENT) {
1181 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vican1ff0e222016-02-26 12:27:01 +01001182 goto error;
1183 }
Pavol Vican07f220f2016-09-02 13:04:37 +02001184 if (typ->type->der->type.der) {
1185 if (typ->type->info.ident.ref) {
1186 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1187 goto error;
1188 }
1189 } else {
1190 if (!typ->type->info.ident.ref) {
1191 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "base", "type");
1192 goto error;
1193 }
1194 }
Pavol Vican1ff0e222016-02-26 12:27:01 +01001195 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001196 case LY_TYPE_UNION:
1197 if (typ->type->base != LY_TYPE_UNION) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001198 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001199 goto error;
1200 }
1201 if (!typ->type->info.uni.types) {
1202 if (typ->type->der->type.der) {
1203 /* this is just a derived type with no additional type specified/required */
1204 break;
1205 }
Pavol Vican0adf01d2016-03-22 12:29:33 +01001206 LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "(union) type");
Pavol Vicana4f045a2016-02-29 15:01:20 +01001207 goto error;
1208 }
1209 for (i = 0; i < typ->type->info.uni.count; i++) {
Radek Krejci3a5501d2016-07-18 22:03:34 +02001210 if (unres_schema_add_node(module, unres, &typ->type->info.uni.types[i],
Michal Vasko5d631402016-07-21 13:15:15 +02001211 tpdftype ? UNRES_TYPE_DER_TPDF : UNRES_TYPE_DER, parent) == -1) {
Pavol Vicana4f045a2016-02-29 15:01:20 +01001212 goto error;
1213 }
1214 if (typ->type->info.uni.types[i].base == LY_TYPE_EMPTY) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001215 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "empty", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001216 goto error;
1217 } else if (typ->type->info.uni.types[i].base == LY_TYPE_LEAFREF) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001218 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "leafref", typ->name);
Pavol Vicana4f045a2016-02-29 15:01:20 +01001219 goto error;
1220 }
1221 }
1222 break;
Pavol Vicana1827962016-02-29 15:39:42 +01001223
1224 default:
1225 if (base >= LY_TYPE_BINARY && base <= LY_TYPE_UINT64) {
1226 if (typ->type->base != base) {
Pavol Vican933aa5a2016-04-09 21:05:46 +02001227 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", typ->type->parent->name);
Pavol Vicana1827962016-02-29 15:39:42 +01001228 goto error;
1229 }
1230 } else {
1231 LOGINT;
1232 goto error;
1233 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001234 }
1235 return EXIT_SUCCESS;
1236
1237error:
1238 if (typ->type->module_name) {
1239 lydict_remove(module->ctx, typ->type->module_name);
1240 typ->type->module_name = NULL;
1241 }
Pavol Vican8bd72e42016-08-29 09:53:05 +02001242 if (base) {
1243 typ->type->base = base;
1244 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001245 return ret;
1246}
1247
1248void *
Pavol Vican5f0316a2016-04-05 21:21:11 +02001249yang_read_type(struct lys_module *module, void *parent, char *value, enum yytokentype type)
Pavol Vican73e7c992016-02-24 12:18:05 +01001250{
1251 struct yang_type *typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001252 struct type_deviation *dev;
1253 struct lys_tpdf *tmp_parent;
Pavol Vican73e7c992016-02-24 12:18:05 +01001254
Pavol Vicand01d8ae2016-03-01 10:45:59 +01001255 typ = calloc(1, sizeof *typ);
1256 if (!typ) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001257 LOGMEM;
1258 return NULL;
1259 }
Pavol Vican73e7c992016-02-24 12:18:05 +01001260
1261 typ->flags = LY_YANG_STRUCTURE_FLAG;
1262 switch (type) {
1263 case LEAF_KEYWORD:
1264 ((struct lys_node_leaf *)parent)->type.der = (struct lys_tpdf *)typ;
1265 ((struct lys_node_leaf *)parent)->type.parent = (struct lys_tpdf *)parent;
1266 typ->type = &((struct lys_node_leaf *)parent)->type;
1267 break;
Pavol Vicana55992a2016-03-01 13:37:17 +01001268 case LEAF_LIST_KEYWORD:
1269 ((struct lys_node_leaflist *)parent)->type.der = (struct lys_tpdf *)typ;
1270 ((struct lys_node_leaflist *)parent)->type.parent = (struct lys_tpdf *)parent;
1271 typ->type = &((struct lys_node_leaflist *)parent)->type;
1272 break;
Pavol Vicana4f045a2016-02-29 15:01:20 +01001273 case UNION_KEYWORD:
1274 ((struct lys_type *)parent)->der = (struct lys_tpdf *)typ;
1275 typ->type = (struct lys_type *)parent;
1276 break;
Pavol Vican0df02b02016-03-01 10:28:50 +01001277 case TYPEDEF_KEYWORD:
1278 ((struct lys_tpdf *)parent)->type.der = (struct lys_tpdf *)typ;
1279 typ->type = &((struct lys_tpdf *)parent)->type;
Pavol Vican4766aca2016-03-07 12:42:36 +01001280 break;
1281 case REPLACE_KEYWORD:
1282 /* deviation replace type*/
1283 dev = (struct type_deviation *)parent;
1284 if (dev->deviate->type) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001285 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "type", "deviation");
Pavol Vican4766aca2016-03-07 12:42:36 +01001286 goto error;
1287 }
1288 /* check target node type */
1289 if (dev->target->nodetype == LYS_LEAF) {
1290 typ->type = &((struct lys_node_leaf *)dev->target)->type;
1291 } else if (dev->target->nodetype == LYS_LEAFLIST) {
1292 typ->type = &((struct lys_node_leaflist *)dev->target)->type;
1293 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001294 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "type");
1295 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"type\" property.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001296 goto error;
1297 }
1298
1299 /* remove type and initialize it */
1300 lys_type_free(module->ctx, typ->type);
1301 tmp_parent = typ->type->parent;
1302 memset(typ->type, 0, sizeof *typ->type);
1303 typ->type->parent = tmp_parent;
1304
1305 /* replace it with the value specified in deviation */
1306 /* HACK for unres */
1307 typ->type->der = (struct lys_tpdf *)typ;
1308 dev->deviate->type = typ->type;
1309 break;
Pavol Vican5f0316a2016-04-05 21:21:11 +02001310 default:
1311 goto error;
1312 break;
Pavol Vican73e7c992016-02-24 12:18:05 +01001313 }
Pavol Vican5f0316a2016-04-05 21:21:11 +02001314 typ->name = lydict_insert_zc(module->ctx, value);
Pavol Vican73e7c992016-02-24 12:18:05 +01001315 return typ;
Pavol Vican4766aca2016-03-07 12:42:36 +01001316
1317error:
Pavol Vican5f0316a2016-04-05 21:21:11 +02001318 free(value);
Pavol Vican4766aca2016-03-07 12:42:36 +01001319 free(typ);
1320 return NULL;
Pavol Vican73e7c992016-02-24 12:18:05 +01001321}
1322
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001323void
1324yang_delete_type(struct lys_module *module, struct yang_type *stype)
1325{
1326 int i;
1327
1328 stype->type->base = stype->base;
1329 stype->type->der = NULL;
1330 lydict_remove(module->ctx, stype->name);
1331 if (stype->base == LY_TYPE_UNION) {
1332 for (i = 0; i < stype->type->info.uni.count; i++) {
1333 if (stype->type->info.uni.types[i].der) {
1334 yang_delete_type(module, (struct yang_type *)stype->type->info.uni.types[i].der);
1335 }
1336 }
1337 }
1338 free(stype);
1339}
1340
Pavol Vican73e7c992016-02-24 12:18:05 +01001341void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001342yang_read_length(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican73e7c992016-02-24 12:18:05 +01001343{
1344 struct lys_restr **length;
1345
Pavol Vican6b072512016-04-04 10:50:21 +02001346 if (typ->base == 0 || typ->base == LY_TYPE_STRING) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001347 length = &typ->type->info.str.length;
Pavol Vican6b072512016-04-04 10:50:21 +02001348 typ->base = LY_TYPE_STRING;
1349 } else if (typ->base == LY_TYPE_BINARY) {
Pavol Vican73e7c992016-02-24 12:18:05 +01001350 length = &typ->type->info.binary.length;
1351 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001352 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected length statement.");
Pavol Vican73e7c992016-02-24 12:18:05 +01001353 goto error;
1354 }
1355
1356 if (*length) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001357 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "length", "type");
Pavol Vicanbe9e3832016-04-28 02:21:37 +02001358 goto error;
Pavol Vican73e7c992016-02-24 12:18:05 +01001359 }
1360 *length = calloc(1, sizeof **length);
1361 if (!*length) {
1362 LOGMEM;
1363 goto error;
1364 }
1365 (*length)->expr = lydict_insert_zc(module->ctx, value);
1366 return *length;
1367
1368error:
1369 free(value);
1370 return NULL;
1371
1372}
Pavol Vican1c203db2016-02-24 14:05:23 +01001373
Pavol Vican6eecf302016-08-10 11:09:05 +02001374int
1375yang_read_pattern(struct lys_module *module, struct lys_restr *pattern, char *value, char modifier)
Pavol Vican1c203db2016-02-24 14:05:23 +01001376{
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001377 char *buf;
1378 size_t len;
1379
Michal Vasko0aee5c12016-06-17 14:27:26 +02001380 if (lyp_check_pattern(value, NULL)) {
Pavol Vican1c203db2016-02-24 14:05:23 +01001381 free(value);
Pavol Vican6eecf302016-08-10 11:09:05 +02001382 return EXIT_FAILURE;
Pavol Vican1c203db2016-02-24 14:05:23 +01001383 }
Pavol Vican1c203db2016-02-24 14:05:23 +01001384
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001385 len = strlen(value);
1386 buf = malloc((len + 2) * sizeof *buf); /* modifier byte + value + terminating NULL byte */
Pavol Vican6eecf302016-08-10 11:09:05 +02001387
1388 if (!buf) {
1389 LOGMEM;
1390 free(value);
1391 return EXIT_FAILURE;
1392 }
1393
1394 buf[0] = modifier;
Radek Krejci0d23e7a2016-08-04 12:46:17 +02001395 strcpy(&buf[1], value);
1396 free(value);
1397
Pavol Vican6eecf302016-08-10 11:09:05 +02001398 pattern->expr = lydict_insert_zc(module->ctx, buf);
1399 return EXIT_SUCCESS;
Pavol Vican1c203db2016-02-24 14:05:23 +01001400}
Pavol Vicanaff5c802016-02-24 15:56:45 +01001401
1402void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001403yang_read_range(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vicanaff5c802016-02-24 15:56:45 +01001404{
Pavol Vican6b072512016-04-04 10:50:21 +02001405 if (typ->base != 0 && typ->base != LY_TYPE_DEC64) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001406 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected range statement.");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001407 goto error;
1408 }
Pavol Vican6b072512016-04-04 10:50:21 +02001409 typ->base = LY_TYPE_DEC64;
Pavol Vicanaff5c802016-02-24 15:56:45 +01001410 if (typ->type->info.dec64.range) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001411 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "range", "type");
Pavol Vicanaff5c802016-02-24 15:56:45 +01001412 goto error;
1413 }
1414 typ->type->info.dec64.range = calloc(1, sizeof *typ->type->info.dec64.range);
1415 if (!typ->type->info.dec64.range) {
1416 LOGMEM;
1417 goto error;
1418 }
1419 typ->type->info.dec64.range->expr = lydict_insert_zc(module->ctx, value);
1420 return typ->type->info.dec64.range;
1421
1422error:
1423 free(value);
1424 return NULL;
1425}
Pavol Vican07ea68d2016-02-25 12:01:37 +01001426
1427int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001428yang_read_fraction(struct yang_type *typ, uint32_t value)
Pavol Vican07ea68d2016-02-25 12:01:37 +01001429{
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001430 unsigned int i;
1431
Pavol Vican6b072512016-04-04 10:50:21 +02001432 if (typ->base == 0 || typ->base == LY_TYPE_DEC64) {
1433 typ->base = LY_TYPE_DEC64;
Pavol Vican07ea68d2016-02-25 12:01:37 +01001434 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001435 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected fraction-digits statement.");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001436 goto error;
1437 }
1438 if (typ->type->info.dec64.dig) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001439 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "fraction-digits", "type");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001440 goto error;
1441 }
1442 /* range check */
1443 if (value < 1 || value > 18) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001444 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", value, "fraction-digits");
Pavol Vican07ea68d2016-02-25 12:01:37 +01001445 goto error;
1446 }
1447 typ->type->info.dec64.dig = value;
Radek Krejci8c3b4b62016-06-17 14:32:12 +02001448 typ->type->info.dec64.div = 10;
1449 for (i = 1; i < value; i++) {
1450 typ->type->info.dec64.div *= 10;
1451 }
Pavol Vican07ea68d2016-02-25 12:01:37 +01001452 return EXIT_SUCCESS;
1453
1454error:
1455 return EXIT_FAILURE;
1456}
Pavol Vican79a763d2016-02-25 15:41:27 +01001457
1458void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001459yang_read_enum(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican79a763d2016-02-25 15:41:27 +01001460{
1461 struct lys_type_enum *enm;
1462 int i;
1463
Pavol Vicanc6662412016-08-30 08:06:28 +02001464 if (!value[0]) {
1465 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "enum name");
1466 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Enum name must not be empty.");
1467 free(value);
1468 goto error;
1469 }
1470
Pavol Vican79a763d2016-02-25 15:41:27 +01001471 enm = &typ->type->info.enums.enm[typ->type->info.enums.count];
1472 enm->name = lydict_insert_zc(module->ctx, value);
1473
1474 /* the assigned name MUST NOT have any leading or trailing whitespace characters */
1475 if (isspace(enm->name[0]) || isspace(enm->name[strlen(enm->name) - 1])) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001476 LOGVAL(LYE_ENUM_WS, LY_VLOG_NONE, NULL, enm->name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001477 goto error;
1478 }
1479
1480 /* check the name uniqueness */
1481 for (i = 0; i < typ->type->info.enums.count; i++) {
1482 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 +01001483 LOGVAL(LYE_ENUM_DUPNAME, LY_VLOG_NONE, NULL, typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001484 goto error;
1485 }
1486 }
1487
1488 typ->type->info.enums.count++;
1489 return enm;
1490
1491error:
1492 typ->type->info.enums.count++;
1493 return NULL;
1494}
1495
1496int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001497yang_check_enum(struct yang_type *typ, struct lys_type_enum *enm, int64_t *value, int assign)
Pavol Vican79a763d2016-02-25 15:41:27 +01001498{
1499 int i, j;
1500
1501 if (!assign) {
1502 /* assign value automatically */
1503 if (*value > INT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001504 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "2147483648", "enum/value");
Pavol Vican79a763d2016-02-25 15:41:27 +01001505 goto error;
1506 }
1507 enm->value = *value;
1508 enm->flags |= LYS_AUTOASSIGNED;
1509 (*value)++;
Pavol Vican5de389c2016-08-30 08:55:15 +02001510 } else if (typ->type->info.enums.enm == enm) {
1511 /* change value, which is assigned automatically, if first enum has value. */
1512 *value = typ->type->info.enums.enm[0].value;
1513 (*value)++;
Pavol Vican79a763d2016-02-25 15:41:27 +01001514 }
1515
1516 /* check that the value is unique */
1517 j = typ->type->info.enums.count-1;
1518 for (i = 0; i < j; i++) {
1519 if (typ->type->info.enums.enm[i].value == typ->type->info.enums.enm[j].value) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001520 LOGVAL(LYE_ENUM_DUPVAL, LY_VLOG_NONE, NULL,
Radek Krejcie663e012016-08-01 17:12:34 +02001521 typ->type->info.enums.enm[j].value, typ->type->info.enums.enm[j].name,
1522 typ->type->info.enums.enm[i].name);
Pavol Vican79a763d2016-02-25 15:41:27 +01001523 goto error;
1524 }
1525 }
1526
1527 return EXIT_SUCCESS;
1528
1529error:
1530 return EXIT_FAILURE;
1531}
Pavol Vican9887c682016-02-29 11:32:01 +01001532
1533void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001534yang_read_bit(struct lys_module *module, struct yang_type *typ, char *value)
Pavol Vican9887c682016-02-29 11:32:01 +01001535{
1536 int i;
1537 struct lys_type_bit *bit;
1538
1539 bit = &typ->type->info.bits.bit[typ->type->info.bits.count];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001540 if (lyp_check_identifier(value, LY_IDENT_SIMPLE, NULL, NULL)) {
Pavol Vican9887c682016-02-29 11:32:01 +01001541 free(value);
1542 goto error;
1543 }
1544 bit->name = lydict_insert_zc(module->ctx, value);
1545
1546 /* check the name uniqueness */
1547 for (i = 0; i < typ->type->info.bits.count; i++) {
1548 if (!strcmp(typ->type->info.bits.bit[i].name, bit->name)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001549 LOGVAL(LYE_BITS_DUPNAME, LY_VLOG_NONE, NULL, bit->name);
Pavol Vican9887c682016-02-29 11:32:01 +01001550 typ->type->info.bits.count++;
1551 goto error;
1552 }
1553 }
1554 typ->type->info.bits.count++;
1555 return bit;
1556
1557error:
1558 return NULL;
1559}
1560
1561int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001562yang_check_bit(struct yang_type *typ, struct lys_type_bit *bit, int64_t *value, int assign)
Pavol Vican9887c682016-02-29 11:32:01 +01001563{
1564 int i,j;
Pavol Vican9887c682016-02-29 11:32:01 +01001565
1566 if (!assign) {
1567 /* assign value automatically */
1568 if (*value > UINT32_MAX) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001569 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "4294967295", "bit/position");
Pavol Vican9887c682016-02-29 11:32:01 +01001570 goto error;
1571 }
1572 bit->pos = (uint32_t)*value;
1573 bit->flags |= LYS_AUTOASSIGNED;
1574 (*value)++;
1575 }
1576
1577 j = typ->type->info.bits.count - 1;
1578 /* check that the value is unique */
1579 for (i = 0; i < j; i++) {
1580 if (typ->type->info.bits.bit[i].pos == bit->pos) {
Radek Krejcie663e012016-08-01 17:12:34 +02001581 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 +01001582 goto error;
1583 }
1584 }
1585
Pavol Vican9887c682016-02-29 11:32:01 +01001586 return EXIT_SUCCESS;
1587
1588error:
1589 return EXIT_FAILURE;
1590}
Pavol Vican0df02b02016-03-01 10:28:50 +01001591
1592void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001593yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican0df02b02016-03-01 10:28:50 +01001594{
1595 struct lys_tpdf *ret;
Pavol Vican810892e2016-07-12 16:55:34 +02001596 struct lys_node *root;
Pavol Vican0df02b02016-03-01 10:28:50 +01001597
Pavol Vican810892e2016-07-12 16:55:34 +02001598 root = (parent) ? NULL : lys_main_module(module)->data;
1599 if (lyp_check_identifier(value, LY_IDENT_TYPE, module, parent) || yang_check_typedef_identif(root, parent, value)) {
Pavol Vican0df02b02016-03-01 10:28:50 +01001600 free(value);
1601 return NULL;
1602 }
Pavol Vican810892e2016-07-12 16:55:34 +02001603
Pavol Vican0df02b02016-03-01 10:28:50 +01001604 if (!parent) {
1605 ret = &module->tpdf[module->tpdf_size];
Pavol Vican0df02b02016-03-01 10:28:50 +01001606 module->tpdf_size++;
Pavol Vican21238f52016-03-01 12:39:52 +01001607 } else {
1608 switch (parent->nodetype) {
1609 case LYS_GROUPING:
1610 ret = &((struct lys_node_grp *)parent)->tpdf[((struct lys_node_grp *)parent)->tpdf_size];
Pavol Vican21238f52016-03-01 12:39:52 +01001611 ((struct lys_node_grp *)parent)->tpdf_size++;
1612 break;
Pavol Vican535d50e2016-03-01 13:05:33 +01001613 case LYS_CONTAINER:
1614 ret = &((struct lys_node_container *)parent)->tpdf[((struct lys_node_container *)parent)->tpdf_size];
1615 ((struct lys_node_container *)parent)->tpdf_size++;
1616 break;
Pavol Vican09f04b82016-03-01 14:02:28 +01001617 case LYS_LIST:
1618 ret = &((struct lys_node_list *)parent)->tpdf[((struct lys_node_list *)parent)->tpdf_size];
1619 ((struct lys_node_list *)parent)->tpdf_size++;
1620 break;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001621 case LYS_RPC:
Michal Vasko44fb6382016-06-29 11:12:27 +02001622 case LYS_ACTION:
1623 ret = &((struct lys_node_rpc_action *)parent)->tpdf[((struct lys_node_rpc_action *)parent)->tpdf_size];
1624 ((struct lys_node_rpc_action *)parent)->tpdf_size++;
Pavol Vican52ed67d2016-03-02 17:46:15 +01001625 break;
Pavol Vican531a9132016-03-03 10:10:09 +01001626 case LYS_INPUT:
1627 case LYS_OUTPUT:
Michal Vasko44fb6382016-06-29 11:12:27 +02001628 ret = &((struct lys_node_inout *)parent)->tpdf[((struct lys_node_inout *)parent)->tpdf_size];
1629 ((struct lys_node_inout *)parent)->tpdf_size++;
Pavol Vican531a9132016-03-03 10:10:09 +01001630 break;
Pavol Vican41267fd2016-03-03 10:47:42 +01001631 case LYS_NOTIF:
1632 ret = &((struct lys_node_notif *)parent)->tpdf[((struct lys_node_notif *)parent)->tpdf_size];
1633 ((struct lys_node_notif *)parent)->tpdf_size++;
1634 break;
Pavol Vicand1dbfda2016-03-21 10:03:58 +01001635 default:
1636 /* another type of nodetype is error*/
1637 LOGINT;
1638 free(value);
1639 return NULL;
Pavol Vican21238f52016-03-01 12:39:52 +01001640 }
Pavol Vican0df02b02016-03-01 10:28:50 +01001641 }
1642
Pavol Vican79436472016-04-04 11:22:02 +02001643 ret->type.parent = ret;
Pavol Vican0df02b02016-03-01 10:28:50 +01001644 ret->name = lydict_insert_zc(module->ctx, value);
1645 ret->module = module;
1646 return ret;
1647}
Pavol Vican1003ead2016-03-02 12:24:52 +01001648
1649void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001650yang_read_refine(struct lys_module *module, struct lys_node_uses *uses, char *value)
Pavol Vican1003ead2016-03-02 12:24:52 +01001651{
1652 struct lys_refine *rfn;
1653
1654 rfn = &uses->refine[uses->refine_size];
1655 uses->refine_size++;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001656 rfn->target_name = transform_schema2json(module, value);
Pavol Vican1003ead2016-03-02 12:24:52 +01001657 free(value);
1658 if (!rfn->target_name) {
1659 return NULL;
1660 }
1661 return rfn;
1662}
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001663
1664void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001665yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001666{
1667 struct lys_node_augment *aug;
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001668
1669 if (parent) {
1670 aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
1671 } else {
1672 aug = &module->augment[module->augment_size];
1673 }
1674 aug->nodetype = LYS_AUGMENT;
Pavol Vican0adf01d2016-03-22 12:29:33 +01001675 aug->target_name = transform_schema2json(module, value);
Pavol Vican92fa0dc2016-03-02 14:20:39 +01001676 free(value);
1677 if (!aug->target_name) {
1678 return NULL;
1679 }
1680 aug->parent = parent;
1681 aug->module = module;
1682 if (parent) {
1683 ((struct lys_node_uses *)parent)->augment_size++;
1684 } else {
1685 module->augment_size++;
1686 }
1687 return aug;
1688}
Pavol Vican220e5a12016-03-03 14:19:43 +01001689
1690void *
Pavol Vican0adf01d2016-03-22 12:29:33 +01001691yang_read_deviation(struct lys_module *module, char *value)
Pavol Vican220e5a12016-03-03 14:19:43 +01001692{
Radek Krejci27fe55e2016-09-13 17:13:35 +02001693 struct lys_node *dev_target = NULL, *parent;
Pavol Vican220e5a12016-03-03 14:19:43 +01001694 struct lys_deviation *dev;
1695 struct type_deviation *deviation = NULL;
Radek Krejci27fe55e2016-09-13 17:13:35 +02001696 struct lys_module *mod;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001697 int rc;
Pavol Vican220e5a12016-03-03 14:19:43 +01001698
Pavol Vican220e5a12016-03-03 14:19:43 +01001699 dev = &module->deviation[module->deviation_size];
Pavol Vican0adf01d2016-03-22 12:29:33 +01001700 dev->target_name = transform_schema2json(module, value);
Pavol Vican220e5a12016-03-03 14:19:43 +01001701 free(value);
1702 if (!dev->target_name) {
1703 goto error;
1704 }
1705
Pavol Vican974377b2016-03-23 00:38:53 +01001706 deviation = calloc(1, sizeof *deviation);
1707 if (!deviation) {
1708 LOGMEM;
1709 goto error;
1710 }
1711
Pavol Vican220e5a12016-03-03 14:19:43 +01001712 /* resolve target node */
1713 rc = resolve_augment_schema_nodeid(dev->target_name, NULL, module, (const struct lys_node **)&dev_target);
1714 if (rc || !dev_target) {
Michal Vasko75c8daf2016-05-19 10:56:39 +02001715 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
Pavol Vican220e5a12016-03-03 14:19:43 +01001716 goto error;
1717 }
Radek Krejcic4283442016-04-22 09:19:27 +02001718 if (dev_target->module == lys_main_module(module)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001719 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->target_name, "deviation");
1720 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
Pavol Vican220e5a12016-03-03 14:19:43 +01001721 goto error;
1722 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001723
Radek Krejci27fe55e2016-09-13 17:13:35 +02001724 /* mark all the affected modules as deviated and implemented */
1725 for(parent = dev_target; parent; parent = lys_parent(parent)) {
1726 mod = lys_node_module(parent);
1727 if (module != mod) {
1728 mod->deviated = 1;
1729 lys_set_implemented(mod);
1730 }
1731 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02001732
Pavol Vican220e5a12016-03-03 14:19:43 +01001733 /*save pointer to the deviation and deviated target*/
1734 deviation->deviation = dev;
1735 deviation->target = dev_target;
1736
Pavol Vican38321d02016-08-16 14:56:02 +02001737 deviation->dflt_check = ly_set_new();
1738 if (!deviation->dflt_check) {
1739 LOGMEM;
1740 goto error;
1741 }
1742
Pavol Vican220e5a12016-03-03 14:19:43 +01001743 return deviation;
1744
1745error:
1746 free(deviation);
1747 lydict_remove(module->ctx, dev->target_name);
1748 return NULL;
1749}
Pavol Vican4c90c642016-03-03 15:06:47 +01001750
1751int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001752yang_read_deviate_unsupported(struct type_deviation *dev)
Pavol Vican4c90c642016-03-03 15:06:47 +01001753{
1754 int i;
1755
1756 if (dev->deviation->deviate_size) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001757 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001758 return EXIT_FAILURE;
1759 }
1760 dev->deviation->deviate[dev->deviation->deviate_size].mod = LY_DEVIATE_NO;
1761
1762 /* you cannot remove a key leaf */
1763 if ((dev->target->nodetype == LYS_LEAF) && dev->target->parent && (dev->target->parent->nodetype == LYS_LIST)) {
1764 for (i = 0; i < ((struct lys_node_list *)dev->target->parent)->keys_size; ++i) {
1765 if (((struct lys_node_list *)dev->target->parent)->keys[i] == (struct lys_node_leaf *)dev->target) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001766 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, "not-supported", "deviation");
1767 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot remove a list key.");
Pavol Vican4c90c642016-03-03 15:06:47 +01001768 return EXIT_FAILURE;
1769 }
1770 }
1771 }
Michal Vaskofe7e5a72016-05-02 14:49:23 +02001772
Pavol Vican4c90c642016-03-03 15:06:47 +01001773 /* unlink and store the original node */
Michal Vaskod921d682016-05-19 10:56:51 +02001774 lys_node_unlink(dev->target);
Pavol Vican4c90c642016-03-03 15:06:47 +01001775 dev->deviation->orig_node = dev->target;
1776
1777 dev->deviation->deviate_size = 1;
1778 return EXIT_SUCCESS;
1779}
Pavol Vican85f12022016-03-05 16:30:35 +01001780
1781int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001782yang_read_deviate(struct type_deviation *dev, LYS_DEVIATE_TYPE mod)
Pavol Vican85f12022016-03-05 16:30:35 +01001783{
1784 struct unres_schema tmp_unres;
1785
1786 dev->deviation->deviate[dev->deviation->deviate_size].mod = mod;
1787 dev->deviate = &dev->deviation->deviate[dev->deviation->deviate_size];
1788 dev->deviation->deviate_size++;
1789 if (dev->deviation->deviate[0].mod == LY_DEVIATE_NO) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001790 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "not-supported");
1791 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"not-supported\" deviation cannot be combined with any other deviation.");
Pavol Vican85f12022016-03-05 16:30:35 +01001792 return EXIT_FAILURE;
1793 }
1794
1795 /* store a shallow copy of the original node */
1796 if (!dev->deviation->orig_node) {
1797 memset(&tmp_unres, 0, sizeof tmp_unres);
1798 dev->deviation->orig_node = lys_node_dup(dev->target->module, NULL, dev->target, 0, 0, &tmp_unres, 1);
1799 /* just to be safe */
1800 if (tmp_unres.count) {
1801 LOGINT;
1802 return EXIT_FAILURE;
1803 }
1804 }
1805
1806 return EXIT_SUCCESS;
1807}
1808
1809int
Pavol Vican0adf01d2016-03-22 12:29:33 +01001810yang_read_deviate_units(struct ly_ctx *ctx, struct type_deviation *dev, char *value)
Pavol Vican85f12022016-03-05 16:30:35 +01001811{
1812 const char **stritem;
1813
1814 if (dev->deviate->units) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001815 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "units", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01001816 free(value);
1817 goto error;
1818 }
1819
1820 /* check target node type */
1821 if (dev->target->nodetype == LYS_LEAFLIST) {
1822 stritem = &((struct lys_node_leaflist *)dev->target)->units;
1823 } else if (dev->target->nodetype == LYS_LEAF) {
1824 stritem = &((struct lys_node_leaf *)dev->target)->units;
1825 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001826 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1827 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"units\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001828 free(value);
1829 goto error;
1830 }
1831
1832 dev->deviate->units = lydict_insert_zc(ctx, value);
1833
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001834 if (dev->deviate->mod == LY_DEVIATE_DEL) {
1835 /* check values */
Michal Vaskob42b6972016-06-06 14:21:30 +02001836 if (!ly_strequal(*stritem, dev->deviate->units, 1)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001837 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
1838 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001839 goto error;
1840 }
1841 /* remove current units value of the target */
1842 lydict_remove(ctx, *stritem);
Pavol Vican4766aca2016-03-07 12:42:36 +01001843 } else {
1844 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1845 /* check that there is no current value */
1846 if (*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001847 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1848 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001849 goto error;
1850 }
1851 } else { /* replace */
1852 if (!*stritem) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001853 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "units");
1854 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01001855 goto error;
1856 }
1857 }
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001858 /* remove current units value of the target ... */
1859 lydict_remove(ctx, *stritem);
1860
1861 /* ... and replace it with the value specified in deviation */
1862 *stritem = lydict_insert(ctx, dev->deviate->units, 0);
1863 }
1864
Pavol Vican85f12022016-03-05 16:30:35 +01001865 return EXIT_SUCCESS;
1866
1867error:
1868 return EXIT_FAILURE;
1869}
1870
1871int
Pavol Vican974377b2016-03-23 00:38:53 +01001872yang_read_deviate_must(struct type_deviation *dev, uint8_t c_must)
Pavol Vican85f12022016-03-05 16:30:35 +01001873{
Pavol Vican85f12022016-03-05 16:30:35 +01001874 /* check target node type */
1875 switch (dev->target->nodetype) {
1876 case LYS_LEAF:
1877 dev->trg_must = &((struct lys_node_leaf *)dev->target)->must;
1878 dev->trg_must_size = &((struct lys_node_leaf *)dev->target)->must_size;
1879 break;
1880 case LYS_CONTAINER:
1881 dev->trg_must = &((struct lys_node_container *)dev->target)->must;
1882 dev->trg_must_size = &((struct lys_node_container *)dev->target)->must_size;
1883 break;
1884 case LYS_LEAFLIST:
1885 dev->trg_must = &((struct lys_node_leaflist *)dev->target)->must;
1886 dev->trg_must_size = &((struct lys_node_leaflist *)dev->target)->must_size;
1887 break;
1888 case LYS_LIST:
1889 dev->trg_must = &((struct lys_node_list *)dev->target)->must;
1890 dev->trg_must_size = &((struct lys_node_list *)dev->target)->must_size;
1891 break;
1892 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001893 case LYS_ANYDATA:
1894 dev->trg_must = &((struct lys_node_anydata *)dev->target)->must;
1895 dev->trg_must_size = &((struct lys_node_anydata *)dev->target)->must_size;
Pavol Vican85f12022016-03-05 16:30:35 +01001896 break;
1897 default:
Pavol Vican0adf01d2016-03-22 12:29:33 +01001898 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "must");
1899 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"must\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001900 goto error;
1901 }
1902
Michal Vasko508a50d2016-09-07 14:50:33 +02001903 /* flag will be checked again, clear it for now */
1904 dev->target->flags &= ~LYS_XPATH_DEP;
1905
Pavol Vican85f12022016-03-05 16:30:35 +01001906 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1907 /* reallocate the must array of the target */
1908 dev->deviate->must = ly_realloc(*dev->trg_must, (c_must + *dev->trg_must_size) * sizeof *dev->deviate->must);
1909 if (!dev->deviate->must) {
1910 LOGMEM;
1911 goto error;
1912 }
1913 *dev->trg_must = dev->deviate->must;
1914 dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
1915 dev->deviate->must_size = c_must;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001916 } else {
1917 /* LY_DEVIATE_DEL */
1918 dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
1919 if (!dev->deviate->must) {
1920 LOGMEM;
1921 goto error;
1922 }
Pavol Vican85f12022016-03-05 16:30:35 +01001923 }
1924
1925 return EXIT_SUCCESS;
1926
1927error:
1928 return EXIT_FAILURE;
1929}
1930
1931int
Pavol Vican974377b2016-03-23 00:38:53 +01001932yang_read_deviate_unique(struct type_deviation *dev, uint8_t c_uniq)
Pavol Vican85f12022016-03-05 16:30:35 +01001933{
Pavol Vican85f12022016-03-05 16:30:35 +01001934 struct lys_node_list *list;
1935
1936 /* check target node type */
1937 if (dev->target->nodetype != LYS_LIST) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01001938 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "unique");
1939 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"unique\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001940 goto error;
1941 }
1942
1943 list = (struct lys_node_list *)dev->target;
1944 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1945 /* reallocate the unique array of the target */
1946 dev->deviate->unique = ly_realloc(list->unique, (c_uniq + list->unique_size) * sizeof *dev->deviate->unique);
1947 if (!dev->deviate->unique) {
1948 LOGMEM;
1949 goto error;
1950 }
1951 list->unique = dev->deviate->unique;
1952 dev->deviate->unique = &list->unique[list->unique_size];
1953 dev->deviate->unique_size = c_uniq;
1954 memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
Pavol Vicanc1f5a502016-03-06 16:51:26 +01001955 } else {
1956 /* LY_DEVIATE_DEL */
1957 dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
1958 if (!dev->deviate->unique) {
1959 LOGMEM;
1960 goto error;
1961 }
Pavol Vican85f12022016-03-05 16:30:35 +01001962 }
1963
1964 return EXIT_SUCCESS;
1965
1966error:
1967 return EXIT_FAILURE;
1968}
1969
1970int
Pavol Vican38321d02016-08-16 14:56:02 +02001971yang_read_deviate_default(struct lys_module *module, struct type_deviation *dev, uint8_t c_dflt)
Pavol Vican85f12022016-03-05 16:30:35 +01001972{
Pavol Vican38321d02016-08-16 14:56:02 +02001973 int i;
1974 struct lys_node_leaflist *llist;
Pavol Vican85f12022016-03-05 16:30:35 +01001975
Pavol Vican38321d02016-08-16 14:56:02 +02001976 /* check target node type */
1977 if (module->version < 2 && dev->target->nodetype == LYS_LEAFLIST) {
1978 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1979 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
1980 goto error;
1981 } else if (c_dflt > 1 && dev->target->nodetype != LYS_LEAFLIST) { /* from YANG 1.1 */
1982 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1983 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow multiple \"default\" properties.");
1984 goto error;
1985 } else if (!(dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
1986 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1987 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"default\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01001988 goto error;
1989 }
1990
Pavol Vican38321d02016-08-16 14:56:02 +02001991 if (dev->deviate->mod == LY_DEVIATE_ADD) {
1992 /* check that there is no current value */
1993 if ((dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) ||
1994 (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt)) {
1995 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
1996 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01001997 goto error;
1998 }
Pavol Vican4766aca2016-03-07 12:42:36 +01001999
Pavol Vican38321d02016-08-16 14:56:02 +02002000 /* check collision with mandatory/min-elements */
2001 if ((dev->target->flags & LYS_MAND_TRUE) ||
2002 (dev->target->nodetype == LYS_LEAFLIST && ((struct lys_node_leaflist *)dev->target)->min)) {
2003 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "deviation");
2004 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2005 "Adding the \"default\" statement is forbidden on %s statement.",
2006 (dev->target->flags & LYS_MAND_TRUE) ? "nodes with the \"mandatory\"" : "leaflists with non-zero \"min-elements\"");
2007 goto error;
Pavol Vican85f12022016-03-05 16:30:35 +01002008 }
Pavol Vican38321d02016-08-16 14:56:02 +02002009 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2010 /* check that there was a value before */
2011 if (((dev->target->nodetype & (LYS_LEAF | LYS_LEAFLIST)) && !((struct lys_node_leaf *)dev->target)->dflt) ||
2012 (dev->target->nodetype == LYS_CHOICE && !((struct lys_node_choice *)dev->target)->dflt)) {
2013 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "default");
2014 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
2015 goto error;
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002016 }
Pavol Vican38321d02016-08-16 14:56:02 +02002017 }
2018
2019 if (dev->target->nodetype == LYS_LEAFLIST) {
2020 /* reallocate default list in the target */
2021 llist = (struct lys_node_leaflist *)dev->target;
2022 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2023 /* reallocate (enlarge) the unique array of the target */
2024 llist->dflt = ly_realloc(llist->dflt, (c_dflt + llist->dflt_size) * sizeof *dev->deviate->dflt);
2025 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2026 /* reallocate (replace) the unique array of the target */
2027 for (i = 0; i < llist->dflt_size; i++) {
2028 lydict_remove(llist->module->ctx, llist->dflt[i]);
2029 }
2030 llist->dflt = ly_realloc(llist->dflt, c_dflt * sizeof *dev->deviate->dflt);
2031 llist->dflt_size = 0;
2032 }
2033 }
2034
2035 dev->deviate->dflt = calloc(c_dflt, sizeof *dev->deviate->dflt);
2036 if (!dev->deviate->dflt) {
2037 LOGMEM;
Pavol Vican85f12022016-03-05 16:30:35 +01002038 goto error;
2039 }
2040
2041 return EXIT_SUCCESS;
2042
2043error:
2044 return EXIT_FAILURE;
2045}
2046
2047int
Pavol Vican38321d02016-08-16 14:56:02 +02002048yang_fill_deviate_default(struct ly_ctx *ctx, struct type_deviation *dev, char *exp)
2049{
2050 struct lys_node *node;
2051 struct lys_node_choice *choice;
2052 struct lys_node_leaf *leaf;
2053 struct lys_node_leaflist *llist;
2054 int rc, i;
2055 unsigned int u;
2056 const char *value;
2057
2058 value = lydict_insert_zc(ctx, exp);
2059 u = strlen(value);
2060 dev->deviate->dflt[dev->deviate->dflt_size++] = value;
2061
2062 if (dev->target->nodetype == LYS_CHOICE) {
2063 choice = (struct lys_node_choice *)dev->target;
2064 rc = resolve_choice_default_schema_nodeid(value, choice->child, (const struct lys_node **)&node);
2065 if (rc || !node) {
2066 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2067 goto error;
2068 }
2069 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2070 if (!choice->dflt || (choice->dflt != node)) {
2071 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2072 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2073 goto error;
2074 }
2075 } else { /* add or replace */
2076 choice->dflt = node;
2077 if (!choice->dflt) {
2078 /* default branch not found */
2079 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2080 goto error;
2081 }
2082 }
2083 } else if (dev->target->nodetype == LYS_LEAF) {
2084 leaf = (struct lys_node_leaf *)dev->target;
2085 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2086 if (!leaf->dflt || !ly_strequal(leaf->dflt, value, 1)) {
2087 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2088 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
2089 goto error;
2090 }
2091 /* remove value */
2092 lydict_remove(ctx, leaf->dflt);
2093 leaf->dflt = NULL;
2094 } else { /* add (already checked) and replace */
2095 /* remove value */
2096 lydict_remove(ctx, leaf->dflt);
2097
2098 /* set new value */
2099 leaf->dflt = lydict_insert(ctx, value, u);
2100
2101 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2102 ly_set_add(dev->dflt_check, dev->target, 0);
2103 }
2104 } else { /* LYS_LEAFLIST */
2105 llist = (struct lys_node_leaflist *)dev->target;
2106 if (dev->deviate->mod == LY_DEVIATE_DEL) {
2107 /* find and remove the value in target list */
2108 for (i = 0; i < llist->dflt_size; i++) {
2109 if (llist->dflt[i] && ly_strequal(llist->dflt[i], value, 1)) {
2110 /* match, remove the value */
2111 lydict_remove(llist->module->ctx, llist->dflt[i]);
2112 llist->dflt[i] = NULL;
2113 break;
2114 }
2115 }
2116 if (i == llist->dflt_size) {
2117 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2118 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The default value to delete not found in the target node.");
2119 goto error;
2120 }
2121 } else {
2122 /* add or replace, anyway we place items into the deviate's list
2123 which propagates to the target */
2124 /* we just want to check that the value isn't already in the list */
2125 for (i = 0; i < llist->dflt_size; i++) {
2126 if (ly_strequal(llist->dflt[i], value, 1)) {
2127 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2128 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", value);
2129 goto error;
2130 }
2131 }
2132 /* store it in target node */
2133 llist->dflt[llist->dflt_size++] = lydict_insert(ctx, value, u);
2134
2135 /* remember to check it later (it may not fit now, but the type can be deviated too) */
2136 ly_set_add(dev->dflt_check, dev->target, 0);
2137 }
2138 }
2139
2140 return EXIT_SUCCESS;
2141error:
2142 return EXIT_FAILURE;
2143}
2144
2145
2146int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002147yang_read_deviate_config(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002148{
2149 if (dev->deviate->flags & LYS_CONFIG_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002150 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002151 goto error;
2152 }
2153
2154 /* for we deviate from RFC 6020 and allow config property even it is/is not
2155 * specified in the target explicitly since config property inherits. So we expect
2156 * that config is specified in every node. But for delete, we check that the value
2157 * is the same as here in deviation
2158 */
2159 dev->deviate->flags |= value;
2160
2161 /* add and replace are the same in this case */
2162 /* remove current config value of the target ... */
2163 dev->target->flags &= ~LYS_CONFIG_MASK;
2164
2165 /* ... and replace it with the value specified in deviation */
2166 dev->target->flags |= dev->deviate->flags & LYS_CONFIG_MASK;
2167
2168 return EXIT_SUCCESS;
2169
2170error:
2171 return EXIT_FAILURE;
2172}
2173
2174int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002175yang_read_deviate_mandatory(struct type_deviation *dev, uint8_t value)
Pavol Vican85f12022016-03-05 16:30:35 +01002176{
Radek Krejcie00d2312016-08-12 15:27:49 +02002177 struct lys_node *parent;
2178
Pavol Vican85f12022016-03-05 16:30:35 +01002179 if (dev->deviate->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002180 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
Pavol Vican85f12022016-03-05 16:30:35 +01002181 goto error;
2182 }
2183
2184 /* check target node type */
Radek Krejcibf2abff2016-08-23 15:51:52 +02002185 if (!(dev->target->nodetype & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA))) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002186 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2187 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Target node does not allow \"mandatory\" property.");
Pavol Vican85f12022016-03-05 16:30:35 +01002188 goto error;
2189 }
2190
2191 dev->deviate->flags |= value;
2192
2193 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2194 /* check that there is no current value */
2195 if (dev->target->flags & LYS_MAND_MASK) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002196 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2197 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002198 goto error;
Pavol Vican321a02e2016-04-05 16:11:59 +02002199 } else {
2200 if (dev->target->nodetype == LYS_LEAF && ((struct lys_node_leaf *)dev->target)->dflt) {
2201 /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2202 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "leaf");
2203 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2204 goto error;
2205 } else if (dev->target->nodetype == LYS_CHOICE && ((struct lys_node_choice *)dev->target)->dflt) {
2206 LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "choice");
2207 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on choices with \"default\".");
2208 goto error;
2209 }
Pavol Vican85f12022016-03-05 16:30:35 +01002210 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002211 } else { /* replace */
2212 if (!(dev->target->flags & LYS_MAND_MASK)) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002213 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2214 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Replacing a property that does not exist.");
Pavol Vican4766aca2016-03-07 12:42:36 +01002215 goto error;
2216 }
Pavol Vican85f12022016-03-05 16:30:35 +01002217 }
2218
Pavol Vican85f12022016-03-05 16:30:35 +01002219 /* remove current mandatory value of the target ... */
2220 dev->target->flags &= ~LYS_MAND_MASK;
2221
2222 /* ... and replace it with the value specified in deviation */
2223 dev->target->flags |= dev->deviate->flags & LYS_MAND_MASK;
2224
Radek Krejcie00d2312016-08-12 15:27:49 +02002225 /* check for mandatory node in default case, first find the closest parent choice to the changed node */
2226 for (parent = dev->target->parent;
2227 parent && !(parent->nodetype & (LYS_CHOICE | LYS_GROUPING | LYS_ACTION));
2228 parent = parent->parent) {
2229 if (parent->nodetype == LYS_CONTAINER && ((struct lys_node_container *)parent)->presence) {
2230 /* stop also on presence containers */
2231 break;
2232 }
2233 }
2234 /* and if it is a choice with the default case, check it for presence of a mandatory node in it */
2235 if (parent && parent->nodetype == LYS_CHOICE && ((struct lys_node_choice *)parent)->dflt) {
2236 if (lyp_check_mandatory_choice(parent)) {
2237 goto error;
2238 }
2239 }
2240
Pavol Vican85f12022016-03-05 16:30:35 +01002241 return EXIT_SUCCESS;
2242
2243error:
2244 return EXIT_FAILURE;
2245}
2246
2247int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002248yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type)
Pavol Vican85f12022016-03-05 16:30:35 +01002249{
Pavol Vican09adcc32016-08-25 10:51:36 +02002250 uint32_t *ui32val, *min, *max;
Pavol Vican85f12022016-03-05 16:30:35 +01002251
2252 /* check target node type */
2253 if (dev->target->nodetype == LYS_LEAFLIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002254 max = &((struct lys_node_leaflist *)dev->target)->max;
2255 min = &((struct lys_node_leaflist *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002256 } else if (dev->target->nodetype == LYS_LIST) {
Pavol Vican09adcc32016-08-25 10:51:36 +02002257 max = &((struct lys_node_list *)dev->target)->max;
2258 min = &((struct lys_node_list *)dev->target)->min;
Pavol Vican85f12022016-03-05 16:30:35 +01002259 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002260 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2261 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 +01002262 goto error;
2263 }
2264
2265 if (type) {
2266 dev->deviate->max = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002267 dev->deviate->max_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002268 ui32val = max;
Pavol Vican85f12022016-03-05 16:30:35 +01002269 } else {
2270 dev->deviate->min = value;
Pavol Vican4766aca2016-03-07 12:42:36 +01002271 dev->deviate->min_set = 1;
Pavol Vican09adcc32016-08-25 10:51:36 +02002272 ui32val = min;
Pavol Vican85f12022016-03-05 16:30:35 +01002273 }
2274
2275 if (dev->deviate->mod == LY_DEVIATE_ADD) {
2276 /* check that there is no current value */
2277 if (*ui32val) {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002278 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, (type) ? "max-elements" : "min-elements");
2279 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Adding property that already exists.");
Pavol Vican85f12022016-03-05 16:30:35 +01002280 goto error;
2281 }
Pavol Vican4766aca2016-03-07 12:42:36 +01002282 } else if (dev->deviate->mod == LY_DEVIATE_RPL) {
2283 /* unfortunately, there is no way to check reliably that there
2284 * was a value before, it could have been the default */
Pavol Vican85f12022016-03-05 16:30:35 +01002285 }
2286
2287 /* add (already checked) and replace */
2288 /* set new value specified in deviation */
2289 *ui32val = value;
2290
Pavol Vican09adcc32016-08-25 10:51:36 +02002291 /* check min-elements is smaller than max-elements */
2292 if (*max && *min > *max) {
2293 if (type) {
2294 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"max-elements\".", value);
2295 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\".");
2296 } else {
2297 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"min-elements\".", value);
2298 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
2299 }
2300 goto error;
2301 }
2302
Pavol Vican85f12022016-03-05 16:30:35 +01002303 return EXIT_SUCCESS;
2304
2305error:
2306 return EXIT_FAILURE;
2307}
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002308
2309int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002310yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002311{
2312 int i;
2313
2314 /* find must to delete, we are ok with just matching conditions */
2315 for (i = 0; i < *dev->trg_must_size; i++) {
2316 if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
2317 /* we have a match, free the must structure ... */
2318 lys_restr_free(ctx, &((*dev->trg_must)[i]));
2319 /* ... and maintain the array */
2320 (*dev->trg_must_size)--;
2321 if (i != *dev->trg_must_size) {
2322 (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
2323 (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
2324 (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
2325 (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
2326 (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
2327 }
2328 if (!(*dev->trg_must_size)) {
2329 free(*dev->trg_must);
2330 *dev->trg_must = NULL;
2331 } else {
2332 (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
2333 (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
2334 (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
2335 (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
2336 (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
2337 }
2338
2339 i = -1; /* set match flag */
2340 break;
2341 }
2342 }
2343 if (i != -1) {
2344 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002345 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
2346 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value does not match any must from the target.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002347 return EXIT_FAILURE;
2348 }
2349
2350 return EXIT_SUCCESS;
2351}
2352
2353int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002354yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value)
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002355{
2356 struct lys_node_list *list;
2357 int i, j;
2358
2359 list = (struct lys_node_list *)dev->target;
Pavol Vican0adf01d2016-03-22 12:29:33 +01002360 if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL)) {
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002361 dev->deviate->unique_size++;
2362 goto error;
2363 }
2364
2365 /* find unique structures to delete */
2366 for (i = 0; i < list->unique_size; i++) {
2367 if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2368 continue;
2369 }
2370
2371 for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
2372 if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
2373 break;
2374 }
2375 }
2376
2377 if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
2378 /* we have a match, free the unique structure ... */
2379 for (j = 0; j < list->unique[i].expr_size; j++) {
2380 lydict_remove(module->ctx, list->unique[i].expr[j]);
2381 }
2382 free(list->unique[i].expr);
2383 /* ... and maintain the array */
2384 list->unique_size--;
2385 if (i != list->unique_size) {
2386 list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
2387 list->unique[i].expr = list->unique[list->unique_size].expr;
2388 }
2389
2390 if (!list->unique_size) {
2391 free(list->unique);
2392 list->unique = NULL;
2393 } else {
2394 list->unique[list->unique_size].expr_size = 0;
2395 list->unique[list->unique_size].expr = NULL;
2396 }
2397
2398 i = -1; /* set match flag */
2399 break;
2400 }
2401 }
2402 dev->deviate->unique_size++;
2403
2404 if (i != -1) {
2405 /* no match found */
Pavol Vican0adf01d2016-03-22 12:29:33 +01002406 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "unique");
2407 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Value differs from the target being deleted.");
Pavol Vicanc1f5a502016-03-06 16:51:26 +01002408 goto error;
2409 }
2410
2411 free(value);
2412 return EXIT_SUCCESS;
2413
2414error:
2415 free(value);
2416 return EXIT_FAILURE;
2417}
Pavol Vicane92421d2016-03-08 10:12:33 +01002418
2419int
Pavol Vican38321d02016-08-16 14:56:02 +02002420yang_check_deviation(struct lys_module *module, struct ly_set *dflt_check, struct unres_schema *unres)
Pavol Vicane92421d2016-03-08 10:12:33 +01002421{
2422 int i, rc;
Pavol Vican38321d02016-08-16 14:56:02 +02002423 unsigned int u;
2424 const char *value, *target_name;
2425 struct lys_node_leaflist *llist;
2426 struct lys_node_leaf *leaf;
Pavol Vicane92421d2016-03-08 10:12:33 +01002427
Pavol Vican38321d02016-08-16 14:56:02 +02002428 /* now check whether default value, if any, matches the type */
2429 for (u = 0; u < dflt_check->number; ++u) {
2430 value = NULL;
2431 rc = EXIT_SUCCESS;
2432 if (dflt_check->set.s[u]->nodetype == LYS_LEAF) {
2433 leaf = (struct lys_node_leaf *)dflt_check->set.s[u];
2434 target_name = leaf->name;
2435 rc = unres_schema_add_str(module, unres, &leaf->type, UNRES_TYPE_DFLT, value = leaf->dflt);
2436 } else { /* LYS_LEAFLIST */
2437 llist = (struct lys_node_leaflist *)dflt_check->set.s[u];
2438 target_name = llist->name;
2439 for (i = 0; i < llist->dflt_size; i++) {
2440 rc = unres_schema_add_str(module, unres, &llist->type, UNRES_TYPE_DFLT, value = llist->dflt[i]);
2441 if (rc == -1) {
Pavol Vicane92421d2016-03-08 10:12:33 +01002442 break;
2443 }
2444 }
2445 }
Pavol Vican38321d02016-08-16 14:56:02 +02002446 if (rc == -1) {
2447 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, "default");
2448 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL,
2449 "The default value \"%s\" of the deviated node \"%s\"no longer matches its type.",
2450 target_name);
2451 return EXIT_FAILURE;
2452 }
Pavol Vicane92421d2016-03-08 10:12:33 +01002453 }
Pavol Vican38321d02016-08-16 14:56:02 +02002454
Pavol Vicane92421d2016-03-08 10:12:33 +01002455 return EXIT_SUCCESS;
Pavol Vican38321d02016-08-16 14:56:02 +02002456
Pavol Vican9b89dda2016-03-09 15:36:55 +01002457}
2458
2459int
2460yang_fill_include(struct lys_module *module, struct lys_submodule *submodule, char *value,
Pavol Vicane024ab72016-07-27 14:27:43 +02002461 struct lys_include *inc, struct unres_schema *unres)
Pavol Vican9b89dda2016-03-09 15:36:55 +01002462{
Pavol Vican9b89dda2016-03-09 15:36:55 +01002463 struct lys_module *trg;
Pavol Vican55870412016-03-10 12:36:21 +01002464 const char *str;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002465 int rc;
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002466 int ret = 0;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002467
Pavol Vican55870412016-03-10 12:36:21 +01002468 str = lydict_insert_zc(module->ctx, value);
Pavol Vican9b89dda2016-03-09 15:36:55 +01002469 trg = (submodule) ? (struct lys_module *)submodule : module;
Pavol Vicane024ab72016-07-27 14:27:43 +02002470 rc = lyp_check_include(module, submodule, str, inc, unres);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002471 if (!rc) {
2472 /* success, copy the filled data into the final array */
Pavol Vicane024ab72016-07-27 14:27:43 +02002473 memcpy(&trg->inc[trg->inc_size], inc, sizeof *inc);
Radek Krejci4dcd3392016-06-22 10:28:40 +02002474 trg->inc_size++;
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002475 } else if (rc == -1) {
Radek Krejci83e3f5b2016-06-24 14:55:25 +02002476 ret = -1;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002477 }
Pavol Vican9b89dda2016-03-09 15:36:55 +01002478
Pavol Vican55870412016-03-10 12:36:21 +01002479 lydict_remove(module->ctx, str);
Radek Krejci5b2c8a82016-06-17 15:36:03 +02002480 return ret;
Pavol Vican9b89dda2016-03-09 15:36:55 +01002481}
Pavol Vicanf4717e62016-03-16 11:30:01 +01002482
2483int
Pavol Vican0adf01d2016-03-22 12:29:33 +01002484yang_use_extension(struct lys_module *module, struct lys_node *data_node, void *actual, char *value)
Pavol Vicanf4717e62016-03-16 11:30:01 +01002485{
2486 char *prefix;
2487 char *identif;
2488 const char *ns = NULL;
2489 int i;
2490
Pavol Vicanf4717e62016-03-16 11:30:01 +01002491 /* check to the same pointer */
2492 if (data_node != actual) {
2493 return EXIT_SUCCESS;
2494 }
2495
Pavol Vicana302aa62016-03-17 10:45:35 +01002496 prefix = strdup(value);
2497 if (!prefix) {
2498 LOGMEM;
2499 goto error;
2500 }
2501 /* find prefix anf identificator*/
2502 identif = strchr(prefix, ':');
Pavol Vicanfbd02782016-08-29 11:14:45 +02002503 if (!identif) {
2504 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, prefix);
2505 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The extension must have prefix.");
2506 goto error;
2507 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002508 *identif = '\0';
2509 identif++;
2510
Pavol Vicanf4717e62016-03-16 11:30:01 +01002511 for(i = 0; i < module->imp_size; ++i) {
2512 if (!strcmp(module->imp[i].prefix, prefix)) {
2513 ns = module->imp[i].module->ns;
2514 break;
2515 }
2516 }
Pavol Vican1ff1b7b2016-04-07 09:51:49 +02002517 if (!ns && !strcmp(module->prefix, prefix)) {
2518 ns = (module->type) ? ((struct lys_submodule *)module)->belongsto->ns : module->ns;
2519 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002520 if (ns && !strcmp(ns, LY_NSNACM)) {
2521 if (!strcmp(identif, "default-deny-write")) {
2522 data_node->nacm |= LYS_NACM_DENYW;
2523 } else if (!strcmp(identif, "default-deny-all")) {
2524 data_node->nacm |= LYS_NACM_DENYA;
2525 } else {
Pavol Vican0adf01d2016-03-22 12:29:33 +01002526 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, identif);
Pavol Vicana302aa62016-03-17 10:45:35 +01002527 goto error;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002528 }
2529 }
Pavol Vicana302aa62016-03-17 10:45:35 +01002530 free(prefix);
Pavol Vicanf4717e62016-03-16 11:30:01 +01002531 return EXIT_SUCCESS;
Pavol Vicana302aa62016-03-17 10:45:35 +01002532
2533error:
2534 free(prefix);
2535 return EXIT_FAILURE;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002536}
2537
2538void
2539nacm_inherit(struct lys_module *module)
2540{
Pavol Vican10ffba52016-04-04 12:21:22 +02002541 struct lys_node *next, *elem, *tmp_node, *tmp_child;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002542
2543 LY_TREE_DFS_BEGIN(module->data, next, elem) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002544 tmp_node = NULL;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002545 if (elem->parent) {
2546 switch (elem->nodetype) {
Pavol Vican10ffba52016-04-04 12:21:22 +02002547 case LYS_GROUPING:
2548 /* extension nacm not inherited*/
2549 break;
2550 case LYS_CHOICE:
2551 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02002552 case LYS_ANYDATA:
Pavol Vican10ffba52016-04-04 12:21:22 +02002553 case LYS_USES:
2554 if (elem->parent->nodetype != LYS_GROUPING) {
2555 elem->nacm |= elem->parent->nacm;
2556 }
2557 break;
2558 case LYS_CONTAINER:
2559 case LYS_LIST:
2560 case LYS_CASE:
2561 case LYS_NOTIF:
2562 case LYS_RPC:
2563 case LYS_INPUT:
2564 case LYS_OUTPUT:
2565 case LYS_AUGMENT:
2566 elem->nacm |= elem->parent->nacm;
2567 break;
2568 case LYS_LEAF:
2569 case LYS_LEAFLIST:
2570 tmp_node = elem;
2571 tmp_child = elem->child;
2572 elem->child = NULL;
2573 default:
2574 break;
Pavol Vicanf4717e62016-03-16 11:30:01 +01002575 }
2576 }
2577 LY_TREE_DFS_END(module->data, next, elem);
Pavol Vican10ffba52016-04-04 12:21:22 +02002578 if (tmp_node) {
2579 tmp_node->child = tmp_child;
2580 }
Pavol Vicanf4717e62016-03-16 11:30:01 +01002581 }
2582}
Pavol Vican4fb66c92016-03-17 10:32:27 +01002583
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002584int
Pavol Vican4fb66c92016-03-17 10:32:27 +01002585store_flags(struct lys_node *node, uint8_t flags, int config_inherit)
2586{
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002587 struct lys_node *elem;
2588
Pavol Vican4fb66c92016-03-17 10:32:27 +01002589 node->flags |= flags;
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002590 if (!(node->flags & LYS_CONFIG_MASK)) {
2591 if (config_inherit) {
2592 /* get config flag from parent */
2593 if (node->parent) {
2594 node->flags |= node->parent->flags & LYS_CONFIG_MASK;
2595 } else {
2596 /* default config is true */
2597 node->flags |= LYS_CONFIG_W;
2598 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002599 }
Michal Vaskoe10d14a2016-08-26 15:17:13 +02002600 } else {
2601 /* do we even care about config flags? */
2602 for (elem = node; elem && !(elem->nodetype & (LYS_NOTIF | LYS_INPUT | LYS_OUTPUT | LYS_RPC)); elem = elem->parent);
2603
2604 if (!elem && (node->flags & LYS_CONFIG_W) && node->parent && (node->parent->flags & LYS_CONFIG_R)) {
2605 LOGVAL(LYE_INARG, LY_VLOG_LYS, node, "true", "config");
2606 LOGVAL(LYE_SPEC, LY_VLOG_LYS, node, "State nodes cannot have configuration nodes as children.");
2607 return EXIT_FAILURE;
2608 }
Pavol Vican4fb66c92016-03-17 10:32:27 +01002609 }
Michal Vaskoe1e351e2016-08-25 12:13:39 +02002610
2611 return EXIT_SUCCESS;
Pavol Vican4fb66c92016-03-17 10:32:27 +01002612}
Pavol Vican8e7110b2016-03-22 17:00:26 +01002613
Pavol Vican1938d882016-04-10 13:36:31 +02002614static int
2615yang_parse(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data,
2616 unsigned int size, struct lys_array_size *size_arrays, int type_read)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002617{
2618 YY_BUFFER_STATE bp;
Pavol Vican802af1e2016-03-23 20:42:26 +01002619 yyscan_t scanner = NULL;
Pavol Vican1938d882016-04-10 13:36:31 +02002620 int ret = EXIT_SUCCESS;
2621
2622 yylex_init(&scanner);
2623 bp = yy_scan_buffer((char *)data, size, scanner);
2624 yy_switch_to_buffer(bp, scanner);
2625 if (yyparse(scanner, module, submodule, unres, size_arrays, type_read)) {
2626 ret = EXIT_FAILURE;
2627 }
2628 yy_delete_buffer(bp, scanner);
2629 yylex_destroy(scanner);
2630 return ret;
2631}
2632
2633int
2634yang_parse_mem(struct lys_module *module, struct lys_submodule *submodule, struct unres_schema *unres, const char *data, unsigned int size_data)
2635{
Pavol Vican8e7110b2016-03-22 17:00:26 +01002636 struct lys_array_size *size_arrays=NULL;
Pavol Vican974377b2016-03-23 00:38:53 +01002637 unsigned int size;
Pavol Vican1938d882016-04-10 13:36:31 +02002638 int ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002639
2640 size_arrays = calloc(1, sizeof *size_arrays);
2641 if (!size_arrays) {
2642 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002643 return EXIT_FAILURE;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002644 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002645 size = (size_data) ? size_data : strlen(data) + 2;
Pavol Vican1938d882016-04-10 13:36:31 +02002646 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ONLY_SIZE);
2647 if (!ret) {
2648 ret = yang_parse(module, submodule, unres, data, size, size_arrays, LY_READ_ALL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002649 }
Pavol Vican8e7110b2016-03-22 17:00:26 +01002650 free(size_arrays->node);
2651 free(size_arrays);
Pavol Vican1938d882016-04-10 13:36:31 +02002652 return ret;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002653}
2654
2655struct lys_module *
Pavol Vican974377b2016-03-23 00:38:53 +01002656yang_read_module(struct ly_ctx *ctx, const char* data, unsigned int size, const char *revision, int implement)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002657{
2658
Pavol Vican10ffba52016-04-04 12:21:22 +02002659 struct lys_module *tmp_module, *module = NULL;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002660 struct unres_schema *unres = NULL;
2661
2662 unres = calloc(1, sizeof *unres);
2663 if (!unres) {
2664 LOGMEM;
2665 goto error;
2666 }
2667
2668 module = calloc(1, sizeof *module);
2669 if (!module) {
2670 LOGMEM;
Pavol Vicanf7994fb2016-04-05 21:55:53 +02002671 goto error;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002672 }
2673
2674 /* initiale module */
Michal Vaskofe7e5a72016-05-02 14:49:23 +02002675 module->ctx = ctx;
Pavol Vican8e7110b2016-03-22 17:00:26 +01002676 module->type = 0;
2677 module->implemented = (implement ? 1 : 0);
2678
2679 if (yang_parse_mem(module, NULL, unres, data, size)) {
2680 goto error;
2681 }
2682
2683 if (module && unres->count && resolve_unres_schema(module, unres)) {
2684 goto error;
2685 }
2686
2687 if (revision) {
2688 /* check revision of the parsed model */
2689 if (!module->rev_size || strcmp(revision, module->rev[0].date)) {
2690 LOGVRB("Module \"%s\" parsed with the wrong revision (\"%s\" instead \"%s\").",
2691 module->name, module->rev[0].date, revision);
2692 goto error;
2693 }
2694 }
2695
Pavol Vican10ffba52016-04-04 12:21:22 +02002696 tmp_module = module;
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002697 if (lyp_ctx_add_module(&module)) {
Pavol Vican8e7110b2016-03-22 17:00:26 +01002698 goto error;
2699 }
2700
Pavol Vican10ffba52016-04-04 12:21:22 +02002701 if (module == tmp_module) {
2702 nacm_inherit(module);
2703 }
2704
Radek Krejci27fe55e2016-09-13 17:13:35 +02002705 if (module->deviation_size && !module->implemented) {
2706 LOGVRB("Module \"%s\" includes deviations, changing its conformance to \"implement\".", module->name);
2707 /* deviations always causes target to be made implemented,
2708 * but augents and leafrefs not, so we have to apply them now */
2709 if (lys_set_implemented(module)) {
Michal Vasko26055752016-05-03 11:36:31 +02002710 goto error;
2711 }
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002712 }
2713
Pavol Vican8e7110b2016-03-22 17:00:26 +01002714 unres_schema_free(NULL, &unres);
2715 LOGVRB("Module \"%s\" successfully parsed.", module->name);
2716 return module;
2717
2718error:
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002719 /* cleanup */
Pavol Vican8e7110b2016-03-22 17:00:26 +01002720 unres_schema_free(module, &unres);
2721 if (!module || !module->name) {
2722 free(module);
2723 LOGERR(ly_errno, "Module parsing failed.");
2724 return NULL;
2725 }
2726
2727 LOGERR(ly_errno, "Module \"%s\" parsing failed.", module->name);
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002728
2729 lys_sub_module_remove_devs_augs(module);
2730 lys_free(module, NULL, 1);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002731 return NULL;
2732}
2733
2734struct lys_submodule *
Pavol Vican974377b2016-03-23 00:38:53 +01002735yang_read_submodule(struct lys_module *module, const char *data, unsigned int size, struct unres_schema *unres)
Pavol Vican8e7110b2016-03-22 17:00:26 +01002736{
2737 struct lys_submodule *submodule;
2738
2739 submodule = calloc(1, sizeof *submodule);
2740 if (!submodule) {
2741 LOGMEM;
2742 goto error;
2743 }
2744
2745 submodule->ctx = module->ctx;
2746 submodule->type = 1;
2747 submodule->belongsto = module;
2748
2749 if (yang_parse_mem(module, submodule, unres, data, size)) {
2750 goto error;
2751 }
2752
Pavol Vican8e7110b2016-03-22 17:00:26 +01002753 LOGVRB("Submodule \"%s\" successfully parsed.", submodule->name);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002754 return submodule;
2755
2756error:
2757 /* cleanup */
2758 unres_schema_free((struct lys_module *)submodule, &unres);
2759
2760 if (!submodule || !submodule->name) {
2761 free(submodule);
2762 LOGERR(ly_errno, "Submodule parsing failed.");
2763 return NULL;
2764 }
2765
2766 LOGERR(ly_errno, "Submodule \"%s\" parsing failed.", submodule->name);
2767
Michal Vasko9eb6dd02016-05-02 14:52:40 +02002768 lys_sub_module_remove_devs_augs((struct lys_module *)submodule);
2769 lys_submodule_module_data_free(submodule);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002770 lys_submodule_free(submodule, NULL);
Pavol Vican8e7110b2016-03-22 17:00:26 +01002771 return NULL;
2772}
Pavol Vican8760bb72016-04-07 09:44:01 +02002773
2774static int
2775count_substring(const char *str, char c)
2776{
2777 const char *tmp = str;
2778 int count = 0;
2779
2780 while ((tmp = strchr(tmp, c))) {
2781 tmp++;
2782 count++;
2783 }
2784 return count;
2785}
2786
2787static int
2788read_indent(const char *input, int indent, int size, int in_index, int *out_index, char *output)
2789{
2790 int k = 0, j;
2791
2792 while (in_index < size) {
2793 if (input[in_index] == ' ') {
2794 k++;
2795 } else if (input[in_index] == '\t') {
2796 /* RFC 6020 6.1.3 tab character is treated as 8 space characters */
2797 k += 8;
2798 } else {
2799 break;
2800 }
2801 ++in_index;
2802 if (k >= indent) {
2803 for (j = k - indent; j > 0; --j) {
2804 output[*out_index] = ' ';
2805 ++(*out_index);
2806 }
2807 break;
2808 }
2809 }
2810 return in_index;
2811}
2812
2813char *
Pavol Vican677b0132016-08-09 15:44:58 +02002814yang_read_string(const char *input, int size, int indent, int version)
Pavol Vican8760bb72016-04-07 09:44:01 +02002815{
2816 int space, count;
2817 int in_index, out_index;
2818 char *value;
2819 char *retval = NULL;
2820
2821 value = malloc(size + 1);
2822 if (!value) {
2823 LOGMEM;
2824 return NULL;
2825 }
2826 /* replace special character in escape sequence */
2827 in_index = out_index = 0;
2828 while (in_index < size) {
2829 if (input[in_index] == '\\') {
2830 if (input[in_index + 1] == 'n') {
2831 value[out_index] = '\n';
2832 ++in_index;
2833 } else if (input[in_index + 1] == 't') {
2834 value[out_index] = '\t';
2835 ++in_index;
2836 } else if (input[in_index + 1] == '\\') {
2837 value[out_index] = '\\';
2838 ++in_index;
2839 } else if ((in_index + 1) != size && input[in_index + 1] == '"') {
2840 value[out_index] = '"';
2841 ++in_index;
2842 } else {
Pavol Vican677b0132016-08-09 15:44:58 +02002843 if (version < 2) {
2844 value[out_index] = input[in_index];
2845 } else {
2846 /* YANG 1.1 backslash must not be followed by any other character */
2847 LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, input);
2848 goto error;
2849 }
Pavol Vican8760bb72016-04-07 09:44:01 +02002850 }
2851 } else {
2852 value[out_index] = input[in_index];
2853 }
2854 ++in_index;
2855 ++out_index;
2856 }
2857 value[out_index] = '\0';
2858 size = out_index;
2859 count = count_substring(value, '\t');
2860
2861 /* extend size of string due to replacing character '\t' with 8 spaces */
2862 retval = malloc(size + 1 + 7 * count);
2863 if (!retval) {
2864 LOGMEM;
2865 goto error;
2866 }
2867 in_index = out_index = space = 0;
2868 while (in_index < size) {
2869 if (value[in_index] == '\n') {
2870 out_index -= space;
2871 space = 0;
2872 retval[out_index] = '\n';
2873 ++out_index;
2874 ++in_index;
2875 in_index = read_indent(value, indent, size, in_index, &out_index, retval);
2876 continue;
2877 } else {
2878 space = (value[in_index] == ' ' || value[in_index] == '\t') ? space + 1 : 0;
2879 retval[out_index] = value[in_index];
2880 ++out_index;
2881 }
2882 ++in_index;
2883 }
2884 retval[out_index] = '\0';
2885 if (out_index != size) {
2886 retval = ly_realloc(retval, out_index + 1);
2887 }
2888 free(value);
2889 return retval;
2890error:
2891 free(value);
2892 return NULL;
2893}