blob: b3cbab05dcc341efa8d03df4ff1b99b48400f68a [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 Vasko56670362018-08-08 16:27:21 +0200640 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
641 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskob7400232018-07-11 15:35:57 +0200642parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200643 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200644
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200645 if (attr) {
646 /* we do not support reference types of attributes */
647 LOGINT(ctx);
648 return -1;
649 }
650
651 if (type->base == LY_TYPE_INST) {
652 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
653 return -1;
654 }
655 } else if (type->base == LY_TYPE_LEAFREF) {
656 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200657 return -1;
658 }
659 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200660 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200661 return -1;
662 }
663 }
664 }
665
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200666 return 0;
667}
668
669static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200670lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
671 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200672{
673 int r, ret = 0;
674 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200675
676 struct ly_ctx *ctx;
677 const char **value_str;
678 lyd_val *value;
679 LY_DATA_TYPE *value_type;
680 uint8_t *value_flags;
681
682 assert((leaf || attr) && (!leaf || !attr));
683
684 if (leaf) {
685 ctx = leaf->schema->module->ctx;
686 value_str = &leaf->value_str;
687 value = &leaf->value;
688 value_type = &leaf->value_type;
689 value_flags = &leaf->value_flags;
690 } else {
691 ctx = attr->annotation->module->ctx;
692 value_str = &attr->value_str;
693 value = &attr->value;
694 value_type = &attr->value_type;
695 value_flags = &attr->value_flags;
696 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200697
698 /* read value type and flags on the first byte */
699 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
700 LYB_HAVE_READ_RETURN(r, data, -1);
701
702 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200703 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200704 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200705 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200706 leaf->dflt = 1;
707 }
708 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200709 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200710 }
711 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200712 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200713 }
714
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200715 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200716 LYB_HAVE_READ_RETURN(r, data, -1);
717
Michal Vasko27e5e682018-07-23 14:22:57 +0200718 /* union is handled specially */
719 if (type->base == LY_TYPE_UNION) {
720 assert(*value_type == LY_TYPE_STRING);
721
722 *value_str = value->string;
723 value->string = NULL;
724 *value_type = LY_TYPE_UNION;
725 }
726
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200727 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200728 LYB_HAVE_READ_RETURN(r, data, -1);
729
730 return ret;
731}
732
733static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200734lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
735 struct lyb_state *lybs)
736{
737 int r, ret = 0, pos, i, j, k;
738 const struct lys_submodule *submod = NULL;
739 char *attr_name = NULL;
740
741 /* attr name */
742 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
743 LYB_HAVE_READ_RETURN(r, data, -1);
744
745 /* search module */
746 pos = -1;
747 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
748 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
749 if (j == -1) {
750 break;
751 }
752 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
753 pos = i + j;
754 break;
755 }
756 }
757
758 /* try submodules */
759 if (pos == -1) {
760 for (k = 0; k < mod->inc_size; ++k) {
761 submod = mod->inc[k].submodule;
762 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
763 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
764 if (j == -1) {
765 break;
766 }
767 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
768 pos = i + j;
769 break;
770 }
771 }
772 }
773 }
774
775 if (pos == -1) {
776 *ext = NULL;
777 } else {
778 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
779 }
780
781 if (!*ext && (options & LYD_OPT_STRICT)) {
782 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
783 free(attr_name);
784 return -1;
785 }
786
787 free(attr_name);
788 return ret;
789}
790
791static int
792lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
793{
794 int r, ret = 0;
795 uint8_t i, count = 0;
796 const struct lys_module *mod;
Michal Vasko3cb7d172018-08-17 10:54:40 +0200797 struct lys_type **type;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200798 struct lyd_attr *attr = NULL;
799 struct lys_ext_instance_complex *ext;
800 struct ly_ctx *ctx = node->schema->module->ctx;
801
802 /* read number of attributes stored */
803 ret += (r = lyb_read(data, &count, 1, lybs));
804 LYB_HAVE_READ_GOTO(r, data, error);
805
806 /* read attributes */
807 for (i = 0; i < count; ++i) {
808 ret += (r = lyb_read_start_subtree(data, lybs));
809 LYB_HAVE_READ_GOTO(r, data, error);
810
811 /* find model */
812 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
813 LYB_HAVE_READ_GOTO(r, data, error);
814
Michal Vasko53830662018-07-24 16:09:49 +0200815 if (mod) {
816 /* annotation name */
817 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
818 LYB_HAVE_READ_GOTO(r, data, error);
819 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200820
Michal Vasko53830662018-07-24 16:09:49 +0200821 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200822 /* unknown attribute, skip it */
823 do {
824 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200825 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200826 } while (lybs->written[lybs->used - 1]);
827 goto stop_subtree;
828 }
829
830 /* allocate new attribute */
831 if (!attr) {
832 assert(!node->attr);
833
834 attr = calloc(1, sizeof *attr);
835 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
836
837 node->attr = attr;
838 } else {
839 attr->next = calloc(1, sizeof *attr);
840 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
841
842 attr = attr->next;
843 }
844
845 /* attribute annotation */
846 attr->annotation = ext;
847
848 /* attribute name */
849 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
850
851 /* get the type */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200852 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
853 if (!type || !(*type)) {
854 goto error;
855 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200856
857 /* attribute value */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200858 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200859 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200860
861stop_subtree:
862 lyb_read_stop_subtree(lybs);
863 }
864
865 return ret;
866
867error:
868 lyd_free_attr(ctx, node, node->attr, 1);
869 return -1;
870}
871
872static int
Michal Vaskob7400232018-07-11 15:35:57 +0200873lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200874{
875 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200876 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200877
Michal Vaskob7400232018-07-11 15:35:57 +0200878 /* compare all the hashes starting from collision ID 0 */
879 for (i = 0; i < hash_count; ++i) {
880 sibling_hash = lyb_hash(sibling, i);
881 if (sibling_hash != hash[i]) {
882 return 0;
883 }
884 }
Michal Vasko228431e2018-07-10 15:47:11 +0200885
Michal Vaskob7400232018-07-11 15:35:57 +0200886 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200887}
888
889static int
890lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
891 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200892{
893 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200894 uint8_t i, j;
895 struct lys_node *sibling;
896 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200897 struct ly_ctx *ctx;
898
899 assert((sparent || mod) && (!sparent || !mod));
900 ctx = (sparent ? sparent->module->ctx : mod->ctx);
901
Michal Vaskob7400232018-07-11 15:35:57 +0200902 /* read the first hash */
903 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200904 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200905
906 /* based on the first hash read all the other ones, if any */
Michal Vasko01fc23a2018-11-21 11:58:26 +0100907 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
908 if (i > LYB_HASH_BITS) {
909 return -1;
910 }
911 }
Michal Vaskob7400232018-07-11 15:35:57 +0200912
913 /* move the first hash on its accurate position */
914 hash[i] = hash[0];
915
916 /* read the rest of hashes */
917 for (j = i; j; --j) {
918 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
919 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200920
Michal Vasko365849c2018-08-07 11:31:30 +0200921 /* correct collision ID */
922 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
923 /* preceded with zeros */
924 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200925 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200926
Michal Vaskoe3880e62018-07-11 16:18:34 +0200927 /* handle yang data templates */
928 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
929 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
930 if (!sparent) {
931 sibling = NULL;
932 goto finish;
933 }
934 }
935
936 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200937 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
938 sibling = NULL;
939 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
940 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
941 break;
942 }
943 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
944 break;
945 }
946 }
947 if (!sibling) {
948 /* fail */
949 goto finish;
950 }
951
952 /* use only input/output children nodes */
953 sparent = sibling;
954 }
955
956 /* find our node with matching hashes */
957 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200958 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
959 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200960 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 +0200961 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200962 break;
963 }
964 }
965
Michal Vaskob7400232018-07-11 15:35:57 +0200966finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200967 *snode = sibling;
968 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200969 if (mod) {
970 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
971 } else {
972 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
973 }
974 return -1;
975 }
976
977 return ret;
978}
979
980static int
981lyb_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 +0200982 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200983{
984 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200985 struct lyd_node *node = NULL, *iter;
986 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200987 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200988
989 assert((parent && !first_sibling) || (!parent && first_sibling));
990
991 /* register a new subtree */
992 ret += (r = lyb_read_start_subtree(data, lybs));
993 LYB_HAVE_READ_GOTO(r, data, error);
994
995 if (!parent) {
996 /* top-level, read module name */
997 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
998 LYB_HAVE_READ_GOTO(r, data, error);
999
Michal Vasko53830662018-07-24 16:09:49 +02001000 if (mod) {
1001 /* read hash, find the schema node starting from mod, possibly yang_data_name */
1002 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
1003 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001004 } else {
Michal Vasko53830662018-07-24 16:09:49 +02001005 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001006
Michal Vaskoe3880e62018-07-11 16:18:34 +02001007 /* read hash, find the schema node starting from parent schema */
1008 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
1009 }
1010 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001011 LYB_HAVE_READ_GOTO(r, data, error);
1012
Michal Vasko53830662018-07-24 16:09:49 +02001013 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +02001014 /* unknown data subtree, skip it whole */
1015 do {
1016 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +02001017 /* also skip the meta information inside */
1018 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +02001019 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +02001020 goto stop_subtree;
1021 }
1022
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001023 /*
1024 * read the node
1025 */
1026 node = lyb_new_node(snode);
1027 if (!node) {
1028 goto error;
1029 }
1030
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001031 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1032 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001033
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001034 /* read node content */
1035 switch (snode->nodetype) {
1036 case LYS_CONTAINER:
1037 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +02001038 case LYS_NOTIF:
1039 case LYS_RPC:
1040 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001041 /* nothing to read */
1042 break;
1043 case LYS_LEAF:
1044 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001045 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1046 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001047 LYB_HAVE_READ_GOTO(r, data, error);
1048 break;
1049 case LYS_ANYXML:
1050 case LYS_ANYDATA:
1051 ret += (r = lyb_parse_anydata(node, data, lybs));
1052 LYB_HAVE_READ_GOTO(r, data, error);
1053 break;
1054 default:
1055 goto error;
1056 }
1057
1058 /* insert into data tree, manually */
1059 if (parent) {
1060 if (!parent->child) {
1061 /* only child */
1062 parent->child = node;
1063 } else {
1064 /* last child */
1065 parent->child->prev->next = node;
1066 node->prev = parent->child->prev;
1067 parent->child->prev = node;
1068 }
1069 node->parent = parent;
1070 } else if (*first_sibling) {
1071 /* last sibling */
1072 (*first_sibling)->prev->next = node;
1073 node->prev = (*first_sibling)->prev;
1074 (*first_sibling)->prev = node;
1075 } else {
1076 /* only sibling */
1077 *first_sibling = node;
1078 }
1079
1080 /* read all descendants */
1081 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001082 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001083 LYB_HAVE_READ_GOTO(r, data, error);
1084 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001085
1086 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001087 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001088 LY_TREE_FOR(node->child, iter) {
1089 if (!iter->dflt) {
1090 break;
1091 }
1092 }
1093
1094 if (!iter) {
1095 node->dflt = 1;
1096 }
1097 }
1098
Michal Vaskofe43d042018-07-24 09:43:46 +02001099#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001100 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1101 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001102 lyd_hash(node);
1103 lyd_insert_hash(node);
1104 }
1105#endif
1106
Michal Vasko228431e2018-07-10 15:47:11 +02001107stop_subtree:
1108 /* end the subtree */
1109 lyb_read_stop_subtree(lybs);
1110
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001111 return ret;
1112
1113error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001114 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001115 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001116 *first_sibling = NULL;
1117 }
1118 return -1;
1119}
1120
1121static int
Michal Vasko228431e2018-07-10 15:47:11 +02001122lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1123{
1124 int i, r, ret = 0;
Graeme Campbell856a40e2018-10-05 14:35:37 +13001125 uint8_t mod_count_buf[2];
Michal Vasko228431e2018-07-10 15:47:11 +02001126
1127 /* read model count */
Graeme Campbell856a40e2018-10-05 14:35:37 +13001128 ret += (r = lyb_read(data, mod_count_buf, 2, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001129 LYB_HAVE_READ_RETURN(r, data, -1);
Graeme Campbell856a40e2018-10-05 14:35:37 +13001130 lybs->mod_count = mod_count_buf[0] | (mod_count_buf[1] << 8);
Michal Vasko228431e2018-07-10 15:47:11 +02001131
1132 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1133 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1134
1135 /* read modules */
1136 for (i = 0; i < lybs->mod_count; ++i) {
1137 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1138 LYB_HAVE_READ_RETURN(r, data, -1);
1139 }
1140
1141 return ret;
1142}
1143
1144static int
Michal Vasko5c445042018-08-28 16:27:45 +02001145lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1146{
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001147 int r, ret = 0;
1148 char magic_byte = 0;
Michal Vasko5c445042018-08-28 16:27:45 +02001149
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001150 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1151 LYB_HAVE_READ_RETURN(r, data, -1);
1152 if (magic_byte != 'l') {
1153 LOGERR(NULL, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1154 return -1;
1155 }
Michal Vasko5c445042018-08-28 16:27:45 +02001156
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001157 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1158 LYB_HAVE_READ_RETURN(r, data, -1);
1159 if (magic_byte != 'y') {
1160 LOGERR(NULL, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1161 return -1;
1162 }
1163
1164 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1165 LYB_HAVE_READ_RETURN(r, data, -1);
1166 if (magic_byte != 'b') {
1167 LOGERR(NULL, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
Michal Vasko5c445042018-08-28 16:27:45 +02001168 return -1;
1169 }
1170
1171 return ret;
1172}
1173
1174static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001175lyb_parse_header(const char *data, struct lyb_state *lybs)
1176{
1177 int ret = 0;
1178 uint8_t byte = 0;
1179
Michal Vasko228431e2018-07-10 15:47:11 +02001180 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001181 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1182
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001183 return ret;
1184}
1185
1186struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001187lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1188 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001189{
Michal Vaskobeeb1bf2018-08-17 10:29:29 +02001190 int r = 0, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001191 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1192 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001193 struct lyb_state lybs;
1194
1195 if (!ctx || !data) {
1196 LOGARG;
1197 return NULL;
1198 }
1199
1200 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1201 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001202 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1203 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001204 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001205 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001206 lybs.models = NULL;
1207 lybs.mod_count = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001208
1209 unres = calloc(1, sizeof *unres);
1210 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001211
Michal Vasko5c445042018-08-28 16:27:45 +02001212 /* read magic number */
1213 ret += (r = lyb_parse_magic_number(data, &lybs));
1214 LYB_HAVE_READ_GOTO(r, data, finish);
1215
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001216 /* read header */
1217 ret += (r = lyb_parse_header(data, &lybs));
1218 LYB_HAVE_READ_GOTO(r, data, finish);
1219
Michal Vasko228431e2018-07-10 15:47:11 +02001220 /* read used models */
1221 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1222 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001223
1224 /* read subtree(s) */
1225 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001226 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1227 if (r < 0) {
1228 lyd_free_withsiblings(node);
1229 node = NULL;
1230 goto finish;
1231 }
1232 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001233 }
1234
1235 /* read the last zero, parsing finished */
1236 ++ret;
1237 r = ret;
1238
Michal Vasko228431e2018-07-10 15:47:11 +02001239 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1240 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1241 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1242 lyd_free_withsiblings(node);
1243 node = NULL;
1244 goto finish;
1245 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001246 }
Michal Vasko228431e2018-07-10 15:47:11 +02001247
1248 /* resolve any unresolved instance-identifiers */
1249 if (unres->count) {
1250 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1251 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1252 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1253 break;
1254 }
1255 LY_TREE_DFS_END(node, next, act_notif);
1256 }
1257 }
Michal Vasko993af1e2018-12-10 12:05:17 +01001258 if (lyd_defaults_add_unres(&node, options, ctx, NULL, 0, data_tree, act_notif, unres, 0)) {
Michal Vasko228431e2018-07-10 15:47:11 +02001259 lyd_free_withsiblings(node);
1260 node = NULL;
1261 goto finish;
1262 }
1263 }
1264
1265finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001266 free(lybs.written);
1267 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001268 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001269 free(lybs.models);
1270 if (unres) {
1271 free(unres->node);
1272 free(unres->type);
1273 free(unres);
1274 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001275
1276 if (parsed) {
1277 *parsed = r;
1278 }
1279 return node;
1280}