blob: 27107518fc70d39e10a8ec84c26ac26dd78a429b [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>
18#include <errno.h>
19#include <inttypes.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "common.h"
25#include "compat.h"
26#include "tree_data_internal.h"
27#include "tree_schema.h"
28#include "validation.h"
29
30/**
31 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
32 *
33 * @param[in] buf Destination buffer.
34 * @param[in] count Number of bytes to read.
35 * @param[in] lybctx LYB context.
36 */
37static void
38lyb_read(uint8_t *buf, size_t count, struct lyd_lyb_ctx *lybctx)
39{
40 int parsed = 0;
41 LY_ARRAY_SIZE_TYPE u;
42 struct lyd_lyb_subtree *empty;
43 size_t to_read;
44 uint8_t meta_buf[LYB_META_BYTES];
45
46 assert(lybctx);
47
48 while (1) {
49 /* check for fully-read (empty) data chunks */
50 to_read = count;
51 empty = NULL;
52 LY_ARRAY_FOR(lybctx->subtrees, u) {
53 /* we want the innermost chunks resolved first, so replace previous empty chunks,
54 * also ignore chunks that are completely finished, there is nothing for us to do */
55 if ((lybctx->subtrees[u].written <= to_read) && lybctx->subtrees[u].position) {
56 /* empty chunk, do not read more */
57 to_read = lybctx->subtrees[u].written;
58 empty = &lybctx->subtrees[u];
59 }
60 }
61
62 if (!empty && !count) {
63 break;
64 }
65
66 /* we are actually reading some data, not just finishing another chunk */
67 if (to_read) {
68 if (buf) {
69 memcpy(buf, lybctx->data + parsed, to_read);
70 }
71
72 LY_ARRAY_FOR(lybctx->subtrees, u) {
73 /* decrease all written counters */
74 lybctx->subtrees[u].written -= to_read;
75 assert(lybctx->subtrees[u].written <= LYB_SIZE_MAX);
76 }
77 /* decrease count/buf */
78 count -= to_read;
79 if (buf) {
80 buf += to_read;
81 }
82
83 parsed += to_read;
84 }
85
86 if (empty) {
87 /* read the next chunk meta information */
88 memcpy(meta_buf, lybctx->data + parsed, LYB_META_BYTES);
89 empty->written = meta_buf[0];
90 empty->inner_chunks = meta_buf[1];
91
92 /* remember whether there is a following chunk or not */
93 empty->position = (empty->written == LYB_SIZE_MAX ? 1 : 0);
94
95 parsed += LYB_META_BYTES;
96 }
97 }
98
99 lybctx->byte_count += parsed;
100 lybctx->data += parsed;
101}
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];
217 LY_ARRAY_SIZE_TYPE u;
218
219 if (!lybctx->subtrees) {
220 u = 0;
221 } else {
222 u = LY_ARRAY_SIZE(lybctx->subtrees);
223 }
224 if (u == lybctx->subtree_size) {
225 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->subtrees, u + LYB_SUBTREE_STEP, LY_EMEM);
226 lybctx->subtree_size = u + LYB_SUBTREE_STEP;
227 }
228
229 memcpy(meta_buf, lybctx->data, LYB_META_BYTES);
230
231 LY_ARRAY_INCREMENT(lybctx->subtrees);
232 LYB_LAST_SUBTREE(lybctx).written = meta_buf[0];
233 LYB_LAST_SUBTREE(lybctx).inner_chunks = meta_buf[LYB_SIZE_BYTES];
234 LYB_LAST_SUBTREE(lybctx).position = (LYB_LAST_SUBTREE(lybctx).written == LYB_SIZE_MAX ? 1 : 0);
235
236 lybctx->byte_count += LYB_META_BYTES;
237 lybctx->data += LYB_META_BYTES;
238 return LY_SUCCESS;
239}
240
241/**
242 * @brief Parse YANG model info.
243 *
244 * @param[in] lybctx LYB context.
245 * @param[out] mod Parsed module.
246 * @return LY_ERR value.
247 */
248static LY_ERR
249lyb_parse_model(struct lyd_lyb_ctx *lybctx, const struct lys_module **mod)
250{
251 LY_ERR ret = LY_SUCCESS;
252 char *mod_name = NULL, mod_rev[11];
253 uint16_t rev;
254
255 /* model name */
256 ret = lyb_read_string(&mod_name, 1, lybctx);
257 LY_CHECK_GOTO(ret, cleanup);
258
259 /* revision */
260 lyb_read_number(&rev, sizeof rev, 2, lybctx);
261
262 if (!mod_name[0]) {
263 /* opaq node, no module */
264 *mod = NULL;
265 goto cleanup;
266 }
267
268 if (rev) {
269 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
270 *mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
271 if ((lybctx->options & LYD_OPT_LYB_MOD_UPDATE) && !(*mod)) {
272 /* try to use an updated module */
273 *mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
274 if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
275 /* not an implemented module in a newer revision */
276 *mod = NULL;
277 }
278 }
279 } else {
280 *mod = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
281 }
282 /* TODO data_clb supported?
283 if (lybctx->ctx->data_clb) {
284 if (!*mod) {
285 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, NULL, 0, lybctx->ctx->data_clb_data);
286 } else if (!(*mod)->implemented) {
287 *mod = lybctx->ctx->data_clb(lybctx->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybctx->ctx->data_clb_data);
288 }
289 }*/
290
291 if (!*mod || !(*mod)->implemented) {
292 if (lybctx->options & LYD_OPT_STRICT) {
293 if (!*mod) {
294 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
295 mod_name, rev ? "@" : "", rev ? mod_rev : "");
296 } else if (!(*mod)->implemented) {
297 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
298 mod_name, rev ? "@" : "", rev ? mod_rev : "");
299 }
300 ret = LY_EINVAL;
301 goto cleanup;
302 }
303
304 }
305
306cleanup:
307 free(mod_name);
308 return ret;
309}
310
311/**
312 * @brief Parse YANG node metadata.
313 *
314 * @param[in] lybctx LYB context.
315 * @param[in] sparent Schema parent node.
316 * @param[out] meta Parsed metadata.
317 * @return LY_ERR value.
318 */
319static LY_ERR
320lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, struct lyd_meta **meta)
321{
322 LY_ERR ret = LY_SUCCESS;
323 int dynamic = 0;
324 uint8_t i, count = 0;
325 char *meta_name = NULL, *meta_value = NULL;
326 const struct lys_module *mod;
327
328 /* read number of attributes stored */
329 lyb_read(&count, 1, lybctx);
330
331 /* read attributes */
332 for (i = 0; i < count; ++i) {
333 ret = lyb_read_start_subtree(lybctx);
334 LY_CHECK_GOTO(ret, cleanup);
335
336 /* find model */
337 ret = lyb_parse_model(lybctx, &mod);
338 LY_CHECK_GOTO(ret, cleanup);
339
340 if (!mod) {
341 /* skip it */
342 do {
343 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
344 } while (LYB_LAST_SUBTREE(lybctx).written);
345 goto stop_subtree;
346 }
347
348 /* meta name */
349 ret = lyb_read_string(&meta_name, 1, lybctx);
350 LY_CHECK_GOTO(ret, cleanup);
351
352 /* meta value */
353 ret = lyb_read_string(&meta_value, 0, lybctx);
354 LY_CHECK_GOTO(ret, cleanup);
355 dynamic = 1;
356
357 /* create metadata */
358 ret = lyd_create_meta(NULL, meta, mod, meta_name, strlen(meta_name), meta_value, strlen(meta_value), &dynamic,
359 lydjson_resolve_prefix, NULL, LYD_JSON, sparent);
360
361 /* free strings */
362 free(meta_name);
363 meta_name = NULL;
364 if (dynamic) {
365 free(meta_value);
366 dynamic = 0;
367 }
368 meta_value = NULL;
369
370 if (ret == LY_EINCOMPLETE) {
371 ly_set_add(&lybctx->unres_meta_type, *meta, LY_SET_OPT_USEASLIST);
372 } else if (ret) {
373 goto cleanup;
374 }
375
376stop_subtree:
377 ret = lyb_read_stop_subtree(lybctx);
378 LY_CHECK_GOTO(ret, cleanup);
379 }
380
381cleanup:
382 free(meta_name);
383 if (dynamic) {
384 free(meta_value);
385 }
386 if (ret) {
387 lyd_free_meta(lybctx->ctx, *meta, 1);
388 *meta = NULL;
389 }
390 return ret;
391}
392
393/**
394 * @brief Parse opaque prefixes structure.
395 *
396 * @param[in] lybctx LYB context.
397 * @param[out] prefs Parsed prefixes.
398 * @return LY_ERR value.
399 */
400static LY_ERR
401lyb_parse_opaq_prefixes(struct lyd_lyb_ctx *lybctx, struct ly_prefix **prefs)
402{
403 LY_ERR ret = LY_SUCCESS;
404 uint8_t count, i;
405 char *str;
406
407 /* read count */
408 lyb_read(&count, 1, lybctx);
409 if (!count) {
410 return LY_SUCCESS;
411 }
412
413 LY_ARRAY_CREATE_RET(lybctx->ctx, *prefs, count, LY_EMEM);
414 for (i = 0; i < count; ++i) {
415 LY_ARRAY_INCREMENT(*prefs);
416
417 /* prefix */
418 ret = lyb_read_string(&str, 1, lybctx);
419 LY_CHECK_GOTO(ret, cleanup);
420 (*prefs)[i].pref = lydict_insert_zc(lybctx->ctx, str);
421
422 /* namespace */
423 ret = lyb_read_string(&str, 1, lybctx);
424 LY_CHECK_GOTO(ret, cleanup);
425 (*prefs)[i].ns = lydict_insert_zc(lybctx->ctx, str);
426 }
427
428cleanup:
429 if (ret) {
430 ly_free_val_prefs(lybctx->ctx, *prefs);
431 *prefs = NULL;
432 }
433 return ret;
434}
435
436/**
437 * @brief Parse opaque attributes.
438 *
439 * @param[in] lybctx LYB context.
440 * @param[out] attr Parsed attributes.
441 * @return LY_ERR value.
442 */
443static LY_ERR
444lyb_parse_attributes(struct lyd_lyb_ctx *lybctx, struct ly_attr **attr)
445{
446 LY_ERR ret = LY_SUCCESS;
447 uint8_t count, i;
448 struct ly_attr *attr2;
449 char *prefix = NULL, *ns = NULL, *name = NULL, *value = NULL;
450 int dynamic = 0;
451 LYD_FORMAT format = 0;
452 struct ly_prefix *val_prefs = NULL;
453
454 /* read count */
455 lyb_read(&count, 1, lybctx);
456
457 /* read attributes */
458 for (i = 0; i < count; ++i) {
459 ret = lyb_read_start_subtree(lybctx);
460 LY_CHECK_GOTO(ret, cleanup);
461
462 /* prefix, may be emtpy */
463 ret = lyb_read_string(&prefix, 1, lybctx);
464 LY_CHECK_GOTO(ret, cleanup);
465 if (!prefix[0]) {
466 free(prefix);
467 prefix = NULL;
468 }
469
470 /* namespace, may be empty */
471 ret = lyb_read_string(&ns, 1, lybctx);
472 LY_CHECK_GOTO(ret, cleanup);
473 if (!ns[0]) {
474 free(ns);
475 ns = NULL;
476 }
477
478 /* name */
479 ret = lyb_read_string(&name, 1, lybctx);
480 LY_CHECK_GOTO(ret, cleanup);
481
482 /* value prefixes */
483 ret = lyb_parse_opaq_prefixes(lybctx, &val_prefs);
484 LY_CHECK_GOTO(ret, cleanup);
485
486 /* format */
487 lyb_read((uint8_t *)&format, 1, lybctx);
488
489 /* value */
490 ret = lyb_read_string(&value, 0, lybctx);
491 LY_CHECK_GOTO(ret, cleanup);
492 dynamic = 1;
493
494 /* attr2 is always changed to the created attribute */
495 ret = ly_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format,
496 val_prefs, prefix, prefix ? strlen(prefix) : 0, ns);
497 LY_CHECK_GOTO(ret, cleanup);
498
499 free(prefix);
500 prefix = NULL;
501 free(ns);
502 ns = NULL;
503 free(name);
504 name = NULL;
505 val_prefs = NULL;
506 assert(!dynamic);
507 value = NULL;
508
509 if (!*attr) {
510 *attr = attr2;
511 }
512
513 ret = lyb_read_stop_subtree(lybctx);
514 LY_CHECK_GOTO(ret, cleanup);
515 }
516
517cleanup:
518 free(prefix);
519 free(ns);
520 free(name);
521 if (dynamic) {
522 free(value);
523 }
524 ly_free_val_prefs(lybctx->ctx, val_prefs);
525 if (ret) {
526 ly_free_attr(lybctx->ctx, *attr, 1);
527 *attr = NULL;
528 }
529 return ret;
530}
531
532/**
533 * @brief Check whether a schema node matches a hash(es).
534 *
535 * @param[in] sibling Schema node to check.
536 * @param[in] hash Hash array to check.
537 * @param[in] hash_count Number of hashes in @p hash.
538 * @return non-zero if matches,
539 * @return 0 if not.
540 */
541static int
542lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
543{
544 LYB_HASH sibling_hash;
545 uint8_t i;
546
547 /* compare all the hashes starting from collision ID 0 */
548 for (i = 0; i < hash_count; ++i) {
549 sibling_hash = lyb_hash(sibling, i);
550 if (sibling_hash != hash[i]) {
551 return 0;
552 }
553 }
554
555 return 1;
556}
557
558/**
559 * @brief Check that a schema node is suitable based on options.
560 *
561 * @param[in] lybctx LYB context.
562 * @param[in] snode Schema node to check.
563 * @return LY_ERR value.
564 */
565static LY_ERR
566lyb_parse_check_schema(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode)
567{
568 LY_ERR ret = LY_SUCCESS;
569
570 if ((lybctx->options & LYD_OPT_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
571 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LY_VCODE_INNODE, "state", snode->name);
572 return LY_EVALID;
573 }
574
575 if (snode->nodetype & (LYS_RPC | LYS_ACTION)) {
576 if (lybctx->int_opts & LYD_INTOPT_RPC) {
577 if (lybctx->op_ntf) {
578 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
579 lys_nodetype2str(snode->nodetype), snode->name,
580 lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
581 return LY_EVALID;
582 }
583 } else {
584 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
585 lys_nodetype2str(snode->nodetype), snode->name);
586 return LY_EVALID;
587 }
588 } else if (snode->nodetype == LYS_NOTIF) {
589 if (lybctx->int_opts & LYD_INTOPT_NOTIF) {
590 if (lybctx->op_ntf) {
591 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
592 lys_nodetype2str(snode->nodetype), snode->name,
593 lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
594 return LY_EVALID;
595 }
596 } else {
597 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
598 lys_nodetype2str(snode->nodetype), snode->name);
599 return LY_EVALID;
600 }
601 }
602
603 return ret;
604}
605
606/**
607 * @brief Parse schema node hash.
608 *
609 * @param[in] lybctx LYB context.
610 * @param[in] sparent Schema parent, must be set if @p mod is not.
611 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
612 * @param[out] snode Parsed found schema node, may be NULL if opaque.
613 * @return LY_ERR value.
614 */
615static LY_ERR
616lyb_parse_schema_hash(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, const struct lys_module *mod,
617 const struct lysc_node **snode)
618{
619 LY_ERR ret;
620 uint8_t i, j;
621 const struct lysc_node *sibling;
622 LYB_HASH hash[LYB_HASH_BITS - 1];
623 int getnext_opts;
624
625 *snode = NULL;
626 /* leave if-feature check for validation */
627 getnext_opts = LYS_GETNEXT_NOSTATECHECK | (lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0);
628
629 /* read the first hash */
630 lyb_read(&hash[0], sizeof *hash, lybctx);
631
632 if (!hash[0]) {
633 /* opaque node */
634 return LY_SUCCESS;
635 }
636
637 /* based on the first hash read all the other ones, if any */
638 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
639 if (i > LYB_HASH_BITS) {
640 LOGINT_RET(lybctx->ctx);
641 }
642 }
643
644 /* move the first hash on its accurate position */
645 hash[i] = hash[0];
646
647 /* read the rest of hashes */
648 for (j = i; j; --j) {
649 lyb_read(&hash[j - 1], sizeof *hash, lybctx);
650
651 /* correct collision ID */
652 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
653 /* preceded with zeros */
654 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
655 }
656
657 /* find our node with matching hashes */
658 sibling = NULL;
659 while ((sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts))) {
660 /* skip schema nodes from models not present during printing */
661 if (lyb_has_schema_model(sibling, lybctx->models)
662 && lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
663 /* match found */
664 break;
665 }
666 }
667
668 if (!sibling && (lybctx->options & LYD_OPT_STRICT)) {
669 if (mod) {
670 LOGVAL(lybctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
671 " from \"%s\".", mod->name);
672 } else {
673 LOGVAL(lybctx->ctx, LY_VLOG_LYSC, sparent, LYVE_REFERENCE, "Failed to find matching hash for a child node"
674 " of \"%s\".", sparent->name);
675 }
676 return LY_EVALID;
677 } else if (sibling && (ret = lyb_parse_check_schema(lybctx, sibling))) {
678 return ret;
679 }
680
681 *snode = sibling;
682 return LY_SUCCESS;
683}
684
685/**
686 * @brief Read until the end of the current subtree.
687 *
688 * @param[in] lybctx LYB context.
689 */
690static void
691lyb_skip_subtree(struct lyd_lyb_ctx *lybctx)
692{
693 int parsed;
694
695 do {
696 /* first skip any meta information inside */
697 parsed = LYB_LAST_SUBTREE(lybctx).inner_chunks * LYB_META_BYTES;
698 lybctx->data += parsed;
699 lybctx->byte_count += parsed;
700
701 /* then read data */
702 lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
703 } while (LYB_LAST_SUBTREE(lybctx).written);
704}
705
706/**
707 * @brief Parse LYB subtree.
708 *
709 * @param[in] lybctx LYB context.
710 * @param[in] parent Data parent of the subtree, must be set if @p first is not.
711 * @param[in,out] first First top-level sibling, must be set if @p parent is not.
712 * @return LY_ERR value.
713 */
714static LY_ERR
715lyb_parse_subtree_r(struct lyd_lyb_ctx *lybctx, struct lyd_node_inner *parent, struct lyd_node **first)
716{
717 LY_ERR ret = LY_SUCCESS;
718 struct lyd_node *node = NULL, *tree;
719 const struct lys_module *mod;
720 const struct lysc_node *snode = NULL;
721 struct lyd_meta *meta = NULL, *m;
722 struct ly_attr *attr = NULL, *a;
723 struct ly_prefix *val_prefs = NULL;
724 LYD_ANYDATA_VALUETYPE value_type;
725 char *value = NULL, *name = NULL, *prefix = NULL, *ns = NULL;
726 int dynamic = 0;
727 LYD_FORMAT format = 0;
728 int prev_lo;
729
730 /* register a new subtree */
731 LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx), cleanup);
732
733 if (!parent) {
734 /* top-level, read module name */
735 ret = lyb_parse_model(lybctx, &mod);
736 LY_CHECK_GOTO(ret, cleanup);
737
738 /* read hash, find the schema node starting from mod */
739 ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode);
740 LY_CHECK_GOTO(ret, cleanup);
741 } else {
742 /* read hash, find the schema node starting from parent schema */
743 ret = lyb_parse_schema_hash(lybctx, parent->schema, NULL, &snode);
744 LY_CHECK_GOTO(ret, cleanup);
745 }
746
747 if (!snode && !(lybctx->options & LYD_OPT_OPAQ)) {
748 /* unknown data, skip them */
749 lyb_skip_subtree(lybctx);
750 goto stop_subtree;
751 }
752
753 /* create metadata/attributes */
754 if (snode) {
755 ret = lyb_parse_metadata(lybctx, snode, &meta);
756 LY_CHECK_GOTO(ret, cleanup);
757 } else {
758 ret = lyb_parse_attributes(lybctx, &attr);
759 LY_CHECK_GOTO(ret, cleanup);
760 }
761
762 if (!snode) {
763 /* parse prefix */
764 ret = lyb_read_string(&prefix, 1, lybctx);
765 LY_CHECK_GOTO(ret, cleanup);
766
767 /* parse namespace */
768 ret = lyb_read_string(&ns, 1, lybctx);
769 LY_CHECK_GOTO(ret, cleanup);
770
771 /* parse name */
772 ret = lyb_read_string(&name, 1, lybctx);
773 LY_CHECK_GOTO(ret, cleanup);
774
775 /* parse value prefixes */
776 ret = lyb_parse_opaq_prefixes(lybctx, &val_prefs);
777 LY_CHECK_GOTO(ret, cleanup);
778
779 /* parse format */
780 lyb_read((uint8_t *)&format, 1, lybctx);
781
782 /* parse value */
783 ret = lyb_read_string(&value, 0, lybctx);
784 LY_CHECK_GOTO(ret, cleanup);
785 dynamic = 1;
786
787 /* create node */
788 ret = lyd_create_opaq(lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format, val_prefs, prefix,
789 strlen(prefix), ns, &node);
790 LY_CHECK_GOTO(ret, cleanup);
791
792 /* process children */
793 while (LYB_LAST_SUBTREE(lybctx).written) {
794 ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
795 LY_CHECK_GOTO(ret, cleanup);
796 }
797 } else if (snode->nodetype & LYD_NODE_TERM) {
798 /* parse value */
799 ret = lyb_read_string(&value, 0, lybctx);
800 LY_CHECK_GOTO(ret, cleanup);
801 dynamic = 1;
802
803 /* create node */
804 ret = lyd_create_term(snode, value, strlen(value), &dynamic, lydjson_resolve_prefix, NULL, LYD_JSON, &node);
805 if (dynamic) {
806 free(value);
807 dynamic = 0;
808 }
809 value = NULL;
810 if (ret == LY_EINCOMPLETE) {
811 if (!(lybctx->options & LYD_OPT_PARSE_ONLY)) {
812 ly_set_add(&lybctx->unres_node_type, node, LY_SET_OPT_USEASLIST);
813 }
814 ret = LY_SUCCESS;
815 } else if (ret) {
816 goto cleanup;
817 }
818 } else if (snode->nodetype & LYD_NODE_INNER) {
819 /* create node */
820 ret = lyd_create_inner(snode, &node);
821 LY_CHECK_GOTO(ret, cleanup);
822
823 /* process children */
824 while (LYB_LAST_SUBTREE(lybctx).written) {
825 ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
826 LY_CHECK_GOTO(ret, cleanup);
827 }
828
829 if (!(lybctx->options & LYD_OPT_PARSE_ONLY)) {
830 /* new node validation, autodelete CANNOT occur, all nodes are new */
831 ret = lyd_validate_new(lyd_node_children_p(node), snode, NULL);
832 LY_CHECK_GOTO(ret, cleanup);
833
834 /* add any missing default children */
835 ret = lyd_validate_defaults_r((struct lyd_node_inner *)node, lyd_node_children_p(node), NULL, NULL,
836 &lybctx->unres_node_type, &lybctx->when_check, lybctx->options);
837 LY_CHECK_GOTO(ret, cleanup);
838 }
839
840 if (snode->nodetype == LYS_LIST) {
841 /* hash now that all keys should be parsed, rehash for key-less list */
842 lyd_hash(node);
843 } else if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
844 /* rememeber the RPC/action/notification */
845 lybctx->op_ntf = node;
846 }
847 } else if (snode->nodetype & LYD_NODE_ANY) {
848 /* parse value type */
849 lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx);
850 if (value_type == LYD_ANYDATA_DATATREE) {
851 /* invalid situation */
852 LOGINT(lybctx->ctx);
853 goto cleanup;
854 }
855
856 /* read anydata content */
857 ret = lyb_read_string(&value, 0, lybctx);
858 LY_CHECK_GOTO(ret, cleanup);
859 dynamic = 1;
860
861 if (value_type == LYD_ANYDATA_LYB) {
862 /* turn logging off */
863 prev_lo = ly_log_options(0);
864
865 /* try to parse LYB into a data tree */
866 tree = lyd_parse_mem((struct ly_ctx *)lybctx->ctx, value, LYD_LYB,
867 LYD_OPT_PARSE_ONLY | LYD_OPT_OPAQ | LYD_OPT_STRICT);
868 ly_log_options(prev_lo);
869 if (!ly_errcode(lybctx->ctx)) {
870 /* successfully parsed */
871 free(value);
872 value = (char *)tree;
873 value_type = LYD_ANYDATA_DATATREE;
874 }
875 }
876
877 /* create node */
878 ret = lyd_create_any(snode, value, value_type, &node);
879 LY_CHECK_GOTO(ret, cleanup);
880
881 dynamic = 0;
882 value = NULL;
883 }
884 assert(node);
885
886 /* add/correct flags */
887 if (snode) {
888 lyd_parse_set_data_flags(node, &lybctx->when_check, &meta, lybctx->options);
889 }
890
891 /* add metadata/attributes */
892 if (snode) {
893 LY_LIST_FOR(meta, m) {
894 m->parent = node;
895 }
896 node->meta = meta;
897 meta = NULL;
898 } else {
899 assert(!node->schema);
900 LY_LIST_FOR(attr, a) {
901 a->parent = (struct lyd_node_opaq *)node;
902 }
903 ((struct lyd_node_opaq *)node)->attr = attr;
904 attr = NULL;
905 }
906
907 /* insert */
908 lyd_insert_node((struct lyd_node *)parent, first, node);
909 node = NULL;
910
911stop_subtree:
912 /* end the subtree */
913 ret = lyb_read_stop_subtree(lybctx);
914 LY_CHECK_GOTO(ret, cleanup);
915
916cleanup:
917 free(prefix);
918 free(ns);
919 free(name);
920 if (dynamic) {
921 free(value);
922 }
923 ly_free_val_prefs(lybctx->ctx, val_prefs);
924
925 lyd_free_meta(lybctx->ctx, meta, 1);
926 ly_free_attr(lybctx->ctx, attr, 1);
927 lyd_free_tree(node);
928 return ret;
929}
930
931/**
932 * @brief Parse used YANG data models.
933 *
934 * @param[in] lybctx LYB context.
935 * @return LY_ERR value.
936 */
937static LY_ERR
938lyb_parse_data_models(struct lyd_lyb_ctx *lybctx)
939{
940 LY_ERR ret;
941 uint32_t count;
942 LY_ARRAY_SIZE_TYPE u;
943
944 /* read model count */
945 lyb_read_number(&count, sizeof count, 2, lybctx);
946
947 if (count) {
948 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
949
950 /* read modules */
951 for (u = 0; u < count; ++u) {
952 ret = lyb_parse_model(lybctx, &lybctx->models[u]);
953 LY_CHECK_RET(ret);
954 LY_ARRAY_INCREMENT(lybctx->models);
955 }
956 }
957
958 return LY_SUCCESS;
959}
960
961/**
962 * @brief Parse LYB magic number.
963 *
964 * @param[in] lybctx LYB context.
965 * @return LY_ERR value.
966 */
967static LY_ERR
968lyb_parse_magic_number(struct lyd_lyb_ctx *lybctx)
969{
970 char magic_byte = 0;
971
972 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
973 if (magic_byte != 'l') {
974 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
975 return LY_EINVAL;
976 }
977
978 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
979 if (magic_byte != 'y') {
980 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
981 return LY_EINVAL;
982 }
983
984 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
985 if (magic_byte != 'b') {
986 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
987 return LY_EINVAL;
988 }
989
990 return LY_SUCCESS;
991}
992
993/**
994 * @brief Parse LYB header.
995 *
996 * @param[in] lybctx LYB context.
997 * @return LY_ERR value.
998 */
999static LY_ERR
1000lyb_parse_header(struct lyd_lyb_ctx *lybctx)
1001{
1002 uint8_t byte = 0;
1003
1004 /* version, future flags */
1005 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1006
1007 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1008 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
1009 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
1010 return LY_EINVAL;
1011 }
1012
1013 return LY_SUCCESS;
1014}
1015
1016LY_ERR
1017lyd_parse_lyb_data(struct ly_ctx *ctx, const char *data, int options, struct lyd_node **tree, int *parsed_bytes)
1018{
1019 LY_ERR ret = LY_SUCCESS;
1020 struct lyd_lyb_ctx lybctx = {0};
1021
1022 *tree = NULL;
1023
1024 lybctx.data = data;
1025 lybctx.ctx = ctx;
1026 lybctx.options = options;
1027
1028 /* read magic number */
1029 ret = lyb_parse_magic_number(&lybctx);
1030 LY_CHECK_GOTO(ret, cleanup);
1031
1032 /* read header */
1033 ret = lyb_parse_header(&lybctx);
1034 LY_CHECK_GOTO(ret, cleanup);
1035
1036 /* read used models */
1037 ret = lyb_parse_data_models(&lybctx);
1038 LY_CHECK_GOTO(ret, cleanup);
1039
1040 /* read subtree(s) */
1041 while (lybctx.data[0]) {
1042 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1043 LY_CHECK_GOTO(ret, cleanup);
1044 }
1045
1046 /* read the last zero, parsing finished */
1047 ++lybctx.byte_count;
1048 ++lybctx.data;
1049
1050 /* TODO validation */
1051
1052cleanup:
1053 LY_ARRAY_FREE(lybctx.subtrees);
1054 LY_ARRAY_FREE(lybctx.models);
1055 ly_set_erase(&lybctx.unres_node_type, NULL);
1056 ly_set_erase(&lybctx.unres_meta_type, NULL);
1057 ly_set_erase(&lybctx.when_check, NULL);
1058
1059 if (parsed_bytes) {
1060 *parsed_bytes = lybctx.byte_count;
1061 }
1062 if (ret) {
1063 lyd_free_all(*tree);
1064 *tree = NULL;
1065 }
1066 return ret;
1067}
1068
1069LY_ERR
1070lyd_parse_lyb_rpc(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **op, int *parsed_bytes)
1071{
1072 LY_ERR ret = LY_SUCCESS;
1073 struct lyd_lyb_ctx lybctx = {0};
1074
1075 lybctx.data = data;
1076 lybctx.ctx = ctx;
1077 lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
1078 lybctx.int_opts = LYD_INTOPT_RPC;
1079
1080 *tree = NULL;
1081 if (op) {
1082 *op = NULL;
1083 }
1084
1085 /* read magic number */
1086 ret = lyb_parse_magic_number(&lybctx);
1087 LY_CHECK_GOTO(ret, cleanup);
1088
1089 /* read header */
1090 ret = lyb_parse_header(&lybctx);
1091 LY_CHECK_GOTO(ret, cleanup);
1092
1093 /* read used models */
1094 ret = lyb_parse_data_models(&lybctx);
1095 LY_CHECK_GOTO(ret, cleanup);
1096
1097 /* read subtree(s) */
1098 while (lybctx.data[0]) {
1099 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1100 LY_CHECK_GOTO(ret, cleanup);
1101 }
1102
1103 /* read the last zero, parsing finished */
1104 ++lybctx.byte_count;
1105 ++lybctx.data;
1106
1107 /* make sure we have parsed some operation */
1108 if (!lybctx.op_ntf) {
1109 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"rpc\"/\"action\" node.");
1110 ret = LY_EVALID;
1111 goto cleanup;
1112 }
1113
1114 if (op) {
1115 *op = lybctx.op_ntf;
1116 }
1117 assert(*tree);
1118
1119cleanup:
1120 LY_ARRAY_FREE(lybctx.subtrees);
1121 LY_ARRAY_FREE(lybctx.models);
1122 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1123
1124 if (parsed_bytes) {
1125 *parsed_bytes = lybctx.byte_count;
1126 }
1127 if (ret) {
1128 lyd_free_all(*tree);
1129 *tree = NULL;
1130 }
1131 return ret;
1132}
1133
1134LY_ERR
1135lyd_parse_lyb_notif(struct ly_ctx *ctx, const char *data, struct lyd_node **tree, struct lyd_node **ntf, int *parsed_bytes)
1136{
1137 LY_ERR ret = LY_SUCCESS;
1138 struct lyd_lyb_ctx lybctx = {0};
1139
1140 lybctx.data = data;
1141 lybctx.ctx = ctx;
1142 lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
1143 lybctx.int_opts = LYD_INTOPT_NOTIF;
1144
1145 *tree = NULL;
1146 if (ntf) {
1147 *ntf = NULL;
1148 }
1149
1150 /* read magic number */
1151 ret = lyb_parse_magic_number(&lybctx);
1152 LY_CHECK_GOTO(ret, cleanup);
1153
1154 /* read header */
1155 ret = lyb_parse_header(&lybctx);
1156 LY_CHECK_GOTO(ret, cleanup);
1157
1158 /* read used models */
1159 ret = lyb_parse_data_models(&lybctx);
1160 LY_CHECK_GOTO(ret, cleanup);
1161
1162 /* read subtree(s) */
1163 while (lybctx.data[0]) {
1164 ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
1165 LY_CHECK_GOTO(ret, cleanup);
1166 }
1167
1168 /* read the last zero, parsing finished */
1169 ++lybctx.byte_count;
1170 ++lybctx.data;
1171
1172 /* make sure we have parsed some notification */
1173 if (!lybctx.op_ntf) {
1174 LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
1175 ret = LY_EVALID;
1176 goto cleanup;
1177 }
1178
1179 if (ntf) {
1180 *ntf = lybctx.op_ntf;
1181 }
1182 assert(*tree);
1183
1184cleanup:
1185 LY_ARRAY_FREE(lybctx.subtrees);
1186 LY_ARRAY_FREE(lybctx.models);
1187 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1188
1189 if (parsed_bytes) {
1190 *parsed_bytes = lybctx.byte_count;
1191 }
1192 if (ret) {
1193 lyd_free_all(*tree);
1194 *tree = NULL;
1195 }
1196 return ret;
1197}
1198
1199LY_ERR
1200lyd_parse_lyb_reply(struct lyd_node *request, const char *data, struct lyd_node **tree, struct lyd_node **op,
1201 int *parsed_bytes)
1202{
1203 LY_ERR ret = LY_SUCCESS;
1204 struct lyd_lyb_ctx lybctx = {0};
1205 struct lyd_node *iter, *req_op, *rep_op = NULL;
1206
1207 lybctx.data = data;
1208 lybctx.ctx = LYD_NODE_CTX(request);
1209 lybctx.options = LYD_OPT_PARSE_ONLY | LYD_OPT_STRICT;
1210 lybctx.int_opts = LYD_INTOPT_REPLY;
1211
1212 *tree = NULL;
1213 if (op) {
1214 *op = NULL;
1215 }
1216
1217 /* find request OP */
1218 LYD_TREE_DFS_BEGIN((struct lyd_node *)request, iter, req_op) {
1219 if (req_op->schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1220 break;
1221 }
1222 LYD_TREE_DFS_END(request, iter, req_op);
1223 }
1224 if (!(req_op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
1225 LOGERR(LYD_NODE_CTX(request), LY_EINVAL, "No RPC/action in the request found.");
1226 ret = LY_EINVAL;
1227 goto cleanup;
1228 }
1229
1230 /* duplicate request OP with parents */
1231 rep_op = lyd_dup(req_op, NULL, LYD_DUP_WITH_PARENTS);
1232 LY_CHECK_ERR_GOTO(!rep_op, ret = LY_EMEM, cleanup);
1233
1234 /* read magic number */
1235 ret = lyb_parse_magic_number(&lybctx);
1236 LY_CHECK_GOTO(ret, cleanup);
1237
1238 /* read header */
1239 ret = lyb_parse_header(&lybctx);
1240 LY_CHECK_GOTO(ret, cleanup);
1241
1242 /* read used models */
1243 ret = lyb_parse_data_models(&lybctx);
1244 LY_CHECK_GOTO(ret, cleanup);
1245
1246 /* read subtree(s) */
1247 while (lybctx.data[0]) {
1248 ret = lyb_parse_subtree_r(&lybctx, (struct lyd_node_inner *)rep_op, NULL);
1249 LY_CHECK_GOTO(ret, cleanup);
1250 }
1251
1252 /* read the last zero, parsing finished */
1253 ++lybctx.byte_count;
1254 ++lybctx.data;
1255
1256 if (op) {
1257 *op = rep_op;
1258 }
1259 for (iter = rep_op; iter->parent; iter = (struct lyd_node *)iter->parent);
1260 *tree = iter;
1261 rep_op = NULL;
1262
1263cleanup:
1264 lyd_free_all(rep_op);
1265 LY_ARRAY_FREE(lybctx.subtrees);
1266 LY_ARRAY_FREE(lybctx.models);
1267 assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
1268
1269 if (parsed_bytes) {
1270 *parsed_bytes = lybctx.byte_count;
1271 }
1272 if (ret) {
1273 lyd_free_all(*tree);
1274 *tree = NULL;
1275 }
1276 return ret;
1277}
1278
1279API int
1280lyd_lyb_data_length(const char *data)
1281{
1282 LY_ERR ret = LY_SUCCESS;
1283 struct lyd_lyb_ctx lybctx = {0};
1284 int count, i;
1285 size_t len;
1286 uint8_t buf[LYB_SIZE_MAX];
1287
1288 if (!data) {
1289 return -1;
1290 }
1291
1292 lybctx.data = data;
1293
1294 /* read magic number */
1295 ret = lyb_parse_magic_number(&lybctx);
1296 LY_CHECK_GOTO(ret, cleanup);
1297
1298 /* read header */
1299 ret = lyb_parse_header(&lybctx);
1300 LY_CHECK_GOTO(ret, cleanup);
1301
1302 /* read model count */
1303 lyb_read_number(&count, sizeof count, 2, &lybctx);
1304
1305 /* read all models */
1306 for (i = 0; i < count; ++i) {
1307 /* module name length */
1308 len = 0;
1309 lyb_read_number(&len, sizeof len, 2, &lybctx);
1310
1311 /* model name */
1312 lyb_read(buf, len, &lybctx);
1313
1314 /* revision */
1315 lyb_read(buf, 2, &lybctx);
1316 }
1317
1318 while (lybctx.data[0]) {
1319 /* register a new subtree */
1320 ret = lyb_read_start_subtree(&lybctx);
1321 LY_CHECK_GOTO(ret, cleanup);
1322
1323 /* skip it */
1324 lyb_skip_subtree(&lybctx);
1325
1326 /* subtree finished */
1327 ret = lyb_read_stop_subtree(&lybctx);
1328 LY_CHECK_GOTO(ret, cleanup);
1329 }
1330
1331 /* read the last zero, parsing finished */
1332 ++lybctx.byte_count;
1333 ++lybctx.data;
1334
1335cleanup:
1336 LY_ARRAY_FREE(lybctx.subtrees);
1337 return ret ? -1 : (signed)lybctx.byte_count;
1338}