Coverage Report

Created: 2022-11-08 06:06

/src/libyang/src/validation.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file validation.c
3
 * @author Michal Vasko <mvasko@cesnet.cz>
4
 * @brief Validation
5
 *
6
 * Copyright (c) 2019 - 2022 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
#define _GNU_SOURCE /* asprintf, strdup */
15
16
#include "validation.h"
17
18
#include <assert.h>
19
#include <limits.h>
20
#include <stdint.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
25
#include "common.h"
26
#include "compat.h"
27
#include "diff.h"
28
#include "hash_table.h"
29
#include "log.h"
30
#include "parser_data.h"
31
#include "parser_internal.h"
32
#include "plugins_exts.h"
33
#include "plugins_exts/metadata.h"
34
#include "plugins_types.h"
35
#include "set.h"
36
#include "tree.h"
37
#include "tree_data.h"
38
#include "tree_data_internal.h"
39
#include "tree_schema.h"
40
#include "tree_schema_internal.h"
41
#include "xpath.h"
42
43
LY_ERR
44
lyd_val_diff_add(const struct lyd_node *node, enum lyd_diff_op op, struct lyd_node **diff)
45
0
{
46
0
    LY_ERR ret = LY_SUCCESS;
47
0
    struct lyd_node *new_diff = NULL;
48
0
    const struct lyd_node *prev_inst;
49
0
    char *key = NULL, *value = NULL, *position = NULL;
50
0
    size_t buflen = 0, bufused = 0;
51
0
    uint32_t pos;
52
53
0
    assert((op == LYD_DIFF_OP_DELETE) || (op == LYD_DIFF_OP_CREATE));
54
55
0
    if ((op == LYD_DIFF_OP_CREATE) && lysc_is_userordered(node->schema)) {
56
0
        if (lysc_is_dup_inst_list(node->schema)) {
57
0
            pos = lyd_list_pos(node);
58
59
            /* generate position meta */
60
0
            if (pos > 1) {
61
0
                if (asprintf(&position, "%" PRIu32, pos - 1) == -1) {
62
0
                    LOGMEM(LYD_CTX(node));
63
0
                    ret = LY_EMEM;
64
0
                    goto cleanup;
65
0
                }
66
0
            } else {
67
0
                position = strdup("");
68
0
                LY_CHECK_ERR_GOTO(!position, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
69
0
            }
70
0
        } else {
71
0
            if (node->prev->next && (node->prev->schema == node->schema)) {
72
0
                prev_inst = node->prev;
73
0
            } else {
74
                /* first instance */
75
0
                prev_inst = NULL;
76
0
            }
77
78
0
            if (node->schema->nodetype == LYS_LIST) {
79
                /* generate key meta */
80
0
                if (prev_inst) {
81
0
                    LY_CHECK_GOTO(ret = lyd_path_list_predicate(prev_inst, &key, &buflen, &bufused, 0), cleanup);
82
0
                } else {
83
0
                    key = strdup("");
84
0
                    LY_CHECK_ERR_GOTO(!key, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
85
0
                }
86
0
            } else {
87
                /* generate value meta */
88
0
                if (prev_inst) {
89
0
                    value = strdup(lyd_get_value(prev_inst));
90
0
                    LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
91
0
                } else {
92
0
                    value = strdup("");
93
0
                    LY_CHECK_ERR_GOTO(!value, LOGMEM(LYD_CTX(node)); ret = LY_EMEM, cleanup);
94
0
                }
95
0
            }
96
0
        }
97
0
    }
98
99
    /* create new diff tree */
100
0
    LY_CHECK_GOTO(ret = lyd_diff_add(node, op, NULL, NULL, key, value, position, NULL, NULL, &new_diff), cleanup);
101
102
    /* merge into existing diff */
103
0
    ret = lyd_diff_merge_all(diff, new_diff, 0);
104
105
0
cleanup:
106
0
    lyd_free_tree(new_diff);
107
0
    free(key);
108
0
    free(value);
109
0
    free(position);
110
0
    return ret;
111
0
}
112
113
/**
114
 * @brief Evaluate all relevant "when" conditions of a node.
115
 *
116
 * @param[in] tree Data tree.
117
 * @param[in] node Node whose relevant when conditions will be evaluated.
118
 * @param[in] schema Schema node of @p node. It may not be possible to use directly if @p node is opaque.
119
 * @param[in] xpath_options Additional XPath options to use.
120
 * @param[out] disabled First when that evaluated false, if any.
121
 * @return LY_SUCCESS on success.
122
 * @return LY_EINCOMPLETE if a referenced node does not have its when evaluated.
123
 * @return LY_ERR value on error.
124
 */
125
static LY_ERR
126
lyd_validate_node_when(const struct lyd_node *tree, const struct lyd_node *node, const struct lysc_node *schema,
127
        uint32_t xpath_options, const struct lysc_when **disabled)
128
0
{
129
0
    LY_ERR ret;
130
0
    const struct lyd_node *ctx_node;
131
0
    struct lyxp_set xp_set;
132
0
    LY_ARRAY_COUNT_TYPE u;
133
134
0
    assert(!node->schema || (node->schema == schema));
135
136
0
    *disabled = NULL;
137
138
0
    do {
139
0
        const struct lysc_when *when;
140
0
        struct lysc_when **when_list = lysc_node_when(schema);
141
142
0
        LY_ARRAY_FOR(when_list, u) {
143
0
            when = when_list[u];
144
145
            /* get context node */
146
0
            if (when->context == schema) {
147
0
                ctx_node = node;
148
0
            } else {
149
0
                assert((!when->context && !node->parent) || (when->context == node->parent->schema));
150
0
                ctx_node = lyd_parent(node);
151
0
            }
152
153
            /* evaluate when */
154
0
            memset(&xp_set, 0, sizeof xp_set);
155
0
            ret = lyxp_eval(LYD_CTX(node), when->cond, schema->module, LY_VALUE_SCHEMA_RESOLVED, when->prefixes,
156
0
                    ctx_node, ctx_node, tree, NULL, &xp_set, LYXP_SCHEMA | xpath_options);
157
0
            lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
158
159
            /* return error or LY_EINCOMPLETE for dependant unresolved when */
160
0
            LY_CHECK_RET(ret);
161
162
0
            if (!xp_set.val.bln) {
163
                /* false when */
164
0
                *disabled = when;
165
0
                return LY_SUCCESS;
166
0
            }
167
0
        }
168
169
0
        schema = schema->parent;
170
0
    } while (schema && (schema->nodetype & (LYS_CASE | LYS_CHOICE)));
171
172
0
    return LY_SUCCESS;
173
0
}
174
175
/**
176
 * @brief Evaluate when conditions of collected unres nodes.
177
 *
178
 * @param[in,out] tree Data tree, is updated if some nodes are autodeleted.
179
 * @param[in] mod Module of the @p tree to take into consideration when deleting @p tree and moving it.
180
 * If set, it is expected @p tree should point to the first node of @p mod. Otherwise it will simply be
181
 * the first top-level sibling.
182
 * @param[in] node_when Set with nodes with "when" conditions.
183
 * @param[in] xpath_options Additional XPath options to use.
184
 * @param[in,out] node_types Set with nodes with unresolved types, remove any with false "when" parents.
185
 * @param[in,out] diff Validation diff.
186
 * @return LY_SUCCESS on success.
187
 * @return LY_ERR value on error.
188
 */
189
static LY_ERR
190
lyd_validate_unres_when(struct lyd_node **tree, const struct lys_module *mod, struct ly_set *node_when,
191
        uint32_t xpath_options, struct ly_set *node_types, struct lyd_node **diff)
192
0
{
193
0
    LY_ERR rc, r;
194
0
    uint32_t i, idx;
195
0
    const struct lysc_when *disabled;
196
0
    struct lyd_node *node = NULL, *elem;
197
198
0
    if (!node_when->count) {
199
0
        return LY_SUCCESS;
200
0
    }
201
202
0
    i = node_when->count;
203
0
    do {
204
0
        --i;
205
0
        node = node_when->dnodes[i];
206
0
        LOG_LOCSET(node->schema, node, NULL, NULL);
207
208
        /* evaluate all when expressions that affect this node's existence */
209
0
        r = lyd_validate_node_when(*tree, node, node->schema, xpath_options, &disabled);
210
0
        if (!r) {
211
0
            if (disabled) {
212
                /* when false */
213
0
                if (node->flags & LYD_WHEN_TRUE) {
214
                    /* autodelete */
215
0
                    lyd_del_move_root(tree, node, mod);
216
0
                    if (diff) {
217
                        /* add into diff */
218
0
                        LY_CHECK_GOTO(rc = lyd_val_diff_add(node, LYD_DIFF_OP_DELETE, diff), error);
219
0
                    }
220
221
                    /* remove from node types set, if present */
222
0
                    if (node_types && node_types->count) {
223
0
                        LYD_TREE_DFS_BEGIN(node, elem) {
224
                            /* only term nodes with a validation callback can be in node_types */
225
0
                            if ((elem->schema->nodetype & LYD_NODE_TERM) &&
226
0
                                    ((struct lysc_node_leaf *)elem->schema)->type->plugin->validate &&
227
0
                                    ly_set_contains(node_types, elem, &idx)) {
228
0
                                LY_CHECK_GOTO(rc = ly_set_rm_index(node_types, idx, NULL), error);
229
0
                            }
230
0
                            LYD_TREE_DFS_END(node, elem);
231
0
                        }
232
0
                    }
233
234
                    /* free */
235
0
                    lyd_free_tree(node);
236
0
                } else {
237
                    /* invalid data */
238
0
                    LOGVAL(LYD_CTX(node), LY_VCODE_NOWHEN, disabled->cond->expr);
239
0
                    rc = LY_EVALID;
240
0
                    goto error;
241
0
                }
242
0
            } else {
243
                /* when true */
244
0
                node->flags |= LYD_WHEN_TRUE;
245
0
            }
246
247
            /* remove this node from the set keeping the order, its when was resolved */
248
0
            ly_set_rm_index_ordered(node_when, i, NULL);
249
0
        } else if (r != LY_EINCOMPLETE) {
250
            /* error */
251
0
            rc = r;
252
0
            goto error;
253
0
        }
254
255
0
        LOG_LOCBACK(1, 1, 0, 0);
256
0
    } while (i);
257
258
0
    return LY_SUCCESS;
259
260
0
error:
261
0
    LOG_LOCBACK(1, 1, 0, 0);
262
0
    return rc;
263
0
}
264
265
LY_ERR
266
lyd_validate_unres(struct lyd_node **tree, const struct lys_module *mod, enum lyd_type data_type, struct ly_set *node_when,
267
        uint32_t when_xp_opts, struct ly_set *node_types, struct ly_set *meta_types, struct ly_set *ext_node,
268
        struct ly_set *ext_val, uint32_t val_opts, struct lyd_node **diff)
269
0
{
270
0
    LY_ERR ret = LY_SUCCESS;
271
0
    uint32_t i;
272
273
0
    if (ext_val && ext_val->count) {
274
        /* first validate parsed extension data */
275
0
        i = ext_val->count;
276
0
        do {
277
0
            --i;
278
279
0
            struct lyd_ctx_ext_val *ext_v = ext_val->objs[i];
280
281
            /* validate extension data */
282
0
            ret = ext_v->ext->def->plugin->validate(ext_v->ext, ext_v->sibling, *tree, data_type, val_opts, diff);
283
0
            LY_CHECK_RET(ret);
284
285
            /* remove this item from the set */
286
0
            ly_set_rm_index(ext_val, i, free);
287
0
        } while (i);
288
0
    }
289
290
0
    if (ext_node && ext_node->count) {
291
        /* validate data nodes with extension instances */
292
0
        i = ext_node->count;
293
0
        do {
294
0
            --i;
295
296
0
            struct lyd_ctx_ext_node *ext_n = ext_node->objs[i];
297
298
            /* validate the node */
299
0
            ret = ext_n->ext->def->plugin->node(ext_n->ext, ext_n->node, val_opts);
300
0
            LY_CHECK_RET(ret);
301
302
            /* remove this item from the set */
303
0
            ly_set_rm_index(ext_node, i, free);
304
0
        } while (i);
305
0
    }
306
307
0
    if (node_when) {
308
        /* evaluate all when conditions */
309
0
        uint32_t prev_count;
310
311
0
        do {
312
0
            prev_count = node_when->count;
313
0
            LY_CHECK_RET(lyd_validate_unres_when(tree, mod, node_when, when_xp_opts, node_types, diff));
314
            /* there must have been some when conditions resolved */
315
0
        } while (prev_count > node_when->count);
316
317
        /* there could have been no cyclic when dependencies, checked during compilation */
318
0
        assert(!node_when->count);
319
0
    }
320
321
0
    if (node_types && node_types->count) {
322
        /* finish incompletely validated terminal values (traverse from the end for efficient set removal) */
323
0
        i = node_types->count;
324
0
        do {
325
0
            --i;
326
327
0
            struct lyd_node_term *node = node_types->objs[i];
328
0
            struct lysc_type *type = ((struct lysc_node_leaf *)node->schema)->type;
329
330
            /* resolve the value of the node */
331
0
            LOG_LOCSET(NULL, &node->node, NULL, NULL);
332
0
            ret = lyd_value_validate_incomplete(LYD_CTX(node), type, &node->value, &node->node, *tree);
333
0
            LOG_LOCBACK(0, 1, 0, 0);
334
0
            LY_CHECK_RET(ret);
335
336
            /* remove this node from the set */
337
0
            ly_set_rm_index(node_types, i, NULL);
338
0
        } while (i);
339
0
    }
340
341
0
    if (meta_types && meta_types->count) {
342
        /* ... and metadata values */
343
0
        i = meta_types->count;
344
0
        do {
345
0
            --i;
346
347
0
            struct lyd_meta *meta = meta_types->objs[i];
348
0
            struct lysc_type *type = *(struct lysc_type **)meta->annotation->substmts[ANNOTATION_SUBSTMT_TYPE].storage;
349
350
            /* validate and store the value of the metadata */
351
0
            ret = lyd_value_validate_incomplete(LYD_CTX(meta->parent), type, &meta->value, meta->parent, *tree);
352
0
            LY_CHECK_RET(ret);
353
354
            /* remove this attr from the set */
355
0
            ly_set_rm_index(meta_types, i, NULL);
356
0
        } while (i);
357
0
    }
358
359
0
    return ret;
360
0
}
361
362
/**
363
 * @brief Validate instance duplication.
364
 *
365
 * @param[in] first First sibling to search in.
366
 * @param[in] node Data node instance to check.
367
 * @return LY_ERR value.
368
 */
369
static LY_ERR
370
lyd_validate_duplicates(const struct lyd_node *first, const struct lyd_node *node)
371
0
{
372
0
    struct lyd_node **match_p;
373
0
    ly_bool fail = 0;
374
375
0
    assert(node->flags & LYD_NEW);
376
377
    /* key-less list or non-configuration leaf-list */
378
0
    if (lysc_is_dup_inst_list(node->schema)) {
379
        /* duplicate instances allowed */
380
0
        return LY_SUCCESS;
381
0
    }
382
383
    /* find exactly the same next instance using hashes if possible */
384
0
    if (node->parent && node->parent->children_ht) {
385
0
        if (!lyht_find_next(node->parent->children_ht, &node, node->hash, (void **)&match_p)) {
386
0
            fail = 1;
387
0
        }
388
0
    } else {
389
0
        for ( ; first; first = first->next) {
390
0
            if (first == node) {
391
0
                continue;
392
0
            }
393
394
0
            if (node->schema->nodetype & (LYD_NODE_ANY | LYS_LEAF)) {
395
0
                if (first->schema == node->schema) {
396
0
                    fail = 1;
397
0
                    break;
398
0
                }
399
0
            } else if (!lyd_compare_single(first, node, 0)) {
400
0
                fail = 1;
401
0
                break;
402
0
            }
403
0
        }
404
0
    }
405
406
0
    if (fail) {
407
0
        LOGVAL(node->schema->module->ctx, LY_VCODE_DUP, node->schema->name);
408
0
        return LY_EVALID;
409
0
    }
410
0
    return LY_SUCCESS;
411
0
}
412
413
/**
414
 * @brief Validate multiple case data existence with possible autodelete.
415
 *
416
 * @param[in,out] first First sibling to search in, is updated if needed.
417
 * @param[in] mod Module of the siblings, NULL for nested siblings.
418
 * @param[in] choic Choice node whose cases to check.
419
 * @param[in,out] diff Validation diff.
420
 * @return LY_ERR value.
421
 */
422
static LY_ERR
423
lyd_validate_cases(struct lyd_node **first, const struct lys_module *mod, const struct lysc_node_choice *choic,
424
        struct lyd_node **diff)
425
0
{
426
0
    const struct lysc_node *scase, *iter, *old_case = NULL, *new_case = NULL;
427
0
    struct lyd_node *match, *to_del;
428
0
    ly_bool found;
429
430
0
    LOG_LOCSET(&choic->node, NULL, NULL, NULL);
431
432
0
    LY_LIST_FOR((struct lysc_node *)choic->cases, scase) {
433
0
        found = 0;
434
0
        iter = NULL;
435
0
        match = NULL;
436
0
        while ((match = lys_getnext_data(match, *first, &iter, scase, NULL))) {
437
0
            if (match->flags & LYD_NEW) {
438
                /* a new case data found, nothing more to look for */
439
0
                found = 2;
440
0
                break;
441
0
            } else {
442
                /* and old case data found */
443
0
                if (found == 0) {
444
0
                    found = 1;
445
0
                }
446
0
            }
447
0
        }
448
449
0
        if (found == 1) {
450
            /* there should not be 2 old cases */
451
0
            if (old_case) {
452
                /* old data from 2 cases */
453
0
                LOGVAL(choic->module->ctx, LY_VCODE_DUPCASE, old_case->name, scase->name);
454
0
                LOG_LOCBACK(1, 0, 0, 0);
455
0
                return LY_EVALID;
456
0
            }
457
458
            /* remember an old existing case */
459
0
            old_case = scase;
460
0
        } else if (found == 2) {
461
0
            if (new_case) {
462
                /* new data from 2 cases */
463
0
                LOGVAL(choic->module->ctx, LY_VCODE_DUPCASE, new_case->name, scase->name);
464
0
                LOG_LOCBACK(1, 0, 0, 0);
465
0
                return LY_EVALID;
466
0
            }
467
468
            /* remember a new existing case */
469
0
            new_case = scase;
470
0
        }
471
0
    }
472
473
0
    LOG_LOCBACK(1, 0, 0, 0);
474
475
0
    if (old_case && new_case) {
476
        /* auto-delete old case */
477
0
        iter = NULL;
478
0
        match = NULL;
479
0
        to_del = NULL;
480
0
        while ((match = lys_getnext_data(match, *first, &iter, old_case, NULL))) {
481
0
            lyd_del_move_root(first, to_del, mod);
482
483
            /* free previous node */
484
0
            lyd_free_tree(to_del);
485
0
            if (diff) {
486
                /* add into diff */
487
0
                LY_CHECK_RET(lyd_val_diff_add(match, LYD_DIFF_OP_DELETE, diff));
488
0
            }
489
0
            to_del = match;
490
0
        }
491
0
        lyd_del_move_root(first, to_del, mod);
492
0
        lyd_free_tree(to_del);
493
0
    }
494
495
0
    return LY_SUCCESS;
496
0
}
497
498
/**
499
 * @brief Check whether a schema node can have some default values (true for NP containers as well).
500
 *
501
 * @param[in] schema Schema node to check.
502
 * @return non-zero if yes,
503
 * @return 0 otherwise.
504
 */
505
static int
506
lyd_val_has_default(const struct lysc_node *schema)
507
0
{
508
0
    switch (schema->nodetype) {
509
0
    case LYS_LEAF:
510
0
        if (((struct lysc_node_leaf *)schema)->dflt) {
511
0
            return 1;
512
0
        }
513
0
        break;
514
0
    case LYS_LEAFLIST:
515
0
        if (((struct lysc_node_leaflist *)schema)->dflts) {
516
0
            return 1;
517
0
        }
518
0
        break;
519
0
    case LYS_CONTAINER:
520
0
        if (!(schema->flags & LYS_PRESENCE)) {
521
0
            return 1;
522
0
        }
523
0
        break;
524
0
    default:
525
0
        break;
526
0
    }
527
528
0
    return 0;
529
0
}
530
531
/**
532
 * @brief Properly delete a node as part of autodelete validation tasks.
533
 *
534
 * @param[in,out] first First sibling, is updated if needed.
535
 * @param[in] node Node instance to delete.
536
 * @param[in] mod Module of the siblings, NULL for nested siblings.
537
 * @param[in,out] next_p Temporary LY_LIST_FOR_SAFE next pointer, is updated if needed.
538
 * @param[in,out] diff Validation diff.
539
 */
540
static void
541
lyd_validate_autodel_node_del(struct lyd_node **first, struct lyd_node *node, const struct lys_module *mod,
542
        struct lyd_node **next_p, struct lyd_node **diff)
543
0
{
544
0
    struct lyd_node *iter;
545
546
0
    lyd_del_move_root(first, node, mod);
547
0
    if (node == *next_p) {
548
0
        *next_p = (*next_p)->next;
549
0
    }
550
0
    if (diff) {
551
        /* add into diff */
552
0
        if ((node->schema->nodetype == LYS_CONTAINER) && !(node->schema->flags & LYS_PRESENCE)) {
553
            /* we do not want to track NP container changes, but remember any removed children */
554
0
            LY_LIST_FOR(lyd_child(node), iter) {
555
0
                lyd_val_diff_add(iter, LYD_DIFF_OP_DELETE, diff);
556
0
            }
557
0
        } else {
558
0
            lyd_val_diff_add(node, LYD_DIFF_OP_DELETE, diff);
559
0
        }
560
0
    }
561
0
    lyd_free_tree(node);
562
0
}
563
564
/**
565
 * @brief Autodelete old instances to prevent validation errors.
566
 *
567
 * @param[in,out] first First sibling to search in, is updated if needed.
568
 * @param[in] node New data node instance to check.
569
 * @param[in] mod Module of the siblings, NULL for nested siblings.
570
 * @param[in,out] next_p Temporary LY_LIST_FOR_SAFE next pointer, is updated if needed.
571
 * @param[in,out] diff Validation diff.
572
 */
573
static void
574
lyd_validate_autodel_dup(struct lyd_node **first, struct lyd_node *node, const struct lys_module *mod,
575
        struct lyd_node **next_p, struct lyd_node **diff)
576
0
{
577
0
    struct lyd_node *match, *next;
578
579
0
    assert(node->flags & LYD_NEW);
580
581
0
    if (lyd_val_has_default(node->schema)) {
582
0
        assert(node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_CONTAINER));
583
0
        LYD_LIST_FOR_INST_SAFE(*first, node->schema, next, match) {
584
0
            if ((match->flags & LYD_DEFAULT) && !(match->flags & LYD_NEW)) {
585
                /* default instance found, remove it */
586
0
                lyd_validate_autodel_node_del(first, match, mod, next_p, diff);
587
588
                /* remove only a single container/leaf default instance, if there are more, it is an error */
589
0
                if (node->schema->nodetype & (LYS_LEAF | LYS_CONTAINER)) {
590
0
                    break;
591
0
                }
592
0
            }
593
0
        }
594
0
    }
595
0
}
596
597
/**
598
 * @brief Autodelete leftover default nodes of deleted cases (that have no existing explicit data).
599
 *
600
 * @param[in,out] first First sibling to search in, is updated if needed.
601
 * @param[in] node Default data node instance to check.
602
 * @param[in] mod Module of the siblings, NULL for nested siblings.
603
 * @param[in,out] next_p Temporary LY_LIST_FOR_SAFE next pointer, is updated if needed.
604
 * @param[in,out] diff Validation diff.
605
 */
606
static void
607
lyd_validate_autodel_case_dflt(struct lyd_node **first, struct lyd_node *node, const struct lys_module *mod,
608
        struct lyd_node **next_p, struct lyd_node **diff)
609
0
{
610
0
    struct lysc_node_choice *choic;
611
0
    struct lyd_node *iter = NULL;
612
0
    const struct lysc_node *slast = NULL;
613
614
0
    assert(node->flags & LYD_DEFAULT);
615
616
0
    if (!node->schema->parent || (node->schema->parent->nodetype != LYS_CASE)) {
617
        /* the default node is not a descendant of a case */
618
0
        return;
619
0
    }
620
621
0
    choic = (struct lysc_node_choice *)node->schema->parent->parent;
622
0
    assert(choic->nodetype == LYS_CHOICE);
623
624
0
    if (choic->dflt && (choic->dflt == (struct lysc_node_case *)node->schema->parent)) {
625
        /* data of a default case, keep them */
626
0
        return;
627
0
    }
628
629
    /* try to find an explicit node of the case */
630
0
    while ((iter = lys_getnext_data(iter, *first, &slast, node->schema->parent, NULL))) {
631
0
        if (!(iter->flags & LYD_DEFAULT)) {
632
0
            break;
633
0
        }
634
0
    }
635
636
0
    if (!iter) {
637
        /* there are only default nodes of the case meaning it does not exist and neither should any default nodes
638
         * of the case, remove this one default node */
639
0
        lyd_validate_autodel_node_del(first, node, mod, next_p, diff);
640
0
    }
641
0
}
642
643
/**
644
 * @brief Validate new siblings in choices, recursively for nested choices.
645
 *
646
 * @param[in,out] first First sibling.
647
 * @param[in] sparent Schema parent of the siblings, NULL for top-level siblings.
648
 * @param[in] mod Module of the siblings, NULL for nested siblings.
649
 * @param[in,out] diff Validation diff.
650
 * @return LY_ERR value.
651
 */
652
static LY_ERR
653
lyd_validate_choice_r(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod,
654
        struct lyd_node **diff)
655
0
{
656
0
    const struct lysc_node *snode = NULL;
657
658
0
    while (*first && (snode = lys_getnext(snode, sparent, mod ? mod->compiled : NULL, LYS_GETNEXT_WITHCHOICE))) {
659
        /* check case duplicites */
660
0
        if (snode->nodetype == LYS_CHOICE) {
661
0
            LY_CHECK_RET(lyd_validate_cases(first, mod, (struct lysc_node_choice *)snode, diff));
662
663
            /* check for nested choice */
664
0
            LY_CHECK_RET(lyd_validate_choice_r(first, snode, mod, diff));
665
0
        }
666
0
    }
667
668
0
    return LY_SUCCESS;
669
0
}
670
671
LY_ERR
672
lyd_validate_new(struct lyd_node **first, const struct lysc_node *sparent, const struct lys_module *mod,
673
        struct lyd_node **diff)
674
0
{
675
0
    struct lyd_node *next, *node;
676
677
0
    assert(first && (sparent || mod));
678
679
    /* validate choices */
680
0
    LY_CHECK_RET(lyd_validate_choice_r(first, sparent, mod, diff));
681
682
0
    LY_LIST_FOR_SAFE(*first, next, node) {
683
0
        if (!node->schema || (mod && (lyd_owner_module(node) != mod))) {
684
            /* opaque node or all top-level data from this module checked */
685
0
            break;
686
0
        }
687
688
0
        if (!(node->flags & (LYD_NEW | LYD_DEFAULT))) {
689
            /* check only new and default nodes */
690
0
            continue;
691
0
        }
692
693
0
        LOG_LOCSET(node->schema, node, NULL, NULL);
694
695
0
        if (node->flags & LYD_NEW) {
696
0
            LY_ERR ret;
697
698
            /* remove old default(s) of the new node if it exists */
699
0
            lyd_validate_autodel_dup(first, node, mod, &next, diff);
700
701
            /* then check new node instance duplicities */
702
0
            ret = lyd_validate_duplicates(*first, node);
703
0
            LY_CHECK_ERR_RET(ret, LOG_LOCBACK(node->schema ? 1 : 0, 1, 0, 0), ret);
704
705
            /* this node is valid */
706
0
            node->flags &= ~LYD_NEW;
707
0
        }
708
709
0
        LOG_LOCBACK(node->schema ? 1 : 0, 1, 0, 0);
710
711
0
        if (node->flags & LYD_DEFAULT) {
712
            /* remove leftover default nodes from a no-longer existing case */
713
0
            lyd_validate_autodel_case_dflt(first, node, mod, &next, diff);
714
0
        }
715
0
    }
716
717
0
    return LY_SUCCESS;
718
0
}
719
720
/**
721
 * @brief Evaluate any "when" conditions of a non-existent data node with existing parent.
722
 *
723
 * @param[in] first First data sibling of the non-existing node.
724
 * @param[in] parent Data parent of the non-existing node.
725
 * @param[in] snode Schema node of the non-existing node.
726
 * @param[out] disabled First when that evaluated false, if any.
727
 * @return LY_ERR value.
728
 */
729
static LY_ERR
730
lyd_validate_dummy_when(const struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *snode,
731
        const struct lysc_when **disabled)
732
0
{
733
0
    LY_ERR ret = LY_SUCCESS;
734
0
    struct lyd_node *tree, *dummy = NULL;
735
0
    uint32_t xp_opts;
736
737
    /* find root */
738
0
    if (parent) {
739
0
        tree = (struct lyd_node *)parent;
740
0
        while (tree->parent) {
741
0
            tree = lyd_parent(tree);
742
0
        }
743
0
        tree = lyd_first_sibling(tree);
744
0
    } else {
745
        /* is the first sibling from the same module, but may not be the actual first */
746
0
        tree = lyd_first_sibling(first);
747
0
    }
748
749
    /* create dummy opaque node */
750
0
    ret = lyd_new_opaq((struct lyd_node *)parent, snode->module->ctx, snode->name, NULL, NULL, snode->module->name, &dummy);
751
0
    LY_CHECK_GOTO(ret, cleanup);
752
753
    /* connect it if needed */
754
0
    if (!parent) {
755
0
        if (first) {
756
0
            lyd_insert_sibling((struct lyd_node *)first, dummy, &tree);
757
0
        } else {
758
0
            assert(!tree);
759
0
            tree = dummy;
760
0
        }
761
0
    }
762
763
    /* explicitly specified accesible tree */
764
0
    if (snode->flags & LYS_CONFIG_W) {
765
0
        xp_opts = LYXP_ACCESS_TREE_CONFIG;
766
0
    } else {
767
0
        xp_opts = LYXP_ACCESS_TREE_ALL;
768
0
    }
769
770
    /* evaluate all when */
771
0
    ret = lyd_validate_node_when(tree, dummy, snode, xp_opts, disabled);
772
0
    if (ret == LY_EINCOMPLETE) {
773
        /* all other when must be resolved by now */
774
0
        LOGINT(snode->module->ctx);
775
0
        ret = LY_EINT;
776
0
        goto cleanup;
777
0
    } else if (ret) {
778
        /* error */
779
0
        goto cleanup;
780
0
    }
781
782
0
cleanup:
783
0
    lyd_free_tree(dummy);
784
0
    return ret;
785
0
}
786
787
/**
788
 * @brief Validate mandatory node existence.
789
 *
790
 * @param[in] first First sibling to search in.
791
 * @param[in] parent Data parent.
792
 * @param[in] snode Schema node to validate.
793
 * @return LY_ERR value.
794
 */
795
static LY_ERR
796
lyd_validate_mandatory(const struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *snode)
797
0
{
798
0
    const struct lysc_when *disabled;
799
800
0
    if (snode->nodetype == LYS_CHOICE) {
801
        /* some data of a choice case exist */
802
0
        if (lys_getnext_data(NULL, first, NULL, snode, NULL)) {
803
0
            return LY_SUCCESS;
804
0
        }
805
0
    } else {
806
0
        assert(snode->nodetype & (LYS_LEAF | LYS_CONTAINER | LYD_NODE_ANY));
807
808
0
        if (!lyd_find_sibling_val(first, snode, NULL, 0, NULL)) {
809
            /* data instance found */
810
0
            return LY_SUCCESS;
811
0
        }
812
0
    }
813
814
0
    disabled = NULL;
815
0
    if (lysc_has_when(snode)) {
816
        /* if there are any when conditions, they must be true for a validation error */
817
0
        LY_CHECK_RET(lyd_validate_dummy_when(first, parent, snode, &disabled));
818
0
    }
819
820
0
    if (!disabled) {
821
        /* node instance not found */
822
0
        if (snode->nodetype == LYS_CHOICE) {
823
0
            LOGVAL_APPTAG(snode->module->ctx, "missing-choice", LY_VCODE_NOMAND_CHOIC, snode->name);
824
0
        } else {
825
0
            LOGVAL(snode->module->ctx, LY_VCODE_NOMAND, snode->name);
826
0
        }
827
0
        return LY_EVALID;
828
0
    }
829
830
0
    return LY_SUCCESS;
831
0
}
832
833
/**
834
 * @brief Validate min/max-elements constraints, if any.
835
 *
836
 * @param[in] first First sibling to search in.
837
 * @param[in] parent Data parent.
838
 * @param[in] snode Schema node to validate.
839
 * @param[in] min Minimum number of elements, 0 for no restriction.
840
 * @param[in] max Max number of elements, 0 for no restriction.
841
 * @return LY_ERR value.
842
 */
843
static LY_ERR
844
lyd_validate_minmax(const struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *snode,
845
        uint32_t min, uint32_t max)
846
0
{
847
0
    uint32_t count = 0;
848
0
    struct lyd_node *iter;
849
0
    const struct lysc_when *disabled;
850
0
    ly_bool invalid_instance = 0;
851
852
0
    assert(min || max);
853
854
0
    LYD_LIST_FOR_INST(first, snode, iter) {
855
0
        ++count;
856
857
0
        if (min && (count == min)) {
858
            /* satisfied */
859
0
            min = 0;
860
0
            if (!max) {
861
                /* nothing more to check */
862
0
                break;
863
0
            }
864
0
        }
865
0
        if (max && (count > max)) {
866
            /* not satisifed */
867
0
            LOG_LOCSET(NULL, iter, NULL, NULL);
868
0
            invalid_instance = 1;
869
0
            break;
870
0
        }
871
0
    }
872
873
0
    if (min) {
874
0
        assert(count < min);
875
876
0
        disabled = NULL;
877
0
        if (lysc_has_when(snode)) {
878
            /* if there are any when conditions, they must be true for a validation error */
879
0
            LY_CHECK_RET(lyd_validate_dummy_when(first, parent, snode, &disabled));
880
0
        }
881
882
0
        if (!disabled) {
883
0
            LOGVAL_APPTAG(snode->module->ctx, "too-few-elements", LY_VCODE_NOMIN, snode->name);
884
0
            goto failure;
885
0
        }
886
0
    } else if (max && (count > max)) {
887
0
        LOGVAL_APPTAG(snode->module->ctx, "too-many-elements", LY_VCODE_NOMAX, snode->name);
888
0
        goto failure;
889
0
    }
890
891
0
    return LY_SUCCESS;
892
893
0
failure:
894
0
    LOG_LOCBACK(0, invalid_instance, 0, 0);
895
0
    return LY_EVALID;
896
0
}
897
898
/**
899
 * @brief Find node referenced by a list unique statement.
900
 *
901
 * @param[in] uniq_leaf Unique leaf to find.
902
 * @param[in] list List instance to use for the search.
903
 * @return Found leaf,
904
 * @return NULL if no leaf found.
905
 */
906
static struct lyd_node *
907
lyd_val_uniq_find_leaf(const struct lysc_node_leaf *uniq_leaf, const struct lyd_node *list)
908
0
{
909
0
    struct lyd_node *node;
910
0
    const struct lysc_node *iter;
911
0
    size_t depth = 0, i;
912
913
    /* get leaf depth */
914
0
    for (iter = &uniq_leaf->node; iter && (iter != list->schema); iter = lysc_data_parent(iter)) {
915
0
        ++depth;
916
0
    }
917
918
0
    node = (struct lyd_node *)list;
919
0
    while (node && depth) {
920
        /* find schema node with this depth */
921
0
        for (i = depth - 1, iter = &uniq_leaf->node; i; iter = lysc_data_parent(iter)) {
922
0
            --i;
923
0
        }
924
925
        /* find iter instance in children */
926
0
        assert(iter->nodetype & (LYS_CONTAINER | LYS_LEAF));
927
0
        lyd_find_sibling_val(lyd_child(node), iter, NULL, 0, &node);
928
0
        --depth;
929
0
    }
930
931
0
    return node;
932
0
}
933
934
/**
935
 * @brief Callback for comparing 2 list unique leaf values.
936
 *
937
 * Implementation of ::lyht_value_equal_cb.
938
 *
939
 * @param[in] cb_data 0 to compare all uniques, n to compare only n-th unique.
940
 */
941
static ly_bool
942
lyd_val_uniq_list_equal(void *val1_p, void *val2_p, ly_bool UNUSED(mod), void *cb_data)
943
0
{
944
0
    struct ly_ctx *ctx;
945
0
    struct lysc_node_list *slist;
946
0
    struct lyd_node *diter, *first, *second;
947
0
    struct lyd_value *val1, *val2;
948
0
    char *path1, *path2, *uniq_str, *ptr;
949
0
    LY_ARRAY_COUNT_TYPE u, v, action;
950
951
0
    assert(val1_p && val2_p);
952
953
0
    first = *((struct lyd_node **)val1_p);
954
0
    second = *((struct lyd_node **)val2_p);
955
0
    action = (uintptr_t)cb_data;
956
957
0
    assert(first && (first->schema->nodetype == LYS_LIST));
958
0
    assert(second && (second->schema == first->schema));
959
960
0
    ctx = first->schema->module->ctx;
961
962
0
    slist = (struct lysc_node_list *)first->schema;
963
964
    /* compare unique leaves */
965
0
    if (action > 0) {
966
0
        u = action - 1;
967
0
        if (u < LY_ARRAY_COUNT(slist->uniques)) {
968
0
            goto uniquecheck;
969
0
        }
970
0
    }
971
0
    LY_ARRAY_FOR(slist->uniques, u) {
972
0
uniquecheck:
973
0
        LY_ARRAY_FOR(slist->uniques[u], v) {
974
            /* first */
975
0
            diter = lyd_val_uniq_find_leaf(slist->uniques[u][v], first);
976
0
            if (diter) {
977
0
                val1 = &((struct lyd_node_term *)diter)->value;
978
0
            } else {
979
                /* use default value */
980
0
                val1 = slist->uniques[u][v]->dflt;
981
0
            }
982
983
            /* second */
984
0
            diter = lyd_val_uniq_find_leaf(slist->uniques[u][v], second);
985
0
            if (diter) {
986
0
                val2 = &((struct lyd_node_term *)diter)->value;
987
0
            } else {
988
                /* use default value */
989
0
                val2 = slist->uniques[u][v]->dflt;
990
0
            }
991
992
0
            if (!val1 || !val2 || val1->realtype->plugin->compare(val1, val2)) {
993
                /* values differ or either one is not set */
994
0
                break;
995
0
            }
996
0
        }
997
0
        if (v && (v == LY_ARRAY_COUNT(slist->uniques[u]))) {
998
            /* all unique leafs are the same in this set, create this nice error */
999
0
            path1 = lyd_path(first, LYD_PATH_STD, NULL, 0);
1000
0
            path2 = lyd_path(second, LYD_PATH_STD, NULL, 0);
1001
1002
            /* use buffer to rebuild the unique string */
1003
0
#define UNIQ_BUF_SIZE 1024
1004
0
            uniq_str = malloc(UNIQ_BUF_SIZE);
1005
0
            uniq_str[0] = '\0';
1006
0
            ptr = uniq_str;
1007
0
            LY_ARRAY_FOR(slist->uniques[u], v) {
1008
0
                if (v) {
1009
0
                    strcpy(ptr, " ");
1010
0
                    ++ptr;
1011
0
                }
1012
0
                ptr = lysc_path_until((struct lysc_node *)slist->uniques[u][v], &slist->node, LYSC_PATH_LOG,
1013
0
                        ptr, UNIQ_BUF_SIZE - (ptr - uniq_str));
1014
0
                if (!ptr) {
1015
                    /* path will be incomplete, whatever */
1016
0
                    break;
1017
0
                }
1018
1019
0
                ptr += strlen(ptr);
1020
0
            }
1021
0
            LOG_LOCSET(NULL, second, NULL, NULL);
1022
0
            LOGVAL_APPTAG(ctx, "data-not-unique", LY_VCODE_NOUNIQ, uniq_str, path1, path2);
1023
0
            LOG_LOCBACK(0, 1, 0, 0);
1024
1025
0
            free(path1);
1026
0
            free(path2);
1027
0
            free(uniq_str);
1028
0
#undef UNIQ_BUF_SIZE
1029
1030
0
            return 1;
1031
0
        }
1032
1033
0
        if (action > 0) {
1034
            /* done */
1035
0
            return 0;
1036
0
        }
1037
0
    }
1038
1039
0
    return 0;
1040
0
}
1041
1042
/**
1043
 * @brief Validate list unique leaves.
1044
 *
1045
 * @param[in] first First sibling to search in.
1046
 * @param[in] snode Schema node to validate.
1047
 * @param[in] uniques List unique arrays to validate.
1048
 * @return LY_ERR value.
1049
 */
1050
static LY_ERR
1051
lyd_validate_unique(const struct lyd_node *first, const struct lysc_node *snode, const struct lysc_node_leaf ***uniques)
1052
0
{
1053
0
    const struct lyd_node *diter;
1054
0
    struct ly_set *set;
1055
0
    LY_ARRAY_COUNT_TYPE u, v, x = 0;
1056
0
    LY_ERR ret = LY_SUCCESS;
1057
0
    uint32_t hash, i;
1058
0
    size_t key_len;
1059
0
    ly_bool dyn;
1060
0
    const void *hash_key;
1061
0
    void *cb_data;
1062
0
    struct hash_table **uniqtables = NULL;
1063
0
    struct lyd_value *val;
1064
0
    struct ly_ctx *ctx = snode->module->ctx;
1065
1066
0
    assert(uniques);
1067
1068
    /* get all list instances */
1069
0
    LY_CHECK_RET(ly_set_new(&set));
1070
0
    LY_LIST_FOR(first, diter) {
1071
0
        if (diter->schema == snode) {
1072
0
            ret = ly_set_add(set, (void *)diter, 1, NULL);
1073
0
            LY_CHECK_GOTO(ret, cleanup);
1074
0
        }
1075
0
    }
1076
1077
0
    if (set->count == 2) {
1078
        /* simple comparison */
1079
0
        if (lyd_val_uniq_list_equal(&set->objs[0], &set->objs[1], 0, (void *)0)) {
1080
            /* instance duplication */
1081
0
            ret = LY_EVALID;
1082
0
            goto cleanup;
1083
0
        }
1084
0
    } else if (set->count > 2) {
1085
        /* use hashes for comparison */
1086
0
        uniqtables = malloc(LY_ARRAY_COUNT(uniques) * sizeof *uniqtables);
1087
0
        LY_CHECK_ERR_GOTO(!uniqtables, LOGMEM(ctx); ret = LY_EMEM, cleanup);
1088
0
        x = LY_ARRAY_COUNT(uniques);
1089
0
        for (v = 0; v < x; v++) {
1090
0
            cb_data = (void *)(uintptr_t)(v + 1L);
1091
0
            uniqtables[v] = lyht_new(lyht_get_fixed_size(set->count), sizeof(struct lyd_node *),
1092
0
                    lyd_val_uniq_list_equal, cb_data, 0);
1093
0
            LY_CHECK_ERR_GOTO(!uniqtables[v], LOGMEM(ctx); ret = LY_EMEM, cleanup);
1094
0
        }
1095
1096
0
        for (i = 0; i < set->count; i++) {
1097
            /* loop for unique - get the hash for the instances */
1098
0
            for (u = 0; u < x; u++) {
1099
0
                val = NULL;
1100
0
                for (v = hash = 0; v < LY_ARRAY_COUNT(uniques[u]); v++) {
1101
0
                    diter = lyd_val_uniq_find_leaf(uniques[u][v], set->objs[i]);
1102
0
                    if (diter) {
1103
0
                        val = &((struct lyd_node_term *)diter)->value;
1104
0
                    } else {
1105
                        /* use default value */
1106
0
                        val = uniques[u][v]->dflt;
1107
0
                    }
1108
0
                    if (!val) {
1109
                        /* unique item not present nor has default value */
1110
0
                        break;
1111
0
                    }
1112
1113
                    /* get hash key */
1114
0
                    hash_key = val->realtype->plugin->print(NULL, val, LY_VALUE_LYB, NULL, &dyn, &key_len);
1115
0
                    hash = dict_hash_multi(hash, hash_key, key_len);
1116
0
                    if (dyn) {
1117
0
                        free((void *)hash_key);
1118
0
                    }
1119
0
                }
1120
0
                if (!val) {
1121
                    /* skip this list instance since its unique set is incomplete */
1122
0
                    continue;
1123
0
                }
1124
1125
                /* finish the hash value */
1126
0
                hash = dict_hash_multi(hash, NULL, 0);
1127
1128
                /* insert into the hashtable */
1129
0
                ret = lyht_insert(uniqtables[u], &set->objs[i], hash, NULL);
1130
0
                if (ret == LY_EEXIST) {
1131
                    /* instance duplication */
1132
0
                    ret = LY_EVALID;
1133
0
                }
1134
0
                LY_CHECK_GOTO(ret != LY_SUCCESS, cleanup);
1135
0
            }
1136
0
        }
1137
0
    }
1138
1139
0
cleanup:
1140
0
    ly_set_free(set, NULL);
1141
0
    for (v = 0; v < x; v++) {
1142
0
        if (!uniqtables[v]) {
1143
            /* failed when allocating uniquetables[j], following j are not allocated */
1144
0
            break;
1145
0
        }
1146
0
        lyht_free(uniqtables[v]);
1147
0
    }
1148
0
    free(uniqtables);
1149
1150
0
    return ret;
1151
0
}
1152
1153
/**
1154
 * @brief Validate data siblings based on generic schema node restrictions, recursively for schema-only nodes.
1155
 *
1156
 * @param[in] first First sibling to search in.
1157
 * @param[in] parent Data parent.
1158
 * @param[in] sparent Schema parent of the nodes to check.
1159
 * @param[in] mod Module of the nodes to check.
1160
 * @param[in] val_opts Validation options, see @ref datavalidationoptions.
1161
 * @param[in] int_opts Internal parser options.
1162
 * @return LY_ERR value.
1163
 */
1164
static LY_ERR
1165
lyd_validate_siblings_schema_r(const struct lyd_node *first, const struct lyd_node *parent,
1166
        const struct lysc_node *sparent, const struct lysc_module *mod, uint32_t val_opts, uint32_t int_opts)
1167
0
{
1168
0
    LY_ERR ret = LY_SUCCESS;
1169
0
    const struct lysc_node *snode = NULL, *scase;
1170
0
    struct lysc_node_list *slist;
1171
0
    struct lysc_node_leaflist *sllist;
1172
0
    uint32_t getnext_opts;
1173
1174
0
    getnext_opts = LYS_GETNEXT_WITHCHOICE | (int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0);
1175
1176
    /* disabled nodes are skipped by lys_getnext */
1177
0
    while ((snode = lys_getnext(snode, sparent, mod, getnext_opts))) {
1178
0
        if ((val_opts & LYD_VALIDATE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
1179
0
            continue;
1180
0
        }
1181
1182
0
        LOG_LOCSET(snode, NULL, NULL, NULL);
1183
1184
        /* check min-elements and max-elements */
1185
0
        if (snode->nodetype == LYS_LIST) {
1186
0
            slist = (struct lysc_node_list *)snode;
1187
0
            if (slist->min || slist->max) {
1188
0
                ret = lyd_validate_minmax(first, parent, snode, slist->min, slist->max);
1189
0
                LY_CHECK_GOTO(ret, error);
1190
0
            }
1191
0
        } else if (snode->nodetype == LYS_LEAFLIST) {
1192
0
            sllist = (struct lysc_node_leaflist *)snode;
1193
0
            if (sllist->min || sllist->max) {
1194
0
                ret = lyd_validate_minmax(first, parent, snode, sllist->min, sllist->max);
1195
0
                LY_CHECK_GOTO(ret, error);
1196
0
            }
1197
1198
0
        } else if (snode->flags & LYS_MAND_TRUE) {
1199
            /* check generic mandatory existence */
1200
0
            ret = lyd_validate_mandatory(first, parent, snode);
1201
0
            LY_CHECK_GOTO(ret, error);
1202
0
        }
1203
1204
        /* check unique */
1205
0
        if (snode->nodetype == LYS_LIST) {
1206
0
            slist = (struct lysc_node_list *)snode;
1207
0
            if (slist->uniques) {
1208
0
                ret = lyd_validate_unique(first, snode, (const struct lysc_node_leaf ***)slist->uniques);
1209
0
                LY_CHECK_GOTO(ret, error);
1210
0
            }
1211
0
        }
1212
1213
0
        if (snode->nodetype == LYS_CHOICE) {
1214
            /* find the existing case, if any */
1215
0
            LY_LIST_FOR(lysc_node_child(snode), scase) {
1216
0
                if (lys_getnext_data(NULL, first, NULL, scase, NULL)) {
1217
                    /* validate only this case */
1218
0
                    ret = lyd_validate_siblings_schema_r(first, parent, scase, mod, val_opts, int_opts);
1219
0
                    LY_CHECK_GOTO(ret, error);
1220
0
                    break;
1221
0
                }
1222
0
            }
1223
0
        }
1224
1225
0
        LOG_LOCBACK(1, 0, 0, 0);
1226
0
    }
1227
1228
0
    return LY_SUCCESS;
1229
1230
0
error:
1231
0
    LOG_LOCBACK(1, 0, 0, 0);
1232
0
    return ret;
1233
0
}
1234
1235
/**
1236
 * @brief Validate obsolete nodes, only warnings are printed.
1237
 *
1238
 * @param[in] node Node to check.
1239
 */
1240
static void
1241
lyd_validate_obsolete(const struct lyd_node *node)
1242
0
{
1243
0
    const struct lysc_node *snode;
1244
1245
0
    snode = node->schema;
1246
0
    do {
1247
0
        if (snode->flags & LYS_STATUS_OBSLT) {
1248
0
            LOGWRN(snode->module->ctx, "Obsolete schema node \"%s\" instantiated in data.", snode->name);
1249
0
            break;
1250
0
        }
1251
1252
0
        snode = snode->parent;
1253
0
    } while (snode && (snode->nodetype & (LYS_CHOICE | LYS_CASE)));
1254
0
}
1255
1256
/**
1257
 * @brief Validate must conditions of a data node.
1258
 *
1259
 * @param[in] node Node to validate.
1260
 * @param[in] int_opts Internal parser options.
1261
 * @param[in] xpath_options Additional XPath options to use.
1262
 * @return LY_ERR value.
1263
 */
1264
static LY_ERR
1265
lyd_validate_must(const struct lyd_node *node, uint32_t int_opts, uint32_t xpath_options)
1266
0
{
1267
0
    LY_ERR ret;
1268
0
    struct lyxp_set xp_set;
1269
0
    struct lysc_must *musts;
1270
0
    const struct lyd_node *tree;
1271
0
    const struct lysc_node *schema;
1272
0
    const char *emsg, *eapptag;
1273
0
    LY_ARRAY_COUNT_TYPE u;
1274
1275
0
    assert((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) != (LYD_INTOPT_RPC | LYD_INTOPT_REPLY));
1276
0
    assert((int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) != (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY));
1277
1278
0
    if (node->schema->nodetype & (LYS_ACTION | LYS_RPC)) {
1279
0
        if (int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION)) {
1280
0
            schema = &((struct lysc_node_action *)node->schema)->input.node;
1281
0
        } else if (int_opts & LYD_INTOPT_REPLY) {
1282
0
            schema = &((struct lysc_node_action *)node->schema)->output.node;
1283
0
        } else {
1284
0
            LOGINT_RET(LYD_CTX(node));
1285
0
        }
1286
0
    } else {
1287
0
        schema = node->schema;
1288
0
    }
1289
0
    musts = lysc_node_musts(schema);
1290
0
    if (!musts) {
1291
        /* no must to evaluate */
1292
0
        return LY_SUCCESS;
1293
0
    }
1294
1295
    /* find first top-level node */
1296
0
    for (tree = node; tree->parent; tree = lyd_parent(tree)) {}
1297
0
    tree = lyd_first_sibling(tree);
1298
1299
0
    LY_ARRAY_FOR(musts, u) {
1300
0
        memset(&xp_set, 0, sizeof xp_set);
1301
1302
        /* evaluate must */
1303
0
        ret = lyxp_eval(LYD_CTX(node), musts[u].cond, node->schema->module, LY_VALUE_SCHEMA_RESOLVED,
1304
0
                musts[u].prefixes, node, node, tree, NULL, &xp_set, LYXP_SCHEMA | xpath_options);
1305
0
        if (ret == LY_EINCOMPLETE) {
1306
0
            LOGINT_RET(LYD_CTX(node));
1307
0
        } else if (ret) {
1308
0
            return ret;
1309
0
        }
1310
1311
        /* check the result */
1312
0
        lyxp_set_cast(&xp_set, LYXP_SET_BOOLEAN);
1313
0
        if (!xp_set.val.bln) {
1314
            /* use specific error information */
1315
0
            emsg = musts[u].emsg;
1316
0
            eapptag = musts[u].eapptag ? musts[u].eapptag : "must-violation";
1317
0
            if (emsg) {
1318
0
                LOGVAL_APPTAG(LYD_CTX(node), eapptag, LYVE_DATA, "%s", emsg);
1319
0
            } else {
1320
0
                LOGVAL_APPTAG(LYD_CTX(node), eapptag, LY_VCODE_NOMUST, musts[u].cond->expr);
1321
0
            }
1322
0
            return LY_EVALID;
1323
0
        }
1324
0
    }
1325
1326
0
    return LY_SUCCESS;
1327
0
}
1328
1329
/**
1330
 * @brief Perform all remaining validation tasks, the data tree must be final when calling this function.
1331
 *
1332
 * @param[in] first First sibling.
1333
 * @param[in] parent Data parent.
1334
 * @param[in] sparent Schema parent of the siblings, NULL for top-level siblings.
1335
 * @param[in] mod Module of the siblings, NULL for nested siblings.
1336
 * @param[in] val_opts Validation options (@ref datavalidationoptions).
1337
 * @param[in] int_opts Internal parser options.
1338
 * @param[in] must_xp_opts Additional XPath options to use for evaluating "must".
1339
 * @return LY_ERR value.
1340
 */
1341
static LY_ERR
1342
lyd_validate_final_r(struct lyd_node *first, const struct lyd_node *parent, const struct lysc_node *sparent,
1343
        const struct lys_module *mod, uint32_t val_opts, uint32_t int_opts, uint32_t must_xp_opts)
1344
0
{
1345
0
    LY_ERR r;
1346
0
    const char *innode;
1347
0
    struct lyd_node *next = NULL, *node;
1348
1349
    /* validate all restrictions of nodes themselves */
1350
0
    LY_LIST_FOR_SAFE(first, next, node) {
1351
0
        if (node->flags & LYD_EXT) {
1352
            /* ext instance data should have already been validated */
1353
0
            continue;
1354
0
        }
1355
1356
0
        LOG_LOCSET(node->schema, node, NULL, NULL);
1357
1358
        /* opaque data */
1359
0
        if (!node->schema) {
1360
0
            r = lyd_parse_opaq_error(node);
1361
0
            LOG_LOCBACK(0, 1, 0, 0);
1362
0
            return r;
1363
0
        }
1364
1365
0
        if (!node->parent && mod && (lyd_owner_module(node) != mod)) {
1366
            /* all top-level data from this module checked */
1367
0
            LOG_LOCBACK(1, 1, 0, 0);
1368
0
            break;
1369
0
        }
1370
1371
        /* no state/input/output/op data */
1372
0
        innode = NULL;
1373
0
        if ((val_opts & LYD_VALIDATE_NO_STATE) && (node->schema->flags & LYS_CONFIG_R)) {
1374
0
            innode = "state";
1375
0
        } else if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION)) && (node->schema->flags & LYS_IS_OUTPUT)) {
1376
0
            innode = "output";
1377
0
        } else if ((int_opts & LYD_INTOPT_REPLY) && (node->schema->flags & LYS_IS_INPUT)) {
1378
0
            innode = "input";
1379
0
        } else if (!(int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_REPLY)) && (node->schema->nodetype == LYS_RPC)) {
1380
0
            innode = "rpc";
1381
0
        } else if (!(int_opts & (LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) && (node->schema->nodetype == LYS_ACTION)) {
1382
0
            innode = "action";
1383
0
        } else if (!(int_opts & LYD_INTOPT_NOTIF) && (node->schema->nodetype == LYS_NOTIF)) {
1384
0
            innode = "notification";
1385
0
        }
1386
0
        if (innode) {
1387
0
            LOGVAL(LYD_CTX(node), LY_VCODE_UNEXPNODE, innode, node->schema->name);
1388
0
            LOG_LOCBACK(1, 1, 0, 0);
1389
0
            return LY_EVALID;
1390
0
        }
1391
1392
        /* obsolete data */
1393
0
        lyd_validate_obsolete(node);
1394
1395
        /* node's musts */
1396
0
        if ((r = lyd_validate_must(node, int_opts, must_xp_opts))) {
1397
0
            LOG_LOCBACK(1, 1, 0, 0);
1398
0
            return r;
1399
0
        }
1400
1401
        /* node value was checked by plugins */
1402
1403
        /* next iter */
1404
0
        LOG_LOCBACK(1, 1, 0, 0);
1405
0
    }
