1 /**
2 * @file parser.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief common libyang parsers routines implementations
5 *
6 * Copyright (c) 2015-2017 CESNET, z.s.p.o.
7 *
8 * 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
13 */
14
15 #define _GNU_SOURCE
16 #include <assert.h>
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <pcre.h>
29 #include <time.h>
30
31 #include "common.h"
32 #include "context.h"
33 #include "libyang.h"
34 #include "parser.h"
35 #include "resolve.h"
36 #include "tree_internal.h"
37 #include "parser_yang.h"
38 #include "xpath.h"
39
40 #define LYP_URANGE_LEN 19
41
42 static char *lyp_ublock2urange[][2] = {
43 {"BasicLatin", "[\\x{0000}-\\x{007F}]"},
44 {"Latin-1Supplement", "[\\x{0080}-\\x{00FF}]"},
45 {"LatinExtended-A", "[\\x{0100}-\\x{017F}]"},
46 {"LatinExtended-B", "[\\x{0180}-\\x{024F}]"},
47 {"IPAExtensions", "[\\x{0250}-\\x{02AF}]"},
48 {"SpacingModifierLetters", "[\\x{02B0}-\\x{02FF}]"},
49 {"CombiningDiacriticalMarks", "[\\x{0300}-\\x{036F}]"},
50 {"Greek", "[\\x{0370}-\\x{03FF}]"},
51 {"Cyrillic", "[\\x{0400}-\\x{04FF}]"},
52 {"Armenian", "[\\x{0530}-\\x{058F}]"},
53 {"Hebrew", "[\\x{0590}-\\x{05FF}]"},
54 {"Arabic", "[\\x{0600}-\\x{06FF}]"},
55 {"Syriac", "[\\x{0700}-\\x{074F}]"},
56 {"Thaana", "[\\x{0780}-\\x{07BF}]"},
57 {"Devanagari", "[\\x{0900}-\\x{097F}]"},
58 {"Bengali", "[\\x{0980}-\\x{09FF}]"},
59 {"Gurmukhi", "[\\x{0A00}-\\x{0A7F}]"},
60 {"Gujarati", "[\\x{0A80}-\\x{0AFF}]"},
61 {"Oriya", "[\\x{0B00}-\\x{0B7F}]"},
62 {"Tamil", "[\\x{0B80}-\\x{0BFF}]"},
63 {"Telugu", "[\\x{0C00}-\\x{0C7F}]"},
64 {"Kannada", "[\\x{0C80}-\\x{0CFF}]"},
65 {"Malayalam", "[\\x{0D00}-\\x{0D7F}]"},
66 {"Sinhala", "[\\x{0D80}-\\x{0DFF}]"},
67 {"Thai", "[\\x{0E00}-\\x{0E7F}]"},
68 {"Lao", "[\\x{0E80}-\\x{0EFF}]"},
69 {"Tibetan", "[\\x{0F00}-\\x{0FFF}]"},
70 {"Myanmar", "[\\x{1000}-\\x{109F}]"},
71 {"Georgian", "[\\x{10A0}-\\x{10FF}]"},
72 {"HangulJamo", "[\\x{1100}-\\x{11FF}]"},
73 {"Ethiopic", "[\\x{1200}-\\x{137F}]"},
74 {"Cherokee", "[\\x{13A0}-\\x{13FF}]"},
75 {"UnifiedCanadianAboriginalSyllabics", "[\\x{1400}-\\x{167F}]"},
76 {"Ogham", "[\\x{1680}-\\x{169F}]"},
77 {"Runic", "[\\x{16A0}-\\x{16FF}]"},
78 {"Khmer", "[\\x{1780}-\\x{17FF}]"},
79 {"Mongolian", "[\\x{1800}-\\x{18AF}]"},
80 {"LatinExtendedAdditional", "[\\x{1E00}-\\x{1EFF}]"},
81 {"GreekExtended", "[\\x{1F00}-\\x{1FFF}]"},
82 {"GeneralPunctuation", "[\\x{2000}-\\x{206F}]"},
83 {"SuperscriptsandSubscripts", "[\\x{2070}-\\x{209F}]"},
84 {"CurrencySymbols", "[\\x{20A0}-\\x{20CF}]"},
85 {"CombiningMarksforSymbols", "[\\x{20D0}-\\x{20FF}]"},
86 {"LetterlikeSymbols", "[\\x{2100}-\\x{214F}]"},
87 {"NumberForms", "[\\x{2150}-\\x{218F}]"},
88 {"Arrows", "[\\x{2190}-\\x{21FF}]"},
89 {"MathematicalOperators", "[\\x{2200}-\\x{22FF}]"},
90 {"MiscellaneousTechnical", "[\\x{2300}-\\x{23FF}]"},
91 {"ControlPictures", "[\\x{2400}-\\x{243F}]"},
92 {"OpticalCharacterRecognition", "[\\x{2440}-\\x{245F}]"},
93 {"EnclosedAlphanumerics", "[\\x{2460}-\\x{24FF}]"},
94 {"BoxDrawing", "[\\x{2500}-\\x{257F}]"},
95 {"BlockElements", "[\\x{2580}-\\x{259F}]"},
96 {"GeometricShapes", "[\\x{25A0}-\\x{25FF}]"},
97 {"MiscellaneousSymbols", "[\\x{2600}-\\x{26FF}]"},
98 {"Dingbats", "[\\x{2700}-\\x{27BF}]"},
99 {"BraillePatterns", "[\\x{2800}-\\x{28FF}]"},
100 {"CJKRadicalsSupplement", "[\\x{2E80}-\\x{2EFF}]"},
101 {"KangxiRadicals", "[\\x{2F00}-\\x{2FDF}]"},
102 {"IdeographicDescriptionCharacters", "[\\x{2FF0}-\\x{2FFF}]"},
103 {"CJKSymbolsandPunctuation", "[\\x{3000}-\\x{303F}]"},
104 {"Hiragana", "[\\x{3040}-\\x{309F}]"},
105 {"Katakana", "[\\x{30A0}-\\x{30FF}]"},
106 {"Bopomofo", "[\\x{3100}-\\x{312F}]"},
107 {"HangulCompatibilityJamo", "[\\x{3130}-\\x{318F}]"},
108 {"Kanbun", "[\\x{3190}-\\x{319F}]"},
109 {"BopomofoExtended", "[\\x{31A0}-\\x{31BF}]"},
110 {"EnclosedCJKLettersandMonths", "[\\x{3200}-\\x{32FF}]"},
111 {"CJKCompatibility", "[\\x{3300}-\\x{33FF}]"},
112 {"CJKUnifiedIdeographsExtensionA", "[\\x{3400}-\\x{4DB5}]"},
113 {"CJKUnifiedIdeographs", "[\\x{4E00}-\\x{9FFF}]"},
114 {"YiSyllables", "[\\x{A000}-\\x{A48F}]"},
115 {"YiRadicals", "[\\x{A490}-\\x{A4CF}]"},
116 {"HangulSyllables", "[\\x{AC00}-\\x{D7A3}]"},
117 {"PrivateUse", "[\\x{E000}-\\x{F8FF}]"},
118 {"CJKCompatibilityIdeographs", "[\\x{F900}-\\x{FAFF}]"},
119 {"AlphabeticPresentationForms", "[\\x{FB00}-\\x{FB4F}]"},
120 {"ArabicPresentationForms-A", "[\\x{FB50}-\\x{FDFF}]"},
121 {"CombiningHalfMarks", "[\\x{FE20}-\\x{FE2F}]"},
122 {"CJKCompatibilityForms", "[\\x{FE30}-\\x{FE4F}]"},
123 {"SmallFormVariants", "[\\x{FE50}-\\x{FE6F}]"},
124 {"ArabicPresentationForms-B", "[\\x{FE70}-\\x{FEFE}]"},
125 {"HalfwidthandFullwidthForms", "[\\x{FF00}-\\x{FFEF}]"},
126 {"Specials", "[\\x{FEFF}|\\x{FFF0}-\\x{FFFD}]"},
127 {NULL, NULL}
128 };
129
130 const char *ly_stmt_str[] = {
131 [LY_STMT_UNKNOWN] = "",
132 [LY_STMT_ARGUMENT] = "argument",
133 [LY_STMT_BASE] = "base",
134 [LY_STMT_BELONGSTO] = "belongs-to",
135 [LY_STMT_CONTACT] = "contact",
136 [LY_STMT_DEFAULT] = "default",
137 [LY_STMT_DESCRIPTION] = "description",
138 [LY_STMT_ERRTAG] = "error-app-tag",
139 [LY_STMT_ERRMSG] = "error-message",
140 [LY_STMT_KEY] = "key",
141 [LY_STMT_NAMESPACE] = "namespace",
142 [LY_STMT_ORGANIZATION] = "organization",
143 [LY_STMT_PATH] = "path",
144 [LY_STMT_PREFIX] = "prefix",
145 [LY_STMT_PRESENCE] = "presence",
146 [LY_STMT_REFERENCE] = "reference",
147 [LY_STMT_REVISIONDATE] = "revision-date",
148 [LY_STMT_UNITS] = "units",
149 [LY_STMT_VALUE] = "value",
150 [LY_STMT_VERSION] = "yang-version",
151 [LY_STMT_MODIFIER] = "modifier",
152 [LY_STMT_REQINSTANCE] = "require-instance",
153 [LY_STMT_YINELEM] = "yin-element",
154 [LY_STMT_CONFIG] = "config",
155 [LY_STMT_MANDATORY] = "mandatory",
156 [LY_STMT_ORDEREDBY] = "ordered-by",
157 [LY_STMT_STATUS] = "status",
158 [LY_STMT_DIGITS] = "fraction-digits",
159 [LY_STMT_MAX] = "max-elements",
160 [LY_STMT_MIN] = "min-elements",
161 [LY_STMT_POSITION] = "position",
162 [LY_STMT_UNIQUE] = "unique",
163 [LY_STMT_MODULE] = "module",
164 [LY_STMT_SUBMODULE] = "submodule",
165 [LY_STMT_ACTION] = "action",
166 [LY_STMT_ANYDATA] = "anydata",
167 [LY_STMT_ANYXML] = "anyxml",
168 [LY_STMT_CASE] = "case",
169 [LY_STMT_CHOICE] = "choice",
170 [LY_STMT_CONTAINER] = "container",
171 [LY_STMT_GROUPING] = "grouping",
172 [LY_STMT_INPUT] = "input",
173 [LY_STMT_LEAF] = "leaf",
174 [LY_STMT_LEAFLIST] = "leaf-list",
175 [LY_STMT_LIST] = "list",
176 [LY_STMT_NOTIFICATION] = "notification",
177 [LY_STMT_OUTPUT] = "output",
178 [LY_STMT_RPC] = "rpc",
179 [LY_STMT_USES] = "uses",
180 [LY_STMT_TYPEDEF] = "typedef",
181 [LY_STMT_TYPE] = "type",
182 [LY_STMT_BIT] = "bit",
183 [LY_STMT_ENUM] = "enum",
184 [LY_STMT_REFINE] = "refine",
185 [LY_STMT_AUGMENT] = "augment",
186 [LY_STMT_DEVIATE] = "deviate",
187 [LY_STMT_DEVIATION] = "deviation",
188 [LY_STMT_EXTENSION] = "extension",
189 [LY_STMT_FEATURE] = "feature",
190 [LY_STMT_IDENTITY] = "identity",
191 [LY_STMT_IFFEATURE] = "if-feature",
192 [LY_STMT_IMPORT] = "import",
193 [LY_STMT_INCLUDE] = "include",
194 [LY_STMT_LENGTH] = "length",
195 [LY_STMT_MUST] = "must",
196 [LY_STMT_PATTERN] = "pattern",
197 [LY_STMT_RANGE] = "range",
198 [LY_STMT_WHEN] = "when",
199 [LY_STMT_REVISION] = "revision"
200 };
201
202 int
lyp_is_rpc_action(struct lys_node * node)203 lyp_is_rpc_action(struct lys_node *node)
204 {
205 assert(node);
206
207 while (lys_parent(node)) {
208 node = lys_parent(node);
209 if (node->nodetype == LYS_ACTION) {
210 break;
211 }
212 }
213
214 if (node->nodetype & (LYS_RPC | LYS_ACTION)) {
215 return 1;
216 } else {
217 return 0;
218 }
219 }
220
221 int
lyp_data_check_options(struct ly_ctx * ctx,int options,const char * func)222 lyp_data_check_options(struct ly_ctx *ctx, int options, const char *func)
223 {
224 int x = options & LYD_OPT_TYPEMASK;
225
226 /* LYD_OPT_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG */
227 if (options & LYD_OPT_WHENAUTODEL) {
228 if ((x == LYD_OPT_EDIT) || (x == LYD_OPT_NOTIF_FILTER)) {
229 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_WHENAUTODEL can be used only with LYD_OPT_DATA or LYD_OPT_CONFIG)",
230 func, options);
231 return 1;
232 }
233 }
234
235 if (options & (LYD_OPT_DATA_ADD_YANGLIB | LYD_OPT_DATA_NO_YANGLIB)) {
236 if (x != LYD_OPT_DATA) {
237 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (LYD_OPT_DATA_*_YANGLIB can be used only with LYD_OPT_DATA)",
238 func, options);
239 return 1;
240 }
241 }
242
243 /* "is power of 2" algorithm, with 0 exception */
244 if (x && !(x && !(x & (x - 1)))) {
245 LOGERR(ctx, LY_EINVAL, "%s: Invalid options 0x%x (multiple data type flags set).", func, options);
246 return 1;
247 }
248
249 return 0;
250 }
251
252 int
lyp_mmap(struct ly_ctx * ctx,int fd,size_t addsize,size_t * length,void ** addr)253 lyp_mmap(struct ly_ctx *ctx, int fd, size_t addsize, size_t *length, void **addr)
254 {
255 struct stat sb;
256 long pagesize;
257 size_t m;
258
259 assert(fd >= 0);
260 if (fstat(fd, &sb) == -1) {
261 LOGERR(ctx, LY_ESYS, "Failed to stat the file descriptor (%s) for the mmap().", strerror(errno));
262 return 1;
263 }
264 if (!S_ISREG(sb.st_mode)) {
265 LOGERR(ctx, LY_EINVAL, "File to mmap() is not a regular file.");
266 return 1;
267 }
268 if (!sb.st_size) {
269 *addr = NULL;
270 return 0;
271 }
272 pagesize = sysconf(_SC_PAGESIZE);
273 ++addsize; /* at least one additional byte for terminating NULL byte */
274
275 m = sb.st_size % pagesize;
276 if (m && pagesize - m >= addsize) {
277 /* there will be enough space after the file content mapping to provide zeroed additional bytes */
278 *length = sb.st_size + addsize;
279 *addr = mmap(NULL, *length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
280 } else {
281 /* there will not be enough bytes after the file content mapping for the additional bytes and some of them
282 * would overflow into another page that would not be zeroed and any access into it would generate SIGBUS.
283 * Therefore we have to do the following hack with double mapping. First, the required number of bytes
284 * (including the additional bytes) is required as anonymous and thus they will be really provided (actually more
285 * because of using whole pages) and also initialized by zeros. Then, the file is mapped to the same address
286 * where the anonymous mapping starts. */
287 *length = sb.st_size + pagesize;
288 *addr = mmap(NULL, *length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
289 *addr = mmap(*addr, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, fd, 0);
290 }
291 if (*addr == MAP_FAILED) {
292 LOGERR(ctx, LY_ESYS, "mmap() failed (%s).", strerror(errno));
293 return 1;
294 }
295
296 return 0;
297 }
298
299 int
lyp_munmap(void * addr,size_t length)300 lyp_munmap(void *addr, size_t length)
301 {
302 if (!addr) {
303 /* nothing to unmap */
304 return 0;
305 }
306
307 return munmap(addr, length);
308 }
309
310 int
lyp_add_ietf_netconf_annotations_config(struct lys_module * mod)311 lyp_add_ietf_netconf_annotations_config(struct lys_module *mod)
312 {
313 void *reallocated;
314 struct lys_ext_instance_complex *op;
315 struct lys_type **type;
316 struct lys_node_anydata *anyxml;
317 int i;
318 struct ly_ctx *ctx = mod->ctx; /* shortcut */
319
320 reallocated = realloc(mod->ext, (mod->ext_size + 3) * sizeof *mod->ext);
321 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx), EXIT_FAILURE);
322 mod->ext = reallocated;
323 /* 1) edit-config's operation */
324 op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
325 LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
326 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
327 op->arg_value = lydict_insert(ctx, "operation", 9);
328 op->def = &ctx->models.list[0]->extensions[0];
329 op->ext_type = LYEXT_COMPLEX;
330 op->module = op->parent = mod;
331 op->parent_type = LYEXT_PAR_MODULE;
332 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
333 op->nodetype = LYS_EXT;
334 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
335 *type = calloc(1, sizeof(struct lys_type));
336 LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
337 (*type)->base = LY_TYPE_ENUM;
338 (*type)->der = ly_types[LY_TYPE_ENUM];
339 (*type)->parent = (struct lys_tpdf *)op;
340 (*type)->info.enums.count = 5;
341 (*type)->info.enums.enm = calloc(5, sizeof *(*type)->info.enums.enm);
342 LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm, LOGMEM(ctx), EXIT_FAILURE);
343 (*type)->info.enums.enm[0].value = 0;
344 (*type)->info.enums.enm[0].name = lydict_insert(ctx, "merge", 5);
345 (*type)->info.enums.enm[1].value = 1;
346 (*type)->info.enums.enm[1].name = lydict_insert(ctx, "replace", 7);
347 (*type)->info.enums.enm[2].value = 2;
348 (*type)->info.enums.enm[2].name = lydict_insert(ctx, "create", 6);
349 (*type)->info.enums.enm[3].value = 3;
350 (*type)->info.enums.enm[3].name = lydict_insert(ctx, "delete", 6);
351 (*type)->info.enums.enm[4].value = 4;
352 (*type)->info.enums.enm[4].name = lydict_insert(ctx, "remove", 6);
353 mod->ext_size++;
354
355 /* 2) filter's type */
356 op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
357 LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
358 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
359 op->arg_value = lydict_insert(ctx, "type", 4);
360 op->def = &ctx->models.list[0]->extensions[0];
361 op->ext_type = LYEXT_COMPLEX;
362 op->module = op->parent = mod;
363 op->parent_type = LYEXT_PAR_MODULE;
364 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
365 op->nodetype = LYS_EXT;
366 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
367 *type = calloc(1, sizeof(struct lys_type));
368 LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
369 (*type)->base = LY_TYPE_ENUM;
370 (*type)->der = ly_types[LY_TYPE_ENUM];
371 (*type)->parent = (struct lys_tpdf *)op;
372 (*type)->info.enums.count = 2;
373 (*type)->info.enums.enm = calloc(2, sizeof *(*type)->info.enums.enm);
374 LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm, LOGMEM(ctx), EXIT_FAILURE);
375 (*type)->info.enums.enm[0].value = 0;
376 (*type)->info.enums.enm[0].name = lydict_insert(ctx, "subtree", 7);
377 (*type)->info.enums.enm[1].value = 1;
378 (*type)->info.enums.enm[1].name = lydict_insert(ctx, "xpath", 5);
379 for (i = mod->features_size; i > 0; i--) {
380 if (!strcmp(mod->features[i - 1].name, "xpath")) {
381 (*type)->info.enums.enm[1].iffeature_size = 1;
382 (*type)->info.enums.enm[1].iffeature = calloc(1, sizeof(struct lys_feature));
383 LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature, LOGMEM(ctx), EXIT_FAILURE);
384 (*type)->info.enums.enm[1].iffeature[0].expr = malloc(sizeof(uint8_t));
385 LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature[0].expr, LOGMEM(ctx), EXIT_FAILURE);
386 *(*type)->info.enums.enm[1].iffeature[0].expr = 3; /* LYS_IFF_F */
387 (*type)->info.enums.enm[1].iffeature[0].features = malloc(sizeof(struct lys_feature*));
388 LY_CHECK_ERR_RETURN(!(*type)->info.enums.enm[1].iffeature[0].features, LOGMEM(ctx), EXIT_FAILURE);
389 (*type)->info.enums.enm[1].iffeature[0].features[0] = &mod->features[i - 1];
390 break;
391 }
392 }
393 mod->ext_size++;
394
395 /* 3) filter's select */
396 op = calloc(1, (sizeof(struct lys_ext_instance_complex) - 1) + 5 * sizeof(void*) + sizeof(uint16_t));
397 LY_CHECK_ERR_RETURN(!op, LOGMEM(ctx), EXIT_FAILURE);
398 mod->ext[mod->ext_size] = (struct lys_ext_instance *)op;
399 op->arg_value = lydict_insert(ctx, "select", 6);
400 op->def = &ctx->models.list[0]->extensions[0];
401 op->ext_type = LYEXT_COMPLEX;
402 op->module = op->parent = mod;
403 op->parent_type = LYEXT_PAR_MODULE;
404 op->substmt = ((struct lyext_plugin_complex *)op->def->plugin)->substmt;
405 op->nodetype = LYS_EXT;
406 type = (struct lys_type**)&op->content; /* type is stored at offset 0 */
407 *type = calloc(1, sizeof(struct lys_type));
408 LY_CHECK_ERR_RETURN(!*type, LOGMEM(ctx), EXIT_FAILURE);
409 (*type)->base = LY_TYPE_STRING;
410 (*type)->der = ly_types[LY_TYPE_STRING];
411 (*type)->parent = (struct lys_tpdf *)op;
412 mod->ext_size++;
413
414 /* 4) URL config */
415 anyxml = calloc(1, sizeof *anyxml);
416 LY_CHECK_ERR_RETURN(!anyxml, LOGMEM(ctx), EXIT_FAILURE);
417 anyxml->nodetype = LYS_ANYXML;
418 anyxml->prev = (struct lys_node *)anyxml;
419 anyxml->name = lydict_insert(ctx, "config", 0);
420 anyxml->module = mod;
421 anyxml->flags = LYS_CONFIG_W;
422 if (lys_node_addchild(NULL, mod, (struct lys_node *)anyxml, 0)) {
423 return EXIT_FAILURE;
424 }
425
426 return EXIT_SUCCESS;
427 }
428
429 /* logs directly
430 * base: 0 - to accept decimal, octal, hexadecimal (in default value)
431 * 10 - to accept only decimal (instance value)
432 */
433 static int
parse_int(const char * val_str,int64_t min,int64_t max,int base,int64_t * ret,struct lyd_node * node)434 parse_int(const char *val_str, int64_t min, int64_t max, int base, int64_t *ret, struct lyd_node *node)
435 {
436 char *strptr;
437
438 assert(node);
439
440 if (!val_str || !val_str[0]) {
441 goto error;
442 }
443
444 /* convert to 64-bit integer, all the redundant characters are handled */
445 errno = 0;
446 strptr = NULL;
447
448 /* parse the value */
449 *ret = strtoll(val_str, &strptr, base);
450 if (errno || (*ret < min) || (*ret > max)) {
451 goto error;
452 } else if (strptr && *strptr) {
453 while (isspace(*strptr)) {
454 ++strptr;
455 }
456 if (*strptr) {
457 goto error;
458 }
459 }
460
461 return EXIT_SUCCESS;
462
463 error:
464 LOGVAL(node->schema->module->ctx, LYE_INVAL, LY_VLOG_LYD, node, val_str ? val_str : "", node->schema->name);
465 return EXIT_FAILURE;
466 }
467
468 /* logs directly
469 * base: 0 - to accept decimal, octal, hexadecimal (in default value)
470 * 10 - to accept only decimal (instance value)
471 */
472 static int
parse_uint(const char * val_str,uint64_t max,int base,uint64_t * ret,struct lyd_node * node)473 parse_uint(const char *val_str, uint64_t max, int base, uint64_t *ret, struct lyd_node *node)
474 {
475 char *strptr;
476 uint64_t u;
477
478 assert(node);
479
480 if (!val_str || !val_str[0]) {
481 goto error;
482 }
483
484 errno = 0;
485 strptr = NULL;
486 u = strtoull(val_str, &strptr, base);
487 if (errno || (u > max)) {
488 goto error;
489 } else if (strptr && *strptr) {
490 while (isspace(*strptr)) {
491 ++strptr;
492 }
493 if (*strptr) {
494 goto error;
495 }
496 } else if (u != 0 && val_str[0] == '-') {
497 goto error;
498 }
499
500 *ret = u;
501 return EXIT_SUCCESS;
502
503 error:
504 LOGVAL(node->schema->module->ctx, LYE_INVAL, LY_VLOG_LYD, node, val_str ? val_str : "", node->schema->name);
505 return EXIT_FAILURE;
506 }
507
508 /* logs directly
509 *
510 * kind == 0 - unsigned (unum used), 1 - signed (snum used), 2 - floating point (fnum used)
511 */
512 static int
validate_length_range(uint8_t kind,uint64_t unum,int64_t snum,int64_t fnum,uint8_t fnum_dig,struct lys_type * type,const char * val_str,struct lyd_node * node)513 validate_length_range(uint8_t kind, uint64_t unum, int64_t snum, int64_t fnum, uint8_t fnum_dig, struct lys_type *type,
514 const char *val_str, struct lyd_node *node)
515 {
516 struct lys_restr *restr = NULL;
517 struct len_ran_intv *intv = NULL, *tmp_intv;
518 struct lys_type *cur_type;
519 struct ly_ctx *ctx = type->parent->module->ctx;
520 int match;
521
522 if (resolve_len_ran_interval(ctx, NULL, type, &intv)) {
523 /* already done during schema parsing */
524 LOGINT(ctx);
525 return EXIT_FAILURE;
526 }
527 if (!intv) {
528 return EXIT_SUCCESS;
529 }
530
531 /* I know that all intervals belonging to a single restriction share one type pointer */
532 tmp_intv = intv;
533 cur_type = intv->type;
534 do {
535 match = 0;
536 for (; tmp_intv && (tmp_intv->type == cur_type); tmp_intv = tmp_intv->next) {
537 if (match) {
538 /* just iterate through the rest of this restriction intervals */
539 continue;
540 }
541
542 if (((kind == 0) && (unum < tmp_intv->value.uval.min))
543 || ((kind == 1) && (snum < tmp_intv->value.sval.min))
544 || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) < 0))) {
545 break;
546 }
547
548 if (((kind == 0) && (unum >= tmp_intv->value.uval.min) && (unum <= tmp_intv->value.uval.max))
549 || ((kind == 1) && (snum >= tmp_intv->value.sval.min) && (snum <= tmp_intv->value.sval.max))
550 || ((kind == 2) && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.min, cur_type->info.dec64.dig) > -1)
551 && (dec64cmp(fnum, fnum_dig, tmp_intv->value.fval.max, cur_type->info.dec64.dig) < 1))) {
552 match = 1;
553 }
554 }
555
556 if (!match) {
557 break;
558 } else if (tmp_intv) {
559 cur_type = tmp_intv->type;
560 }
561 } while (tmp_intv);
562
563 while (intv) {
564 tmp_intv = intv->next;
565 free(intv);
566 intv = tmp_intv;
567 }
568
569 if (!match) {
570 switch (cur_type->base) {
571 case LY_TYPE_BINARY:
572 restr = cur_type->info.binary.length;
573 break;
574 case LY_TYPE_DEC64:
575 restr = cur_type->info.dec64.range;
576 break;
577 case LY_TYPE_INT8:
578 case LY_TYPE_INT16:
579 case LY_TYPE_INT32:
580 case LY_TYPE_INT64:
581 case LY_TYPE_UINT8:
582 case LY_TYPE_UINT16:
583 case LY_TYPE_UINT32:
584 case LY_TYPE_UINT64:
585 restr = cur_type->info.num.range;
586 break;
587 case LY_TYPE_STRING:
588 restr = cur_type->info.str.length;
589 break;
590 default:
591 LOGINT(ctx);
592 return EXIT_FAILURE;
593 }
594
595 LOGVAL(ctx, LYE_NOCONSTR, LY_VLOG_LYS, node->schema, (val_str ? val_str : ""), restr ? restr->expr : "");
596 if (restr && restr->emsg) {
597 ly_vlog_str(ctx, LY_VLOG_PREV, restr->emsg);
598 }
599 if (restr && restr->eapptag) {
600 ly_err_last_set_apptag(ctx, restr->eapptag);
601 }
602 return EXIT_FAILURE;
603 }
604 return EXIT_SUCCESS;
605 }
606
607 /* logs directly */
608 static int
validate_pattern(struct ly_ctx * ctx,const char * val_str,struct lys_type * type,struct lyd_node * node)609 validate_pattern(struct ly_ctx *ctx, const char *val_str, struct lys_type *type, struct lyd_node *node)
610 {
611 int rc;
612 unsigned int i;
613 #ifndef LY_ENABLED_CACHE
614 pcre *precomp;
615 #endif
616
617 assert(ctx && (type->base == LY_TYPE_STRING));
618
619 if (!val_str) {
620 val_str = "";
621 }
622
623 if (type->der && validate_pattern(ctx, val_str, &type->der->type, node)) {
624 return EXIT_FAILURE;
625 }
626
627 #ifdef LY_ENABLED_CACHE
628 /* there is no cache, build it */
629 if (!type->info.str.patterns_pcre && type->info.str.pat_count) {
630 type->info.str.patterns_pcre = malloc(2 * type->info.str.pat_count * sizeof *type->info.str.patterns_pcre);
631 LY_CHECK_ERR_RETURN(!type->info.str.patterns_pcre, LOGMEM(ctx), -1);
632
633 for (i = 0; i < type->info.str.pat_count; ++i) {
634 if (lyp_precompile_pattern(ctx, &type->info.str.patterns[i].expr[1],
635 (pcre**)&type->info.str.patterns_pcre[i * 2],
636 (pcre_extra**)&type->info.str.patterns_pcre[i * 2 + 1])) {
637 return EXIT_FAILURE;
638 }
639 }
640 }
641 #endif
642
643 for (i = 0; i < type->info.str.pat_count; ++i) {
644 #ifdef LY_ENABLED_CACHE
645 rc = pcre_exec((pcre *)type->info.str.patterns_pcre[2 * i], (pcre_extra *)type->info.str.patterns_pcre[2 * i + 1],
646 val_str, strlen(val_str), 0, 0, NULL, 0);
647 #else
648 if (lyp_check_pattern(ctx, &type->info.str.patterns[i].expr[1], &precomp)) {
649 return EXIT_FAILURE;
650 }
651 rc = pcre_exec(precomp, NULL, val_str, strlen(val_str), 0, 0, NULL, 0);
652 free(precomp);
653 #endif
654 if ((rc && type->info.str.patterns[i].expr[0] == 0x06) || (!rc && type->info.str.patterns[i].expr[0] == 0x15)) {
655 LOGVAL(ctx, LYE_NOCONSTR, LY_VLOG_LYD, node, val_str, &type->info.str.patterns[i].expr[1]);
656 if (type->info.str.patterns[i].emsg) {
657 ly_vlog_str(ctx, LY_VLOG_PREV, type->info.str.patterns[i].emsg);
658 }
659 if (type->info.str.patterns[i].eapptag) {
660 ly_err_last_set_apptag(ctx, type->info.str.patterns[i].eapptag);
661 }
662 return EXIT_FAILURE;
663 }
664 }
665
666 return EXIT_SUCCESS;
667 }
668
669 static void
check_number(const char * str_num,const char ** num_end,LY_DATA_TYPE base)670 check_number(const char *str_num, const char **num_end, LY_DATA_TYPE base)
671 {
672 if (!isdigit(str_num[0]) && (str_num[0] != '-') && (str_num[0] != '+')) {
673 *num_end = str_num;
674 return;
675 }
676
677 if ((str_num[0] == '-') || (str_num[0] == '+')) {
678 ++str_num;
679 }
680
681 while (isdigit(str_num[0])) {
682 ++str_num;
683 }
684
685 if ((base != LY_TYPE_DEC64) || (str_num[0] != '.') || !isdigit(str_num[1])) {
686 *num_end = str_num;
687 return;
688 }
689
690 ++str_num;
691 while (isdigit(str_num[0])) {
692 ++str_num;
693 }
694
695 *num_end = str_num;
696 }
697
698 /**
699 * @brief Checks the syntax of length or range statement,
700 * on success checks the semantics as well. Does not log.
701 *
702 * @param[in] expr Length or range expression.
703 * @param[in] type Type with the restriction.
704 *
705 * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise.
706 */
707 int
lyp_check_length_range(struct ly_ctx * ctx,const char * expr,struct lys_type * type)708 lyp_check_length_range(struct ly_ctx *ctx, const char *expr, struct lys_type *type)
709 {
710 struct len_ran_intv *intv = NULL, *tmp_intv;
711 const char *c = expr, *tail;
712 int ret = EXIT_FAILURE, flg = 1; /* first run flag */
713
714 assert(expr);
715
716 lengthpart:
717
718 while (isspace(*c)) {
719 c++;
720 }
721
722 /* lower boundary or explicit number */
723 if (!strncmp(c, "max", 3)) {
724 max:
725 c += 3;
726 while (isspace(*c)) {
727 c++;
728 }
729 if (*c != '\0') {
730 goto error;
731 }
732
733 goto syntax_ok;
734
735 } else if (!strncmp(c, "min", 3)) {
736 if (!flg) {
737 /* min cannot be used elsewhere than in the first length-part */
738 goto error;
739 } else {
740 flg = 0;
741 }
742 c += 3;
743 while (isspace(*c)) {
744 c++;
745 }
746
747 if (*c == '|') {
748 c++;
749 /* process next length-part */
750 goto lengthpart;
751 } else if (*c == '\0') {
752 goto syntax_ok;
753 } else if (!strncmp(c, "..", 2)) {
754 upper:
755 c += 2;
756 while (isspace(*c)) {
757 c++;
758 }
759 if (*c == '\0') {
760 goto error;
761 }
762
763 /* upper boundary */
764 if (!strncmp(c, "max", 3)) {
765 goto max;
766 }
767
768 check_number(c, &tail, type->base);
769 if (c == tail) {
770 goto error;
771 }
772 c = tail;
773 while (isspace(*c)) {
774 c++;
775 }
776 if (*c == '\0') {
777 goto syntax_ok;
778 } else if (*c == '|') {
779 c++;
780 /* process next length-part */
781 goto lengthpart;
782 } else {
783 goto error;
784 }
785 } else {
786 goto error;
787 }
788
789 } else if (isdigit(*c) || (*c == '-') || (*c == '+')) {
790 /* number */
791 check_number(c, &tail, type->base);
792 if (c == tail) {
793 goto error;
794 }
795 c = tail;
796
797 while (isspace(*c)) {
798 c++;
799 }
800
801 if (*c == '|') {
802 c++;
803 /* process next length-part */
804 goto lengthpart;
805 } else if (*c == '\0') {
806 goto syntax_ok;
807 } else if (!strncmp(c, "..", 2)) {
808 goto upper;
809 }
810
811 } else {
812 goto error;
813 }
814
815 syntax_ok:
816 if (resolve_len_ran_interval(ctx, expr, type, &intv)) {
817 goto error;
818 }
819
820 ret = EXIT_SUCCESS;
821
822 error:
823 while (intv) {
824 tmp_intv = intv->next;
825 free(intv);
826 intv = tmp_intv;
827 }
828
829 return ret;
830 }
831
832 /**
833 * @brief Checks pattern syntax. Logs directly.
834 *
835 * @param[in] pattern Pattern to check.
836 * @param[out] pcre_precomp Precompiled PCRE pattern. Can be NULL.
837 * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise.
838 */
839 int
lyp_check_pattern(struct ly_ctx * ctx,const char * pattern,pcre ** pcre_precomp)840 lyp_check_pattern(struct ly_ctx *ctx, const char *pattern, pcre **pcre_precomp)
841 {
842 int idx, idx2, start, end, err_offset, count, end_anchor = 0;
843 char *perl_regex, *ptr;
844 const char *err_msg, *orig_ptr;
845 pcre *precomp;
846
847 /*
848 * adjust the expression to a Perl equivalent
849 *
850 * http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#regexs
851 */
852
853 /* we need to replace all "$" with "\$", count them now */
854 for (count = 0, ptr = strchr(pattern, '$'); ptr; ++count, ptr = strchr(ptr + 1, '$'));
855
856 perl_regex = malloc((strlen(pattern) + 4 + count) * sizeof(char));
857 LY_CHECK_ERR_RETURN(!perl_regex, LOGMEM(ctx), EXIT_FAILURE);
858 perl_regex[0] = '\0';
859
860 ptr = perl_regex;
861
862 if ((strlen(pattern) > 1) && strncmp(pattern + strlen(pattern) - 2, ".*", 2)) {
863 /* we wil add line-end anchoring */
864 end_anchor = 1;
865
866 ptr[0] = '(';
867 ++ptr;
868 }
869
870 for (orig_ptr = pattern; orig_ptr[0]; ++orig_ptr) {
871 if (orig_ptr[0] == '$') {
872 ptr += sprintf(ptr, "\\$");
873 } else {
874 ptr[0] = orig_ptr[0];
875 ++ptr;
876 }
877 }
878
879 if (end_anchor) {
880 ptr += sprintf(ptr, ")$");
881 } else {
882 ptr[0] = '\0';
883 ++ptr;
884 }
885
886 /* substitute Unicode Character Blocks with exact Character Ranges */
887 while ((ptr = strstr(perl_regex, "\\p{Is"))) {
888 start = ptr - perl_regex;
889
890 ptr = strchr(ptr, '}');
891 if (!ptr) {
892 LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + start + 2, "unterminated character property");
893 free(perl_regex);
894 return EXIT_FAILURE;
895 }
896
897 end = (ptr - perl_regex) + 1;
898
899 /* need more space */
900 if (end - start < LYP_URANGE_LEN) {
901 perl_regex = ly_realloc(perl_regex, strlen(perl_regex) + (LYP_URANGE_LEN - (end - start)) + 1);
902 LY_CHECK_ERR_RETURN(!perl_regex, LOGMEM(ctx); free(perl_regex), EXIT_FAILURE);
903 }
904
905 /* find our range */
906 for (idx = 0; lyp_ublock2urange[idx][0]; ++idx) {
907 if (!strncmp(perl_regex + start + 5, lyp_ublock2urange[idx][0], strlen(lyp_ublock2urange[idx][0]))) {
908 break;
909 }
910 }
911 if (!lyp_ublock2urange[idx][0]) {
912 LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + start + 5, "unknown block name");
913 free(perl_regex);
914 return EXIT_FAILURE;
915 }
916
917 /* make the space in the string and replace the block (but we cannot include brackets if it was already enclosed in them) */
918 for (idx2 = 0, count = 0; idx2 < start; ++idx2) {
919 if ((perl_regex[idx2] == '[') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
920 ++count;
921 }
922 if ((perl_regex[idx2] == ']') && (!idx2 || (perl_regex[idx2 - 1] != '\\'))) {
923 --count;
924 }
925 }
926 if (count) {
927 /* skip brackets */
928 memmove(perl_regex + start + (LYP_URANGE_LEN - 2), perl_regex + end, strlen(perl_regex + end) + 1);
929 memcpy(perl_regex + start, lyp_ublock2urange[idx][1] + 1, LYP_URANGE_LEN - 2);
930 } else {
931 memmove(perl_regex + start + LYP_URANGE_LEN, perl_regex + end, strlen(perl_regex + end) + 1);
932 memcpy(perl_regex + start, lyp_ublock2urange[idx][1], LYP_URANGE_LEN);
933 }
934 }
935
936 /* must return 0, already checked during parsing */
937 precomp = pcre_compile(perl_regex, PCRE_UTF8 | PCRE_ANCHORED | PCRE_DOLLAR_ENDONLY | PCRE_NO_AUTO_CAPTURE,
938 &err_msg, &err_offset, NULL);
939 if (!precomp) {
940 LOGVAL(ctx, LYE_INREGEX, LY_VLOG_NONE, NULL, pattern, perl_regex + err_offset, err_msg);
941 free(perl_regex);
942 return EXIT_FAILURE;
943 }
944 free(perl_regex);
945
946 if (pcre_precomp) {
947 *pcre_precomp = precomp;
948 } else {
949 free(precomp);
950 }
951
952 return EXIT_SUCCESS;
953 }
954
955 int
lyp_precompile_pattern(struct ly_ctx * ctx,const char * pattern,pcre ** pcre_cmp,pcre_extra ** pcre_std)956 lyp_precompile_pattern(struct ly_ctx *ctx, const char *pattern, pcre** pcre_cmp, pcre_extra **pcre_std)
957 {
958 const char *err_msg = NULL;
959
960 if (lyp_check_pattern(ctx, pattern, pcre_cmp)) {
961 return EXIT_FAILURE;
962 }
963
964 if (pcre_std && pcre_cmp) {
965 (*pcre_std) = pcre_study(*pcre_cmp, 0, &err_msg);
966 if (err_msg) {
967 LOGWRN(ctx, "Studying pattern \"%s\" failed (%s).", pattern, err_msg);
968 }
969 }
970
971 return EXIT_SUCCESS;
972 }
973
974 /**
975 * @brief Change the value into its canonical form. In libyang, additionally to the RFC,
976 * all identities have their module as a prefix in their canonical form.
977 *
978 * @param[in] ctx
979 * @param[in] type Type of the value.
980 * @param[in,out] value Original and then canonical value.
981 * @param[in] data1 If \p type is #LY_TYPE_BITS: (struct lys_type_bit **) type bit field,
982 * #LY_TYPE_DEC64: (int64_t *) parsed digits of the number itself without floating point,
983 * #LY_TYPE_IDENT: (const char *) local module name (identityref node module),
984 * #LY_TYPE_INT*: (int64_t *) parsed int number itself,
985 * #LY_TYPE_UINT*: (uint64_t *) parsed uint number itself,
986 * otherwise ignored.
987 * @param[in] data2 If \p type is #LY_TYPE_BITS: (int *) type bit field length,
988 * #LY_TYPE_DEC64: (uint8_t *) number of fraction digits (position of the floating point),
989 * otherwise ignored.
990 * @return 1 if a conversion took place, 0 if the value was kept the same, -1 on error.
991 */
992 static int
make_canonical(struct ly_ctx * ctx,int type,const char ** value,void * data1,void * data2)993 make_canonical(struct ly_ctx *ctx, int type, const char **value, void *data1, void *data2)
994 {
995 const uint16_t buf_len = 511;
996 char buf[buf_len + 1];
997 struct lys_type_bit **bits = NULL;
998 struct lyxp_expr *exp;
999 const char *module_name, *cur_expr, *end;
1000 int i, j, count;
1001 int64_t num;
1002 uint64_t unum;
1003 uint8_t c;
1004
1005 #define LOGBUF(str) LOGERR(ctx, LY_EINVAL, "Value \"%s\" is too long.", str)
1006
1007 switch (type) {
1008 case LY_TYPE_BITS:
1009 bits = (struct lys_type_bit **)data1;
1010 count = *((int *)data2);
1011 /* in canonical form, the bits are ordered by their position */
1012 buf[0] = '\0';
1013 for (i = 0; i < count; i++) {
1014 if (!bits[i]) {
1015 /* bit not set */
1016 continue;
1017 }
1018 if (buf[0]) {
1019 LY_CHECK_ERR_RETURN(strlen(buf) + 1 + strlen(bits[i]->name) > buf_len, LOGBUF(bits[i]->name), -1);
1020 sprintf(buf + strlen(buf), " %s", bits[i]->name);
1021 } else {
1022 LY_CHECK_ERR_RETURN(strlen(bits[i]->name) > buf_len, LOGBUF(bits[i]->name), -1);
1023 strcpy(buf, bits[i]->name);
1024 }
1025 }
1026 break;
1027
1028 case LY_TYPE_IDENT:
1029 module_name = (const char *)data1;
1030 /* identity must always have a prefix */
1031 if (!strchr(*value, ':')) {
1032 LY_CHECK_ERR_RETURN(strlen(module_name) + 1 + strlen(*value) > buf_len, LOGBUF(*value), -1);
1033 sprintf(buf, "%s:%s", module_name, *value);
1034 } else {
1035 LY_CHECK_ERR_RETURN(strlen(*value) > buf_len, LOGBUF(*value), -1);
1036 strcpy(buf, *value);
1037 }
1038 break;
1039
1040 case LY_TYPE_INST:
1041 exp = lyxp_parse_expr(ctx, *value);
1042 LY_CHECK_ERR_RETURN(!exp, LOGINT(ctx), -1);
1043
1044 module_name = NULL;
1045 count = 0;
1046 for (i = 0; (unsigned)i < exp->used; ++i) {
1047 cur_expr = &exp->expr[exp->expr_pos[i]];
1048
1049 /* copy WS */
1050 if (i && ((end = exp->expr + exp->expr_pos[i - 1] + exp->tok_len[i - 1]) != cur_expr)) {
1051 if (count + (cur_expr - end) > buf_len) {
1052 LOGBUF(end);
1053 lyxp_expr_free(exp);
1054 return -1;
1055 }
1056 strncpy(&buf[count], end, cur_expr - end);
1057 count += cur_expr - end;
1058 }
1059
1060 if ((exp->tokens[i] == LYXP_TOKEN_NAMETEST) && (end = strnchr(cur_expr, ':', exp->tok_len[i]))) {
1061 /* get the module name with ":" */
1062 ++end;
1063 j = end - cur_expr;
1064
1065 if (!module_name || strncmp(cur_expr, module_name, j)) {
1066 /* print module name with colon, it does not equal to the parent one */
1067 if (count + j > buf_len) {
1068 LOGBUF(cur_expr);
1069 lyxp_expr_free(exp);
1070 return -1;
1071 }
1072 strncpy(&buf[count], cur_expr, j);
1073 count += j;
1074 }
1075 module_name = cur_expr;
1076
1077 /* copy the rest */
1078 if (count + (exp->tok_len[i] - j) > buf_len) {
1079 LOGBUF(end);
1080 lyxp_expr_free(exp);
1081 return -1;
1082 }
1083 strncpy(&buf[count], end, exp->tok_len[i] - j);
1084 count += exp->tok_len[i] - j;
1085 } else {
1086 if (count + exp->tok_len[i] > buf_len) {
1087 LOGBUF(&exp->expr[exp->expr_pos[i]]);
1088 lyxp_expr_free(exp);
1089 return -1;
1090 }
1091 strncpy(&buf[count], &exp->expr[exp->expr_pos[i]], exp->tok_len[i]);
1092 count += exp->tok_len[i];
1093 }
1094 }
1095 if (count > buf_len) {
1096 LOGINT(ctx);
1097 lyxp_expr_free(exp);
1098 return -1;
1099 }
1100 buf[count] = '\0';
1101
1102 lyxp_expr_free(exp);
1103 break;
1104
1105 case LY_TYPE_DEC64:
1106 num = *((int64_t *)data1);
1107 c = *((uint8_t *)data2);
1108 if (num) {
1109 count = sprintf(buf, "%"PRId64" ", num);
1110 if ( (num > 0 && (count - 1) <= c)
1111 || (count - 2) <= c ) {
1112 /* we have 0. value, print the value with the leading zeros
1113 * (one for 0. and also keep the correct with of num according
1114 * to fraction-digits value)
1115 * for (num<0) - extra character for '-' sign */
1116 count = sprintf(buf, "%0*"PRId64" ", (num > 0) ? (c + 1) : (c + 2), num);
1117 }
1118 for (i = c, j = 1; i > 0 ; i--) {
1119 if (j && i > 1 && buf[count - 2] == '0') {
1120 /* we have trailing zero to skip */
1121 buf[count - 1] = '\0';
1122 } else {
1123 j = 0;
1124 buf[count - 1] = buf[count - 2];
1125 }
1126 count--;
1127 }
1128 buf[count - 1] = '.';
1129 } else {
1130 /* zero */
1131 sprintf(buf, "0.0");
1132 }
1133 break;
1134
1135 case LY_TYPE_INT8:
1136 case LY_TYPE_INT16:
1137 case LY_TYPE_INT32:
1138 case LY_TYPE_INT64:
1139 num = *((int64_t *)data1);
1140 sprintf(buf, "%"PRId64, num);
1141 break;
1142
1143 case LY_TYPE_UINT8:
1144 case LY_TYPE_UINT16:
1145 case LY_TYPE_UINT32:
1146 case LY_TYPE_UINT64:
1147 unum = *((uint64_t *)data1);
1148 sprintf(buf, "%"PRIu64, unum);
1149 break;
1150
1151 default:
1152 /* should not be even called - just do nothing */
1153 return 0;
1154 }
1155
1156 if (strcmp(buf, *value)) {
1157 lydict_remove(ctx, *value);
1158 *value = lydict_insert(ctx, buf, 0);
1159 return 1;
1160 }
1161
1162 return 0;
1163
1164 #undef LOGBUF
1165 }
1166
1167 static const char *
ident_val_add_module_prefix(const char * value,const struct lyxml_elem * xml,struct ly_ctx * ctx)1168 ident_val_add_module_prefix(const char *value, const struct lyxml_elem *xml, struct ly_ctx *ctx)
1169 {
1170 const struct lyxml_ns *ns;
1171 const struct lys_module *mod;
1172 char *str;
1173
1174 do {
1175 LY_TREE_FOR((struct lyxml_ns *)xml->attr, ns) {
1176 if ((ns->type == LYXML_ATTR_NS) && !ns->prefix) {
1177 /* match */
1178 break;
1179 }
1180 }
1181 if (!ns) {
1182 xml = xml->parent;
1183 }
1184 } while (!ns && xml);
1185
1186 if (!ns) {
1187 /* no default namespace */
1188 LOGERR(ctx, LY_EINVAL, "Identity \"%s\" has no namespace.", value);
1189 return NULL;
1190 }
1191
1192 /* find module */
1193 mod = ly_ctx_get_module_by_ns(ctx, ns->value, NULL, 1);
1194 if (!mod) {
1195 LOGINT(ctx);
1196 return NULL;
1197 }
1198
1199 if (asprintf(&str, "%s:%s", mod->name, value) == -1) {
1200 LOGMEM(ctx);
1201 return NULL;
1202 }
1203 lydict_remove(ctx, value);
1204
1205 return lydict_insert_zc(ctx, str);
1206 }
1207
1208 /*
1209 * xml - optional for converting instance-identifier and identityref into JSON format
1210 * leaf - mandatory to know the context (necessary e.g. for prefixes in idenitytref values)
1211 * attr - alternative to leaf in case of parsing value in annotations (attributes)
1212 * local_mod - optional if the local module dos not match the module of leaf/attr
1213 * store - flag for union resolution - we do not want to store the result, we are just learning the type
1214 * dflt - whether the value is a default value from the schema
1215 */
1216 struct lys_type *
lyp_parse_value(struct lys_type * type,const char ** value_,struct lyxml_elem * xml,struct lyd_node_leaf_list * leaf,struct lyd_attr * attr,struct lys_module * local_mod,int store,int dflt)1217 lyp_parse_value(struct lys_type *type, const char **value_, struct lyxml_elem *xml,
1218 struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct lys_module *local_mod,
1219 int store, int dflt)
1220 {
1221 struct lys_type *ret = NULL, *t;
1222 struct lys_tpdf *tpdf;
1223 enum int_log_opts prev_ilo;
1224 int c, len, found = 0;
1225 unsigned int i, j;
1226 int64_t num;
1227 uint64_t unum, uind, u = 0;
1228 const char *ptr, *value = *value_, *itemname, *old_val_str = NULL;
1229 struct lys_type_bit **bits = NULL;
1230 struct lys_ident *ident;
1231 lyd_val *val, old_val;
1232 LY_DATA_TYPE *val_type, old_val_type;
1233 uint8_t *val_flags, old_val_flags;
1234 struct lyd_node *contextnode;
1235 struct ly_ctx *ctx = type->parent->module->ctx;
1236
1237 assert(leaf || attr);
1238
1239 if (leaf) {
1240 assert(!attr);
1241 if (!local_mod) {
1242 local_mod = leaf->schema->module;
1243 }
1244 val = &leaf->value;
1245 val_type = &leaf->value_type;
1246 val_flags = &leaf->value_flags;
1247 contextnode = (struct lyd_node *)leaf;
1248 itemname = leaf->schema->name;
1249 } else {
1250 assert(!leaf);
1251 if (!local_mod) {
1252 local_mod = attr->annotation->module;
1253 }
1254 val = &attr->value;
1255 val_type = &attr->value_type;
1256 val_flags = &attr->value_flags;
1257 contextnode = attr->parent;
1258 itemname = attr->name;
1259 }
1260
1261 /* fully clear the value */
1262 if (store) {
1263 if (leaf) {
1264 old_val_str = lydict_insert(ctx, leaf->value_str, 0);
1265 } else {
1266 old_val_str = lydict_insert(ctx, attr->value_str, 0);
1267 }
1268 lyd_free_value(*val, *val_type, *val_flags, type, old_val_str, &old_val, &old_val_type, &old_val_flags);
1269 *val_flags &= ~LY_VALUE_UNRES;
1270 *val_flags &= ~LY_VALUE_USER;
1271 }
1272
1273 ret = type;
1274 switch (type->base) {
1275 case LY_TYPE_BINARY:
1276 /* get number of octets for length validation */
1277 unum = 0;
1278 ptr = NULL;
1279 if (value) {
1280 /* silently skip leading/trailing whitespaces */
1281 for (uind = 0; isspace(value[uind]); ++uind);
1282 ptr = &value[uind];
1283 u = strlen(ptr);
1284 while (u && isspace(ptr[u - 1])) {
1285 --u;
1286 }
1287 unum = u;
1288 for (uind = 0; uind < u; ++uind) {
1289 if (ptr[uind] == '\n') {
1290 unum--;
1291 } else if ((ptr[uind] < '/' && ptr[uind] != '+') ||
1292 (ptr[uind] > '9' && ptr[uind] < 'A') ||
1293 (ptr[uind] > 'Z' && ptr[uind] < 'a') || ptr[uind] > 'z') {
1294 if (ptr[uind] == '=') {
1295 /* padding */
1296 if (uind == u - 2 && ptr[uind + 1] == '=') {
1297 found = 2;
1298 uind++;
1299 } else if (uind == u - 1) {
1300 found = 1;
1301 }
1302 }
1303 if (!found) {
1304 /* error */
1305 LOGVAL(ctx, LYE_INCHAR, LY_VLOG_LYD, contextnode, ptr[uind], &ptr[uind]);
1306 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Invalid Base64 character.");
1307 goto error;
1308 }
1309 }
1310 }
1311 }
1312
1313 if (unum & 3) {
1314 /* base64 length must be multiple of 4 chars */
1315 if (leaf) {
1316 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1317 } else {
1318 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1319 }
1320 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Base64 encoded value length must be divisible by 4.");
1321 goto error;
1322 }
1323
1324 /* length of the encoded string */
1325 len = ((unum / 4) * 3) - found;
1326 if (validate_length_range(0, len, 0, 0, 0, type, value, contextnode)) {
1327 goto error;
1328 }
1329
1330 if (value && (ptr != value || ptr[u] != '\0')) {
1331 /* update the changed value */
1332 ptr = lydict_insert(ctx, ptr, u);
1333 lydict_remove(ctx, *value_);
1334 *value_ = ptr;
1335 }
1336
1337 if (store) {
1338 /* store the result */
1339 val->binary = value;
1340 *val_type = LY_TYPE_BINARY;
1341 }
1342 break;
1343
1344 case LY_TYPE_BITS:
1345 /* locate bits structure with the bits definitions
1346 * since YANG 1.1 allows restricted bits, it is the first
1347 * bits type with some explicit bit specification */
1348 for (; !type->info.bits.count; type = &type->der->type);
1349
1350 if (value || store) {
1351 /* allocate the array of pointers to bits definition */
1352 bits = calloc(type->info.bits.count, sizeof *bits);
1353 LY_CHECK_ERR_GOTO(!bits, LOGMEM(ctx), error);
1354 }
1355
1356 if (!value) {
1357 /* no bits set */
1358 if (store) {
1359 /* store empty array */
1360 val->bit = bits;
1361 *val_type = LY_TYPE_BITS;
1362 }
1363 break;
1364 }
1365
1366 c = 0;
1367 i = 0;
1368 while (value[c]) {
1369 /* skip leading whitespaces */
1370 while (isspace(value[c])) {
1371 c++;
1372 }
1373 if (!value[c]) {
1374 /* trailing white spaces */
1375 break;
1376 }
1377
1378 /* get the length of the bit identifier */
1379 for (len = 0; value[c] && !isspace(value[c]); c++, len++);
1380
1381 /* go back to the beginning of the identifier */
1382 c = c - len;
1383
1384 /* find bit definition, identifiers appear ordered by their position */
1385 for (found = i = 0; i < type->info.bits.count; i++) {
1386 if (!strncmp(type->info.bits.bit[i].name, &value[c], len) && !type->info.bits.bit[i].name[len]) {
1387 if (!dflt) {
1388 /* we have match, check if the value is enabled ... */
1389 for (j = 0; j < type->info.bits.bit[i].iffeature_size; j++) {
1390 if (!resolve_iffeature(&type->info.bits.bit[i].iffeature[j])) {
1391 if (leaf) {
1392 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1393 } else {
1394 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1395 }
1396 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL,
1397 "Bit \"%s\" is disabled by its %d. if-feature condition.",
1398 type->info.bits.bit[i].name, j + 1);
1399 free(bits);
1400 goto error;
1401 }
1402 }
1403 }
1404 /* check that the value was not already set */
1405 if (bits[i]) {
1406 if (leaf) {
1407 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1408 } else {
1409 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1410 }
1411 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Bit \"%s\" used multiple times.",
1412 type->info.bits.bit[i].name);
1413 free(bits);
1414 goto error;
1415 }
1416 /* ... and then store the pointer */
1417 bits[i] = &type->info.bits.bit[i];
1418
1419 /* stop searching */
1420 found = 1;
1421 break;
1422 }
1423 }
1424
1425 if (!found) {
1426 /* referenced bit value does not exist */
1427 if (leaf) {
1428 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1429 } else {
1430 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1431 }
1432 free(bits);
1433 goto error;
1434 }
1435 c = c + len;
1436 }
1437
1438 if (make_canonical(ctx, LY_TYPE_BITS, value_, bits, &type->info.bits.count) == -1) {
1439 free(bits);
1440 goto error;
1441 }
1442
1443 if (store) {
1444 /* store the result */
1445 val->bit = bits;
1446 *val_type = LY_TYPE_BITS;
1447 } else {
1448 free(bits);
1449 }
1450 break;
1451
1452 case LY_TYPE_BOOL:
1453 if (value && !strcmp(value, "true")) {
1454 if (store) {
1455 val->bln = 1;
1456 }
1457 } else if (!value || strcmp(value, "false")) {
1458 if (leaf) {
1459 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value ? value : "", itemname);
1460 } else {
1461 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value ? value : "");
1462 }
1463 goto error;
1464 } else {
1465 if (store) {
1466 val->bln = 0;
1467 }
1468 }
1469
1470 if (store) {
1471 *val_type = LY_TYPE_BOOL;
1472 }
1473 break;
1474
1475 case LY_TYPE_DEC64:
1476 if (!value || !value[0]) {
1477 if (leaf) {
1478 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1479 } else {
1480 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1481 }
1482 goto error;
1483 }
1484
1485 ptr = value;
1486 if (parse_range_dec64(&ptr, type->info.dec64.dig, &num) || ptr[0]) {
1487 if (leaf) {
1488 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1489 } else {
1490 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1491 }
1492 goto error;
1493 }
1494
1495 if (validate_length_range(2, 0, 0, num, type->info.dec64.dig, type, value, contextnode)) {
1496 goto error;
1497 }
1498
1499 if (make_canonical(ctx, LY_TYPE_DEC64, value_, &num, &type->info.dec64.dig) == -1) {
1500 goto error;
1501 }
1502
1503 if (store) {
1504 /* store the result */
1505 val->dec64 = num;
1506 *val_type = LY_TYPE_DEC64;
1507 }
1508 break;
1509
1510 case LY_TYPE_EMPTY:
1511 if (value && value[0]) {
1512 if (leaf) {
1513 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1514 } else {
1515 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1516 }
1517 goto error;
1518 }
1519
1520 if (store) {
1521 *val_type = LY_TYPE_EMPTY;
1522 }
1523 break;
1524
1525 case LY_TYPE_ENUM:
1526 /* locate enums structure with the enumeration definitions,
1527 * since YANG 1.1 allows restricted enums, it is the first
1528 * enum type with some explicit enum specification */
1529 for (; !type->info.enums.count; type = &type->der->type);
1530
1531 /* find matching enumeration value */
1532 for (i = found = 0; i < type->info.enums.count; i++) {
1533 if (value && !strcmp(value, type->info.enums.enm[i].name)) {
1534 if (!dflt) {
1535 /* we have match, check if the value is enabled ... */
1536 for (j = 0; j < type->info.enums.enm[i].iffeature_size; j++) {
1537 if (!resolve_iffeature(&type->info.enums.enm[i].iffeature[j])) {
1538 if (leaf) {
1539 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value, itemname);
1540 } else {
1541 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value);
1542 }
1543 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Enum \"%s\" is disabled by its %d. if-feature condition.",
1544 value, j + 1);
1545 goto error;
1546 }
1547 }
1548 }
1549 /* ... and store pointer to the definition */
1550 if (store) {
1551 val->enm = &type->info.enums.enm[i];
1552 *val_type = LY_TYPE_ENUM;
1553 }
1554 found = 1;
1555 break;
1556 }
1557 }
1558
1559 if (!found) {
1560 if (leaf) {
1561 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, value ? value : "", itemname);
1562 } else {
1563 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, value ? value : "");
1564 }
1565 goto error;
1566 }
1567 break;
1568
1569 case LY_TYPE_IDENT:
1570 if (!value) {
1571 if (leaf) {
1572 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1573 } else {
1574 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1575 }
1576 goto error;
1577 }
1578
1579 if (xml) {
1580 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1581 /* first, convert value into the json format, silently */
1582 value = transform_xml2json(ctx, value, xml, 0, 0);
1583 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1584 if (!value) {
1585 /* invalid identityref format */
1586 if (leaf) {
1587 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1588 } else {
1589 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1590 }
1591 goto error;
1592 }
1593
1594 /* the value has no prefix (default namespace), but the element's namespace has a prefix, find default namespace */
1595 if (!strchr(value, ':') && xml->ns->prefix) {
1596 value = ident_val_add_module_prefix(value, xml, ctx);
1597 if (!value) {
1598 goto error;
1599 }
1600 }
1601 } else if (dflt) {
1602 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1603 /* the value actually uses module's prefixes instead of the module names as in JSON format,
1604 * we have to convert it */
1605 value = transform_schema2json(local_mod, value);
1606 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1607 if (!value) {
1608 /* invalid identityref format or it was already transformed, so ignore the error here */
1609 value = lydict_insert(ctx, *value_, 0);
1610 }
1611 } else {
1612 value = lydict_insert(ctx, *value_, 0);
1613 }
1614 /* value is now in the dictionary, whether it differs from *value_ or not */
1615
1616 ident = resolve_identref(type, value, contextnode, local_mod, dflt);
1617 if (!ident) {
1618 lydict_remove(ctx, value);
1619 goto error;
1620 } else if (store) {
1621 /* store the result */
1622 val->ident = ident;
1623 *val_type = LY_TYPE_IDENT;
1624 }
1625
1626 /* the value is always changed and includes prefix */
1627 if (dflt) {
1628 type->parent->flags |= LYS_DFLTJSON;
1629 }
1630
1631 if (make_canonical(ctx, LY_TYPE_IDENT, &value, (void*)lys_main_module(local_mod)->name, NULL) == -1) {
1632 lydict_remove(ctx, value);
1633 goto error;
1634 }
1635
1636 /* replace the old value with the new one (even if they may be the same) */
1637 lydict_remove(ctx, *value_);
1638 *value_ = value;
1639 break;
1640
1641 case LY_TYPE_INST:
1642 if (!value) {
1643 if (leaf) {
1644 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1645 } else {
1646 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1647 }
1648 goto error;
1649 }
1650
1651 if (xml) {
1652 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1653 /* first, convert value into the json format, silently */
1654 value = transform_xml2json(ctx, value, xml, 1, 1);
1655 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1656 if (!value) {
1657 /* invalid instance-identifier format */
1658 if (leaf) {
1659 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1660 } else {
1661 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1662 }
1663 goto error;
1664 } else if (ly_strequal(value, *value_, 1)) {
1665 /* we have actually created the same expression (prefixes are the same as the module names)
1666 * so we have just increased dictionary's refcount - fix it */
1667 lydict_remove(ctx, value);
1668 }
1669 } else if (dflt) {
1670 /* turn logging off */
1671 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1672
1673 /* the value actually uses module's prefixes instead of the module names as in JSON format,
1674 * we have to convert it */
1675 value = transform_schema2json(local_mod, value);
1676 if (!value) {
1677 /* invalid identityref format or it was already transformed, so ignore the error here */
1678 value = *value_;
1679 } else if (ly_strequal(value, *value_, 1)) {
1680 /* we have actually created the same expression (prefixes are the same as the module names)
1681 * so we have just increased dictionary's refcount - fix it */
1682 lydict_remove(ctx, value);
1683 }
1684 /* turn logging back on */
1685 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1686 } else {
1687 if ((c = make_canonical(ctx, LY_TYPE_INST, &value, NULL, NULL))) {
1688 if (c == -1) {
1689 goto error;
1690 }
1691
1692 /* if a change occurred, value was removed from the dictionary so fix the pointers */
1693 *value_ = value;
1694 }
1695 }
1696
1697 if (store) {
1698 /* note that the data node is an unresolved instance-identifier */
1699 val->instance = NULL;
1700 *val_type = LY_TYPE_INST;
1701 *val_flags |= LY_VALUE_UNRES;
1702 }
1703
1704 if (!ly_strequal(value, *value_, 1)) {
1705 /* update the changed value */
1706 lydict_remove(ctx, *value_);
1707 *value_ = value;
1708
1709 /* we have to remember the conversion into JSON format to be able to print it in correct form */
1710 if (dflt) {
1711 type->parent->flags |= LYS_DFLTJSON;
1712 }
1713 }
1714 break;
1715
1716 case LY_TYPE_LEAFREF:
1717 if (!value) {
1718 if (leaf) {
1719 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, "", itemname);
1720 } else {
1721 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, "");
1722 }
1723 goto error;
1724 }
1725
1726 /* it is called not only to get the final type, but mainly to update value to canonical or JSON form
1727 * if needed */
1728 t = lyp_parse_value(&type->info.lref.target->type, value_, xml, leaf, attr, NULL, store, dflt);
1729 value = *value_; /* refresh possibly changed value */
1730 if (!t) {
1731 /* already logged */
1732 goto error;
1733 }
1734
1735 if (store) {
1736 /* make the note that the data node is an unresolved leafref (value union was already filled) */
1737 *val_flags |= LY_VALUE_UNRES;
1738 }
1739
1740 ret = t;
1741 break;
1742
1743 case LY_TYPE_STRING:
1744 if (validate_length_range(0, (value ? ly_strlen_utf8(value) : 0), 0, 0, 0, type, value, contextnode)) {
1745 goto error;
1746 }
1747
1748 if (validate_pattern(ctx, value, type, contextnode)) {
1749 goto error;
1750 }
1751
1752 /* special handling of ietf-yang-types xpath1.0 */
1753 for (tpdf = type->der;
1754 tpdf->module && (strcmp(tpdf->name, "xpath1.0") || strcmp(tpdf->module->name, "ietf-yang-types"));
1755 tpdf = tpdf->type.der);
1756 if (tpdf->module && xml) {
1757 /* convert value into the json format */
1758 value = transform_xml2json(ctx, value ? value : "", xml, 1, 1);
1759 if (!value) {
1760 /* invalid instance-identifier format */
1761 if (leaf) {
1762 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_, itemname);
1763 } else {
1764 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1765 }
1766 goto error;
1767 }
1768
1769 if (!ly_strequal(value, *value_, 1)) {
1770 /* update the changed value */
1771 lydict_remove(ctx, *value_);
1772 *value_ = value;
1773 }
1774 }
1775
1776 if (store) {
1777 /* store the result */
1778 val->string = value;
1779 *val_type = LY_TYPE_STRING;
1780 }
1781 break;
1782
1783 case LY_TYPE_INT8:
1784 if (parse_int(value, __INT64_C(-128), __INT64_C(127), dflt ? 0 : 10, &num, contextnode)
1785 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1786 goto error;
1787 }
1788
1789 if (make_canonical(ctx, LY_TYPE_INT8, value_, &num, NULL) == -1) {
1790 goto error;
1791 }
1792
1793 if (store) {
1794 /* store the result */
1795 val->int8 = (int8_t)num;
1796 *val_type = LY_TYPE_INT8;
1797 }
1798 break;
1799
1800 case LY_TYPE_INT16:
1801 if (parse_int(value, __INT64_C(-32768), __INT64_C(32767), dflt ? 0 : 10, &num, contextnode)
1802 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1803 goto error;
1804 }
1805
1806 if (make_canonical(ctx, LY_TYPE_INT16, value_, &num, NULL) == -1) {
1807 goto error;
1808 }
1809
1810 if (store) {
1811 /* store the result */
1812 val->int16 = (int16_t)num;
1813 *val_type = LY_TYPE_INT16;
1814 }
1815 break;
1816
1817 case LY_TYPE_INT32:
1818 if (parse_int(value, __INT64_C(-2147483648), __INT64_C(2147483647), dflt ? 0 : 10, &num, contextnode)
1819 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1820 goto error;
1821 }
1822
1823 if (make_canonical(ctx, LY_TYPE_INT32, value_, &num, NULL) == -1) {
1824 goto error;
1825 }
1826
1827 if (store) {
1828 /* store the result */
1829 val->int32 = (int32_t)num;
1830 *val_type = LY_TYPE_INT32;
1831 }
1832 break;
1833
1834 case LY_TYPE_INT64:
1835 if (parse_int(value, __INT64_C(-9223372036854775807) - __INT64_C(1), __INT64_C(9223372036854775807),
1836 dflt ? 0 : 10, &num, contextnode)
1837 || validate_length_range(1, 0, num, 0, 0, type, value, contextnode)) {
1838 goto error;
1839 }
1840
1841 if (make_canonical(ctx, LY_TYPE_INT64, value_, &num, NULL) == -1) {
1842 goto error;
1843 }
1844
1845 if (store) {
1846 /* store the result */
1847 val->int64 = num;
1848 *val_type = LY_TYPE_INT64;
1849 }
1850 break;
1851
1852 case LY_TYPE_UINT8:
1853 if (parse_uint(value, __UINT64_C(255), dflt ? 0 : 10, &unum, contextnode)
1854 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1855 goto error;
1856 }
1857
1858 if (make_canonical(ctx, LY_TYPE_UINT8, value_, &unum, NULL) == -1) {
1859 goto error;
1860 }
1861
1862 if (store) {
1863 /* store the result */
1864 val->uint8 = (uint8_t)unum;
1865 *val_type = LY_TYPE_UINT8;
1866 }
1867 break;
1868
1869 case LY_TYPE_UINT16:
1870 if (parse_uint(value, __UINT64_C(65535), dflt ? 0 : 10, &unum, contextnode)
1871 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1872 goto error;
1873 }
1874
1875 if (make_canonical(ctx, LY_TYPE_UINT16, value_, &unum, NULL) == -1) {
1876 goto error;
1877 }
1878
1879 if (store) {
1880 /* store the result */
1881 val->uint16 = (uint16_t)unum;
1882 *val_type = LY_TYPE_UINT16;
1883 }
1884 break;
1885
1886 case LY_TYPE_UINT32:
1887 if (parse_uint(value, __UINT64_C(4294967295), dflt ? 0 : 10, &unum, contextnode)
1888 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1889 goto error;
1890 }
1891
1892 if (make_canonical(ctx, LY_TYPE_UINT32, value_, &unum, NULL) == -1) {
1893 goto error;
1894 }
1895
1896 if (store) {
1897 /* store the result */
1898 val->uint32 = (uint32_t)unum;
1899 *val_type = LY_TYPE_UINT32;
1900 }
1901 break;
1902
1903 case LY_TYPE_UINT64:
1904 if (parse_uint(value, __UINT64_C(18446744073709551615), dflt ? 0 : 10, &unum, contextnode)
1905 || validate_length_range(0, unum, 0, 0, 0, type, value, contextnode)) {
1906 goto error;
1907 }
1908
1909 if (make_canonical(ctx, LY_TYPE_UINT64, value_, &unum, NULL) == -1) {
1910 goto error;
1911 }
1912
1913 if (store) {
1914 /* store the result */
1915 val->uint64 = unum;
1916 *val_type = LY_TYPE_UINT64;
1917 }
1918 break;
1919
1920 case LY_TYPE_UNION:
1921 if (store) {
1922 /* unresolved union type */
1923 memset(val, 0, sizeof(lyd_val));
1924 *val_type = LY_TYPE_UNION;
1925 }
1926
1927 if (type->info.uni.has_ptr_type) {
1928 /* we are not resolving anything here, only parsing, and in this case we cannot decide
1929 * the type without resolving it -> we return the union type (resolve it with resolve_union()) */
1930 if (xml) {
1931 /* in case it should resolve into a instance-identifier, we can only do the JSON conversion here */
1932 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1933 value = transform_xml2json(ctx, value, xml, 1, 1);
1934 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1935
1936 /* update the changed value */
1937 if (value) {
1938 lydict_remove(ctx, *value_);
1939 *value_ = value;
1940 } else {
1941 value = *value_;
1942 }
1943
1944 if (store) {
1945 /* store the (unresolved) result */
1946 val->string = lydict_insert(ctx, value, 0);
1947 }
1948 }
1949 break;
1950 }
1951
1952 t = NULL;
1953 found = 0;
1954
1955 /* turn logging off, we are going to try to validate the value with all the types in order */
1956 ly_ilo_change(NULL, ILO_IGNORE, &prev_ilo, NULL);
1957
1958 while ((t = lyp_get_next_union_type(type, t, &found))) {
1959 found = 0;
1960 ret = lyp_parse_value(t, value_, xml, leaf, attr, NULL, store, dflt);
1961 if (ret) {
1962 /* we have the result */
1963 break;
1964 }
1965
1966 if (store) {
1967 /* erase possible present and invalid value data */
1968 lyd_free_value(*val, *val_type, *val_flags, t, *value_, NULL, NULL, NULL);
1969 memset(val, 0, sizeof(lyd_val));
1970 }
1971 }
1972
1973 /* turn logging back on */
1974 ly_ilo_restore(NULL, prev_ilo, NULL, 0);
1975
1976 if (!t) {
1977 /* not found */
1978 if (store) {
1979 *val_type = 0;
1980 }
1981 if (leaf) {
1982 LOGVAL(ctx, LYE_INVAL, LY_VLOG_LYD, contextnode, *value_ ? *value_ : "", itemname);
1983 } else {
1984 LOGVAL(ctx, LYE_INMETA, LY_VLOG_LYD, contextnode, "<none>", itemname, *value_);
1985 }
1986 goto error;
1987 }
1988 break;
1989
1990 default:
1991 LOGINT(ctx);
1992 goto error;
1993 }
1994
1995 /* search user types in case this value is supposed to be stored in a custom way */
1996 if (store && ret->der && ret->der->module) {
1997 c = lytype_store(ret->der->module, ret->der->name, value_, val);
1998 if (c == -1) {
1999 if (leaf) {
2000 LOGPATH(ctx, LY_VLOG_LYD, leaf);
2001 }
2002 goto error;
2003 } else if (!c) {
2004 *val_flags |= LY_VALUE_USER;
2005 }
2006 }
2007
2008 /* free backup (using the original type, unless we were parsing a leafref - then this was freed in the recursive call) */
2009 if (store) {
2010 if (type->base != LY_TYPE_LEAFREF) {
2011 lyd_free_value(old_val, old_val_type, old_val_flags, type, old_val_str, NULL, NULL, NULL);
2012 }
2013 lydict_remove(ctx, old_val_str);
2014 }
2015 return ret;
2016
2017 error:
2018 /* restore the backup */
2019 if (store) {
2020 *val = old_val;
2021 *val_type = old_val_type;
2022 *val_flags = old_val_flags;
2023 lydict_remove(ctx, old_val_str);
2024 }
2025 return NULL;
2026 }
2027
2028 /* does not log, cannot fail */
2029 struct lys_type *
lyp_get_next_union_type(struct lys_type * type,struct lys_type * prev_type,int * found)2030 lyp_get_next_union_type(struct lys_type *type, struct lys_type *prev_type, int *found)
2031 {
2032 unsigned int i;
2033 struct lys_type *ret = NULL;
2034
2035 while (!type->info.uni.count) {
2036 assert(type->der); /* at least the direct union type has to have type specified */
2037 type = &type->der->type;
2038 }
2039
2040 for (i = 0; i < type->info.uni.count; ++i) {
2041 if (type->info.uni.types[i].base == LY_TYPE_UNION) {
2042 ret = lyp_get_next_union_type(&type->info.uni.types[i], prev_type, found);
2043 if (ret) {
2044 break;
2045 }
2046 continue;
2047 }
2048
2049 if (!prev_type || *found) {
2050 ret = &type->info.uni.types[i];
2051 break;
2052 }
2053
2054 if (&type->info.uni.types[i] == prev_type) {
2055 *found = 1;
2056 }
2057 }
2058
2059 return ret;
2060 }
2061
2062 /* ret 0 - ret set, ret 1 - ret not set, no log, ret -1 - ret not set, fatal error */
2063 int
lyp_fill_attr(struct ly_ctx * ctx,struct lyd_node * parent,const char * module_ns,const char * module_name,const char * attr_name,const char * attr_value,struct lyxml_elem * xml,struct lyd_attr ** ret)2064 lyp_fill_attr(struct ly_ctx *ctx, struct lyd_node *parent, const char *module_ns, const char *module_name,
2065 const char *attr_name, const char *attr_value, struct lyxml_elem *xml, struct lyd_attr **ret)
2066 {
2067 const struct lys_module *mod = NULL;
2068 const struct lys_submodule *submod = NULL;
2069 struct lys_type **type;
2070 struct lyd_attr *dattr;
2071 int pos, i, j, k;
2072
2073 /* first, get module where the annotation should be defined */
2074 if (module_ns) {
2075 mod = (struct lys_module *)ly_ctx_get_module_by_ns(ctx, module_ns, NULL, 0);
2076 } else if (module_name) {
2077 mod = (struct lys_module *)ly_ctx_get_module(ctx, module_name, NULL, 0);
2078 } else {
2079 LOGINT(ctx);
2080 return -1;
2081 }
2082 if (!mod) {
2083 return 1;
2084 }
2085
2086 /* then, find the appropriate annotation definition */
2087 pos = -1;
2088 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
2089 j = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
2090 if (j == -1) {
2091 break;
2092 }
2093 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
2094 pos = i + j;
2095 break;
2096 }
2097 }
2098
2099 /* try submodules */
2100 if (pos == -1) {
2101 for (k = 0; k < mod->inc_size; ++k) {
2102 submod = mod->inc[k].submodule;
2103 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
2104 j = lys_ext_instance_presence(&ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
2105 if (j == -1) {
2106 break;
2107 }
2108 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
2109 pos = i + j;
2110 break;
2111 }
2112 }
2113 }
2114 }
2115
2116 if (pos == -1) {
2117 return 1;
2118 }
2119
2120 /* allocate and fill the data attribute structure */
2121 dattr = calloc(1, sizeof *dattr);
2122 LY_CHECK_ERR_RETURN(!dattr, LOGMEM(ctx), -1);
2123
2124 dattr->parent = parent;
2125 dattr->next = NULL;
2126 dattr->annotation = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] :
2127 (struct lys_ext_instance_complex *)mod->ext[pos];
2128 dattr->name = lydict_insert(ctx, attr_name, 0);
2129 dattr->value_str = lydict_insert(ctx, attr_value, 0);
2130
2131 /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
2132 * canonical form of the value */
2133 type = lys_ext_complex_get_substmt(LY_STMT_TYPE, dattr->annotation, NULL);
2134 if (!type || !lyp_parse_value(*type, &dattr->value_str, xml, NULL, dattr, NULL, 1, 0)) {
2135 lydict_remove(ctx, dattr->name);
2136 lydict_remove(ctx, dattr->value_str);
2137 free(dattr);
2138 return -1;
2139 }
2140
2141 *ret = dattr;
2142 return 0;
2143 }
2144
2145 int
lyp_check_edit_attr(struct ly_ctx * ctx,struct lyd_attr * attr,struct lyd_node * parent,int * editbits)2146 lyp_check_edit_attr(struct ly_ctx *ctx, struct lyd_attr *attr, struct lyd_node *parent, int *editbits)
2147 {
2148 struct lyd_attr *last = NULL;
2149 int bits = 0;
2150
2151 /* 0x01 - insert attribute present
2152 * 0x02 - insert is relative (before or after)
2153 * 0x04 - value attribute present
2154 * 0x08 - key attribute present
2155 * 0x10 - operation attribute present
2156 * 0x20 - operation not allowing insert attribute (delete or remove)
2157 */
2158 LY_TREE_FOR(attr, attr) {
2159 last = NULL;
2160 if (!strcmp(attr->annotation->arg_value, "operation") &&
2161 !strcmp(attr->annotation->module->name, "ietf-netconf")) {
2162 if (bits & 0x10) {
2163 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "operation attributes", parent->schema->name);
2164 return -1;
2165 }
2166
2167 bits |= 0x10;
2168 if (attr->value.enm->value >= 3) {
2169 /* delete or remove */
2170 bits |= 0x20;
2171 }
2172 } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2173 !strcmp(attr->annotation->arg_value, "insert")) {
2174 /* 'insert' attribute present */
2175 if (!(parent->schema->flags & LYS_USERORDERED)) {
2176 /* ... but it is not expected */
2177 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, "insert");
2178 return -1;
2179 }
2180 if (bits & 0x01) {
2181 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "insert attributes", parent->schema->name);
2182 return -1;
2183 }
2184
2185 bits |= 0x01;
2186 if (attr->value.enm->value >= 2) {
2187 /* before or after */
2188 bits |= 0x02;
2189 }
2190 last = attr;
2191 } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2192 !strcmp(attr->annotation->arg_value, "value")) {
2193 if (bits & 0x04) {
2194 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "value attributes", parent->schema->name);
2195 return -1;
2196 } else if (parent->schema->nodetype & LYS_LIST) {
2197 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, attr->name);
2198 return -1;
2199 }
2200 bits |= 0x04;
2201 last = attr;
2202 } else if (attr->annotation->module == ctx->models.list[1] && /* internal YANG schema */
2203 !strcmp(attr->annotation->arg_value, "key")) {
2204 if (bits & 0x08) {
2205 LOGVAL(ctx, LYE_TOOMANY, LY_VLOG_LYD, parent, "key attributes", parent->schema->name);
2206 return -1;
2207 } else if (parent->schema->nodetype & LYS_LEAFLIST) {
2208 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, attr->name);
2209 return -1;
2210 }
2211 bits |= 0x08;
2212 last = attr;
2213 }
2214 }
2215
2216 /* report errors */
2217 if (last && (!(parent->schema->nodetype & (LYS_LEAFLIST | LYS_LIST)) || !(parent->schema->flags & LYS_USERORDERED))) {
2218 /* moving attributes in wrong elements (not an user ordered list or not a list at all) */
2219 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, last->name);
2220 return -1;
2221 } else if (bits == 3) {
2222 /* 0x01 | 0x02 - relative position, but value/key is missing */
2223 if (parent->schema->nodetype & LYS_LIST) {
2224 LOGVAL(ctx, LYE_MISSATTR, LY_VLOG_LYD, parent, "key", parent->schema->name);
2225 } else { /* LYS_LEAFLIST */
2226 LOGVAL(ctx, LYE_MISSATTR, LY_VLOG_LYD, parent, "value", parent->schema->name);
2227 }
2228 return -1;
2229 } else if ((bits & (0x04 | 0x08)) && !(bits & 0x02)) {
2230 /* key/value without relative position */
2231 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, (bits & 0x04) ? "value" : "key");
2232 return -1;
2233 } else if ((bits & 0x21) == 0x21) {
2234 /* insert in delete/remove */
2235 LOGVAL(ctx, LYE_INATTR, LY_VLOG_LYD, parent, "insert");
2236 return -1;
2237 }
2238
2239 if (editbits) {
2240 *editbits = bits;
2241 }
2242 return 0;
2243 }
2244
2245 /* does not log */
2246 static int
dup_identity_check(const char * id,struct lys_ident * ident,uint32_t size)2247 dup_identity_check(const char *id, struct lys_ident *ident, uint32_t size)
2248 {
2249 uint32_t i;
2250
2251 for (i = 0; i < size; i++) {
2252 if (ly_strequal(id, ident[i].name, 1)) {
2253 /* name collision */
2254 return EXIT_FAILURE;
2255 }
2256 }
2257
2258 return EXIT_SUCCESS;
2259 }
2260
2261 int
dup_identities_check(const char * id,struct lys_module * module)2262 dup_identities_check(const char *id, struct lys_module *module)
2263 {
2264 struct lys_module *mainmod;
2265 int i;
2266
2267 if (dup_identity_check(id, module->ident, module->ident_size)) {
2268 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "identity", id);
2269 return EXIT_FAILURE;
2270 }
2271
2272 /* check identity in submodules */
2273 mainmod = lys_main_module(module);
2274 for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; ++i) {
2275 if (dup_identity_check(id, mainmod->inc[i].submodule->ident, mainmod->inc[i].submodule->ident_size)) {
2276 LOGVAL(module->ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "identity", id);
2277 return EXIT_FAILURE;
2278 }
2279 }
2280
2281 return EXIT_SUCCESS;
2282 }
2283
2284 /* does not log */
2285 int
dup_typedef_check(const char * type,struct lys_tpdf * tpdf,int size)2286 dup_typedef_check(const char *type, struct lys_tpdf *tpdf, int size)
2287 {
2288 int i;
2289
2290 for (i = 0; i < size; i++) {
2291 if (!strcmp(type, tpdf[i].name)) {
2292 /* name collision */
2293 return EXIT_FAILURE;
2294 }
2295 }
2296
2297 return EXIT_SUCCESS;
2298 }
2299
2300 /* does not log */
2301 static int
dup_feature_check(const char * id,struct lys_module * module)2302 dup_feature_check(const char *id, struct lys_module *module)
2303 {
2304 int i;
2305
2306 for (i = 0; i < module->features_size; i++) {
2307 if (!strcmp(id, module->features[i].name)) {
2308 return EXIT_FAILURE;
2309 }
2310 }
2311
2312 return EXIT_SUCCESS;
2313 }
2314
2315 /* does not log */
2316 static int
dup_prefix_check(const char * prefix,struct lys_module * module)2317 dup_prefix_check(const char *prefix, struct lys_module *module)
2318 {
2319 int i;
2320
2321 if (module->prefix && !strcmp(module->prefix, prefix)) {
2322 return EXIT_FAILURE;
2323 }
2324 for (i = 0; i < module->imp_size; i++) {
2325 if (!strcmp(module->imp[i].prefix, prefix)) {
2326 return EXIT_FAILURE;
2327 }
2328 }
2329
2330 return EXIT_SUCCESS;
2331 }
2332
2333 /* logs directly */
2334 int
lyp_check_identifier(struct ly_ctx * ctx,const char * id,enum LY_IDENT type,struct lys_module * module,struct lys_node * parent)2335 lyp_check_identifier(struct ly_ctx *ctx, const char *id, enum LY_IDENT type, struct lys_module *module,
2336 struct lys_node *parent)
2337 {
2338 int i, j;
2339 int size;
2340 struct lys_tpdf *tpdf;
2341 struct lys_node *node;
2342 struct lys_module *mainmod;
2343 struct lys_submodule *submod;
2344
2345 assert(ctx && id);
2346
2347 /* check id syntax */
2348 if (!(id[0] >= 'A' && id[0] <= 'Z') && !(id[0] >= 'a' && id[0] <= 'z') && id[0] != '_') {
2349 LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "invalid start character");
2350 return EXIT_FAILURE;
2351 }
2352 for (i = 1; id[i]; i++) {
2353 if (!(id[i] >= 'A' && id[i] <= 'Z') && !(id[i] >= 'a' && id[i] <= 'z')
2354 && !(id[i] >= '0' && id[i] <= '9') && id[i] != '_' && id[i] != '-' && id[i] != '.') {
2355 LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "invalid character");
2356 return EXIT_FAILURE;
2357 }
2358 }
2359
2360 if (i > 64) {
2361 LOGWRN(ctx, "Identifier \"%s\" is long, you should use something shorter.", id);
2362 }
2363
2364 switch (type) {
2365 case LY_IDENT_NAME:
2366 /* check uniqueness of the node within its siblings */
2367 if (!parent) {
2368 break;
2369 }
2370
2371 LY_TREE_FOR(parent->child, node) {
2372 if (ly_strequal(node->name, id, 1)) {
2373 LOGVAL(ctx, LYE_INID, LY_VLOG_NONE, NULL, id, "name duplication");
2374 return EXIT_FAILURE;
2375 }
2376 }
2377 break;
2378 case LY_IDENT_TYPE:
2379 assert(module);
2380 mainmod = lys_main_module(module);
2381
2382 /* check collision with the built-in types */
2383 if (!strcmp(id, "binary") || !strcmp(id, "bits") ||
2384 !strcmp(id, "boolean") || !strcmp(id, "decimal64") ||
2385 !strcmp(id, "empty") || !strcmp(id, "enumeration") ||
2386 !strcmp(id, "identityref") || !strcmp(id, "instance-identifier") ||
2387 !strcmp(id, "int8") || !strcmp(id, "int16") ||
2388 !strcmp(id, "int32") || !strcmp(id, "int64") ||
2389 !strcmp(id, "leafref") || !strcmp(id, "string") ||
2390 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
2391 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
2392 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, id, "typedef");
2393 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Typedef name duplicates a built-in type.");
2394 return EXIT_FAILURE;
2395 }
2396
2397 /* check locally scoped typedefs (avoid name shadowing) */
2398 for (; parent; parent = lys_parent(parent)) {
2399 switch (parent->nodetype) {
2400 case LYS_CONTAINER:
2401 size = ((struct lys_node_container *)parent)->tpdf_size;
2402 tpdf = ((struct lys_node_container *)parent)->tpdf;
2403 break;
2404 case LYS_LIST:
2405 size = ((struct lys_node_list *)parent)->tpdf_size;
2406 tpdf = ((struct lys_node_list *)parent)->tpdf;
2407 break;
2408 case LYS_GROUPING:
2409 size = ((struct lys_node_grp *)parent)->tpdf_size;
2410 tpdf = ((struct lys_node_grp *)parent)->tpdf;
2411 break;
2412 default:
2413 continue;
2414 }
2415
2416 if (dup_typedef_check(id, tpdf, size)) {
2417 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2418 return EXIT_FAILURE;
2419 }
2420 }
2421
2422 /* check top-level names */
2423 if (dup_typedef_check(id, module->tpdf, module->tpdf_size)) {
2424 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2425 return EXIT_FAILURE;
2426 }
2427
2428 /* check submodule's top-level names */
2429 for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; i++) {
2430 if (dup_typedef_check(id, mainmod->inc[i].submodule->tpdf, mainmod->inc[i].submodule->tpdf_size)) {
2431 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "typedef", id);
2432 return EXIT_FAILURE;
2433 }
2434 }
2435
2436 break;
2437 case LY_IDENT_PREFIX:
2438 assert(module);
2439
2440 /* check the module itself */
2441 if (dup_prefix_check(id, module)) {
2442 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "prefix", id);
2443 return EXIT_FAILURE;
2444 }
2445 break;
2446 case LY_IDENT_FEATURE:
2447 assert(module);
2448 mainmod = lys_main_module(module);
2449
2450 /* check feature name uniqueness*/
2451 /* check features in the current module */
2452 if (dup_feature_check(id, module)) {
2453 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "feature", id);
2454 return EXIT_FAILURE;
2455 }
2456
2457 /* and all its submodules */
2458 for (i = 0; i < mainmod->inc_size && mainmod->inc[i].submodule; i++) {
2459 if (dup_feature_check(id, (struct lys_module *)mainmod->inc[i].submodule)) {
2460 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "feature", id);
2461 return EXIT_FAILURE;
2462 }
2463 }
2464 break;
2465
2466 case LY_IDENT_EXTENSION:
2467 assert(module);
2468 mainmod = lys_main_module(module);
2469
2470 /* check extension name uniqueness in the main module ... */
2471 for (i = 0; i < mainmod->extensions_size; i++) {
2472 if (ly_strequal(id, mainmod->extensions[i].name, 1)) {
2473 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "extension", id);
2474 return EXIT_FAILURE;
2475 }
2476 }
2477
2478 /* ... and all its submodules */
2479 for (j = 0; j < mainmod->inc_size && mainmod->inc[j].submodule; j++) {
2480 submod = mainmod->inc[j].submodule; /* shortcut */
2481 for (i = 0; i < submod->extensions_size; i++) {
2482 if (ly_strequal(id, submod->extensions[i].name, 1)) {
2483 LOGVAL(ctx, LYE_DUPID, LY_VLOG_NONE, NULL, "extension", id);
2484 return EXIT_FAILURE;
2485 }
2486 }
2487 }
2488
2489 break;
2490
2491 default:
2492 /* no check required */
2493 break;
2494 }
2495
2496 return EXIT_SUCCESS;
2497 }
2498
2499 /* logs directly */
2500 int
lyp_check_date(struct ly_ctx * ctx,const char * date)2501 lyp_check_date(struct ly_ctx *ctx, const char *date)
2502 {
2503 int i;
2504 struct tm tm, tm_;
2505 time_t t;
2506 char *r;
2507
2508 assert(date);
2509
2510 /* check format */
2511 for (i = 0; i < LY_REV_SIZE - 1; i++) {
2512 if (i == 4 || i == 7) {
2513 if (date[i] != '-') {
2514 goto error;
2515 }
2516 } else if (!isdigit(date[i])) {
2517 goto error;
2518 }
2519 }
2520
2521 /* pre-fill tm with valid data */
2522 t = time(NULL);
2523 localtime_r(&t, &tm);
2524
2525 /* check content, e.g. 2018-02-31 */
2526 r = strptime(date, "%Y-%m-%d", &tm);
2527 if (!r || r != &date[LY_REV_SIZE - 1]) {
2528 goto error;
2529 }
2530
2531 memcpy(&tm_, &tm, sizeof tm);
2532 tm_.tm_isdst = -1; /* mktime corrects DST mismatches, this stops it from doing that */
2533 mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
2534 if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
2535 /* checking days is enough, since other errors
2536 * have been checked by strptime() */
2537 goto error;
2538 }
2539
2540 return EXIT_SUCCESS;
2541
2542 error:
2543 LOGVAL(ctx, LYE_INDATE, LY_VLOG_NONE, NULL, date);
2544 return EXIT_FAILURE;
2545 }
2546
2547 /**
2548 * @return
2549 * NULL - success
2550 * root - not yet resolvable
2551 * other node - mandatory node under the root
2552 */
2553 static const struct lys_node *
lyp_check_mandatory_(const struct lys_node * root)2554 lyp_check_mandatory_(const struct lys_node *root)
2555 {
2556 int mand_flag = 0;
2557 const struct lys_node *iter = NULL;
2558
2559 while ((iter = lys_getnext(iter, root, NULL, LYS_GETNEXT_WITHCHOICE | LYS_GETNEXT_WITHUSES | LYS_GETNEXT_INTOUSES
2560 | LYS_GETNEXT_INTONPCONT | LYS_GETNEXT_NOSTATECHECK))) {
2561 if (iter->nodetype == LYS_USES) {
2562 if (!((struct lys_node_uses *)iter)->grp) {
2563 /* not yet resolved uses */
2564 return root;
2565 } else {
2566 /* go into uses */
2567 continue;
2568 }
2569 }
2570 if (iter->nodetype == LYS_CHOICE) {
2571 /* skip it, it was already checked for direct mandatory node in default */
2572 continue;
2573 }
2574 if (iter->nodetype == LYS_LIST) {
2575 if (((struct lys_node_list *)iter)->min) {
2576 mand_flag = 1;
2577 }
2578 } else if (iter->nodetype == LYS_LEAFLIST) {
2579 if (((struct lys_node_leaflist *)iter)->min) {
2580 mand_flag = 1;
2581 }
2582 } else if (iter->flags & LYS_MAND_TRUE) {
2583 mand_flag = 1;
2584 }
2585
2586 if (mand_flag) {
2587 return iter;
2588 }
2589 }
2590
2591 return NULL;
2592 }
2593
2594 /* logs directly */
2595 int
lyp_check_mandatory_augment(struct lys_node_augment * aug,const struct lys_node * target)2596 lyp_check_mandatory_augment(struct lys_node_augment *aug, const struct lys_node *target)
2597 {
2598 const struct lys_node *node;
2599
2600 if (aug->when || target->nodetype == LYS_CHOICE) {
2601 /* - mandatory nodes in new cases are ok;
2602 * clarification from YANG 1.1 - augmentation can add mandatory nodes when it is
2603 * conditional with a when statement */
2604 return EXIT_SUCCESS;
2605 }
2606
2607 if ((node = lyp_check_mandatory_((struct lys_node *)aug))) {
2608 if (node != (struct lys_node *)aug) {
2609 LOGVAL(target->module->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2610 LOGVAL(target->module->ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2611 "Mandatory node \"%s\" appears in augment of \"%s\" without when condition.",
2612 node->name, aug->target_name);
2613 return -1;
2614 }
2615 return EXIT_FAILURE;
2616 }
2617
2618 return EXIT_SUCCESS;
2619 }
2620
2621 /**
2622 * @brief check that a mandatory node is not directly under the default case.
2623 * @param[in] node choice with default node
2624 * @return EXIT_SUCCESS if the constraint is fulfilled, EXIT_FAILURE otherwise
2625 */
2626 int
lyp_check_mandatory_choice(struct lys_node * node)2627 lyp_check_mandatory_choice(struct lys_node *node)
2628 {
2629 const struct lys_node *mand, *dflt = ((struct lys_node_choice *)node)->dflt;
2630
2631 if ((mand = lyp_check_mandatory_(dflt))) {
2632 if (mand != dflt) {
2633 LOGVAL(node->module->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "mandatory");
2634 LOGVAL(node->module->ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2635 "Mandatory node \"%s\" is directly under the default case \"%s\" of the \"%s\" choice.",
2636 mand->name, dflt->name, node->name);
2637 return -1;
2638 }
2639 return EXIT_FAILURE;
2640 }
2641
2642 return EXIT_SUCCESS;
2643 }
2644
2645 /**
2646 * @brief Check status for invalid combination.
2647 *
2648 * @param[in] flags1 Flags of the referencing node.
2649 * @param[in] mod1 Module of the referencing node,
2650 * @param[in] name1 Schema node name of the referencing node.
2651 * @param[in] flags2 Flags of the referenced node.
2652 * @param[in] mod2 Module of the referenced node,
2653 * @param[in] name2 Schema node name of the referenced node.
2654 * @return EXIT_SUCCES on success, EXIT_FAILURE on invalid reference.
2655 */
2656 int
lyp_check_status(uint16_t flags1,struct lys_module * mod1,const char * name1,uint16_t flags2,struct lys_module * mod2,const char * name2,const struct lys_node * node)2657 lyp_check_status(uint16_t flags1, struct lys_module *mod1, const char *name1,
2658 uint16_t flags2, struct lys_module *mod2, const char *name2,
2659 const struct lys_node *node)
2660 {
2661 uint16_t flg1, flg2;
2662
2663 flg1 = (flags1 & LYS_STATUS_MASK) ? (flags1 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
2664 flg2 = (flags2 & LYS_STATUS_MASK) ? (flags2 & LYS_STATUS_MASK) : LYS_STATUS_CURR;
2665
2666 if ((flg1 < flg2) && (lys_main_module(mod1) == lys_main_module(mod2))) {
2667 LOGVAL(mod1->ctx, LYE_INSTATUS, node ? LY_VLOG_LYS : LY_VLOG_NONE, node,
2668 flg1 == LYS_STATUS_CURR ? "current" : "deprecated", name1, "references",
2669 flg2 == LYS_STATUS_OBSLT ? "obsolete" : "deprecated", name2);
2670 return EXIT_FAILURE;
2671 }
2672
2673 return EXIT_SUCCESS;
2674 }
2675
2676 void
lyp_del_includedup(struct lys_module * mod,int free_subs)2677 lyp_del_includedup(struct lys_module *mod, int free_subs)
2678 {
2679 struct ly_modules_list *models = &mod->ctx->models;
2680 uint8_t i;
2681
2682 assert(mod && !mod->type);
2683
2684 if (models->parsed_submodules_count) {
2685 for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i);
2686 if (models->parsed_submodules[i] == mod) {
2687 if (free_subs) {
2688 for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i) {
2689 lys_sub_module_remove_devs_augs((struct lys_module *)models->parsed_submodules[i]);
2690 lys_submodule_module_data_free((struct lys_submodule *)models->parsed_submodules[i]);
2691 lys_submodule_free((struct lys_submodule *)models->parsed_submodules[i], NULL);
2692 }
2693 }
2694
2695 models->parsed_submodules_count = i;
2696 if (!models->parsed_submodules_count) {
2697 free(models->parsed_submodules);
2698 models->parsed_submodules = NULL;
2699 }
2700 }
2701 }
2702 }
2703
2704 static void
lyp_add_includedup(struct lys_module * sub_mod,struct lys_submodule * parsed_submod)2705 lyp_add_includedup(struct lys_module *sub_mod, struct lys_submodule *parsed_submod)
2706 {
2707 struct ly_modules_list *models = &sub_mod->ctx->models;
2708 int16_t i;
2709
2710 /* store main module if first include */
2711 if (models->parsed_submodules_count) {
2712 for (i = models->parsed_submodules_count - 1; models->parsed_submodules[i]->type; --i);
2713 } else {
2714 i = -1;
2715 }
2716 if ((i == -1) || (models->parsed_submodules[i] != lys_main_module(sub_mod))) {
2717 ++models->parsed_submodules_count;
2718 models->parsed_submodules = ly_realloc(models->parsed_submodules,
2719 models->parsed_submodules_count * sizeof *models->parsed_submodules);
2720 LY_CHECK_ERR_RETURN(!models->parsed_submodules, LOGMEM(sub_mod->ctx), );
2721 models->parsed_submodules[models->parsed_submodules_count - 1] = lys_main_module(sub_mod);
2722 }
2723
2724 /* store parsed submodule */
2725 ++models->parsed_submodules_count;
2726 models->parsed_submodules = ly_realloc(models->parsed_submodules,
2727 models->parsed_submodules_count * sizeof *models->parsed_submodules);
2728 LY_CHECK_ERR_RETURN(!models->parsed_submodules, LOGMEM(sub_mod->ctx), );
2729 models->parsed_submodules[models->parsed_submodules_count - 1] = (struct lys_module *)parsed_submod;
2730 }
2731
2732 /*
2733 * types: 0 - include, 1 - import
2734 */
2735 static int
lyp_check_circmod(struct lys_module * module,const char * value,int type)2736 lyp_check_circmod(struct lys_module *module, const char *value, int type)
2737 {
2738 LY_ECODE code = type ? LYE_CIRC_IMPORTS : LYE_CIRC_INCLUDES;
2739 struct ly_modules_list *models = &module->ctx->models;
2740 uint8_t i;
2741
2742 /* include/import itself */
2743 if (ly_strequal(module->name, value, 1)) {
2744 LOGVAL(module->ctx, code, LY_VLOG_NONE, NULL, value);
2745 return -1;
2746 }
2747
2748 /* currently parsed modules */
2749 for (i = 0; i < models->parsing_sub_modules_count; i++) {
2750 if (ly_strequal(models->parsing_sub_modules[i]->name, value, 1)) {
2751 LOGVAL(module->ctx, code, LY_VLOG_NONE, NULL, value);
2752 return -1;
2753 }
2754 }
2755
2756 return 0;
2757 }
2758
2759 int
lyp_check_circmod_add(struct lys_module * module)2760 lyp_check_circmod_add(struct lys_module *module)
2761 {
2762 struct ly_modules_list *models = &module->ctx->models;
2763
2764 /* storing - enlarge the list of modules being currently parsed */
2765 ++models->parsing_sub_modules_count;
2766 models->parsing_sub_modules = ly_realloc(models->parsing_sub_modules,
2767 models->parsing_sub_modules_count * sizeof *models->parsing_sub_modules);
2768 LY_CHECK_ERR_RETURN(!models->parsing_sub_modules, LOGMEM(module->ctx), -1);
2769 models->parsing_sub_modules[models->parsing_sub_modules_count - 1] = module;
2770
2771 return 0;
2772 }
2773
2774 void
lyp_check_circmod_pop(struct ly_ctx * ctx)2775 lyp_check_circmod_pop(struct ly_ctx *ctx)
2776 {
2777 if (!ctx->models.parsing_sub_modules_count) {
2778 LOGINT(ctx);
2779 return;
2780 }
2781
2782 /* update the list of currently being parsed modules */
2783 ctx->models.parsing_sub_modules_count--;
2784 if (!ctx->models.parsing_sub_modules_count) {
2785 free(ctx->models.parsing_sub_modules);
2786 ctx->models.parsing_sub_modules = NULL;
2787 }
2788 }
2789
2790 /*
2791 * -1 - error - invalid duplicities)
2792 * 0 - success, no duplicity
2793 * 1 - success, valid duplicity found and stored in *sub
2794 */
2795 static int
lyp_check_includedup(struct lys_module * mod,const char * name,struct lys_include * inc,struct lys_submodule ** sub)2796 lyp_check_includedup(struct lys_module *mod, const char *name, struct lys_include *inc, struct lys_submodule **sub)
2797 {
2798 struct lys_module **parsed_sub = mod->ctx->models.parsed_submodules;
2799 uint8_t i, parsed_sub_count = mod->ctx->models.parsed_submodules_count;
2800
2801 assert(sub);
2802
2803 for (i = 0; i < mod->inc_size; ++i) {
2804 if (ly_strequal(mod->inc[i].submodule->name, name, 1)) {
2805 /* the same module is already included in the same module - error */
2806 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "include");
2807 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Submodule \"%s\" included twice in the same module \"%s\".",
2808 name, mod->name);
2809 return -1;
2810 }
2811 }
2812
2813 if (parsed_sub_count) {
2814 assert(!parsed_sub[0]->type);
2815 for (i = parsed_sub_count - 1; parsed_sub[i]->type; --i) {
2816 if (ly_strequal(parsed_sub[i]->name, name, 1)) {
2817 /* check revisions, including multiple revisions of a single module is error */
2818 if (inc->rev[0] && (!parsed_sub[i]->rev_size || strcmp(parsed_sub[i]->rev[0].date, inc->rev))) {
2819 /* the already included submodule has
2820 * - no revision, but here we require some
2821 * - different revision than the one required here */
2822 LOGVAL(mod->ctx, LYE_INARG, LY_VLOG_NONE, NULL, name, "include");
2823 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Including multiple revisions of submodule \"%s\".", name);
2824 return -1;
2825 }
2826
2827 /* the same module is already included in some other submodule, return it */
2828 (*sub) = (struct lys_submodule *)parsed_sub[i];
2829 return 1;
2830 }
2831 }
2832 }
2833
2834 /* no duplicity found */
2835 return 0;
2836 }
2837
2838 /* returns:
2839 * 0 - inc successfully filled
2840 * -1 - error
2841 */
2842 int
lyp_check_include(struct lys_module * module,const char * value,struct lys_include * inc,struct unres_schema * unres)2843 lyp_check_include(struct lys_module *module, const char *value, struct lys_include *inc, struct unres_schema *unres)
2844 {
2845 int i;
2846
2847 /* check that the submodule was not included yet */
2848 i = lyp_check_includedup(module, value, inc, &inc->submodule);
2849 if (i == -1) {
2850 return -1;
2851 } else if (i == 1) {
2852 return 0;
2853 }
2854 /* submodule is not yet loaded */
2855
2856 /* circular include check */
2857 if (lyp_check_circmod(module, value, 0)) {
2858 return -1;
2859 }
2860
2861 /* try to load the submodule */
2862 inc->submodule = (struct lys_submodule *)ly_ctx_load_sub_module(module->ctx, module, value,
2863 inc->rev[0] ? inc->rev : NULL, 1, unres);
2864
2865 /* check the result */
2866 if (!inc->submodule) {
2867 if (ly_errno != LY_EVALID) {
2868 LOGVAL(module->ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "include");
2869 }
2870 LOGERR(module->ctx, LY_EVALID, "Including \"%s\" module into \"%s\" failed.", value, module->name);
2871 return -1;
2872 }
2873
2874 /* check the revision */
2875 if (inc->rev[0] && inc->submodule->rev_size && strcmp(inc->rev, inc->submodule->rev[0].date)) {
2876 LOGERR(module->ctx, LY_EVALID, "\"%s\" include of submodule \"%s\" in revision \"%s\" not found.",
2877 module->name, value, inc->rev);
2878 unres_schema_free((struct lys_module *)inc->submodule, &unres, 0);
2879 lys_sub_module_remove_devs_augs((struct lys_module *)inc->submodule);
2880 lys_submodule_module_data_free((struct lys_submodule *)inc->submodule);
2881 lys_submodule_free(inc->submodule, NULL);
2882 inc->submodule = NULL;
2883 return -1;
2884 }
2885
2886 /* store the submodule as successfully parsed */
2887 lyp_add_includedup(module, inc->submodule);
2888
2889 return 0;
2890 }
2891
2892 static int
lyp_check_include_missing_recursive(struct lys_module * main_module,struct lys_submodule * sub)2893 lyp_check_include_missing_recursive(struct lys_module *main_module, struct lys_submodule *sub)
2894 {
2895 uint8_t i, j;
2896 void *reallocated;
2897 int ret = 0, tmp;
2898 struct ly_ctx *ctx = main_module->ctx;
2899
2900 for (i = 0; i < sub->inc_size; i++) {
2901 /* check that the include is also present in the main module */
2902 for (j = 0; j < main_module->inc_size; j++) {
2903 if (main_module->inc[j].submodule == sub->inc[i].submodule) {
2904 break;
2905 }
2906 }
2907
2908 if (j == main_module->inc_size) {
2909 /* match not found */
2910 if (main_module->version >= LYS_VERSION_1_1) {
2911 LOGVAL(ctx, LYE_MISSSTMT, LY_VLOG_NONE, NULL, "include");
2912 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
2913 "The main module \"%s\" misses include of the \"%s\" submodule used in another submodule \"%s\".",
2914 main_module->name, sub->inc[i].submodule->name, sub->name);
2915 /* now we should return error, but due to the issues with freeing the module, we actually have
2916 * to go through the all includes and, as in case of 1.0, add them into the main module and fail
2917 * at the end when all the includes are in the main module and we can free them */
2918 ret = 1;
2919 } else {
2920 /* not strictly an error in YANG 1.0 */
2921 LOGWRN(ctx, "The main module \"%s\" misses include of the \"%s\" submodule used in another submodule \"%s\".",
2922 main_module->name, sub->inc[i].submodule->name, sub->name);
2923 LOGWRN(ctx, "To avoid further issues, adding submodule \"%s\" into the main module \"%s\".",
2924 sub->inc[i].submodule->name, main_module->name);
2925 /* but since it is a good practise and because we expect all the includes in the main module
2926 * when searching it and also when freeing the module, put it into it */
2927 }
2928 main_module->inc_size++;
2929 reallocated = realloc(main_module->inc, main_module->inc_size * sizeof *main_module->inc);
2930 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx), 1);
2931 main_module->inc = reallocated;
2932 memset(&main_module->inc[main_module->inc_size - 1], 0, sizeof *main_module->inc);
2933 /* to avoid unexpected consequences, copy just a link to the submodule and the revision,
2934 * all other substatements of the include are ignored */
2935 memcpy(&main_module->inc[main_module->inc_size - 1].rev, sub->inc[i].rev, LY_REV_SIZE - 1);
2936 main_module->inc[main_module->inc_size - 1].submodule = sub->inc[i].submodule;
2937 }
2938
2939 /* recursion */
2940 tmp = lyp_check_include_missing_recursive(main_module, sub->inc[i].submodule);
2941 if (!ret && tmp) {
2942 ret = 1;
2943 }
2944 }
2945
2946 return ret;
2947 }
2948
2949 int
lyp_check_include_missing(struct lys_module * main_module)2950 lyp_check_include_missing(struct lys_module *main_module)
2951 {
2952 int ret = 0;
2953 uint8_t i;
2954
2955 /* in YANG 1.1, all the submodules must be in the main module, check it even for
2956 * 1.0 where it will be printed as warning and the include will be added into the main module */
2957 for (i = 0; i < main_module->inc_size; i++) {
2958 if (lyp_check_include_missing_recursive(main_module, main_module->inc[i].submodule)) {
2959 ret = 1;
2960 }
2961 }
2962
2963 return ret;
2964 }
2965
2966 /* returns:
2967 * 0 - imp successfully filled
2968 * -1 - error, imp not cleaned
2969 */
2970 int
lyp_check_import(struct lys_module * module,const char * value,struct lys_import * imp)2971 lyp_check_import(struct lys_module *module, const char *value, struct lys_import *imp)
2972 {
2973 int i;
2974 struct lys_module *dup = NULL;
2975 struct ly_ctx *ctx = module->ctx;
2976
2977 /* check for importing a single module in multiple revisions */
2978 for (i = 0; i < module->imp_size; i++) {
2979 if (!module->imp[i].module) {
2980 /* skip the not yet filled records */
2981 continue;
2982 }
2983 if (ly_strequal(module->imp[i].module->name, value, 1)) {
2984 /* check revisions, including multiple revisions of a single module is error */
2985 if (imp->rev[0] && (!module->imp[i].module->rev_size || strcmp(module->imp[i].module->rev[0].date, imp->rev))) {
2986 /* the already imported module has
2987 * - no revision, but here we require some
2988 * - different revision than the one required here */
2989 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
2990 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
2991 return -1;
2992 } else if (!imp->rev[0]) {
2993 /* no revision, remember the duplication, but check revisions after loading the module
2994 * because the current revision can be the same (then it is ok) or it can differ (then it
2995 * is error */
2996 dup = module->imp[i].module;
2997 break;
2998 }
2999
3000 /* there is duplication, but since prefixes differs (checked in caller of this function),
3001 * it is ok */
3002 imp->module = module->imp[i].module;
3003 return 0;
3004 }
3005 }
3006
3007 /* circular import check */
3008 if (lyp_check_circmod(module, value, 1)) {
3009 return -1;
3010 }
3011
3012 /* load module - in specific situations it tries to get the module from the context */
3013 imp->module = (struct lys_module *)ly_ctx_load_sub_module(module->ctx, NULL, value, imp->rev[0] ? imp->rev : NULL,
3014 module->ctx->models.flags & LY_CTX_ALLIMPLEMENTED ? 1 : 0,
3015 NULL);
3016
3017 /* check the result */
3018 if (!imp->module) {
3019 LOGERR(ctx, LY_EVALID, "Importing \"%s\" module into \"%s\" failed.", value, module->name);
3020 return -1;
3021 }
3022
3023 if (imp->rev[0] && imp->module->rev_size && strcmp(imp->rev, imp->module->rev[0].date)) {
3024 LOGERR(ctx, LY_EVALID, "\"%s\" import of module \"%s\" in revision \"%s\" not found.",
3025 module->name, value, imp->rev);
3026 return -1;
3027 }
3028
3029 if ((module->version < 2) && imp->rev[0] && (imp->module->version == 2)) {
3030 LOGERR(ctx, LY_EVALID, "YANG 1.0 module \"%s\" import with revision of YANG 1.1 module \"%s\".",
3031 module->name, imp->module->name);
3032 return -1;
3033 }
3034
3035 if (dup) {
3036 /* check the revisions */
3037 if ((dup != imp->module) ||
3038 (dup->rev_size != imp->module->rev_size && (!dup->rev_size || imp->module->rev_size)) ||
3039 (dup->rev_size && strcmp(dup->rev[0].date, imp->module->rev[0].date))) {
3040 /* - modules are not the same
3041 * - one of modules has no revision (except they both has no revision)
3042 * - revisions of the modules are not the same */
3043 LOGVAL(ctx, LYE_INARG, LY_VLOG_NONE, NULL, value, "import");
3044 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Importing multiple revisions of module \"%s\".", value);
3045 return -1;
3046 } else {
3047 LOGWRN(ctx, "Module \"%s\" is imported by \"%s\" multiple times with different prefixes.", dup->name, module->name);
3048 }
3049 }
3050
3051 return 0;
3052 }
3053
3054 /*
3055 * put the newest revision to the first position
3056 */
3057 void
lyp_sort_revisions(struct lys_module * module)3058 lyp_sort_revisions(struct lys_module *module)
3059 {
3060 uint8_t i, r;
3061 struct lys_revision rev;
3062
3063 for (i = 1, r = 0; i < module->rev_size; i++) {
3064 if (strcmp(module->rev[i].date, module->rev[r].date) > 0) {
3065 r = i;
3066 }
3067 }
3068
3069 if (r) {
3070 /* the newest revision is not on position 0, switch them */
3071 memcpy(&rev, &module->rev[0], sizeof rev);
3072 memcpy(&module->rev[0], &module->rev[r], sizeof rev);
3073 memcpy(&module->rev[r], &rev, sizeof rev);
3074 }
3075 }
3076
3077 void
lyp_ext_instance_rm(struct ly_ctx * ctx,struct lys_ext_instance *** ext,uint8_t * size,uint8_t index)3078 lyp_ext_instance_rm(struct ly_ctx *ctx, struct lys_ext_instance ***ext, uint8_t *size, uint8_t index)
3079 {
3080 uint8_t i;
3081
3082 lys_extension_instances_free(ctx, (*ext)[index]->ext, (*ext)[index]->ext_size, NULL);
3083 lydict_remove(ctx, (*ext)[index]->arg_value);
3084 free((*ext)[index]);
3085
3086 /* move the rest of the array */
3087 for (i = index + 1; i < (*size); i++) {
3088 (*ext)[i - 1] = (*ext)[i];
3089 }
3090 /* clean the last cell in the array structure */
3091 (*ext)[(*size) - 1] = NULL;
3092 /* the array is not reallocated here, just change its size */
3093 (*size) = (*size) - 1;
3094
3095 if (!(*size)) {
3096 /* ext array is empty */
3097 free((*ext));
3098 ext = NULL;
3099 }
3100 }
3101
3102 static int
lyp_rfn_apply_ext_(struct lys_refine * rfn,struct lys_node * target,LYEXT_SUBSTMT substmt,struct lys_ext * extdef)3103 lyp_rfn_apply_ext_(struct lys_refine *rfn, struct lys_node *target, LYEXT_SUBSTMT substmt, struct lys_ext *extdef)
3104 {
3105 struct ly_ctx *ctx;
3106 int m, n;
3107 struct lys_ext_instance *new;
3108 void *reallocated;
3109
3110 ctx = target->module->ctx; /* shortcut */
3111
3112 m = n = -1;
3113 while ((m = lys_ext_iter(rfn->ext, rfn->ext_size, m + 1, substmt)) != -1) {
3114 /* refine's substatement includes extensions, copy them to the target, replacing the previous
3115 * substatement's extensions if any. In case of refining the extension itself, we are going to
3116 * replace only the same extension (pointing to the same definition) */
3117 if (substmt == LYEXT_SUBSTMT_SELF && rfn->ext[m]->def != extdef) {
3118 continue;
3119 }
3120
3121 /* get the index of the extension to replace in the target node */
3122 do {
3123 n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3124 } while (n != -1 && substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef);
3125
3126 /* TODO cover complex extension instances */
3127 if (n == -1) {
3128 /* nothing to replace, we are going to add it - reallocate */
3129 new = malloc(sizeof **target->ext);
3130 LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3131 reallocated = realloc(target->ext, (target->ext_size + 1) * sizeof *target->ext);
3132 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx); free(new), EXIT_FAILURE);
3133 target->ext = reallocated;
3134 target->ext_size++;
3135
3136 /* init */
3137 n = target->ext_size - 1;
3138 target->ext[n] = new;
3139 target->ext[n]->parent = target;
3140 target->ext[n]->parent_type = LYEXT_PAR_NODE;
3141 target->ext[n]->flags = 0;
3142 target->ext[n]->insubstmt = substmt;
3143 target->ext[n]->priv = NULL;
3144 target->ext[n]->nodetype = LYS_EXT;
3145 target->ext[n]->module = target->module;
3146 } else {
3147 /* replacing - first remove the allocated data from target */
3148 lys_extension_instances_free(ctx, target->ext[n]->ext, target->ext[n]->ext_size, NULL);
3149 lydict_remove(ctx, target->ext[n]->arg_value);
3150 }
3151 /* common part for adding and replacing */
3152 target->ext[n]->def = rfn->ext[m]->def;
3153 /* parent and parent_type do not change */
3154 target->ext[n]->arg_value = lydict_insert(ctx, rfn->ext[m]->arg_value, 0);
3155 /* flags do not change */
3156 target->ext[n]->ext_size = rfn->ext[m]->ext_size;
3157 lys_ext_dup(ctx, target->module, rfn->ext[m]->ext, rfn->ext[m]->ext_size, target, LYEXT_PAR_NODE,
3158 &target->ext[n]->ext, 0, NULL);
3159 /* substmt does not change, but the index must be taken from the refine */
3160 target->ext[n]->insubstmt_index = rfn->ext[m]->insubstmt_index;
3161 }
3162
3163 /* remove the rest of extensions belonging to the original substatement in the target node */
3164 while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt)) != -1) {
3165 if (substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef) {
3166 /* keep this extension */
3167 continue;
3168 }
3169
3170 /* remove the item */
3171 lyp_ext_instance_rm(ctx, &target->ext, &target->ext_size, n);
3172 --n;
3173 }
3174
3175 return EXIT_SUCCESS;
3176 }
3177
3178 /*
3179 * apply extension instances defined under refine's substatements.
3180 * It cannot be done immediately when applying the refine because there can be
3181 * still unresolved data (e.g. type) and mainly the targeted extension instances.
3182 */
3183 int
lyp_rfn_apply_ext(struct lys_module * module)3184 lyp_rfn_apply_ext(struct lys_module *module)
3185 {
3186 int i, k, a = 0;
3187 struct lys_node *root, *nextroot, *next, *node;
3188 struct lys_node *target;
3189 struct lys_node_uses *uses;
3190 struct lys_refine *rfn;
3191 struct ly_set *extset;
3192
3193 /* refines in uses */
3194 LY_TREE_FOR_SAFE(module->data, nextroot, root) {
3195 /* go through the data tree of the module and all the defined augments */
3196
3197 LY_TREE_DFS_BEGIN(root, next, node) {
3198 if (node->nodetype == LYS_USES) {
3199 uses = (struct lys_node_uses *)node;
3200
3201 for (i = 0; i < uses->refine_size; i++) {
3202 if (!uses->refine[i].ext_size) {
3203 /* no extensions in refine */
3204 continue;
3205 }
3206 rfn = &uses->refine[i]; /* shortcut */
3207
3208 /* get the target node */
3209 target = NULL;
3210 resolve_descendant_schema_nodeid(rfn->target_name, uses->child,
3211 LYS_NO_RPC_NOTIF_NODE | LYS_ACTION | LYS_NOTIF,
3212 0, (const struct lys_node **)&target);
3213 if (!target) {
3214 /* it should always succeed since the target_name was already resolved at least
3215 * once when the refine itself was being resolved */
3216 LOGINT(module->ctx);;
3217 return EXIT_FAILURE;
3218 }
3219
3220 /* extensions */
3221 extset = ly_set_new();
3222 k = -1;
3223 while ((k = lys_ext_iter(rfn->ext, rfn->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3224 ly_set_add(extset, rfn->ext[k]->def, 0);
3225 }
3226 for (k = 0; (unsigned int)k < extset->number; k++) {
3227 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_SELF, (struct lys_ext *)extset->set.g[k])) {
3228 ly_set_free(extset);
3229 return EXIT_FAILURE;
3230 }
3231 }
3232 ly_set_free(extset);
3233
3234 /* description */
3235 if (rfn->dsc && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_DESCRIPTION, NULL)) {
3236 return EXIT_FAILURE;
3237 }
3238 /* reference */
3239 if (rfn->ref && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_REFERENCE, NULL)) {
3240 return EXIT_FAILURE;
3241 }
3242 /* config, in case of notification or rpc/action{notif, the config is not applicable
3243 * (there is no config status) */
3244 if ((rfn->flags & LYS_CONFIG_MASK) && (target->flags & LYS_CONFIG_MASK)) {
3245 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_CONFIG, NULL)) {
3246 return EXIT_FAILURE;
3247 }
3248 }
3249 /* default value */
3250 if (rfn->dflt_size && lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_DEFAULT, NULL)) {
3251 return EXIT_FAILURE;
3252 }
3253 /* mandatory */
3254 if (rfn->flags & LYS_MAND_MASK) {
3255 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MANDATORY, NULL)) {
3256 return EXIT_FAILURE;
3257 }
3258 }
3259 /* presence */
3260 if ((target->nodetype & LYS_CONTAINER) && rfn->mod.presence) {
3261 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_PRESENCE, NULL)) {
3262 return EXIT_FAILURE;
3263 }
3264 }
3265 /* min/max */
3266 if (rfn->flags & LYS_RFN_MINSET) {
3267 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MIN, NULL)) {
3268 return EXIT_FAILURE;
3269 }
3270 }
3271 if (rfn->flags & LYS_RFN_MAXSET) {
3272 if (lyp_rfn_apply_ext_(rfn, target, LYEXT_SUBSTMT_MAX, NULL)) {
3273 return EXIT_FAILURE;
3274 }
3275 }
3276 /* must and if-feature contain extensions on their own, not needed to be solved here */
3277
3278 if (target->ext_size) {
3279 /* the allocated target's extension array can be now longer than needed in case
3280 * there is less refine substatement's extensions than in original. Since we are
3281 * going to reduce or keep the same memory, it is not necessary to test realloc's result */
3282 target->ext = realloc(target->ext, target->ext_size * sizeof *target->ext);
3283 }
3284 }
3285 }
3286 LY_TREE_DFS_END(root, next, node)
3287 }
3288
3289 if (!nextroot && a < module->augment_size) {
3290 nextroot = module->augment[a].child;
3291 a++;
3292 }
3293 }
3294
3295 return EXIT_SUCCESS;
3296 }
3297
3298 /*
3299 * check mandatory substatements defined under extension instances.
3300 */
3301 int
lyp_mand_check_ext(struct lys_ext_instance_complex * ext,const char * ext_name)3302 lyp_mand_check_ext(struct lys_ext_instance_complex *ext, const char *ext_name)
3303 {
3304 void *p;
3305 int i;
3306 struct ly_ctx *ctx = ext->module->ctx;
3307
3308 /* check for mandatory substatements */
3309 for (i = 0; ext->substmt[i].stmt; i++) {
3310 if (ext->substmt[i].cardinality == LY_STMT_CARD_OPT || ext->substmt[i].cardinality == LY_STMT_CARD_ANY) {
3311 /* not a mandatory */
3312 continue;
3313 } else if (ext->substmt[i].cardinality == LY_STMT_CARD_SOME) {
3314 goto array;
3315 }
3316
3317 /*
3318 * LY_STMT_ORDEREDBY - not checked, has a default value which is the same as explicit system order
3319 * LY_STMT_MODIFIER, LY_STMT_STATUS, LY_STMT_MANDATORY, LY_STMT_CONFIG - checked, but mandatory requirement
3320 * does not make sense since there is also a default value specified
3321 */
3322 switch(ext->substmt[i].stmt) {
3323 case LY_STMT_ORDEREDBY:
3324 /* always ok */
3325 break;
3326 case LY_STMT_REQINSTANCE:
3327 case LY_STMT_DIGITS:
3328 case LY_STMT_MODIFIER:
3329 p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3330 if (!*(uint8_t*)p) {
3331 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3332 goto error;
3333 }
3334 break;
3335 case LY_STMT_STATUS:
3336 p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3337 if (!(*(uint16_t*)p & LYS_STATUS_MASK)) {
3338 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3339 goto error;
3340 }
3341 break;
3342 case LY_STMT_MANDATORY:
3343 p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3344 if (!(*(uint16_t*)p & LYS_MAND_MASK)) {
3345 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3346 goto error;
3347 }
3348 break;
3349 case LY_STMT_CONFIG:
3350 p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3351 if (!(*(uint16_t*)p & LYS_CONFIG_MASK)) {
3352 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3353 goto error;
3354 }
3355 break;
3356 default:
3357 array:
3358 /* stored as a pointer */
3359 p = lys_ext_complex_get_substmt(ext->substmt[i].stmt, ext, NULL);
3360 if (!(*(void**)p)) {
3361 LOGVAL(ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, ly_stmt_str[ext->substmt[i].stmt], ext_name);
3362 goto error;
3363 }
3364 break;
3365 }
3366 }
3367
3368 return EXIT_SUCCESS;
3369
3370 error:
3371 return EXIT_FAILURE;
3372 }
3373
3374 static int
check_deviate_config(struct lys_node * node)3375 check_deviate_config(struct lys_node *node)
3376 {
3377 struct ly_ctx *ctx = node->module->ctx;
3378 struct lys_node *parent = lys_parent(node);
3379
3380 /* from rfc7950#page-86: All key leafs in a list MUST have the same value
3381 * for their "config" as the list itself.
3382 */
3383 if (lys_is_key((struct lys_node_leaf *)node, NULL) &&
3384 ((parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK))) {
3385 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3386 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "The deviate statement causes a violation of \"config\" rules in"
3387 " a key leaf. The \"config\" value in the key leaf must be the same as in the list to which belongs.");
3388 return EXIT_FAILURE;
3389 }
3390
3391 /* from rfc7950#page-135: If the parent node is a case node,
3392 * the value is the same as the case node's parent choice node.
3393 */
3394 if (node->nodetype == LYS_CASE) {
3395 assert(parent && (parent->nodetype == LYS_CHOICE));
3396 if ((parent->flags & LYS_CONFIG_MASK) != (node->flags & LYS_CONFIG_MASK)) {
3397 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3398 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
3399 "The deviate statement causes a violation of \"config\" rules in a case node. "
3400 "The \"config\" value in the case must be the same as in the choice to which belongs.");
3401 return EXIT_FAILURE;
3402 }
3403 }
3404
3405 /* from rfc7950#page-135: If a node has "config" set to "false",
3406 * no node underneath it can have "config" set to "true".
3407 */
3408 if (parent && (node->flags & LYS_CONFIG_W) && (parent->flags & LYS_CONFIG_R)) {
3409 LOGVAL(ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "config");
3410 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
3411 "The deviate statement causes a violation of \"config\" nesting rules. The config for node \"%s\" is"
3412 " \"true\" while for its parent \"%s\" is \"false\".", node->name, parent->name);
3413 return EXIT_FAILURE;
3414 }
3415
3416 return EXIT_SUCCESS;
3417 }
3418
3419 int
lyp_deviate_inherit_config_r(struct lys_node * node)3420 lyp_deviate_inherit_config_r(struct lys_node *node)
3421 {
3422 struct lys_node *child;
3423
3424 /* check node */
3425 if (check_deviate_config(node)) {
3426 return EXIT_FAILURE;
3427 }
3428
3429 /* recursive check and inherit (operations ignore config so it can be skipped) */
3430 if (!(node->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA | LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
3431 LY_TREE_FOR(node->child, child) {
3432 if (child->flags & LYS_CONFIG_SET) {
3433 /* keep the explicit config, but check it is fine because it may depend on the parent config */
3434 if (check_deviate_config(child)) {
3435 return EXIT_FAILURE;
3436 }
3437 } else {
3438 /* inherit config from the parent */
3439 child->flags &= ~LYS_CONFIG_MASK;
3440 child->flags |= (node->flags & LYS_CONFIG_MASK);
3441
3442 /* recursive call */
3443 if (lyp_deviate_inherit_config_r(child)) {
3444 return EXIT_FAILURE;
3445 }
3446 }
3447 }
3448 }
3449
3450 return EXIT_SUCCESS;
3451 }
3452
3453 static int
lyp_deviate_del_ext(struct lys_node * target,struct lys_ext_instance * ext)3454 lyp_deviate_del_ext(struct lys_node *target, struct lys_ext_instance *ext)
3455 {
3456 int n = -1, found = 0;
3457 char *path;
3458
3459 while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, ext->insubstmt)) != -1) {
3460 if (target->ext[n]->def != ext->def) {
3461 continue;
3462 }
3463
3464 if (ext->def->argument) {
3465 /* check matching arguments */
3466 if (!ly_strequal(target->ext[n]->arg_value, ext->arg_value, 1)) {
3467 continue;
3468 }
3469 }
3470
3471 /* we have the matching extension - remove it */
3472 ++found;
3473 lyp_ext_instance_rm(target->module->ctx, &target->ext, &target->ext_size, n);
3474 --n;
3475 }
3476
3477 if (!found) {
3478 path = lys_path(target, LYS_PATH_FIRST_PREFIX);
3479 LOGERR(target->module->ctx, LY_EVALID, "Extension deviation: extension \"%s\" to delete not found in \"%s\".",
3480 ext->def->name, path)
3481 free(path);
3482 return EXIT_FAILURE;
3483 }
3484 return EXIT_SUCCESS;
3485 }
3486
3487 static int
lyp_deviate_apply_ext(struct lys_deviate * dev,struct lys_node * target,LYEXT_SUBSTMT substmt,struct lys_ext * extdef)3488 lyp_deviate_apply_ext(struct lys_deviate *dev, struct lys_node *target, LYEXT_SUBSTMT substmt, struct lys_ext *extdef)
3489 {
3490 struct ly_ctx *ctx;
3491 int m, n;
3492 struct lys_ext_instance *new;
3493 void *reallocated;
3494
3495 /* LY_DEVIATE_ADD and LY_DEVIATE_RPL are very similar so they are implement the same way - in replacing,
3496 * there can be some extension instances in the target, in case of adding, there should not be any so we
3497 * will be just adding. */
3498
3499 ctx = target->module->ctx; /* shortcut */
3500 m = n = -1;
3501
3502 while ((m = lys_ext_iter(dev->ext, dev->ext_size, m + 1, substmt)) != -1) {
3503 /* deviate and its substatements include extensions, copy them to the target, replacing the previous
3504 * extensions if any. In case of deviating extension itself, we have to deviate only the same type
3505 * of the extension as specified in the deviation */
3506 if (substmt == LYEXT_SUBSTMT_SELF && dev->ext[m]->def != extdef) {
3507 continue;
3508 }
3509
3510 if (substmt == LYEXT_SUBSTMT_SELF && dev->mod == LY_DEVIATE_ADD) {
3511 /* in case of adding extension, we will be replacing only the inherited extensions */
3512 do {
3513 n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3514 } while (n != -1 && (target->ext[n]->def != extdef || !(target->ext[n]->flags & LYEXT_OPT_INHERIT)));
3515 } else {
3516 /* get the index of the extension to replace in the target node */
3517 do {
3518 n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt);
3519 /* if we are applying extension deviation, we have to deviate only the same type of the extension */
3520 } while (n != -1 && substmt == LYEXT_SUBSTMT_SELF && target->ext[n]->def != extdef);
3521 }
3522
3523 if (n == -1) {
3524 /* nothing to replace, we are going to add it - reallocate */
3525 new = malloc(sizeof **target->ext);
3526 LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3527 reallocated = realloc(target->ext, (target->ext_size + 1) * sizeof *target->ext);
3528 LY_CHECK_ERR_RETURN(!reallocated, LOGMEM(ctx); free(new), EXIT_FAILURE);
3529 target->ext = reallocated;
3530 target->ext_size++;
3531
3532 n = target->ext_size - 1;
3533 } else {
3534 /* replacing - the original set of extensions is actually backuped together with the
3535 * node itself, so we are supposed only to free the allocated data here ... */
3536 lys_extension_instances_free(ctx, target->ext[n]->ext, target->ext[n]->ext_size, NULL);
3537 lydict_remove(ctx, target->ext[n]->arg_value);
3538 free(target->ext[n]);
3539
3540 /* and prepare the new structure */
3541 new = malloc(sizeof **target->ext);
3542 LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), EXIT_FAILURE);
3543 }
3544 /* common part for adding and replacing - fill the newly created / replaced cell */
3545 target->ext[n] = new;
3546 target->ext[n]->def = dev->ext[m]->def;
3547 target->ext[n]->arg_value = lydict_insert(ctx, dev->ext[m]->arg_value, 0);
3548 target->ext[n]->flags = 0;
3549 target->ext[n]->parent = target;
3550 target->ext[n]->parent_type = LYEXT_PAR_NODE;
3551 target->ext[n]->insubstmt = substmt;
3552 target->ext[n]->insubstmt_index = dev->ext[m]->insubstmt_index;
3553 target->ext[n]->ext_size = dev->ext[m]->ext_size;
3554 lys_ext_dup(ctx, target->module, dev->ext[m]->ext, dev->ext[m]->ext_size, target, LYEXT_PAR_NODE,
3555 &target->ext[n]->ext, 1, NULL);
3556 target->ext[n]->nodetype = LYS_EXT;
3557 target->ext[n]->module = target->module;
3558 target->ext[n]->priv = NULL;
3559
3560 /* TODO cover complex extension instances */
3561 }
3562
3563 /* remove the rest of extensions belonging to the original substatement in the target node,
3564 * due to possible reverting of the deviation effect, they are actually not removed, just moved
3565 * to the backup of the original node when the original node is backuped, here we just have to
3566 * free the replaced / deleted originals */
3567 while ((n = lys_ext_iter(target->ext, target->ext_size, n + 1, substmt)) != -1) {
3568 if (substmt == LYEXT_SUBSTMT_SELF) {
3569 /* if we are applying extension deviation, we are going to remove only
3570 * - the same type of the extension in case of replacing
3571 * - the same type of the extension which was inherited in case of adding
3572 * note - delete deviation is covered in lyp_deviate_del_ext */
3573 if (target->ext[n]->def != extdef ||
3574 (dev->mod == LY_DEVIATE_ADD && !(target->ext[n]->flags & LYEXT_OPT_INHERIT))) {
3575 /* keep this extension */
3576 continue;
3577 }
3578
3579 }
3580
3581 /* remove the item */
3582 lyp_ext_instance_rm(ctx, &target->ext, &target->ext_size, n);
3583 --n;
3584 }
3585
3586 return EXIT_SUCCESS;
3587 }
3588
3589 /*
3590 * not-supported deviations are not processed since they affect the complete node, not just their substatements
3591 */
3592 int
lyp_deviation_apply_ext(struct lys_module * module)3593 lyp_deviation_apply_ext(struct lys_module *module)
3594 {
3595 int i, j, k;
3596 struct lys_deviate *dev;
3597 struct lys_node *target;
3598 struct ly_set *extset;
3599
3600 for (i = 0; i < module->deviation_size; i++) {
3601 target = NULL;
3602 extset = NULL;
3603 j = resolve_schema_nodeid(module->deviation[i].target_name, NULL, module, &extset, 0, 0);
3604 if (j == -1) {
3605 return EXIT_FAILURE;
3606 } else if (!extset) {
3607 /* LY_DEVIATE_NO */
3608 ly_set_free(extset);
3609 continue;
3610 }
3611 target = extset->set.s[0];
3612 ly_set_free(extset);
3613
3614 for (j = 0; j < module->deviation[i].deviate_size; j++) {
3615 dev = &module->deviation[i].deviate[j];
3616 if (!dev->ext_size) {
3617 /* no extensions in deviate and its substatement, nothing to do here */
3618 continue;
3619 }
3620
3621 /* extensions */
3622 if (dev->mod == LY_DEVIATE_DEL) {
3623 k = -1;
3624 while ((k = lys_ext_iter(dev->ext, dev->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3625 if (lyp_deviate_del_ext(target, dev->ext[k])) {
3626 return EXIT_FAILURE;
3627 }
3628 }
3629
3630 /* In case of LY_DEVIATE_DEL, we are applying only extension deviation, removing
3631 * of the substatement's extensions was already done when the substatement was applied.
3632 * Extension deviation could not be applied by the parser since the extension could be unresolved,
3633 * which is not the issue of the other substatements. */
3634 continue;
3635 } else {
3636 extset = ly_set_new();
3637 k = -1;
3638 while ((k = lys_ext_iter(dev->ext, dev->ext_size, k + 1, LYEXT_SUBSTMT_SELF)) != -1) {
3639 ly_set_add(extset, dev->ext[k]->def, 0);
3640 }
3641 for (k = 0; (unsigned int)k < extset->number; k++) {
3642 if (lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_SELF, (struct lys_ext *)extset->set.g[k])) {
3643 ly_set_free(extset);
3644 return EXIT_FAILURE;
3645 }
3646 }
3647 ly_set_free(extset);
3648 }
3649
3650 /* unique */
3651 if (dev->unique_size && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_UNIQUE, NULL)) {
3652 return EXIT_FAILURE;
3653 }
3654 /* units */
3655 if (dev->units && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_UNITS, NULL)) {
3656 return EXIT_FAILURE;
3657 }
3658 /* default */
3659 if (dev->dflt_size && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_DEFAULT, NULL)) {
3660 return EXIT_FAILURE;
3661 }
3662 /* config */
3663 if ((dev->flags & LYS_CONFIG_MASK) && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_CONFIG, NULL)) {
3664 return EXIT_FAILURE;
3665 }
3666 /* mandatory */
3667 if ((dev->flags & LYS_MAND_MASK) && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MANDATORY, NULL)) {
3668 return EXIT_FAILURE;
3669 }
3670 /* min/max */
3671 if (dev->min_set && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MIN, NULL)) {
3672 return EXIT_FAILURE;
3673 }
3674 if (dev->min_set && lyp_deviate_apply_ext(dev, target, LYEXT_SUBSTMT_MAX, NULL)) {
3675 return EXIT_FAILURE;
3676 }
3677 /* type and must contain extension instances in their structures */
3678 }
3679 }
3680
3681 return EXIT_SUCCESS;
3682 }
3683
3684 int
lyp_ctx_check_module(struct lys_module * module)3685 lyp_ctx_check_module(struct lys_module *module)
3686 {
3687 struct ly_ctx *ctx;
3688 int i, match_i = -1, to_implement;
3689 const char *last_rev = NULL;
3690
3691 assert(module);
3692 to_implement = 0;
3693 ctx = module->ctx;
3694
3695 /* find latest revision */
3696 for (i = 0; i < module->rev_size; ++i) {
3697 if (!last_rev || (strcmp(last_rev, module->rev[i].date) < 0)) {
3698 last_rev = module->rev[i].date;
3699 }
3700 }
3701
3702 for (i = 0; i < ctx->models.used; i++) {
3703 /* check name (name/revision) and namespace uniqueness */
3704 if (!strcmp(ctx->models.list[i]->name, module->name)) {
3705 if (to_implement) {
3706 if (i == match_i) {
3707 continue;
3708 }
3709 LOGERR(ctx, LY_EINVAL, "Module \"%s@%s\" in another revision \"%s\" already implemented.",
3710 module->name, last_rev ? last_rev : "<latest>", ctx->models.list[i]->rev[0].date);
3711 return -1;
3712 } else if (!ctx->models.list[i]->rev_size && module->rev_size) {
3713 LOGERR(ctx, LY_EINVAL, "Module \"%s\" without revision already in context.", module->name);
3714 return -1;
3715 } else if (ctx->models.list[i]->rev_size && !module->rev_size) {
3716 LOGERR(ctx, LY_EINVAL, "Module \"%s\" with revision \"%s\" already in context.",
3717 module->name, ctx->models.list[i]->rev[0].date);
3718 return -1;
3719 } else if ((!module->rev_size && !ctx->models.list[i]->rev_size)
3720 || !strcmp(ctx->models.list[i]->rev[0].date, last_rev)) {
3721
3722 LOGVRB("Module \"%s@%s\" already in context.", module->name, last_rev ? last_rev : "<latest>");
3723
3724 /* if disabled, enable first */
3725 if (ctx->models.list[i]->disabled) {
3726 lys_set_enabled(ctx->models.list[i]);
3727 }
3728
3729 to_implement = module->implemented;
3730 match_i = i;
3731 if (to_implement && !ctx->models.list[i]->implemented) {
3732 /* check first that it is okay to change it to implemented */
3733 i = -1;
3734 continue;
3735 }
3736 return 1;
3737
3738 } else if (module->implemented && ctx->models.list[i]->implemented) {
3739 LOGERR(ctx, LY_EINVAL, "Module \"%s@%s\" in another revision \"%s\" already implemented.",
3740 module->name, last_rev ? last_rev : "<latest>", ctx->models.list[i]->rev[0].date);
3741 return -1;
3742 }
3743 /* else keep searching, for now the caller is just adding
3744 * another revision of an already present schema
3745 */
3746 } else if (!strcmp(ctx->models.list[i]->ns, module->ns)) {
3747 LOGERR(ctx, LY_EINVAL, "Two different modules (\"%s\" and \"%s\") have the same namespace \"%s\".",
3748 ctx->models.list[i]->name, module->name, module->ns);
3749 return -1;
3750 }
3751 }
3752
3753 if (to_implement) {
3754 if (lys_set_implemented(ctx->models.list[match_i])) {
3755 return -1;
3756 }
3757 return 1;
3758 }
3759
3760 return 0;
3761 }
3762
3763 int
lyp_ctx_add_module(struct lys_module * module)3764 lyp_ctx_add_module(struct lys_module *module)
3765 {
3766 struct lys_module **newlist = NULL;
3767 int i;
3768
3769 assert(!lyp_ctx_check_module(module));
3770
3771 #ifndef NDEBUG
3772 int j;
3773 /* check that all augments are resolved */
3774 for (i = 0; i < module->augment_size; ++i) {
3775 assert(module->augment[i].target);
3776 }
3777 for (i = 0; i < module->inc_size; ++i) {
3778 for (j = 0; j < module->inc[i].submodule->augment_size; ++j) {
3779 assert(module->inc[i].submodule->augment[j].target);
3780 }
3781 }
3782 #endif
3783
3784 /* add to the context's list of modules */
3785 if (module->ctx->models.used == module->ctx->models.size) {
3786 newlist = realloc(module->ctx->models.list, (2 * module->ctx->models.size) * sizeof *newlist);
3787 LY_CHECK_ERR_RETURN(!newlist, LOGMEM(module->ctx), -1);
3788 for (i = module->ctx->models.size; i < module->ctx->models.size * 2; i++) {
3789 newlist[i] = NULL;
3790 }
3791 module->ctx->models.size *= 2;
3792 module->ctx->models.list = newlist;
3793 }
3794 module->ctx->models.list[module->ctx->models.used++] = module;
3795 module->ctx->models.module_set_id++;
3796
3797 return 0;
3798 }
3799
3800 /**
3801 * Store UTF-8 character specified as 4byte integer into the dst buffer.
3802 * Returns number of written bytes (4 max), expects that dst has enough space.
3803 *
3804 * UTF-8 mapping:
3805 * 00000000 -- 0000007F: 0xxxxxxx
3806 * 00000080 -- 000007FF: 110xxxxx 10xxxxxx
3807 * 00000800 -- 0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
3808 * 00010000 -- 001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
3809 *
3810 * Includes checking for valid characters (following RFC 7950, sec 9.4)
3811 */
3812 unsigned int
pututf8(struct ly_ctx * ctx,char * dst,int32_t value)3813 pututf8(struct ly_ctx *ctx, char *dst, int32_t value)
3814 {
3815 if (value < 0x80) {
3816 /* one byte character */
3817 if (value < 0x20 &&
3818 value != 0x09 &&
3819 value != 0x0a &&
3820 value != 0x0d) {
3821 goto error;
3822 }
3823
3824 dst[0] = value;
3825 return 1;
3826 } else if (value < 0x800) {
3827 /* two bytes character */
3828 dst[0] = 0xc0 | (value >> 6);
3829 dst[1] = 0x80 | (value & 0x3f);
3830 return 2;
3831 } else if (value < 0xfffe) {
3832 /* three bytes character */
3833 if (((value & 0xf800) == 0xd800) ||
3834 (value >= 0xfdd0 && value <= 0xfdef)) {
3835 /* exclude surrogate blocks %xD800-DFFF */
3836 /* exclude noncharacters %xFDD0-FDEF */
3837 goto error;
3838 }
3839
3840 dst[0] = 0xe0 | (value >> 12);
3841 dst[1] = 0x80 | ((value >> 6) & 0x3f);
3842 dst[2] = 0x80 | (value & 0x3f);
3843
3844 return 3;
3845 } else if (value < 0x10fffe) {
3846 if ((value & 0xffe) == 0xffe) {
3847 /* exclude noncharacters %xFFFE-FFFF, %x1FFFE-1FFFF, %x2FFFE-2FFFF, %x3FFFE-3FFFF, %x4FFFE-4FFFF,
3848 * %x5FFFE-5FFFF, %x6FFFE-6FFFF, %x7FFFE-7FFFF, %x8FFFE-8FFFF, %x9FFFE-9FFFF, %xAFFFE-AFFFF,
3849 * %xBFFFE-BFFFF, %xCFFFE-CFFFF, %xDFFFE-DFFFF, %xEFFFE-EFFFF, %xFFFFE-FFFFF, %x10FFFE-10FFFF */
3850 goto error;
3851 }
3852 /* four bytes character */
3853 dst[0] = 0xf0 | (value >> 18);
3854 dst[1] = 0x80 | ((value >> 12) & 0x3f);
3855 dst[2] = 0x80 | ((value >> 6) & 0x3f);
3856 dst[3] = 0x80 | (value & 0x3f);
3857
3858 return 4;
3859 }
3860
3861 error:
3862 /* out of range */
3863 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, NULL);
3864 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3865 return 0;
3866 }
3867
3868 unsigned int
copyutf8(struct ly_ctx * ctx,char * dst,const char * src)3869 copyutf8(struct ly_ctx *ctx, char *dst, const char *src)
3870 {
3871 uint32_t value;
3872
3873 /* unicode characters */
3874 if (!(src[0] & 0x80)) {
3875 /* one byte character */
3876 if (src[0] < 0x20 &&
3877 src[0] != 0x09 &&
3878 src[0] != 0x0a &&
3879 src[0] != 0x0d) {
3880 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3881 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x", src[0]);
3882 return 0;
3883 }
3884
3885 dst[0] = src[0];
3886 return 1;
3887 } else if ((src[0] & 0xe0) == 0xc0) {
3888 /* two bytes character */
3889 if ((src[1] & 0xc0) != 0x80) {
3890 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3891 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x",
3892 (unsigned char)src[0], (unsigned char)src[1])
3893 return 0;
3894 }
3895
3896 dst[0] = src[0];
3897 dst[1] = src[1];
3898 return 2;
3899 } else if ((src[0] & 0xf0) == 0xe0) {
3900 /* three bytes character */
3901 if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80) {
3902 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3903 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x 0x%02x",
3904 (unsigned char)src[0], (unsigned char)src[1], (src[1] ? (unsigned char)src[2] : 0))
3905 return 0;
3906 }
3907
3908 value = ((uint32_t)(src[0] & 0xf) << 12) | ((uint32_t)(src[1] & 0x3f) << 6) | (src[2] & 0x3f);
3909 if (((value & 0xf800) == 0xd800) ||
3910 (value >= 0xfdd0 && value <= 0xfdef) ||
3911 (value & 0xffe) == 0xffe) {
3912 /* exclude surrogate blocks %xD800-DFFF */
3913 /* exclude noncharacters %xFDD0-FDEF */
3914 /* exclude noncharacters %xFFFE-FFFF */
3915 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3916 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3917 return 0;
3918 }
3919
3920 dst[0] = src[0];
3921 dst[1] = src[1];
3922 dst[2] = src[2];
3923 return 3;
3924 } else if ((src[0] & 0xf8) == 0xf0) {
3925 /* four bytes character */
3926 if ((src[1] & 0xc0) != 0x80 || (src[2] & 0xc0) != 0x80 || (src[3] & 0xc0) != 0x80) {
3927 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3928 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%02x 0x%02x 0x%02x 0x%02x",
3929 (unsigned char)src[0], (unsigned char)src[1],
3930 (src[1] ? (unsigned char)src[2] : 0), ((src[1] && src[2]) ? (unsigned char)src[3] : 0));
3931 return 0;
3932 }
3933
3934 value = ((uint32_t)(src[0] & 0x7) << 18) | ((uint32_t)(src[1] & 0x3f) << 12) | ((uint32_t)(src[2] & 0x3f) << 6) | (src[3] & 0x3f);
3935 if ((value & 0xffe) == 0xffe) {
3936 /* exclude noncharacters %x1FFFE-1FFFF, %x2FFFE-2FFFF, %x3FFFE-3FFFF, %x4FFFE-4FFFF,
3937 * %x5FFFE-5FFFF, %x6FFFE-6FFFF, %x7FFFE-7FFFF, %x8FFFE-8FFFF, %x9FFFE-9FFFF, %xAFFFE-AFFFF,
3938 * %xBFFFE-BFFFF, %xCFFFE-CFFFF, %xDFFFE-DFFFF, %xEFFFE-EFFFF, %xFFFFE-FFFFF, %x10FFFE-10FFFF */
3939 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3940 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 value 0x%08x", value);
3941 return 0;
3942 }
3943 dst[0] = src[0];
3944 dst[1] = src[1];
3945 dst[2] = src[2];
3946 dst[3] = src[3];
3947 return 4;
3948 } else {
3949 LOGVAL(ctx, LYE_XML_INCHAR, LY_VLOG_NONE, NULL, src);
3950 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid UTF-8 leading byte 0x%02x", src[0]);
3951 return 0;
3952 }
3953 }
3954
3955 const struct lys_module *
lyp_get_module(const struct lys_module * module,const char * prefix,int pref_len,const char * name,int name_len,int in_data)3956 lyp_get_module(const struct lys_module *module, const char *prefix, int pref_len, const char *name, int name_len, int in_data)
3957 {
3958 const struct lys_module *main_module;
3959 char *str;
3960 int i;
3961
3962 assert(!prefix || !name);
3963
3964 if (prefix && !pref_len) {
3965 pref_len = strlen(prefix);
3966 }
3967 if (name && !name_len) {
3968 name_len = strlen(name);
3969 }
3970
3971 main_module = lys_main_module(module);
3972
3973 /* module own prefix, submodule own prefix, (sub)module own name */
3974 if ((!prefix || (!module->type && !strncmp(main_module->prefix, prefix, pref_len) && !main_module->prefix[pref_len])
3975 || (module->type && !strncmp(module->prefix, prefix, pref_len) && !module->prefix[pref_len]))
3976 && (!name || (!strncmp(main_module->name, name, name_len) && !main_module->name[name_len]))) {
3977 return main_module;
3978 }
3979
3980 /* standard import */
3981 for (i = 0; i < module->imp_size; ++i) {
3982 if ((!prefix || (!strncmp(module->imp[i].prefix, prefix, pref_len) && !module->imp[i].prefix[pref_len]))
3983 && (!name || (!strncmp(module->imp[i].module->name, name, name_len) && !module->imp[i].module->name[name_len]))) {
3984 return module->imp[i].module;
3985 }
3986 }
3987
3988 /* module required by a foreign grouping, deviation, or submodule */
3989 if (name) {
3990 str = strndup(name, name_len);
3991 if (!str) {
3992 LOGMEM(module->ctx);
3993 return NULL;
3994 }
3995 main_module = ly_ctx_get_module(module->ctx, str, NULL, 0);
3996
3997 /* try data callback */
3998 if (!main_module && in_data && module->ctx->data_clb) {
3999 main_module = module->ctx->data_clb(module->ctx, str, NULL, 0, module->ctx->data_clb_data);
4000 }
4001
4002 free(str);
4003 return main_module;
4004 }
4005
4006 return NULL;
4007 }
4008
4009 const struct lys_module *
lyp_get_import_module_ns(const struct lys_module * module,const char * ns)4010 lyp_get_import_module_ns(const struct lys_module *module, const char *ns)
4011 {
4012 int i;
4013 const struct lys_module *mod = NULL;
4014
4015 assert(module && ns);
4016
4017 if (module->type) {
4018 /* the module is actually submodule and to get the namespace, we need the main module */
4019 if (ly_strequal(((struct lys_submodule *)module)->belongsto->ns, ns, 0)) {
4020 return ((struct lys_submodule *)module)->belongsto;
4021 }
4022 } else {
4023 /* module's own namespace */
4024 if (ly_strequal(module->ns, ns, 0)) {
4025 return module;
4026 }
4027 }
4028
4029 /* imported modules */
4030 for (i = 0; i < module->imp_size; ++i) {
4031 if (ly_strequal(module->imp[i].module->ns, ns, 0)) {
4032 return module->imp[i].module;
4033 }
4034 }
4035
4036 return mod;
4037 }
4038
4039 const char *
lyp_get_yang_data_template_name(const struct lyd_node * node)4040 lyp_get_yang_data_template_name(const struct lyd_node *node)
4041 {
4042 struct lys_node *snode;
4043
4044 snode = lys_parent(node->schema);
4045 while (snode && snode->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE)) {
4046 snode = lys_parent(snode);
4047 }
4048
4049 if (snode && snode->nodetype == LYS_EXT && strcmp(((struct lys_ext_instance_complex *)snode)->def->name, "yang-data") == 0) {
4050 return ((struct lys_ext_instance_complex *)snode)->arg_value;
4051 } else {
4052 return NULL;
4053 }
4054 }
4055
4056 const struct lys_node *
lyp_get_yang_data_template(const struct lys_module * module,const char * yang_data_name,int yang_data_name_len)4057 lyp_get_yang_data_template(const struct lys_module *module, const char *yang_data_name, int yang_data_name_len)
4058 {
4059 int i, j;
4060 const struct lys_node *ret = NULL;
4061 const struct lys_submodule *submodule;
4062
4063 for(i = 0; i < module->ext_size; ++i) {
4064 if (!strcmp(module->ext[i]->def->name, "yang-data") && !strncmp(module->ext[i]->arg_value, yang_data_name, yang_data_name_len)
4065 && !module->ext[i]->arg_value[yang_data_name_len]) {
4066 ret = (struct lys_node *)module->ext[i];
4067 break;
4068 }
4069 }
4070
4071 for(j = 0; !ret && j < module->inc_size; ++j) {
4072 submodule = module->inc[j].submodule;
4073 for(i = 0; i < submodule->ext_size; ++i) {
4074 if (!strcmp(submodule->ext[i]->def->name, "yang-data") && !strncmp(submodule->ext[i]->arg_value, yang_data_name, yang_data_name_len)
4075 && !submodule->ext[i]->arg_value[yang_data_name_len]) {
4076 ret = (struct lys_node *)submodule->ext[i];
4077 break;
4078 }
4079 }
4080 }
4081
4082 return ret;
4083 }
4084
4085 int
lyp_get_ext_list(struct ly_ctx * ctx,void * elem,LYEXT_PAR elem_type,struct lys_ext_instance **** ext_list,uint8_t ** ext_size,const char ** stmt)4086 lyp_get_ext_list(struct ly_ctx *ctx, void *elem, LYEXT_PAR elem_type,
4087 struct lys_ext_instance ****ext_list, uint8_t **ext_size, const char **stmt)
4088 {
4089 const char *statement = NULL;
4090
4091 switch (elem_type) {
4092 case LYEXT_PAR_MODULE:
4093 *ext_size = &((struct lys_module *)elem)->ext_size;
4094 *ext_list = &((struct lys_module *)elem)->ext;
4095 statement = ((struct lys_module *)elem)->type ? "submodule" : "module";
4096 break;
4097 case LYEXT_PAR_IMPORT:
4098 *ext_size = &((struct lys_import *)elem)->ext_size;
4099 *ext_list = &((struct lys_import *)elem)->ext;
4100 statement = "import";
4101 break;
4102 case LYEXT_PAR_INCLUDE:
4103 *ext_size = &((struct lys_include *)elem)->ext_size;
4104 *ext_list = &((struct lys_include *)elem)->ext;
4105 statement = "include";
4106 break;
4107 case LYEXT_PAR_REVISION:
4108 *ext_size = &((struct lys_revision *)elem)->ext_size;
4109 *ext_list = &((struct lys_revision *)elem)->ext;
4110 statement = "revision";
4111 break;
4112 case LYEXT_PAR_NODE:
4113 *ext_size = &((struct lys_node *)elem)->ext_size;
4114 *ext_list = &((struct lys_node *)elem)->ext;
4115 statement = strnodetype(((struct lys_node *)elem)->nodetype);
4116 break;
4117 case LYEXT_PAR_IDENT:
4118 *ext_size = &((struct lys_ident *)elem)->ext_size;
4119 *ext_list = &((struct lys_ident *)elem)->ext;
4120 statement = "identity";
4121 break;
4122 case LYEXT_PAR_TYPE:
4123 *ext_size = &((struct lys_type *)elem)->ext_size;
4124 *ext_list = &((struct lys_type *)elem)->ext;
4125 statement = "type";
4126 break;
4127 case LYEXT_PAR_TYPE_BIT:
4128 *ext_size = &((struct lys_type_bit *)elem)->ext_size;
4129 *ext_list = &((struct lys_type_bit *)elem)->ext;
4130 statement = "bit";
4131 break;
4132 case LYEXT_PAR_TYPE_ENUM:
4133 *ext_size = &((struct lys_type_enum *)elem)->ext_size;
4134 *ext_list = &((struct lys_type_enum *)elem)->ext;
4135 statement = "enum";
4136 break;
4137 case LYEXT_PAR_TPDF:
4138 *ext_size = &((struct lys_tpdf *)elem)->ext_size;
4139 *ext_list = &((struct lys_tpdf *)elem)->ext;
4140 statement = "typedef";
4141 break;
4142 case LYEXT_PAR_EXT:
4143 *ext_size = &((struct lys_ext *)elem)->ext_size;
4144 *ext_list = &((struct lys_ext *)elem)->ext;
4145 statement = "extension";
4146 break;
4147 case LYEXT_PAR_EXTINST:
4148 *ext_size = &((struct lys_ext_instance *)elem)->ext_size;
4149 *ext_list = &((struct lys_ext_instance *)elem)->ext;
4150 statement = "extension instance";
4151 break;
4152 case LYEXT_PAR_FEATURE:
4153 *ext_size = &((struct lys_feature *)elem)->ext_size;
4154 *ext_list = &((struct lys_feature *)elem)->ext;
4155 statement = "feature";
4156 break;
4157 case LYEXT_PAR_REFINE:
4158 *ext_size = &((struct lys_refine *)elem)->ext_size;
4159 *ext_list = &((struct lys_refine *)elem)->ext;
4160 statement = "refine";
4161 break;
4162 case LYEXT_PAR_RESTR:
4163 *ext_size = &((struct lys_restr *)elem)->ext_size;
4164 *ext_list = &((struct lys_restr *)elem)->ext;
4165 statement = "YANG restriction";
4166 break;
4167 case LYEXT_PAR_WHEN:
4168 *ext_size = &((struct lys_when *)elem)->ext_size;
4169 *ext_list = &((struct lys_when *)elem)->ext;
4170 statement = "when";
4171 break;
4172 case LYEXT_PAR_DEVIATE:
4173 *ext_size = &((struct lys_deviate *)elem)->ext_size;
4174 *ext_list = &((struct lys_deviate *)elem)->ext;
4175 statement = "deviate";
4176 break;
4177 case LYEXT_PAR_DEVIATION:
4178 *ext_size = &((struct lys_deviation *)elem)->ext_size;
4179 *ext_list = &((struct lys_deviation *)elem)->ext;
4180 statement = "deviation";
4181 break;
4182 default:
4183 LOGERR(ctx, LY_EINT, "parent type %d", elem_type);
4184 return -1;
4185 }
4186
4187 if (stmt) {
4188 *stmt = statement;
4189 }
4190
4191 return 0;
4192 }
4193
4194 inline void
lyp_reduce_ext_list(struct lys_ext_instance *** ext,uint8_t new_size,uint8_t orig_size)4195 lyp_reduce_ext_list(struct lys_ext_instance ***ext, uint8_t new_size, uint8_t orig_size)
4196 {
4197 struct lys_ext_instance **tmp;
4198
4199 if (new_size != orig_size) {
4200 if (new_size == 0) {
4201 free(*ext);
4202 *ext = NULL;
4203 } else {
4204 tmp = realloc(*ext, new_size * sizeof(*tmp));
4205 if (!tmp) {
4206 /* we just reduce the size, so this failure is harmless. */
4207 return;
4208 }
4209 *ext = tmp;
4210 }
4211 }
4212 }
4213
4214