blob: 78496fceb5a9e751bdb53efdd82b88fd7f68e339 [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 */
531 lyb_read((uint8_t *)&format, 1, lybctx);
532
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);
740 lydctx->free(lydctx);
741 if (ret) {
742 lyd_free_siblings(*tree);
743 *tree = NULL;
744 }
745 return ret;
746}
747
748/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200749 * @brief Parse LYB subtree.
750 *
751 * @param[in] lybctx LYB context.
752 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
753 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
754 * @return LY_ERR value.
755 */
756static LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100757lyb_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 +0200758{
759 LY_ERR ret = LY_SUCCESS;
760 struct lyd_node *node = NULL, *tree;
761 const struct lys_module *mod;
762 const struct lysc_node *snode = NULL;
763 struct lyd_meta *meta = NULL, *m;
Radek Krejci1798aae2020-07-14 13:26:06 +0200764 struct lyd_attr *attr = NULL, *a;
Michal Vasko60ea6352020-06-29 13:39:39 +0200765 LYD_ANYDATA_VALUETYPE value_type;
Radek Krejci1798aae2020-07-14 13:26:06 +0200766 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
Michal Vasko9afe3df2021-02-05 16:33:50 +0100767 const char *val_dict;
Radek Krejci857189e2020-09-01 13:26:36 +0200768 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200769 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100770 void *val_prefix_data = NULL;
Michal Vasko02ed9d82021-07-15 14:58:04 +0200771 uint32_t flags;
Radek Krejci1798aae2020-07-14 13:26:06 +0200772 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +0200773
774 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200775 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200776
777 if (!parent) {
778 /* top-level, read module name */
Michal Vaskoe0665742021-02-11 11:08:44 +0100779 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200780 LY_CHECK_GOTO(ret, cleanup);
781
782 /* read hash, find the schema node starting from mod */
783 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
784 LY_CHECK_GOTO(ret, cleanup);
785 } else {
786 /* read hash, find the schema node starting from parent schema */
787 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
788 LY_CHECK_GOTO(ret, cleanup);
789 }
790
Michal Vaskoe0665742021-02-11 11:08:44 +0100791 if (!snode && !(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200792 /* unknown data, skip them */
Radek Krejci1798aae2020-07-14 13:26:06 +0200793 lyb_skip_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200794 goto stop_subtree;
Radek Krejci0f969882020-08-21 16:56:47 +0200795 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200796
797 /* create metadata/attributes */
798 if (snode) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200799 ret = lyb_parse_metadata(lybctx, &meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200800 LY_CHECK_GOTO(ret, cleanup);
801 } else {
Radek Krejci1798aae2020-07-14 13:26:06 +0200802 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200803 LY_CHECK_GOTO(ret, cleanup);
804 }
805
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100806 /* read flags */
807 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
808
Michal Vasko60ea6352020-06-29 13:39:39 +0200809 if (!snode) {
810 /* parse prefix */
Radek Krejci1798aae2020-07-14 13:26:06 +0200811 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200812 LY_CHECK_GOTO(ret, cleanup);
813
Radek Krejci1798aae2020-07-14 13:26:06 +0200814 /* parse module key */
815 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200816 LY_CHECK_GOTO(ret, cleanup);
817
818 /* parse name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200819 ret = lyb_read_string(&name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200820 LY_CHECK_GOTO(ret, cleanup);
821
Michal Vaskoffc92bf2021-06-21 08:15:14 +0200822 /* parse value */
823 ret = lyb_read_string(&value, 1, lybctx->lybctx);
824 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
825 dynamic = 1;
826
Michal Vasko60ea6352020-06-29 13:39:39 +0200827 /* parse format */
Radek Krejci1798aae2020-07-14 13:26:06 +0200828 lyb_read((uint8_t *)&format, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200829
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100830 /* parse value prefixes */
831 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
832 LY_CHECK_GOTO(ret, cleanup);
833
Michal Vasko60ea6352020-06-29 13:39:39 +0200834 /* create node */
Michal Vasko501af032020-11-11 20:27:44 +0100835 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
836 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200837 LY_CHECK_GOTO(ret, cleanup);
838
839 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200840 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100841 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200842 LY_CHECK_GOTO(ret, cleanup);
843 }
844 } else if (snode->nodetype & LYD_NODE_TERM) {
845 /* parse value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200846 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200847 LY_CHECK_GOTO(ret, cleanup);
848 dynamic = 1;
849
850 /* create node */
Radek Krejci8df109d2021-04-23 12:19:08 +0200851 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 +0200852 NULL, LYD_HINT_DATA, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200853 if (dynamic) {
854 free(value);
855 dynamic = 0;
856 }
857 value = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200858 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200859 } else if (snode->nodetype & LYD_NODE_INNER) {
860 /* create node */
861 ret = lyd_create_inner(snode, &node);
862 LY_CHECK_GOTO(ret, cleanup);
863
864 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200865 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100866 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200867 LY_CHECK_GOTO(ret, cleanup);
868 }
869
Michal Vaskoe0665742021-02-11 11:08:44 +0100870 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200871 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vaskoe0665742021-02-11 11:08:44 +0100872 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200873 LY_CHECK_GOTO(ret, cleanup);
874
875 /* add any missing default children */
Radek Krejci4f2e3e52021-03-30 14:20:28 +0200876 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 +0100877 &lybctx->node_types, (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200878 LY_CHECK_GOTO(ret, cleanup);
879 }
880
Michal Vasko751cb4d2020-07-14 12:25:28 +0200881 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200882 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +0200883 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +0200884 }
885 } else if (snode->nodetype & LYD_NODE_ANY) {
886 /* parse value type */
Radek Krejci1798aae2020-07-14 13:26:06 +0200887 lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200888 if (value_type == LYD_ANYDATA_DATATREE) {
889 /* invalid situation */
Radek Krejci1798aae2020-07-14 13:26:06 +0200890 LOGINT(ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200891 goto cleanup;
892 }
893
894 /* read anydata content */
Radek Krejci1798aae2020-07-14 13:26:06 +0200895 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200896 LY_CHECK_GOTO(ret, cleanup);
897 dynamic = 1;
898
899 if (value_type == LYD_ANYDATA_LYB) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200900 /* try to parse LYB into a data tree */
Michal Vasko02ed9d82021-07-15 14:58:04 +0200901 if (!lyb_parse_any_content(ctx, value, &tree)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200902 /* successfully parsed */
903 free(value);
904 value = (char *)tree;
905 value_type = LYD_ANYDATA_DATATREE;
906 }
907 }
908
Michal Vasko9afe3df2021-02-05 16:33:50 +0100909 /* create the node */
910 switch (value_type) {
911 case LYD_ANYDATA_LYB:
912 case LYD_ANYDATA_DATATREE:
913 /* use the value directly */
914 ret = lyd_create_any(snode, value, value_type, 1, &node);
915 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200916
Michal Vasko9afe3df2021-02-05 16:33:50 +0100917 dynamic = 0;
918 value = NULL;
919 break;
920 case LYD_ANYDATA_STRING:
921 case LYD_ANYDATA_XML:
922 case LYD_ANYDATA_JSON:
923 /* value is expected to be in the dictionary */
924 ret = lydict_insert_zc(ctx, value, &val_dict);
925 LY_CHECK_GOTO(ret, cleanup);
926 dynamic = 0;
927 value = NULL;
928
929 /* use the value in the dictionary */
930 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
931 if (ret) {
932 lydict_remove(ctx, val_dict);
933 goto cleanup;
934 }
935 break;
936 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200937 }
938 assert(node);
939
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100940 /* set flags */
941 node->flags = flags;
Michal Vasko60ea6352020-06-29 13:39:39 +0200942
943 /* add metadata/attributes */
944 if (snode) {
945 LY_LIST_FOR(meta, m) {
946 m->parent = node;
947 }
948 node->meta = meta;
949 meta = NULL;
950 } else {
951 assert(!node->schema);
952 LY_LIST_FOR(attr, a) {
953 a->parent = (struct lyd_node_opaq *)node;
954 }
955 ((struct lyd_node_opaq *)node)->attr = attr;
956 attr = NULL;
957 }
958
Michal Vaskob104f112020-07-17 09:54:54 +0200959 /* insert, keep first pointer correct */
Michal Vasko6ee6f432021-07-16 09:49:14 +0200960 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
Michal Vaskoe0665742021-02-11 11:08:44 +0100961 while (!parent && (*first_p)->prev->next) {
962 *first_p = (*first_p)->prev;
963 }
964
965 /* rememeber a successfully parsed node */
966 if (parsed) {
967 ly_set_add(parsed, node, 1, NULL);
Michal Vaskob104f112020-07-17 09:54:54 +0200968 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200969 node = NULL;
970
971stop_subtree:
972 /* end the subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200973 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200974 LY_CHECK_GOTO(ret, cleanup);
975
976cleanup:
977 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200978 free(module_key);
Michal Vasko60ea6352020-06-29 13:39:39 +0200979 free(name);
980 if (dynamic) {
981 free(value);
982 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200983
Michal Vasko3a41dff2020-07-15 14:30:28 +0200984 lyd_free_meta_siblings(meta);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200985 lyd_free_attr_siblings(ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200986 lyd_free_tree(node);
987 return ret;
988}
989
990/**
991 * @brief Parse used YANG data models.
992 *
993 * @param[in] lybctx LYB context.
994 * @return LY_ERR value.
995 */
996static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200997lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +0200998{
999 LY_ERR ret;
1000 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001001 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001002
1003 /* read model count */
1004 lyb_read_number(&count, sizeof count, 2, lybctx);
1005
1006 if (count) {
1007 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1008
1009 /* read modules */
1010 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001011 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001012 LY_CHECK_RET(ret);
1013 LY_ARRAY_INCREMENT(lybctx->models);
1014 }
1015 }
1016
1017 return LY_SUCCESS;
1018}
1019
1020/**
1021 * @brief Parse LYB magic number.
1022 *
1023 * @param[in] lybctx LYB context.
1024 * @return LY_ERR value.
1025 */
1026static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001027lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001028{
1029 char magic_byte = 0;
1030
1031 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1032 if (magic_byte != 'l') {
1033 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1034 return LY_EINVAL;
1035 }
1036
1037 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1038 if (magic_byte != 'y') {
1039 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1040 return LY_EINVAL;
1041 }
1042
1043 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1044 if (magic_byte != 'b') {
1045 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1046 return LY_EINVAL;
1047 }
1048
1049 return LY_SUCCESS;
1050}
1051
1052/**
1053 * @brief Parse LYB header.
1054 *
1055 * @param[in] lybctx LYB context.
1056 * @return LY_ERR value.
1057 */
1058static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001059lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001060{
1061 uint8_t byte = 0;
1062
1063 /* version, future flags */
1064 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1065
1066 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1067 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001068 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001069 return LY_EINVAL;
1070 }
1071
1072 return LY_SUCCESS;
1073}
1074
Michal Vasko02ed9d82021-07-15 14:58:04 +02001075static LY_ERR
1076_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1077 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 +01001078 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001079{
Michal Vaskoe0665742021-02-11 11:08:44 +01001080 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001081 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001082
Michal Vaskoe0665742021-02-11 11:08:44 +01001083 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1084 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001085
Radek Krejci1798aae2020-07-14 13:26:06 +02001086 lybctx = calloc(1, sizeof *lybctx);
1087 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1088 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001089 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001090
Radek Krejci1798aae2020-07-14 13:26:06 +02001091 lybctx->lybctx->in = in;
1092 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001093 lybctx->parse_opts = parse_opts;
1094 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001095 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001096 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001097 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001098
1099 /* find the operation node if it exists already */
1100 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1101
Michal Vasko60ea6352020-06-29 13:39:39 +02001102 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001103 rc = lyb_parse_magic_number(lybctx->lybctx);
1104 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001105
1106 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001107 rc = lyb_parse_header(lybctx->lybctx);
1108 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001109
1110 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001111 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1112 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001113
1114 /* read subtree(s) */
Radek Krejci1798aae2020-07-14 13:26:06 +02001115 while (lybctx->lybctx->in->current[0]) {
Michal Vaskoe0665742021-02-11 11:08:44 +01001116 rc = lyb_parse_subtree_r(lybctx, parent, first_p, parsed);
1117 LY_CHECK_GOTO(rc, cleanup);
1118
1119 if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1120 break;
1121 }
1122 }
1123
1124 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1125 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1126 rc = LY_EVALID;
1127 goto cleanup;
1128 }
1129 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1130 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1131 rc = LY_EVALID;
1132 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001133 }
1134
1135 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001136 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001137
Michal Vasko60ea6352020-06-29 13:39:39 +02001138cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001139 /* there should be no unres stored if validation should be skipped */
1140 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1141 !lybctx->node_when.count));
1142
1143 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001144 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001145 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001146 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001147 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001148 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001149}
1150
Michal Vasko02ed9d82021-07-15 14:58:04 +02001151LY_ERR
1152lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1153 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1154 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
1155{
1156 uint32_t int_opts;
1157
1158 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1159 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1160
1161 switch (data_type) {
1162 case LYD_TYPE_DATA_YANG:
1163 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1164 break;
1165 case LYD_TYPE_RPC_YANG:
1166 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1167 break;
1168 case LYD_TYPE_NOTIF_YANG:
1169 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1170 break;
1171 case LYD_TYPE_REPLY_YANG:
1172 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1173 break;
1174 default:
1175 LOGINT(ctx);
1176 return LY_EINT;
1177 }
1178
1179 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1180}
1181
Michal Vasko60ea6352020-06-29 13:39:39 +02001182API int
1183lyd_lyb_data_length(const char *data)
1184{
1185 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001186 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001187 int count, i;
1188 size_t len;
1189 uint8_t buf[LYB_SIZE_MAX];
1190
1191 if (!data) {
1192 return -1;
1193 }
1194
Radek Krejci1798aae2020-07-14 13:26:06 +02001195 lybctx = calloc(1, sizeof *lybctx);
1196 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1197 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001198 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001199
1200 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001201 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001202 LY_CHECK_GOTO(ret, cleanup);
1203
1204 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001205 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001206 LY_CHECK_GOTO(ret, cleanup);
1207
1208 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001209 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001210
1211 /* read all models */
1212 for (i = 0; i < count; ++i) {
1213 /* module name length */
1214 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001215 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001216
1217 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001218 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001219
1220 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001221 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001222 }
1223
Radek Krejci1798aae2020-07-14 13:26:06 +02001224 while (lybctx->in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001225 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001226 ret = lyb_read_start_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001227 LY_CHECK_GOTO(ret, cleanup);
1228
1229 /* skip it */
Radek Krejci1798aae2020-07-14 13:26:06 +02001230 lyb_skip_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001231
1232 /* subtree finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001233 ret = lyb_read_stop_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001234 LY_CHECK_GOTO(ret, cleanup);
1235 }
1236
1237 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001238 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001239
1240cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001241 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001242
Radek Krejci1798aae2020-07-14 13:26:06 +02001243 ly_in_free(lybctx->in, 0);
1244 lylyb_ctx_free(lybctx);
1245
Michal Vasko63f3d842020-07-08 10:10:14 +02001246 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001247}