1406
1407
    /* validate schema-based restrictions */
1408
0
    LY_CHECK_RET(lyd_validate_siblings_schema_r(first, parent, sparent, mod ? mod->compiled : NULL, val_opts, int_opts));
1409
1410
0
    LY_LIST_FOR(first, node) {
1411
0
        if (!node->parent && mod && (lyd_owner_module(node) != mod)) {
1412
            /* all top-level data from this module checked */
1413
0
            break;
1414
0
        }
1415
1416
        /* validate all children recursively */
1417
0
        LY_CHECK_RET(lyd_validate_final_r(lyd_child(node), node, node->schema, NULL, val_opts, int_opts, must_xp_opts));
1418
1419
        /* set default for containers */
1420
0
        if (node->schema && (node->schema->nodetype == LYS_CONTAINER) && !(node->schema->flags & LYS_PRESENCE)) {
1421
0
            LY_LIST_FOR(lyd_child(node), next) {
1422
0
                if (!(next->flags & LYD_DEFAULT)) {
1423
0
                    break;
1424
0
                }
1425
0
            }
1426
0
            if (!next) {
1427
0
                node->flags |= LYD_DEFAULT;
1428
0
            }
1429
0
        }
1430
0
    }
1431
1432
0
    return LY_SUCCESS;
