blob: a30ca8e7a2c4a397855819bc95ff0a2cbb03ba8b [file] [log] [blame]
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2018 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 <assert.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
Michal Vaskoe581e982018-08-21 12:26:55 +020019#include <inttypes.h>
Michal Vasko6b69e4b2018-10-17 12:07:27 +020020#ifdef __APPLE__
Michal Vaskob27fb152018-10-17 12:54:47 +020021# include <libkern/OSByteOrder.h>
22
23# define le16toh(x) OSSwapLittleToHostInt16(x)
24# define le32toh(x) OSSwapLittleToHostInt32(x)
25# define le64toh(x) OSSwapLittleToHostInt64(x)
Michal Vasko6b69e4b2018-10-17 12:07:27 +020026#else
Michal Vaskob27fb152018-10-17 12:54:47 +020027# include <endian.h>
Michal Vasko6b69e4b2018-10-17 12:07:27 +020028#endif
Michal Vasko1e82a3b2018-07-03 12:16:58 +020029
30#include "libyang.h"
31#include "common.h"
32#include "context.h"
33#include "parser.h"
34#include "tree_internal.h"
35
36#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
37#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
38
39static int
40lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
41{
42 int ret = 0, i, empty_chunk_i;
43 size_t to_read;
Graeme Campbell856a40e2018-10-05 14:35:37 +130044 uint8_t meta_buf[LYB_META_BYTES];
Michal Vasko1e82a3b2018-07-03 12:16:58 +020045
46 assert(data && lybs);
47
48 while (1) {
49 /* check for fully-read (empty) data chunks */
50 to_read = count;
51 empty_chunk_i = -1;
52 for (i = 0; i < lybs->used; ++i) {
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 */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020055 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020056 /* empty chunk, do not read more */
57 to_read = lybs->written[i];
58 empty_chunk_i = i;
59 }
60 }
61
62 if ((empty_chunk_i == -1) && !count) {
63 break;
64 }
65
66 /* we are actually reading some data, not just finishing another chunk */
67 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020068 if (buf) {
69 memcpy(buf, data + ret, to_read);
70 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020071
72 for (i = 0; i < lybs->used; ++i) {
73 /* decrease all written counters */
74 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020075 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020076 }
77 /* decrease count/buf */
78 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020079 if (buf) {
80 buf += to_read;
81 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020082
83 ret += to_read;
84 }
85
86 if (empty_chunk_i > -1) {
Michal Vaskoa9852522018-08-08 16:24:45 +020087 /* read the next chunk meta information */
Graeme Campbell856a40e2018-10-05 14:35:37 +130088 memcpy(meta_buf, data + ret, LYB_META_BYTES);
89 lybs->written[empty_chunk_i] = meta_buf[0];
90 lybs->inner_chunks[empty_chunk_i] = meta_buf[1];
Michal Vaskoa9852522018-08-08 16:24:45 +020091
Michal Vasko1e82a3b2018-07-03 12:16:58 +020092 /* remember whether there is a following chunk or not */
93 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
94
Michal Vaskoa9852522018-08-08 16:24:45 +020095 ret += LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020096 }
97 }
98
99 return ret;
100}
101
102static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200103lyb_read_number(uint64_t *num, size_t bytes, const char *data, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200104{
Michal Vasko1440eb52018-08-14 13:42:14 +0200105 int r, ret = 0;
106 size_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200107 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200108
Michal Vasko1440eb52018-08-14 13:42:14 +0200109 for (i = 0; i < bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +0200110 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200111 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200112
113 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200114 }
115
116 return ret;
117}
118
119static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200120lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
121{
Graeme Campbell856a40e2018-10-05 14:35:37 +1300122 int ret = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200123 size_t bytes;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300124 uint64_t tmp_enum = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200125
Michal Vasko81426892018-11-21 11:57:49 +0100126 if (count < (1 << 8)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200127 bytes = 1;
Michal Vasko81426892018-11-21 11:57:49 +0100128 } else if (count < (1 << 16)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200129 bytes = 2;
Michal Vasko81426892018-11-21 11:57:49 +0100130 } else if (count < (1 << 24)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200131 bytes = 3;
132 } else {
133 bytes = 4;
134 }
135
Graeme Campbell856a40e2018-10-05 14:35:37 +1300136 /* The enum is always read into a uint64_t buffer */
137 ret = lyb_read_number(&tmp_enum, bytes, data, lybs);
138 *enum_idx = le64toh(tmp_enum);
139
140 return ret;
Michal Vasko1440eb52018-08-14 13:42:14 +0200141}
142
143static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200144lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200145{
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200146 int next_chunk = 0, r, ret = 0;
147 size_t len = 0, cur_len;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300148 uint8_t len_buf[2];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200149
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200150 if (with_length) {
Graeme Campbell856a40e2018-10-05 14:35:37 +1300151 ret += (r = lyb_read(data, len_buf, 2, lybs));
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200152 LYB_HAVE_READ_GOTO(r, data, error);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300153 len = len_buf[0] | (len_buf[1] << 8);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200154 } else {
155 /* read until the end of this subtree */
156 len = lybs->written[lybs->used - 1];
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200157 if (lybs->position[lybs->used - 1]) {
158 next_chunk = 1;
159 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200160 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200161
162 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200163 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200164
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200165 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200166 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200167
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200168 while (next_chunk) {
169 cur_len = lybs->written[lybs->used - 1];
170 if (lybs->position[lybs->used - 1]) {
171 next_chunk = 1;
172 } else {
173 next_chunk = 0;
174 }
175
176 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
177 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
178
179 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200180 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200181
182 len += cur_len;
183 }
184
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200185 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200186 return ret;
187
188error:
189 free((char *)*str);
190 *str = NULL;
191 return -1;
192}
193
194static void
195lyb_read_stop_subtree(struct lyb_state *lybs)
196{
197 if (lybs->written[lybs->used - 1]) {
198 LOGINT(NULL);
199 }
200
201 --lybs->used;
202}
203
204static int
205lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
206{
Graeme Campbell856a40e2018-10-05 14:35:37 +1300207 uint8_t meta_buf[LYB_META_BYTES];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200208
209 if (lybs->used == lybs->size) {
210 lybs->size += LYB_STATE_STEP;
211 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
212 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
Michal Vaskoa9852522018-08-08 16:24:45 +0200213 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
214 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200215 }
216
Graeme Campbell856a40e2018-10-05 14:35:37 +1300217 memcpy(meta_buf, data, LYB_META_BYTES);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200218
219 ++lybs->used;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300220 lybs->written[lybs->used - 1] = meta_buf[0];
221 lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES];
Michal Vaskoa9852522018-08-08 16:24:45 +0200222 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
223
224 return LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200225}
226
227static int
228lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
229{
230 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200231 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200232 uint16_t rev = 0;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300233 uint8_t tmp_buf[2];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200234
235 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200236 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200237 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200238
239 /* revision */
Graeme Campbell856a40e2018-10-05 14:35:37 +1300240 ret += (r = lyb_read(data, tmp_buf, sizeof tmp_buf, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200241 LYB_HAVE_READ_GOTO(r, data, error);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300242 rev = tmp_buf[0] | (tmp_buf[1] << 8);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200243
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200244 if (rev) {
245 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200246 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
247 } else {
248 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
249 }
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200250 if (ctx->data_clb) {
251 if (!*mod) {
252 *mod = ctx->data_clb(ctx, mod_name, NULL, 0, ctx->data_clb_data);
253 } else if (!(*mod)->implemented) {
254 *mod = ctx->data_clb(ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
255 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200256 }
257
Michal Vasko60b02ff2018-09-25 11:01:18 +0200258 if (!*mod) {
259 LOGERR(ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
260 mod_name, rev ? "@" : "", rev ? mod_rev : "");
261 goto error;
262 } else if (!(*mod)->implemented) {
263 LOGERR(ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
264 mod_name, rev ? "@" : "", rev ? mod_rev : "");
265 goto error;
266 }
267
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200268 free(mod_name);
269 return ret;
270
271error:
272 free(mod_name);
273 return -1;
274}
275
276static struct lyd_node *
277lyb_new_node(const struct lys_node *schema)
278{
279 struct lyd_node *node;
280
281 switch (schema->nodetype) {
282 case LYS_CONTAINER:
283 case LYS_LIST:
284 case LYS_NOTIF:
285 case LYS_RPC:
286 case LYS_ACTION:
287 node = calloc(sizeof(struct lyd_node), 1);
288 break;
289 case LYS_LEAF:
290 case LYS_LEAFLIST:
291 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200292
293 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
294 node->validity |= LYD_VAL_LEAFREF;
295 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200296 break;
297 case LYS_ANYDATA:
298 case LYS_ANYXML:
299 node = calloc(sizeof(struct lyd_node_anydata), 1);
300 break;
301 default:
302 return NULL;
303 }
304 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
305
306 /* fill basic info */
307 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200308 if (resolve_applies_when(schema, 0, NULL)) {
Michal Vasko7b2a5822018-12-18 13:13:03 +0100309 /* this data are considered trusted so if this node exists, it means its when must have been true */
310 node->when_status = LYD_WHEN | LYD_WHEN_TRUE;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200311 }
312 node->prev = node;
313
314 return node;
315}
316
317static int
318lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
319{
320 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200321 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200322 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
323
324 /* read value type */
325 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
326 LYB_HAVE_READ_RETURN(r, data, -1);
327
328 /* read anydata content */
329 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko33901702018-08-17 10:29:09 +0200330 /* invalid situation */
331 LOGINT(node->schema->module->ctx);
332 return -1;
Michal Vaskodcaf7222018-08-08 16:27:00 +0200333 } else if (any->value_type == LYD_ANYDATA_LYB) {
334 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
335 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200336 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200337 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200338 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200339
340 /* add to dictionary */
341 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200342 }
343
344 return ret;
345}
346
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200347/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200348static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200349lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
350 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200351{
Michal Vasko228431e2018-07-10 15:47:11 +0200352 int r, ret;
353 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200354 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200355 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200356 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200357
Michal Vasko42132c52018-07-24 16:09:21 +0200358 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200359 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200360 ret = lyb_read_string(data, &str, 0, lybs);
361 if (ret > -1) {
362 *value_str = lydict_insert_zc(ctx, str);
363 }
364 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200365 }
366
Michal Vasko6fb57892018-08-23 10:21:21 +0200367 /* find the correct structure, go through leafrefs and typedefs */
368 switch (value_type) {
369 case LY_TYPE_ENUM:
370 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
371 for (; !type->info.enums.count; type = &type->der->type);
372 break;
373 case LY_TYPE_BITS:
374 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
375 for (; !type->info.bits.count; type = &type->der->type);
376 break;
377 default:
378 break;
379 }
380
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200381 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200382 case LY_TYPE_INST:
383 case LY_TYPE_IDENT:
384 case LY_TYPE_UNION:
385 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200386 ret = lyb_read_string(data, &str, 0, lybs);
387 if (ret > -1) {
388 *value_str = lydict_insert_zc(ctx, str);
389 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200390 break;
391 case LY_TYPE_BINARY:
392 case LY_TYPE_STRING:
393 case LY_TYPE_UNKNOWN:
394 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200395 ret = lyb_read_string(data, &str, 0, lybs);
396 if (ret > -1) {
397 value->string = lydict_insert_zc(ctx, str);
398 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200399 break;
400 case LY_TYPE_BITS:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200401 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
402 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200403
404 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200405 ret = 0;
406 for (i = 0; i < type->info.bits.count; ++i) {
407 if (i % 8 == 0) {
408 /* read another byte */
Andrew Langefeld1f3e4f52018-08-24 22:30:37 -0500409 ret += (r = lyb_read(data + ret, &byte, sizeof byte, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +0200410 if (r < 0) {
411 return -1;
412 }
413 }
414
415 if (byte & (0x01 << (i % 8))) {
416 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200417 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200418 }
419 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200420 break;
421 case LY_TYPE_BOOL:
422 /* read byte */
423 ret = lyb_read(data, &byte, sizeof byte, lybs);
424 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200425 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200426 }
427 break;
428 case LY_TYPE_EMPTY:
429 /* nothing to read */
430 ret = 0;
431 break;
432 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200433 num = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200434 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
Michal Vaskob7400232018-07-11 15:35:57 +0200435 if (ret > 0) {
436 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200437 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200438 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200439 break;
440 case LY_TYPE_INT8:
441 case LY_TYPE_UINT8:
Michal Vasko1440eb52018-08-14 13:42:14 +0200442 ret = lyb_read_number((uint64_t *)&value->uint8, 1, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200443 break;
444 case LY_TYPE_INT16:
445 case LY_TYPE_UINT16:
Michal Vasko1440eb52018-08-14 13:42:14 +0200446 ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300447 value->uint16 = le16toh(value->uint16);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200448 break;
449 case LY_TYPE_INT32:
450 case LY_TYPE_UINT32:
Michal Vasko1440eb52018-08-14 13:42:14 +0200451 ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300452 value->uint32 = le32toh(value->uint32);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200453 break;
454 case LY_TYPE_DEC64:
455 case LY_TYPE_INT64:
456 case LY_TYPE_UINT64:
Michal Vasko1440eb52018-08-14 13:42:14 +0200457 ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300458 value->uint64 = le64toh(value->uint64);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200459 break;
460 default:
461 return -1;
462 }
463
464 return ret;
465}
466
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200467/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200468static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200469lyb_parse_val_2(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct unres_data *unres)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200470{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200471 struct ly_ctx *ctx;
472 struct lys_module *mod;
Michal Vasko6fb57892018-08-23 10:21:21 +0200473 struct lys_type *rtype;
Michal Vasko228431e2018-07-10 15:47:11 +0200474 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200475 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200476 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200477 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200478 const char **value_str;
479 LY_DATA_TYPE value_type;
480 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200481
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200482 if (leaf) {
483 ctx = leaf->schema->module->ctx;
484 mod = lys_node_module(leaf->schema);
485
486 value = &leaf->value;
487 value_str = &leaf->value_str;
488 value_flags = &leaf->value_flags;
489 value_type = leaf->value_type;
490 } else {
491 ctx = attr->annotation->module->ctx;
492 mod = lys_main_module(attr->annotation->module);
493
494 value = &attr->value;
495 value_str = &attr->value_str;
496 value_flags = &attr->value_flags;
497 value_type = attr->value_type;
498 }
499
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200500 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200501 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200502 *value_flags &= ~LY_VALUE_USER;
503 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200504 return -1;
505 }
506
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200507 if (!(*value_flags & LY_VALUE_USER)) {
508 LOGWRN(ctx, "Value \"%s\" was stored as a user type, but it is not in the current context.", value_str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200509 }
510 return 0;
511 }
512
Michal Vaskob7400232018-07-11 15:35:57 +0200513 /* we are parsing leafref/ptr union stored as the target type,
514 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200515 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
516 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200517 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200518 /* we already have a string */
519 goto parse_reference;
520 }
521 }
522
Michal Vasko6fb57892018-08-23 10:21:21 +0200523 /* find the correct structure, go through leafrefs and typedefs */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200524 switch (value_type) {
Michal Vasko58608522018-08-22 13:04:37 +0200525 case LY_TYPE_BITS:
Michal Vasko6fb57892018-08-23 10:21:21 +0200526 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &rtype->info.lref.target->type);
527 for (; !rtype->info.bits.count; rtype = &rtype->der->type);
528 break;
Michal Vasko58608522018-08-22 13:04:37 +0200529 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200530 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &type->info.lref.target->type);
Michal Vasko58608522018-08-22 13:04:37 +0200531 break;
532 default:
533 break;
534 }
535
536 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200537 case LY_TYPE_IDENT:
538 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200539 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
540 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200541 return -1;
542 }
543 break;
Michal Vasko56670362018-08-08 16:27:21 +0200544 case LY_TYPE_INST:
545 /* unresolved instance-identifier, keep value NULL */
546 value->instance = NULL;
547 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200548 case LY_TYPE_BINARY:
549 case LY_TYPE_STRING:
550 case LY_TYPE_UNKNOWN:
551 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200552 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200553 break;
554 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200555 /* print the set bits */
556 str = malloc(1);
557 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
558 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200559 str_len = 0;
Michal Vasko6fb57892018-08-23 10:21:21 +0200560 for (i = 0; i < rtype->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200561 if (value->bit[i]) {
562 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200563 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
564
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200565 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200566 }
567 }
568
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200569 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200570 break;
571 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200572 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200573 break;
574 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200575 *value_str = lydict_insert(ctx, "", 0);
576 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200577 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200578 if (attr) {
579 /* we do not support union type attribute */
580 LOGINT(ctx);
581 return -1;
582 }
583
584 if (resolve_union(leaf, type, 1, 2, NULL)) {
585 return -1;
586 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200587 break;
588 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200589 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200590 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200591 break;
592 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200593 sprintf(num_str, "%d", value->int8);
594 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200595 break;
596 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200597 sprintf(num_str, "%u", value->uint8);
598 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200599 break;
600 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200601 sprintf(num_str, "%d", value->int16);
602 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200603 break;
604 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200605 sprintf(num_str, "%u", value->uint16);
606 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200607 break;
608 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200609 sprintf(num_str, "%d", value->int32);
610 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200611 break;
612 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200613 sprintf(num_str, "%u", value->uint32);
614 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200615 break;
616 case LY_TYPE_INT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200617 sprintf(num_str, "%"PRId64, value->int64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200618 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200619 break;
620 case LY_TYPE_UINT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200621 sprintf(num_str, "%"PRIu64, value->uint64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200622 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200623 break;
624 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200625 frac = value->dec64 % rtype->info.dec64.div;
626 dig = rtype->info.dec64.dig;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200627 /* remove trailing zeros */
628 while ((dig > 1) && !(frac % 10)) {
629 frac /= 10;
630 --dig;
631 }
632
Michal Vasko6fb57892018-08-23 10:21:21 +0200633 sprintf(num_str, "%"PRId64".%.*"PRId64, value->dec64 / (int64_t)rtype->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200634 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200635 break;
636 default:
637 return -1;
638 }
639
Michal Vaskoc2a25242018-12-19 08:52:28 +0100640 if (*value_flags & LY_VALUE_UNRES) {
641 /* just remove the flag, it should stay unresolved */
642 leaf->validity &= ~LYD_VAL_LEAFREF;
643 } else if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
644 || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200645parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200646 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200647
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200648 if (attr) {
649 /* we do not support reference types of attributes */
650 LOGINT(ctx);
651 return -1;
652 }
653
654 if (type->base == LY_TYPE_INST) {
655 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
656 return -1;
657 }
658 } else if (type->base == LY_TYPE_LEAFREF) {
659 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200660 return -1;
661 }
662 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200663 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200664 return -1;
665 }
666 }
667 }
668
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200669 return 0;
670}
671
672static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200673lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
674 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200675{
676 int r, ret = 0;
677 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200678
679 struct ly_ctx *ctx;
680 const char **value_str;
681 lyd_val *value;
682 LY_DATA_TYPE *value_type;
683 uint8_t *value_flags;
684
685 assert((leaf || attr) && (!leaf || !attr));
686
687 if (leaf) {
688 ctx = leaf->schema->module->ctx;
689 value_str = &leaf->value_str;
690 value = &leaf->value;
691 value_type = &leaf->value_type;
692 value_flags = &leaf->value_flags;
693 } else {
694 ctx = attr->annotation->module->ctx;
695 value_str = &attr->value_str;
696 value = &attr->value;
697 value_type = &attr->value_type;
698 value_flags = &attr->value_flags;
699 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200700
701 /* read value type and flags on the first byte */
702 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
703 LYB_HAVE_READ_RETURN(r, data, -1);
704
705 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200706 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200707 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200708 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200709 leaf->dflt = 1;
710 }
711 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200712 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200713 }
714 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200715 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200716 }
717
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200718 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200719 LYB_HAVE_READ_RETURN(r, data, -1);
720
Michal Vasko27e5e682018-07-23 14:22:57 +0200721 /* union is handled specially */
722 if (type->base == LY_TYPE_UNION) {
723 assert(*value_type == LY_TYPE_STRING);
724
725 *value_str = value->string;
726 value->string = NULL;
727 *value_type = LY_TYPE_UNION;
728 }
729
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200730 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200731 LYB_HAVE_READ_RETURN(r, data, -1);
732
733 return ret;
734}
735
736static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200737lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
738 struct lyb_state *lybs)
739{
740 int r, ret = 0, pos, i, j, k;
741 const struct lys_submodule *submod = NULL;
742 char *attr_name = NULL;
743
744 /* attr name */
745 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
746 LYB_HAVE_READ_RETURN(r, data, -1);
747
748 /* search module */
749 pos = -1;
750 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
751 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
752 if (j == -1) {
753 break;
754 }
755 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
756 pos = i + j;
757 break;
758 }
759 }
760
761 /* try submodules */
762 if (pos == -1) {
763 for (k = 0; k < mod->inc_size; ++k) {
764 submod = mod->inc[k].submodule;
765 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
766 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
767 if (j == -1) {
768 break;
769 }
770 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
771 pos = i + j;
772 break;
773 }
774 }
775 }
776 }
777
778 if (pos == -1) {
779 *ext = NULL;
780 } else {
781 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
782 }
783
784 if (!*ext && (options & LYD_OPT_STRICT)) {
785 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
786 free(attr_name);
787 return -1;
788 }
789
790 free(attr_name);
791 return ret;
792}
793
794static int
795lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
796{
797 int r, ret = 0;
798 uint8_t i, count = 0;
799 const struct lys_module *mod;
Michal Vasko3cb7d172018-08-17 10:54:40 +0200800 struct lys_type **type;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200801 struct lyd_attr *attr = NULL;
802 struct lys_ext_instance_complex *ext;
803 struct ly_ctx *ctx = node->schema->module->ctx;
804
805 /* read number of attributes stored */
806 ret += (r = lyb_read(data, &count, 1, lybs));
807 LYB_HAVE_READ_GOTO(r, data, error);
808
809 /* read attributes */
810 for (i = 0; i < count; ++i) {
811 ret += (r = lyb_read_start_subtree(data, lybs));
812 LYB_HAVE_READ_GOTO(r, data, error);
813
814 /* find model */
815 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
816 LYB_HAVE_READ_GOTO(r, data, error);
817
Michal Vasko53830662018-07-24 16:09:49 +0200818 if (mod) {
819 /* annotation name */
820 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
821 LYB_HAVE_READ_GOTO(r, data, error);
822 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200823
Michal Vasko53830662018-07-24 16:09:49 +0200824 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200825 /* unknown attribute, skip it */
826 do {
827 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200828 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200829 } while (lybs->written[lybs->used - 1]);
830 goto stop_subtree;
831 }
832
833 /* allocate new attribute */
834 if (!attr) {
835 assert(!node->attr);
836
837 attr = calloc(1, sizeof *attr);
838 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
839
840 node->attr = attr;
841 } else {
842 attr->next = calloc(1, sizeof *attr);
843 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
844
845 attr = attr->next;
846 }
847
848 /* attribute annotation */
849 attr->annotation = ext;
850
851 /* attribute name */
852 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
853
854 /* get the type */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200855 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
856 if (!type || !(*type)) {
857 goto error;
858 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200859
860 /* attribute value */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200861 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200862 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200863
864stop_subtree:
865 lyb_read_stop_subtree(lybs);
866 }
867
868 return ret;
869
870error:
871 lyd_free_attr(ctx, node, node->attr, 1);
872 return -1;
873}
874
875static int
Michal Vaskob7400232018-07-11 15:35:57 +0200876lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200877{
878 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200879 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200880
Michal Vaskob7400232018-07-11 15:35:57 +0200881 /* compare all the hashes starting from collision ID 0 */
882 for (i = 0; i < hash_count; ++i) {
883 sibling_hash = lyb_hash(sibling, i);
884 if (sibling_hash != hash[i]) {
885 return 0;
886 }
887 }
Michal Vasko228431e2018-07-10 15:47:11 +0200888
Michal Vaskob7400232018-07-11 15:35:57 +0200889 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200890}
891
892static int
893lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
894 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200895{
896 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200897 uint8_t i, j;
898 struct lys_node *sibling;
899 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200900 struct ly_ctx *ctx;
901
902 assert((sparent || mod) && (!sparent || !mod));
903 ctx = (sparent ? sparent->module->ctx : mod->ctx);
904
Michal Vaskob7400232018-07-11 15:35:57 +0200905 /* read the first hash */
906 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200907 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200908
909 /* based on the first hash read all the other ones, if any */
Michal Vasko01fc23a2018-11-21 11:58:26 +0100910 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
911 if (i > LYB_HASH_BITS) {
912 return -1;
913 }
914 }
Michal Vaskob7400232018-07-11 15:35:57 +0200915
916 /* move the first hash on its accurate position */
917 hash[i] = hash[0];
918
919 /* read the rest of hashes */
920 for (j = i; j; --j) {
921 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
922 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200923
Michal Vasko365849c2018-08-07 11:31:30 +0200924 /* correct collision ID */
925 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
926 /* preceded with zeros */
927 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200928 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200929
Michal Vaskoe3880e62018-07-11 16:18:34 +0200930 /* handle yang data templates */
931 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
932 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
933 if (!sparent) {
934 sibling = NULL;
935 goto finish;
936 }
937 }
938
939 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200940 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
941 sibling = NULL;
942 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
943 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
944 break;
945 }
946 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
947 break;
948 }
949 }
950 if (!sibling) {
951 /* fail */
952 goto finish;
953 }
954
955 /* use only input/output children nodes */
956 sparent = sibling;
957 }
958
959 /* find our node with matching hashes */
960 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200961 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
962 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200963 if (lyb_has_schema_model(sibling, lybs->models, lybs->mod_count) && lyb_is_schema_hash_match(sibling, hash, i + 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200964 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200965 break;
966 }
967 }
968
Michal Vaskob7400232018-07-11 15:35:57 +0200969finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200970 *snode = sibling;
971 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200972 if (mod) {
973 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
974 } else {
975 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
976 }
977 return -1;
978 }
979
980 return ret;
981}
982
983static int
984lyb_parse_subtree(struct ly_ctx *ctx, const char *data, struct lyd_node *parent, struct lyd_node **first_sibling,
Michal Vasko228431e2018-07-10 15:47:11 +0200985 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200986{
987 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200988 struct lyd_node *node = NULL, *iter;
989 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200990 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200991
992 assert((parent && !first_sibling) || (!parent && first_sibling));
993
994 /* register a new subtree */
995 ret += (r = lyb_read_start_subtree(data, lybs));
996 LYB_HAVE_READ_GOTO(r, data, error);
997
998 if (!parent) {
999 /* top-level, read module name */
1000 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
1001 LYB_HAVE_READ_GOTO(r, data, error);
1002
Michal Vasko53830662018-07-24 16:09:49 +02001003 if (mod) {
1004 /* read hash, find the schema node starting from mod, possibly yang_data_name */
1005 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
1006 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001007 } else {
Michal Vasko53830662018-07-24 16:09:49 +02001008 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001009
Michal Vaskoe3880e62018-07-11 16:18:34 +02001010 /* read hash, find the schema node starting from parent schema */
1011 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
1012 }
1013 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001014 LYB_HAVE_READ_GOTO(r, data, error);
1015
Michal Vasko53830662018-07-24 16:09:49 +02001016 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +02001017 /* unknown data subtree, skip it whole */
1018 do {
1019 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +02001020 /* also skip the meta information inside */
1021 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +02001022 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +02001023 goto stop_subtree;
1024 }
1025
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001026 /*
1027 * read the node
1028 */
1029 node = lyb_new_node(snode);
1030 if (!node) {
1031 goto error;
1032 }
1033
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001034 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1035 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001036
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001037 /* read node content */
1038 switch (snode->nodetype) {
1039 case LYS_CONTAINER:
1040 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +02001041 case LYS_NOTIF:
1042 case LYS_RPC:
1043 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001044 /* nothing to read */
1045 break;
1046 case LYS_LEAF:
1047 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001048 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1049 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001050 LYB_HAVE_READ_GOTO(r, data, error);
1051 break;
1052 case LYS_ANYXML:
1053 case LYS_ANYDATA:
1054 ret += (r = lyb_parse_anydata(node, data, lybs));
1055 LYB_HAVE_READ_GOTO(r, data, error);
1056 break;
1057 default:
1058 goto error;
1059 }
1060
1061 /* insert into data tree, manually */
1062 if (parent) {
1063 if (!parent->child) {
1064 /* only child */
1065 parent->child = node;
1066 } else {
1067 /* last child */
1068 parent->child->prev->next = node;
1069 node->prev = parent->child->prev;
1070 parent->child->prev = node;
1071 }
1072 node->parent = parent;
1073 } else if (*first_sibling) {
1074 /* last sibling */
1075 (*first_sibling)->prev->next = node;
1076 node->prev = (*first_sibling)->prev;
1077 (*first_sibling)->prev = node;
1078 } else {
1079 /* only sibling */
1080 *first_sibling = node;
1081 }
1082
1083 /* read all descendants */
1084 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001085 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001086 LYB_HAVE_READ_GOTO(r, data, error);
1087 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001088
1089 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001090 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001091 LY_TREE_FOR(node->child, iter) {
1092 if (!iter->dflt) {
1093 break;
1094 }
1095 }
1096
1097 if (!iter) {
1098 node->dflt = 1;
1099 }
1100 }
1101
Michal Vaskofe43d042018-07-24 09:43:46 +02001102#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001103 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1104 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001105 lyd_hash(node);
1106 lyd_insert_hash(node);
1107 }
1108#endif
1109
Michal Vasko228431e2018-07-10 15:47:11 +02001110stop_subtree:
1111 /* end the subtree */
1112 lyb_read_stop_subtree(lybs);
1113
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001114 return ret;
1115
1116error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001117 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001118 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001119 *first_sibling = NULL;
1120 }
1121 return -1;
1122}
1123
1124static int
Michal Vasko228431e2018-07-10 15:47:11 +02001125lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1126{
1127 int i, r, ret = 0;
Graeme Campbell856a40e2018-10-05 14:35:37 +13001128 uint8_t mod_count_buf[2];
Michal Vasko228431e2018-07-10 15:47:11 +02001129
1130 /* read model count */
Graeme Campbell856a40e2018-10-05 14:35:37 +13001131 ret += (r = lyb_read(data, mod_count_buf, 2, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001132 LYB_HAVE_READ_RETURN(r, data, -1);
Graeme Campbell856a40e2018-10-05 14:35:37 +13001133 lybs->mod_count = mod_count_buf[0] | (mod_count_buf[1] << 8);
Michal Vasko228431e2018-07-10 15:47:11 +02001134
1135 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1136 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1137
1138 /* read modules */
1139 for (i = 0; i < lybs->mod_count; ++i) {
1140 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1141 LYB_HAVE_READ_RETURN(r, data, -1);
1142 }
1143
1144 return ret;
1145}
1146
1147static int
Michal Vasko5c445042018-08-28 16:27:45 +02001148lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1149{
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001150 int r, ret = 0;
1151 char magic_byte = 0;
Michal Vasko5c445042018-08-28 16:27:45 +02001152
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001153 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1154 LYB_HAVE_READ_RETURN(r, data, -1);
1155 if (magic_byte != 'l') {
1156 LOGERR(NULL, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1157 return -1;
1158 }
Michal Vasko5c445042018-08-28 16:27:45 +02001159
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001160 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1161 LYB_HAVE_READ_RETURN(r, data, -1);
1162 if (magic_byte != 'y') {
1163 LOGERR(NULL, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1164 return -1;
1165 }
1166
1167 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1168 LYB_HAVE_READ_RETURN(r, data, -1);
1169 if (magic_byte != 'b') {
1170 LOGERR(NULL, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
Michal Vasko5c445042018-08-28 16:27:45 +02001171 return -1;
1172 }
1173
1174 return ret;
1175}
1176
1177static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001178lyb_parse_header(const char *data, struct lyb_state *lybs)
1179{
1180 int ret = 0;
1181 uint8_t byte = 0;
1182
Michal Vasko228431e2018-07-10 15:47:11 +02001183 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001184 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1185
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001186 return ret;
1187}
1188
1189struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001190lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1191 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001192{
Michal Vaskobeeb1bf2018-08-17 10:29:29 +02001193 int r = 0, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001194 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1195 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001196 struct lyb_state lybs;
1197
1198 if (!ctx || !data) {
1199 LOGARG;
1200 return NULL;
1201 }
1202
1203 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1204 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001205 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1206 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001207 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001208 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001209 lybs.models = NULL;
1210 lybs.mod_count = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001211
1212 unres = calloc(1, sizeof *unres);
1213 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001214
Michal Vasko5c445042018-08-28 16:27:45 +02001215 /* read magic number */
1216 ret += (r = lyb_parse_magic_number(data, &lybs));
1217 LYB_HAVE_READ_GOTO(r, data, finish);
1218
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001219 /* read header */
1220 ret += (r = lyb_parse_header(data, &lybs));
1221 LYB_HAVE_READ_GOTO(r, data, finish);
1222
Michal Vasko228431e2018-07-10 15:47:11 +02001223 /* read used models */
1224 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1225 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001226
1227 /* read subtree(s) */
1228 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001229 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1230 if (r < 0) {
1231 lyd_free_withsiblings(node);
1232 node = NULL;
1233 goto finish;
1234 }
1235 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001236 }
1237
1238 /* read the last zero, parsing finished */
1239 ++ret;
1240 r = ret;
1241
Michal Vasko228431e2018-07-10 15:47:11 +02001242 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1243 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1244 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1245 lyd_free_withsiblings(node);
1246 node = NULL;
1247 goto finish;
1248 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001249 }
Michal Vasko228431e2018-07-10 15:47:11 +02001250
1251 /* resolve any unresolved instance-identifiers */
1252 if (unres->count) {
1253 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1254 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1255 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1256 break;
1257 }
1258 LY_TREE_DFS_END(node, next, act_notif);
1259 }
1260 }
Michal Vasko993af1e2018-12-10 12:05:17 +01001261 if (lyd_defaults_add_unres(&node, options, ctx, NULL, 0, data_tree, act_notif, unres, 0)) {
Michal Vasko228431e2018-07-10 15:47:11 +02001262 lyd_free_withsiblings(node);
1263 node = NULL;
1264 goto finish;
1265 }
1266 }
1267
1268finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001269 free(lybs.written);
1270 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001271 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001272 free(lybs.models);
1273 if (unres) {
1274 free(unres->node);
1275 free(unres->type);
1276 free(unres);
1277 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001278
1279 if (parsed) {
1280 *parsed = r;
1281 }
1282 return node;
1283}