blob: f1ed909b852a64fd31260ca3e9849767fde387d5 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include "parser_yang.h"
23#include "parser_yang_bis.h"
Pavol Vican6eb14e82016-02-03 12:27:13 +010024#include "parser.h"
Pavol Vicanf37eeaa2016-02-09 20:54:06 +010025#include "xpath.h"
Pavol Vican021488a2016-01-25 23:56:12 +010026
Pavol Vican2a064652016-02-02 22:54:34 +010027static int
28yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value, int line)
29{
Pavol Vicanbf805472016-01-26 14:24:56 +010030 if (*target) {
Pavol Vican2a064652016-02-02 22:54:34 +010031 LOGVAL(LYE_TOOMANY, line, what, where);
Pavol Vicanbf805472016-01-26 14:24:56 +010032 free(value);
33 return 1;
34 } else {
Pavol Vican2a064652016-02-02 22:54:34 +010035 *target = lydict_insert_zc(module->ctx, value);
Pavol Vicanbf805472016-01-26 14:24:56 +010036 return 0;
37 }
38}
39
Pavol Vican2a064652016-02-02 22:54:34 +010040int
41yang_read_common(struct lys_module *module, char *value, int type, int line)
42{
Pavol Vican6eb14e82016-02-03 12:27:13 +010043 int ret = 0;
Pavol Vican021488a2016-01-25 23:56:12 +010044
45 switch (type) {
Pavol Vican2a064652016-02-02 22:54:34 +010046 case MODULE_KEYWORD:
47 module->name = lydict_insert_zc(module->ctx, value);
48 break;
49 case NAMESPACE_KEYWORD:
50 ret = yang_check_string(module, &module->ns, "namespace", "module", value, line);
51 break;
Pavol Vican1ca072c2016-02-03 13:03:56 +010052 case ORGANIZATION_KEYWORD:
53 ret = yang_check_string(module, &module->org, "organization", "module", value, line);
54 break;
55 case CONTACT_KEYWORD:
56 ret = yang_check_string(module, &module->contact, "contact", "module", value, line);
57 break;
Pavol Vican2a064652016-02-02 22:54:34 +010058 }
59
Pavol Vican021488a2016-01-25 23:56:12 +010060 return ret;
Pavol Vicanbf805472016-01-26 14:24:56 +010061}
62
Pavol Vican2a064652016-02-02 22:54:34 +010063int
64yang_read_prefix(struct lys_module *module, void *save, char *value, int type, int line)
65{
Pavol Vican6eb14e82016-02-03 12:27:13 +010066 int ret = 0;
Pavol Vicanbf805472016-01-26 14:24:56 +010067
Pavol Vican6eb14e82016-02-03 12:27:13 +010068 if (lyp_check_identifier(value, LY_IDENT_PREFIX, line, module, NULL)) {
69 free(value);
70 return EXIT_FAILURE;
71 }
Pavol Vicanbf805472016-01-26 14:24:56 +010072 switch (type){
Pavol Vican2a064652016-02-02 22:54:34 +010073 case MODULE_KEYWORD:
74 ret = yang_check_string(module, &module->prefix, "prefix", "module", value, line);
75 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +010076 case IMPORT_KEYWORD:
77 ((struct lys_import *)save)->prefix = lydict_insert_zc(module->ctx, value);
78 break;
Pavol Vican2a064652016-02-02 22:54:34 +010079 }
Pavol Vican6eb14e82016-02-03 12:27:13 +010080
Pavol Vicanbf805472016-01-26 14:24:56 +010081 return ret;
82}
Pavol Vican6eb14e82016-02-03 12:27:13 +010083
84void *
85yang_elem_of_array(void **ptr, uint8_t *act_size, int type, int sizeof_struct)
86{
87 void *retval;
88
89 if (!(*act_size % LY_ARRAY_SIZE) && !(*ptr = ly_realloc(*ptr, (*act_size + LY_ARRAY_SIZE) * sizeof_struct))) {
90 LOGMEM;
91 return NULL;
92 }
93 switch (type) {
94 case IMPORT_KEYWORD:
95 retval = &((struct lys_import *)(*ptr))[*act_size];
96 break;
Pavol Vicanbedff692016-02-03 14:29:17 +010097 case REVISION_KEYWORD:
98 retval = &((struct lys_revision *)(*ptr))[*act_size];
99 break;
Pavol Vican6eb14e82016-02-03 12:27:13 +0100100 }
101 (*act_size)++;
102 memset(retval,0,sizeof_struct);
103 return retval;
104}
105
106int
107yang_fill_import(struct lys_module *module, struct lys_import *imp, char *value, int line)
108{
109 int count, i;
110
111 /* check for circular import, store it if passed */
112 if (!module->ctx->models.parsing) {
113 count = 0;
114 } else {
115 for (count = 0; module->ctx->models.parsing[count]; ++count) {
116 if (value == module->ctx->models.parsing[count]) {
117 LOGERR(LY_EVALID, "Circular import dependency on the module \"%s\".", value);
118 goto error;
119 }
120 }
121 }
122 ++count;
123 module->ctx->models.parsing =
124 ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
125 if (!module->ctx->models.parsing) {
126 LOGMEM;
127 goto error;
128 }
129 module->ctx->models.parsing[count - 1] = value;
130 module->ctx->models.parsing[count] = NULL;
131
132 /* try to load the module */
133 imp->module = (struct lys_module *)ly_ctx_get_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
134 if (!imp->module) {
135 /* whether to use a user callback is decided in the function */
136 imp->module = (struct lys_module *)ly_ctx_load_module(module->ctx, value, imp->rev[0] ? imp->rev : NULL);
137 }
138
139 /* remove the new module name now that its parsing is finished (even if failed) */
140 if (module->ctx->models.parsing[count] || (module->ctx->models.parsing[count - 1] != value)) {
141 LOGINT;
142 }
143 --count;
144 if (count) {
145 module->ctx->models.parsing[count] = NULL;
146 } else {
147 free(module->ctx->models.parsing);
148 module->ctx->models.parsing = NULL;
149 }
150
151 /* check the result */
152 if (!imp->module) {
153 LOGERR(LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
154 goto error;
155 }
156
157 module->imp_size++;
158
159 /* check duplicities in imported modules */
160 for (i = 0; i < module->imp_size - 1; i++) {
161 if (!strcmp(module->imp[i].module->name, module->imp[module->imp_size - 1].module->name)) {
162 LOGVAL(LYE_SPEC, line, "Importing module \"%s\" repeatedly.", module->imp[i].module->name);
163 goto error;
164 }
165 }
166
167 free(value);
168 return EXIT_SUCCESS;
169
170 error:
171
172 free(value);
173 return EXIT_FAILURE;
174}
Pavol Vican1ca072c2016-02-03 13:03:56 +0100175
176int
177yang_read_description(struct lys_module *module, void *node, char *value, int type, int line)
178{
179 int ret;
180
181 if (!node) {
182 ret = yang_check_string(module, &module->dsc, "description", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100183 } else {
184 switch (type) {
185 case REVISION_KEYWORD:
186 ret = yang_check_string(module, &((struct lys_revision *) node)->dsc, "description", "revision", value, line);
187 break;
Pavol Vicane1354e92016-02-09 14:02:09 +0100188 case FEATURE_KEYWORD:
189 ret = yang_check_string(module, &((struct lys_feature *) node)->dsc, "description", "feature", value, line);
190 break;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100191 case IDENTITY_KEYWORD:
192 ret = yang_check_string(module, &((struct lys_ident *) node)->dsc, "description", "identity", value, line);
193 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100194 case MUST_KEYWORD:
195 ret = yang_check_string(module, &((struct lys_restr *) node)->dsc, "description", "must", value, line);
196 break;
Pavol Vican235dbd42016-02-10 10:34:19 +0100197 case WHEN_KEYWORD:
198 ret = yang_check_string(module, &((struct lys_when *) node)->dsc, "description", "when" , value, line);
199 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100200 case CONTAINER_KEYWORD:
201 ret = yang_check_string(module, &((struct lys_node_container *) node)->dsc, "description", "container", value, line);
202 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100203 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100204 }
205 return ret;
206}
207
208int
209yang_read_reference(struct lys_module *module, void *node, char *value, int type, int line)
210{
211 int ret;
212
213 if (!node) {
214 ret = yang_check_string(module, &module->ref, "reference", "module", value, line);
Pavol Vicanbedff692016-02-03 14:29:17 +0100215 } else {
216 switch (type) {
217 case REVISION_KEYWORD:
218 ret = yang_check_string(module, &((struct lys_revision *) node)->ref, "reference", "revision", value, line);
219 break;
Pavol Vicanbbdef532016-02-09 14:52:12 +0100220 case FEATURE_KEYWORD:
221 ret = yang_check_string(module, &((struct lys_feature *) node)->ref, "reference", "feature", value, line);
222 break;
223 case IDENTITY_KEYWORD:
224 ret = yang_check_string(module, &((struct lys_ident *) node)->ref, "reference", "identity", value, line);
225 break;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100226 case MUST_KEYWORD:
Pavol Vican235dbd42016-02-10 10:34:19 +0100227 ret = yang_check_string(module, &((struct lys_restr *) node)->ref, "reference", "must", value, line);
228 break;
229 case WHEN_KEYWORD:
230 ret = yang_check_string(module, &((struct lys_when *) node)->ref, "reference", "when", value, line);
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100231 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100232 case CONTAINER_KEYWORD:
233 ret = yang_check_string(module, &((struct lys_node_container *) node)->ref, "reference", "container", value, line);
234 break;
Pavol Vicanbedff692016-02-03 14:29:17 +0100235 }
Pavol Vican1ca072c2016-02-03 13:03:56 +0100236 }
237 return ret;
238}
Pavol Vicanbedff692016-02-03 14:29:17 +0100239
240void *
241yang_read_revision(struct lys_module *module, char *value)
242{
243 struct lys_revision *retval;
244
Pavol Vican1eeb1992016-02-09 11:10:45 +0100245 retval = &module->rev[module->rev_size];
Pavol Vicanbedff692016-02-03 14:29:17 +0100246
247 /* first member of array is last revision */
Pavol Vican1eeb1992016-02-09 11:10:45 +0100248 if (module->rev_size && strcmp(module->rev[0].date, value) < 0) {
Pavol Vicanbedff692016-02-03 14:29:17 +0100249 memcpy(retval->date, module->rev[0].date, LY_REV_SIZE);
250 memcpy(module->rev[0].date, value, LY_REV_SIZE);
251 retval->dsc = module->rev[0].dsc;
252 retval->ref = module->rev[0].ref;
253 retval = module->rev;
254 retval->dsc = NULL;
255 retval->ref = NULL;
256 } else {
257 memcpy(retval->date, value, LY_REV_SIZE);
258 }
Pavol Vican1eeb1992016-02-09 11:10:45 +0100259 module->rev_size++;
Pavol Vicanbedff692016-02-03 14:29:17 +0100260 free(value);
261 return retval;
262}
Pavol Vican1eeb1992016-02-09 11:10:45 +0100263
264int
265yang_add_elem(struct lys_node_array **node, int *size)
266{
267 if (!*size % LY_ARRAY_SIZE) {
268 if (!(*node = ly_realloc(*node, (*size + LY_ARRAY_SIZE) * sizeof **node))) {
269 LOGMEM;
270 return EXIT_FAILURE;
271 } else {
272 memset(*node+*size,0,LY_ARRAY_SIZE*sizeof **node);
273 }
274 }
275 (*size)++;
276 return EXIT_SUCCESS;
277}
Pavol Vicane1354e92016-02-09 14:02:09 +0100278
279void *
280yang_read_feature(struct lys_module *module, char *value, int line)
281{
282 struct lys_feature *retval;
283
284 /* check uniqueness of feature's names */
285 if (lyp_check_identifier(value, LY_IDENT_FEATURE, line, module, NULL)) {
286 goto error;
287 }
288 retval = &module->features[module->features_size];
289 retval->name = lydict_insert_zc(module->ctx, value);
290 retval->module = module;
291 module->features_size++;
292 return retval;
293
294error:
295 free(value);
296 return NULL;
297}
298
299int
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100300yang_read_if_feature(struct lys_module *module, void *ptr, char *value, struct unres_schema *unres, int type, int line)
Pavol Vicane1354e92016-02-09 14:02:09 +0100301{
302 const char *exp;
303 int ret;
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100304 struct lys_feature *f;
305 struct lys_node *n;
Pavol Vicane1354e92016-02-09 14:02:09 +0100306
307 if (!(exp = transform_schema2json(module, value, line))) {
308 free(value);
309 return EXIT_FAILURE;
310 }
311 free(value);
312
313 /* hack - store pointer to the parent node for later status check */
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100314 if (type == FEATURE_KEYWORD) {
315 f = (struct lys_feature *) ptr;
316 f->features[f->features_size] = f;
317 ret = unres_schema_add_str(module, unres, &f->features[f->features_size], UNRES_IFFEAT, exp, line);
318 f->features_size++;
319 } else {
320 n = (struct lys_node *) ptr;
321 n->features[n->features_size] = (struct lys_feature *) n;
322 ret = unres_schema_add_str(module, unres, &n->features[n->features_size], UNRES_IFFEAT, exp, line);
323 n->features_size++;
324 }
Pavol Vicane1354e92016-02-09 14:02:09 +0100325
326 lydict_remove(module->ctx, exp);
327 if (ret == -1) {
328
329 return EXIT_FAILURE;
330 }
331 return EXIT_SUCCESS;
332}
333
334static int
335yang_check_flags(uint8_t *flags, uint8_t mask, char *what, char *where, int value, int line)
336{
337 if (*flags & mask) {
338 LOGVAL(LYE_TOOMANY, line, what, where);
339 return EXIT_FAILURE;
340 } else {
341 *flags = value;
342 return EXIT_SUCCESS;
343 }
344}
345
346int
347yang_read_status(void *node, int value, int type, int line)
348{
349 int retval;
350
351 switch (type) {
352 case FEATURE_KEYWORD:
353 retval = yang_check_flags(&((struct lys_feature *) node)->flags, LYS_STATUS_MASK, "status", "feature", value, line);
354 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100355 case IDENTITY_KEYWORD:
Pavol Vicanbbdef532016-02-09 14:52:12 +0100356 retval = yang_check_flags(&((struct lys_ident *) node)->flags, LYS_STATUS_MASK, "status", "identity", value, line);
357 break;
Pavol Vican7c8ae122016-02-10 11:01:50 +0100358 case CONTAINER_KEYWORD:
359 retval = yang_check_flags(&((struct lys_node_container *) node)->flags, LYS_STATUS_MASK, "status", "container", value, line);
Pavol Vicane1354e92016-02-09 14:02:09 +0100360 }
361 return retval;
362}
Pavol Vicanbbdef532016-02-09 14:52:12 +0100363
364void *
365yang_read_identity(struct lys_module *module, char *value)
366{
367 struct lys_ident *ret;
368
369 ret = &module->ident[module->ident_size];
370 ret->name = lydict_insert_zc(module->ctx, value);
371 ret->module = module;
372 module->ident_size++;
373 return ret;
374}
375
376int
377yang_read_base(struct lys_module *module, struct lys_ident *ident, char *value, struct unres_schema *unres, int line)
378{
379 const char *exp;
380
381 if (ident->base) {
382 LOGVAL(LYE_TOOMANY, line, "base", "identity");
383 return EXIT_FAILURE;
384 }
Pavol Vicanbbdef532016-02-09 14:52:12 +0100385 exp = transform_schema2json(module, value, line);
386 free(value);
387 if (!exp) {
388 return EXIT_FAILURE;
389 }
390 if (unres_schema_add_str(module, unres, ident, UNRES_IDENT, exp, line) == -1) {
391 lydict_remove(module->ctx, exp);
392 return EXIT_FAILURE;
393 }
394 lydict_remove(module->ctx, exp);
395 return EXIT_SUCCESS;
396}
Pavol Vicanf37eeaa2016-02-09 20:54:06 +0100397
398void *
399yang_read_cont(struct lys_module *module, struct lys_node *parent, char *value)
400{
401 struct lys_node_container *cont;
402
403 cont = calloc(1, sizeof *cont);
404 if (!cont) {
405 LOGMEM;
406 return NULL;
407 }
408 cont->module = module;
409 cont->name = lydict_insert_zc(module->ctx, value);
410 cont->nodetype = LYS_CONTAINER;
411 cont->prev = (struct lys_node *)cont;
412 if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, (struct lys_node *)cont)) {
413 lydict_remove(module->ctx, cont->name);
414 free(cont);
415 return NULL;
416 }
417 return cont;
418}
419
420void *
421yang_read_must(struct lys_module *module, struct lys_node *node, char *value, int type, int line)
422{
423 struct lys_restr *retval;
424
425 switch (type) {
426 case CONTAINER_KEYWORD:
427 retval = &((struct lys_node_container *)node)->must[((struct lys_node_container *)node)->must_size];
428 break;
429 }
430 retval->expr = transform_schema2json(module, value, line);
431 if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
432 goto error;
433 }
434 free(value);
435 return retval;
436
437error:
438 free(value);
439 return NULL;
440}
441
442int
443yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, int type, int message, int line)
444{
445 int ret;
446 char *exp;
447
448 switch (type) {
449 case MUST_KEYWORD:
450 exp = "must";
451 break;
452 }
453 if (message==ERROR_APP_TAG_KEYWORD) {
454 ret = yang_check_string(module, &save->eapptag, "error_app_tag", exp, value, line);
455 } else {
456 ret = yang_check_string(module, &save->emsg, "error_app_tag", exp, value, line);
457 }
458 return ret;
459}
Pavol Vicanb5687112016-02-09 22:35:59 +0100460
461int
462yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value, int line)
463{
464 if (cont->presence) {
465 LOGVAL(LYE_TOOMANY, line, "presence", "container");
466 free(value);
467 return EXIT_FAILURE;
468 } else {
469 cont->presence = lydict_insert_zc(module->ctx, value);
470 return EXIT_SUCCESS;
471 }
472}
473
474int
475yang_read_config(void *node, int value, int type, int line)
476{
477 int ret;
478
479 switch (type) {
480 case CONTAINER_KEYWORD:
481 ret = yang_check_flags(&((struct lys_node_container *)node)->flags, LYS_CONFIG_MASK, "config", "container", value, line);
482 break;
483 }
484 return ret;
485}
Pavol Vican235dbd42016-02-10 10:34:19 +0100486
487void *
488yang_read_when(struct lys_module *module, struct lys_node *node, int type, char *value, int line)
489{
490 struct lys_when *retval;
491
492 retval = calloc(1, sizeof *retval);
493 if (!retval) {
494 LOGMEM;
495 free(value);
496 return NULL;
497 }
498 retval->cond = transform_schema2json(module, value, line);
499 if (!retval->cond || lyxp_syntax_check(retval->cond, line)) {
500 goto error;
501 }
502 switch (type) {
503 case CONTAINER_KEYWORD:
504 if (((struct lys_node_container *)node)->when) {
505 LOGVAL(LYE_TOOMANY,line,"when","container");
506 goto error;
507 }
508 ((struct lys_node_container *)node)->when = retval;
509 break;
510 }
511 free(value);
512 return retval;
513
514error:
515 free(value);
516 lys_when_free(module->ctx, retval);
517 return NULL;
518}