1433
0
}
1434
1435
/**
1436
 * @brief Validate extension instance data by storing it in its unres set.
1437
 *
1438
 * @param[in] sibling First sibling with ::LYD_EXT flag, all the following ones are expected to have it, too.
1439
 * @param[in,out] ext_val Set with parsed extension instance data to validate.
1440
 * @return LY_ERR value.
1441
 */
1442
static LY_ERR
1443
lyd_validate_nested_ext(struct lyd_node *sibling, struct ly_set *ext_val)
1444
0
{
1445
0
    struct lyd_node *node;
1446
0
    struct lyd_ctx_ext_val *ext_v;
1447
0
    struct lysc_ext_instance *nested_exts, *ext = NULL;
1448
0
    LY_ARRAY_COUNT_TYPE u;
1449
1450
    /* check of basic assumptions */
1451
0
    if (!sibling->parent || !sibling->parent->schema) {
1452
0
        LOGINT_RET(LYD_CTX(sibling));
1453
0
    }
1454
0
    LY_LIST_FOR(sibling, node) {
1455
0
        if (!(node->flags & LYD_EXT)) {
1456
0
            LOGINT_RET(LYD_CTX(sibling));
1457
0
        }
1458
0
    }
1459
1460
    /* try to find the extension instance */
1461
0
    nested_exts = sibling->parent->schema->exts;
1462
0
    LY_ARRAY_FOR(nested_exts, u) {
1463
0
        if (nested_exts[u].def->plugin->validate) {
1464
0
            if (ext) {
1465
                /* more extension instances with validate callback */
1466
0
                LOGINT_RET(LYD_CTX(sibling));
1467
0
            }
1468
0
            ext = &nested_exts[u];
1469
0
        }
1470
0
    }
1471
0
    if (!ext) {
1472
        /* no extension instance with validate callback */
1473
0
        LOGINT_RET(LYD_CTX(sibling));
1474
0
    }
1475
1476
    /* store for validation */
1477
0
    ext_v = malloc(sizeof *ext_v);
1478
0
    LY_CHECK_ERR_RET(!ext_v, LOGMEM(LYD_CTX(sibling)), LY_EMEM);
1479
0
    ext_v->ext = ext;
1480
0
    ext_v->sibling = sibling;
1481
0
    LY_CHECK_RET(ly_set_add(ext_val, ext_v, 1, NULL));
1482
1483
0
    return LY_SUCCESS;
1484
0
}
1485
1486
LY_ERR
1487
lyd_validate_node_ext(struct lyd_node *node, struct ly_set *ext_node)
1488
0
{
1489
0
    struct lyd_ctx_ext_node *ext_n;
1490
0
    struct lysc_ext_instance *exts;
1491
0
    LY_ARRAY_COUNT_TYPE u;
1492
1493
    /* try to find a relevant extension instance with node callback */
1494
0
    exts = node->schema->exts;
1495
0
    LY_ARRAY_FOR(exts, u) {
1496
0
        if (exts[u].def->plugin && exts[u].def->plugin->node) {
1497
            /* store for validation */
1498
0
            ext_n = malloc(sizeof *ext_n);
1499
0
            LY_CHECK_ERR_RET(!ext_n, LOGMEM(LYD_CTX(node)), LY_EMEM);
1500
0
            ext_n->ext = &exts[u];
1501
0
            ext_n->node = node;
1502
0
            LY_CHECK_RET(ly_set_add(ext_node, ext_n, 1, NULL));
1503
0
        }
1504
0
    }
1505
1506
0
    return LY_SUCCESS;
1507
0
}
1508
1509
/**
1510
 * @brief Validate the whole data subtree.
1511
 *
1512
 * @param[in] root Subtree root.
1513
 * @param[in,out] node_when Set for nodes with when conditions.
1514
 * @param[in,out] node_types Set for unres node types.
1515
 * @param[in,out] meta_types Set for unres metadata types.
1516
 * @param[in,out] ext_node Set with nodes with extensions to validate.
1517
 * @param[in,out] ext_val Set for parsed extension data to validate.
1518
 * @param[in] impl_opts Implicit options, see @ref implicitoptions.
1519
 * @param[in,out] diff Validation diff.
1520
 * @return LY_ERR value.
1521
 */
