blob: e2e7baf1403d1ec44639bdbd9b09f9008f1ed0a7 [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
Michal Vasko60b02ff2018-09-25 11:01:18 +0200245 if (!*mod) {
246 LOGERR(ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
247 mod_name, rev ? "@" : "", rev ? mod_rev : "");
248 goto error;
249 } else if (!(*mod)->implemented) {
250 LOGERR(ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
251 mod_name, rev ? "@" : "", rev ? mod_rev : "");
252 goto error;
253 }
254
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200255 free(mod_name);
256 return ret;
257
258error:
259 free(mod_name);
260 return -1;
261}
262
263static struct lyd_node *
264lyb_new_node(const struct lys_node *schema)
265{
266 struct lyd_node *node;
267
268 switch (schema->nodetype) {
269 case LYS_CONTAINER:
270 case LYS_LIST:
271 case LYS_NOTIF:
272 case LYS_RPC:
273 case LYS_ACTION:
274 node = calloc(sizeof(struct lyd_node), 1);
275 break;
276 case LYS_LEAF:
277 case LYS_LEAFLIST:
278 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200279
280 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
281 node->validity |= LYD_VAL_LEAFREF;
282 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200283 break;
284 case LYS_ANYDATA:
285 case LYS_ANYXML:
286 node = calloc(sizeof(struct lyd_node_anydata), 1);
287 break;
288 default:
289 return NULL;
290 }
291 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
292
293 /* fill basic info */
294 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200295 if (resolve_applies_when(schema, 0, NULL)) {
296 node->when_status = LYD_WHEN;
297 }
298 node->prev = node;
299
300 return node;
301}
302
303static int
304lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
305{
306 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200307 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200308 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
309
310 /* read value type */
311 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
312 LYB_HAVE_READ_RETURN(r, data, -1);
313
314 /* read anydata content */
315 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko33901702018-08-17 10:29:09 +0200316 /* invalid situation */
317 LOGINT(node->schema->module->ctx);
318 return -1;
Michal Vaskodcaf7222018-08-08 16:27:00 +0200319 } else if (any->value_type == LYD_ANYDATA_LYB) {
320 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
321 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200322 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200323 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200324 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200325
326 /* add to dictionary */
327 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200328 }
329
330 return ret;
331}
332
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200333/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200334static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200335lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
336 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200337{
Michal Vasko228431e2018-07-10 15:47:11 +0200338 int r, ret;
339 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200340 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200341 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200342 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200343
Michal Vasko42132c52018-07-24 16:09:21 +0200344 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200345 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200346 ret = lyb_read_string(data, &str, 0, lybs);
347 if (ret > -1) {
348 *value_str = lydict_insert_zc(ctx, str);
349 }
350 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200351 }
352
Michal Vasko6fb57892018-08-23 10:21:21 +0200353 /* find the correct structure, go through leafrefs and typedefs */
354 switch (value_type) {
355 case LY_TYPE_ENUM:
356 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
357 for (; !type->info.enums.count; type = &type->der->type);
358 break;
359 case LY_TYPE_BITS:
360 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
361 for (; !type->info.bits.count; type = &type->der->type);
362 break;
363 default:
364 break;
365 }
366
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200367 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200368 case LY_TYPE_INST:
369 case LY_TYPE_IDENT:
370 case LY_TYPE_UNION:
371 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200372 ret = lyb_read_string(data, &str, 0, lybs);
373 if (ret > -1) {
374 *value_str = lydict_insert_zc(ctx, str);
375 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200376 break;
377 case LY_TYPE_BINARY:
378 case LY_TYPE_STRING:
379 case LY_TYPE_UNKNOWN:
380 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200381 ret = lyb_read_string(data, &str, 0, lybs);
382 if (ret > -1) {
383 value->string = lydict_insert_zc(ctx, str);
384 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200385 break;
386 case LY_TYPE_BITS:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200387 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
388 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200389
390 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200391 ret = 0;
392 for (i = 0; i < type->info.bits.count; ++i) {
393 if (i % 8 == 0) {
394 /* read another byte */
Andrew Langefeld1f3e4f52018-08-24 22:30:37 -0500395 ret += (r = lyb_read(data + ret, &byte, sizeof byte, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +0200396 if (r < 0) {
397 return -1;
398 }
399 }
400
401 if (byte & (0x01 << (i % 8))) {
402 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200403 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200404 }
405 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200406 break;
407 case LY_TYPE_BOOL:
408 /* read byte */
409 ret = lyb_read(data, &byte, sizeof byte, lybs);
410 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200411 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200412 }
413 break;
414 case LY_TYPE_EMPTY:
415 /* nothing to read */
416 ret = 0;
417 break;
418 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200419 num = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200420 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
Michal Vaskob7400232018-07-11 15:35:57 +0200421 if (ret > 0) {
422 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200423 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200424 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200425 break;
426 case LY_TYPE_INT8:
427 case LY_TYPE_UINT8:
Michal Vasko1440eb52018-08-14 13:42:14 +0200428 ret = lyb_read_number((uint64_t *)&value->uint8, 1, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200429 break;
430 case LY_TYPE_INT16:
431 case LY_TYPE_UINT16:
Michal Vasko1440eb52018-08-14 13:42:14 +0200432 ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200433 break;
434 case LY_TYPE_INT32:
435 case LY_TYPE_UINT32:
Michal Vasko1440eb52018-08-14 13:42:14 +0200436 ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200437 break;
438 case LY_TYPE_DEC64:
439 case LY_TYPE_INT64:
440 case LY_TYPE_UINT64:
Michal Vasko1440eb52018-08-14 13:42:14 +0200441 ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200442 break;
443 default:
444 return -1;
445 }
446
447 return ret;
448}
449
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200450/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200451static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200452lyb_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 +0200453{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200454 struct ly_ctx *ctx;
455 struct lys_module *mod;
Michal Vasko6fb57892018-08-23 10:21:21 +0200456 struct lys_type *rtype;
Michal Vasko228431e2018-07-10 15:47:11 +0200457 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200458 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200459 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200460 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200461 const char **value_str;
462 LY_DATA_TYPE value_type;
463 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200464
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200465 if (leaf) {
466 ctx = leaf->schema->module->ctx;
467 mod = lys_node_module(leaf->schema);
468
469 value = &leaf->value;
470 value_str = &leaf->value_str;
471 value_flags = &leaf->value_flags;
472 value_type = leaf->value_type;
473 } else {
474 ctx = attr->annotation->module->ctx;
475 mod = lys_main_module(attr->annotation->module);
476
477 value = &attr->value;
478 value_str = &attr->value_str;
479 value_flags = &attr->value_flags;
480 value_type = attr->value_type;
481 }
482
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200483 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200484 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200485 *value_flags &= ~LY_VALUE_USER;
486 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200487 return -1;
488 }
489
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200490 if (!(*value_flags & LY_VALUE_USER)) {
491 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 +0200492 }
493 return 0;
494 }
495
Michal Vaskob7400232018-07-11 15:35:57 +0200496 /* we are parsing leafref/ptr union stored as the target type,
497 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200498 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
499 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200500 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200501 /* we already have a string */
502 goto parse_reference;
503 }
504 }
505
Michal Vasko6fb57892018-08-23 10:21:21 +0200506 /* find the correct structure, go through leafrefs and typedefs */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200507 switch (value_type) {
Michal Vasko58608522018-08-22 13:04:37 +0200508 case LY_TYPE_BITS:
Michal Vasko6fb57892018-08-23 10:21:21 +0200509 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &rtype->info.lref.target->type);
510 for (; !rtype->info.bits.count; rtype = &rtype->der->type);
511 break;
Michal Vasko58608522018-08-22 13:04:37 +0200512 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200513 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &type->info.lref.target->type);
Michal Vasko58608522018-08-22 13:04:37 +0200514 break;
515 default:
516 break;
517 }
518
519 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200520 case LY_TYPE_IDENT:
521 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200522 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
523 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200524 return -1;
525 }
526 break;
Michal Vasko56670362018-08-08 16:27:21 +0200527 case LY_TYPE_INST:
528 /* unresolved instance-identifier, keep value NULL */
529 value->instance = NULL;
530 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200531 case LY_TYPE_BINARY:
532 case LY_TYPE_STRING:
533 case LY_TYPE_UNKNOWN:
534 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200535 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200536 break;
537 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200538 /* print the set bits */
539 str = malloc(1);
540 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
541 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200542 str_len = 0;
Michal Vasko6fb57892018-08-23 10:21:21 +0200543 for (i = 0; i < rtype->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200544 if (value->bit[i]) {
545 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200546 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
547
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200548 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200549 }
550 }
551
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200552 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200553 break;
554 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200555 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200556 break;
557 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200558 *value_str = lydict_insert(ctx, "", 0);
559 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200560 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200561 if (attr) {
562 /* we do not support union type attribute */
563 LOGINT(ctx);
564 return -1;
565 }
566
567 if (resolve_union(leaf, type, 1, 2, NULL)) {
568 return -1;
569 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200570 break;
571 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200572 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200573 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200574 break;
575 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200576 sprintf(num_str, "%d", value->int8);
577 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200578 break;
579 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200580 sprintf(num_str, "%u", value->uint8);
581 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200582 break;
583 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200584 sprintf(num_str, "%d", value->int16);
585 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200586 break;
587 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200588 sprintf(num_str, "%u", value->uint16);
589 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200590 break;
591 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200592 sprintf(num_str, "%d", value->int32);
593 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200594 break;
595 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200596 sprintf(num_str, "%u", value->uint32);
597 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200598 break;
599 case LY_TYPE_INT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200600 sprintf(num_str, "%"PRId64, value->int64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200601 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200602 break;
603 case LY_TYPE_UINT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200604 sprintf(num_str, "%"PRIu64, value->uint64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200605 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200606 break;
607 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200608 frac = value->dec64 % rtype->info.dec64.div;
609 dig = rtype->info.dec64.dig;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200610 /* remove trailing zeros */
611 while ((dig > 1) && !(frac % 10)) {
612 frac /= 10;
613 --dig;
614 }
615
Michal Vasko6fb57892018-08-23 10:21:21 +0200616 sprintf(num_str, "%"PRId64".%.*"PRId64, value->dec64 / (int64_t)rtype->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200617 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200618 break;
619 default:
620 return -1;
621 }
622
Michal Vasko56670362018-08-08 16:27:21 +0200623 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
624 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskob7400232018-07-11 15:35:57 +0200625parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200626 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200627
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200628 if (attr) {
629 /* we do not support reference types of attributes */
630 LOGINT(ctx);
631 return -1;
632 }
633
634 if (type->base == LY_TYPE_INST) {
635 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
636 return -1;
637 }
638 } else if (type->base == LY_TYPE_LEAFREF) {
639 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200640 return -1;
641 }
642 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200643 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200644 return -1;
645 }
646 }
647 }
648
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200649 return 0;
650}
651
652static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200653lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
654 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200655{
656 int r, ret = 0;
657 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200658
659 struct ly_ctx *ctx;
660 const char **value_str;
661 lyd_val *value;
662 LY_DATA_TYPE *value_type;
663 uint8_t *value_flags;
664
665 assert((leaf || attr) && (!leaf || !attr));
666
667 if (leaf) {
668 ctx = leaf->schema->module->ctx;
669 value_str = &leaf->value_str;
670 value = &leaf->value;
671 value_type = &leaf->value_type;
672 value_flags = &leaf->value_flags;
673 } else {
674 ctx = attr->annotation->module->ctx;
675 value_str = &attr->value_str;
676 value = &attr->value;
677 value_type = &attr->value_type;
678 value_flags = &attr->value_flags;
679 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200680
681 /* read value type and flags on the first byte */
682 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
683 LYB_HAVE_READ_RETURN(r, data, -1);
684
685 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200686 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200687 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200688 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200689 leaf->dflt = 1;
690 }
691 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200692 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200693 }
694 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200695 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200696 }
697
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200698 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200699 LYB_HAVE_READ_RETURN(r, data, -1);
700
Michal Vasko27e5e682018-07-23 14:22:57 +0200701 /* union is handled specially */
702 if (type->base == LY_TYPE_UNION) {
703 assert(*value_type == LY_TYPE_STRING);
704
705 *value_str = value->string;
706 value->string = NULL;
707 *value_type = LY_TYPE_UNION;
708 }
709
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200710 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200711 LYB_HAVE_READ_RETURN(r, data, -1);
712
713 return ret;
714}
715
716static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200717lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
718 struct lyb_state *lybs)
719{
720 int r, ret = 0, pos, i, j, k;
721 const struct lys_submodule *submod = NULL;
722 char *attr_name = NULL;
723
724 /* attr name */
725 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
726 LYB_HAVE_READ_RETURN(r, data, -1);
727
728 /* search module */
729 pos = -1;
730 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
731 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
732 if (j == -1) {
733 break;
734 }
735 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
736 pos = i + j;
737 break;
738 }
739 }
740
741 /* try submodules */
742 if (pos == -1) {
743 for (k = 0; k < mod->inc_size; ++k) {
744 submod = mod->inc[k].submodule;
745 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
746 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
747 if (j == -1) {
748 break;
749 }
750 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
751 pos = i + j;
752 break;
753 }
754 }
755 }
756 }
757
758 if (pos == -1) {
759 *ext = NULL;
760 } else {
761 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
762 }
763
764 if (!*ext && (options & LYD_OPT_STRICT)) {
765 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
766 free(attr_name);
767 return -1;
768 }
769
770 free(attr_name);
771 return ret;
772}
773
774static int
775lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
776{
777 int r, ret = 0;
778 uint8_t i, count = 0;
779 const struct lys_module *mod;
Michal Vasko3cb7d172018-08-17 10:54:40 +0200780 struct lys_type **type;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200781 struct lyd_attr *attr = NULL;
782 struct lys_ext_instance_complex *ext;
783 struct ly_ctx *ctx = node->schema->module->ctx;
784
785 /* read number of attributes stored */
786 ret += (r = lyb_read(data, &count, 1, lybs));
787 LYB_HAVE_READ_GOTO(r, data, error);
788
789 /* read attributes */
790 for (i = 0; i < count; ++i) {
791 ret += (r = lyb_read_start_subtree(data, lybs));
792 LYB_HAVE_READ_GOTO(r, data, error);
793
794 /* find model */
795 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
796 LYB_HAVE_READ_GOTO(r, data, error);
797
Michal Vasko53830662018-07-24 16:09:49 +0200798 if (mod) {
799 /* annotation name */
800 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
801 LYB_HAVE_READ_GOTO(r, data, error);
802 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200803
Michal Vasko53830662018-07-24 16:09:49 +0200804 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200805 /* unknown attribute, skip it */
806 do {
807 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200808 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200809 } while (lybs->written[lybs->used - 1]);
810 goto stop_subtree;
811 }
812
813 /* allocate new attribute */
814 if (!attr) {
815 assert(!node->attr);
816
817 attr = calloc(1, sizeof *attr);
818 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
819
820 node->attr = attr;
821 } else {
822 attr->next = calloc(1, sizeof *attr);
823 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
824
825 attr = attr->next;
826 }
827
828 /* attribute annotation */
829 attr->annotation = ext;
830
831 /* attribute name */
832 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
833
834 /* get the type */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200835 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
836 if (!type || !(*type)) {
837 goto error;
838 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200839
840 /* attribute value */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200841 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200842 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200843
844stop_subtree:
845 lyb_read_stop_subtree(lybs);
846 }
847
848 return ret;
849
850error:
851 lyd_free_attr(ctx, node, node->attr, 1);
852 return -1;
853}
854
855static int
Michal Vaskob7400232018-07-11 15:35:57 +0200856lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200857{
858 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200859 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200860
Michal Vaskob7400232018-07-11 15:35:57 +0200861 /* compare all the hashes starting from collision ID 0 */
862 for (i = 0; i < hash_count; ++i) {
863 sibling_hash = lyb_hash(sibling, i);
864 if (sibling_hash != hash[i]) {
865 return 0;
866 }
867 }
Michal Vasko228431e2018-07-10 15:47:11 +0200868
Michal Vaskob7400232018-07-11 15:35:57 +0200869 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200870}
871
872static int
873lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
874 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200875{
876 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200877 uint8_t i, j;
878 struct lys_node *sibling;
879 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200880 struct ly_ctx *ctx;
881
882 assert((sparent || mod) && (!sparent || !mod));
883 ctx = (sparent ? sparent->module->ctx : mod->ctx);
884
Michal Vaskob7400232018-07-11 15:35:57 +0200885 /* read the first hash */
886 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200887 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200888
889 /* based on the first hash read all the other ones, if any */
890 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
891
892 /* move the first hash on its accurate position */
893 hash[i] = hash[0];
894
895 /* read the rest of hashes */
896 for (j = i; j; --j) {
897 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
898 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200899
Michal Vasko365849c2018-08-07 11:31:30 +0200900 /* correct collision ID */
901 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
902 /* preceded with zeros */
903 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200904 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200905
Michal Vaskoe3880e62018-07-11 16:18:34 +0200906 /* handle yang data templates */
907 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
908 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
909 if (!sparent) {
910 sibling = NULL;
911 goto finish;
912 }
913 }
914
915 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200916 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
917 sibling = NULL;
918 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
919 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
920 break;
921 }
922 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
923 break;
924 }
925 }
926 if (!sibling) {
927 /* fail */
928 goto finish;
929 }
930
931 /* use only input/output children nodes */
932 sparent = sibling;
933 }
934
935 /* find our node with matching hashes */
936 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200937 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
938 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200939 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 +0200940 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200941 break;
942 }
943 }
944
Michal Vaskob7400232018-07-11 15:35:57 +0200945finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200946 *snode = sibling;
947 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200948 if (mod) {
949 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
950 } else {
951 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
952 }
953 return -1;
954 }
955
956 return ret;
957}
958
959static int
960lyb_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 +0200961 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200962{
963 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200964 struct lyd_node *node = NULL, *iter;
965 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200966 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200967
968 assert((parent && !first_sibling) || (!parent && first_sibling));
969
970 /* register a new subtree */
971 ret += (r = lyb_read_start_subtree(data, lybs));
972 LYB_HAVE_READ_GOTO(r, data, error);
973
974 if (!parent) {
975 /* top-level, read module name */
976 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
977 LYB_HAVE_READ_GOTO(r, data, error);
978
Michal Vasko53830662018-07-24 16:09:49 +0200979 if (mod) {
980 /* read hash, find the schema node starting from mod, possibly yang_data_name */
981 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
982 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200983 } else {
Michal Vasko53830662018-07-24 16:09:49 +0200984 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200985
Michal Vaskoe3880e62018-07-11 16:18:34 +0200986 /* read hash, find the schema node starting from parent schema */
987 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
988 }
989 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200990 LYB_HAVE_READ_GOTO(r, data, error);
991
Michal Vasko53830662018-07-24 16:09:49 +0200992 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200993 /* unknown data subtree, skip it whole */
994 do {
995 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +0200996 /* also skip the meta information inside */
997 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +0200998 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200999 goto stop_subtree;
1000 }
1001
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001002 /*
1003 * read the node
1004 */
1005 node = lyb_new_node(snode);
1006 if (!node) {
1007 goto error;
1008 }
1009
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001010 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1011 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001012
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001013 /* read node content */
1014 switch (snode->nodetype) {
1015 case LYS_CONTAINER:
1016 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +02001017 case LYS_NOTIF:
1018 case LYS_RPC:
1019 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001020 /* nothing to read */
1021 break;
1022 case LYS_LEAF:
1023 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001024 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1025 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001026 LYB_HAVE_READ_GOTO(r, data, error);
1027 break;
1028 case LYS_ANYXML:
1029 case LYS_ANYDATA:
1030 ret += (r = lyb_parse_anydata(node, data, lybs));
1031 LYB_HAVE_READ_GOTO(r, data, error);
1032 break;
1033 default:
1034 goto error;
1035 }
1036
1037 /* insert into data tree, manually */
1038 if (parent) {
1039 if (!parent->child) {
1040 /* only child */
1041 parent->child = node;
1042 } else {
1043 /* last child */
1044 parent->child->prev->next = node;
1045 node->prev = parent->child->prev;
1046 parent->child->prev = node;
1047 }
1048 node->parent = parent;
1049 } else if (*first_sibling) {
1050 /* last sibling */
1051 (*first_sibling)->prev->next = node;
1052 node->prev = (*first_sibling)->prev;
1053 (*first_sibling)->prev = node;
1054 } else {
1055 /* only sibling */
1056 *first_sibling = node;
1057 }
1058
1059 /* read all descendants */
1060 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001061 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001062 LYB_HAVE_READ_GOTO(r, data, error);
1063 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001064
1065 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001066 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001067 LY_TREE_FOR(node->child, iter) {
1068 if (!iter->dflt) {
1069 break;
1070 }
1071 }
1072
1073 if (!iter) {
1074 node->dflt = 1;
1075 }
1076 }
1077
Michal Vaskofe43d042018-07-24 09:43:46 +02001078#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001079 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1080 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001081 lyd_hash(node);
1082 lyd_insert_hash(node);
1083 }
1084#endif
1085
Michal Vasko228431e2018-07-10 15:47:11 +02001086stop_subtree:
1087 /* end the subtree */
1088 lyb_read_stop_subtree(lybs);
1089
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001090 return ret;
1091
1092error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001093 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001094 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001095 *first_sibling = NULL;
1096 }
1097 return -1;
1098}
1099
1100static int
Michal Vasko228431e2018-07-10 15:47:11 +02001101lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1102{
1103 int i, r, ret = 0;
1104
1105 /* read model count */
1106 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1107 LYB_HAVE_READ_RETURN(r, data, -1);
1108
1109 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1110 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1111
1112 /* read modules */
1113 for (i = 0; i < lybs->mod_count; ++i) {
1114 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1115 LYB_HAVE_READ_RETURN(r, data, -1);
1116 }
1117
1118 return ret;
1119}
1120
1121static int
Michal Vasko5c445042018-08-28 16:27:45 +02001122lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1123{
1124 int ret = 0;
1125 uint32_t magic_number = 0;
1126
1127 ret += lyb_read(data, (uint8_t *)&magic_number, 3, lybs);
1128
1129 if (memcmp(&magic_number, "lyb", 3)) {
1130 LOGERR(NULL, LY_EINVAL, "Invalid magic number \"0x%02x%02x%02x\".",
1131 ((uint8_t *)&magic_number)[0], ((uint8_t *)&magic_number)[1], ((uint8_t *)&magic_number)[2]);
1132 return -1;
1133 }
1134
1135 return ret;
1136}
1137
1138static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001139lyb_parse_header(const char *data, struct lyb_state *lybs)
1140{
1141 int ret = 0;
1142 uint8_t byte = 0;
1143
Michal Vasko228431e2018-07-10 15:47:11 +02001144 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001145 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1146
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001147 return ret;
1148}
1149
1150struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001151lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1152 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001153{
Michal Vaskobeeb1bf2018-08-17 10:29:29 +02001154 int r = 0, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001155 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1156 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001157 struct lyb_state lybs;
1158
1159 if (!ctx || !data) {
1160 LOGARG;
1161 return NULL;
1162 }
1163
1164 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1165 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001166 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1167 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001168 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001169 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001170 lybs.models = NULL;
1171 lybs.mod_count = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001172
1173 unres = calloc(1, sizeof *unres);
1174 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001175
Michal Vasko5c445042018-08-28 16:27:45 +02001176 /* read magic number */
1177 ret += (r = lyb_parse_magic_number(data, &lybs));
1178 LYB_HAVE_READ_GOTO(r, data, finish);
1179
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001180 /* read header */
1181 ret += (r = lyb_parse_header(data, &lybs));
1182 LYB_HAVE_READ_GOTO(r, data, finish);
1183
Michal Vasko228431e2018-07-10 15:47:11 +02001184 /* read used models */
1185 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1186 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001187
1188 /* read subtree(s) */
1189 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001190 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1191 if (r < 0) {
1192 lyd_free_withsiblings(node);
1193 node = NULL;
1194 goto finish;
1195 }
1196 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001197 }
1198
1199 /* read the last zero, parsing finished */
1200 ++ret;
1201 r = ret;
1202
Michal Vasko228431e2018-07-10 15:47:11 +02001203 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1204 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1205 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1206 lyd_free_withsiblings(node);
1207 node = NULL;
1208 goto finish;
1209 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001210 }
Michal Vasko228431e2018-07-10 15:47:11 +02001211
1212 /* resolve any unresolved instance-identifiers */
1213 if (unres->count) {
1214 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1215 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1216 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1217 break;
1218 }
1219 LY_TREE_DFS_END(node, next, act_notif);
1220 }
1221 }
1222 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1223 lyd_free_withsiblings(node);
1224 node = NULL;
1225 goto finish;
1226 }
1227 }
1228
1229finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001230 free(lybs.written);
1231 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001232 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001233 free(lybs.models);
1234 if (unres) {
1235 free(unres->node);
1236 free(unres->type);
1237 free(unres);
1238 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001239
1240 if (parsed) {
1241 *parsed = r;
1242 }
1243 return node;
1244}