blob: 498791371fcc3eaaeb5acab29a0806797f8230fa [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>
19
20#include "libyang.h"
21#include "common.h"
22#include "context.h"
23#include "parser.h"
24#include "tree_internal.h"
25
26#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
27#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
28
29static int
30lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
31{
32 int ret = 0, i, empty_chunk_i;
33 size_t to_read;
Michal Vaskoa9852522018-08-08 16:24:45 +020034 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020035
36 assert(data && lybs);
37
38 while (1) {
39 /* check for fully-read (empty) data chunks */
40 to_read = count;
41 empty_chunk_i = -1;
42 for (i = 0; i < lybs->used; ++i) {
43 /* we want the innermost chunks resolved first, so replace previous empty chunks,
44 * also ignore chunks that are completely finished, there is nothing for us to do */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020045 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020046 /* empty chunk, do not read more */
47 to_read = lybs->written[i];
48 empty_chunk_i = i;
49 }
50 }
51
52 if ((empty_chunk_i == -1) && !count) {
53 break;
54 }
55
56 /* we are actually reading some data, not just finishing another chunk */
57 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020058 if (buf) {
59 memcpy(buf, data + ret, to_read);
60 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020061
62 for (i = 0; i < lybs->used; ++i) {
63 /* decrease all written counters */
64 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020065 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020066 }
67 /* decrease count/buf */
68 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020069 if (buf) {
70 buf += to_read;
71 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020072
73 ret += to_read;
74 }
75
76 if (empty_chunk_i > -1) {
Michal Vaskoa9852522018-08-08 16:24:45 +020077 /* read the next chunk meta information */
78 memcpy(&meta, data + ret, LYB_META_BYTES);
79 lybs->written[empty_chunk_i] = 0;
80 lybs->inner_chunks[empty_chunk_i] = 0;
81
82 memcpy(&lybs->written[empty_chunk_i], &meta, LYB_SIZE_BYTES);
83 memcpy(&lybs->inner_chunks[empty_chunk_i], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
84
Michal Vasko1e82a3b2018-07-03 12:16:58 +020085 /* remember whether there is a following chunk or not */
86 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
87
Michal Vaskoa9852522018-08-08 16:24:45 +020088 ret += LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020089 }
90 }
91
92 return ret;
93}
94
95static int
Michal Vasko1440eb52018-08-14 13:42:14 +020096lyb_read_number(uint64_t *num, size_t bytes, const char *data, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +020097{
Michal Vasko1440eb52018-08-14 13:42:14 +020098 int r, ret = 0;
99 size_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200100 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200101
Michal Vasko1440eb52018-08-14 13:42:14 +0200102 for (i = 0; i < bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +0200103 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200104 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200105
106 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200107 }
108
109 return ret;
110}
111
112static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200113lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
114{
115 size_t bytes;
116
117 if (count < (2 << 8)) {
118 bytes = 1;
119 } else if (count < (2 << 16)) {
120 bytes = 2;
121 } else if (count < (2 << 24)) {
122 bytes = 3;
123 } else {
124 bytes = 4;
125 }
126
127 return lyb_read_number(enum_idx, bytes, data, lybs);
128}
129
130static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200131lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200132{
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200133 int next_chunk = 0, r, ret = 0;
134 size_t len = 0, cur_len;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200135
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200136 if (with_length) {
137 ret += (r = lyb_read(data, (uint8_t *)&len, 2, lybs));
138 LYB_HAVE_READ_GOTO(r, data, error);
139 } else {
140 /* read until the end of this subtree */
141 len = lybs->written[lybs->used - 1];
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200142 if (lybs->position[lybs->used - 1]) {
143 next_chunk = 1;
144 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200145 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200146
147 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200148 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200149
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200150 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200151 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200152
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200153 while (next_chunk) {
154 cur_len = lybs->written[lybs->used - 1];
155 if (lybs->position[lybs->used - 1]) {
156 next_chunk = 1;
157 } else {
158 next_chunk = 0;
159 }
160
161 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
162 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
163
164 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200165 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200166
167 len += cur_len;
168 }
169
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200170 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200171 return ret;
172
173error:
174 free((char *)*str);
175 *str = NULL;
176 return -1;
177}
178
179static void
180lyb_read_stop_subtree(struct lyb_state *lybs)
181{
182 if (lybs->written[lybs->used - 1]) {
183 LOGINT(NULL);
184 }
185
186 --lybs->used;
187}
188
189static int
190lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
191{
Michal Vaskoa9852522018-08-08 16:24:45 +0200192 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200193
194 if (lybs->used == lybs->size) {
195 lybs->size += LYB_STATE_STEP;
196 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
197 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
Michal Vaskoa9852522018-08-08 16:24:45 +0200198 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
199 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200200 }
201
Michal Vaskoa9852522018-08-08 16:24:45 +0200202 memcpy(&meta, data, LYB_META_BYTES);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200203
204 ++lybs->used;
Michal Vaskoa9852522018-08-08 16:24:45 +0200205 lybs->written[lybs->used - 1] = 0;
206 lybs->inner_chunks[lybs->used - 1] = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200207
Michal Vaskoa9852522018-08-08 16:24:45 +0200208 memcpy(&lybs->written[lybs->used - 1], &meta, LYB_SIZE_BYTES);
209 memcpy(&lybs->inner_chunks[lybs->used - 1], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
210 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
211
212 return LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200213}
214
215static int
216lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
217{
218 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200219 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200220 uint16_t rev = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200221
222 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200223 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200224 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200225
226 /* revision */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200227 ret += (r = lyb_read(data, (uint8_t *)&rev, sizeof rev, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200228 LYB_HAVE_READ_GOTO(r, data, error);
229
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200230 if (rev) {
231 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200232 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
233 } else {
234 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
235 }
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200236 if (ctx->data_clb) {
237 if (!*mod) {
238 *mod = ctx->data_clb(ctx, mod_name, NULL, 0, ctx->data_clb_data);
239 } else if (!(*mod)->implemented) {
240 *mod = ctx->data_clb(ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
241 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200242 }
243
244 free(mod_name);
245 return ret;
246
247error:
248 free(mod_name);
249 return -1;
250}
251
252static struct lyd_node *
253lyb_new_node(const struct lys_node *schema)
254{
255 struct lyd_node *node;
256
257 switch (schema->nodetype) {
258 case LYS_CONTAINER:
259 case LYS_LIST:
260 case LYS_NOTIF:
261 case LYS_RPC:
262 case LYS_ACTION:
263 node = calloc(sizeof(struct lyd_node), 1);
264 break;
265 case LYS_LEAF:
266 case LYS_LEAFLIST:
267 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200268
269 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
270 node->validity |= LYD_VAL_LEAFREF;
271 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200272 break;
273 case LYS_ANYDATA:
274 case LYS_ANYXML:
275 node = calloc(sizeof(struct lyd_node_anydata), 1);
276 break;
277 default:
278 return NULL;
279 }
280 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
281
282 /* fill basic info */
283 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200284 if (resolve_applies_when(schema, 0, NULL)) {
285 node->when_status = LYD_WHEN;
286 }
287 node->prev = node;
288
289 return node;
290}
291
292static int
293lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
294{
295 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200296 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200297 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
298
299 /* read value type */
300 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
301 LYB_HAVE_READ_RETURN(r, data, -1);
302
303 /* read anydata content */
304 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko33901702018-08-17 10:29:09 +0200305 /* invalid situation */
306 LOGINT(node->schema->module->ctx);
307 return -1;
Michal Vaskodcaf7222018-08-08 16:27:00 +0200308 } else if (any->value_type == LYD_ANYDATA_LYB) {
309 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
310 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200311 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200312 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200313 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200314
315 /* add to dictionary */
316 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200317 }
318
319 return ret;
320}
321
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200322/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200323static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200324lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
325 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200326{
Michal Vasko228431e2018-07-10 15:47:11 +0200327 int r, ret;
328 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200329 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200330 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200331 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200332
Michal Vasko42132c52018-07-24 16:09:21 +0200333 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200334 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200335 ret = lyb_read_string(data, &str, 0, lybs);
336 if (ret > -1) {
337 *value_str = lydict_insert_zc(ctx, str);
338 }
339 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200340 }
341
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200342 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200343 case LY_TYPE_INST:
344 case LY_TYPE_IDENT:
345 case LY_TYPE_UNION:
346 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200347 ret = lyb_read_string(data, &str, 0, lybs);
348 if (ret > -1) {
349 *value_str = lydict_insert_zc(ctx, str);
350 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200351 break;
352 case LY_TYPE_BINARY:
353 case LY_TYPE_STRING:
354 case LY_TYPE_UNKNOWN:
355 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200356 ret = lyb_read_string(data, &str, 0, lybs);
357 if (ret > -1) {
358 value->string = lydict_insert_zc(ctx, str);
359 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200360 break;
361 case LY_TYPE_BITS:
362 /* find the correct structure */
363 for (; !type->info.bits.count; type = &type->der->type);
364
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200365 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
366 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200367
368 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200369 ret = 0;
370 for (i = 0; i < type->info.bits.count; ++i) {
371 if (i % 8 == 0) {
372 /* read another byte */
373 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
374 if (r < 0) {
375 return -1;
376 }
377 }
378
379 if (byte & (0x01 << (i % 8))) {
380 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200381 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200382 }
383 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200384 break;
385 case LY_TYPE_BOOL:
386 /* read byte */
387 ret = lyb_read(data, &byte, sizeof byte, lybs);
388 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200389 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200390 }
391 break;
392 case LY_TYPE_EMPTY:
393 /* nothing to read */
394 ret = 0;
395 break;
396 case LY_TYPE_ENUM:
397 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200398 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200399
Michal Vasko228431e2018-07-10 15:47:11 +0200400 num = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200401 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
Michal Vaskob7400232018-07-11 15:35:57 +0200402 if (ret > 0) {
403 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200404 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200405 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200406 break;
407 case LY_TYPE_INT8:
408 case LY_TYPE_UINT8:
Michal Vasko1440eb52018-08-14 13:42:14 +0200409 ret = lyb_read_number((uint64_t *)&value->uint8, 1, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200410 break;
411 case LY_TYPE_INT16:
412 case LY_TYPE_UINT16:
Michal Vasko1440eb52018-08-14 13:42:14 +0200413 ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200414 break;
415 case LY_TYPE_INT32:
416 case LY_TYPE_UINT32:
Michal Vasko1440eb52018-08-14 13:42:14 +0200417 ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200418 break;
419 case LY_TYPE_DEC64:
420 case LY_TYPE_INT64:
421 case LY_TYPE_UINT64:
Michal Vasko1440eb52018-08-14 13:42:14 +0200422 ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200423 break;
424 default:
425 return -1;
426 }
427
428 return ret;
429}
430
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200431/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200432static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200433lyb_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 +0200434{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200435 struct ly_ctx *ctx;
436 struct lys_module *mod;
Michal Vasko228431e2018-07-10 15:47:11 +0200437 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200438 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200439 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200440 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200441 const char **value_str;
442 LY_DATA_TYPE value_type;
443 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200444
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200445 if (leaf) {
446 ctx = leaf->schema->module->ctx;
447 mod = lys_node_module(leaf->schema);
448
449 value = &leaf->value;
450 value_str = &leaf->value_str;
451 value_flags = &leaf->value_flags;
452 value_type = leaf->value_type;
453 } else {
454 ctx = attr->annotation->module->ctx;
455 mod = lys_main_module(attr->annotation->module);
456
457 value = &attr->value;
458 value_str = &attr->value_str;
459 value_flags = &attr->value_flags;
460 value_type = attr->value_type;
461 }
462
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200463 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200464 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200465 *value_flags &= ~LY_VALUE_USER;
466 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200467 return -1;
468 }
469
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200470 if (!(*value_flags & LY_VALUE_USER)) {
471 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 +0200472 }
473 return 0;
474 }
475
Michal Vaskob7400232018-07-11 15:35:57 +0200476 /* we are parsing leafref/ptr union stored as the target type,
477 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200478 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
479 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200480 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200481 /* we already have a string */
482 goto parse_reference;
483 }
484 }
485
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200486 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200487 case LY_TYPE_IDENT:
488 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200489 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
490 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200491 return -1;
492 }
493 break;
Michal Vasko56670362018-08-08 16:27:21 +0200494 case LY_TYPE_INST:
495 /* unresolved instance-identifier, keep value NULL */
496 value->instance = NULL;
497 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200498 case LY_TYPE_BINARY:
499 case LY_TYPE_STRING:
500 case LY_TYPE_UNKNOWN:
501 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200502 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200503 break;
504 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200505 for (; !type->info.bits.count; type = &type->der->type);
506
507 /* print the set bits */
508 str = malloc(1);
509 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
510 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200511 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200512 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200513 if (value->bit[i]) {
514 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200515 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
516
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200517 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200518 }
519 }
520
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200521 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200522 break;
523 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200524 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200525 break;
526 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200527 *value_str = lydict_insert(ctx, "", 0);
528 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200529 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200530 if (attr) {
531 /* we do not support union type attribute */
532 LOGINT(ctx);
533 return -1;
534 }
535
536 if (resolve_union(leaf, type, 1, 2, NULL)) {
537 return -1;
538 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200539 break;
540 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200541 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200542 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200543 break;
544 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200545 sprintf(num_str, "%d", value->int8);
546 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200547 break;
548 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200549 sprintf(num_str, "%u", value->uint8);
550 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200551 break;
552 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200553 sprintf(num_str, "%d", value->int16);
554 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200555 break;
556 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200557 sprintf(num_str, "%u", value->uint16);
558 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200559 break;
560 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200561 sprintf(num_str, "%d", value->int32);
562 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200563 break;
564 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200565 sprintf(num_str, "%u", value->uint32);
566 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200567 break;
568 case LY_TYPE_INT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200569 sprintf(num_str, "%ld", value->int64);
570 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200571 break;
572 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200573 sprintf(num_str, "%lu", value->uint64);
574 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200575 break;
576 case LY_TYPE_DEC64:
Michal Vasko27e5e682018-07-23 14:22:57 +0200577 frac = value->dec64 % type->info.dec64.div;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200578 dig = type->info.dec64.dig;
579 /* remove trailing zeros */
580 while ((dig > 1) && !(frac % 10)) {
581 frac /= 10;
582 --dig;
583 }
584
585 sprintf(num_str, "%ld.%.*ld", value->dec64 / (int64_t)type->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200586 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200587 break;
588 default:
589 return -1;
590 }
591
Michal Vasko56670362018-08-08 16:27:21 +0200592 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
593 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskob7400232018-07-11 15:35:57 +0200594parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200595 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200596
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200597 if (attr) {
598 /* we do not support reference types of attributes */
599 LOGINT(ctx);
600 return -1;
601 }
602
603 if (type->base == LY_TYPE_INST) {
604 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
605 return -1;
606 }
607 } else if (type->base == LY_TYPE_LEAFREF) {
608 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200609 return -1;
610 }
611 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200612 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200613 return -1;
614 }
615 }
616 }
617
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200618 return 0;
619}
620
621static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200622lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
623 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200624{
625 int r, ret = 0;
626 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200627
628 struct ly_ctx *ctx;
629 const char **value_str;
630 lyd_val *value;
631 LY_DATA_TYPE *value_type;
632 uint8_t *value_flags;
633
634 assert((leaf || attr) && (!leaf || !attr));
635
636 if (leaf) {
637 ctx = leaf->schema->module->ctx;
638 value_str = &leaf->value_str;
639 value = &leaf->value;
640 value_type = &leaf->value_type;
641 value_flags = &leaf->value_flags;
642 } else {
643 ctx = attr->annotation->module->ctx;
644 value_str = &attr->value_str;
645 value = &attr->value;
646 value_type = &attr->value_type;
647 value_flags = &attr->value_flags;
648 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200649
650 /* read value type and flags on the first byte */
651 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
652 LYB_HAVE_READ_RETURN(r, data, -1);
653
654 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200655 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200656 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200657 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200658 leaf->dflt = 1;
659 }
660 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200661 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200662 }
663 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200664 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200665 }
666
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200667 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200668 LYB_HAVE_READ_RETURN(r, data, -1);
669
Michal Vasko27e5e682018-07-23 14:22:57 +0200670 /* union is handled specially */
671 if (type->base == LY_TYPE_UNION) {
672 assert(*value_type == LY_TYPE_STRING);
673
674 *value_str = value->string;
675 value->string = NULL;
676 *value_type = LY_TYPE_UNION;
677 }
678
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200679 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200680 LYB_HAVE_READ_RETURN(r, data, -1);
681
682 return ret;
683}
684
685static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200686lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
687 struct lyb_state *lybs)
688{
689 int r, ret = 0, pos, i, j, k;
690 const struct lys_submodule *submod = NULL;
691 char *attr_name = NULL;
692
693 /* attr name */
694 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
695 LYB_HAVE_READ_RETURN(r, data, -1);
696
697 /* search module */
698 pos = -1;
699 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
700 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
701 if (j == -1) {
702 break;
703 }
704 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
705 pos = i + j;
706 break;
707 }
708 }
709
710 /* try submodules */
711 if (pos == -1) {
712 for (k = 0; k < mod->inc_size; ++k) {
713 submod = mod->inc[k].submodule;
714 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
715 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
716 if (j == -1) {
717 break;
718 }
719 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
720 pos = i + j;
721 break;
722 }
723 }
724 }
725 }
726
727 if (pos == -1) {
728 *ext = NULL;
729 } else {
730 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
731 }
732
733 if (!*ext && (options & LYD_OPT_STRICT)) {
734 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
735 free(attr_name);
736 return -1;
737 }
738
739 free(attr_name);
740 return ret;
741}
742
743static int
744lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
745{
746 int r, ret = 0;
747 uint8_t i, count = 0;
748 const struct lys_module *mod;
749 struct lys_type *type;
750 struct lyd_attr *attr = NULL;
751 struct lys_ext_instance_complex *ext;
752 struct ly_ctx *ctx = node->schema->module->ctx;
753
754 /* read number of attributes stored */
755 ret += (r = lyb_read(data, &count, 1, lybs));
756 LYB_HAVE_READ_GOTO(r, data, error);
757
758 /* read attributes */
759 for (i = 0; i < count; ++i) {
760 ret += (r = lyb_read_start_subtree(data, lybs));
761 LYB_HAVE_READ_GOTO(r, data, error);
762
763 /* find model */
764 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
765 LYB_HAVE_READ_GOTO(r, data, error);
766
Michal Vasko53830662018-07-24 16:09:49 +0200767 if (mod) {
768 /* annotation name */
769 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
770 LYB_HAVE_READ_GOTO(r, data, error);
771 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200772
Michal Vasko53830662018-07-24 16:09:49 +0200773 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200774 /* unknown attribute, skip it */
775 do {
776 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200777 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200778 } while (lybs->written[lybs->used - 1]);
779 goto stop_subtree;
780 }
781
782 /* allocate new attribute */
783 if (!attr) {
784 assert(!node->attr);
785
786 attr = calloc(1, sizeof *attr);
787 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
788
789 node->attr = attr;
790 } else {
791 attr->next = calloc(1, sizeof *attr);
792 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
793
794 attr = attr->next;
795 }
796
797 /* attribute annotation */
798 attr->annotation = ext;
799
800 /* attribute name */
801 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
802
803 /* get the type */
804 type = *(struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
805
806 /* attribute value */
807 ret += (r = lyb_parse_value(type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200808 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200809
810stop_subtree:
811 lyb_read_stop_subtree(lybs);
812 }
813
814 return ret;
815
816error:
817 lyd_free_attr(ctx, node, node->attr, 1);
818 return -1;
819}
820
821static int
Michal Vaskob7400232018-07-11 15:35:57 +0200822lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200823{
824 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200825 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200826
Michal Vaskob7400232018-07-11 15:35:57 +0200827 /* compare all the hashes starting from collision ID 0 */
828 for (i = 0; i < hash_count; ++i) {
829 sibling_hash = lyb_hash(sibling, i);
830 if (sibling_hash != hash[i]) {
831 return 0;
832 }
833 }
Michal Vasko228431e2018-07-10 15:47:11 +0200834
Michal Vaskob7400232018-07-11 15:35:57 +0200835 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200836}
837
838static int
839lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
840 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200841{
842 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200843 uint8_t i, j;
844 struct lys_node *sibling;
845 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200846 struct ly_ctx *ctx;
847
848 assert((sparent || mod) && (!sparent || !mod));
849 ctx = (sparent ? sparent->module->ctx : mod->ctx);
850
Michal Vaskob7400232018-07-11 15:35:57 +0200851 /* read the first hash */
852 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200853 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200854
855 /* based on the first hash read all the other ones, if any */
856 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
857
858 /* move the first hash on its accurate position */
859 hash[i] = hash[0];
860
861 /* read the rest of hashes */
862 for (j = i; j; --j) {
863 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
864 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200865
Michal Vasko365849c2018-08-07 11:31:30 +0200866 /* correct collision ID */
867 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
868 /* preceded with zeros */
869 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200870 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200871
Michal Vaskoe3880e62018-07-11 16:18:34 +0200872 /* handle yang data templates */
873 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
874 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
875 if (!sparent) {
876 sibling = NULL;
877 goto finish;
878 }
879 }
880
881 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200882 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
883 sibling = NULL;
884 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
885 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
886 break;
887 }
888 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
889 break;
890 }
891 }
892 if (!sibling) {
893 /* fail */
894 goto finish;
895 }
896
897 /* use only input/output children nodes */
898 sparent = sibling;
899 }
900
901 /* find our node with matching hashes */
902 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200903 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
904 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200905 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 +0200906 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200907 break;
908 }
909 }
910
Michal Vaskob7400232018-07-11 15:35:57 +0200911finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200912 *snode = sibling;
913 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200914 if (mod) {
915 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
916 } else {
917 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
918 }
919 return -1;
920 }
921
922 return ret;
923}
924
925static int
926lyb_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 +0200927 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200928{
929 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200930 struct lyd_node *node = NULL, *iter;
931 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200932 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200933
934 assert((parent && !first_sibling) || (!parent && first_sibling));
935
936 /* register a new subtree */
937 ret += (r = lyb_read_start_subtree(data, lybs));
938 LYB_HAVE_READ_GOTO(r, data, error);
939
940 if (!parent) {
941 /* top-level, read module name */
942 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
943 LYB_HAVE_READ_GOTO(r, data, error);
944
Michal Vasko53830662018-07-24 16:09:49 +0200945 if (mod) {
946 /* read hash, find the schema node starting from mod, possibly yang_data_name */
947 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
948 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200949 } else {
Michal Vasko53830662018-07-24 16:09:49 +0200950 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200951
Michal Vaskoe3880e62018-07-11 16:18:34 +0200952 /* read hash, find the schema node starting from parent schema */
953 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
954 }
955 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200956 LYB_HAVE_READ_GOTO(r, data, error);
957
Michal Vasko53830662018-07-24 16:09:49 +0200958 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200959 /* unknown data subtree, skip it whole */
960 do {
961 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +0200962 /* also skip the meta information inside */
963 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +0200964 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200965 goto stop_subtree;
966 }
967
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200968 /*
969 * read the node
970 */
971 node = lyb_new_node(snode);
972 if (!node) {
973 goto error;
974 }
975
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200976 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
977 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200978
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200979 /* read node content */
980 switch (snode->nodetype) {
981 case LYS_CONTAINER:
982 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200983 case LYS_NOTIF:
984 case LYS_RPC:
985 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200986 /* nothing to read */
987 break;
988 case LYS_LEAF:
989 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200990 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
991 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200992 LYB_HAVE_READ_GOTO(r, data, error);
993 break;
994 case LYS_ANYXML:
995 case LYS_ANYDATA:
996 ret += (r = lyb_parse_anydata(node, data, lybs));
997 LYB_HAVE_READ_GOTO(r, data, error);
998 break;
999 default:
1000 goto error;
1001 }
1002
1003 /* insert into data tree, manually */
1004 if (parent) {
1005 if (!parent->child) {
1006 /* only child */
1007 parent->child = node;
1008 } else {
1009 /* last child */
1010 parent->child->prev->next = node;
1011 node->prev = parent->child->prev;
1012 parent->child->prev = node;
1013 }
1014 node->parent = parent;
1015 } else if (*first_sibling) {
1016 /* last sibling */
1017 (*first_sibling)->prev->next = node;
1018 node->prev = (*first_sibling)->prev;
1019 (*first_sibling)->prev = node;
1020 } else {
1021 /* only sibling */
1022 *first_sibling = node;
1023 }
1024
1025 /* read all descendants */
1026 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001027 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001028 LYB_HAVE_READ_GOTO(r, data, error);
1029 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001030
1031 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001032 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001033 LY_TREE_FOR(node->child, iter) {
1034 if (!iter->dflt) {
1035 break;
1036 }
1037 }
1038
1039 if (!iter) {
1040 node->dflt = 1;
1041 }
1042 }
1043
Michal Vaskofe43d042018-07-24 09:43:46 +02001044#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001045 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1046 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001047 lyd_hash(node);
1048 lyd_insert_hash(node);
1049 }
1050#endif
1051
Michal Vasko228431e2018-07-10 15:47:11 +02001052stop_subtree:
1053 /* end the subtree */
1054 lyb_read_stop_subtree(lybs);
1055
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001056 return ret;
1057
1058error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001059 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001060 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001061 *first_sibling = NULL;
1062 }
1063 return -1;
1064}
1065
1066static int
Michal Vasko228431e2018-07-10 15:47:11 +02001067lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1068{
1069 int i, r, ret = 0;
1070
1071 /* read model count */
1072 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1073 LYB_HAVE_READ_RETURN(r, data, -1);
1074
1075 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1076 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1077
1078 /* read modules */
1079 for (i = 0; i < lybs->mod_count; ++i) {
1080 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1081 LYB_HAVE_READ_RETURN(r, data, -1);
1082 }
1083
1084 return ret;
1085}
1086
1087static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001088lyb_parse_header(const char *data, struct lyb_state *lybs)
1089{
1090 int ret = 0;
1091 uint8_t byte = 0;
1092
Michal Vasko228431e2018-07-10 15:47:11 +02001093 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001094 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1095
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001096 return ret;
1097}
1098
1099struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001100lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1101 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001102{
1103 int r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001104 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1105 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001106 struct lyb_state lybs;
1107
1108 if (!ctx || !data) {
1109 LOGARG;
1110 return NULL;
1111 }
1112
1113 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1114 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001115 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1116 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001117 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001118 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001119 lybs.models = NULL;
1120 lybs.mod_count = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001121
1122 unres = calloc(1, sizeof *unres);
1123 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001124
1125 /* read header */
1126 ret += (r = lyb_parse_header(data, &lybs));
1127 LYB_HAVE_READ_GOTO(r, data, finish);
1128
Michal Vasko228431e2018-07-10 15:47:11 +02001129 /* read used models */
1130 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1131 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001132
1133 /* read subtree(s) */
1134 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001135 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1136 if (r < 0) {
1137 lyd_free_withsiblings(node);
1138 node = NULL;
1139 goto finish;
1140 }
1141 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001142 }
1143
1144 /* read the last zero, parsing finished */
1145 ++ret;
1146 r = ret;
1147
Michal Vasko228431e2018-07-10 15:47:11 +02001148 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1149 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1150 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1151 lyd_free_withsiblings(node);
1152 node = NULL;
1153 goto finish;
1154 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001155 }
Michal Vasko228431e2018-07-10 15:47:11 +02001156
1157 /* resolve any unresolved instance-identifiers */
1158 if (unres->count) {
1159 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1160 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1161 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1162 break;
1163 }
1164 LY_TREE_DFS_END(node, next, act_notif);
1165 }
1166 }
1167 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1168 lyd_free_withsiblings(node);
1169 node = NULL;
1170 goto finish;
1171 }
1172 }
1173
1174finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001175 free(lybs.written);
1176 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001177 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001178 free(lybs.models);
1179 if (unres) {
1180 free(unres->node);
1181 free(unres->type);
1182 free(unres);
1183 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001184
1185 if (parsed) {
1186 *parsed = r;
1187 }
1188 return node;
1189}