1522
static LY_ERR
1523
lyd_validate_subtree(struct lyd_node *root, struct ly_set *node_when, struct ly_set *node_types,
1524
        struct ly_set *meta_types, struct ly_set *ext_node, struct ly_set *ext_val, uint32_t impl_opts,
1525
        struct lyd_node **diff)
1526
0
{
1527
0
    const struct lyd_meta *meta;
1528
0
    struct lyd_node *node;
1529
1530
0
    LYD_TREE_DFS_BEGIN(root, node) {
1531
0
        if (node->flags & LYD_EXT) {
1532
            /* validate using the extension instance callback */
1533
0
            return lyd_validate_nested_ext(node, ext_val);
1534
0
        }
1535
1536
0
        if (!node->schema) {
1537
            /* do not validate opaque nodes */
1538
0
            goto next_node;
1539
0
        }
1540
1541
0
        LY_LIST_FOR(node->meta, meta) {
1542
0
            if ((*(const struct lysc_type **)meta->annotation->substmts[ANNOTATION_SUBSTMT_TYPE].storage)->plugin->validate) {
1543
                /* metadata type resolution */
1544
0
                LY_CHECK_RET(ly_set_add(meta_types, (void *)meta, 1, NULL));
1545
0
            }
1546
0
        }
1547
1548
0
        if ((node->schema->nodetype & LYD_NODE_TERM) && ((struct lysc_node_leaf *)node->schema)->type->plugin->validate) {
1549
            /* node type resolution */
1550
0
            LY_CHECK_RET(ly_set_add(node_types, (void *)node, 1, NULL));
1551
0
        } else if (node->schema->nodetype & LYD_NODE_INNER) {
1552
            /* new node validation, autodelete */
1553
0
            LY_CHECK_RET(lyd_validate_new(lyd_node_child_p(node), node->schema, NULL, diff));
1554
1555
            /* add nested defaults */
1556
0
            LY_CHECK_RET(lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, NULL, NULL, NULL, impl_opts, diff));
1557
0
        }
1558
1559
0
        if (lysc_has_when(node->schema)) {
1560
            /* when evaluation */
1561
0
            LY_CHECK_RET(ly_set_add(node_when, (void *)node, 1, NULL));
1562
0
        }
1563
1564
        /* store for ext instance node validation, if needed */
1565
0
        LY_CHECK_RET(lyd_validate_node_ext(node, ext_node));
1566
1567
0
next_node:
1568
0
        LYD_TREE_DFS_END(root, node);
1569
0
    }
