blob: 65fdb19393f782d5fbf7fcde39e41d1f95e8f146 [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"
27#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020028#include "parser_data.h"
29#include "parser_internal.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020030#include "set.h"
31#include "tree.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020032#include "tree_data_internal.h"
33#include "tree_schema.h"
34#include "validation.h"
35
36/**
37 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
38 *
39 * @param[in] buf Destination buffer.
40 * @param[in] count Number of bytes to read.
41 * @param[in] lybctx LYB context.
42 */
43static void
44lyb_read(uint8_t *buf, size_t count, struct lyd_lyb_ctx *lybctx)
45{
Michal Vaskofd69e1d2020-07-03 11:57:17 +020046 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +020047 struct lyd_lyb_subtree *empty;
48 size_t to_read;
49 uint8_t meta_buf[LYB_META_BYTES];
50
51 assert(lybctx);
52
53 while (1) {
54 /* check for fully-read (empty) data chunks */
55 to_read = count;
56 empty = NULL;
57 LY_ARRAY_FOR(lybctx->subtrees, u) {
58 /* we want the innermost chunks resolved first, so replace previous empty chunks,
59 * also ignore chunks that are completely finished, there is nothing for us to do */
60 if ((lybctx->subtrees[u].written <= to_read) && lybctx->subtrees[u].position) {
61 /* empty chunk, do not read more */
62 to_read = lybctx->subtrees[u].written;
63 empty = &lybctx->subtrees[u];
64 }
65 }
66
67 if (!empty && !count) {
68 break;
69 }
70
71 /* we are actually reading some data, not just finishing another chunk */
72 if (to_read) {
73 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +020074 ly_in_read(lybctx->in, buf, to_read);
75 } else {
76 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +020077 }
78
79 LY_ARRAY_FOR(lybctx->subtrees, u) {
80 /* decrease all written counters */
81 lybctx->subtrees[u].written -= to_read;
82 assert(lybctx->subtrees[u].written <= LYB_SIZE_MAX);
83 }
84 /* decrease count/buf */
85 count -= to_read;
86 if (buf) {
87 buf += to_read;
88 }
Michal Vasko60ea6352020-06-29 13:39:39 +020089 }
90
91 if (empty) {
92 /* read the next chunk meta information */
Michal Vasko63f3d842020-07-08 10:10:14 +020093 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +020094 empty->written = meta_buf[0];
95 empty->inner_chunks = meta_buf[1];
96
97 /* remember whether there is a following chunk or not */
98 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
Michal Vasko60ea6352020-06-29 13:39:39 +020099 }
100 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200101}
102
103/**
104 * @brief Read a number.
105 *
106 * @param[in] num Destination buffer.
107 * @param[in] num_size Size of @p num.
108 * @param[in] bytes Number of bytes to read.
109 * @param[in] lybctx LYB context.
110 */
111static void
112lyb_read_number(void *num, size_t num_size, size_t bytes, struct lyd_lyb_ctx *lybctx)
113{
114 uint64_t buf = 0;
115
116 lyb_read((uint8_t *)&buf, bytes, lybctx);
117
118 /* correct byte order */
119 buf = le64toh(buf);
120
121 switch (num_size) {
122 case 1:
123 *((uint8_t *)num) = buf;
124 break;
125 case 2:
126 *((uint16_t *)num) = buf;
127 break;
128 case 4:
129 *((uint32_t *)num) = buf;
130 break;
131 case 8:
132 *((uint64_t *)num) = buf;
133 break;
134 default:
135 LOGINT(lybctx->ctx);
136 }
137}
138
139/**
140 * @brief Read a string.
141 *
142 * @param[in] str Destination buffer, is allocated.
143 * @param[in] with_length Whether the string is preceded with its length or it ends at the end of this subtree.
144 * @param[in] lybctx LYB context.
145 * @return LY_ERR value.
146 */
147static LY_ERR
148lyb_read_string(char **str, int with_length, struct lyd_lyb_ctx *lybctx)
149{
150 int next_chunk = 0;
151 size_t len = 0, cur_len;
152
153 *str = NULL;
154
155 if (with_length) {
156 lyb_read_number(&len, sizeof len, 2, lybctx);
157 } else {
158 /* read until the end of this subtree */
159 len = LYB_LAST_SUBTREE(lybctx).written;
160 if (LYB_LAST_SUBTREE(lybctx).position) {
161 next_chunk = 1;
162 }
163 }
164
165 *str = malloc((len + 1) * sizeof **str);
166 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
167
168 lyb_read((uint8_t *)*str, len, lybctx);
169
170 while (next_chunk) {
171 cur_len = LYB_LAST_SUBTREE(lybctx).written;
172 if (LYB_LAST_SUBTREE(lybctx).position) {
173 next_chunk = 1;
174 } else {
175 next_chunk = 0;
176 }
177
178 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
179 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
180
181 lyb_read(((uint8_t *)*str) + len, cur_len, lybctx);
182
183 len += cur_len;
184 }
185
186 ((char *)*str)[len] = '\0';
187 return LY_SUCCESS;
188}
189
190/**
191 * @brief Stop the current subtree - change LYB context state.
192 *
193 * @param[in] lybctx LYB context.
194 * @return LY_ERR value.
195 */
196static LY_ERR
197lyb_read_stop_subtree(struct lyd_lyb_ctx *lybctx)
198{
199 if (LYB_LAST_SUBTREE(lybctx).written) {
200 LOGINT_RET(lybctx->ctx);
201 }
202
203 LY_ARRAY_DECREMENT(lybctx->subtrees);
204 return LY_SUCCESS;
205}
206
207/**
208 * @brief Start a new subtree - change LYB context state but also read the expected metadata.
209 *
210 * @param[in] lybctx LYB context.
211 * @return LY_ERR value.
212 */
213static LY_ERR
214lyb_read_start_subtree(struct lyd_lyb_ctx *lybctx)
215{
216 uint8_t meta_buf[LYB_META_BYTES];
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200217 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200218
219 if (!lybctx->subtrees) {
Radek Krejcif6d14cb2020-07-02 16:11:45 +0200220 assert(lybctx->subtree_size == 0);
Michal Vasko60ea6352020-06-29 13:39:39 +0200221 u = 0;
222 } else {
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200223 u = LY_ARRAY_COUNT(lybctx->subtrees);
Michal Vasko60ea6352020-06-29 13:39:39 +0200224 }
225 if (u == lybctx->subtree_size) {
226 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
227 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
228 }
229
Michal Vasko63f3d842020-07-08 10:10:14 +0200230 LY_CHECK_RET(ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES));
Michal Vasko60ea6352020-06-29 13:39:39 +0200231
232 LY_ARRAY_INCREMENT(lybctx->subtrees);
233 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
234 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
235 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
236
Michal Vasko60ea6352020-06-29 13:39:39 +0200237 return LY_SUCCESS;
238}
239
240/**
241 * @brief Parse YANG model info.
242 *
243 * @param[in] lybctx LYB context.
244 * @param[out] mod Parsed module.
245 * @return LY_ERR value.
246 */
247static LY_ERR
248lyb_parse_model(struct lyd_lyb_ctx *lybctx, const struct lys_module **mod)
249{
250 LY_ERR ret = LY_SUCCESS;
251 char *mod_name = NULL, mod_rev[11];
252 uint16_t rev;
253
254 /* model name */
255 ret = lyb_read_string(&mod_name, 1, lybctx);
256 LY_CHECK_GOTO(ret, cleanup);
257
258 /* revision */
259 lyb_read_number(&rev, sizeof rev, 2, lybctx);
260
261 if (!mod_name[0]) {
262 /* opaq node, no module */
263 *mod = NULL;
264 goto cleanup;
265 }
266
267 if (rev) {
268 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
269 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
Radek Krejci7931b192020-06-25 17:05:03 +0200270 if ((lybctx->parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200271 /* try to use an updated module */
272 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
273 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
274 /* not an implemented module in a newer revision */
275 *mod = NULL;
276 }
277 }
278 } else {
279 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
280 }
281 /* TODO data_clb supported?
282 if (lybctx->ctx->data_clb) {
283 if (!*mod) {
284 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
285 } else if (!(*mod)->implemented) {
286 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
287 }
288 }*/
289
290 if (!*mod || !(*mod)->implemented) {
Radek Krejci7931b192020-06-25 17:05:03 +0200291 if (lybctx->parse_options & LYD_PARSE_STRICT) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200292 if (!*mod) {
293 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
294 mod_name, rev ? "@" : "", rev ? mod_rev : "");
295 } else if (!(*mod)->implemented) {
296 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
297 mod_name, rev ? "@" : "", rev ? mod_rev : "");
298 }
299 ret = LY_EINVAL;
300 goto cleanup;
301 }
302
303 }
304
305cleanup:
306 free(mod_name);
307 return ret;
308}
309
310/**
311 * @brief Parse YANG node metadata.
312 *
313 * @param[in] lybctx LYB context.
314 * @param[in] sparent Schema parent node.
315 * @param[out] meta Parsed metadata.
316 * @return LY_ERR value.
317 */
318static LY_ERR
319lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, struct lyd_meta **meta)
320{
321 LY_ERR ret = LY_SUCCESS;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200322 int dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200323 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200324 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200325 const struct lys_module *mod;
326
327 /* read number of attributes stored */
328 lyb_read(&count, 1, lybctx);
329
330 /* read attributes */
331 for (i = 0; i < count; ++i) {
332 ret = lyb_read_start_subtree(lybctx);
333 LY_CHECK_GOTO(ret, cleanup);
334
335 /* find model */
336 ret = lyb_parse_model(lybctx, &mod);
337 LY_CHECK_GOTO(ret, cleanup);
338
339 if (!mod) {
340 /* skip it */
341 do {
342 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
343 } while (LYB_LAST_SUBTREE(lybctx).written);
344 goto stop_subtree;
345 }
346
347 /* meta name */
348 ret = lyb_read_string(&meta_name, 1, lybctx);
349 LY_CHECK_GOTO(ret, cleanup);
350
351 /* meta value */
352 ret = lyb_read_string(&meta_value, 0, lybctx);
353 LY_CHECK_GOTO(ret, cleanup);
354 dynamic = 1;
355
356 /* create metadata */
357 ret = lyd_create_meta(NULL, meta, mod, meta_name, strlen(meta_name), meta_value, strlen(meta_value), &dynamic,
358 lydjson_resolve_prefix, NULL, LYD_JSON, sparent);
359
360 /* free strings */
361 free(meta_name);
362 meta_name = NULL;
363 if (dynamic) {
364 free(meta_value);
365 dynamic = 0;
366 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200367
368 if (ret == LY_EINCOMPLETE) {
369 ly_set_add(&lybctx->unres_meta_type, *meta, LY_SET_OPT_USEASLIST);
370 } else if (ret) {
371 goto cleanup;
372 }
373
374stop_subtree:
375 ret = lyb_read_stop_subtree(lybctx);
376 LY_CHECK_GOTO(ret, cleanup);
377 }
378
379cleanup:
380 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200381 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200382 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200383 *meta = NULL;
384 }
385 return ret;
386}
387
388/**
389 * @brief Parse opaque prefixes structure.
390 *
391 * @param[in] lybctx LYB context.
392 * @param[out] prefs Parsed prefixes.
393 * @return LY_ERR value.
394 */
395static LY_ERR
396lyb_parse_opaq_prefixes(struct lyd_lyb_ctx *lybctx, struct ly_prefix **prefs)
397{
398 LY_ERR ret = LY_SUCCESS;
399 uint8_t count, i;
400 char *str;
401
402 /* read count */
403 lyb_read(&count, 1, lybctx);
404 if (!count) {
405 return LY_SUCCESS;
406 }
407
408 LY_ARRAY_CREATE_RET(lybctx->ctx, *prefs, count, LY_EMEM);
409 for (i = 0; i < count; ++i) {
410 LY_ARRAY_INCREMENT(*prefs);
411
412 /* prefix */
413 ret = lyb_read_string(&str, 1, lybctx);
414 LY_CHECK_GOTO(ret, cleanup);
415 (*prefs)[i].pref = lydict_insert_zc(lybctx->ctx, str);
416
417 /* namespace */
418 ret = lyb_read_string(&str, 1, lybctx);
419 LY_CHECK_GOTO(ret, cleanup);
420 (*prefs)[i].ns = lydict_insert_zc(lybctx->ctx, str);
421 }
422
423cleanup:
424 if (ret) {
425 ly_free_val_prefs(lybctx->ctx, *prefs);
426 *prefs = NULL;
427 }
428 return ret;
429}
430
431/**
432 * @brief Parse opaque attributes.
433 *
434 * @param[in] lybctx LYB context.
435 * @param[out] attr Parsed attributes.
436 * @return LY_ERR value.
437 */
438static LY_ERR
439lyb_parse_attributes(struct lyd_lyb_ctx *lybctx, struct ly_attr **attr)
440{
441 LY_ERR ret = LY_SUCCESS;
442 uint8_t count, i;
443 struct ly_attr *attr2;
444 char *prefix = NULL, *ns = NULL, *name = NULL, *value = NULL;
445 int dynamic = 0;
446 LYD_FORMAT format = 0;
447 struct ly_prefix *val_prefs = NULL;
448
449 /* read count */
450 lyb_read(&count, 1, lybctx);
451
452 /* read attributes */
453 for (i = 0; i < count; ++i) {
454 ret = lyb_read_start_subtree(lybctx);
455 LY_CHECK_GOTO(ret, cleanup);
456
457 /* prefix, may be emtpy */
458 ret = lyb_read_string(&prefix, 1, lybctx);
459 LY_CHECK_GOTO(ret, cleanup);
460 if (!prefix[0]) {
461 free(prefix);
462 prefix = NULL;
463 }
464
465 /* namespace, may be empty */
466 ret = lyb_read_string(&ns, 1, lybctx);
467 LY_CHECK_GOTO(ret, cleanup);
468 if (!ns[0]) {
469 free(ns);
470 ns = NULL;
471 }
472
473 /* name */
474 ret = lyb_read_string(&name, 1, lybctx);
475 LY_CHECK_GOTO(ret, cleanup);
476
477 /* value prefixes */
478 ret = lyb_parse_opaq_prefixes(lybctx, &val_prefs);
479 LY_CHECK_GOTO(ret, cleanup);
480
481 /* format */
482 lyb_read((uint8_t *)&format, 1, lybctx);
483
484 /* value */
485 ret = lyb_read_string(&value, 0, lybctx);
486 LY_CHECK_GOTO(ret, cleanup);
487 dynamic = 1;
488
489 /* attr2 is always changed to the created attribute */
490 ret = ly_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format,
491 val_prefs, prefix, prefix ? strlen(prefix) : 0, ns);
492 LY_CHECK_GOTO(ret, cleanup);
493
494 free(prefix);
495 prefix = NULL;
496 free(ns);
497 ns = NULL;
498 free(name);
499 name = NULL;
500 val_prefs = NULL;
501 assert(!dynamic);
502 value = NULL;
503
504 if (!*attr) {
505 *attr = attr2;
506 }
507
508 ret = lyb_read_stop_subtree(lybctx);
509 LY_CHECK_GOTO(ret, cleanup);
510 }
511
512cleanup:
513 free(prefix);
514 free(ns);
515 free(name);
516 if (dynamic) {
517 free(value);
518 }
519 ly_free_val_prefs(lybctx->ctx, val_prefs);
520 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200521 ly_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200522 *attr = NULL;
523 }
524 return ret;
525}
526
527/**
528 * @brief Check whether a schema node matches a hash(es).
529 *
530 * @param[in] sibling Schema node to check.
531 * @param[in] hash Hash array to check.
532 * @param[in] hash_count Number of hashes in @p hash.
533 * @return non-zero if matches,
534 * @return 0 if not.
535 */
536static int
537lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
538{
539 LYB_HASH sibling_hash;
540 uint8_t i;
541
542 /* compare all the hashes starting from collision ID 0 */
543 for (i = 0; i < hash_count; ++i) {
544 sibling_hash = lyb_hash(sibling, i);
545 if (sibling_hash != hash[i]) {
546 return 0;
547 }
548 }
549
550 return 1;
551}
552
553/**
554 * @brief Check that a schema node is suitable based on options.
555 *
556 * @param[in] lybctx LYB context.
557 * @param[in] snode Schema node to check.
558 * @return LY_ERR value.
559 */
560static LY_ERR
561lyb_parse_check_schema(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode)
562{
563 LY_ERR ret = LY_SUCCESS;
564
Radek Krejci7931b192020-06-25 17:05:03 +0200565 if ((lybctx->parse_options & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200566 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LY_VCODE_INNODE, "state", snode->name);
567 return LY_EVALID;
568 }
569
570 if (snode->nodetype & (LYS_RPC | LYS_ACTION)) {
571 if (lybctx->int_opts & LYD_INTOPT_RPC) {
572 if (lybctx->op_ntf) {
573 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
574 lys_nodetype2str(snode->nodetype), snode->name,
575 lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
576 return LY_EVALID;
577 }
578 } else {
579 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
580 lys_nodetype2str(snode->nodetype), snode->name);
581 return LY_EVALID;
582 }
583 } else if (snode->nodetype == LYS_NOTIF) {
584 if (lybctx->int_opts & LYD_INTOPT_NOTIF) {
585 if (lybctx->op_ntf) {
586 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
587 lys_nodetype2str(snode->nodetype), snode->name,
588 lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
589 return LY_EVALID;
590 }
591 } else {
592 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
593 lys_nodetype2str(snode->nodetype), snode->name);
594 return LY_EVALID;
595 }
596 }
597
598 return ret;
599}
600
601/**
602 * @brief Parse schema node hash.
603 *
604 * @param[in] lybctx LYB context.
605 * @param[in] sparent Schema parent, must be set if @p mod is not.
606 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
607 * @param[out] snode Parsed found schema node, may be NULL if opaque.
608 * @return LY_ERR value.
609 */
610static LY_ERR
611lyb_parse_schema_hash(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, const struct lys_module *mod,
612 const struct lysc_node **snode)
613{
614 LY_ERR ret;
615 uint8_t i, j;
616 const struct lysc_node *sibling;
617 LYB_HASH hash[LYB_HASH_BITS - 1];
618 int getnext_opts;
619
620 *snode = NULL;
621 /* leave if-feature check for validation */
622 getnext_opts = LYS_GETNEXT_NOSTATECHECK | (lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0);
623
624 /* read the first hash */
625 lyb_read(&hash[0], sizeof *hash, lybctx);
626
627 if (!hash[0]) {
628 /* opaque node */
629 return LY_SUCCESS;
630 }
631
632 /* based on the first hash read all the other ones, if any */
633 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
634 if (i > LYB_HASH_BITS) {
635 LOGINT_RET(lybctx->ctx);
636 }
637 }
638
639 /* move the first hash on its accurate position */
640 hash[i] = hash[0];
641
642 /* read the rest of hashes */
643 for (j = i; j; --j) {
644 lyb_read(&hash[j - 1], sizeof *hash, lybctx);
645
646 /* correct collision ID */
647 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
648 /* preceded with zeros */
649 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
650 }
651
652 /* find our node with matching hashes */
653 sibling = NULL;
654 while ((sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts))) {
655 /* skip schema nodes from models not present during printing */
656 if (lyb_has_schema_model(sibling, lybctx->models)
657 && lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
658 /* match found */
659 break;
660 }
661 }
662
Radek Krejci7931b192020-06-25 17:05:03 +0200663 if (!sibling && (lybctx->parse_options & LYD_PARSE_STRICT)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200664 if (mod) {
665 LOGVAL(lybctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
666 " from \"%s\".", mod->name);
667 } else {
668 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, sparent, LYVE_REFERENCE, "Failed to find matching hash for a child node"
669 " of \"%s\".", sparent->name);
670 }
671 return LY_EVALID;
672 } else if (sibling && (ret = lyb_parse_check_schema(lybctx, sibling))) {
673 return ret;
674 }
675
676 *snode = sibling;
677 return LY_SUCCESS;
678}
679
680/**
681 * @brief Read until the end of the current subtree.
682 *
683 * @param[in] lybctx LYB context.
684 */
685static void
686lyb_skip_subtree(struct lyd_lyb_ctx *lybctx)
687{
Michal Vasko60ea6352020-06-29 13:39:39 +0200688 do {
689 /* first skip any meta information inside */
Michal Vasko63f3d842020-07-08 10:10:14 +0200690 ly_in_skip(lybctx->in, LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200691
692 /* then read data */
693 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
694 } while (LYB_LAST_SUBTREE(lybctx).written);
695}
696
697/**
698 * @brief Parse LYB subtree.
699 *
700 * @param[in] lybctx LYB context.
701 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
702 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
703 * @return LY_ERR value.
704 */
705static LY_ERR
706lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node_inner *parent, struct lyd_node **first)
707{
708 LY_ERR ret = LY_SUCCESS;
709 struct lyd_node *node = NULL, *tree;
710 const struct lys_module *mod;
711 const struct lysc_node *snode = NULL;
712 struct lyd_meta *meta = NULL, *m;
713 struct ly_attr *attr = NULL, *a;
714 struct ly_prefix *val_prefs = NULL;
715 LYD_ANYDATA_VALUETYPE value_type;
716 char *value = NULL, *name = NULL, *prefix = NULL, *ns = NULL;
717 int dynamic = 0;
718 LYD_FORMAT format = 0;
719 int prev_lo;
720
721 /* register a new subtree */
722 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx), cleanup);
723
724 if (!parent) {
725 /* top-level, read module name */
726 ret = lyb_parse_model(lybctx, &mod);
727 LY_CHECK_GOTO(ret, cleanup);
728
729 /* read hash, find the schema node starting from mod */
730 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
731 LY_CHECK_GOTO(ret, cleanup);
732 } else {
733 /* read hash, find the schema node starting from parent schema */
734 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
735 LY_CHECK_GOTO(ret, cleanup);
736 }
737
Radek Krejci7931b192020-06-25 17:05:03 +0200738 if (!snode && !(lybctx->parse_options & LYD_PARSE_OPAQ)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200739 /* unknown data, skip them */
740 lyb_skip_subtree(lybctx);
741 goto stop_subtree;
742 }
743
744 /* create metadata/attributes */
745 if (snode) {
746 ret = lyb_parse_metadata(lybctx, snode, &meta);
747 LY_CHECK_GOTO(ret, cleanup);
748 } else {
749 ret = lyb_parse_attributes(lybctx, &attr);
750 LY_CHECK_GOTO(ret, cleanup);
751 }
752
753 if (!snode) {
754 /* parse prefix */
755 ret = lyb_read_string(&prefix, 1, lybctx);
756 LY_CHECK_GOTO(ret, cleanup);
757
758 /* parse namespace */
759 ret = lyb_read_string(&ns, 1, lybctx);
760 LY_CHECK_GOTO(ret, cleanup);
761
762 /* parse name */
763 ret = lyb_read_string(&name, 1, lybctx);
764 LY_CHECK_GOTO(ret, cleanup);
765
766 /* parse value prefixes */
767 ret = lyb_parse_opaq_prefixes(lybctx, &val_prefs);
768 LY_CHECK_GOTO(ret, cleanup);
769
770 /* parse format */
771 lyb_read((uint8_t *)&format, 1, lybctx);
772
773 /* parse value */
774 ret = lyb_read_string(&value, 0, lybctx);
775 LY_CHECK_GOTO(ret, cleanup);
776 dynamic = 1;
777
778 /* create node */
779 ret = lyd_create_opaq(lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format, val_prefs, prefix,
780 strlen(prefix), ns, &node);
781 LY_CHECK_GOTO(ret, cleanup);
782
783 /* process children */
784 while (LYB_LAST_SUBTREE(lybctx).written) {
785 ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
786 LY_CHECK_GOTO(ret, cleanup);
787 }
788 } else if (snode->nodetype & LYD_NODE_TERM) {
789 /* parse value */
790 ret = lyb_read_string(&value, 0, lybctx);
791 LY_CHECK_GOTO(ret, cleanup);
792 dynamic = 1;
793
794 /* create node */
795 ret = lyd_create_term(snode, value, strlen(value), &dynamic, lydjson_resolve_prefix, NULL, LYD_JSON, &node);
796 if (dynamic) {
797 free(value);
798 dynamic = 0;
799 }
800 value = NULL;
801 if (ret == LY_EINCOMPLETE) {
Radek Krejci7931b192020-06-25 17:05:03 +0200802 if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200803 ly_set_add(&lybctx->unres_node_type, node, LY_SET_OPT_USEASLIST);
804 }
805 ret = LY_SUCCESS;
806 } else if (ret) {
807 goto cleanup;
808 }
809 } else if (snode->nodetype & LYD_NODE_INNER) {
810 /* create node */
811 ret = lyd_create_inner(snode, &node);
812 LY_CHECK_GOTO(ret, cleanup);
813
814 /* process children */
815 while (LYB_LAST_SUBTREE(lybctx).written) {
816 ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
817 LY_CHECK_GOTO(ret, cleanup);
818 }
819
Radek Krejci7931b192020-06-25 17:05:03 +0200820 if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200821 /* new node validation, autodelete CANNOT occur, all nodes are new */
Michal Vasko8104fd42020-07-13 11:09:51 +0200822 ret = lyd_validate_new(lyd_node_children_p(node), snode, NULL, NULL);
Michal Vasko60ea6352020-06-29 13:39:39 +0200823 LY_CHECK_GOTO(ret, cleanup);
824
825 /* add any missing default children */
Michal Vaskoa6669ba2020-08-06 16:14:26 +0200826 ret = lyd_new_implicit_r(node, lyd_node_children_p(node), NULL, NULL, &lybctx->unres_node_type,
827 &lybctx->when_check, (lybctx->validate_options & LYD_VALIDATE_NO_STATE)
828 ? 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 */
834 lybctx->op_ntf = node;
835 }
836 } else if (snode->nodetype & LYD_NODE_ANY) {
837 /* parse value type */
838 lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx);
839 if (value_type == LYD_ANYDATA_DATATREE) {
840 /* invalid situation */
841 LOGINT(lybctx->ctx);
842 goto cleanup;
843 }
844
845 /* read anydata content */
846 ret = lyb_read_string(&value, 0, lybctx);
847 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 Krejci7931b192020-06-25 17:05:03 +0200855 if (lyd_parse_data_mem((struct ly_ctx *)lybctx->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
866 /* create node */
867 ret = lyd_create_any(snode, value, value_type, &node);
868 LY_CHECK_GOTO(ret, cleanup);
869
870 dynamic = 0;
871 value = NULL;
872 }
873 assert(node);
874
875 /* add/correct flags */
876 if (snode) {
Radek Krejci7931b192020-06-25 17:05:03 +0200877 lyd_parse_set_data_flags(node, &lybctx->when_check, &meta, lybctx->parse_options);
Michal Vasko60ea6352020-06-29 13:39:39 +0200878 }
879
880 /* add metadata/attributes */
881 if (snode) {
882 LY_LIST_FOR(meta, m) {
883 m->parent = node;
884 }
885 node->meta = meta;
886 meta = NULL;
887 } else {
888 assert(!node->schema);
889 LY_LIST_FOR(attr, a) {
890 a->parent = (struct lyd_node_opaq *)node;
891 }
892 ((struct lyd_node_opaq *)node)->attr = attr;
893 attr = NULL;
894 }
895
Michal Vaskob104f112020-07-17 09:54:54 +0200896 /* insert, keep first pointer correct */
Michal Vasko60ea6352020-06-29 13:39:39 +0200897 lyd_insert_node((struct lyd_node *)parent, first, node);
Michal Vaskob104f112020-07-17 09:54:54 +0200898 while (!parent && (*first)->prev->next) {
899 *first = (*first)->prev;
900 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200901 node = NULL;
902
903stop_subtree:
904 /* end the subtree */
905 ret = lyb_read_stop_subtree(lybctx);
906 LY_CHECK_GOTO(ret, cleanup);
907
908cleanup:
909 free(prefix);
910 free(ns);
911 free(name);
912 if (dynamic) {
913 free(value);
914 }
915 ly_free_val_prefs(lybctx->ctx, val_prefs);
916
Michal Vasko3a41dff2020-07-15 14:30:28 +0200917 lyd_free_meta_siblings(meta);
918 ly_free_attr_siblings(lybctx->ctx, attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200919 lyd_free_tree(node);
920 return ret;
921}
922
923/**
924 * @brief Parse used YANG data models.
925 *
926 * @param[in] lybctx LYB context.
927 * @return LY_ERR value.
928 */
929static LY_ERR
930lyb_parse_data_models(struct lyd_lyb_ctx *lybctx)
931{
932 LY_ERR ret;
933 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200934 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200935
936 /* read model count */
937 lyb_read_number(&count, sizeof count, 2, lybctx);
938
939 if (count) {
940 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
941
942 /* read modules */
943 for (u = 0; u < count; ++u) {
944 ret = lyb_parse_model(lybctx, &lybctx->models[u]);
945 LY_CHECK_RET(ret);
946 LY_ARRAY_INCREMENT(lybctx->models);
947 }
948 }
949
950 return LY_SUCCESS;
951}
952
953/**
954 * @brief Parse LYB magic number.
955 *
956 * @param[in] lybctx LYB context.
957 * @return LY_ERR value.
958 */
959static LY_ERR
960lyb_parse_magic_number(struct lyd_lyb_ctx *lybctx)
961{
962 char magic_byte = 0;
963
964 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
965 if (magic_byte != 'l') {
966 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
967 return LY_EINVAL;
968 }
969
970 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
971 if (magic_byte != 'y') {
972 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
973 return LY_EINVAL;
974 }
975
976 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
977 if (magic_byte != 'b') {
978 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
979 return LY_EINVAL;
980 }
981
982 return LY_SUCCESS;
983}
984
985/**
986 * @brief Parse LYB header.
987 *
988 * @param[in] lybctx LYB context.
989 * @return LY_ERR value.
990 */
991static LY_ERR
992lyb_parse_header(struct lyd_lyb_ctx *lybctx)
993{
994 uint8_t byte = 0;
995
996 /* version, future flags */
997 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
998
999 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1000 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
1001 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
1002 return LY_EINVAL;
1003 }
1004
1005 return LY_SUCCESS;
1006}
1007
1008LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001009lyd_parse_lyb_data(const struct ly_ctx *ctx, struct ly_in *in, int parse_options, int validate_options,
1010 struct lyd_node **tree)
Michal Vasko60ea6352020-06-29 13:39:39 +02001011{
1012 LY_ERR ret = LY_SUCCESS;
1013 struct lyd_lyb_ctx lybctx = {0};
1014
Radek Krejci7931b192020-06-25 17:05:03 +02001015 assert(!(parse_options & ~LYD_PARSE_OPTS_MASK));
1016 assert(!(validate_options & ~LYD_VALIDATE_OPTS_MASK));
1017
Michal Vasko60ea6352020-06-29 13:39:39 +02001018 *tree = NULL;
1019
Michal Vasko63f3d842020-07-08 10:10:14 +02001020 lybctx.in = in;
Michal Vasko60ea6352020-06-29 13:39:39 +02001021 lybctx.ctx = ctx;
Radek Krejci7931b192020-06-25 17:05:03 +02001022 lybctx.parse_options = parse_options;
1023 lybctx.validate_options = validate_options;
Michal Vasko60ea6352020-06-29 13:39:39 +02001024
1025 /* read magic number */
1026 ret = lyb_parse_magic_number(&lybctx);
1027 LY_CHECK_GOTO(ret, cleanup);
1028
1029 /* read header */
1030 ret = lyb_parse_header(&lybctx);
1031 LY_CHECK_GOTO(ret, cleanup);
1032
1033 /* read used models */
1034 ret = lyb_parse_data_models(&lybctx);
1035 LY_CHECK_GOTO(ret, cleanup);
1036
1037 /* read subtree(s) */
Michal Vasko63f3d842020-07-08 10:10:14 +02001038 while (lybctx.in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001039 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1040 LY_CHECK_GOTO(ret, cleanup);
1041 }
1042
1043 /* read the last zero, parsing finished */
Michal Vasko63f3d842020-07-08 10:10:14 +02001044 ly_in_skip(lybctx.in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001045
1046 /* TODO validation */
1047
1048cleanup:
1049 LY_ARRAY_FREE(lybctx.subtrees);
1050 LY_ARRAY_FREE(lybctx.models);
1051 ly_set_erase(&lybctx.unres_node_type, NULL);
1052 ly_set_erase(&lybctx.unres_meta_type, NULL);
1053 ly_set_erase(&lybctx.when_check, NULL);
1054
Michal Vasko60ea6352020-06-29 13:39:39 +02001055 if (ret) {
1056 lyd_free_all(*tree);
1057 *tree = NULL;
1058 }
1059 return ret;
1060}
1061
1062LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001063lyd_parse_lyb_rpc(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree, struct lyd_node **op)
Michal Vasko60ea6352020-06-29 13:39:39 +02001064{
1065 LY_ERR ret = LY_SUCCESS;
1066 struct lyd_lyb_ctx lybctx = {0};
1067
Michal Vasko63f3d842020-07-08 10:10:14 +02001068 lybctx.in = in;
Michal Vasko60ea6352020-06-29 13:39:39 +02001069 lybctx.ctx = ctx;
Radek Krejci7931b192020-06-25 17:05:03 +02001070 lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
Michal Vasko60ea6352020-06-29 13:39:39 +02001071 lybctx.int_opts = LYD_INTOPT_RPC;
1072
1073 *tree = NULL;
1074 if (op) {
1075 *op = NULL;
1076 }
1077
1078 /* read magic number */
1079 ret = lyb_parse_magic_number(&lybctx);
1080 LY_CHECK_GOTO(ret, cleanup);
1081
1082 /* read header */
1083 ret = lyb_parse_header(&lybctx);
1084 LY_CHECK_GOTO(ret, cleanup);
1085
1086 /* read used models */
1087 ret = lyb_parse_data_models(&lybctx);
1088 LY_CHECK_GOTO(ret, cleanup);
1089
1090 /* read subtree(s) */
Michal Vasko63f3d842020-07-08 10:10:14 +02001091 while (lybctx.in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001092 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1093 LY_CHECK_GOTO(ret, cleanup);
1094 }
1095
1096 /* read the last zero, parsing finished */
Michal Vasko63f3d842020-07-08 10:10:14 +02001097 ly_in_skip(lybctx.in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001098
1099 /* make sure we have parsed some operation */
1100 if (!lybctx.op_ntf) {
1101 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"rpc\"/\"action\" node.");
1102 ret = LY_EVALID;
1103 goto cleanup;
1104 }
1105
1106 if (op) {
1107 *op = lybctx.op_ntf;
1108 }
1109 assert(*tree);
1110
1111cleanup:
1112 LY_ARRAY_FREE(lybctx.subtrees);
1113 LY_ARRAY_FREE(lybctx.models);
1114 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1115
Michal Vasko60ea6352020-06-29 13:39:39 +02001116 if (ret) {
1117 lyd_free_all(*tree);
1118 *tree = NULL;
1119 }
1120 return ret;
1121}
1122
1123LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001124lyd_parse_lyb_notif(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree, struct lyd_node **ntf)
Michal Vasko60ea6352020-06-29 13:39:39 +02001125{
1126 LY_ERR ret = LY_SUCCESS;
1127 struct lyd_lyb_ctx lybctx = {0};
1128
Michal Vasko63f3d842020-07-08 10:10:14 +02001129 lybctx.in = in;
Michal Vasko60ea6352020-06-29 13:39:39 +02001130 lybctx.ctx = ctx;
Radek Krejci7931b192020-06-25 17:05:03 +02001131 lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
Michal Vasko60ea6352020-06-29 13:39:39 +02001132 lybctx.int_opts = LYD_INTOPT_NOTIF;
1133
1134 *tree = NULL;
1135 if (ntf) {
1136 *ntf = NULL;
1137 }
1138
1139 /* read magic number */
1140 ret = lyb_parse_magic_number(&lybctx);
1141 LY_CHECK_GOTO(ret, cleanup);
1142
1143 /* read header */
1144 ret = lyb_parse_header(&lybctx);
1145 LY_CHECK_GOTO(ret, cleanup);
1146
1147 /* read used models */
1148 ret = lyb_parse_data_models(&lybctx);
1149 LY_CHECK_GOTO(ret, cleanup);
1150
1151 /* read subtree(s) */
Michal Vasko63f3d842020-07-08 10:10:14 +02001152 while (lybctx.in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001153 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1154 LY_CHECK_GOTO(ret, cleanup);
1155 }
1156
1157 /* read the last zero, parsing finished */
Michal Vasko63f3d842020-07-08 10:10:14 +02001158 ly_in_skip(lybctx.in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001159
1160 /* make sure we have parsed some notification */
1161 if (!lybctx.op_ntf) {
1162 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
1163 ret = LY_EVALID;
1164 goto cleanup;
1165 }
1166
1167 if (ntf) {
1168 *ntf = lybctx.op_ntf;
1169 }
1170 assert(*tree);
1171
1172cleanup:
1173 LY_ARRAY_FREE(lybctx.subtrees);
1174 LY_ARRAY_FREE(lybctx.models);
1175 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1176
Michal Vasko60ea6352020-06-29 13:39:39 +02001177 if (ret) {
1178 lyd_free_all(*tree);
1179 *tree = NULL;
1180 }
1181 return ret;
1182}
1183
1184LY_ERR
Michal Vasko63f3d842020-07-08 10:10:14 +02001185lyd_parse_lyb_reply(const struct lyd_node *request, struct ly_in *in, struct lyd_node **tree, struct lyd_node **op)
Michal Vasko60ea6352020-06-29 13:39:39 +02001186{
1187 LY_ERR ret = LY_SUCCESS;
1188 struct lyd_lyb_ctx lybctx = {0};
1189 struct lyd_node *iter, *req_op, *rep_op = NULL;
1190
Michal Vasko63f3d842020-07-08 10:10:14 +02001191 lybctx.in = in;
Michal Vasko60ea6352020-06-29 13:39:39 +02001192 lybctx.ctx = LYD_NODE_CTX(request);
Radek Krejci7931b192020-06-25 17:05:03 +02001193 lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
Michal Vasko60ea6352020-06-29 13:39:39 +02001194 lybctx.int_opts = LYD_INTOPT_REPLY;
1195
1196 *tree = NULL;
1197 if (op) {
1198 *op = NULL;
1199 }
1200
1201 /* find request OP */
1202 LYD_TREE_DFS_BEGIN((struct lyd_node *)request, iter, req_op) {
1203 if (req_op->schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1204 break;
1205 }
1206 LYD_TREE_DFS_END(request, iter, req_op);
1207 }
1208 if (!(req_op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
1209 LOGERR(LYD_NODE_CTX(request), LY_EINVAL, "No RPC/action in the request found.");
1210 ret = LY_EINVAL;
1211 goto cleanup;
1212 }
1213
1214 /* duplicate request OP with parents */
Michal Vasko3a41dff2020-07-15 14:30:28 +02001215 ret = lyd_dup_single(req_op, NULL, LYD_DUP_WITH_PARENTS, &rep_op);
1216 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001217
1218 /* read magic number */
1219 ret = lyb_parse_magic_number(&lybctx);
1220 LY_CHECK_GOTO(ret, cleanup);
1221
1222 /* read header */
1223 ret = lyb_parse_header(&lybctx);
1224 LY_CHECK_GOTO(ret, cleanup);
1225
1226 /* read used models */
1227 ret = lyb_parse_data_models(&lybctx);
1228 LY_CHECK_GOTO(ret, cleanup);
1229
1230 /* read subtree(s) */
Michal Vasko63f3d842020-07-08 10:10:14 +02001231 while (lybctx.in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001232 ret = lyb_parse_subtree_r(&lybctx, (struct lyd_node_inner *)rep_op, NULL);
1233 LY_CHECK_GOTO(ret, cleanup);
1234 }
1235
1236 /* read the last zero, parsing finished */
Michal Vasko63f3d842020-07-08 10:10:14 +02001237 ly_in_skip(lybctx.in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001238
1239 if (op) {
1240 *op = rep_op;
1241 }
1242 for (iter = rep_op; iter->parent; iter = (struct lyd_node *)iter->parent);
1243 *tree = iter;
1244 rep_op = NULL;
1245
1246cleanup:
1247 lyd_free_all(rep_op);
1248 LY_ARRAY_FREE(lybctx.subtrees);
1249 LY_ARRAY_FREE(lybctx.models);
1250 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1251
Michal Vasko60ea6352020-06-29 13:39:39 +02001252 if (ret) {
1253 lyd_free_all(*tree);
1254 *tree = NULL;
1255 }
1256 return ret;
1257}
1258
1259API int
1260lyd_lyb_data_length(const char *data)
1261{
1262 LY_ERR ret = LY_SUCCESS;
1263 struct lyd_lyb_ctx lybctx = {0};
1264 int count, i;
1265 size_t len;
1266 uint8_t buf[LYB_SIZE_MAX];
1267
1268 if (!data) {
1269 return -1;
1270 }
1271
Michal Vasko63f3d842020-07-08 10:10:14 +02001272 ret = ly_in_new_memory(data, &lybctx.in);
1273 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001274
1275 /* read magic number */
1276 ret = lyb_parse_magic_number(&lybctx);
1277 LY_CHECK_GOTO(ret, cleanup);
1278
1279 /* read header */
1280 ret = lyb_parse_header(&lybctx);
1281 LY_CHECK_GOTO(ret, cleanup);
1282
1283 /* read model count */
1284 lyb_read_number(&count, sizeof count, 2, &lybctx);
1285
1286 /* read all models */
1287 for (i = 0; i < count; ++i) {
1288 /* module name length */
1289 len = 0;
1290 lyb_read_number(&len, sizeof len, 2, &lybctx);
1291
1292 /* model name */
1293 lyb_read(buf, len, &lybctx);
1294
1295 /* revision */
1296 lyb_read(buf, 2, &lybctx);
1297 }
1298
Michal Vasko63f3d842020-07-08 10:10:14 +02001299 while (lybctx.in->current[0]) {
Michal Vasko60ea6352020-06-29 13:39:39 +02001300 /* register a new subtree */
1301 ret = lyb_read_start_subtree(&lybctx);
1302 LY_CHECK_GOTO(ret, cleanup);
1303
1304 /* skip it */
1305 lyb_skip_subtree(&lybctx);
1306
1307 /* subtree finished */
1308 ret = lyb_read_stop_subtree(&lybctx);
1309 LY_CHECK_GOTO(ret, cleanup);
1310 }
1311
1312 /* read the last zero, parsing finished */
Michal Vasko63f3d842020-07-08 10:10:14 +02001313 ly_in_skip(lybctx.in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001314
1315cleanup:
Michal Vasko63f3d842020-07-08 10:10:14 +02001316 count = lybctx.in->current - lybctx.in->start;
1317
1318 ly_in_free(lybctx.in, 0);
Michal Vasko60ea6352020-06-29 13:39:39 +02001319 LY_ARRAY_FREE(lybctx.subtrees);
Michal Vasko63f3d842020-07-08 10:10:14 +02001320 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001321}