blob: c169bb619bad98ac43b1a4dcb1a98380fd87a9f2 [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 Vasko1e82a3b2018-07-03 12:16:58 +020020
21#include "libyang.h"
22#include "common.h"
23#include "context.h"
24#include "parser.h"
25#include "tree_internal.h"
26
27#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
28#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
29
30static int
31lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
32{
33 int ret = 0, i, empty_chunk_i;
34 size_t to_read;
Michal Vaskoa9852522018-08-08 16:24:45 +020035 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020036
37 assert(data && lybs);
38
39 while (1) {
40 /* check for fully-read (empty) data chunks */
41 to_read = count;
42 empty_chunk_i = -1;
43 for (i = 0; i < lybs->used; ++i) {
44 /* we want the innermost chunks resolved first, so replace previous empty chunks,
45 * also ignore chunks that are completely finished, there is nothing for us to do */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020046 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020047 /* empty chunk, do not read more */
48 to_read = lybs->written[i];
49 empty_chunk_i = i;
50 }
51 }
52
53 if ((empty_chunk_i == -1) && !count) {
54 break;
55 }
56
57 /* we are actually reading some data, not just finishing another chunk */
58 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020059 if (buf) {
60 memcpy(buf, data + ret, to_read);
61 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020062
63 for (i = 0; i < lybs->used; ++i) {
64 /* decrease all written counters */
65 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020066 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020067 }
68 /* decrease count/buf */
69 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020070 if (buf) {
71 buf += to_read;
72 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020073
74 ret += to_read;
75 }
76
77 if (empty_chunk_i > -1) {
Michal Vaskoa9852522018-08-08 16:24:45 +020078 /* read the next chunk meta information */
79 memcpy(&meta, data + ret, LYB_META_BYTES);
80 lybs->written[empty_chunk_i] = 0;
81 lybs->inner_chunks[empty_chunk_i] = 0;
82
83 memcpy(&lybs->written[empty_chunk_i], &meta, LYB_SIZE_BYTES);
84 memcpy(&lybs->inner_chunks[empty_chunk_i], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
85
Michal Vasko1e82a3b2018-07-03 12:16:58 +020086 /* remember whether there is a following chunk or not */
87 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
88
Michal Vaskoa9852522018-08-08 16:24:45 +020089 ret += LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020090 }
91 }
92
93 return ret;
94}
95
96static int
Michal Vasko1440eb52018-08-14 13:42:14 +020097lyb_read_number(uint64_t *num, size_t bytes, const char *data, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +020098{
Michal Vasko1440eb52018-08-14 13:42:14 +020099 int r, ret = 0;
100 size_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200101 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200102
Michal Vasko1440eb52018-08-14 13:42:14 +0200103 for (i = 0; i < bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +0200104 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200105 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200106
107 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200108 }
109
110 return ret;
111}
112
113static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200114lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
115{
116 size_t bytes;
117
118 if (count < (2 << 8)) {
119 bytes = 1;
120 } else if (count < (2 << 16)) {
121 bytes = 2;
122 } else if (count < (2 << 24)) {
123 bytes = 3;
124 } else {
125 bytes = 4;
126 }
127
128 return lyb_read_number(enum_idx, bytes, data, lybs);
129}
130
131static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200132lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200133{
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200134 int next_chunk = 0, r, ret = 0;
135 size_t len = 0, cur_len;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200136
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200137 if (with_length) {
138 ret += (r = lyb_read(data, (uint8_t *)&len, 2, lybs));
139 LYB_HAVE_READ_GOTO(r, data, error);
140 } else {
141 /* read until the end of this subtree */
142 len = lybs->written[lybs->used - 1];
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200143 if (lybs->position[lybs->used - 1]) {
144 next_chunk = 1;
145 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200146 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200147
148 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200149 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200150
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200151 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200152 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200153
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200154 while (next_chunk) {
155 cur_len = lybs->written[lybs->used - 1];
156 if (lybs->position[lybs->used - 1]) {
157 next_chunk = 1;
158 } else {
159 next_chunk = 0;
160 }
161
162 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
163 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
164
165 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200166 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200167
168 len += cur_len;
169 }
170
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200171 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200172 return ret;
173
174error:
175 free((char *)*str);
176 *str = NULL;
177 return -1;
178}
179
180static void
181lyb_read_stop_subtree(struct lyb_state *lybs)
182{
183 if (lybs->written[lybs->used - 1]) {
184 LOGINT(NULL);
185 }
186
187 --lybs->used;
188}
189
190static int
191lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
192{
Michal Vaskoa9852522018-08-08 16:24:45 +0200193 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200194
195 if (lybs->used == lybs->size) {
196 lybs->size += LYB_STATE_STEP;
197 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
198 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
Michal Vaskoa9852522018-08-08 16:24:45 +0200199 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
200 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200201 }
202
Michal Vaskoa9852522018-08-08 16:24:45 +0200203 memcpy(&meta, data, LYB_META_BYTES);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200204
205 ++lybs->used;
Michal Vaskoa9852522018-08-08 16:24:45 +0200206 lybs->written[lybs->used - 1] = 0;
207 lybs->inner_chunks[lybs->used - 1] = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200208
Michal Vaskoa9852522018-08-08 16:24:45 +0200209 memcpy(&lybs->written[lybs->used - 1], &meta, LYB_SIZE_BYTES);
210 memcpy(&lybs->inner_chunks[lybs->used - 1], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
211 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
212
213 return LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200214}
215
216static int
217lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
218{
219 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200220 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200221 uint16_t rev = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200222
223 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200224 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200225 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200226
227 /* revision */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200228 ret += (r = lyb_read(data, (uint8_t *)&rev, sizeof rev, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200229 LYB_HAVE_READ_GOTO(r, data, error);
230
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200231 if (rev) {
232 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200233 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
234 } else {
235 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
236 }
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200237 if (ctx->data_clb) {
238 if (!*mod) {
239 *mod = ctx->data_clb(ctx, mod_name, NULL, 0, ctx->data_clb_data);
240 } else if (!(*mod)->implemented) {
241 *mod = ctx->data_clb(ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
242 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200243 }
244
245 free(mod_name);
246 return ret;
247
248error:
249 free(mod_name);
250 return -1;
251}
252
253static struct lyd_node *
254lyb_new_node(const struct lys_node *schema)
255{
256 struct lyd_node *node;
257
258 switch (schema->nodetype) {
259 case LYS_CONTAINER:
260 case LYS_LIST:
261 case LYS_NOTIF:
262 case LYS_RPC:
263 case LYS_ACTION:
264 node = calloc(sizeof(struct lyd_node), 1);
265 break;
266 case LYS_LEAF:
267 case LYS_LEAFLIST:
268 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200269
270 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
271 node->validity |= LYD_VAL_LEAFREF;
272 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200273 break;
274 case LYS_ANYDATA:
275 case LYS_ANYXML:
276 node = calloc(sizeof(struct lyd_node_anydata), 1);
277 break;
278 default:
279 return NULL;
280 }
281 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
282
283 /* fill basic info */
284 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200285 if (resolve_applies_when(schema, 0, NULL)) {
286 node->when_status = LYD_WHEN;
287 }
288 node->prev = node;
289
290 return node;
291}
292
293static int
294lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
295{
296 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200297 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200298 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
299
300 /* read value type */
301 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
302 LYB_HAVE_READ_RETURN(r, data, -1);
303
304 /* read anydata content */
305 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko33901702018-08-17 10:29:09 +0200306 /* invalid situation */
307 LOGINT(node->schema->module->ctx);
308 return -1;
Michal Vaskodcaf7222018-08-08 16:27:00 +0200309 } else if (any->value_type == LYD_ANYDATA_LYB) {
310 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
311 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200312 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200313 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200314 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200315
316 /* add to dictionary */
317 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200318 }
319
320 return ret;
321}
322
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200323/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200324static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200325lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
326 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200327{
Michal Vasko228431e2018-07-10 15:47:11 +0200328 int r, ret;
329 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200330 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200331 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200332 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200333
Michal Vasko42132c52018-07-24 16:09:21 +0200334 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200335 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200336 ret = lyb_read_string(data, &str, 0, lybs);
337 if (ret > -1) {
338 *value_str = lydict_insert_zc(ctx, str);
339 }
340 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200341 }
342
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200343 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200344 case LY_TYPE_INST:
345 case LY_TYPE_IDENT:
346 case LY_TYPE_UNION:
347 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200348 ret = lyb_read_string(data, &str, 0, lybs);
349 if (ret > -1) {
350 *value_str = lydict_insert_zc(ctx, str);
351 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200352 break;
353 case LY_TYPE_BINARY:
354 case LY_TYPE_STRING:
355 case LY_TYPE_UNKNOWN:
356 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200357 ret = lyb_read_string(data, &str, 0, lybs);
358 if (ret > -1) {
359 value->string = lydict_insert_zc(ctx, str);
360 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200361 break;
362 case LY_TYPE_BITS:
363 /* find the correct structure */
364 for (; !type->info.bits.count; type = &type->der->type);
365
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200366 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
367 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200368
369 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200370 ret = 0;
371 for (i = 0; i < type->info.bits.count; ++i) {
372 if (i % 8 == 0) {
373 /* read another byte */
374 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
375 if (r < 0) {
376 return -1;
377 }
378 }
379
380 if (byte & (0x01 << (i % 8))) {
381 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200382 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200383 }
384 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200385 break;
386 case LY_TYPE_BOOL:
387 /* read byte */
388 ret = lyb_read(data, &byte, sizeof byte, lybs);
389 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200390 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200391 }
392 break;
393 case LY_TYPE_EMPTY:
394 /* nothing to read */
395 ret = 0;
396 break;
397 case LY_TYPE_ENUM:
398 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200399 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200400
Michal Vasko228431e2018-07-10 15:47:11 +0200401 num = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200402 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
Michal Vaskob7400232018-07-11 15:35:57 +0200403 if (ret > 0) {
404 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200405 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200406 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200407 break;
408 case LY_TYPE_INT8:
409 case LY_TYPE_UINT8:
Michal Vasko1440eb52018-08-14 13:42:14 +0200410 ret = lyb_read_number((uint64_t *)&value->uint8, 1, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200411 break;
412 case LY_TYPE_INT16:
413 case LY_TYPE_UINT16:
Michal Vasko1440eb52018-08-14 13:42:14 +0200414 ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200415 break;
416 case LY_TYPE_INT32:
417 case LY_TYPE_UINT32:
Michal Vasko1440eb52018-08-14 13:42:14 +0200418 ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200419 break;
420 case LY_TYPE_DEC64:
421 case LY_TYPE_INT64:
422 case LY_TYPE_UINT64:
Michal Vasko1440eb52018-08-14 13:42:14 +0200423 ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200424 break;
425 default:
426 return -1;
427 }
428
429 return ret;
430}
431
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200432/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200433static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200434lyb_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 +0200435{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200436 struct ly_ctx *ctx;
437 struct lys_module *mod;
Michal Vasko228431e2018-07-10 15:47:11 +0200438 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200439 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200440 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200441 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200442 const char **value_str;
443 LY_DATA_TYPE value_type;
444 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200445
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200446 if (leaf) {
447 ctx = leaf->schema->module->ctx;
448 mod = lys_node_module(leaf->schema);
449
450 value = &leaf->value;
451 value_str = &leaf->value_str;
452 value_flags = &leaf->value_flags;
453 value_type = leaf->value_type;
454 } else {
455 ctx = attr->annotation->module->ctx;
456 mod = lys_main_module(attr->annotation->module);
457
458 value = &attr->value;
459 value_str = &attr->value_str;
460 value_flags = &attr->value_flags;
461 value_type = attr->value_type;
462 }
463
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200464 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200465 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200466 *value_flags &= ~LY_VALUE_USER;
467 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200468 return -1;
469 }
470
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200471 if (!(*value_flags & LY_VALUE_USER)) {
472 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 +0200473 }
474 return 0;
475 }
476
Michal Vaskob7400232018-07-11 15:35:57 +0200477 /* we are parsing leafref/ptr union stored as the target type,
478 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200479 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
480 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200481 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200482 /* we already have a string */
483 goto parse_reference;
484 }
485 }
486
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200487 switch (value_type) {
Michal Vasko58608522018-08-22 13:04:37 +0200488 case LY_TYPE_BITS:
489 case LY_TYPE_DEC64:
490 /* we need the actual type */
491 for (; type->base == LY_TYPE_LEAFREF; type = &type->der->type);
492 break;
493 default:
494 break;
495 }
496
497 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200498 case LY_TYPE_IDENT:
499 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200500 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
501 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200502 return -1;
503 }
504 break;
Michal Vasko56670362018-08-08 16:27:21 +0200505 case LY_TYPE_INST:
506 /* unresolved instance-identifier, keep value NULL */
507 value->instance = NULL;
508 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200509 case LY_TYPE_BINARY:
510 case LY_TYPE_STRING:
511 case LY_TYPE_UNKNOWN:
512 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200513 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200514 break;
515 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200516 /* print the set bits */
517 str = malloc(1);
518 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
519 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200520 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200521 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200522 if (value->bit[i]) {
523 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200524 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
525
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200526 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200527 }
528 }
529
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200530 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200531 break;
532 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200533 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200534 break;
535 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200536 *value_str = lydict_insert(ctx, "", 0);
537 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200538 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200539 if (attr) {
540 /* we do not support union type attribute */
541 LOGINT(ctx);
542 return -1;
543 }
544
545 if (resolve_union(leaf, type, 1, 2, NULL)) {
546 return -1;
547 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200548 break;
549 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200550 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200551 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200552 break;
553 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200554 sprintf(num_str, "%d", value->int8);
555 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200556 break;
557 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200558 sprintf(num_str, "%u", value->uint8);
559 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200560 break;
561 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200562 sprintf(num_str, "%d", value->int16);
563 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200564 break;
565 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200566 sprintf(num_str, "%u", value->uint16);
567 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200568 break;
569 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200570 sprintf(num_str, "%d", value->int32);
571 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200572 break;
573 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200574 sprintf(num_str, "%u", value->uint32);
575 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200576 break;
577 case LY_TYPE_INT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200578 sprintf(num_str, "%"PRId64, value->int64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200579 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200580 break;
581 case LY_TYPE_UINT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200582 sprintf(num_str, "%"PRIu64, value->uint64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200583 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200584 break;
585 case LY_TYPE_DEC64:
Michal Vasko27e5e682018-07-23 14:22:57 +0200586 frac = value->dec64 % type->info.dec64.div;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200587 dig = type->info.dec64.dig;
588 /* remove trailing zeros */
589 while ((dig > 1) && !(frac % 10)) {
590 frac /= 10;
591 --dig;
592 }
593
Michal Vaskoe581e982018-08-21 12:26:55 +0200594 sprintf(num_str, "%"PRId64".%.*"PRId64, value->dec64 / (int64_t)type->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200595 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200596 break;
597 default:
598 return -1;
599 }
600
Michal Vasko56670362018-08-08 16:27:21 +0200601 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
602 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskob7400232018-07-11 15:35:57 +0200603parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200604 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200605
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200606 if (attr) {
607 /* we do not support reference types of attributes */
608 LOGINT(ctx);
609 return -1;
610 }
611
612 if (type->base == LY_TYPE_INST) {
613 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
614 return -1;
615 }
616 } else if (type->base == LY_TYPE_LEAFREF) {
617 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200618 return -1;
619 }
620 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200621 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200622 return -1;
623 }
624 }
625 }
626
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200627 return 0;
628}
629
630static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200631lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
632 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200633{
634 int r, ret = 0;
635 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200636
637 struct ly_ctx *ctx;
638 const char **value_str;
639 lyd_val *value;
640 LY_DATA_TYPE *value_type;
641 uint8_t *value_flags;
642
643 assert((leaf || attr) && (!leaf || !attr));
644
645 if (leaf) {
646 ctx = leaf->schema->module->ctx;
647 value_str = &leaf->value_str;
648 value = &leaf->value;
649 value_type = &leaf->value_type;
650 value_flags = &leaf->value_flags;
651 } else {
652 ctx = attr->annotation->module->ctx;
653 value_str = &attr->value_str;
654 value = &attr->value;
655 value_type = &attr->value_type;
656 value_flags = &attr->value_flags;
657 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200658
659 /* read value type and flags on the first byte */
660 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
661 LYB_HAVE_READ_RETURN(r, data, -1);
662
663 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200664 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200665 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200666 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200667 leaf->dflt = 1;
668 }
669 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200670 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200671 }
672 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200673 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200674 }
675
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200676 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200677 LYB_HAVE_READ_RETURN(r, data, -1);
678
Michal Vasko27e5e682018-07-23 14:22:57 +0200679 /* union is handled specially */
680 if (type->base == LY_TYPE_UNION) {
681 assert(*value_type == LY_TYPE_STRING);
682
683 *value_str = value->string;
684 value->string = NULL;
685 *value_type = LY_TYPE_UNION;
686 }
687
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200688 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200689 LYB_HAVE_READ_RETURN(r, data, -1);
690
691 return ret;
692}
693
694static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200695lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
696 struct lyb_state *lybs)
697{
698 int r, ret = 0, pos, i, j, k;
699 const struct lys_submodule *submod = NULL;
700 char *attr_name = NULL;
701
702 /* attr name */
703 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
704 LYB_HAVE_READ_RETURN(r, data, -1);
705
706 /* search module */
707 pos = -1;
708 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
709 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
710 if (j == -1) {
711 break;
712 }
713 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
714 pos = i + j;
715 break;
716 }
717 }
718
719 /* try submodules */
720 if (pos == -1) {
721 for (k = 0; k < mod->inc_size; ++k) {
722 submod = mod->inc[k].submodule;
723 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
724 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
725 if (j == -1) {
726 break;
727 }
728 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
729 pos = i + j;
730 break;
731 }
732 }
733 }
734 }
735
736 if (pos == -1) {
737 *ext = NULL;
738 } else {
739 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
740 }
741
742 if (!*ext && (options & LYD_OPT_STRICT)) {
743 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
744 free(attr_name);
745 return -1;
746 }
747
748 free(attr_name);
749 return ret;
750}
751
752static int
753lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
754{
755 int r, ret = 0;
756 uint8_t i, count = 0;
757 const struct lys_module *mod;
Michal Vasko3cb7d172018-08-17 10:54:40 +0200758 struct lys_type **type;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200759 struct lyd_attr *attr = NULL;
760 struct lys_ext_instance_complex *ext;
761 struct ly_ctx *ctx = node->schema->module->ctx;
762
763 /* read number of attributes stored */
764 ret += (r = lyb_read(data, &count, 1, lybs));
765 LYB_HAVE_READ_GOTO(r, data, error);
766
767 /* read attributes */
768 for (i = 0; i < count; ++i) {
769 ret += (r = lyb_read_start_subtree(data, lybs));
770 LYB_HAVE_READ_GOTO(r, data, error);
771
772 /* find model */
773 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
774 LYB_HAVE_READ_GOTO(r, data, error);
775
Michal Vasko53830662018-07-24 16:09:49 +0200776 if (mod) {
777 /* annotation name */
778 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
779 LYB_HAVE_READ_GOTO(r, data, error);
780 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200781
Michal Vasko53830662018-07-24 16:09:49 +0200782 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200783 /* unknown attribute, skip it */
784 do {
785 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200786 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200787 } while (lybs->written[lybs->used - 1]);
788 goto stop_subtree;
789 }
790
791 /* allocate new attribute */
792 if (!attr) {
793 assert(!node->attr);
794
795 attr = calloc(1, sizeof *attr);
796 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
797
798 node->attr = attr;
799 } else {
800 attr->next = calloc(1, sizeof *attr);
801 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
802
803 attr = attr->next;
804 }
805
806 /* attribute annotation */
807 attr->annotation = ext;
808
809 /* attribute name */
810 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
811
812 /* get the type */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200813 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
814 if (!type || !(*type)) {
815 goto error;
816 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200817
818 /* attribute value */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200819 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200820 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200821
822stop_subtree:
823 lyb_read_stop_subtree(lybs);
824 }
825
826 return ret;
827
828error:
829 lyd_free_attr(ctx, node, node->attr, 1);
830 return -1;
831}
832
833static int
Michal Vaskob7400232018-07-11 15:35:57 +0200834lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200835{
836 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200837 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200838
Michal Vaskob7400232018-07-11 15:35:57 +0200839 /* compare all the hashes starting from collision ID 0 */
840 for (i = 0; i < hash_count; ++i) {
841 sibling_hash = lyb_hash(sibling, i);
842 if (sibling_hash != hash[i]) {
843 return 0;
844 }
845 }
Michal Vasko228431e2018-07-10 15:47:11 +0200846
Michal Vaskob7400232018-07-11 15:35:57 +0200847 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200848}
849
850static int
851lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
852 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200853{
854 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200855 uint8_t i, j;
856 struct lys_node *sibling;
857 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200858 struct ly_ctx *ctx;
859
860 assert((sparent || mod) && (!sparent || !mod));
861 ctx = (sparent ? sparent->module->ctx : mod->ctx);
862
Michal Vaskob7400232018-07-11 15:35:57 +0200863 /* read the first hash */
864 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200865 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200866
867 /* based on the first hash read all the other ones, if any */
868 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
869
870 /* move the first hash on its accurate position */
871 hash[i] = hash[0];
872
873 /* read the rest of hashes */
874 for (j = i; j; --j) {
875 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
876 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200877
Michal Vasko365849c2018-08-07 11:31:30 +0200878 /* correct collision ID */
879 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
880 /* preceded with zeros */
881 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200882 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200883
Michal Vaskoe3880e62018-07-11 16:18:34 +0200884 /* handle yang data templates */
885 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
886 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
887 if (!sparent) {
888 sibling = NULL;
889 goto finish;
890 }
891 }
892
893 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200894 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
895 sibling = NULL;
896 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
897 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
898 break;
899 }
900 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
901 break;
902 }
903 }
904 if (!sibling) {
905 /* fail */
906 goto finish;
907 }
908
909 /* use only input/output children nodes */
910 sparent = sibling;
911 }
912
913 /* find our node with matching hashes */
914 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200915 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
916 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200917 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 +0200918 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200919 break;
920 }
921 }
922
Michal Vaskob7400232018-07-11 15:35:57 +0200923finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200924 *snode = sibling;
925 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200926 if (mod) {
927 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
928 } else {
929 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
930 }
931 return -1;
932 }
933
934 return ret;
935}
936
937static int
938lyb_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 +0200939 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200940{
941 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200942 struct lyd_node *node = NULL, *iter;
943 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200944 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200945
946 assert((parent && !first_sibling) || (!parent && first_sibling));
947
948 /* register a new subtree */
949 ret += (r = lyb_read_start_subtree(data, lybs));
950 LYB_HAVE_READ_GOTO(r, data, error);
951
952 if (!parent) {
953 /* top-level, read module name */
954 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
955 LYB_HAVE_READ_GOTO(r, data, error);
956
Michal Vasko53830662018-07-24 16:09:49 +0200957 if (mod) {
958 /* read hash, find the schema node starting from mod, possibly yang_data_name */
959 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
960 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200961 } else {
Michal Vasko53830662018-07-24 16:09:49 +0200962 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200963
Michal Vaskoe3880e62018-07-11 16:18:34 +0200964 /* read hash, find the schema node starting from parent schema */
965 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
966 }
967 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200968 LYB_HAVE_READ_GOTO(r, data, error);
969
Michal Vasko53830662018-07-24 16:09:49 +0200970 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200971 /* unknown data subtree, skip it whole */
972 do {
973 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +0200974 /* also skip the meta information inside */
975 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +0200976 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200977 goto stop_subtree;
978 }
979
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200980 /*
981 * read the node
982 */
983 node = lyb_new_node(snode);
984 if (!node) {
985 goto error;
986 }
987
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200988 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
989 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200990
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200991 /* read node content */
992 switch (snode->nodetype) {
993 case LYS_CONTAINER:
994 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200995 case LYS_NOTIF:
996 case LYS_RPC:
997 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200998 /* nothing to read */
999 break;
1000 case LYS_LEAF:
1001 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001002 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1003 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001004 LYB_HAVE_READ_GOTO(r, data, error);
1005 break;
1006 case LYS_ANYXML:
1007 case LYS_ANYDATA:
1008 ret += (r = lyb_parse_anydata(node, data, lybs));
1009 LYB_HAVE_READ_GOTO(r, data, error);
1010 break;
1011 default:
1012 goto error;
1013 }
1014
1015 /* insert into data tree, manually */
1016 if (parent) {
1017 if (!parent->child) {
1018 /* only child */
1019 parent->child = node;
1020 } else {
1021 /* last child */
1022 parent->child->prev->next = node;
1023 node->prev = parent->child->prev;
1024 parent->child->prev = node;
1025 }
1026 node->parent = parent;
1027 } else if (*first_sibling) {
1028 /* last sibling */
1029 (*first_sibling)->prev->next = node;
1030 node->prev = (*first_sibling)->prev;
1031 (*first_sibling)->prev = node;
1032 } else {
1033 /* only sibling */
1034 *first_sibling = node;
1035 }
1036
1037 /* read all descendants */
1038 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001039 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001040 LYB_HAVE_READ_GOTO(r, data, error);
1041 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001042
1043 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001044 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001045 LY_TREE_FOR(node->child, iter) {
1046 if (!iter->dflt) {
1047 break;
1048 }
1049 }
1050
1051 if (!iter) {
1052 node->dflt = 1;
1053 }
1054 }
1055
Michal Vaskofe43d042018-07-24 09:43:46 +02001056#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001057 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1058 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001059 lyd_hash(node);
1060 lyd_insert_hash(node);
1061 }
1062#endif
1063
Michal Vasko228431e2018-07-10 15:47:11 +02001064stop_subtree:
1065 /* end the subtree */
1066 lyb_read_stop_subtree(lybs);
1067
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001068 return ret;
1069
1070error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001071 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001072 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001073 *first_sibling = NULL;
1074 }
1075 return -1;
1076}
1077
1078static int
Michal Vasko228431e2018-07-10 15:47:11 +02001079lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1080{
1081 int i, r, ret = 0;
1082
1083 /* read model count */
1084 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1085 LYB_HAVE_READ_RETURN(r, data, -1);
1086
1087 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1088 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1089
1090 /* read modules */
1091 for (i = 0; i < lybs->mod_count; ++i) {
1092 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1093 LYB_HAVE_READ_RETURN(r, data, -1);
1094 }
1095
1096 return ret;
1097}
1098
1099static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001100lyb_parse_header(const char *data, struct lyb_state *lybs)
1101{
1102 int ret = 0;
1103 uint8_t byte = 0;
1104
Michal Vasko228431e2018-07-10 15:47:11 +02001105 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001106 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1107
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001108 return ret;
1109}
1110
1111struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001112lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1113 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001114{
Michal Vaskobeeb1bf2018-08-17 10:29:29 +02001115 int r = 0, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001116 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1117 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001118 struct lyb_state lybs;
1119
1120 if (!ctx || !data) {
1121 LOGARG;
1122 return NULL;
1123 }
1124
1125 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1126 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001127 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1128 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001129 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001130 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001131 lybs.models = NULL;
1132 lybs.mod_count = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001133
1134 unres = calloc(1, sizeof *unres);
1135 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001136
1137 /* read header */
1138 ret += (r = lyb_parse_header(data, &lybs));
1139 LYB_HAVE_READ_GOTO(r, data, finish);
1140
Michal Vasko228431e2018-07-10 15:47:11 +02001141 /* read used models */
1142 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1143 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001144
1145 /* read subtree(s) */
1146 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001147 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1148 if (r < 0) {
1149 lyd_free_withsiblings(node);
1150 node = NULL;
1151 goto finish;
1152 }
1153 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001154 }
1155
1156 /* read the last zero, parsing finished */
1157 ++ret;
1158 r = ret;
1159
Michal Vasko228431e2018-07-10 15:47:11 +02001160 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1161 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1162 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1163 lyd_free_withsiblings(node);
1164 node = NULL;
1165 goto finish;
1166 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001167 }
Michal Vasko228431e2018-07-10 15:47:11 +02001168
1169 /* resolve any unresolved instance-identifiers */
1170 if (unres->count) {
1171 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1172 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1173 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1174 break;
1175 }
1176 LY_TREE_DFS_END(node, next, act_notif);
1177 }
1178 }
1179 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1180 lyd_free_withsiblings(node);
1181 node = NULL;
1182 goto finish;
1183 }
1184 }
1185
1186finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001187 free(lybs.written);
1188 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001189 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001190 free(lybs.models);
1191 if (unres) {
1192 free(unres->node);
1193 free(unres->type);
1194 free(unres);
1195 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001196
1197 if (parsed) {
1198 *parsed = r;
1199 }
1200 return node;
1201}