1570
1571
0
    return LY_SUCCESS;
1572
0
}
1573
1574
LY_ERR
1575
lyd_validate(struct lyd_node **tree, const struct lys_module *module, const struct ly_ctx *ctx, uint32_t val_opts,
1576
        ly_bool validate_subtree, struct ly_set *node_when_p, struct ly_set *node_types_p, struct ly_set *meta_types_p,
1577
        struct ly_set *ext_node_p, struct ly_set *ext_val_p, struct lyd_node **diff)
1578
0
{
1579
0
    LY_ERR ret = LY_SUCCESS;
1580
0
    struct lyd_node *first, *next, **first2, *iter;
1581
0
    const struct lys_module *mod;
1582
0
    struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_node = {0}, ext_val = {0};
1583
0
    uint32_t i = 0;
1584
1585
0
    assert(tree && ctx);
1586
0
    assert((node_when_p && node_types_p && meta_types_p && ext_node_p && ext_val_p) ||
1587
0
            (!node_when_p && !node_types_p && !meta_types_p && !ext_node_p && !ext_val_p));
1588
1589
0
    if (!node_when_p) {
1590
0
        node_when_p = &node_when;
1591
0
        node_types_p = &node_types;
1592
0
        meta_types_p = &meta_types;
1593
0
        ext_node_p = &ext_node;
1594
0
        ext_val_p = &ext_val;
1595
0
    }
1596
1597
0
    next = *tree;
1598
0
    while (1) {
1599
0
        if (val_opts & LYD_VALIDATE_PRESENT) {
1600
0
            mod = lyd_data_next_module(&next, &first);
1601
0
        } else {
1602
0
            mod = lyd_mod_next_module(next, module, ctx, &i, &first);
1603
0
        }
1604
0
        if (!mod) {
1605
0
            break;
1606
0
        }
1607
0
        if (!first || (first == *tree)) {
1608
            /* make sure first2 changes are carried to tree */
1609
0
            first2 = tree;
1610
0
        } else {
1611
0
            first2 = &first;
1612
0
        }
1613
1614
        /* validate new top-level nodes of this module, autodelete */
1615
0
        ret = lyd_validate_new(first2, NULL, mod, diff);
1616
0
        LY_CHECK_GOTO(ret, cleanup);
1617
1618
        /* add all top-level defaults for this module, if going to validate subtree, do not add into unres sets
1619
         * (lyd_validate_subtree() adds all the nodes in that case) */
1620
0
        ret = lyd_new_implicit_r(NULL, first2, NULL, mod, validate_subtree ? NULL : node_when_p,
1621
0
                validate_subtree ? NULL : node_types_p, validate_subtree ? NULL : ext_node_p,
1622
0
                (val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, diff);
1623
0
        LY_CHECK_GOTO(ret, cleanup);
1624
1625
        /* our first module node pointer may no longer be the first */
1626
0
        first = *first2;
1627
0
        lyd_first_module_sibling(&first, mod);
1628
0
        if (!first || (first == *tree)) {
1629
0
            first2 = tree;
1630
0
        } else {
1631
0
            first2 = &first;
1632
0
        }
1633
1634
0
        if (validate_subtree) {
1635
            /* process nested nodes */
1636
0
            LY_LIST_FOR(*first2, iter) {
1637
0
                if (lyd_owner_module(iter) != mod) {
1638
0
                    break;
1639
0
                }
1640
1641
0
                ret = lyd_validate_subtree(iter, node_when_p, node_types_p, meta_types_p, ext_node_p, ext_val_p,
1642
0
                        (val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0, diff);
1643
0
                LY_CHECK_GOTO(ret, cleanup);
1644
0
            }
1645
0
        }
1646
1647
        /* finish incompletely validated terminal values/attributes and when conditions */
1648
0
        ret = lyd_validate_unres(first2, mod, LYD_TYPE_DATA_YANG, node_when_p, 0, node_types_p, meta_types_p,
1649
0
                ext_node_p, ext_val_p, val_opts, diff);
1650
0
        LY_CHECK_GOTO(ret, cleanup);
1651
1652
        /* perform final validation that assumes the data tree is final */
1653
0
        ret = lyd_validate_final_r(*first2, NULL, NULL, mod, val_opts, 0, 0);
1654
0
        LY_CHECK_GOTO(ret, cleanup);
1655
0
    }
1656
1657
0
cleanup:
1658
0
    ly_set_erase(&node_when, NULL);
1659
0
    ly_set_erase(&node_types, NULL);
1660
0
    ly_set_erase(&meta_types, NULL);
1661
0
    ly_set_erase(&ext_node, free);
1662
0
    ly_set_erase(&ext_val, free);
1663
0
    return ret;
1664
0
}
1665
1666
LIBYANG_API_DEF LY_ERR
1667
lyd_validate_all(struct lyd_node **tree, const struct ly_ctx *ctx, uint32_t val_opts, struct lyd_node **diff)
1668
0
{
1669
0
    LY_CHECK_ARG_RET(NULL, tree, *tree || ctx, LY_EINVAL);
1670
0
    LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, ctx, LY_EINVAL);
1671
0
    if (!ctx) {
1672
0
        ctx = LYD_CTX(*tree);
1673
0
    }
1674
0
    if (diff) {
1675
0
        *diff = NULL;
1676
0
    }
1677
1678
0
    return lyd_validate(tree, NULL, ctx, val_opts, 1, NULL, NULL, NULL, NULL, NULL, diff);
1679
0
}
1680
1681
LIBYANG_API_DEF LY_ERR
1682
lyd_validate_module(struct lyd_node **tree, const struct lys_module *module, uint32_t val_opts, struct lyd_node **diff)
1683
0
{
1684
0
    LY_CHECK_ARG_RET(NULL, tree, *tree || module, LY_EINVAL);
1685
0
    LY_CHECK_CTX_EQUAL_RET(*tree ? LYD_CTX(*tree) : NULL, module ? module->ctx : NULL, LY_EINVAL);
1686
0
    if (diff) {
1687
0
        *diff = NULL;
1688
0
    }
1689
1690
0
    return lyd_validate(tree, module, (*tree) ? LYD_CTX(*tree) : module->ctx, val_opts, 1, NULL, NULL, NULL, NULL, NULL,
1691
0
            diff);
1692
0
}
1693
1694
/**
1695
 * @brief Find nodes for merging an operation into data tree for validation.
1696
 *
1697
 * @param[in] op_tree Full operation data tree.
1698
 * @param[in] op_node Operation node itself.
1699
 * @param[in] tree Data tree to be merged into.
1700
 * @param[out] op_subtree Operation subtree to merge.
1701
 * @param[out] tree_sibling Data tree sibling to merge next to, is set if @p tree_parent is NULL.
1702
 * @param[out] tree_parent Data tree parent to merge into, is set if @p tree_sibling is NULL.
1703
 */
1704
static void
1705
lyd_val_op_merge_find(const struct lyd_node *op_tree, const struct lyd_node *op_node, const struct lyd_node *tree,
1706
        struct lyd_node **op_subtree, struct lyd_node **tree_sibling, struct lyd_node **tree_parent)
1707
0
{
1708
0
    const struct lyd_node *tree_iter, *op_iter;
1709
0
    struct lyd_node *match;
1710
0
    uint32_t i, cur_depth, op_depth;
1711
1712
0
    *op_subtree = NULL;
1713
0
    *tree_sibling = NULL;
1714
0
    *tree_parent = NULL;
1715
1716
    /* learn op depth (top-level being depth 0) */
1717
0
    op_depth = 0;
1718
0
    for (op_iter = op_node; op_iter != op_tree; op_iter = lyd_parent(op_iter)) {
1719
0
        ++op_depth;
1720
0
    }
1721
1722
    /* find where to merge op */
1723
0
    tree_iter = tree;
1724
0
    cur_depth = op_depth;
1725
0
    while (cur_depth && tree_iter) {
1726
        /* find op iter in tree */
1727
0
        lyd_find_sibling_first(tree_iter, op_iter, &match);
1728
0
        if (!match) {
1729
0
            break;
1730
0
        }
1731
1732
        /* move tree_iter */
1733
0
        tree_iter = lyd_child(match);
1734
1735
        /* move depth */
1736
0
        --cur_depth;
1737
1738
        /* find next op parent */
1739
0
        op_iter = op_node;
1740
0
        for (i = 0; i < cur_depth; ++i) {
1741
0
            op_iter = lyd_parent(op_iter);
1742
0
        }
1743
0
    }
1744
1745
0
    assert(op_iter);
1746
0
    *op_subtree = (struct lyd_node *)op_iter;
1747
0
    if (!tree || tree_iter) {
1748
        /* there is no tree whatsoever or this is the last found sibling */
1749
0
        *tree_sibling = (struct lyd_node *)tree_iter;
1750
0
    } else {
1751
        /* matching parent was found but it has no children to insert next to */
1752
0
        assert(match);
1753
0
        *tree_parent = match;
1754
0
    }
1755
0
}
1756
1757
/**
1758
 * @brief Validate an RPC/action request, reply, or notification.
1759
 *
1760
 * @param[in] op_tree Full operation data tree.
1761
 * @param[in] op_node Operation node itself.
1762
 * @param[in] dep_tree Tree to be used for validating references from the operation subtree.
1763
 * @param[in] int_opts Internal parser options.
1764
 * @param[in] data_type Type of validated data.
1765
 * @param[in] validate_subtree Whether subtree was already validated (as part of data parsing) or not (separate validation).
1766
 * @param[in] node_when_p Set of nodes with when conditions, if NULL a local set is used.
1767
 * @param[in] node_types_p Set of unres node types, if NULL a local set is used.
1768
 * @param[in] meta_types_p Set of unres metadata types, if NULL a local set is used.
1769
 * @param[in] ext_node_p Set of unres nodes with extensions to validate, if NULL a local set is used.
1770
 * @param[in] ext_val_p Set of parsed extension data to validate, if NULL a local set is used.
1771
 * @param[out] diff Optional diff with any changes made by the validation.
1772
 * @return LY_SUCCESS on success.
1773
 * @return LY_ERR error on error.
1774
 */
1775
static LY_ERR
1776
_lyd_validate_op(struct lyd_node *op_tree, struct lyd_node *op_node, const struct lyd_node *dep_tree, enum lyd_type data_type,
1777
        uint32_t int_opts, ly_bool validate_subtree, struct ly_set *node_when_p, struct ly_set *node_types_p,
1778
        struct ly_set *meta_types_p,  struct ly_set *ext_node_p, struct ly_set *ext_val_p, struct lyd_node **diff)
1779
0
{
1780
0
    LY_ERR rc = LY_SUCCESS;
1781
0
    struct lyd_node *tree_sibling, *tree_parent, *op_subtree, *op_parent, *op_sibling_before, *op_sibling_after, *child;
1782
0
    struct ly_set node_types = {0}, meta_types = {0}, node_when = {0}, ext_node = {0}, ext_val = {0};
1783
1784
0
    assert(op_tree && op_node);
1785
0
    assert((node_when_p && node_types_p && meta_types_p && ext_node_p && ext_val_p) ||
1786
0
            (!node_when_p && !node_types_p && !meta_types_p && !ext_node_p && !ext_val_p));
1787
1788
0
    if (!node_when_p) {
1789
0
        node_when_p = &node_when;
1790
0
        node_types_p = &node_types;
1791
0
        meta_types_p = &meta_types;
1792
0
        ext_node_p = &ext_node;
1793
0
        ext_val_p = &ext_val;
1794
0
    }
1795
1796
    /* merge op_tree into dep_tree */
1797
0
    lyd_val_op_merge_find(op_tree, op_node, dep_tree, &op_subtree, &tree_sibling, &tree_parent);
1798
0
    op_sibling_before = op_subtree->prev->next ? op_subtree->prev : NULL;
1799
0
    op_sibling_after = op_subtree->next;
1800
0
    op_parent = lyd_parent(op_subtree);
1801
1802
0
    lyd_unlink_tree(op_subtree);
1803
0
    lyd_insert_node(tree_parent, &tree_sibling, op_subtree, 0);
1804
0
    if (!dep_tree) {
1805
0
        dep_tree = tree_sibling;
1806
0
    }
1807
1808
0
    LOG_LOCSET(NULL, op_node, NULL, NULL);
1809
1810
0
    if (int_opts & LYD_INTOPT_REPLY) {
1811
        /* add output children defaults */
1812
0
        rc = lyd_new_implicit_r(op_node, lyd_node_child_p(op_node), NULL, NULL, node_when_p, node_types_p,
1813
0
                ext_node_p, LYD_IMPLICIT_OUTPUT, diff);
1814
0
        LY_CHECK_GOTO(rc, cleanup);
1815
1816
0
        if (validate_subtree) {
1817
            /* skip validating the operation itself, go to children directly */
1818
0
            LY_LIST_FOR(lyd_child(op_node), child) {
1819
0
                rc = lyd_validate_subtree(child, node_when_p, node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff);
1820
0
                LY_CHECK_GOTO(rc, cleanup);
1821
0
            }
1822
0
        }
1823
0
    } else {
1824
0
        if (validate_subtree) {
1825
            /* prevalidate whole operation subtree */
1826
0
            rc = lyd_validate_subtree(op_node, node_when_p, node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff);
1827
0
            LY_CHECK_GOTO(rc, cleanup);
1828
0
        }
1829
0
    }
1830
1831
    /* finish incompletely validated terminal values/attributes and when conditions on the full tree,
1832
     * account for unresolved 'when' that may appear in the non-validated dependency data tree */
1833
0
    LY_CHECK_GOTO(rc = lyd_validate_unres((struct lyd_node **)&dep_tree, NULL, data_type, node_when_p, LYXP_IGNORE_WHEN,
1834
0
            node_types_p, meta_types_p, ext_node_p, ext_val_p, 0, diff), cleanup);
1835
1836
    /* perform final validation of the operation/notification */
1837
0
    lyd_validate_obsolete(op_node);
1838
0
    LY_CHECK_GOTO(rc = lyd_validate_must(op_node, int_opts, LYXP_IGNORE_WHEN), cleanup);
1839
1840
    /* final validation of all the descendants */
1841
0
    rc = lyd_validate_final_r(lyd_child(op_node), op_node, op_node->schema, NULL, 0, int_opts, LYXP_IGNORE_WHEN);
1842
0
    LY_CHECK_GOTO(rc, cleanup);
1843
1844
0
cleanup:
1845
0
    LOG_LOCBACK(0, 1, 0, 0);
1846
1847
    /* restore operation tree */
1848
0
    lyd_unlink_tree(op_subtree);
1849
0
    if (op_sibling_before) {
1850
0
        lyd_insert_after_node(op_sibling_before, op_subtree);
1851
0
    } else if (op_sibling_after) {
1852
0
        lyd_insert_before_node(op_sibling_after, op_subtree);
1853
0
    } else if (op_parent) {
1854
0
        lyd_insert_node(op_parent, NULL, op_subtree, 0);
1855
0
    }
1856
1857
0
    ly_set_erase(&node_when, NULL);
1858
0
    ly_set_erase(&node_types, NULL);
1859
0
    ly_set_erase(&meta_types, NULL);
1860
0
    ly_set_erase(&ext_node, free);
1861
0
    ly_set_erase(&ext_val, free);
1862
0
    return rc;
1863
0
}
1864
1865
LIBYANG_API_DEF LY_ERR
1866
lyd_validate_op(struct lyd_node *op_tree, const struct lyd_node *dep_tree, enum lyd_type data_type, struct lyd_node **diff)
1867
0
{
1868
0
    struct lyd_node *op_node;
1869
0
    uint32_t int_opts;
1870
0
    struct ly_set ext_val = {0};
1871
0
    LY_ERR rc;
1872
1873
0
    LY_CHECK_ARG_RET(NULL, op_tree, !dep_tree || !dep_tree->parent, (data_type == LYD_TYPE_RPC_YANG) ||
1874
0
            (data_type == LYD_TYPE_NOTIF_YANG) || (data_type == LYD_TYPE_REPLY_YANG), LY_EINVAL);
1875
0
    if (diff) {
1876
0
        *diff = NULL;
1877
0
    }
1878
0
    if (data_type == LYD_TYPE_RPC_YANG) {
1879
0
        int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION;
1880
0
    } else if (data_type == LYD_TYPE_NOTIF_YANG) {
1881
0
        int_opts = LYD_INTOPT_NOTIF;
1882
0
    } else {
1883
0
        int_opts = LYD_INTOPT_REPLY;
1884
0
    }
1885
1886
0
    if (op_tree->schema && (op_tree->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF))) {
1887
        /* we have the operation/notification, adjust the pointers */
1888
0
        op_node = op_tree;
1889
0
        while (op_tree->parent) {
1890
0
            op_tree = lyd_parent(op_tree);
1891
0
        }
1892
0
    } else {
1893
        /* find the operation/notification */
1894
0
        while (op_tree->parent) {
1895
0
            op_tree = lyd_parent(op_tree);
1896
0
        }
1897
0
        LYD_TREE_DFS_BEGIN(op_tree, op_node) {
1898
0
            if (!op_node->schema) {
1899
0
                return lyd_parse_opaq_error(op_node);
1900
0
            } else if (op_node->flags & LYD_EXT) {
1901
                /* fully validate the rest using the extension instance callback */
1902
0
                LY_CHECK_RET(lyd_validate_nested_ext(op_node, &ext_val));
1903
0
                rc = lyd_validate_unres((struct lyd_node **)&dep_tree, NULL, data_type, NULL, 0, NULL, NULL, NULL,
1904
0
                        &ext_val, 0, diff);
1905
0
                ly_set_erase(&ext_val, free);
1906
0
                return rc;
1907
0
            }
1908
1909
0
            if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) &&
1910
0
                    (op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
1911
0
                break;
1912
0
            } else if ((int_opts & LYD_INTOPT_NOTIF) && (op_node->schema->nodetype == LYS_NOTIF)) {
1913
0
                break;
1914
0
            }
1915
0
            LYD_TREE_DFS_END(op_tree, op_node);
1916
0
        }
1917
0
    }
1918
1919
0
    if (int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_REPLY)) {
1920
0
        if (!op_node || !(op_node->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
1921
0
            LOGERR(LYD_CTX(op_tree), LY_EINVAL, "No RPC/action to validate found.");
1922
0
            return LY_EINVAL;
1923
0
        }
1924
0
    } else {
1925
0
        if (!op_node || (op_node->schema->nodetype != LYS_NOTIF)) {
1926
0
            LOGERR(LYD_CTX(op_tree), LY_EINVAL, "No notification to validate found.");
1927
0
            return LY_EINVAL;
1928
0
        }
1929
0
    }
1930
1931
    /* validate */
1932
0
    return _lyd_validate_op(op_tree, op_node, dep_tree, data_type, int_opts, 1, NULL, NULL, NULL, NULL, NULL, diff);
1933
0
}