blob: b4abac39a944bd538b2d1e79dc382a8cf589bd44 [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 Krejciad97c5f2020-06-30 09:19:28 +020033#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010034#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020035#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010036#include "tree_edit.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020037#include "tree_schema.h"
38#include "validation.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010039#include "xml.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020040
Radek Krejci1798aae2020-07-14 13:26:06 +020041void
42lylyb_ctx_free(struct lylyb_ctx *ctx)
43{
44 LY_ARRAY_COUNT_TYPE u;
45
46 LY_ARRAY_FREE(ctx->subtrees);
47 LY_ARRAY_FREE(ctx->models);
48
49 LY_ARRAY_FOR(ctx->sib_hts, u) {
50 lyht_free(ctx->sib_hts[u].ht);
51 }
52 LY_ARRAY_FREE(ctx->sib_hts);
53
54 free(ctx);
55}
56
57void
58lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
59{
60 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
61
62 lyd_ctx_free(lydctx);
63 lylyb_ctx_free(ctx->lybctx);
64 free(ctx);
65}
66
Michal Vasko60ea6352020-06-29 13:39:39 +020067/**
68 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
69 *
70 * @param[in] buf Destination buffer.
71 * @param[in] count Number of bytes to read.
72 * @param[in] lybctx LYB context.
73 */
74static void
Radek Krejci1798aae2020-07-14 13:26:06 +020075lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +020076{
Michal Vaskofd69e1d2020-07-03 11:57:17 +020077 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +020078 struct lyd_lyb_subtree *empty;
79 size_t to_read;
80 uint8_t meta_buf[LYB_META_BYTES];
81
82 assert(lybctx);
83
84 while (1) {
85 /* check for fully-read (empty) data chunks */
86 to_read = count;
87 empty = NULL;
88 LY_ARRAY_FOR(lybctx->subtrees, u) {
89 /* we want the innermost chunks resolved first, so replace previous empty chunks,
90 * also ignore chunks that are completely finished, there is nothing for us to do */
91 if ((lybctx->subtrees[u].written <= to_read) && lybctx->subtrees[u].position) {
92 /* empty chunk, do not read more */
93 to_read = lybctx->subtrees[u].written;
94 empty = &lybctx->subtrees[u];
95 }
96 }
97
98 if (!empty && !count) {
99 break;
100 }
101
102 /* we are actually reading some data, not just finishing another chunk */
103 if (to_read) {
104 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200105 ly_in_read(lybctx->in, buf, to_read);
106 } else {
107 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200108 }
109
110 LY_ARRAY_FOR(lybctx->subtrees, u) {
111 /* decrease all written counters */
112 lybctx->subtrees[u].written -= to_read;
113 assert(lybctx->subtrees[u].written <= LYB_SIZE_MAX);
114 }
115 /* decrease count/buf */
116 count -= to_read;
117 if (buf) {
118 buf += to_read;
119 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200120 }
121
122 if (empty) {
123 /* read the next chunk meta information */
Michal Vasko63f3d842020-07-08 10:10:14 +0200124 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200125 empty->written = meta_buf[0];
126 empty->inner_chunks = meta_buf[1];
127
128 /* remember whether there is a following chunk or not */
129 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200130 }
131 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200132}
133
134/**
135 * @brief Read a number.
136 *
137 * @param[in] num Destination buffer.
138 * @param[in] num_size Size of @p num.
139 * @param[in] bytes Number of bytes to read.
140 * @param[in] lybctx LYB context.
141 */
142static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200143lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200144{
145 uint64_t buf = 0;
146
147 lyb_read((uint8_t *)&buf, bytes, lybctx);
148
149 /* correct byte order */
150 buf = le64toh(buf);
151
152 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100153 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200154 *((uint8_t *)num) = buf;
155 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100156 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200157 *((uint16_t *)num) = buf;
158 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100159 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200160 *((uint32_t *)num) = buf;
161 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100162 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200163 *((uint64_t *)num) = buf;
164 break;
165 default:
166 LOGINT(lybctx->ctx);
167 }
168}
169
170/**
171 * @brief Read a string.
172 *
173 * @param[in] str Destination buffer, is allocated.
174 * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this subtree.
175 * @param[in] lybctx LYB context.
176 * @return LY_ERR value.
177 */
178static LY_ERR
Radek Krejci857189e2020-09-01 13:26:36 +0200179lyb_read_string(char **str, ly_bool with_length, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200180{
Radek Krejci857189e2020-09-01 13:26:36 +0200181 ly_bool next_chunk = 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200182 size_t len = 0, cur_len;
183
184 *str = NULL;
185
186 if (with_length) {
187 lyb_read_number(&len, sizeof len, 2, lybctx);
188 } else {
189 /* read until the end of this subtree */
190 len = LYB_LAST_SUBTREE(lybctx).written;
191 if (LYB_LAST_SUBTREE(lybctx).position) {
192 next_chunk = 1;
193 }
194 }
195
196 *str = malloc((len + 1) * sizeof **str);
197 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
198
199 lyb_read((uint8_t *)*str, len, lybctx);
200
201 while (next_chunk) {
202 cur_len = LYB_LAST_SUBTREE(lybctx).written;
203 if (LYB_LAST_SUBTREE(lybctx).position) {
204 next_chunk = 1;
205 } else {
206 next_chunk = 0;
207 }
208
209 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
210 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
211
212 lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
213
214 len += cur_len;
215 }
216
217 ((char *)*str)[len] = '\0';
218 return LY_SUCCESS;
219}
220
221/**
222 * @brief Stop the current subtree - change LYB context state.
223 *
224 * @param[in] lybctx LYB context.
225 * @return LY_ERR value.
226 */
227static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200228lyb_read_stop_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200229{
230 if (LYB_LAST_SUBTREE(lybctx).written) {
231 LOGINT_RET(lybctx->ctx);
232 }
233
234 LY_ARRAY_DECREMENT(lybctx->subtrees);
235 return LY_SUCCESS;
236}
237
238/**
239 * @brief Start a new subtree - change LYB context state but also read the expected metadata.
240 *
241 * @param[in] lybctx LYB context.
242 * @return LY_ERR value.
243 */
244static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200245lyb_read_start_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200246{
247 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200248 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200249
Radek Krejcic7d13e32020-12-09 12:32:24 +0100250 u = LY_ARRAY_COUNT(lybctx->subtrees);
Michal Vasko60ea6352020-06-29 13:39:39 +0200251 if (u == lybctx->subtree_size) {
252 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
253 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
254 }
255
Michal Vasko63f3d842020-07-08 10:10:14 +0200256 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200257
258 LY_ARRAY_INCREMENT(lybctx->subtrees);
259 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
260 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
261 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
262
Michal Vasko60ea6352020-06-29 13:39:39 +0200263 return LY_SUCCESS;
264}
265
266/**
267 * @brief Parse YANG model info.
268 *
269 * @param[in] lybctx LYB context.
270 * @param[out] mod Parsed module.
271 * @return LY_ERR value.
272 */
273static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200274lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
Michal Vasko60ea6352020-06-29 13:39:39 +0200275{
276 LY_ERR ret = LY_SUCCESS;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100277 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
Michal Vasko60ea6352020-06-29 13:39:39 +0200278 uint16_t rev;
279
280 /* model name */
281 ret = lyb_read_string(&mod_name, 1, lybctx);
282 LY_CHECK_GOTO(ret, cleanup);
283
284 /* revision */
285 lyb_read_number(&rev, sizeof rev, 2, lybctx);
286
287 if (!mod_name[0]) {
288 /* opaq node, no module */
289 *mod = NULL;
290 goto cleanup;
291 }
292
293 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100294 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
295 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko60ea6352020-06-29 13:39:39 +0200296 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
Radek Krejci1798aae2020-07-14 13:26:06 +0200297 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200298 /* try to use an updated module */
299 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
300 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
301 /* not an implemented module in a newer revision */
302 *mod = NULL;
303 }
304 }
305 } else {
306 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
307 }
308 /* TODO data_clb supported?
309 if (lybctx->ctx->data_clb) {
310 if (!*mod) {
311 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
312 } else if (!(*mod)->implemented) {
313 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
314 }
315 }*/
316
317 if (!*mod || !(*mod)->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200318 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200319 if (!*mod) {
320 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko69730152020-10-09 16:30:07 +0200321 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200322 } else if (!(*mod)->implemented) {
323 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko69730152020-10-09 16:30:07 +0200324 mod_name, rev ? "@" : "", rev ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200325 }
326 ret = LY_EINVAL;
327 goto cleanup;
328 }
329
330 }
331
332cleanup:
333 free(mod_name);
334 return ret;
335}
336
337/**
338 * @brief Parse YANG node metadata.
339 *
340 * @param[in] lybctx LYB context.
Michal Vasko60ea6352020-06-29 13:39:39 +0200341 * @param[out] meta Parsed metadata.
342 * @return LY_ERR value.
343 */
344static LY_ERR
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200345lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200346{
347 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200348 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200349 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200350 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200351 const struct lys_module *mod;
352
353 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200354 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200355
356 /* read attributes */
357 for (i = 0; i < count; ++i) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200358 ret = lyb_read_start_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200359 LY_CHECK_GOTO(ret, cleanup);
360
361 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100362 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200363 LY_CHECK_GOTO(ret, cleanup);
364
365 if (!mod) {
366 /* skip it */
367 do {
Radek Krejci1798aae2020-07-14 13:26:06 +0200368 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx->lybctx).written, lybctx->lybctx);
369 } while (LYB_LAST_SUBTREE(lybctx->lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200370 goto stop_subtree;
371 }
372
373 /* meta name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200374 ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200375 LY_CHECK_GOTO(ret, cleanup);
376
377 /* meta value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200378 ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200379 LY_CHECK_GOTO(ret, cleanup);
380 dynamic = 1;
381
382 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200383 ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
Michal Vasko69730152020-10-09 16:30:07 +0200384 ly_strlen(meta_value), &dynamic, LY_PREF_JSON, NULL, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200385
386 /* free strings */
387 free(meta_name);
388 meta_name = NULL;
389 if (dynamic) {
390 free(meta_value);
391 dynamic = 0;
392 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200393
Radek Krejci1798aae2020-07-14 13:26:06 +0200394 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200395
396stop_subtree:
Radek Krejci1798aae2020-07-14 13:26:06 +0200397 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200398 LY_CHECK_GOTO(ret, cleanup);
399 }
400
401cleanup:
402 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200403 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200404 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200405 *meta = NULL;
406 }
407 return ret;
408}
409
410/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100411 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200412 *
413 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100414 * @param[in] format Prefix data format.
415 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200416 * @return LY_ERR value.
417 */
418static LY_ERR
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100419lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_PREFIX_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200420{
421 LY_ERR ret = LY_SUCCESS;
422 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100423 struct ly_set *set = NULL;
424 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200425
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100426 switch (format) {
427 case LY_PREF_XML:
428 /* read count */
429 lyb_read(&count, 1, lybctx);
430 if (!count) {
431 return LY_SUCCESS;
432 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200433
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100434 /* read all NS elements */
435 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200436
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100437 for (i = 0; i < count; ++i) {
438 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200439
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100440 /* prefix */
441 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, 1, lybctx), cleanup);
442
443 /* namespace */
444 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, 1, lybctx), cleanup);
445
446 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
447 ns = NULL;
448 }
449
450 *prefix_data = set;
451 break;
452 case LY_PREF_JSON:
453 /* nothing stored */
454 break;
455 default:
456 LOGINT(lybctx->ctx);
457 ret = LY_EINT;
458 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200459 }
460
461cleanup:
462 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100463 ly_free_prefix_data(format, set);
464 if (ns) {
465 free(ns->prefix);
466 free(ns->uri);
467 free(ns);
468 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200469 }
470 return ret;
471}
472
473/**
474 * @brief Parse opaque attributes.
475 *
476 * @param[in] lybctx LYB context.
477 * @param[out] attr Parsed attributes.
478 * @return LY_ERR value.
479 */
480static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200481lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200482{
483 LY_ERR ret = LY_SUCCESS;
484 uint8_t count, i;
Radek Krejci1798aae2020-07-14 13:26:06 +0200485 struct lyd_attr *attr2;
486 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200487 ly_bool dynamic = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100488 LY_PREFIX_FORMAT format = 0;
489 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200490
491 /* read count */
492 lyb_read(&count, 1, lybctx);
493
494 /* read attributes */
495 for (i = 0; i < count; ++i) {
496 ret = lyb_read_start_subtree(lybctx);
497 LY_CHECK_GOTO(ret, cleanup);
498
Michal Vasko0fdcd242020-11-11 19:12:30 +0100499 /* prefix, may be empty */
Michal Vasko60ea6352020-06-29 13:39:39 +0200500 ret = lyb_read_string(&prefix, 1, lybctx);
501 LY_CHECK_GOTO(ret, cleanup);
502 if (!prefix[0]) {
503 free(prefix);
504 prefix = NULL;
505 }
506
507 /* namespace, may be empty */
Radek Krejci1798aae2020-07-14 13:26:06 +0200508 ret = lyb_read_string(&module_name, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200509 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200510 if (!module_name[0]) {
511 free(module_name);
512 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200513 }
514
515 /* name */
516 ret = lyb_read_string(&name, 1, lybctx);
517 LY_CHECK_GOTO(ret, cleanup);
518
Michal Vasko60ea6352020-06-29 13:39:39 +0200519 /* format */
520 lyb_read((uint8_t *)&format, 1, lybctx);
521
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100522 /* value prefixes */
523 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
524 LY_CHECK_GOTO(ret, cleanup);
525
Michal Vasko60ea6352020-06-29 13:39:39 +0200526 /* value */
527 ret = lyb_read_string(&value, 0, lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100528 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200529 dynamic = 1;
530
531 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100532 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
533 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200534 LY_CHECK_GOTO(ret, cleanup);
535
536 free(prefix);
537 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200538 free(module_name);
539 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200540 free(name);
541 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200542 assert(!dynamic);
543 value = NULL;
544
545 if (!*attr) {
546 *attr = attr2;
547 }
548
549 ret = lyb_read_stop_subtree(lybctx);
550 LY_CHECK_GOTO(ret, cleanup);
551 }
552
553cleanup:
554 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200555 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200556 free(name);
557 if (dynamic) {
558 free(value);
559 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200560 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200561 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200562 *attr = NULL;
563 }
564 return ret;
565}
566
567/**
568 * @brief Check whether a schema node matches a hash(es).
569 *
570 * @param[in] sibling Schema node to check.
571 * @param[in] hash Hash array to check.
572 * @param[in] hash_count Number of hashes in @p hash.
573 * @return non-zero if matches,
574 * @return 0 if not.
575 */
576static int
577lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
578{
579 LYB_HASH sibling_hash;
580 uint8_t i;
581
582 /* compare all the hashes starting from collision ID 0 */
583 for (i = 0; i < hash_count; ++i) {
584 sibling_hash = lyb_hash(sibling, i);
585 if (sibling_hash != hash[i]) {
586 return 0;
587 }
588 }
589
590 return 1;
591}
592
593/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200594 * @brief Parse schema node hash.
595 *
596 * @param[in] lybctx LYB context.
597 * @param[in] sparent Schema parent, must be set if @p mod is not.
598 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
599 * @param[out] snode Parsed found schema node, may be NULL if opaque.
600 * @return LY_ERR value.
601 */
602static LY_ERR
603lyb_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 +0200604 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200605{
606 LY_ERR ret;
607 uint8_t i, j;
608 const struct lysc_node *sibling;
609 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200610 uint32_t getnext_opts;
Michal Vasko60ea6352020-06-29 13:39:39 +0200611
612 *snode = NULL;
Michal Vasko7b1ad1a2020-11-02 15:41:27 +0100613 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200614
615 /* read the first hash */
Radek Krejci1798aae2020-07-14 13:26:06 +0200616 lyb_read(&hash[0], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200617
618 if (!hash[0]) {
619 /* opaque node */
620 return LY_SUCCESS;
621 }
622
623 /* based on the first hash read all the other ones, if any */
624 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
625 if (i > LYB_HASH_BITS) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200626 LOGINT_RET(lybctx->lybctx->ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200627 }
628 }
629
630 /* move the first hash on its accurate position */
631 hash[i] = hash[0];
632
633 /* read the rest of hashes */
634 for (j = i; j; --j) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200635 lyb_read(&hash[j - 1], sizeof *hash, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200636
637 /* correct collision ID */
638 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
639 /* preceded with zeros */
640 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
641 }
642
643 /* find our node with matching hashes */
644 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100645 while (1) {
646 if (!sparent && lybctx->ext) {
647 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
648 } else {
649 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
650 }
651 if (!sibling) {
652 break;
653 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200654 /* skip schema nodes from models not present during printing */
Michal Vasko69730152020-10-09 16:30:07 +0200655 if (lyb_has_schema_model(sibling, lybctx->lybctx->models) &&
656 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200657 /* match found */
658 break;
659 }
660 }
661
Michal Vaskoe0665742021-02-11 11:08:44 +0100662 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100663 if (lybctx->ext) {
664 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
665 lybctx->ext->def->name);
666 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100667 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200668 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200669 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100670 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200671 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200672 }
673 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200674 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200675 return ret;
676 }
677
678 *snode = sibling;
679 return LY_SUCCESS;
680}
681
682/**
683 * @brief Read until the end of the current subtree.
684 *
685 * @param[in] lybctx LYB context.
686 */
687static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200688lyb_skip_subtree(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200689{
Michal Vasko60ea6352020-06-29 13:39:39 +0200690 do {
691 /* first skip any meta information inside */
Michal Vasko63f3d842020-07-08 10:10:14 +0200692 ly_in_skip(lybctx->in, LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200693
694 /* then read data */
695 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
696 } while (LYB_LAST_SUBTREE(lybctx).written);
697}
698
699/**
700 * @brief Parse LYB subtree.
701 *
702 * @param[in] lybctx LYB context.
703 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
704 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
705 * @return LY_ERR value.
706 */
707static LY_ERR
Michal Vaskoe0665742021-02-11 11:08:44 +0100708lyb_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 +0200709{
710 LY_ERR ret = LY_SUCCESS;
711 struct lyd_node *node = NULL, *tree;
712 const struct lys_module *mod;
713 const struct lysc_node *snode = NULL;
714 struct lyd_meta *meta = NULL, *m;
Radek Krejci1798aae2020-07-14 13:26:06 +0200715 struct lyd_attr *attr = NULL, *a;
Michal Vasko60ea6352020-06-29 13:39:39 +0200716 LYD_ANYDATA_VALUETYPE value_type;
Radek Krejci1798aae2020-07-14 13:26:06 +0200717 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
Michal Vasko9afe3df2021-02-05 16:33:50 +0100718 const char *val_dict;
Radek Krejci857189e2020-09-01 13:26:36 +0200719 ly_bool dynamic = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100720 LY_PREFIX_FORMAT format = 0;
721 void *val_prefix_data = NULL;
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100722 uint32_t prev_lo, flags;
Radek Krejci1798aae2020-07-14 13:26:06 +0200723 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
Michal Vasko60ea6352020-06-29 13:39:39 +0200724
725 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200726 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200727
728 if (!parent) {
729 /* top-level, read module name */
Michal Vaskoe0665742021-02-11 11:08:44 +0100730 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200731 LY_CHECK_GOTO(ret, cleanup);
732
733 /* read hash, find the schema node starting from mod */
734 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
735 LY_CHECK_GOTO(ret, cleanup);
736 } else {
737 /* read hash, find the schema node starting from parent schema */
738 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
739 LY_CHECK_GOTO(ret, cleanup);
740 }
741
Michal Vaskoe0665742021-02-11 11:08:44 +0100742 if (!snode && !(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200743 /* unknown data, skip them */
Radek Krejci1798aae2020-07-14 13:26:06 +0200744 lyb_skip_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200745 goto stop_subtree;
Radek Krejci0f969882020-08-21 16:56:47 +0200746 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200747
748 /* create metadata/attributes */
749 if (snode) {
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200750 ret = lyb_parse_metadata(lybctx, &meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200751 LY_CHECK_GOTO(ret, cleanup);
752 } else {
Radek Krejci1798aae2020-07-14 13:26:06 +0200753 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200754 LY_CHECK_GOTO(ret, cleanup);
755 }
756
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100757 /* read flags */
758 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
759
Michal Vasko60ea6352020-06-29 13:39:39 +0200760 if (!snode) {
761 /* parse prefix */
Radek Krejci1798aae2020-07-14 13:26:06 +0200762 ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200763 LY_CHECK_GOTO(ret, cleanup);
764
Radek Krejci1798aae2020-07-14 13:26:06 +0200765 /* parse module key */
766 ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200767 LY_CHECK_GOTO(ret, cleanup);
768
769 /* parse name */
Radek Krejci1798aae2020-07-14 13:26:06 +0200770 ret = lyb_read_string(&name, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200771 LY_CHECK_GOTO(ret, cleanup);
772
Michal Vasko60ea6352020-06-29 13:39:39 +0200773 /* parse format */
Radek Krejci1798aae2020-07-14 13:26:06 +0200774 lyb_read((uint8_t *)&format, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200775
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100776 /* parse value prefixes */
777 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
778 LY_CHECK_GOTO(ret, cleanup);
779
Michal Vasko60ea6352020-06-29 13:39:39 +0200780 /* parse value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200781 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100782 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200783 dynamic = 1;
784
785 /* create node */
Michal Vasko501af032020-11-11 20:27:44 +0100786 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
787 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200788 LY_CHECK_GOTO(ret, cleanup);
789
790 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200791 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100792 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200793 LY_CHECK_GOTO(ret, cleanup);
794 }
795 } else if (snode->nodetype & LYD_NODE_TERM) {
796 /* parse value */
Radek Krejci1798aae2020-07-14 13:26:06 +0200797 ret = lyb_read_string(&value, 0, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200798 LY_CHECK_GOTO(ret, cleanup);
799 dynamic = 1;
800
801 /* create node */
Michal Vaskofeca4fb2020-10-05 08:58:40 +0200802 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode, value, ly_strlen(value), &dynamic, LY_PREF_JSON,
Michal Vasko69730152020-10-09 16:30:07 +0200803 NULL, LYD_HINT_DATA, &node);
Michal Vasko60ea6352020-06-29 13:39:39 +0200804 if (dynamic) {
805 free(value);
806 dynamic = 0;
807 }
808 value = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200809 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200810 } else if (snode->nodetype & LYD_NODE_INNER) {
811 /* create node */
812 ret = lyd_create_inner(snode, &node);
813 LY_CHECK_GOTO(ret, cleanup);
814
815 /* process children */
Radek Krejci1798aae2020-07-14 13:26:06 +0200816 while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
Michal Vaskoe0665742021-02-11 11:08:44 +0100817 ret = lyb_parse_subtree_r(lybctx, node, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200818 LY_CHECK_GOTO(ret, cleanup);
819 }
820
Michal Vaskoe0665742021-02-11 11:08:44 +0100821 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200822 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vaskoe0665742021-02-11 11:08:44 +0100823 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200824 LY_CHECK_GOTO(ret, cleanup);
825
826 /* add any missing default children */
Michal Vaskoc43c8ab2021-03-05 13:32:44 +0100827 ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &lybctx->node_when,
828 &lybctx->node_types, (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200829 LY_CHECK_GOTO(ret, cleanup);
830 }
831
Michal Vasko751cb4d2020-07-14 12:25:28 +0200832 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200833 /* rememeber the RPC/action/notification */
Radek Krejci1798aae2020-07-14 13:26:06 +0200834 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +0200835 }
836 } else if (snode->nodetype & LYD_NODE_ANY) {
837 /* parse value type */
Radek Krejci1798aae2020-07-14 13:26:06 +0200838 lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200839 if (value_type == LYD_ANYDATA_DATATREE) {
840 /* invalid situation */
Radek Krejci1798aae2020-07-14 13:26:06 +0200841 LOGINT(ctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200842 goto cleanup;
843 }
844
845 /* read anydata content */
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 if (value_type == LYD_ANYDATA_LYB) {
851 /* turn logging off */
852 prev_lo = ly_log_options(0);
853
854 /* try to parse LYB into a data tree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200855 if (lyd_parse_data_mem(ctx, value, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200856 /* successfully parsed */
857 free(value);
858 value = (char *)tree;
859 value_type = LYD_ANYDATA_DATATREE;
860 }
Radek Krejci7931b192020-06-25 17:05:03 +0200861
862 /* turn logging on again */
863 ly_log_options(prev_lo);
Michal Vasko60ea6352020-06-29 13:39:39 +0200864 }
865
Michal Vasko9afe3df2021-02-05 16:33:50 +0100866 /* create the node */
867 switch (value_type) {
868 case LYD_ANYDATA_LYB:
869 case LYD_ANYDATA_DATATREE:
870 /* use the value directly */
871 ret = lyd_create_any(snode, value, value_type, 1, &node);
872 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200873
Michal Vasko9afe3df2021-02-05 16:33:50 +0100874 dynamic = 0;
875 value = NULL;
876 break;
877 case LYD_ANYDATA_STRING:
878 case LYD_ANYDATA_XML:
879 case LYD_ANYDATA_JSON:
880 /* value is expected to be in the dictionary */
881 ret = lydict_insert_zc(ctx, value, &val_dict);
882 LY_CHECK_GOTO(ret, cleanup);
883 dynamic = 0;
884 value = NULL;
885
886 /* use the value in the dictionary */
887 ret = lyd_create_any(snode, val_dict, value_type, 1, &node);
888 if (ret) {
889 lydict_remove(ctx, val_dict);
890 goto cleanup;
891 }
892 break;
893 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200894 }
895 assert(node);
896
Michal Vaskoc5e866a2020-11-04 17:09:26 +0100897 /* set flags */
898 node->flags = flags;
Michal Vasko60ea6352020-06-29 13:39:39 +0200899
900 /* add metadata/attributes */
901 if (snode) {
902 LY_LIST_FOR(meta, m) {
903 m->parent = node;
904 }
905 node->meta = meta;
906 meta = NULL;
907 } else {
908 assert(!node->schema);
909 LY_LIST_FOR(attr, a) {
910 a->parent = (struct lyd_node_opaq *)node;
911 }
912 ((struct lyd_node_opaq *)node)->attr = attr;
913 attr = NULL;
914 }
915
Michal Vaskob104f112020-07-17 09:54:54 +0200916 /* insert, keep first pointer correct */
Michal Vaskoe0665742021-02-11 11:08:44 +0100917 lyd_insert_node(parent, first_p, node);
918 while (!parent && (*first_p)->prev->next) {
919 *first_p = (*first_p)->prev;
920 }
921
922 /* rememeber a successfully parsed node */
923 if (parsed) {
924 ly_set_add(parsed, node, 1, NULL);
Michal Vaskob104f112020-07-17 09:54:54 +0200925 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200926 node = NULL;
927
928stop_subtree:
929 /* end the subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +0200930 ret = lyb_read_stop_subtree(lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200931 LY_CHECK_GOTO(ret, cleanup);
932
933cleanup:
934 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200935 free(module_key);
Michal Vasko60ea6352020-06-29 13:39:39 +0200936 free(name);
937 if (dynamic) {
938 free(value);
939 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200940
Michal Vasko3a41dff2020-07-15 14:30:28 +0200941 lyd_free_meta_siblings(meta);
Radek Krejci011e4aa2020-09-04 15:22:31 +0200942 lyd_free_attr_siblings(ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200943 lyd_free_tree(node);
944 return ret;
945}
946
947/**
948 * @brief Parse used YANG data models.
949 *
950 * @param[in] lybctx LYB context.
951 * @return LY_ERR value.
952 */
953static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200954lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +0200955{
956 LY_ERR ret;
957 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200958 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200959
960 /* read model count */
961 lyb_read_number(&count, sizeof count, 2, lybctx);
962
963 if (count) {
964 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
965
966 /* read modules */
967 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200968 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +0200969 LY_CHECK_RET(ret);
970 LY_ARRAY_INCREMENT(lybctx->models);
971 }
972 }
973
974 return LY_SUCCESS;
975}
976
977/**
978 * @brief Parse LYB magic number.
979 *
980 * @param[in] lybctx LYB context.
981 * @return LY_ERR value.
982 */
983static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200984lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200985{
986 char magic_byte = 0;
987
988 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
989 if (magic_byte != 'l') {
990 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
991 return LY_EINVAL;
992 }
993
994 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
995 if (magic_byte != 'y') {
996 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
997 return LY_EINVAL;
998 }
999
1000 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1001 if (magic_byte != 'b') {
1002 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1003 return LY_EINVAL;
1004 }
1005
1006 return LY_SUCCESS;
1007}
1008
1009/**
1010 * @brief Parse LYB header.
1011 *
1012 * @param[in] lybctx LYB context.
1013 * @return LY_ERR value.
1014 */
1015static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001016lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001017{
1018 uint8_t byte = 0;
1019
1020 /* version, future flags */
1021 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1022
1023 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1024 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001025 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001026 return LY_EINVAL;
1027 }
1028
1029 return LY_SUCCESS;
1030}
1031
Michal Vaskoe0665742021-02-11 11:08:44 +01001032LY_ERR
Radek Krejcif16e2542021-02-17 15:39:23 +01001033lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1034 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
1035 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001036{
Michal Vaskoe0665742021-02-11 11:08:44 +01001037 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001038 struct lyd_lyb_ctx *lybctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001039 uint32_t int_opts;
Michal Vasko60ea6352020-06-29 13:39:39 +02001040
Michal Vaskoe0665742021-02-11 11:08:44 +01001041 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1042 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001043
Radek Krejci1798aae2020-07-14 13:26:06 +02001044 lybctx = calloc(1, sizeof *lybctx);
1045 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1046 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001047 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001048
Radek Krejci1798aae2020-07-14 13:26:06 +02001049 lybctx->lybctx->in = in;
1050 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001051 lybctx->parse_opts = parse_opts;
1052 lybctx->val_opts = val_opts;
Radek Krejci1798aae2020-07-14 13:26:06 +02001053 lybctx->free = lyd_lyb_ctx_free;
Michal Vasko60ea6352020-06-29 13:39:39 +02001054
Michal Vaskoe0665742021-02-11 11:08:44 +01001055 switch (data_type) {
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001056 case LYD_TYPE_DATA_YANG:
Michal Vaskoe0665742021-02-11 11:08:44 +01001057 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1058 break;
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001059 case LYD_TYPE_RPC_YANG:
Michal Vaskoe0665742021-02-11 11:08:44 +01001060 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1061 break;
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001062 case LYD_TYPE_NOTIF_YANG:
Michal Vaskoe0665742021-02-11 11:08:44 +01001063 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1064 break;
Michal Vasko1e4c68e2021-02-18 15:03:01 +01001065 case LYD_TYPE_REPLY_YANG:
Michal Vaskoe0665742021-02-11 11:08:44 +01001066 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1067 break;
1068 default:
1069 LOGINT(ctx);
1070 rc = LY_EINT;
1071 goto cleanup;
1072 }
1073 lybctx->int_opts = int_opts;
Radek Krejcif16e2542021-02-17 15:39:23 +01001074 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001075
1076 /* find the operation node if it exists already */
1077 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1078
Michal Vasko60ea6352020-06-29 13:39:39 +02001079 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001080 rc = lyb_parse_magic_number(lybctx->lybctx);
1081 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001082
1083 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001084 rc = lyb_parse_header(lybctx->lybctx);
1085 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001086
1087 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001088 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1089 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001090
1091 /* read subtree(s) */
Radek Krejci1798aae2020-07-14 13:26:06 +02001092 while (lybctx->lybctx->in->current[0]) {
Michal Vaskoe0665742021-02-11 11:08:44 +01001093 rc = lyb_parse_subtree_r(lybctx, parent, first_p, parsed);
1094 LY_CHECK_GOTO(rc, cleanup);
1095
1096 if (!(int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1097 break;
1098 }
1099 }
1100
1101 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1102 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1103 rc = LY_EVALID;
1104 goto cleanup;
1105 }
1106 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1107 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1108 rc = LY_EVALID;
1109 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001110 }
1111
1112 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001113 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001114
Michal Vasko60ea6352020-06-29 13:39:39 +02001115cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001116 /* there should be no unres stored if validation should be skipped */
1117 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1118 !lybctx->node_when.count));
1119
1120 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001121 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001122 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001123 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001124 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001125 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001126}
1127
1128API int
1129lyd_lyb_data_length(const char *data)
1130{
1131 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001132 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001133 int count, i;
1134 size_t len;
1135 uint8_t buf[LYB_SIZE_MAX];
1136
1137 if (!data) {
1138 return -1;
1139 }
1140
Radek Krejci1798aae2020-07-14 13:26:06 +02001141 lybctx = calloc(1, sizeof *lybctx);
1142 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1143 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001144 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001145
1146 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001147 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001148 LY_CHECK_GOTO(ret, cleanup);
1149
1150 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001151 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001152 LY_CHECK_GOTO(ret, cleanup);
1153
1154 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001155 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001156
1157 /* read all models */
1158 for (i = 0; i < count; ++i) {
1159 /* module name length */
1160 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001161 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001162
1163 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001164 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001165
1166 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001167 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001168 }
1169
Radek Krejci1798aae2020-07-14 13:26:06 +02001170 while (lybctx->in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001171 /* register a new subtree */
Radek Krejci1798aae2020-07-14 13:26:06 +02001172 ret = lyb_read_start_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001173 LY_CHECK_GOTO(ret, cleanup);
1174
1175 /* skip it */
Radek Krejci1798aae2020-07-14 13:26:06 +02001176 lyb_skip_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001177
1178 /* subtree finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001179 ret = lyb_read_stop_subtree(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001180 LY_CHECK_GOTO(ret, cleanup);
1181 }
1182
1183 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001184 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001185
1186cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001187 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001188
Radek Krejci1798aae2020-07-14 13:26:06 +02001189 ly_in_free(lybctx->in, 0);
1190 lylyb_ctx_free(lybctx);
1191
Michal Vasko63f3d842020-07-08 10:10:14 +02001192 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001193}