Bug Summary

File:home/sharpd/frr3/lib/yang.c
Warning:line 656, column 17
Access to field 'len' results in a dereference of a null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name yang.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/sharpd/frr3 -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D HAVE_CONFIG_H -D SYSCONFDIR="/etc/frr/" -D CONFDATE=20240105 -I . -I ./lib/assert -I . -I ./include -I ./lib -I . -I /usr/include/lua5.3 -I /usr/include/x86_64-linux-gnu -D PIC -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wwrite-strings -Wno-unused-result -Wno-unused-parameter -Wno-missing-field-initializers -Wno-microsoft-anon-tag -fconst-strings -fdebug-compilation-dir=/home/sharpd/frr3 -ferror-limit 19 -fms-extensions -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-01-05-120749-780821-1 -x c lib/yang.c
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2018 NetDEF, Inc.
4 * Renato Westphal
5 */
6
7#include <zebra.h>
8
9#include "darr.h"
10#include "log.h"
11#include "lib_errors.h"
12#include "yang.h"
13#include "yang_translator.h"
14#include "northbound.h"
15
16DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module")static struct memtype MTYPE_YANG_MODULE[1] __attribute__((section
(".data.mtypes"))) = { { .name = "YANG module", .next = ((void
*)0), .n_alloc = 0, .size = 0, .ref = ((void*)0), } }; static
void _mtinit_YANG_MODULE(void) __attribute__((constructor(1001
))); static void _mtinit_YANG_MODULE(void) { if (_mg_LIB.insert
== ((void*)0)) _mg_LIB.insert = &_mg_LIB.types; MTYPE_YANG_MODULE
->ref = _mg_LIB.insert; *_mg_LIB.insert = MTYPE_YANG_MODULE
; _mg_LIB.insert = &MTYPE_YANG_MODULE->next; } static void
_mtfini_YANG_MODULE(void) __attribute__((destructor)); static
void _mtfini_YANG_MODULE(void) { if (MTYPE_YANG_MODULE->next
) MTYPE_YANG_MODULE->next->ref = MTYPE_YANG_MODULE->
ref; *MTYPE_YANG_MODULE->ref = MTYPE_YANG_MODULE->next;
} _Static_assert(1, "please add a semicolon after this macro"
)
;
17DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure")static struct memtype MTYPE_YANG_DATA[1] __attribute__((section
(".data.mtypes"))) = { { .name = "YANG data structure", .next
= ((void*)0), .n_alloc = 0, .size = 0, .ref = ((void*)0), } }
; static void _mtinit_YANG_DATA(void) __attribute__((constructor
(1001))); static void _mtinit_YANG_DATA(void) { if (_mg_LIB.insert
== ((void*)0)) _mg_LIB.insert = &_mg_LIB.types; MTYPE_YANG_DATA
->ref = _mg_LIB.insert; *_mg_LIB.insert = MTYPE_YANG_DATA;
_mg_LIB.insert = &MTYPE_YANG_DATA->next; } static void
_mtfini_YANG_DATA(void) __attribute__((destructor)); static void
_mtfini_YANG_DATA(void) { if (MTYPE_YANG_DATA->next) MTYPE_YANG_DATA
->next->ref = MTYPE_YANG_DATA->ref; *MTYPE_YANG_DATA
->ref = MTYPE_YANG_DATA->next; } _Static_assert(1, "please add a semicolon after this macro"
)
;
18
19/* libyang container. */
20struct ly_ctx *ly_native_ctx;
21
22static struct yang_module_embed *embeds, **embedupd = &embeds;
23
24void yang_module_embed(struct yang_module_embed *embed)
25{
26 embed->next = NULL((void*)0);
27 *embedupd = embed;
28 embedupd = &embed->next;
29}
30
31static LY_ERR yang_module_imp_clb(const char *mod_name, const char *mod_rev,
32 const char *submod_name,
33 const char *submod_rev, void *user_data,
34 LYS_INFORMAT *format,
35 const char **module_data,
36 void (**free_module_data)(void *, void *))
37{
38 struct yang_module_embed *e;
39
40 if (!strcmp(mod_name, "ietf-inet-types") ||
41 !strcmp(mod_name, "ietf-yang-types"))
42 /* libyang has these built in, don't try finding them here */
43 return LY_ENOTFOUND;
44
45 for (e = embeds; e; e = e->next) {
46 if (e->sub_mod_name && submod_name) {
47 if (strcmp(e->sub_mod_name, submod_name))
48 continue;
49
50 if (submod_rev && strcmp(e->sub_mod_rev, submod_rev))
51 continue;
52 } else {
53 if (strcmp(e->mod_name, mod_name))
54 continue;
55
56 if (mod_rev && strcmp(e->mod_rev, mod_rev))
57 continue;
58 }
59
60 *format = e->format;
61 *module_data = e->data;
62 return LY_SUCCESS;
63 }
64
65 /* We get here for indirect modules like ietf-inet-types */
66 zlog_debug(do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 69, "lib/yang.c", __func__, }, .fmtstring =
("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .priority = (7), .ec = (0), .args = ("mod_name, mod_rev ? mod_rev : \"*\", submod_name ? submod_name : \"*\", submod_rev ? submod_rev : \"*\""
), }; static const struct xref * const xref_p_25 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name
: "*", submod_rev ? submod_rev : "*"); } while (0)
67 "YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 69, "lib/yang.c", __func__, }, .fmtstring =
("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .priority = (7), .ec = (0), .args = ("mod_name, mod_rev ? mod_rev : \"*\", submod_name ? submod_name : \"*\", submod_rev ? submod_rev : \"*\""
), }; static const struct xref * const xref_p_25 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name
: "*", submod_rev ? submod_rev : "*"); } while (0)
68 mod_name, mod_rev ? mod_rev : "*",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 69, "lib/yang.c", __func__, }, .fmtstring =
("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .priority = (7), .ec = (0), .args = ("mod_name, mod_rev ? mod_rev : \"*\", submod_name ? submod_name : \"*\", submod_rev ? submod_rev : \"*\""
), }; static const struct xref * const xref_p_25 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name
: "*", submod_rev ? submod_rev : "*"); } while (0)
69 submod_name ? submod_name : "*", submod_rev ? submod_rev : "*")do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .hashu32 = {(7), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 69, "lib/yang.c", __func__, }, .fmtstring =
("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), .priority = (7), .ec = (0), .args = ("mod_name, mod_rev ? mod_rev : \"*\", submod_name ? submod_name : \"*\", submod_rev ? submod_rev : \"*\""
), }; static const struct xref * const xref_p_25 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("YANG model \"%s@%s\" \"%s@%s\"not embedded, trying external file"
), mod_name, mod_rev ? mod_rev : "*", submod_name ? submod_name
: "*", submod_rev ? submod_rev : "*"); } while (0)
;
70
71 return LY_ENOTFOUND;
72}
73
74/* clang-format off */
75static const char *const frr_native_modules[] = {
76 "frr-interface",
77 "frr-vrf",
78 "frr-routing",
79 "frr-affinity-map",
80 "frr-route-map",
81 "frr-nexthop",
82 "frr-ripd",
83 "frr-ripngd",
84 "frr-isisd",
85 "frr-vrrpd",
86 "frr-zebra",
87 "frr-pathd",
88};
89/* clang-format on */
90
91/* Generate the yang_modules tree. */
92static inline int yang_module_compare(const struct yang_module *a,
93 const struct yang_module *b)
94{
95 return strcmp(a->name, b->name);
96}
97RB_GENERATE(yang_modules, yang_module, entry, yang_module_compare)static int yang_modules_RB_COMPARE(const void *lptr, const void
*rptr) { const struct yang_module *l = lptr, *r = rptr; return
yang_module_compare(l, r); } static const struct rb_type yang_modules_RB_INFO
= { yang_modules_RB_COMPARE, ((void*)0), __builtin_offsetof(
struct yang_module, entry), }; const struct rb_type *const yang_modules_RB_TYPE
= &yang_modules_RB_INFO;
98
99struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules){ { ((void*)0) } };
100
101struct yang_module *yang_module_load(const char *module_name)
102{
103 struct yang_module *module;
104 const struct lys_module *module_info;
105
106 module_info =
107 ly_ctx_load_module(ly_native_ctx, module_name, NULL((void*)0), NULL((void*)0));
108 if (!module_info) {
109 flog_err(EC_LIB_YANG_MODULE_LOAD,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to load data model: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 111, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to load data model: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, module_name"), }; static const struct xref * const
xref_p_26 __attribute__((used, section("xref_array"))) = &
(_xref.xref); zlog_ref(&_xref, ("%s: failed to load data model: %s"
), __func__, module_name); } while (0)
110 "%s: failed to load data model: %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to load data model: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 111, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to load data model: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, module_name"), }; static const struct xref * const
xref_p_26 __attribute__((used, section("xref_array"))) = &
(_xref.xref); zlog_ref(&_xref, ("%s: failed to load data model: %s"
), __func__, module_name); } while (0)
111 module_name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to load data model: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 111, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to load data model: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, module_name"), }; static const struct xref * const
xref_p_26 __attribute__((used, section("xref_array"))) = &
(_xref.xref); zlog_ref(&_xref, ("%s: failed to load data model: %s"
), __func__, module_name); } while (0)
;
112 exit(1);
113 }
114
115 module = XCALLOC(MTYPE_YANG_MODULE, sizeof(*module))qcalloc(MTYPE_YANG_MODULE, sizeof(*module));
116 module->name = module_name;
117 module->info = module_info;
118
119 if (RB_INSERT(yang_modules, &yang_modules, module)yang_modules_RB_INSERT(&yang_modules, module) != NULL((void*)0)) {
120 flog_err(EC_LIB_YANG_MODULE_LOADED_ALREADY,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: YANG module is loaded already: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOADED_ALREADY)}, }, }
; static const struct xref_logmsg _xref __attribute__( (used)
) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 122
, "lib/yang.c", __func__, }, .fmtstring = ("%s: YANG module is loaded already: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOADED_ALREADY)
, .args = ("__func__, module_name"), }; static const struct xref
* const xref_p_27 __attribute__((used, section("xref_array")
)) = &(_xref.xref); zlog_ref(&_xref, ("%s: YANG module is loaded already: %s"
), __func__, module_name); } while (0)
121 "%s: YANG module is loaded already: %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: YANG module is loaded already: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOADED_ALREADY)}, }, }
; static const struct xref_logmsg _xref __attribute__( (used)
) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 122
, "lib/yang.c", __func__, }, .fmtstring = ("%s: YANG module is loaded already: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOADED_ALREADY)
, .args = ("__func__, module_name"), }; static const struct xref
* const xref_p_27 __attribute__((used, section("xref_array")
)) = &(_xref.xref); zlog_ref(&_xref, ("%s: YANG module is loaded already: %s"
), __func__, module_name); } while (0)
122 module_name)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: YANG module is loaded already: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOADED_ALREADY)}, }, }
; static const struct xref_logmsg _xref __attribute__( (used)
) = { .xref = { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 122
, "lib/yang.c", __func__, }, .fmtstring = ("%s: YANG module is loaded already: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOADED_ALREADY)
, .args = ("__func__, module_name"), }; static const struct xref
* const xref_p_27 __attribute__((used, section("xref_array")
)) = &(_xref.xref); zlog_ref(&_xref, ("%s: YANG module is loaded already: %s"
), __func__, module_name); } while (0)
;
123 exit(1);
124 }
125
126 return module;
127}
128
129void yang_module_load_all(void)
130{
131 for (size_t i = 0; i < array_size(frr_native_modules)(sizeof(frr_native_modules) / sizeof(frr_native_modules[0])); i++)
132 yang_module_load(frr_native_modules[i]);
133}
134
135struct yang_module *yang_module_find(const char *module_name)
136{
137 struct yang_module s;
138
139 s.name = module_name;
140 return RB_FIND(yang_modules, &yang_modules, &s)yang_modules_RB_FIND(&yang_modules, &s);
141}
142
143int yang_snodes_iterate_subtree(const struct lysc_node *snode,
144 const struct lys_module *module,
145 yang_iterate_cb cb, uint16_t flags, void *arg)
146{
147 const struct lysc_node *child;
148 int ret = YANG_ITER_CONTINUE0;
149
150 if (module && snode->module != module)
151 goto next;
152
153 switch (snode->nodetype) {
154 case LYS_CONTAINER0x0001:
155 if (CHECK_FLAG(flags, YANG_ITER_FILTER_NPCONTAINERS)((flags) & (YANG_ITER_FILTER_NPCONTAINERS))) {
156 if (!CHECK_FLAG(snode->flags, LYS_PRESENCE)((snode->flags) & (0x80)))
157 goto next;
158 }
159 break;
160 case LYS_LEAF0x0004:
161 if (CHECK_FLAG(flags, YANG_ITER_FILTER_LIST_KEYS)((flags) & (YANG_ITER_FILTER_LIST_KEYS))) {
162 /* Ignore list keys. */
163 if (lysc_is_key(snode)((!snode || (snode->nodetype != 0x0004) || !(snode->flags
& 0x0100)) ? 0 : 1)
)
164 goto next;
165 }
166 break;
167 case LYS_INPUT0x1000:
168 case LYS_OUTPUT0x2000:
169 if (CHECK_FLAG(flags, YANG_ITER_FILTER_INPUT_OUTPUT)((flags) & (YANG_ITER_FILTER_INPUT_OUTPUT)))
170 goto next;
171 break;
172 default:
173 assert(snode->nodetype != LYS_AUGMENT({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 175, "lib/yang.c"
, __func__, }, .expr = "snode->nodetype != LYS_AUGMENT && snode->nodetype != LYS_GROUPING && snode->nodetype != LYS_USES"
, }; static const struct xref * const xref_p_28 __attribute__
((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect
((snode->nodetype != 0x8000 && snode->nodetype !=
0x4000 && snode->nodetype != 0x0800) ? 0 : 1, 0))
do { _zlog_assert_failed(&_xref, ((void*)0)); } while (snode
->nodetype != 0x8000 && snode->nodetype != 0x4000
&& snode->nodetype != 0x0800); })
174 && snode->nodetype != LYS_GROUPING({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 175, "lib/yang.c"
, __func__, }, .expr = "snode->nodetype != LYS_AUGMENT && snode->nodetype != LYS_GROUPING && snode->nodetype != LYS_USES"
, }; static const struct xref * const xref_p_28 __attribute__
((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect
((snode->nodetype != 0x8000 && snode->nodetype !=
0x4000 && snode->nodetype != 0x0800) ? 0 : 1, 0))
do { _zlog_assert_failed(&_xref, ((void*)0)); } while (snode
->nodetype != 0x8000 && snode->nodetype != 0x4000
&& snode->nodetype != 0x0800); })
175 && snode->nodetype != LYS_USES)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 175, "lib/yang.c"
, __func__, }, .expr = "snode->nodetype != LYS_AUGMENT && snode->nodetype != LYS_GROUPING && snode->nodetype != LYS_USES"
, }; static const struct xref * const xref_p_28 __attribute__
((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect
((snode->nodetype != 0x8000 && snode->nodetype !=
0x4000 && snode->nodetype != 0x0800) ? 0 : 1, 0))
do { _zlog_assert_failed(&_xref, ((void*)0)); } while (snode
->nodetype != 0x8000 && snode->nodetype != 0x4000
&& snode->nodetype != 0x0800); })
;
176 break;
177 }
178
179 ret = (*cb)(snode, arg);
180 if (ret == YANG_ITER_STOP-1)
181 return ret;
182
183next:
184 /*
185 * YANG leafs and leaf-lists can't have child nodes.
186 */
187 if (CHECK_FLAG(snode->nodetype, LYS_LEAF | LYS_LEAFLIST)((snode->nodetype) & (0x0004 | 0x0008)))
188 return YANG_ITER_CONTINUE0;
189
190 LY_LIST_FOR (lysc_node_child(snode), child)for ((child) = (lysc_node_child(snode)); (child); (child) = (
child)->next)
{
191 ret = yang_snodes_iterate_subtree(child, module, cb, flags,
192 arg);
193 if (ret == YANG_ITER_STOP-1)
194 return ret;
195 }
196 return ret;
197}
198
199int yang_snodes_iterate(const struct lys_module *module, yang_iterate_cb cb,
200 uint16_t flags, void *arg)
201{
202 const struct lys_module *module_iter;
203 uint32_t idx = 0;
204 int ret = YANG_ITER_CONTINUE0;
205
206 idx = ly_ctx_internal_modules_count(ly_native_ctx);
207 while ((module_iter = ly_ctx_get_module_iter(ly_native_ctx, &idx))) {
208 struct lysc_node *snode;
209
210 if (!module_iter->implemented)
211 continue;
212
213 LY_LIST_FOR (module_iter->compiled->data, snode)for ((snode) = (module_iter->compiled->data); (snode); (
snode) = (snode)->next)
{
214 ret = yang_snodes_iterate_subtree(snode, module, cb,
215 flags, arg);
216 if (ret == YANG_ITER_STOP-1)
217 return ret;
218 }
219 LY_LIST_FOR (&module_iter->compiled->rpcs->node, snode)for ((snode) = (&module_iter->compiled->rpcs->node
); (snode); (snode) = (snode)->next)
{
220 ret = yang_snodes_iterate_subtree(snode, module, cb,
221 flags, arg);
222 if (ret == YANG_ITER_STOP-1)
223 return ret;
224 }
225 LY_LIST_FOR (&module_iter->compiled->notifs->node, snode)for ((snode) = (&module_iter->compiled->notifs->
node); (snode); (snode) = (snode)->next)
{
226 ret = yang_snodes_iterate_subtree(snode, module, cb,
227 flags, arg);
228 if (ret == YANG_ITER_STOP-1)
229 return ret;
230 }
231 }
232
233 return ret;
234}
235
236void yang_snode_get_path(const struct lysc_node *snode,
237 enum yang_path_type type, char *xpath,
238 size_t xpath_len)
239{
240 switch (type) {
241 case YANG_PATH_SCHEMA:
242 (void)lysc_path(snode, LYSC_PATH_LOG, xpath, xpath_len);
243 break;
244 case YANG_PATH_DATA:
245 (void)lysc_path(snode, LYSC_PATH_DATA, xpath, xpath_len);
246 break;
247 default:
248 flog_err(EC_LIB_DEVELOPMENT, "%s: unknown yang path type: %u",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: unknown yang path type: %u"
), .hashu32 = {(3), (EC_LIB_DEVELOPMENT)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 249, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: unknown yang path type: %u"
), .priority = (3), .ec = (EC_LIB_DEVELOPMENT), .args = ("__func__, type"
), }; static const struct xref * const xref_p_29 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: unknown yang path type: %u"), __func__, type
); } while (0)
249 __func__, type)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: unknown yang path type: %u"
), .hashu32 = {(3), (EC_LIB_DEVELOPMENT)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 249, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: unknown yang path type: %u"
), .priority = (3), .ec = (EC_LIB_DEVELOPMENT), .args = ("__func__, type"
), }; static const struct xref * const xref_p_29 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("%s: unknown yang path type: %u"), __func__, type
); } while (0)
;
250 exit(1);
251 }
252}
253
254struct lysc_node *yang_find_snode(struct ly_ctx *ly_ctx, const char *xpath,
255 uint32_t options)
256{
257 struct lysc_node *snode;
258
259 snode = (struct lysc_node *)lys_find_path(ly_ctx, NULL((void*)0), xpath, 0);
260
261 return snode;
262}
263
264struct lysc_node *yang_snode_real_parent(const struct lysc_node *snode)
265{
266 struct lysc_node *parent = snode->parent;
267
268 while (parent) {
269 switch (parent->nodetype) {
270 case LYS_CONTAINER0x0001:
271 if (CHECK_FLAG(parent->flags, LYS_PRESENCE)((parent->flags) & (0x80)))
272 return parent;
273 break;
274 case LYS_LIST0x0010:
275 return parent;
276 default:
277 break;
278 }
279 parent = parent->parent;
280 }
281
282 return NULL((void*)0);
283}
284
285struct lysc_node *yang_snode_parent_list(const struct lysc_node *snode)
286{
287 struct lysc_node *parent = snode->parent;
288
289 while (parent) {
290 switch (parent->nodetype) {
291 case LYS_LIST0x0010:
292 return parent;
293 default:
294 break;
295 }
296 parent = parent->parent;
297 }
298
299 return NULL((void*)0);
300}
301
302bool_Bool yang_snode_is_typeless_data(const struct lysc_node *snode)
303{
304 const struct lysc_node_leaf *sleaf;
305
306 switch (snode->nodetype) {
307 case LYS_LEAF0x0004:
308 sleaf = (struct lysc_node_leaf *)snode;
309 if (sleaf->type->basetype == LY_TYPE_EMPTY)
310 return true1;
311 return false0;
312 case LYS_LEAFLIST0x0008:
313 return false0;
314 default:
315 return true1;
316 }
317}
318
319const char *yang_snode_get_default(const struct lysc_node *snode)
320{
321 const struct lysc_node_leaf *sleaf;
322
323 switch (snode->nodetype) {
324 case LYS_LEAF0x0004:
325 sleaf = (const struct lysc_node_leaf *)snode;
326 return sleaf->dflt ? lyd_value_get_canonical(sleaf->module->ctx,
327 sleaf->dflt)
328 : NULL((void*)0);
329 case LYS_LEAFLIST0x0008:
330 /* TODO: check leaf-list default values */
331 return NULL((void*)0);
332 default:
333 return NULL((void*)0);
334 }
335}
336
337const struct lysc_type *yang_snode_get_type(const struct lysc_node *snode)
338{
339 struct lysc_node_leaf *sleaf = (struct lysc_node_leaf *)snode;
340 struct lysc_type *type;
341
342 if (!CHECK_FLAG(sleaf->nodetype, LYS_LEAF | LYS_LEAFLIST)((sleaf->nodetype) & (0x0004 | 0x0008)))
343 return NULL((void*)0);
344
345 type = sleaf->type;
346 while (type->basetype == LY_TYPE_LEAFREF)
347 type = ((struct lysc_type_leafref *)type)->realtype;
348
349 return type;
350}
351
352unsigned int yang_snode_num_keys(const struct lysc_node *snode)
353{
354 const struct lysc_node_leaf *skey;
355 uint count = 0;
356
357 if (!CHECK_FLAG(snode->nodetype, LYS_LIST)((snode->nodetype) & (0x0010)))
358 return 0;
359
360 /* Walk list of children */
361 LY_FOR_KEYS (snode, skey)for ((skey) = (const struct lysc_node_leaf *)lysc_node_child(
(snode)); (skey); (skey) = (const struct lysc_node_leaf *)((skey
)->next)) if (!((!skey || (skey->nodetype != 0x0004) ||
!(skey->flags & 0x0100)) ? 0 : 1)) { break; } else
{
362 count++;
363 }
364 return count;
365}
366
367char *yang_dnode_get_path(const struct lyd_node *dnode, char *xpath,
368 size_t xpath_len)
369{
370 return lyd_path(dnode, LYD_PATH_STD, xpath, xpath_len);
371}
372
373struct lyd_node *yang_dnode_get(const struct lyd_node *dnode, const char *xpath)
374{
375 struct ly_set *set = NULL((void*)0);
376 struct lyd_node *dnode_ret = NULL((void*)0);
377
378 /*
379 * XXX a lot of the code uses this for style I guess. It shouldn't, as
380 * it adds to the xpath parsing complexity in libyang.
381 */
382 if (xpath[0] == '.' && xpath[1] == '/')
383 xpath += 2;
384
385 if (lyd_find_xpath(dnode, xpath, &set)) {
386 /*
387 * Commenting out the below assert failure as it crashes mgmtd
388 * when bad xpath is passed.
389 *
390 * assert(0); XXX replicates old libyang1 base code
391 */
392 goto exit;
393 }
394 if (set->count == 0)
395 goto exit;
396
397 if (set->count > 1) {
398 flog_warn(EC_LIB_YANG_DNODE_NOT_FOUND,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .hashu32 = {(4), (EC_LIB_YANG_DNODE_NOT_FOUND)}, }, }; static
const struct xref_logmsg _xref __attribute__( (used)) = { .xref
= { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 400, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .priority = (4), .ec = (EC_LIB_YANG_DNODE_NOT_FOUND), .args
= ("__func__, set->count, xpath"), }; static const struct
xref * const xref_p_30 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), __func__, set->count, xpath); } while (0)
399 "%s: found %u elements (expected 0 or 1) [xpath %s]",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .hashu32 = {(4), (EC_LIB_YANG_DNODE_NOT_FOUND)}, }, }; static
const struct xref_logmsg _xref __attribute__( (used)) = { .xref
= { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 400, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .priority = (4), .ec = (EC_LIB_YANG_DNODE_NOT_FOUND), .args
= ("__func__, set->count, xpath"), }; static const struct
xref * const xref_p_30 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), __func__, set->count, xpath); } while (0)
400 __func__, set->count, xpath)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .hashu32 = {(4), (EC_LIB_YANG_DNODE_NOT_FOUND)}, }, }; static
const struct xref_logmsg _xref __attribute__( (used)) = { .xref
= { (&_xrefdata.xrefdata), (XREFT_LOGMSG), 400, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), .priority = (4), .ec = (EC_LIB_YANG_DNODE_NOT_FOUND), .args
= ("__func__, set->count, xpath"), }; static const struct
xref * const xref_p_30 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: found %u elements (expected 0 or 1) [xpath %s]"
), __func__, set->count, xpath); } while (0)
;
401 goto exit;
402 }
403
404 dnode_ret = set->dnodes[0];
405
406exit:
407 ly_set_free(set, NULL((void*)0));
408
409 return dnode_ret;
410}
411
412struct lyd_node *yang_dnode_getf(const struct lyd_node *dnode,
413 const char *xpath_fmt, ...)
414{
415 va_list ap;
416 char xpath[XPATH_MAXLEN1024];
417
418 va_start(ap, xpath_fmt)__builtin_va_start(ap, xpath_fmt);
419 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
420 va_end(ap)__builtin_va_end(ap);
421
422 return yang_dnode_get(dnode, xpath);
423}
424
425bool_Bool yang_dnode_exists(const struct lyd_node *dnode, const char *xpath)
426{
427 struct ly_set *set = NULL((void*)0);
428 bool_Bool exists = false0;
429
430 if (xpath[0] == '.' && xpath[1] == '/')
431 xpath += 2;
432 if (lyd_find_xpath(dnode, xpath, &set))
433 return false0;
434 exists = set->count > 0;
435 ly_set_free(set, NULL((void*)0));
436 return exists;
437}
438
439bool_Bool yang_dnode_existsf(const struct lyd_node *dnode, const char *xpath_fmt,
440 ...)
441{
442 va_list ap;
443 char xpath[XPATH_MAXLEN1024];
444
445 va_start(ap, xpath_fmt)__builtin_va_start(ap, xpath_fmt);
446 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
447 va_end(ap)__builtin_va_end(ap);
448
449 return yang_dnode_exists(dnode, xpath);
450}
451
452void yang_dnode_iterate(yang_dnode_iter_cb cb, void *arg,
453 const struct lyd_node *dnode, const char *xpath_fmt,
454 ...)
455{
456 va_list ap;
457 char xpath[XPATH_MAXLEN1024];
458 struct ly_set *set;
459
460 va_start(ap, xpath_fmt)__builtin_va_start(ap, xpath_fmt);
461 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
462 va_end(ap)__builtin_va_end(ap);
463
464 if (lyd_find_xpath(dnode, xpath, &set)) {
465 assert(0)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 465, "lib/yang.c"
, __func__, }, .expr = "0", }; static const struct xref * const
xref_p_31 __attribute__((used, section("xref_array"))) = &
(_xref.xref); if (__builtin_expect((0) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while (0); })
; /* XXX libyang2: ly1 code asserted success */
466 return;
467 }
468 for (unsigned int i = 0; i < set->count; i++) {
469 int ret;
470
471 ret = (*cb)(set->dnodes[i], arg);
472 if (ret == YANG_ITER_STOP-1)
473 break;
474 }
475
476 ly_set_free(set, NULL((void*)0));
477}
478
479bool_Bool yang_dnode_is_default(const struct lyd_node *dnode, const char *xpath)
480{
481 const struct lysc_node *snode;
482 struct lysc_node_leaf *sleaf;
483
484 if (xpath)
485 dnode = yang_dnode_get(dnode, xpath);
486
487 assert(dnode)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 487, "lib/yang.c"
, __func__, }, .expr = "dnode", }; static const struct xref *
const xref_p_32 __attribute__((used, section("xref_array")))
= &(_xref.xref); if (__builtin_expect((dnode) ? 0 : 1, 0
)) do { _zlog_assert_failed(&_xref, ((void*)0)); } while (
dnode); })
;
488 snode = dnode->schema;
489 switch (snode->nodetype) {
490 case LYS_LEAF0x0004:
491 sleaf = (struct lysc_node_leaf *)snode;
492 if (sleaf->type->basetype == LY_TYPE_EMPTY)
493 return false0;
494 return lyd_is_default(dnode);
495 case LYS_LEAFLIST0x0008:
496 /* TODO: check leaf-list default values */
497 return false0;
498 case LYS_CONTAINER0x0001:
499 if (CHECK_FLAG(snode->flags, LYS_PRESENCE)((snode->flags) & (0x80)))
500 return false0;
501 return true1;
502 default:
503 return false0;
504 }
505}
506
507bool_Bool yang_dnode_is_defaultf(const struct lyd_node *dnode, const char *xpath_fmt,
508 ...)
509{
510 if (!xpath_fmt)
511 return yang_dnode_is_default(dnode, NULL((void*)0));
512 else {
513 va_list ap;
514 char xpath[XPATH_MAXLEN1024];
515
516 va_start(ap, xpath_fmt)__builtin_va_start(ap, xpath_fmt);
517 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
518 va_end(ap)__builtin_va_end(ap);
519
520 return yang_dnode_is_default(dnode, xpath);
521 }
522}
523
524bool_Bool yang_dnode_is_default_recursive(const struct lyd_node *dnode)
525{
526 struct lyd_node *root, *dnode_iter;
527
528 if (!yang_dnode_is_default(dnode, NULL((void*)0)))
529 return false0;
530
531 if (CHECK_FLAG(dnode->schema->nodetype, LYS_LEAF | LYS_LEAFLIST)((dnode->schema->nodetype) & (0x0004 | 0x0008)))
532 return true1;
533
534 LY_LIST_FOR (lyd_child(dnode), root)for ((root) = (lyd_child(dnode)); (root); (root) = (root)->
next)
{
535 LYD_TREE_DFS_BEGIN (root, dnode_iter){ ly_bool LYD_TREE_DFS_continue = 0; struct lyd_node *LYD_TREE_DFS_next
; for ((dnode_iter) = (LYD_TREE_DFS_next) = (struct lyd_node *
)(root); (dnode_iter); (dnode_iter) = (LYD_TREE_DFS_next), LYD_TREE_DFS_continue
= 0)
{
536 if (!yang_dnode_is_default(dnode_iter, NULL((void*)0)))
537 return false0;
538
539 LYD_TREE_DFS_END(root, dnode_iter)if (LYD_TREE_DFS_continue) { (LYD_TREE_DFS_next) = ((void*)0)
; } else { (LYD_TREE_DFS_next) = lyd_child(dnode_iter); } if (
!(LYD_TREE_DFS_next)) { if ((dnode_iter) == (struct lyd_node *
)(root)) { break; } (LYD_TREE_DFS_next) = (dnode_iter)->next
; } while (!(LYD_TREE_DFS_next)) { (dnode_iter) = (struct lyd_node
*)(dnode_iter)->parent; if ((dnode_iter)->parent == (root
)->parent) { break; } (LYD_TREE_DFS_next) = (dnode_iter)->
next; } }
;
540 }
541 }
542
543 return true1;
544}
545
546void yang_dnode_change_leaf(struct lyd_node *dnode, const char *value)
547{
548 assert(dnode->schema->nodetype == LYS_LEAF)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 548, "lib/yang.c"
, __func__, }, .expr = "dnode->schema->nodetype == LYS_LEAF"
, }; static const struct xref * const xref_p_33 __attribute__
((used, section("xref_array"))) = &(_xref.xref); if (__builtin_expect
((dnode->schema->nodetype == 0x0004) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while (dnode->schema->nodetype
== 0x0004); })
;
549 lyd_change_term(dnode, value);
550}
551
552struct lyd_node *yang_dnode_new(struct ly_ctx *ly_ctx, bool_Bool config_only)
553{
554 struct lyd_node *dnode = NULL((void*)0);
555 int options = config_only ? LYD_VALIDATE_NO_STATE0x0001 : 0;
556
557 if (lyd_validate_all(&dnode, ly_ctx, options, NULL((void*)0)) != 0) {
558 /* Should never happen. */
559 flog_err(EC_LIB_LIBYANG, "%s: lyd_validate() failed", __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: lyd_validate() failed"
), .hashu32 = {(3), (EC_LIB_LIBYANG)}, }, }; static const struct
xref_logmsg _xref __attribute__( (used)) = { .xref = { (&
_xrefdata.xrefdata), (XREFT_LOGMSG), 559, "lib/yang.c", __func__
, }, .fmtstring = ("%s: lyd_validate() failed"), .priority = (
3), .ec = (EC_LIB_LIBYANG), .args = ("__func__"), }; static const
struct xref * const xref_p_34 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: lyd_validate() failed"
), __func__); } while (0)
;
560 exit(1);
561 }
562
563 return dnode;
564}
565
566struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode)
567{
568 struct lyd_node *dup = NULL((void*)0);
569 LY_ERR err;
570 err = lyd_dup_siblings(dnode, NULL((void*)0), LYD_DUP_RECURSIVE0x01, &dup);
571 assert(!err)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 571, "lib/yang.c"
, __func__, }, .expr = "!err", }; static const struct xref * const
xref_p_35 __attribute__((used, section("xref_array"))) = &
(_xref.xref); if (__builtin_expect((!err) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while (!err); })
;
572 return dup;
573}
574
575void yang_dnode_free(struct lyd_node *dnode)
576{
577 while (dnode->parent)
578 dnode = lyd_parent(dnode);
579 lyd_free_all(dnode);
580}
581
582struct yang_data *yang_data_new(const char *xpath, const char *value)
583{
584 struct yang_data *data;
585
586 data = XCALLOC(MTYPE_YANG_DATA, sizeof(*data))qcalloc(MTYPE_YANG_DATA, sizeof(*data));
587 strlcpy(data->xpath, xpath, sizeof(data->xpath));
588 if (value)
589 data->value = strdup(value);
590
591 return data;
592}
593
594void yang_data_free(struct yang_data *data)
595{
596 if (data->value)
597 free(data->value);
598 XFREE(MTYPE_YANG_DATA, data)do { qfree(MTYPE_YANG_DATA, data); data = ((void*)0); } while
(0)
;
599}
600
601struct list *yang_data_list_new(void)
602{
603 struct list *list;
604
605 list = list_new();
606 list->del = (void (*)(void *))yang_data_free;
607
608 return list;
609}
610
611struct yang_data *yang_data_list_find(const struct list *list,
612 const char *xpath_fmt, ...)
613{
614 char xpath[XPATH_MAXLEN1024];
615 struct yang_data *data;
616 struct listnode *node;
617 va_list ap;
618
619 va_start(ap, xpath_fmt)__builtin_va_start(ap, xpath_fmt);
620 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
621 va_end(ap)__builtin_va_end(ap);
622
623 for (ALL_LIST_ELEMENTS_RO(list, node, data)(node) = ((list) ? ((list)->head) : ((void*)0)), ((data) =
((void*)0)); (node) != ((void*)0) && ((data) = ((({ static
const struct xref_assert _xref __attribute__( (used)) = { .xref
= { (((void*)0)), (XREFT_ASSERT), 623, "lib/yang.c", __func__
, }, .expr = "node", }; static const struct xref * const xref_p_36
__attribute__((used, section("xref_array"))) = &(_xref.xref
); if (__builtin_expect((node) ? 0 : 1, 0)) do { _zlog_assert_failed
(&_xref, ((void*)0)); } while (node); }), ({ static const
struct xref_assert _xref __attribute__( (used)) = { .xref = {
(((void*)0)), (XREFT_ASSERT), 623, "lib/yang.c", __func__, }
, .expr = "(node)->data != NULL", }; static const struct xref
* const xref_p_37 __attribute__((used, section("xref_array")
)) = &(_xref.xref); if (__builtin_expect(((node)->data
!= ((void*)0)) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref
, ((void*)0)); } while ((node)->data != ((void*)0)); }), (
node)->data)), 1); (node) = ((node) ? ((node)->next) : (
(void*)0)), ((data) = ((void*)0))
)
624 if (strmatch(data->xpath, xpath)(!strcmp((data->xpath), (xpath))))
625 return data;
626
627 return NULL((void*)0);
628}
629
630/* Make libyang log its errors using FRR logging infrastructure. */
631static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
632{
633 int priority = LOG_ERR3;
634
635 switch (level) {
636 case LY_LLERR:
637 priority = LOG_ERR3;
638 break;
639 case LY_LLWRN:
640 priority = LOG_WARNING4;
641 break;
642 case LY_LLVRB:
643 case LY_LLDBG:
644 priority = LOG_DEBUG7;
645 break;
646 }
647
648 if (path)
649 zlog(priority, "libyang: %s (%s)", msg, path);
650 else
651 zlog(priority, "libyang: %s", msg);
652}
653
654static ssize_t yang_print_darr(void *arg, const void *buf, size_t count)
655{
656 uint8_t *dst = darr_append_n(*(uint8_t **)arg, count)({ uint __len = (((*(uint8_t **)arg) == ((void*)0)) ? 0 : (((
struct darr_metadata *)(*(uint8_t **)arg)) - 1)->len); ({ if
((ssize_t)(((*(uint8_t **)arg) == ((void*)0)) ? 0 : (((struct
darr_metadata *)(*(uint8_t **)arg)) - 1)->cap) < (ssize_t
)(__len + (count))) ({ ((*(uint8_t **)arg)) = __darr_resize((
*(uint8_t **)arg), (__len + (count)), sizeof(((*(uint8_t **)arg
))[0]), MTYPE_DARR); }); (*(uint8_t **)arg); }); (((struct darr_metadata
*)(*(uint8_t **)arg)) - 1)->len = __len + (count); if (0)
memset(&(*(uint8_t **)arg)[__len], 0, (count)*sizeof((*(
uint8_t **)arg)[0])); &(*(uint8_t **)arg)[__len]; })
;
1
Assuming pointer value is null
2
'?' condition is true
3
'?' condition is true
4
Assuming the condition is false
5
Taking false branch
6
Access to field 'len' results in a dereference of a null pointer
657
658 memcpy(dst, buf, count);
659 return count;
660}
661
662LY_ERR yang_print_tree_append(uint8_t **darr, const struct lyd_node *root,
663 LYD_FORMAT format, uint32_t options)
664{
665 LY_ERR err;
666
667 err = lyd_print_clb(yang_print_darr, darr, root, format, options);
668 if (err)
669 zlog_err("Failed to save yang tree: %s", ly_last_errmsg())do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("Failed to save yang tree: %s"
), .hashu32 = {(3), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 669, "lib/yang.c", __func__, }, .fmtstring
= ("Failed to save yang tree: %s"), .priority = (3), .ec = (
0), .args = ("ly_last_errmsg()"), }; static const struct xref
* const xref_p_38 __attribute__((used, section("xref_array")
)) = &(_xref.xref); zlog_ref(&_xref, ("Failed to save yang tree: %s"
), ly_last_errmsg()); } while (0)
;
670 else if (format != LYD_LYB)
671 *darr_append(*darr)({ uint __len = (((*darr) == ((void*)0)) ? 0 : (((struct darr_metadata
*)(*darr)) - 1)->len); ({ if ((ssize_t)(((*darr) == ((void
*)0)) ? 0 : (((struct darr_metadata *)(*darr)) - 1)->cap) <
(ssize_t)(__len + (1))) ({ ((*darr)) = __darr_resize((*darr)
, (__len + (1)), sizeof(((*darr))[0]), MTYPE_DARR); }); (*darr
); }); (((struct darr_metadata *)(*darr)) - 1)->len = __len
+ (1); if (0) memset(&(*darr)[__len], 0, (1)*sizeof((*darr
)[0])); &(*darr)[__len]; })
= 0;
672 return err;
673}
674
675uint8_t *yang_print_tree(const struct lyd_node *root, LYD_FORMAT format,
676 uint32_t options)
677{
678 uint8_t *darr = NULL((void*)0);
679
680 if (yang_print_tree_append(&darr, root, format, options))
681 return NULL((void*)0);
682 return darr;
683}
684
685const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len)
686{
687 struct ly_err_item *ei;
688
689 ei = ly_err_first(ly_ctx);
690 if (!ei)
691 return "";
692
693 strlcpy(buf, "YANG error(s):\n", buf_len);
694 for (; ei; ei = ei->next) {
695 if (ei->path) {
696 strlcat(buf, " Path: ", buf_len);
697 strlcat(buf, ei->path, buf_len);
698 strlcat(buf, "\n", buf_len);
699 }
700 strlcat(buf, " Error: ", buf_len);
701 strlcat(buf, ei->msg, buf_len);
702 strlcat(buf, "\n", buf_len);
703 }
704
705 ly_err_clean(ly_ctx, NULL((void*)0));
706
707 return buf;
708}
709
710void yang_debugging_set(bool_Bool enable)
711{
712 if (enable) {
713 ly_log_level(LY_LLDBG);
714 ly_log_dbg_groups(0xFF);
715 } else {
716 ly_log_level(LY_LLERR);
717 ly_log_dbg_groups(0);
718 }
719}
720
721struct ly_ctx *yang_ctx_new_setup(bool_Bool embedded_modules, bool_Bool explicit_compile)
722{
723 struct ly_ctx *ctx = NULL((void*)0);
724 const char *yang_models_path = YANG_MODELS_PATH"/usr/share/yang";
725 uint options;
726 LY_ERR err;
727
728 if (access(yang_models_path, R_OK4 | X_OK1)) {
729 yang_models_path = NULL((void*)0);
730 if (errno(*__errno_location ()) == ENOENT2)
731 zlog_info("yang model directory \"%s\" does not exist",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("yang model directory \"%s\" does not exist"
), .hashu32 = {(6), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 732, "lib/yang.c", __func__, }, .fmtstring
= ("yang model directory \"%s\" does not exist"), .priority =
(6), .ec = (0), .args = ("\"/usr/share/yang\""), }; static const
struct xref * const xref_p_39 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("yang model directory \"%s\" does not exist"
), "/usr/share/yang"); } while (0)
732 YANG_MODELS_PATH)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("yang model directory \"%s\" does not exist"
), .hashu32 = {(6), (0)}, }, }; static const struct xref_logmsg
_xref __attribute__( (used)) = { .xref = { (&_xrefdata.xrefdata
), (XREFT_LOGMSG), 732, "lib/yang.c", __func__, }, .fmtstring
= ("yang model directory \"%s\" does not exist"), .priority =
(6), .ec = (0), .args = ("\"/usr/share/yang\""), }; static const
struct xref * const xref_p_39 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("yang model directory \"%s\" does not exist"
), "/usr/share/yang"); } while (0)
;
733 else
734 flog_err_sys(EC_LIB_LIBYANG,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("cannot access yang model directory \"%s\""
), .hashu32 = {(3), (EC_LIB_LIBYANG)}, }, }; static const struct
xref_logmsg _xref __attribute__( (used)) = { .xref = { (&
_xrefdata.xrefdata), (XREFT_LOGMSG), 736, "lib/yang.c", __func__
, }, .fmtstring = ("cannot access yang model directory \"%s\""
), .priority = (3), .ec = (EC_LIB_LIBYANG), .args = ("YANG_MODELS_PATH"
), }; static const struct xref * const xref_p_40 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("cannot access yang model directory \"%s\""), "/usr/share/yang"
); } while (0)
735 "cannot access yang model directory \"%s\"",do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("cannot access yang model directory \"%s\""
), .hashu32 = {(3), (EC_LIB_LIBYANG)}, }, }; static const struct
xref_logmsg _xref __attribute__( (used)) = { .xref = { (&
_xrefdata.xrefdata), (XREFT_LOGMSG), 736, "lib/yang.c", __func__
, }, .fmtstring = ("cannot access yang model directory \"%s\""
), .priority = (3), .ec = (EC_LIB_LIBYANG), .args = ("YANG_MODELS_PATH"
), }; static const struct xref * const xref_p_40 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("cannot access yang model directory \"%s\""), "/usr/share/yang"
); } while (0)
736 YANG_MODELS_PATH)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("cannot access yang model directory \"%s\""
), .hashu32 = {(3), (EC_LIB_LIBYANG)}, }, }; static const struct
xref_logmsg _xref __attribute__( (used)) = { .xref = { (&
_xrefdata.xrefdata), (XREFT_LOGMSG), 736, "lib/yang.c", __func__
, }, .fmtstring = ("cannot access yang model directory \"%s\""
), .priority = (3), .ec = (EC_LIB_LIBYANG), .args = ("YANG_MODELS_PATH"
), }; static const struct xref * const xref_p_40 __attribute__
((used, section("xref_array"))) = &(_xref.xref); zlog_ref
(&_xref, ("cannot access yang model directory \"%s\""), "/usr/share/yang"
); } while (0)
;
737 }
738
739 options = LY_CTX_NO_YANGLIBRARY0x04 | LY_CTX_DISABLE_SEARCHDIR_CWD0x10;
740 if (explicit_compile)
741 options |= LY_CTX_EXPLICIT_COMPILE0x80;
742 err = ly_ctx_new(yang_models_path, options, &ctx);
743 if (err)
744 return NULL((void*)0);
745
746 if (embedded_modules)
747 ly_ctx_set_module_imp_clb(ctx, yang_module_imp_clb, NULL((void*)0));
748
749 return ctx;
750}
751
752void yang_init(bool_Bool embedded_modules, bool_Bool defer_compile)
753{
754 /* Initialize libyang global parameters that affect all containers. */
755 ly_set_log_clb(ly_log_cb, 1);
756 ly_log_options(LY_LOLOG0x01 | LY_LOSTORE0x02);
757
758 /* Initialize libyang container for native models. */
759 ly_native_ctx = yang_ctx_new_setup(embedded_modules, defer_compile);
760 if (!ly_native_ctx) {
761 flog_err(EC_LIB_LIBYANG, "%s: ly_ctx_new() failed", __func__)do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: ly_ctx_new() failed"
), .hashu32 = {(3), (EC_LIB_LIBYANG)}, }, }; static const struct
xref_logmsg _xref __attribute__( (used)) = { .xref = { (&
_xrefdata.xrefdata), (XREFT_LOGMSG), 761, "lib/yang.c", __func__
, }, .fmtstring = ("%s: ly_ctx_new() failed"), .priority = (3
), .ec = (EC_LIB_LIBYANG), .args = ("__func__"), }; static const
struct xref * const xref_p_41 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: ly_ctx_new() failed"
), __func__); } while (0)
;
762 exit(1);
763 }
764
765 yang_translator_init();
766}
767
768void yang_init_loading_complete(void)
769{
770 /* Compile everything */
771 if (ly_ctx_compile(ly_native_ctx) != LY_SUCCESS) {
772 flog_err(EC_LIB_YANG_MODULE_LOAD,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to compile loaded modules: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 774, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to compile loaded modules: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, ly_errmsg(ly_native_ctx)"), }; static const struct
xref * const xref_p_42 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: failed to compile loaded modules: %s"
), __func__, ly_errmsg(ly_native_ctx)); } while (0)
773 "%s: failed to compile loaded modules: %s", __func__,do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to compile loaded modules: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 774, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to compile loaded modules: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, ly_errmsg(ly_native_ctx)"), }; static const struct
xref * const xref_p_42 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: failed to compile loaded modules: %s"
), __func__, ly_errmsg(ly_native_ctx)); } while (0)
774 ly_errmsg(ly_native_ctx))do { static struct xrefdata_logmsg _xrefdata = { .xrefdata = {
.xref = ((void*)0), .uid = {}, .hashstr = ("%s: failed to compile loaded modules: %s"
), .hashu32 = {(3), (EC_LIB_YANG_MODULE_LOAD)}, }, }; static const
struct xref_logmsg _xref __attribute__( (used)) = { .xref = {
(&_xrefdata.xrefdata), (XREFT_LOGMSG), 774, "lib/yang.c"
, __func__, }, .fmtstring = ("%s: failed to compile loaded modules: %s"
), .priority = (3), .ec = (EC_LIB_YANG_MODULE_LOAD), .args = (
"__func__, ly_errmsg(ly_native_ctx)"), }; static const struct
xref * const xref_p_42 __attribute__((used, section("xref_array"
))) = &(_xref.xref); zlog_ref(&_xref, ("%s: failed to compile loaded modules: %s"
), __func__, ly_errmsg(ly_native_ctx)); } while (0)
;
775 exit(1);
776 }
777}
778
779void yang_terminate(void)
780{
781 struct yang_module *module;
782
783 yang_translator_terminate();
784
785 while (!RB_EMPTY(yang_modules, &yang_modules)yang_modules_RB_EMPTY(&yang_modules)) {
786 module = RB_ROOT(yang_modules, &yang_modules)yang_modules_RB_ROOT(&yang_modules);
787
788 /*
789 * We shouldn't call ly_ctx_remove_module() here because this
790 * function also removes other modules that depend on it.
791 *
792 * ly_ctx_destroy() will release all memory for us.
793 */
794 RB_REMOVE(yang_modules, &yang_modules, module)yang_modules_RB_REMOVE(&yang_modules, module);
795 XFREE(MTYPE_YANG_MODULE, module)do { qfree(MTYPE_YANG_MODULE, module); module = ((void*)0); }
while (0)
;
796 }
797
798 ly_ctx_destroy(ly_native_ctx);
799}
800
801const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode,
802 const char *name)
803{
804 const struct lyd_node *orig_dnode = dnode;
805
806 while (orig_dnode) {
807 switch (orig_dnode->schema->nodetype) {
808 case LYS_LIST0x0010:
809 case LYS_CONTAINER0x0001:
810 if (!strcmp(orig_dnode->schema->name, name))
811 return orig_dnode;
812 break;
813 default:
814 break;
815 }
816
817 orig_dnode = lyd_parent(orig_dnode);
818 }
819
820 return NULL((void*)0);
821}
822
823bool_Bool yang_is_last_list_dnode(const struct lyd_node *dnode)
824{
825 return (((dnode->next == NULL((void*)0))
826 || (dnode->next
827 && (strcmp(dnode->next->schema->name, dnode->schema->name)
828 != 0)))
829 && dnode->prev
830 && ((dnode->prev == dnode)
831 || (strcmp(dnode->prev->schema->name, dnode->schema->name)
832 != 0)));
833}
834
835bool_Bool yang_is_last_level_dnode(const struct lyd_node *dnode)
836{
837 const struct lyd_node *parent;
838 const struct lyd_node *key_leaf;
839 uint8_t keys_size;
840
841 switch (dnode->schema->nodetype) {
842 case LYS_LIST0x0010:
843 assert(dnode->parent)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 843, "lib/yang.c"
, __func__, }, .expr = "dnode->parent", }; static const struct
xref * const xref_p_43 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect((dnode->parent
) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void*)0
)); } while (dnode->parent); })
;
844 parent = lyd_parent(dnode);
845 uint snode_num_keys = yang_snode_num_keys(parent->schema);
846 /* XXX libyang2: q: really don't understand this code. */
847 key_leaf = dnode->prev;
848 for (keys_size = 1; keys_size < snode_num_keys; keys_size++)
849 key_leaf = key_leaf->prev;
850 if (key_leaf->prev == dnode)
851 return true1;
852 break;
853 case LYS_CONTAINER0x0001:
854 return true1;
855 default:
856 break;
857 }
858
859 return false0;
860}
861
862const struct lyd_node *
863yang_get_subtree_with_no_sibling(const struct lyd_node *dnode)
864{
865 bool_Bool parent = true1;
866 const struct lyd_node *node;
867
868 node = dnode;
869 if (node->schema->nodetype != LYS_LIST0x0010)
870 return node;
871
872 while (parent) {
873 switch (node->schema->nodetype) {
874 case LYS_CONTAINER0x0001:
875 if (!CHECK_FLAG(node->schema->flags, LYS_PRESENCE)((node->schema->flags) & (0x80))) {
876 if (node->parent
877 && (node->parent->schema->module
878 == dnode->schema->module))
879 node = lyd_parent(node);
880 else
881 parent = false0;
882 } else
883 parent = false0;
884 break;
885 case LYS_LIST0x0010:
886 if (yang_is_last_list_dnode(node)
887 && yang_is_last_level_dnode(node)) {
888 if (node->parent
889 && (node->parent->schema->module
890 == dnode->schema->module))
891 node = lyd_parent(node);
892 else
893 parent = false0;
894 } else
895 parent = false0;
896 break;
897 default:
898 parent = false0;
899 break;
900 }
901 }
902 return node;
903}
904
905uint32_t yang_get_list_pos(const struct lyd_node *node)
906{
907 return lyd_list_pos(node);
908}
909
910uint32_t yang_get_list_elements_count(const struct lyd_node *node)
911{
912 unsigned int count;
913 const struct lysc_node *schema;
914
915 if (!node
916 || ((node->schema->nodetype != LYS_LIST0x0010)
917 && (node->schema->nodetype != LYS_LEAFLIST0x0008))) {
918 return 0;
919 }
920
921 schema = node->schema;
922 count = 0;
923 do {
924 if (node->schema == schema)
925 ++count;
926 node = node->next;
927 } while (node);
928 return count;
929}
930
931int yang_get_key_preds(char *s, const struct lysc_node *snode,
932 struct yang_list_keys *keys, ssize_t space)
933{
934 const struct lysc_node_leaf *skey;
935 ssize_t len2, len = 0;
936 ssize_t i = 0;
937
938 LY_FOR_KEYS (snode, skey)for ((skey) = (const struct lysc_node_leaf *)lysc_node_child(
(snode)); (skey); (skey) = (const struct lysc_node_leaf *)((skey
)->next)) if (!((!skey || (skey->nodetype != 0x0004) ||
!(skey->flags & 0x0100)) ? 0 : 1)) { break; } else
{
939 assert(i < keys->num)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 939, "lib/yang.c"
, __func__, }, .expr = "i < keys->num", }; static const
struct xref * const xref_p_44 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect((i < keys->
num) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void
*)0)); } while (i < keys->num); })
;
940 len2 = snprintf(s + len, space - len, "[%s='%s']", skey->name,
941 keys->key[i]);
942 if (len2 > space - len)
943 len = space;
944 else
945 len += len2;
946 i++;
947 }
948
949 assert(i == keys->num)({ static const struct xref_assert _xref __attribute__( (used
)) = { .xref = { (((void*)0)), (XREFT_ASSERT), 949, "lib/yang.c"
, __func__, }, .expr = "i == keys->num", }; static const struct
xref * const xref_p_45 __attribute__((used, section("xref_array"
))) = &(_xref.xref); if (__builtin_expect((i == keys->
num) ? 0 : 1, 0)) do { _zlog_assert_failed(&_xref, ((void
*)0)); } while (i == keys->num); })
;
950 return i;
951}
952
953int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys)
954{
955 struct lyd_node *child = lyd_child(node);
956
957 keys->num = 0;
958 for (; child && lysc_is_key(child->schema)((!child->schema || (child->schema->nodetype != 0x0004
) || !(child->schema->flags & 0x0100)) ? 0 : 1)
; child = child->next) {
959 const char *value = lyd_get_value(child);
960
961 if (!value)
962 return NB_ERR;
963 strlcpy(keys->key[keys->num], value,
964 sizeof(keys->key[keys->num]));
965 keys->num++;
966 }
967 return NB_OK;
968}
969
970LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
971 const struct lysc_node *snode,
972 const struct yang_list_keys *list_keys,
973 struct lyd_node_inner **node)
974{
975 struct lyd_node *pnode = &parent->node;
976 struct lyd_node **nodepp = (struct lyd_node **)node;
977 const char(*keys)[LIST_MAXKEYLEN128] = list_keys->key;
978
979 /*
980 * When
981 * https://github.com/CESNET/libyang/commit/2c1e327c7c2dd3ba12d466a4ebcf62c1c44116c4
982 * is released in libyang we should add a configure.ac check for the
983 * lyd_new_list3 function and use it here.
984 */
985 switch (list_keys->num) {
986 case 0:
987 return lyd_new_list(pnode, snode->module, snode->name, false0,
988 nodepp);
989 case 1:
990 return lyd_new_list(pnode, snode->module, snode->name, false0,
991 nodepp, keys[0]);
992 case 2:
993 return lyd_new_list(pnode, snode->module, snode->name, false0,
994 nodepp, keys[0], keys[1]);
995 case 3:
996 return lyd_new_list(pnode, snode->module, snode->name, false0,
997 nodepp, keys[0], keys[1], keys[2]);
998 case 4:
999 return lyd_new_list(pnode, snode->module, snode->name, false0,
1000 nodepp, keys[0], keys[1], keys[2], keys[3]);
1001 case 5:
1002 return lyd_new_list(pnode, snode->module, snode->name, false0,
1003 nodepp, keys[0], keys[1], keys[2], keys[3],
1004 keys[4]);
1005 case 6:
1006 return lyd_new_list(pnode, snode->module, snode->name, false0,
1007 nodepp, keys[0], keys[1], keys[2], keys[3],
1008 keys[4], keys[5]);
1009 case 7:
1010 return lyd_new_list(pnode, snode->module, snode->name, false0,
1011 nodepp, keys[0], keys[1], keys[2], keys[3],
1012 keys[4], keys[5], keys[6]);
1013 case 8:
1014 return lyd_new_list(pnode, snode->module, snode->name, false0,
1015 nodepp, keys[0], keys[1], keys[2], keys[3],
1016 keys[4], keys[5], keys[6], keys[7]);
1017 }
1018 _Static_assert(LIST_MAXKEYS8 == 8, "max key mismatch in switch unroll");
1019 /*NOTREACHED*/
1020 return LY_EINVAL;
1021}