blob: f25578b351542d2c88a28d007bdcd7e45c130afe [file] [log] [blame]
Michal Vasko60ea6352020-06-29 13:39:39 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2020 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#include "lyb.h"
16
17#include <assert.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020018#include <stdint.h>
Michal Vasko60ea6352020-06-29 13:39:39 +020019#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include "common.h"
24#include "compat.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020025#include "context.h"
26#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010027#include "hash_table.h"
28#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020029#include "in_internal.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020030#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020031#include "parser_data.h"
32#include "parser_internal.h"
Radek Krejci77114102021-03-10 15:21:57 +010033#include "set.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020034#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010035#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020036#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010037#include "tree_edit.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020038#include "tree_schema.h"
39#include "validation.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010040#include "xml.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020041
Michal Vasko02ed9d82021-07-15 14:58:04 +020042static LY_ERR _lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
43 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
44 struct ly_set *parsed, struct lyd_ctx **lydctx_p);
45
Radek Krejci1798aae2020-07-14 13:26:06 +020046void
47lylyb_ctx_free(struct lylyb_ctx *ctx)
48{
49 LY_ARRAY_COUNT_TYPE u;
50
51 LY_ARRAY_FREE(ctx->subtrees);
52 LY_ARRAY_FREE(ctx->models);
53
54 LY_ARRAY_FOR(ctx->sib_hts, u) {
55 lyht_free(ctx->sib_hts[u].ht);
56 }
57 LY_ARRAY_FREE(ctx->sib_hts);
58
59 free(ctx);
60}
61
62void
63lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
64{
65 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
66
67 lyd_ctx_free(lydctx);
68 lylyb_ctx_free(ctx->lybctx);
69 free(ctx);
70}
71
Michal Vasko60ea6352020-06-29 13:39:39 +020072/**
73 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
74 *
75 * @param[in] buf Destination buffer.
76 * @param[in] count Number of bytes to read.
77 * @param[in] lybctx LYB context.
78 */
79static void
Radek Krejci1798aae2020-07-14 13:26:06 +020080lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +020081{
Michal Vaskofd69e1d2020-07-03 11:57:17 +020082 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +020083 struct lyd_lyb_subtree *empty;
84 size_t to_read;
85 uint8_t meta_buf[LYB_META_BYTES];
86
87 assert(lybctx);
88
89 while (1) {
90 /* check for fully-read (empty) data chunks */
91 to_read = count;
92 empty = NULL;
93 LY_ARRAY_FOR(lybctx->subtrees, u) {
94 /* we want the innermost chunks resolved first, so replace previous empty chunks,
95 * also ignore chunks that are completely finished, there is nothing for us to do */
96 if ((lybctx->subtrees[u].written <= to_read) && lybctx->subtrees[u].position) {
97 /* empty chunk, do not read more */
98 to_read = lybctx->subtrees[u].written;
99 empty = &lybctx->subtrees[u];
100 }
101 }
102
103 if (!empty && !count) {
104 break;
105 }
106
107 /* we are actually reading some data, not just finishing another chunk */
108 if (to_read) {
109 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200110 ly_in_read(lybctx->in, buf, to_read);
111 } else {
112 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200113 }
114
115 LY_ARRAY_FOR(lybctx->subtrees, u) {
116 /* decrease all written counters */
117 lybctx->subtrees[u].written -= to_read;
118 assert(lybctx->subtrees[u].written <= LYB_SIZE_MAX);
119 }
120 /* decrease count/buf */
121 count -= to_read;
122 if (buf) {
123 buf += to_read;
124 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200125 }
126
127 if (empty) {
128 /* read the next chunk meta information */
Michal Vasko63f3d842020-07-08 10:10:14 +0200129 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200130 empty->written = meta_buf[0];
131 empty->inner_chunks = meta_buf[1];
132
133 /* remember whether there is a following chunk or not */
134 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200135 }
136 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200137}
138
139/**
140 * @brief Read a number.
141 *
142 * @param[in] num Destination buffer.
143 * @param[in] num_size Size of @p num.
144 * @param[in] bytes Number of bytes to read.
145 * @param[in] lybctx LYB context.
146 */
147static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200148lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200149{
150 uint64_t buf = 0;
151
152 lyb_read((uint8_t *)&buf, bytes, lybctx);
153
154 /* correct byte order */
155 buf = le64toh(buf);
156
157 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100158 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200159 *((uint8_t *)num) = buf;
160 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100161 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200162 *((uint16_t *)num) = buf;
163 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100164 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200165 *((uint32_t *)num) = buf;
166 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100167 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200168 *((uint64_t *)num) = buf;
169 break;
170 default:
171 LOGINT(lybctx->ctx);
172 }
173}
174
175/**
176 * @brief Read a string.
177 *
178 * @param[in] str Destination buffer, is allocated.
179 * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this subtree.
180 * @param[in] lybctx LYB context.
181 * @return LY_ERR value.
182 */
183static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +0200184lyb_read_string(char **str, ly_bool with_length, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200185{
Radek Krejci857189e2020-09-01 13:26:36 +0200186 ly_bool next_chunk = 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200187 size_t len = 0, cur_len;
188
189 *str = NULL;
190
191 if (with_length) {
192 lyb_read_number(&len, sizeof len, 2, lybctx);
193 } else {
194 /* read until the end of this subtree */
195 len = LYB_LAST_SUBTREE(lybctx).written;
196 if (LYB_LAST_SUBTREE(lybctx).position) {
197 next_chunk = 1;
198 }
199 }
200
201 *str = malloc((len + 1) * sizeof **str);
202 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
203
204 lyb_read((uint8_t *)*str, len, lybctx);
205
206 while (next_chunk) {
207 cur_len = LYB_LAST_SUBTREE(lybctx).written;
208 if (LYB_LAST_SUBTREE(lybctx).position) {
209 next_chunk = 1;
210 } else {
211 next_chunk = 0;
212 }
213
214 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
215 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
216
217 lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
218
219 len += cur_len;
220 }
221
Michal Vaskocebbae52021-05-31 11:11:36 +0200222 (*str)[len] = '\0';
Michal Vasko60ea6352020-06-29 13:39:39 +0200223 return LY_SUCCESS;
224}
225
226/**
aPiecekea304e32021-08-18 09:13:47 +0200227 * @brief Read the term node.
228 *
229 * @param[out] term_value Set to term node value in dynamically
230 * allocated memory. The caller must release it.
231 * @param[out] term_value_len Value length in bytes. The zero byte is
232 * always included and is not counted.
233 * @param[in,out] lybctx LYB context.
234 * @return LY_ERR value.
235 */
236static LY_ERR
237lyb_read_term(uint8_t **term_value, uint32_t *term_value_len, struct lylyb_ctx *lybctx)
238{
239 uint32_t allocated_size;
240
241 assert(term_value && term_value_len && lybctx);
242
243 /* Parse value size. */
244 lyb_read_number(term_value_len, sizeof *term_value_len, sizeof *term_value_len, lybctx);
245
246 /* Allocate memory. */
247 allocated_size = *term_value_len + 1;
248 *term_value = malloc(allocated_size * sizeof **term_value);
249 LY_CHECK_ERR_RET(!*term_value, LOGMEM(lybctx->ctx), LY_EMEM);
250
251 if (*term_value_len > 0) {
252 /* Parse value. */
253 lyb_read(*term_value, *term_value_len, lybctx);
254 }
255
256 /* Add extra zero byte regardless of whether it is string or not. */
257 (*term_value)[allocated_size - 1] = 0;
258
259 return LY_SUCCESS;
260}
261
262/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200263 * @brief Stop the current subtree - change LYB context state.
264 *
265 * @param[in] lybctx LYB context.
266 * @return LY_ERR value.
267 */
268static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200269lyb_read_stop_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200270{
271 if (LYB_LAST_SUBTREE(lybctx).written) {
272 LOGINT_RET(lybctx->ctx);
273 }
274
275 LY_ARRAY_DECREMENT(lybctx->subtrees);
276 return LY_SUCCESS;
277}
278
279/**
280 * @brief Start a new subtree - change LYB context state but also read the expected metadata.
281 *
282 * @param[in] lybctx LYB context.
283 * @return LY_ERR value.
284 */
285static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200286lyb_read_start_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200287{
288 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200289 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200290
Radek Krejcic7d13e32020-12-09 12:32:24 +0100291 u = LY_ARRAY_COUNT(lybctx->subtrees);
Michal Vasko60ea6352020-06-29 13:39:39 +0200292 if (u == lybctx->subtree_size) {
293 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
294 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
295 }
296
Michal Vasko63f3d842020-07-08 10:10:14 +0200297 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200298
299 LY_ARRAY_INCREMENT(lybctx->subtrees);
300 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
301 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
302 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
303
Michal Vasko60ea6352020-06-29 13:39:39 +0200304 return LY_SUCCESS;
305}
306
307/**
308 * @brief Parse YANG model info.
309 *
310 * @param[in] lybctx LYB context.
311 * @param[out] mod Parsed module.
312 * @return LY_ERR value.
313 */
314static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200315lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
Michal Vasko60ea6352020-06-29 13:39:39 +0200316{
317 LY_ERR ret = LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100318 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
Michal Vasko60ea6352020-06-29 13:39:39 +0200319 uint16_t rev;
320
321 /* model name */
322 ret = lyb_read_string(&mod_name, 1, lybctx);
323 LY_CHECK_GOTO(ret, cleanup);
324
325 /* revision */
326 lyb_read_number(&rev, sizeof rev, 2, lybctx);
327
328 if (!mod_name[0]) {
329 /* opaq node, no module */
330 *mod = NULL;
331 goto cleanup;
332 }
333
334 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100335 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
336 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko60ea6352020-06-29 13:39:39 +0200337 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
Radek Krejci1798aae2020-07-14 13:26:06 +0200338 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200339 /* try to use an updated module */
340 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
341 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
342 /* not an implemented module in a newer revision */
343 *mod = NULL;
344 }
345 }
346 } else {
347 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
348 }
349 /* TODO data_clb supported?
350 if (lybctx->ctx->data_clb) {
351 if (!*mod) {
352 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
353 } else if (!(*mod)->implemented) {
354 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
355 }
356 }*/
357
358 if (!*mod || !(*mod)->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200359 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200360 if (!*mod) {
361 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +0200362 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200363 } else if (!(*mod)->implemented) {
364 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko69730152020-10-09 16:30:07 +0200365 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200366 }
367 ret = LY_EINVAL;
368 goto cleanup;
369 }
370
371 }
372
Michal Vasko85d9edc2021-04-22 09:15:05 +0200373 if (*mod) {
374 /* fill cached hashes, if not already */
375 lyb_cache_module_hash(*mod);
376 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200377
Michal Vasko60ea6352020-06-29 13:39:39 +0200378cleanup:
379 free(mod_name);
380 return ret;
381}
382
383/**
384 * @brief Parse YANG node metadata.
385 *
386 * @param[in] lybctx LYB context.
Michal Vasko60ea6352020-06-29 13:39:39 +0200387 * @param[out] meta Parsed metadata.
388 * @return LY_ERR value.
389 */
390static LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200391lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200392{
393 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200394 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200395 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200396 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200397 const struct lys_module *mod;
398
399 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200400 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200401
402 /* read attributes */
403 for (i = 0; i < count; ++i) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200404 ret = lyb_read_start_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200405 LY_CHECK_GOTO(ret, cleanup);
406
407 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100408 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200409 LY_CHECK_GOTO(ret, cleanup);
410
411 if (!mod) {
412 /* skip it */
413 do {
Radek Krejci1798aae2020-07-14 13:26:06 +0200414 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx->lybctx).written, lybctx->lybctx);
415 } while (LYB_LAST_SUBTREE(lybctx->lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200416 goto stop_subtree;
417 }
418
419 /* meta name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200420 ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200421 LY_CHECK_GOTO(ret, cleanup);
422
423 /* meta value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200424 ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200425 LY_CHECK_GOTO(ret, cleanup);
426 dynamic = 1;
427
428 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200429 ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
Radek Krejci8df109d2021-04-23 12:19:08 +0200430 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200431
432 /* free strings */
433 free(meta_name);
434 meta_name = NULL;
435 if (dynamic) {
436 free(meta_value);
437 dynamic = 0;
438 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200439
Radek Krejci1798aae2020-07-14 13:26:06 +0200440 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200441
442stop_subtree:
Radek Krejci1798aae2020-07-14 13:26:06 +0200443 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200444 LY_CHECK_GOTO(ret, cleanup);
445 }
446
447cleanup:
448 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200449 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200450 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200451 *meta = NULL;
452 }
453 return ret;
454}
455
456/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100457 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200458 *
459 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100460 * @param[in] format Prefix data format.
461 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200462 * @return LY_ERR value.
463 */
464static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200465lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200466{
467 LY_ERR ret = LY_SUCCESS;
468 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100469 struct ly_set *set = NULL;
470 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200471
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100472 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200473 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100474 /* read count */
475 lyb_read(&count, 1, lybctx);
476 if (!count) {
477 return LY_SUCCESS;
478 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200479
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100480 /* read all NS elements */
481 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200482
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100483 for (i = 0; i < count; ++i) {
484 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200485
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100486 /* prefix */
487 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
488
489 /* namespace */
490 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
491
492 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
493 ns = NULL;
494 }
495
496 *prefix_data = set;
497 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200498 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200499 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100500 /* nothing stored */
501 break;
502 default:
503 LOGINT(lybctx->ctx);
504 ret = LY_EINT;
505 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200506 }
507
508cleanup:
509 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100510 ly_free_prefix_data(format, set);
511 if (ns) {
512 free(ns->prefix);
513 free(ns->uri);
514 free(ns);
515 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200516 }
517 return ret;
518}
519
520/**
521 * @brief Parse opaque attributes.
522 *
523 * @param[in] lybctx LYB context.
524 * @param[out] attr Parsed attributes.
525 * @return LY_ERR value.
526 */
527static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200528lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200529{
530 LY_ERR ret = LY_SUCCESS;
531 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200532 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200533 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200534 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200535 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100536 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200537
538 /* read count */
539 lyb_read(&count, 1, lybctx);
540
541 /* read attributes */
542 for (i = 0; i < count; ++i) {
543 ret = lyb_read_start_subtree(lybctx);
544 LY_CHECK_GOTO(ret, cleanup);
545
Michal Vasko0fdcd242020-11-11 19:12:30 +0100546 /* prefix, may be empty */
Michal Vasko60ea6352020-06-29 13:39:39 +0200547 ret = lyb_read_string(&prefix, 1, lybctx);
548 LY_CHECK_GOTO(ret, cleanup);
549 if (!prefix[0]) {
550 free(prefix);
551 prefix = NULL;
552 }
553
554 /* namespace, may be empty */
Radek Krejci1798aae2020-07-14 13:26:06 +0200555 ret = lyb_read_string(&module_name, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200556 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200557 if (!module_name[0]) {
558 free(module_name);
559 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200560 }
561
562 /* name */
563 ret = lyb_read_string(&name, 1, lybctx);
564 LY_CHECK_GOTO(ret, cleanup);
565
Michal Vasko60ea6352020-06-29 13:39:39 +0200566 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200567 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200568
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100569 /* value prefixes */
570 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
571 LY_CHECK_GOTO(ret, cleanup);
572
Michal Vasko60ea6352020-06-29 13:39:39 +0200573 /* value */
574 ret = lyb_read_string(&value, 0, lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100575 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200576 dynamic = 1;
577
578 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100579 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200580 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200581 LY_CHECK_GOTO(ret, cleanup);
582
583 free(prefix);
584 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200585 free(module_name);
586 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200587 free(name);
588 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200589 assert(!dynamic);
590 value = NULL;
591
592 if (!*attr) {
593 *attr = attr2;
594 }
595
596 ret = lyb_read_stop_subtree(lybctx);
597 LY_CHECK_GOTO(ret, cleanup);
598 }
599
600cleanup:
601 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200602 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200603 free(name);
604 if (dynamic) {
605 free(value);
606 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200607 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200608 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200609 *attr = NULL;
610 }
611 return ret;
612}
613
614/**
615 * @brief Check whether a schema node matches a hash(es).
616 *
617 * @param[in] sibling Schema node to check.
618 * @param[in] hash Hash array to check.
619 * @param[in] hash_count Number of hashes in @p hash.
620 * @return non-zero if matches,
621 * @return 0 if not.
622 */
623static int
624lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
625{
626 LYB_HASH sibling_hash;
627 uint8_t i;
628
629 /* compare all the hashes starting from collision ID 0 */
630 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200631 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200632 if (sibling_hash != hash[i]) {
633 return 0;
634 }
635 }
636
637 return 1;
638}
639
640/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200641 * @brief Parse schema node hash.
642 *
643 * @param[in] lybctx LYB context.
644 * @param[in] sparent Schema parent, must be set if @p mod is not.
645 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
646 * @param[out] snode Parsed found schema node, may be NULL if opaque.
647 * @return LY_ERR value.
648 */
649static LY_ERR
650lyb_parse_schema_hash(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, const struct lys_module *mod,
Radek Krejci0f969882020-08-21 16:56:47 +0200651 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200652{
653 LY_ERR ret;
654 uint8_t i, j;
655 const struct lysc_node *sibling;
656 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200657 uint32_t getnext_opts;
Michal Vasko60ea6352020-06-29 13:39:39 +0200658
659 *snode = NULL;
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100660 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200661
662 /* read the first hash */
Radek Krejci1798aae2020-07-14 13:26:06 +0200663 lyb_read(&hash[0], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200664
665 if (!hash[0]) {
666 /* opaque node */
667 return LY_SUCCESS;
668 }
669
670 /* based on the first hash read all the other ones, if any */
671 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
672 if (i > LYB_HASH_BITS) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200673 LOGINT_RET(lybctx->lybctx->ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200674 }
675 }
676
677 /* move the first hash on its accurate position */
678 hash[i] = hash[0];
679
680 /* read the rest of hashes */
681 for (j = i; j; --j) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200682 lyb_read(&hash[j - 1], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200683
684 /* correct collision ID */
685 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
686 /* preceded with zeros */
687 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
688 }
689
690 /* find our node with matching hashes */
691 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100692 while (1) {
693 if (!sparent && lybctx->ext) {
694 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
695 } else {
696 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
697 }
698 if (!sibling) {
699 break;
700 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200701 /* skip schema nodes from models not present during printing */
Michal Vasko69730152020-10-09 16:30:07 +0200702 if (lyb_has_schema_model(sibling, lybctx->lybctx->models) &&
703 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200704 /* match found */
705 break;
706 }
707 }
708
Michal Vaskoe0665742021-02-11 11:08:44 +0100709 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100710 if (lybctx->ext) {
711 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
712 lybctx->ext->def->name);
713 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100714 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200715 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200716 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100717 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200718 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200719 }
720 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200721 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200722 return ret;
723 }
724
725 *snode = sibling;
726 return LY_SUCCESS;
727}
728
729/**
730 * @brief Read until the end of the current subtree.
731 *
732 * @param[in] lybctx LYB context.
733 */
734static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200735lyb_skip_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200736{
Michal Vasko60ea6352020-06-29 13:39:39 +0200737 do {
738 /* first skip any meta information inside */
Michal Vasko63f3d842020-07-08 10:10:14 +0200739 ly_in_skip(lybctx->in, LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200740
741 /* then read data */
742 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
743 } while (LYB_LAST_SUBTREE(lybctx).written);
744}
745
746/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200747 * @brief Parse the context of anydata/anyxml node.
748 *
749 * @param[in] ctx libyang context.
750 * @param[in] data LYB data to parse.
751 * @param[out] tree Parsed tree.
752 * @return LY_ERR value.
753 */
754static LY_ERR
755lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
756{
757 LY_ERR ret;
758 uint32_t prev_lo;
759 struct ly_in *in;
760 struct lyd_ctx *lydctx = NULL;
761
762 *tree = NULL;
763
764 LY_CHECK_RET(ly_in_new_memory(data, &in));
765
766 /* turn logging off */
767 prev_lo = ly_log_options(0);
768
Michal Vasko56d88602021-07-15 16:37:59 +0200769 ret = _lyd_parse_lyb(ctx, NULL, NULL, tree, in, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
Michal Vasko02ed9d82021-07-15 14:58:04 +0200770 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
771
772 /* turn logging on again */
773 ly_log_options(prev_lo);
774
775 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200776 if (lydctx) {
777 lydctx->free(lydctx);
778 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200779 if (ret) {
780 lyd_free_siblings(*tree);
781 *tree = NULL;
782 }
783 return ret;
784}
785
786/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200787 * @brief Parse LYB subtree.
788 *
789 * @param[in] lybctx LYB context.
790 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
791 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
792 * @return LY_ERR value.
793 */
794static LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100795lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
Michal Vasko60ea6352020-06-29 13:39:39 +0200796{
797 LY_ERR ret = LY_SUCCESS;
798 struct lyd_node *node = NULL, *tree;
799 const struct lys_module *mod;
800 const struct lysc_node *snode = NULL;
801 struct lyd_meta *meta = NULL, *m;
Radek Krejci1798aae2020-07-14 13:26:06 +0200802 struct lyd_attr *attr = NULL, *a;
Michal Vasko60ea6352020-06-29 13:39:39 +0200803 LYD_ANYDATA_VALUETYPE value_type;
Radek Krejci1798aae2020-07-14 13:26:06 +0200804 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
aPiecekea304e32021-08-18 09:13:47 +0200805 uint8_t *term_value = NULL;
Michal Vasko9afe3df2021-02-05 16:33:50 +0100806 const char *val_dict;
Radek Krejci857189e2020-09-01 13:26:36 +0200807 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200808 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100809 void *val_prefix_data = NULL;
aPiecekea304e32021-08-18 09:13:47 +0200810 uint32_t flags, term_value_len;
Radek Krejci1798aae2020-07-14 13:26:06 +0200811 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +0200812
813 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200814 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200815
Michal Vaskof4b4d002021-08-23 12:16:02 +0200816 if (!parent || !parent->schema) {
817 /* top-level or opaque, read module name */
Michal Vaskoe0665742021-02-11 11:08:44 +0100818 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200819 LY_CHECK_GOTO(ret, cleanup);
820
821 /* read hash, find the schema node starting from mod */
822 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
823 LY_CHECK_GOTO(ret, cleanup);
824 } else {
825 /* read hash, find the schema node starting from parent schema */
826 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
827 LY_CHECK_GOTO(ret, cleanup);
828 }
829
Michal Vaskoe0665742021-02-11 11:08:44 +0100830 if (!snode && !(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200831 /* unknown data, skip them */
Radek Krejci1798aae2020-07-14 13:26:06 +0200832 lyb_skip_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200833 goto stop_subtree;
Radek Krejci0f969882020-08-21 16:56:47 +0200834 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200835
836 /* create metadata/attributes */
837 if (snode) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200838 ret = lyb_parse_metadata(lybctx, &meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200839 LY_CHECK_GOTO(ret, cleanup);
840 } else {
Radek Krejci1798aae2020-07-14 13:26:06 +0200841 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200842 LY_CHECK_GOTO(ret, cleanup);
843 }
844
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100845 /* read flags */
846 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
847
Michal Vasko60ea6352020-06-29 13:39:39 +0200848 if (!snode) {
849 /* parse prefix */
Radek Krejci1798aae2020-07-14 13:26:06 +0200850 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200851 LY_CHECK_GOTO(ret, cleanup);
852
Radek Krejci1798aae2020-07-14 13:26:06 +0200853 /* parse module key */
854 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200855 LY_CHECK_GOTO(ret, cleanup);
856
857 /* parse name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200858 ret = lyb_read_string(&name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200859 LY_CHECK_GOTO(ret, cleanup);
860
Michal Vaskoffc92bf2021-06-21 08:15:14 +0200861 /* parse value */
862 ret = lyb_read_string(&value, 1, lybctx->lybctx);
863 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
864 dynamic = 1;
865
Michal Vasko60ea6352020-06-29 13:39:39 +0200866 /* parse format */
Michal Vasko403beac2021-08-24 08:27:52 +0200867 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200868
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100869 /* parse value prefixes */
870 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
871 LY_CHECK_GOTO(ret, cleanup);
872
Michal Vasko60ea6352020-06-29 13:39:39 +0200873 /* create node */
Michal Vasko501af032020-11-11 20:27:44 +0100874 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
875 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200876 LY_CHECK_GOTO(ret, cleanup);
877
878 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200879 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100880 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200881 LY_CHECK_GOTO(ret, cleanup);
882 }
883 } else if (snode->nodetype & LYD_NODE_TERM) {
884 /* parse value */
aPiecekea304e32021-08-18 09:13:47 +0200885 ret = lyb_read_term(&term_value, &term_value_len, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200886 LY_CHECK_GOTO(ret, cleanup);
887 dynamic = 1;
888
889 /* create node */
aPiecekea304e32021-08-18 09:13:47 +0200890 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode,
891 term_value, term_value_len, &dynamic, LY_VALUE_LYB,
Michal Vasko69730152020-10-09 16:30:07 +0200892 NULL, LYD_HINT_DATA, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200893 if (dynamic) {
aPiecekea304e32021-08-18 09:13:47 +0200894 free(term_value);
Michal Vasko60ea6352020-06-29 13:39:39 +0200895 dynamic = 0;
896 }
aPiecekea304e32021-08-18 09:13:47 +0200897 term_value = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200898 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200899 } else if (snode->nodetype & LYD_NODE_INNER) {
900 /* create node */
901 ret = lyd_create_inner(snode, &node);
902 LY_CHECK_GOTO(ret, cleanup);
903
904 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200905 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100906 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200907 LY_CHECK_GOTO(ret, cleanup);
908 }
909
Michal Vaskoe0665742021-02-11 11:08:44 +0100910 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200911 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vaskoe0665742021-02-11 11:08:44 +0100912 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200913 LY_CHECK_GOTO(ret, cleanup);
914
915 /* add any missing default children */
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200916 ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &lybctx->node_when, &lybctx->node_exts,
Michal Vaskoc43c8ab2021-03-05 13:32:44 +0100917 &lybctx->node_types, (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200918 LY_CHECK_GOTO(ret, cleanup);
919 }
920
Michal Vasko751cb4d2020-07-14 12:25:28 +0200921 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200922 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +0200923 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +0200924 }
925 } else if (snode->nodetype & LYD_NODE_ANY) {
926 /* parse value type */
Michal Vasko403beac2021-08-24 08:27:52 +0200927 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200928 if (value_type == LYD_ANYDATA_DATATREE) {
929 /* invalid situation */
Radek Krejci1798aae2020-07-14 13:26:06 +0200930 LOGINT(ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200931 goto cleanup;
932 }
933
934 /* read anydata content */
Radek Krejci1798aae2020-07-14 13:26:06 +0200935 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200936 LY_CHECK_GOTO(ret, cleanup);
937 dynamic = 1;
938
939 if (value_type == LYD_ANYDATA_LYB) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200940 /* try to parse LYB into a data tree */
Michal Vasko02ed9d82021-07-15 14:58:04 +0200941 if (!lyb_parse_any_content(ctx, value, &tree)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200942 /* successfully parsed */
943 free(value);
944 value = (char *)tree;
945 value_type = LYD_ANYDATA_DATATREE;
946 }
947 }
948
Michal Vasko9afe3df2021-02-05 16:33:50 +0100949 /* create the node */
950 switch (value_type) {
951 case LYD_ANYDATA_LYB:
952 case LYD_ANYDATA_DATATREE:
953 /* use the value directly */
954 ret = lyd_create_any(snode, value, value_type, 1, &node);
955 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200956
Michal Vasko9afe3df2021-02-05 16:33:50 +0100957 dynamic = 0;
958 value = NULL;
959 break;
960 case LYD_ANYDATA_STRING:
961 case LYD_ANYDATA_XML:
962 case LYD_ANYDATA_JSON:
963 /* value is expected to be in the dictionary */
964 ret = lydict_insert_zc(ctx, value, &val_dict);
965 LY_CHECK_GOTO(ret, cleanup);
966 dynamic = 0;
967 value = NULL;
968
969 /* use the value in the dictionary */
970 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
971 if (ret) {
972 lydict_remove(ctx, val_dict);
973 goto cleanup;
974 }
975 break;
976 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200977 }
978 assert(node);
979
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100980 /* set flags */
981 node->flags = flags;
Michal Vasko60ea6352020-06-29 13:39:39 +0200982
983 /* add metadata/attributes */
984 if (snode) {
985 LY_LIST_FOR(meta, m) {
986 m->parent = node;
987 }
988 node->meta = meta;
989 meta = NULL;
990 } else {
991 assert(!node->schema);
992 LY_LIST_FOR(attr, a) {
993 a->parent = (struct lyd_node_opaq *)node;
994 }
995 ((struct lyd_node_opaq *)node)->attr = attr;
996 attr = NULL;
997 }
998
Michal Vaskob104f112020-07-17 09:54:54 +0200999 /* insert, keep first pointer correct */
Michal Vasko6ee6f432021-07-16 09:49:14 +02001000 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
Michal Vaskoe0665742021-02-11 11:08:44 +01001001 while (!parent && (*first_p)->prev->next) {
1002 *first_p = (*first_p)->prev;
1003 }
1004
1005 /* rememeber a successfully parsed node */
1006 if (parsed) {
1007 ly_set_add(parsed, node, 1, NULL);
Michal Vaskob104f112020-07-17 09:54:54 +02001008 }
Michal Vasko60ea6352020-06-29 13:39:39 +02001009 node = NULL;
1010
1011stop_subtree:
1012 /* end the subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001013 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001014 LY_CHECK_GOTO(ret, cleanup);
1015
1016cleanup:
1017 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +02001018 free(module_key);
Michal Vasko60ea6352020-06-29 13:39:39 +02001019 free(name);
1020 if (dynamic) {
1021 free(value);
1022 }
Michal Vasko60ea6352020-06-29 13:39:39 +02001023
Michal Vasko3a41dff2020-07-15 14:30:28 +02001024 lyd_free_meta_siblings(meta);
Radek Krejci011e4aa2020-09-04 15:22:31 +02001025 lyd_free_attr_siblings(ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +02001026 lyd_free_tree(node);
1027 return ret;
1028}
1029
1030/**
1031 * @brief Parse used YANG data models.
1032 *
1033 * @param[in] lybctx LYB context.
1034 * @return LY_ERR value.
1035 */
1036static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001037lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001038{
1039 LY_ERR ret;
1040 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001041 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001042
1043 /* read model count */
1044 lyb_read_number(&count, sizeof count, 2, lybctx);
1045
1046 if (count) {
1047 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1048
1049 /* read modules */
1050 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001051 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001052 LY_CHECK_RET(ret);
1053 LY_ARRAY_INCREMENT(lybctx->models);
1054 }
1055 }
1056
1057 return LY_SUCCESS;
1058}
1059
1060/**
1061 * @brief Parse LYB magic number.
1062 *
1063 * @param[in] lybctx LYB context.
1064 * @return LY_ERR value.
1065 */
1066static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001067lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001068{
1069 char magic_byte = 0;
1070
1071 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1072 if (magic_byte != 'l') {
1073 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1074 return LY_EINVAL;
1075 }
1076
1077 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1078 if (magic_byte != 'y') {
1079 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1080 return LY_EINVAL;
1081 }
1082
1083 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1084 if (magic_byte != 'b') {
1085 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1086 return LY_EINVAL;
1087 }
1088
1089 return LY_SUCCESS;
1090}
1091
1092/**
1093 * @brief Parse LYB header.
1094 *
1095 * @param[in] lybctx LYB context.
1096 * @return LY_ERR value.
1097 */
1098static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001099lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001100{
1101 uint8_t byte = 0;
1102
1103 /* version, future flags */
1104 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1105
1106 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1107 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001108 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001109 return LY_EINVAL;
1110 }
1111
1112 return LY_SUCCESS;
1113}
1114
Michal Vasko02ed9d82021-07-15 14:58:04 +02001115static LY_ERR
1116_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1117 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
Radek Krejcif16e2542021-02-17 15:39:23 +01001118 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001119{
Michal Vaskoe0665742021-02-11 11:08:44 +01001120 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001121 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001122
Michal Vaskoe0665742021-02-11 11:08:44 +01001123 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1124 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001125
Radek Krejci1798aae2020-07-14 13:26:06 +02001126 lybctx = calloc(1, sizeof *lybctx);
1127 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1128 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001129 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001130
Radek Krejci1798aae2020-07-14 13:26:06 +02001131 lybctx->lybctx->in = in;
1132 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001133 lybctx->parse_opts = parse_opts;
1134 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001135 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001136 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001137 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001138
1139 /* find the operation node if it exists already */
1140 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1141
Michal Vasko60ea6352020-06-29 13:39:39 +02001142 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001143 rc = lyb_parse_magic_number(lybctx->lybctx);
1144 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001145
1146 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001147 rc = lyb_parse_header(lybctx->lybctx);
1148 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001149
1150 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001151 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1152 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001153
1154 /* read subtree(s) */
Radek Krejci1798aae2020-07-14 13:26:06 +02001155 while (lybctx->lybctx->in->current[0]) {
Michal Vaskoe0665742021-02-11 11:08:44 +01001156 rc = lyb_parse_subtree_r(lybctx, parent, first_p, parsed);
1157 LY_CHECK_GOTO(rc, cleanup);
1158
1159 if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1160 break;
1161 }
1162 }
1163
1164 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1165 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1166 rc = LY_EVALID;
1167 goto cleanup;
1168 }
1169 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1170 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1171 rc = LY_EVALID;
1172 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001173 }
1174
1175 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001176 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001177
Michal Vasko60ea6352020-06-29 13:39:39 +02001178cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001179 /* there should be no unres stored if validation should be skipped */
1180 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1181 !lybctx->node_when.count));
1182
1183 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001184 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001185 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001186 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001187 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001188 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001189}
1190
Michal Vasko02ed9d82021-07-15 14:58:04 +02001191LY_ERR
1192lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1193 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1194 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
1195{
1196 uint32_t int_opts;
1197
1198 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1199 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1200
1201 switch (data_type) {
1202 case LYD_TYPE_DATA_YANG:
1203 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1204 break;
1205 case LYD_TYPE_RPC_YANG:
1206 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1207 break;
1208 case LYD_TYPE_NOTIF_YANG:
1209 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1210 break;
1211 case LYD_TYPE_REPLY_YANG:
1212 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1213 break;
1214 default:
1215 LOGINT(ctx);
1216 return LY_EINT;
1217 }
1218
1219 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1220}
1221
Michal Vasko60ea6352020-06-29 13:39:39 +02001222API int
1223lyd_lyb_data_length(const char *data)
1224{
1225 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001226 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001227 int count, i;
1228 size_t len;
1229 uint8_t buf[LYB_SIZE_MAX];
1230
1231 if (!data) {
1232 return -1;
1233 }
1234
Radek Krejci1798aae2020-07-14 13:26:06 +02001235 lybctx = calloc(1, sizeof *lybctx);
1236 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1237 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001238 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001239
1240 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001241 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001242 LY_CHECK_GOTO(ret, cleanup);
1243
1244 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001245 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001246 LY_CHECK_GOTO(ret, cleanup);
1247
1248 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001249 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001250
1251 /* read all models */
1252 for (i = 0; i < count; ++i) {
1253 /* module name length */
1254 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001255 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001256
1257 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001258 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001259
1260 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001261 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001262 }
1263
Radek Krejci1798aae2020-07-14 13:26:06 +02001264 while (lybctx->in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001265 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001266 ret = lyb_read_start_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001267 LY_CHECK_GOTO(ret, cleanup);
1268
1269 /* skip it */
Radek Krejci1798aae2020-07-14 13:26:06 +02001270 lyb_skip_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001271
1272 /* subtree finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001273 ret = lyb_read_stop_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001274 LY_CHECK_GOTO(ret, cleanup);
1275 }
1276
1277 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001278 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001279
1280cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001281 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001282
Radek Krejci1798aae2020-07-14 13:26:06 +02001283 ly_in_free(lybctx->in, 0);
1284 lylyb_ctx_free(lybctx);
1285
Michal Vasko63f3d842020-07-08 10:10:14 +02001286 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001287}