blob: 81b640aabd3b5ce77b65694a8de1d2578627b3da [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
aPiecek570d7ed2021-09-10 07:15:35 +020046static LY_ERR lyb_parse_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode, struct lyd_node **first_p, struct ly_set *parsed);
aPiecek18457d72021-09-09 15:52:20 +020047static LY_ERR lyb_parse_node_header(struct lyd_lyb_ctx *lybctx, uint32_t *flags, struct lyd_meta **meta);
aPiecek570d7ed2021-09-10 07:15:35 +020048static LY_ERR lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed);
aPiecek821cf732021-09-09 15:37:28 +020049
Radek Krejci1798aae2020-07-14 13:26:06 +020050void
51lylyb_ctx_free(struct lylyb_ctx *ctx)
52{
53 LY_ARRAY_COUNT_TYPE u;
54
aPiecek570d7ed2021-09-10 07:15:35 +020055 LY_ARRAY_FREE(ctx->siblings);
Radek Krejci1798aae2020-07-14 13:26:06 +020056 LY_ARRAY_FREE(ctx->models);
57
58 LY_ARRAY_FOR(ctx->sib_hts, u) {
59 lyht_free(ctx->sib_hts[u].ht);
60 }
61 LY_ARRAY_FREE(ctx->sib_hts);
62
63 free(ctx);
64}
65
66void
67lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
68{
69 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
70
71 lyd_ctx_free(lydctx);
72 lylyb_ctx_free(ctx->lybctx);
73 free(ctx);
74}
75
Michal Vasko60ea6352020-06-29 13:39:39 +020076/**
77 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
78 *
79 * @param[in] buf Destination buffer.
80 * @param[in] count Number of bytes to read.
81 * @param[in] lybctx LYB context.
82 */
83static void
Radek Krejci1798aae2020-07-14 13:26:06 +020084lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +020085{
Michal Vaskofd69e1d2020-07-03 11:57:17 +020086 LY_ARRAY_COUNT_TYPE u;
aPiecek570d7ed2021-09-10 07:15:35 +020087 struct lyd_lyb_sibling *empty;
Michal Vasko60ea6352020-06-29 13:39:39 +020088 size_t to_read;
89 uint8_t meta_buf[LYB_META_BYTES];
90
91 assert(lybctx);
92
93 while (1) {
94 /* check for fully-read (empty) data chunks */
95 to_read = count;
96 empty = NULL;
aPiecek570d7ed2021-09-10 07:15:35 +020097 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +020098 /* we want the innermost chunks resolved first, so replace previous empty chunks,
99 * also ignore chunks that are completely finished, there is nothing for us to do */
aPiecek570d7ed2021-09-10 07:15:35 +0200100 if ((lybctx->siblings[u].written <= to_read) && lybctx->siblings[u].position) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200101 /* empty chunk, do not read more */
aPiecek570d7ed2021-09-10 07:15:35 +0200102 to_read = lybctx->siblings[u].written;
103 empty = &lybctx->siblings[u];
Michal Vasko60ea6352020-06-29 13:39:39 +0200104 }
105 }
106
107 if (!empty && !count) {
108 break;
109 }
110
111 /* we are actually reading some data, not just finishing another chunk */
112 if (to_read) {
113 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200114 ly_in_read(lybctx->in, buf, to_read);
115 } else {
116 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200117 }
118
aPiecek570d7ed2021-09-10 07:15:35 +0200119 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200120 /* decrease all written counters */
aPiecek570d7ed2021-09-10 07:15:35 +0200121 lybctx->siblings[u].written -= to_read;
122 assert(lybctx->siblings[u].written <= LYB_SIZE_MAX);
Michal Vasko60ea6352020-06-29 13:39:39 +0200123 }
124 /* decrease count/buf */
125 count -= to_read;
126 if (buf) {
127 buf += to_read;
128 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200129 }
130
131 if (empty) {
132 /* read the next chunk meta information */
Michal Vasko63f3d842020-07-08 10:10:14 +0200133 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200134 empty->written = meta_buf[0];
135 empty->inner_chunks = meta_buf[1];
136
137 /* remember whether there is a following chunk or not */
138 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200139 }
140 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200141}
142
143/**
144 * @brief Read a number.
145 *
146 * @param[in] num Destination buffer.
147 * @param[in] num_size Size of @p num.
148 * @param[in] bytes Number of bytes to read.
149 * @param[in] lybctx LYB context.
150 */
151static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200152lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200153{
154 uint64_t buf = 0;
155
156 lyb_read((uint8_t *)&buf, bytes, lybctx);
157
158 /* correct byte order */
159 buf = le64toh(buf);
160
161 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100162 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200163 *((uint8_t *)num) = buf;
164 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100165 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200166 *((uint16_t *)num) = buf;
167 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100168 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200169 *((uint32_t *)num) = buf;
170 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100171 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200172 *((uint64_t *)num) = buf;
173 break;
174 default:
175 LOGINT(lybctx->ctx);
176 }
177}
178
179/**
180 * @brief Read a string.
181 *
182 * @param[in] str Destination buffer, is allocated.
aPiecek570d7ed2021-09-10 07:15:35 +0200183 * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this "sibling".
Michal Vasko60ea6352020-06-29 13:39:39 +0200184 * @param[in] lybctx LYB context.
185 * @return LY_ERR value.
186 */
187static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +0200188lyb_read_string(char **str, ly_bool with_length, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200189{
Radek Krejci857189e2020-09-01 13:26:36 +0200190 ly_bool next_chunk = 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200191 size_t len = 0, cur_len;
192
193 *str = NULL;
194
195 if (with_length) {
196 lyb_read_number(&len, sizeof len, 2, lybctx);
197 } else {
aPiecek570d7ed2021-09-10 07:15:35 +0200198 /* read until the end of this "sibling" */
199 len = LYB_LAST_SIBLING(lybctx).written;
200 if (LYB_LAST_SIBLING(lybctx).position) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200201 next_chunk = 1;
202 }
203 }
204
205 *str = malloc((len + 1) * sizeof **str);
206 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
207
208 lyb_read((uint8_t *)*str, len, lybctx);
209
210 while (next_chunk) {
aPiecek570d7ed2021-09-10 07:15:35 +0200211 cur_len = LYB_LAST_SIBLING(lybctx).written;
212 if (LYB_LAST_SIBLING(lybctx).position) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200213 next_chunk = 1;
214 } else {
215 next_chunk = 0;
216 }
217
218 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
219 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
220
221 lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
222
223 len += cur_len;
224 }
225
Michal Vaskocebbae52021-05-31 11:11:36 +0200226 (*str)[len] = '\0';
Michal Vasko60ea6352020-06-29 13:39:39 +0200227 return LY_SUCCESS;
228}
229
230/**
aPiecek91eec232021-09-09 15:42:37 +0200231 * @brief Read value of term node.
aPiecekea304e32021-08-18 09:13:47 +0200232 *
aPiecekaa5b70a2021-08-30 08:33:25 +0200233 * @param[in] term Compiled term node.
aPiecekea304e32021-08-18 09:13:47 +0200234 * @param[out] term_value Set to term node value in dynamically
235 * allocated memory. The caller must release it.
236 * @param[out] term_value_len Value length in bytes. The zero byte is
237 * always included and is not counted.
238 * @param[in,out] lybctx LYB context.
239 * @return LY_ERR value.
240 */
241static LY_ERR
aPiecek91eec232021-09-09 15:42:37 +0200242lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uint32_t *term_value_len,
243 struct lylyb_ctx *lybctx)
aPiecekea304e32021-08-18 09:13:47 +0200244{
245 uint32_t allocated_size;
aPiecekaa5b70a2021-08-30 08:33:25 +0200246 int32_t lyb_data_len;
247 struct lysc_type_leafref *type_lf;
aPiecekea304e32021-08-18 09:13:47 +0200248
aPiecekaa5b70a2021-08-30 08:33:25 +0200249 assert(term && term_value && term_value_len && lybctx);
aPiecekea304e32021-08-18 09:13:47 +0200250
aPiecekaa5b70a2021-08-30 08:33:25 +0200251 /* Find out the size from @ref howtoDataLYB. */
252 if (term->type->basetype == LY_TYPE_LEAFREF) {
253 /* Leafref itself is ignored, the target is loaded directly. */
254 type_lf = (struct lysc_type_leafref *)term->type;
255 lyb_data_len = type_lf->realtype->plugin->lyb_data_len;
256 } else {
257 lyb_data_len = term->type->plugin->lyb_data_len;
258 }
259
260 if (lyb_data_len < 0) {
261 /* Parse value size. */
262 lyb_read_number(term_value_len, sizeof *term_value_len,
263 sizeof *term_value_len, lybctx);
264 } else {
265 /* Data size is fixed. */
266 *term_value_len = lyb_data_len;
267 }
aPiecekea304e32021-08-18 09:13:47 +0200268
269 /* Allocate memory. */
270 allocated_size = *term_value_len + 1;
271 *term_value = malloc(allocated_size * sizeof **term_value);
272 LY_CHECK_ERR_RET(!*term_value, LOGMEM(lybctx->ctx), LY_EMEM);
273
274 if (*term_value_len > 0) {
275 /* Parse value. */
276 lyb_read(*term_value, *term_value_len, lybctx);
277 }
278
279 /* Add extra zero byte regardless of whether it is string or not. */
280 (*term_value)[allocated_size - 1] = 0;
281
282 return LY_SUCCESS;
283}
284
285/**
aPiecek570d7ed2021-09-10 07:15:35 +0200286 * @brief Stop the current "siblings" - change LYB context state.
Michal Vasko60ea6352020-06-29 13:39:39 +0200287 *
288 * @param[in] lybctx LYB context.
289 * @return LY_ERR value.
290 */
291static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200292lyb_read_stop_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200293{
aPiecek570d7ed2021-09-10 07:15:35 +0200294 if (LYB_LAST_SIBLING(lybctx).written) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200295 LOGINT_RET(lybctx->ctx);
296 }
297
aPiecek570d7ed2021-09-10 07:15:35 +0200298 LY_ARRAY_DECREMENT(lybctx->siblings);
Michal Vasko60ea6352020-06-29 13:39:39 +0200299 return LY_SUCCESS;
300}
301
302/**
aPiecek570d7ed2021-09-10 07:15:35 +0200303 * @brief Start a new "siblings" - change LYB context state but also read the expected metadata.
Michal Vasko60ea6352020-06-29 13:39:39 +0200304 *
305 * @param[in] lybctx LYB context.
306 * @return LY_ERR value.
307 */
308static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200309lyb_read_start_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200310{
311 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200312 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200313
aPiecek570d7ed2021-09-10 07:15:35 +0200314 u = LY_ARRAY_COUNT(lybctx->siblings);
315 if (u == lybctx->sibling_size) {
316 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->siblings, u + LYB_SIBLING_STEP, LY_EMEM);
317 lybctx->sibling_size = u + LYB_SIBLING_STEP;
Michal Vasko60ea6352020-06-29 13:39:39 +0200318 }
319
Michal Vasko63f3d842020-07-08 10:10:14 +0200320 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200321
aPiecek570d7ed2021-09-10 07:15:35 +0200322 LY_ARRAY_INCREMENT(lybctx->siblings);
323 LYB_LAST_SIBLING(lybctx).written = meta_buf[0];
324 LYB_LAST_SIBLING(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
325 LYB_LAST_SIBLING(lybctx).position = (LYB_LAST_SIBLING(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200326
Michal Vasko60ea6352020-06-29 13:39:39 +0200327 return LY_SUCCESS;
328}
329
330/**
331 * @brief Parse YANG model info.
332 *
333 * @param[in] lybctx LYB context.
aPiecekfc7cf7e2021-09-09 11:20:27 +0200334 * @param[in] parse_options Flag with options for parsing.
aPiecek339bdc32021-09-10 08:42:36 +0200335 * @param[out] model Parsed module.
Michal Vasko60ea6352020-06-29 13:39:39 +0200336 * @return LY_ERR value.
337 */
338static LY_ERR
aPiecek339bdc32021-09-10 08:42:36 +0200339lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **model)
Michal Vasko60ea6352020-06-29 13:39:39 +0200340{
341 LY_ERR ret = LY_SUCCESS;
aPiecek570d7ed2021-09-10 07:15:35 +0200342 const struct lys_module *mod = NULL;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100343 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
aPiecek570d7ed2021-09-10 07:15:35 +0200344 uint16_t rev, length;
Michal Vasko60ea6352020-06-29 13:39:39 +0200345
aPiecek570d7ed2021-09-10 07:15:35 +0200346 lyb_read_number(&length, 2, 2, lybctx);
aPiecek339bdc32021-09-10 08:42:36 +0200347
aPiecek570d7ed2021-09-10 07:15:35 +0200348 if (length) {
349 mod_name = malloc((length + 1) * sizeof *mod_name);
350 LY_CHECK_ERR_RET(!mod_name, LOGMEM(lybctx->ctx), LY_EMEM);
351 lyb_read(((uint8_t *)mod_name), length, lybctx);
352 mod_name[length] = '\0';
353 } else {
354 goto cleanup;
355 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200356
357 /* revision */
358 lyb_read_number(&rev, sizeof rev, 2, lybctx);
359
Michal Vasko60ea6352020-06-29 13:39:39 +0200360 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100361 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
362 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
aPiecek339bdc32021-09-10 08:42:36 +0200363 mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
364 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !mod) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200365 /* try to use an updated module */
aPiecek339bdc32021-09-10 08:42:36 +0200366 mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
367 if (mod && (!mod->revision || (strcmp(mod->revision, mod_rev) < 0))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200368 /* not an implemented module in a newer revision */
aPiecek339bdc32021-09-10 08:42:36 +0200369 mod = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200370 }
371 }
372 } else {
aPiecek339bdc32021-09-10 08:42:36 +0200373 mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200374 }
375 /* TODO data_clb supported?
376 if (lybctx->ctx->data_clb) {
377 if (!*mod) {
378 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
379 } else if (!(*mod)->implemented) {
380 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
381 }
382 }*/
383
aPiecek339bdc32021-09-10 08:42:36 +0200384 if (!mod || !mod->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200385 if (parse_options & LYD_PARSE_STRICT) {
aPiecek339bdc32021-09-10 08:42:36 +0200386 if (!mod) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200387 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +0200388 mod_name, rev ? "@" : "", rev ? mod_rev : "");
aPiecek339bdc32021-09-10 08:42:36 +0200389 } else if (!mod->implemented) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200390 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko69730152020-10-09 16:30:07 +0200391 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200392 }
393 ret = LY_EINVAL;
394 goto cleanup;
395 }
396
397 }
398
aPiecek339bdc32021-09-10 08:42:36 +0200399 if (mod) {
Michal Vasko85d9edc2021-04-22 09:15:05 +0200400 /* fill cached hashes, if not already */
aPiecek339bdc32021-09-10 08:42:36 +0200401 lyb_cache_module_hash(mod);
Michal Vasko85d9edc2021-04-22 09:15:05 +0200402 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200403
Michal Vasko60ea6352020-06-29 13:39:39 +0200404cleanup:
aPiecek570d7ed2021-09-10 07:15:35 +0200405 *model = mod;
Michal Vasko60ea6352020-06-29 13:39:39 +0200406 free(mod_name);
407 return ret;
408}
409
410/**
411 * @brief Parse YANG node metadata.
412 *
413 * @param[in] lybctx LYB context.
Michal Vasko60ea6352020-06-29 13:39:39 +0200414 * @param[out] meta Parsed metadata.
415 * @return LY_ERR value.
416 */
417static LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200418lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200419{
420 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200421 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200422 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200423 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200424 const struct lys_module *mod;
425
426 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200427 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200428
429 /* read attributes */
430 for (i = 0; i < count; ++i) {
aPiecek570d7ed2021-09-10 07:15:35 +0200431 ret = lyb_read_start_siblings(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200432 LY_CHECK_GOTO(ret, cleanup);
433
434 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100435 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200436 LY_CHECK_GOTO(ret, cleanup);
437
438 if (!mod) {
439 /* skip it */
440 do {
aPiecek570d7ed2021-09-10 07:15:35 +0200441 lyb_read(NULL, LYB_LAST_SIBLING(lybctx->lybctx).written, lybctx->lybctx);
442 } while (LYB_LAST_SIBLING(lybctx->lybctx).written);
443 goto stop_sibling;
Michal Vasko60ea6352020-06-29 13:39:39 +0200444 }
445
446 /* meta name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200447 ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200448 LY_CHECK_GOTO(ret, cleanup);
449
450 /* meta value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200451 ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200452 LY_CHECK_GOTO(ret, cleanup);
453 dynamic = 1;
454
455 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200456 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 +0200457 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200458
459 /* free strings */
460 free(meta_name);
461 meta_name = NULL;
462 if (dynamic) {
463 free(meta_value);
464 dynamic = 0;
465 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200466
Radek Krejci1798aae2020-07-14 13:26:06 +0200467 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200468
aPiecek570d7ed2021-09-10 07:15:35 +0200469stop_sibling:
470 ret = lyb_read_stop_siblings(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200471 LY_CHECK_GOTO(ret, cleanup);
472 }
473
474cleanup:
475 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200476 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200477 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200478 *meta = NULL;
479 }
480 return ret;
481}
482
483/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100484 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200485 *
486 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100487 * @param[in] format Prefix data format.
488 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200489 * @return LY_ERR value.
490 */
491static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200492lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200493{
494 LY_ERR ret = LY_SUCCESS;
495 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100496 struct ly_set *set = NULL;
497 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200498
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100499 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200500 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100501 /* read count */
502 lyb_read(&count, 1, lybctx);
503 if (!count) {
504 return LY_SUCCESS;
505 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200506
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100507 /* read all NS elements */
508 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200509
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100510 for (i = 0; i < count; ++i) {
511 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200512
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100513 /* prefix */
514 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
515
516 /* namespace */
517 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
518
519 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
520 ns = NULL;
521 }
522
523 *prefix_data = set;
524 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200525 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200526 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100527 /* nothing stored */
528 break;
529 default:
530 LOGINT(lybctx->ctx);
531 ret = LY_EINT;
532 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200533 }
534
535cleanup:
536 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100537 ly_free_prefix_data(format, set);
538 if (ns) {
539 free(ns->prefix);
540 free(ns->uri);
541 free(ns);
542 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200543 }
544 return ret;
545}
546
547/**
548 * @brief Parse opaque attributes.
549 *
550 * @param[in] lybctx LYB context.
551 * @param[out] attr Parsed attributes.
552 * @return LY_ERR value.
553 */
554static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200555lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200556{
557 LY_ERR ret = LY_SUCCESS;
558 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200559 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200560 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200561 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200562 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100563 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200564
565 /* read count */
566 lyb_read(&count, 1, lybctx);
567
568 /* read attributes */
569 for (i = 0; i < count; ++i) {
aPiecek570d7ed2021-09-10 07:15:35 +0200570 ret = lyb_read_start_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200571 LY_CHECK_GOTO(ret, cleanup);
572
Michal Vasko0fdcd242020-11-11 19:12:30 +0100573 /* prefix, may be empty */
Michal Vasko60ea6352020-06-29 13:39:39 +0200574 ret = lyb_read_string(&prefix, 1, lybctx);
575 LY_CHECK_GOTO(ret, cleanup);
576 if (!prefix[0]) {
577 free(prefix);
578 prefix = NULL;
579 }
580
581 /* namespace, may be empty */
Radek Krejci1798aae2020-07-14 13:26:06 +0200582 ret = lyb_read_string(&module_name, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200583 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200584 if (!module_name[0]) {
585 free(module_name);
586 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200587 }
588
589 /* name */
590 ret = lyb_read_string(&name, 1, lybctx);
591 LY_CHECK_GOTO(ret, cleanup);
592
Michal Vasko60ea6352020-06-29 13:39:39 +0200593 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200594 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200595
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100596 /* value prefixes */
597 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
598 LY_CHECK_GOTO(ret, cleanup);
599
Michal Vasko60ea6352020-06-29 13:39:39 +0200600 /* value */
601 ret = lyb_read_string(&value, 0, lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100602 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200603 dynamic = 1;
604
605 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100606 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200607 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200608 LY_CHECK_GOTO(ret, cleanup);
609
610 free(prefix);
611 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200612 free(module_name);
613 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200614 free(name);
615 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200616 assert(!dynamic);
617 value = NULL;
618
619 if (!*attr) {
620 *attr = attr2;
621 }
622
aPiecek570d7ed2021-09-10 07:15:35 +0200623 ret = lyb_read_stop_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200624 LY_CHECK_GOTO(ret, cleanup);
625 }
626
627cleanup:
628 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200629 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200630 free(name);
631 if (dynamic) {
632 free(value);
633 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200634 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200635 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200636 *attr = NULL;
637 }
638 return ret;
639}
640
641/**
aPiecek619350d2021-09-09 16:06:59 +0200642 * @brief Fill @p hash with hash values.
643 *
644 * @param[in] lybctx LYB context.
645 * @param[in,out] hash Pointer to the array in which the hash values are to be written.
646 * @param[out] hash_count Number of hashes in @p hash.
647 * @return LY_ERR value.
648 */
649static LY_ERR
650lyb_read_hashes(struct lylyb_ctx *lybctx, LYB_HASH *hash, uint8_t *hash_count)
651{
652 uint8_t i = 0, j;
653
654 /* read the first hash */
655 lyb_read(&hash[0], sizeof *hash, lybctx);
656
657 if (!hash[0]) {
658 *hash_count = i + 1;
659 return LY_SUCCESS;
660 }
661
662 /* based on the first hash read all the other ones, if any */
663 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
664 if (i > LYB_HASH_BITS) {
665 LOGINT_RET(lybctx->ctx);
666 }
667 }
668
669 /* move the first hash on its accurate position */
670 hash[i] = hash[0];
671
672 /* read the rest of hashes */
673 for (j = i; j; --j) {
674 lyb_read(&hash[j - 1], sizeof *hash, lybctx);
675
676 /* correct collision ID */
677 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
678 /* preceded with zeros */
679 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
680 }
681
682 *hash_count = i + 1;
683
684 return LY_SUCCESS;
685}
686
687/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200688 * @brief Check whether a schema node matches a hash(es).
689 *
690 * @param[in] sibling Schema node to check.
691 * @param[in] hash Hash array to check.
692 * @param[in] hash_count Number of hashes in @p hash.
693 * @return non-zero if matches,
694 * @return 0 if not.
695 */
696static int
697lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
698{
699 LYB_HASH sibling_hash;
700 uint8_t i;
701
702 /* compare all the hashes starting from collision ID 0 */
703 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200704 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200705 if (sibling_hash != hash[i]) {
706 return 0;
707 }
708 }
709
710 return 1;
711}
712
713/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200714 * @brief Parse schema node hash.
715 *
716 * @param[in] lybctx LYB context.
717 * @param[in] sparent Schema parent, must be set if @p mod is not.
718 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
719 * @param[out] snode Parsed found schema node, may be NULL if opaque.
720 * @return LY_ERR value.
721 */
722static LY_ERR
723lyb_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 +0200724 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200725{
726 LY_ERR ret;
Michal Vasko60ea6352020-06-29 13:39:39 +0200727 const struct lysc_node *sibling;
728 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200729 uint32_t getnext_opts;
aPiecek619350d2021-09-09 16:06:59 +0200730 uint8_t hash_count;
Michal Vasko60ea6352020-06-29 13:39:39 +0200731
aPiecek570d7ed2021-09-10 07:15:35 +0200732 *snode = NULL;
733
aPiecek619350d2021-09-09 16:06:59 +0200734 ret = lyb_read_hashes(lybctx->lybctx, hash, &hash_count);
735 LY_CHECK_RET(ret);
Michal Vasko60ea6352020-06-29 13:39:39 +0200736
737 if (!hash[0]) {
738 /* opaque node */
739 return LY_SUCCESS;
740 }
741
aPiecek619350d2021-09-09 16:06:59 +0200742 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200743
744 /* find our node with matching hashes */
745 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100746 while (1) {
747 if (!sparent && lybctx->ext) {
748 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
749 } else {
750 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
751 }
752 if (!sibling) {
753 break;
754 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200755 /* skip schema nodes from models not present during printing */
Michal Vasko69730152020-10-09 16:30:07 +0200756 if (lyb_has_schema_model(sibling, lybctx->lybctx->models) &&
aPiecek619350d2021-09-09 16:06:59 +0200757 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, hash_count)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200758 /* match found */
759 break;
760 }
761 }
762
Michal Vaskoe0665742021-02-11 11:08:44 +0100763 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100764 if (lybctx->ext) {
765 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
766 lybctx->ext->def->name);
767 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100768 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200769 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200770 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100771 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200772 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200773 }
774 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200775 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200776 return ret;
777 }
778
779 *snode = sibling;
780 return LY_SUCCESS;
781}
782
783/**
aPiecek570d7ed2021-09-10 07:15:35 +0200784 * @brief Read until the end of the current siblings.
Michal Vasko60ea6352020-06-29 13:39:39 +0200785 *
786 * @param[in] lybctx LYB context.
787 */
788static void
aPiecek570d7ed2021-09-10 07:15:35 +0200789lyb_skip_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200790{
Michal Vasko60ea6352020-06-29 13:39:39 +0200791 do {
792 /* first skip any meta information inside */
aPiecek570d7ed2021-09-10 07:15:35 +0200793 ly_in_skip(lybctx->in, LYB_LAST_SIBLING(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200794
795 /* then read data */
aPiecek570d7ed2021-09-10 07:15:35 +0200796 lyb_read(NULL, LYB_LAST_SIBLING(lybctx).written, lybctx);
797 } while (LYB_LAST_SIBLING(lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200798}
799
800/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200801 * @brief Parse the context of anydata/anyxml node.
802 *
803 * @param[in] ctx libyang context.
804 * @param[in] data LYB data to parse.
805 * @param[out] tree Parsed tree.
806 * @return LY_ERR value.
807 */
808static LY_ERR
809lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
810{
811 LY_ERR ret;
812 uint32_t prev_lo;
813 struct ly_in *in;
814 struct lyd_ctx *lydctx = NULL;
815
816 *tree = NULL;
817
818 LY_CHECK_RET(ly_in_new_memory(data, &in));
819
820 /* turn logging off */
821 prev_lo = ly_log_options(0);
822
Michal Vasko56d88602021-07-15 16:37:59 +0200823 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 +0200824 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
825
826 /* turn logging on again */
827 ly_log_options(prev_lo);
828
829 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200830 if (lydctx) {
831 lydctx->free(lydctx);
832 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200833 if (ret) {
834 lyd_free_siblings(*tree);
835 *tree = NULL;
836 }
837 return ret;
838}
839
840/**
aPiecek37c493b2021-09-09 12:52:30 +0200841 * @brief Insert new node to @p parsed set.
842 *
843 * Also if needed, correct @p first_p.
844 *
845 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200846 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200847 * @param[in,out] node Parsed node to insertion.
848 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
849 * @param[out] parsed Set of all successfully parsed nodes.
850 * @return LY_ERR value.
851 */
852static void
853lyb_insert_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node *node, struct lyd_node **first_p,
854 struct ly_set *parsed)
855{
856 /* insert, keep first pointer correct */
857 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
858 while (!parent && (*first_p)->prev->next) {
859 *first_p = (*first_p)->prev;
860 }
861
862 /* rememeber a successfully parsed node */
863 if (parsed) {
864 ly_set_add(parsed, node, 1, NULL);
865 }
866}
867
868/**
869 * @brief Finish parsing the opaq node.
870 *
871 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200872 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200873 * @param[in] flags Node flags to set.
874 * @param[in,out] attr Attributes to be attached. Finally set to NULL.
875 * @param[in,out] node Parsed opaq node to finish.
876 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
877 * @param[out] parsed Set of all successfully parsed nodes.
878 * @return LY_ERR value.
879 */
880static void
881lyb_finish_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_attr **attr,
882 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
883{
884 struct lyd_attr *iter;
885
886 /* set flags */
887 (*node)->flags = flags;
888
889 /* add attributes */
890 assert(!(*node)->schema);
891 LY_LIST_FOR(*attr, iter) {
892 iter->parent = (struct lyd_node_opaq *)*node;
893 }
894 ((struct lyd_node_opaq *)*node)->attr = *attr;
895 *attr = NULL;
896
897 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
898 *node = NULL;
899}
900
901/**
902 * @brief Finish parsing the node.
903 *
904 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200905 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200906 * @param[in] flags Node flags to set.
907 * @param[in,out] meta Metadata to be attached. Finally set to NULL.
908 * @param[in,out] node Parsed node to finish.
909 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
910 * @param[out] parsed Set of all successfully parsed nodes.
911 * @return LY_ERR value.
912 */
913static void
914lyb_finish_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_meta **meta,
915 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
916{
917 struct lyd_meta *m;
918
919 /* set flags */
920 (*node)->flags = flags;
921
922 /* add metadata */
923 LY_LIST_FOR(*meta, m) {
924 m->parent = *node;
925 }
926 (*node)->meta = *meta;
927 *meta = NULL;
928
929 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
930 *node = NULL;
931}
932
933/**
aPiecek33fc6b02021-09-09 15:45:37 +0200934 * @brief Create term node and fill it with value.
935 *
936 * @param[in] lybctx LYB context.
937 * @param[in] snode Schema of the term node.
938 * @param[out] node Created term node.
939 * @return LY_ERR value.
940 */
941static LY_ERR
942lyb_create_term(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node **node)
943{
944 LY_ERR ret;
945 ly_bool dynamic;
946 uint8_t *term_value;
947 uint32_t term_value_len;
948
949 ret = lyb_read_term_value((struct lysc_node_leaf *)snode, &term_value, &term_value_len, lybctx->lybctx);
950 LY_CHECK_RET(ret);
951
952 dynamic = 1;
953 /* create node */
954 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode,
955 term_value, term_value_len, &dynamic, LY_VALUE_LYB,
956 NULL, LYD_HINT_DATA, node);
957 if (dynamic) {
958 free(term_value);
959 }
960 if (ret) {
961 lyd_free_tree(*node);
962 *node = NULL;
963 }
964
965 return ret;
966}
967
968/**
aPiecek0e2e1052021-09-09 15:48:27 +0200969 * @brief Validate inner node, autodelete default values nad create implicit nodes.
970 *
971 * @param[in,out] lybctx LYB context.
972 * @param[in] snode Schema of the inner node.
973 * @param[in] node Parsed inner node.
974 * @return LY_ERR value.
975 */
976static LY_ERR
977lyb_validate_node_inner(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node *node)
978{
979 LY_ERR ret = LY_SUCCESS;
980 uint32_t impl_opts;
981
982 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
983 /* new node validation, autodelete CANNOT occur, all nodes are new */
984 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
985 LY_CHECK_RET(ret);
986
987 /* add any missing default children */
988 impl_opts = (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0;
989 ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL,
990 NULL, &lybctx->node_when, &lybctx->node_exts,
991 &lybctx->node_types, impl_opts, NULL);
992 LY_CHECK_RET(ret);
993 }
994
995 return ret;
996}
997
998/**
aPiecek821cf732021-09-09 15:37:28 +0200999 * @brief Parse opaq node.
1000 *
1001 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001002 * @param[in] parent Data parent of the sibling.
aPiecek821cf732021-09-09 15:37:28 +02001003 * @param[in,out] first_p First top-level sibling.
1004 * @param[out] parsed Set of all successfully parsed nodes.
1005 * @return LY_ERR value.
1006 */
1007static LY_ERR
1008lyb_parse_node_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
1009{
1010 LY_ERR ret;
1011 struct lyd_node *node = NULL;
1012 struct lyd_attr *attr = NULL;
1013 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
1014 ly_bool dynamic = 0;
1015 LY_VALUE_FORMAT format = 0;
1016 void *val_prefix_data = NULL;
1017 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1018 uint32_t flags;
1019
aPiecek821cf732021-09-09 15:37:28 +02001020 /* parse opaq node attributes */
1021 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
1022 LY_CHECK_GOTO(ret, cleanup);
1023
1024 /* read flags */
1025 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
1026
1027 /* parse prefix */
1028 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
1029 LY_CHECK_GOTO(ret, cleanup);
1030
1031 /* parse module key */
1032 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
1033 LY_CHECK_GOTO(ret, cleanup);
1034
1035 /* parse name */
1036 ret = lyb_read_string(&name, 1, lybctx->lybctx);
1037 LY_CHECK_GOTO(ret, cleanup);
1038
1039 /* parse value */
1040 ret = lyb_read_string(&value, 1, lybctx->lybctx);
1041 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
1042 dynamic = 1;
1043
1044 /* parse format */
1045 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
1046
1047 /* parse value prefixes */
1048 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
1049 LY_CHECK_GOTO(ret, cleanup);
1050
aPiecek570d7ed2021-09-10 07:15:35 +02001051 if (!(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
1052 if (lybctx->lybctx->in->current[0] == 0) {
1053 /* opaq node has no children */
1054 lyb_read(NULL, 1, lybctx->lybctx);
1055 } else {
1056 /* skip children */
1057 ret = lyb_read_start_siblings(lybctx->lybctx);
1058 LY_CHECK_RET(ret);
1059 lyb_skip_siblings(lybctx->lybctx);
1060 ret = lyb_read_stop_siblings(lybctx->lybctx);
1061 LY_CHECK_RET(ret);
1062 }
1063
1064 goto cleanup;
1065 }
1066
aPiecek821cf732021-09-09 15:37:28 +02001067 /* create node */
1068 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
1069 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
1070 LY_CHECK_GOTO(ret, cleanup);
1071
1072 /* process children */
aPiecek570d7ed2021-09-10 07:15:35 +02001073 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1074 LY_CHECK_GOTO(ret, cleanup);
aPiecek821cf732021-09-09 15:37:28 +02001075
1076 /* register parsed opaq node */
1077 lyb_finish_opaq(lybctx, parent, flags, &attr, &node, first_p, parsed);
1078 assert(!attr && !node);
1079
1080cleanup:
1081 free(prefix);
1082 free(module_key);
1083 free(name);
1084 if (dynamic) {
1085 free(value);
1086 }
1087 lyd_free_attr_siblings(ctx, attr);
1088 lyd_free_tree(node);
1089
1090 return ret;
1091}
1092
aPiecek18457d72021-09-09 15:52:20 +02001093/**
1094 * @brief Parse anydata or anyxml node.
1095 *
1096 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001097 * @param[in] parent Data parent of the sibling.
aPiecek18457d72021-09-09 15:52:20 +02001098 * @param[in] snode Schema of the node to be parsed.
1099 * @param[in,out] first_p First top-level sibling.
1100 * @param[out] parsed Set of all successfully parsed nodes.
1101 * @return LY_ERR value.
1102 */
1103static LY_ERR
1104lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1105 struct lyd_node **first_p, struct ly_set *parsed)
1106{
1107 LY_ERR ret;
1108 struct lyd_node *node = NULL, *tree;
1109 struct lyd_meta *meta = NULL;
1110 LYD_ANYDATA_VALUETYPE value_type;
1111 char *value = NULL;
1112 const char *val_dict;
1113 uint32_t flags;
1114 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1115
1116 /* read necessary basic data */
aPiecek570d7ed2021-09-10 07:15:35 +02001117 lyb_parse_node_header(lybctx, &flags, &meta);
aPiecek18457d72021-09-09 15:52:20 +02001118
1119 /* parse value type */
1120 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
1121 if (value_type == LYD_ANYDATA_DATATREE) {
1122 /* invalid situation */
1123 LOGINT(ctx);
1124 ret = LY_EINT;
1125 goto error;
1126 }
1127
1128 /* read anydata content */
aPiecek570d7ed2021-09-10 07:15:35 +02001129 ret = lyb_read_string(&value, 1, lybctx->lybctx);
aPiecek18457d72021-09-09 15:52:20 +02001130 LY_CHECK_GOTO(ret, error);
1131
1132 if (value_type == LYD_ANYDATA_LYB) {
1133 /* try to parse LYB into a data tree */
1134 if (!lyb_parse_any_content(ctx, value, &tree)) {
1135 /* successfully parsed */
1136 free(value);
1137 value = (char *)tree;
1138 value_type = LYD_ANYDATA_DATATREE;
1139 }
1140 }
1141
1142 /* create the node */
1143 switch (value_type) {
1144 case LYD_ANYDATA_LYB:
1145 case LYD_ANYDATA_DATATREE:
1146 /* use the value directly */
1147 ret = lyd_create_any(snode, value, value_type, 1, &node);
1148 LY_CHECK_GOTO(ret, error);
1149
1150 break;
1151 case LYD_ANYDATA_STRING:
1152 case LYD_ANYDATA_XML:
1153 case LYD_ANYDATA_JSON:
1154 /* value is expected to be in the dictionary */
1155 ret = lydict_insert_zc(ctx, value, &val_dict);
1156 LY_CHECK_GOTO(ret, error);
1157
1158 /* use the value in the dictionary */
1159 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
1160 if (ret) {
1161 lydict_remove(ctx, val_dict);
1162 goto error;
1163 }
1164 break;
1165 default:
1166 LOGINT(ctx);
1167 ret = LY_EINT;
1168 goto error;
1169 }
1170
1171 /* register parsed anydata node */
1172 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1173
1174 return LY_SUCCESS;
1175
1176error:
1177 free(value);
1178 lyd_free_meta_siblings(meta);
1179 lyd_free_tree(node);
1180 return ret;
1181}
aPiecek821cf732021-09-09 15:37:28 +02001182
1183/**
aPiecek37c493b2021-09-09 12:52:30 +02001184 * @brief Parse header for non-opaq node.
1185 *
1186 * @param[in] lybctx LYB context.
1187 * @param[out] flags Parsed node flags.
1188 * @param[out] meta Parsed metadata of the node.
1189 * @return LY_ERR value.
1190 */
1191static LY_ERR
1192lyb_parse_node_header(struct lyd_lyb_ctx *lybctx, uint32_t *flags, struct lyd_meta **meta)
1193{
1194 LY_ERR ret;
1195
1196 /* create and read metadata */
1197 ret = lyb_parse_metadata(lybctx, meta);
1198 LY_CHECK_RET(ret);
1199
1200 /* read flags */
1201 lyb_read_number(flags, sizeof *flags, sizeof *flags, lybctx->lybctx);
1202
1203 return ret;
1204}
1205
1206/**
aPiecek570d7ed2021-09-10 07:15:35 +02001207 * @brief Parse LYB node with children.
aPiecek37c493b2021-09-09 12:52:30 +02001208 *
1209 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001210 * @param[in] parent Data parent of the sibling, must be set if @p first is not.
1211 * @param[in] snode Schema of the node to be parsed.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001212 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1213 * @param[out] parsed Set of all successfully parsed nodes.
Michal Vasko60ea6352020-06-29 13:39:39 +02001214 * @return LY_ERR value.
1215 */
1216static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +02001217lyb_parse_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1218 struct lyd_node **first_p, struct ly_set *parsed)
Michal Vasko60ea6352020-06-29 13:39:39 +02001219{
1220 LY_ERR ret = LY_SUCCESS;
aPiecek18457d72021-09-09 15:52:20 +02001221 struct lyd_node *node = NULL;
aPiecek37c493b2021-09-09 12:52:30 +02001222 struct lyd_meta *meta = NULL;
aPiecek33fc6b02021-09-09 15:45:37 +02001223 uint32_t flags;
Radek Krejci1798aae2020-07-14 13:26:06 +02001224 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001225
aPiecek37c493b2021-09-09 12:52:30 +02001226 if (!snode) {
aPiecek821cf732021-09-09 15:37:28 +02001227 ret = lyb_parse_node_opaq(lybctx, parent, first_p, parsed);
Michal Vasko60ea6352020-06-29 13:39:39 +02001228 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001229 } else if (snode->nodetype & LYD_NODE_TERM) {
aPiecek570d7ed2021-09-10 07:15:35 +02001230 /* read necessary basic data */
aPiecek37c493b2021-09-09 12:52:30 +02001231 ret = lyb_parse_node_header(lybctx, &flags, &meta);
1232 LY_CHECK_GOTO(ret, cleanup);
1233
aPiecek33fc6b02021-09-09 15:45:37 +02001234 /* read value of term node and create it */
1235 ret = lyb_create_term(lybctx, snode, &node);
Radek Krejci1798aae2020-07-14 13:26:06 +02001236 LY_CHECK_GOTO(ret, cleanup);
aPiecek37c493b2021-09-09 12:52:30 +02001237
aPiecek37c493b2021-09-09 12:52:30 +02001238 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
Michal Vasko60ea6352020-06-29 13:39:39 +02001239 } else if (snode->nodetype & LYD_NODE_INNER) {
aPiecek570d7ed2021-09-10 07:15:35 +02001240 /* read necessary basic data */
aPiecek37c493b2021-09-09 12:52:30 +02001241 ret = lyb_parse_node_header(lybctx, &flags, &meta);
1242 LY_CHECK_GOTO(ret, cleanup);
1243
Michal Vasko60ea6352020-06-29 13:39:39 +02001244 /* create node */
1245 ret = lyd_create_inner(snode, &node);
1246 LY_CHECK_GOTO(ret, cleanup);
1247
1248 /* process children */
aPiecek570d7ed2021-09-10 07:15:35 +02001249 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1250 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001251
aPiecek0e2e1052021-09-09 15:48:27 +02001252 /* additional procedure for inner node */
1253 ret = lyb_validate_node_inner(lybctx, snode, node);
1254 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001255
Michal Vasko751cb4d2020-07-14 12:25:28 +02001256 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001257 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +02001258 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +02001259 }
aPiecek37c493b2021-09-09 12:52:30 +02001260
aPiecek570d7ed2021-09-10 07:15:35 +02001261 /* register parsed node */
aPiecek37c493b2021-09-09 12:52:30 +02001262 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
Michal Vasko60ea6352020-06-29 13:39:39 +02001263 } else if (snode->nodetype & LYD_NODE_ANY) {
aPiecek18457d72021-09-09 15:52:20 +02001264 ret = lyb_parse_node_any(lybctx, parent, snode, first_p, parsed);
aPiecek37c493b2021-09-09 12:52:30 +02001265 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001266 } else {
aPiecek37c493b2021-09-09 12:52:30 +02001267 LOGINT(ctx);
1268 ret = LY_EINT;
1269 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001270 }
1271
Michal Vasko60ea6352020-06-29 13:39:39 +02001272cleanup:
Michal Vasko3a41dff2020-07-15 14:30:28 +02001273 lyd_free_meta_siblings(meta);
Michal Vasko60ea6352020-06-29 13:39:39 +02001274 lyd_free_tree(node);
1275 return ret;
1276}
1277
1278/**
aPiecek570d7ed2021-09-10 07:15:35 +02001279 * @brief Parse siblings (@ref lyb_print_siblings()).
1280 *
1281 * @param[in] lybctx LYB context.
1282 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
1283 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1284 * @param[out] parsed Set of all successfully parsed nodes.
1285 * @return LY_ERR value.
1286 */
1287static LY_ERR
1288lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
1289 struct ly_set *parsed)
1290{
1291 LY_ERR ret;
1292 const struct lysc_node *snode;
1293 const struct lys_module *mod;
1294 ly_bool top_level;
1295
1296 if (lybctx->lybctx->in->current[0] == 0) {
1297 lyb_read(NULL, 1, lybctx->lybctx);
1298 return LY_SUCCESS;
1299 }
1300
1301 top_level = !LY_ARRAY_COUNT(lybctx->lybctx->siblings);
1302
1303 /* register a new siblings */
1304 ret = lyb_read_start_siblings(lybctx->lybctx);
1305 LY_CHECK_RET(ret);
1306
1307 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
1308 if (!parent || !parent->schema) {
1309 /* top-level or opaque, read module name */
1310 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
1311 LY_CHECK_RET(ret);
1312
1313 /* read hash, find the schema node starting from mod */
1314 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
1315 } else {
1316 /* read hash, find the schema node starting from parent schema */
1317 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
1318 }
1319 LY_CHECK_RET(ret);
1320
1321 lyb_parse_node(lybctx, parent, snode, first_p, parsed);
1322 LY_CHECK_RET(ret);
1323
1324 if (top_level && !(lybctx->int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1325 break;
1326 }
1327 }
1328
1329 /* end the siblings */
1330 ret = lyb_read_stop_siblings(lybctx->lybctx);
1331 LY_CHECK_RET(ret);
1332
1333 return ret;
1334}
1335
1336/**
Michal Vasko60ea6352020-06-29 13:39:39 +02001337 * @brief Parse used YANG data models.
1338 *
1339 * @param[in] lybctx LYB context.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001340 * @param[in] parse_options Flag with options for parsing.
Michal Vasko60ea6352020-06-29 13:39:39 +02001341 * @return LY_ERR value.
1342 */
1343static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001344lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001345{
1346 LY_ERR ret;
1347 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001348 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001349
1350 /* read model count */
1351 lyb_read_number(&count, sizeof count, 2, lybctx);
1352
1353 if (count) {
1354 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1355
1356 /* read modules */
1357 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001358 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001359 LY_CHECK_RET(ret);
1360 LY_ARRAY_INCREMENT(lybctx->models);
1361 }
1362 }
1363
1364 return LY_SUCCESS;
1365}
1366
1367/**
1368 * @brief Parse LYB magic number.
1369 *
1370 * @param[in] lybctx LYB context.
1371 * @return LY_ERR value.
1372 */
1373static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001374lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001375{
1376 char magic_byte = 0;
1377
1378 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1379 if (magic_byte != 'l') {
1380 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1381 return LY_EINVAL;
1382 }
1383
1384 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1385 if (magic_byte != 'y') {
1386 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1387 return LY_EINVAL;
1388 }
1389
1390 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1391 if (magic_byte != 'b') {
1392 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1393 return LY_EINVAL;
1394 }
1395
1396 return LY_SUCCESS;
1397}
1398
1399/**
1400 * @brief Parse LYB header.
1401 *
1402 * @param[in] lybctx LYB context.
1403 * @return LY_ERR value.
1404 */
1405static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001406lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001407{
1408 uint8_t byte = 0;
1409
1410 /* version, future flags */
1411 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1412
1413 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1414 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001415 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001416 return LY_EINVAL;
1417 }
1418
1419 return LY_SUCCESS;
1420}
1421
Michal Vasko02ed9d82021-07-15 14:58:04 +02001422static LY_ERR
1423_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1424 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 +01001425 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001426{
Michal Vaskoe0665742021-02-11 11:08:44 +01001427 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001428 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001429
Michal Vaskoe0665742021-02-11 11:08:44 +01001430 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1431 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001432
Radek Krejci1798aae2020-07-14 13:26:06 +02001433 lybctx = calloc(1, sizeof *lybctx);
1434 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1435 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001436 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001437
Radek Krejci1798aae2020-07-14 13:26:06 +02001438 lybctx->lybctx->in = in;
1439 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001440 lybctx->parse_opts = parse_opts;
1441 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001442 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001443 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001444 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001445
1446 /* find the operation node if it exists already */
1447 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1448
Michal Vasko60ea6352020-06-29 13:39:39 +02001449 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001450 rc = lyb_parse_magic_number(lybctx->lybctx);
1451 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001452
1453 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001454 rc = lyb_parse_header(lybctx->lybctx);
1455 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001456
1457 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001458 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1459 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001460
aPiecek570d7ed2021-09-10 07:15:35 +02001461 /* read sibling(s) */
1462 rc = lyb_parse_siblings(lybctx, parent, first_p, parsed);
1463 LY_CHECK_GOTO(rc, cleanup);
Michal Vaskoe0665742021-02-11 11:08:44 +01001464
1465 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1466 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1467 rc = LY_EVALID;
1468 goto cleanup;
1469 }
1470 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1471 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1472 rc = LY_EVALID;
1473 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001474 }
1475
1476 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001477 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001478
Michal Vasko60ea6352020-06-29 13:39:39 +02001479cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001480 /* there should be no unres stored if validation should be skipped */
1481 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1482 !lybctx->node_when.count));
1483
1484 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001485 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001486 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001487 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001488 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001489 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001490}
1491
Michal Vasko02ed9d82021-07-15 14:58:04 +02001492LY_ERR
1493lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1494 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1495 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
1496{
1497 uint32_t int_opts;
1498
1499 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1500 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1501
1502 switch (data_type) {
1503 case LYD_TYPE_DATA_YANG:
1504 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1505 break;
1506 case LYD_TYPE_RPC_YANG:
1507 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1508 break;
1509 case LYD_TYPE_NOTIF_YANG:
1510 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1511 break;
1512 case LYD_TYPE_REPLY_YANG:
1513 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1514 break;
1515 default:
1516 LOGINT(ctx);
1517 return LY_EINT;
1518 }
1519
1520 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1521}
1522
Michal Vasko60ea6352020-06-29 13:39:39 +02001523API int
1524lyd_lyb_data_length(const char *data)
1525{
1526 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001527 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001528 int count, i;
1529 size_t len;
1530 uint8_t buf[LYB_SIZE_MAX];
1531
1532 if (!data) {
1533 return -1;
1534 }
1535
Radek Krejci1798aae2020-07-14 13:26:06 +02001536 lybctx = calloc(1, sizeof *lybctx);
1537 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1538 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001539 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001540
1541 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001542 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001543 LY_CHECK_GOTO(ret, cleanup);
1544
1545 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001546 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001547 LY_CHECK_GOTO(ret, cleanup);
1548
1549 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001550 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001551
1552 /* read all models */
1553 for (i = 0; i < count; ++i) {
1554 /* module name length */
1555 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001556 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001557
1558 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001559 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001560
1561 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001562 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001563 }
1564
aPiecek570d7ed2021-09-10 07:15:35 +02001565 if (lybctx->in->current[0]) {
1566 /* register a new sibling */
1567 ret = lyb_read_start_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001568 LY_CHECK_GOTO(ret, cleanup);
1569
1570 /* skip it */
aPiecek570d7ed2021-09-10 07:15:35 +02001571 lyb_skip_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001572
aPiecek570d7ed2021-09-10 07:15:35 +02001573 /* sibling finished */
1574 ret = lyb_read_stop_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001575 LY_CHECK_GOTO(ret, cleanup);
aPiecek570d7ed2021-09-10 07:15:35 +02001576 } else {
1577 lyb_read(NULL, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001578 }
1579
1580 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001581 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001582
1583cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001584 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001585
Radek Krejci1798aae2020-07-14 13:26:06 +02001586 ly_in_free(lybctx->in, 0);
1587 lylyb_ctx_free(lybctx);
1588
Michal Vasko63f3d842020-07-08 10:10:14 +02001589 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001590}