blob: 8af9988fb9fabdbbd10d2d0cda5faea5dac29bce [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/**
227 * @brief Stop the current subtree - change LYB context state.
228 *
229 * @param[in] lybctx LYB context.
230 * @return LY_ERR value.
231 */
232static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200233lyb_read_stop_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200234{
235 if (LYB_LAST_SUBTREE(lybctx).written) {
236 LOGINT_RET(lybctx->ctx);
237 }
238
239 LY_ARRAY_DECREMENT(lybctx->subtrees);
240 return LY_SUCCESS;
241}
242
243/**
244 * @brief Start a new subtree - change LYB context state but also read the expected metadata.
245 *
246 * @param[in] lybctx LYB context.
247 * @return LY_ERR value.
248 */
249static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200250lyb_read_start_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200251{
252 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200253 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200254
Radek Krejcic7d13e32020-12-09 12:32:24 +0100255 u = LY_ARRAY_COUNT(lybctx->subtrees);
Michal Vasko60ea6352020-06-29 13:39:39 +0200256 if (u == lybctx->subtree_size) {
257 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
258 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
259 }
260
Michal Vasko63f3d842020-07-08 10:10:14 +0200261 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200262
263 LY_ARRAY_INCREMENT(lybctx->subtrees);
264 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
265 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
266 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
267
Michal Vasko60ea6352020-06-29 13:39:39 +0200268 return LY_SUCCESS;
269}
270
271/**
272 * @brief Parse YANG model info.
273 *
274 * @param[in] lybctx LYB context.
275 * @param[out] mod Parsed module.
276 * @return LY_ERR value.
277 */
278static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200279lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
Michal Vasko60ea6352020-06-29 13:39:39 +0200280{
281 LY_ERR ret = LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100282 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
Michal Vasko60ea6352020-06-29 13:39:39 +0200283 uint16_t rev;
284
285 /* model name */
286 ret = lyb_read_string(&mod_name, 1, lybctx);
287 LY_CHECK_GOTO(ret, cleanup);
288
289 /* revision */
290 lyb_read_number(&rev, sizeof rev, 2, lybctx);
291
292 if (!mod_name[0]) {
293 /* opaq node, no module */
294 *mod = NULL;
295 goto cleanup;
296 }
297
298 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100299 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
300 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko60ea6352020-06-29 13:39:39 +0200301 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
Radek Krejci1798aae2020-07-14 13:26:06 +0200302 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200303 /* try to use an updated module */
304 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
305 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
306 /* not an implemented module in a newer revision */
307 *mod = NULL;
308 }
309 }
310 } else {
311 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
312 }
313 /* TODO data_clb supported?
314 if (lybctx->ctx->data_clb) {
315 if (!*mod) {
316 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
317 } else if (!(*mod)->implemented) {
318 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
319 }
320 }*/
321
322 if (!*mod || !(*mod)->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200323 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200324 if (!*mod) {
325 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +0200326 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200327 } else if (!(*mod)->implemented) {
328 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko69730152020-10-09 16:30:07 +0200329 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200330 }
331 ret = LY_EINVAL;
332 goto cleanup;
333 }
334
335 }
336
Michal Vasko85d9edc2021-04-22 09:15:05 +0200337 if (*mod) {
338 /* fill cached hashes, if not already */
339 lyb_cache_module_hash(*mod);
340 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200341
Michal Vasko60ea6352020-06-29 13:39:39 +0200342cleanup:
343 free(mod_name);
344 return ret;
345}
346
347/**
348 * @brief Parse YANG node metadata.
349 *
350 * @param[in] lybctx LYB context.
Michal Vasko60ea6352020-06-29 13:39:39 +0200351 * @param[out] meta Parsed metadata.
352 * @return LY_ERR value.
353 */
354static LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200355lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200356{
357 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200358 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200359 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200360 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200361 const struct lys_module *mod;
362
363 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200364 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200365
366 /* read attributes */
367 for (i = 0; i < count; ++i) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200368 ret = lyb_read_start_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200369 LY_CHECK_GOTO(ret, cleanup);
370
371 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100372 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200373 LY_CHECK_GOTO(ret, cleanup);
374
375 if (!mod) {
376 /* skip it */
377 do {
Radek Krejci1798aae2020-07-14 13:26:06 +0200378 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx->lybctx).written, lybctx->lybctx);
379 } while (LYB_LAST_SUBTREE(lybctx->lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200380 goto stop_subtree;
381 }
382
383 /* meta name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200384 ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200385 LY_CHECK_GOTO(ret, cleanup);
386
387 /* meta value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200388 ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200389 LY_CHECK_GOTO(ret, cleanup);
390 dynamic = 1;
391
392 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200393 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 +0200394 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200395
396 /* free strings */
397 free(meta_name);
398 meta_name = NULL;
399 if (dynamic) {
400 free(meta_value);
401 dynamic = 0;
402 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200403
Radek Krejci1798aae2020-07-14 13:26:06 +0200404 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200405
406stop_subtree:
Radek Krejci1798aae2020-07-14 13:26:06 +0200407 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200408 LY_CHECK_GOTO(ret, cleanup);
409 }
410
411cleanup:
412 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200413 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200414 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200415 *meta = NULL;
416 }
417 return ret;
418}
419
420/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100421 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200422 *
423 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100424 * @param[in] format Prefix data format.
425 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200426 * @return LY_ERR value.
427 */
428static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200429lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200430{
431 LY_ERR ret = LY_SUCCESS;
432 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100433 struct ly_set *set = NULL;
434 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200435
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100436 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200437 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100438 /* read count */
439 lyb_read(&count, 1, lybctx);
440 if (!count) {
441 return LY_SUCCESS;
442 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200443
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100444 /* read all NS elements */
445 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200446
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100447 for (i = 0; i < count; ++i) {
448 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200449
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100450 /* prefix */
451 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
452
453 /* namespace */
454 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
455
456 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
457 ns = NULL;
458 }
459
460 *prefix_data = set;
461 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200462 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200463 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100464 /* nothing stored */
465 break;
466 default:
467 LOGINT(lybctx->ctx);
468 ret = LY_EINT;
469 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200470 }
471
472cleanup:
473 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100474 ly_free_prefix_data(format, set);
475 if (ns) {
476 free(ns->prefix);
477 free(ns->uri);
478 free(ns);
479 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200480 }
481 return ret;
482}
483
484/**
485 * @brief Parse opaque attributes.
486 *
487 * @param[in] lybctx LYB context.
488 * @param[out] attr Parsed attributes.
489 * @return LY_ERR value.
490 */
491static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200492lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200493{
494 LY_ERR ret = LY_SUCCESS;
495 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200496 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200497 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200498 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200499 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100500 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200501
502 /* read count */
503 lyb_read(&count, 1, lybctx);
504
505 /* read attributes */
506 for (i = 0; i < count; ++i) {
507 ret = lyb_read_start_subtree(lybctx);
508 LY_CHECK_GOTO(ret, cleanup);
509
Michal Vasko0fdcd242020-11-11 19:12:30 +0100510 /* prefix, may be empty */
Michal Vasko60ea6352020-06-29 13:39:39 +0200511 ret = lyb_read_string(&prefix, 1, lybctx);
512 LY_CHECK_GOTO(ret, cleanup);
513 if (!prefix[0]) {
514 free(prefix);
515 prefix = NULL;
516 }
517
518 /* namespace, may be empty */
Radek Krejci1798aae2020-07-14 13:26:06 +0200519 ret = lyb_read_string(&module_name, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200520 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200521 if (!module_name[0]) {
522 free(module_name);
523 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200524 }
525
526 /* name */
527 ret = lyb_read_string(&name, 1, lybctx);
528 LY_CHECK_GOTO(ret, cleanup);
529
Michal Vasko60ea6352020-06-29 13:39:39 +0200530 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200531 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200532
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100533 /* value prefixes */
534 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
535 LY_CHECK_GOTO(ret, cleanup);
536
Michal Vasko60ea6352020-06-29 13:39:39 +0200537 /* value */
538 ret = lyb_read_string(&value, 0, lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100539 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200540 dynamic = 1;
541
542 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100543 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200544 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200545 LY_CHECK_GOTO(ret, cleanup);
546
547 free(prefix);
548 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200549 free(module_name);
550 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200551 free(name);
552 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200553 assert(!dynamic);
554 value = NULL;
555
556 if (!*attr) {
557 *attr = attr2;
558 }
559
560 ret = lyb_read_stop_subtree(lybctx);
561 LY_CHECK_GOTO(ret, cleanup);
562 }
563
564cleanup:
565 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200566 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200567 free(name);
568 if (dynamic) {
569 free(value);
570 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200571 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200572 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200573 *attr = NULL;
574 }
575 return ret;
576}
577
578/**
579 * @brief Check whether a schema node matches a hash(es).
580 *
581 * @param[in] sibling Schema node to check.
582 * @param[in] hash Hash array to check.
583 * @param[in] hash_count Number of hashes in @p hash.
584 * @return non-zero if matches,
585 * @return 0 if not.
586 */
587static int
588lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
589{
590 LYB_HASH sibling_hash;
591 uint8_t i;
592
593 /* compare all the hashes starting from collision ID 0 */
594 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200595 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200596 if (sibling_hash != hash[i]) {
597 return 0;
598 }
599 }
600
601 return 1;
602}
603
604/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200605 * @brief Parse schema node hash.
606 *
607 * @param[in] lybctx LYB context.
608 * @param[in] sparent Schema parent, must be set if @p mod is not.
609 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
610 * @param[out] snode Parsed found schema node, may be NULL if opaque.
611 * @return LY_ERR value.
612 */
613static LY_ERR
614lyb_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 +0200615 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200616{
617 LY_ERR ret;
618 uint8_t i, j;
619 const struct lysc_node *sibling;
620 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200621 uint32_t getnext_opts;
Michal Vasko60ea6352020-06-29 13:39:39 +0200622
623 *snode = NULL;
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100624 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200625
626 /* read the first hash */
Radek Krejci1798aae2020-07-14 13:26:06 +0200627 lyb_read(&hash[0], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200628
629 if (!hash[0]) {
630 /* opaque node */
631 return LY_SUCCESS;
632 }
633
634 /* based on the first hash read all the other ones, if any */
635 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
636 if (i > LYB_HASH_BITS) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200637 LOGINT_RET(lybctx->lybctx->ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200638 }
639 }
640
641 /* move the first hash on its accurate position */
642 hash[i] = hash[0];
643
644 /* read the rest of hashes */
645 for (j = i; j; --j) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200646 lyb_read(&hash[j - 1], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200647
648 /* correct collision ID */
649 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
650 /* preceded with zeros */
651 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
652 }
653
654 /* find our node with matching hashes */
655 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100656 while (1) {
657 if (!sparent && lybctx->ext) {
658 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
659 } else {
660 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
661 }
662 if (!sibling) {
663 break;
664 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200665 /* skip schema nodes from models not present during printing */
Michal Vasko69730152020-10-09 16:30:07 +0200666 if (lyb_has_schema_model(sibling, lybctx->lybctx->models) &&
667 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200668 /* match found */
669 break;
670 }
671 }
672
Michal Vaskoe0665742021-02-11 11:08:44 +0100673 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100674 if (lybctx->ext) {
675 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
676 lybctx->ext->def->name);
677 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100678 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200679 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200680 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100681 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200682 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200683 }
684 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200685 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200686 return ret;
687 }
688
689 *snode = sibling;
690 return LY_SUCCESS;
691}
692
693/**
694 * @brief Read until the end of the current subtree.
695 *
696 * @param[in] lybctx LYB context.
697 */
698static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200699lyb_skip_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200700{
Michal Vasko60ea6352020-06-29 13:39:39 +0200701 do {
702 /* first skip any meta information inside */
Michal Vasko63f3d842020-07-08 10:10:14 +0200703 ly_in_skip(lybctx->in, LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200704
705 /* then read data */
706 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
707 } while (LYB_LAST_SUBTREE(lybctx).written);
708}
709
710/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200711 * @brief Parse the context of anydata/anyxml node.
712 *
713 * @param[in] ctx libyang context.
714 * @param[in] data LYB data to parse.
715 * @param[out] tree Parsed tree.
716 * @return LY_ERR value.
717 */
718static LY_ERR
719lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
720{
721 LY_ERR ret;
722 uint32_t prev_lo;
723 struct ly_in *in;
724 struct lyd_ctx *lydctx = NULL;
725
726 *tree = NULL;
727
728 LY_CHECK_RET(ly_in_new_memory(data, &in));
729
730 /* turn logging off */
731 prev_lo = ly_log_options(0);
732
Michal Vasko56d88602021-07-15 16:37:59 +0200733 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 +0200734 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
735
736 /* turn logging on again */
737 ly_log_options(prev_lo);
738
739 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200740 if (lydctx) {
741 lydctx->free(lydctx);
742 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200743 if (ret) {
744 lyd_free_siblings(*tree);
745 *tree = NULL;
746 }
747 return ret;
748}
749
750/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200751 * @brief Parse LYB subtree.
752 *
753 * @param[in] lybctx LYB context.
754 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
755 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
756 * @return LY_ERR value.
757 */
758static LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100759lyb_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 +0200760{
761 LY_ERR ret = LY_SUCCESS;
762 struct lyd_node *node = NULL, *tree;
763 const struct lys_module *mod;
764 const struct lysc_node *snode = NULL;
765 struct lyd_meta *meta = NULL, *m;
Radek Krejci1798aae2020-07-14 13:26:06 +0200766 struct lyd_attr *attr = NULL, *a;
Michal Vasko60ea6352020-06-29 13:39:39 +0200767 LYD_ANYDATA_VALUETYPE value_type;
Radek Krejci1798aae2020-07-14 13:26:06 +0200768 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
Michal Vasko9afe3df2021-02-05 16:33:50 +0100769 const char *val_dict;
Radek Krejci857189e2020-09-01 13:26:36 +0200770 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200771 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100772 void *val_prefix_data = NULL;
Michal Vasko02ed9d82021-07-15 14:58:04 +0200773 uint32_t flags;
Radek Krejci1798aae2020-07-14 13:26:06 +0200774 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +0200775
776 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200777 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200778
Michal Vaskof4b4d002021-08-23 12:16:02 +0200779 if (!parent || !parent->schema) {
780 /* top-level or opaque, read module name */
Michal Vaskoe0665742021-02-11 11:08:44 +0100781 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200782 LY_CHECK_GOTO(ret, cleanup);
783
784 /* read hash, find the schema node starting from mod */
785 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
786 LY_CHECK_GOTO(ret, cleanup);
787 } else {
788 /* read hash, find the schema node starting from parent schema */
789 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
790 LY_CHECK_GOTO(ret, cleanup);
791 }
792
Michal Vaskoe0665742021-02-11 11:08:44 +0100793 if (!snode && !(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200794 /* unknown data, skip them */
Radek Krejci1798aae2020-07-14 13:26:06 +0200795 lyb_skip_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200796 goto stop_subtree;
Radek Krejci0f969882020-08-21 16:56:47 +0200797 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200798
799 /* create metadata/attributes */
800 if (snode) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200801 ret = lyb_parse_metadata(lybctx, &meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200802 LY_CHECK_GOTO(ret, cleanup);
803 } else {
Radek Krejci1798aae2020-07-14 13:26:06 +0200804 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200805 LY_CHECK_GOTO(ret, cleanup);
806 }
807
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100808 /* read flags */
809 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
810
Michal Vasko60ea6352020-06-29 13:39:39 +0200811 if (!snode) {
812 /* parse prefix */
Radek Krejci1798aae2020-07-14 13:26:06 +0200813 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200814 LY_CHECK_GOTO(ret, cleanup);
815
Radek Krejci1798aae2020-07-14 13:26:06 +0200816 /* parse module key */
817 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200818 LY_CHECK_GOTO(ret, cleanup);
819
820 /* parse name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200821 ret = lyb_read_string(&name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200822 LY_CHECK_GOTO(ret, cleanup);
823
Michal Vaskoffc92bf2021-06-21 08:15:14 +0200824 /* parse value */
825 ret = lyb_read_string(&value, 1, lybctx->lybctx);
826 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
827 dynamic = 1;
828
Michal Vasko60ea6352020-06-29 13:39:39 +0200829 /* parse format */
Michal Vasko403beac2021-08-24 08:27:52 +0200830 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200831
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100832 /* parse value prefixes */
833 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
834 LY_CHECK_GOTO(ret, cleanup);
835
Michal Vasko60ea6352020-06-29 13:39:39 +0200836 /* create node */
Michal Vasko501af032020-11-11 20:27:44 +0100837 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
838 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200839 LY_CHECK_GOTO(ret, cleanup);
840
841 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200842 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100843 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200844 LY_CHECK_GOTO(ret, cleanup);
845 }
846 } else if (snode->nodetype & LYD_NODE_TERM) {
847 /* parse value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200848 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200849 LY_CHECK_GOTO(ret, cleanup);
850 dynamic = 1;
851
852 /* create node */
Radek Krejci8df109d2021-04-23 12:19:08 +0200853 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode, value, ly_strlen(value), &dynamic, LY_VALUE_JSON,
Michal Vasko69730152020-10-09 16:30:07 +0200854 NULL, LYD_HINT_DATA, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200855 if (dynamic) {
856 free(value);
857 dynamic = 0;
858 }
859 value = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200860 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200861 } else if (snode->nodetype & LYD_NODE_INNER) {
862 /* create node */
863 ret = lyd_create_inner(snode, &node);
864 LY_CHECK_GOTO(ret, cleanup);
865
866 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200867 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100868 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200869 LY_CHECK_GOTO(ret, cleanup);
870 }
871
Michal Vaskoe0665742021-02-11 11:08:44 +0100872 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200873 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vaskoe0665742021-02-11 11:08:44 +0100874 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200875 LY_CHECK_GOTO(ret, cleanup);
876
877 /* add any missing default children */
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200878 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 +0100879 &lybctx->node_types, (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200880 LY_CHECK_GOTO(ret, cleanup);
881 }
882
Michal Vasko751cb4d2020-07-14 12:25:28 +0200883 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200884 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +0200885 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +0200886 }
887 } else if (snode->nodetype & LYD_NODE_ANY) {
888 /* parse value type */
Michal Vasko403beac2021-08-24 08:27:52 +0200889 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200890 if (value_type == LYD_ANYDATA_DATATREE) {
891 /* invalid situation */
Radek Krejci1798aae2020-07-14 13:26:06 +0200892 LOGINT(ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200893 goto cleanup;
894 }
895
896 /* read anydata content */
Radek Krejci1798aae2020-07-14 13:26:06 +0200897 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200898 LY_CHECK_GOTO(ret, cleanup);
899 dynamic = 1;
900
901 if (value_type == LYD_ANYDATA_LYB) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200902 /* try to parse LYB into a data tree */
Michal Vasko02ed9d82021-07-15 14:58:04 +0200903 if (!lyb_parse_any_content(ctx, value, &tree)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200904 /* successfully parsed */
905 free(value);
906 value = (char *)tree;
907 value_type = LYD_ANYDATA_DATATREE;
908 }
909 }
910
Michal Vasko9afe3df2021-02-05 16:33:50 +0100911 /* create the node */
912 switch (value_type) {
913 case LYD_ANYDATA_LYB:
914 case LYD_ANYDATA_DATATREE:
915 /* use the value directly */
916 ret = lyd_create_any(snode, value, value_type, 1, &node);
917 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200918
Michal Vasko9afe3df2021-02-05 16:33:50 +0100919 dynamic = 0;
920 value = NULL;
921 break;
922 case LYD_ANYDATA_STRING:
923 case LYD_ANYDATA_XML:
924 case LYD_ANYDATA_JSON:
925 /* value is expected to be in the dictionary */
926 ret = lydict_insert_zc(ctx, value, &val_dict);
927 LY_CHECK_GOTO(ret, cleanup);
928 dynamic = 0;
929 value = NULL;
930
931 /* use the value in the dictionary */
932 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
933 if (ret) {
934 lydict_remove(ctx, val_dict);
935 goto cleanup;
936 }
937 break;
938 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200939 }
940 assert(node);
941
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100942 /* set flags */
943 node->flags = flags;
Michal Vasko60ea6352020-06-29 13:39:39 +0200944
945 /* add metadata/attributes */
946 if (snode) {
947 LY_LIST_FOR(meta, m) {
948 m->parent = node;
949 }
950 node->meta = meta;
951 meta = NULL;
952 } else {
953 assert(!node->schema);
954 LY_LIST_FOR(attr, a) {
955 a->parent = (struct lyd_node_opaq *)node;
956 }
957 ((struct lyd_node_opaq *)node)->attr = attr;
958 attr = NULL;
959 }
960
Michal Vaskob104f112020-07-17 09:54:54 +0200961 /* insert, keep first pointer correct */
Michal Vasko6ee6f432021-07-16 09:49:14 +0200962 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
Michal Vaskoe0665742021-02-11 11:08:44 +0100963 while (!parent && (*first_p)->prev->next) {
964 *first_p = (*first_p)->prev;
965 }
966
967 /* rememeber a successfully parsed node */
968 if (parsed) {
969 ly_set_add(parsed, node, 1, NULL);
Michal Vaskob104f112020-07-17 09:54:54 +0200970 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200971 node = NULL;
972
973stop_subtree:
974 /* end the subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200975 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200976 LY_CHECK_GOTO(ret, cleanup);
977
978cleanup:
979 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200980 free(module_key);
Michal Vasko60ea6352020-06-29 13:39:39 +0200981 free(name);
982 if (dynamic) {
983 free(value);
984 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200985
Michal Vasko3a41dff2020-07-15 14:30:28 +0200986 lyd_free_meta_siblings(meta);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200987 lyd_free_attr_siblings(ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200988 lyd_free_tree(node);
989 return ret;
990}
991
992/**
993 * @brief Parse used YANG data models.
994 *
995 * @param[in] lybctx LYB context.
996 * @return LY_ERR value.
997 */
998static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200999lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001000{
1001 LY_ERR ret;
1002 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001003 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001004
1005 /* read model count */
1006 lyb_read_number(&count, sizeof count, 2, lybctx);
1007
1008 if (count) {
1009 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1010
1011 /* read modules */
1012 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001013 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001014 LY_CHECK_RET(ret);
1015 LY_ARRAY_INCREMENT(lybctx->models);
1016 }
1017 }
1018
1019 return LY_SUCCESS;
1020}
1021
1022/**
1023 * @brief Parse LYB magic number.
1024 *
1025 * @param[in] lybctx LYB context.
1026 * @return LY_ERR value.
1027 */
1028static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001029lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001030{
1031 char magic_byte = 0;
1032
1033 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1034 if (magic_byte != 'l') {
1035 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1036 return LY_EINVAL;
1037 }
1038
1039 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1040 if (magic_byte != 'y') {
1041 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1042 return LY_EINVAL;
1043 }
1044
1045 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1046 if (magic_byte != 'b') {
1047 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1048 return LY_EINVAL;
1049 }
1050
1051 return LY_SUCCESS;
1052}
1053
1054/**
1055 * @brief Parse LYB header.
1056 *
1057 * @param[in] lybctx LYB context.
1058 * @return LY_ERR value.
1059 */
1060static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001061lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001062{
1063 uint8_t byte = 0;
1064
1065 /* version, future flags */
1066 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1067
1068 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1069 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001070 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001071 return LY_EINVAL;
1072 }
1073
1074 return LY_SUCCESS;
1075}
1076
Michal Vasko02ed9d82021-07-15 14:58:04 +02001077static LY_ERR
1078_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1079 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 +01001080 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001081{
Michal Vaskoe0665742021-02-11 11:08:44 +01001082 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001083 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001084
Michal Vaskoe0665742021-02-11 11:08:44 +01001085 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1086 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001087
Radek Krejci1798aae2020-07-14 13:26:06 +02001088 lybctx = calloc(1, sizeof *lybctx);
1089 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1090 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001091 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001092
Radek Krejci1798aae2020-07-14 13:26:06 +02001093 lybctx->lybctx->in = in;
1094 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001095 lybctx->parse_opts = parse_opts;
1096 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001097 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001098 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001099 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001100
1101 /* find the operation node if it exists already */
1102 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1103
Michal Vasko60ea6352020-06-29 13:39:39 +02001104 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001105 rc = lyb_parse_magic_number(lybctx->lybctx);
1106 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001107
1108 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001109 rc = lyb_parse_header(lybctx->lybctx);
1110 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001111
1112 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001113 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1114 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001115
1116 /* read subtree(s) */
Radek Krejci1798aae2020-07-14 13:26:06 +02001117 while (lybctx->lybctx->in->current[0]) {
Michal Vaskoe0665742021-02-11 11:08:44 +01001118 rc = lyb_parse_subtree_r(lybctx, parent, first_p, parsed);
1119 LY_CHECK_GOTO(rc, cleanup);
1120
1121 if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1122 break;
1123 }
1124 }
1125
1126 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1127 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1128 rc = LY_EVALID;
1129 goto cleanup;
1130 }
1131 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1132 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1133 rc = LY_EVALID;
1134 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001135 }
1136
1137 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001138 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001139
Michal Vasko60ea6352020-06-29 13:39:39 +02001140cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001141 /* there should be no unres stored if validation should be skipped */
1142 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1143 !lybctx->node_when.count));
1144
1145 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001146 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001147 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001148 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001149 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001150 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001151}
1152
Michal Vasko02ed9d82021-07-15 14:58:04 +02001153LY_ERR
1154lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1155 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1156 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
1157{
1158 uint32_t int_opts;
1159
1160 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1161 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1162
1163 switch (data_type) {
1164 case LYD_TYPE_DATA_YANG:
1165 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1166 break;
1167 case LYD_TYPE_RPC_YANG:
1168 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1169 break;
1170 case LYD_TYPE_NOTIF_YANG:
1171 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1172 break;
1173 case LYD_TYPE_REPLY_YANG:
1174 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1175 break;
1176 default:
1177 LOGINT(ctx);
1178 return LY_EINT;
1179 }
1180
1181 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1182}
1183
Michal Vasko60ea6352020-06-29 13:39:39 +02001184API int
1185lyd_lyb_data_length(const char *data)
1186{
1187 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001188 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001189 int count, i;
1190 size_t len;
1191 uint8_t buf[LYB_SIZE_MAX];
1192
1193 if (!data) {
1194 return -1;
1195 }
1196
Radek Krejci1798aae2020-07-14 13:26:06 +02001197 lybctx = calloc(1, sizeof *lybctx);
1198 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1199 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001200 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001201
1202 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001203 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001204 LY_CHECK_GOTO(ret, cleanup);
1205
1206 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001207 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001208 LY_CHECK_GOTO(ret, cleanup);
1209
1210 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001211 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001212
1213 /* read all models */
1214 for (i = 0; i < count; ++i) {
1215 /* module name length */
1216 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001217 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001218
1219 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001220 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001221
1222 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001223 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001224 }
1225
Radek Krejci1798aae2020-07-14 13:26:06 +02001226 while (lybctx->in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001227 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001228 ret = lyb_read_start_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001229 LY_CHECK_GOTO(ret, cleanup);
1230
1231 /* skip it */
Radek Krejci1798aae2020-07-14 13:26:06 +02001232 lyb_skip_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001233
1234 /* subtree finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001235 ret = lyb_read_stop_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001236 LY_CHECK_GOTO(ret, cleanup);
1237 }
1238
1239 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001240 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001241
1242cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001243 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001244
Radek Krejci1798aae2020-07-14 13:26:06 +02001245 ly_in_free(lybctx->in, 0);
1246 lylyb_ctx_free(lybctx);
1247
Michal Vasko63f3d842020-07-08 10:10:14 +02001248 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001249}