File: | home/sharpd/frr3/lib/yang.c |
Warning: | line 656, column 17 Access to field 'len' results in a dereference of a null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
16 | DEFINE_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" ); | |||
17 | DEFINE_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. */ | |||
20 | struct ly_ctx *ly_native_ctx; | |||
21 | ||||
22 | static struct yang_module_embed *embeds, **embedupd = &embeds; | |||
23 | ||||
24 | void yang_module_embed(struct yang_module_embed *embed) | |||
25 | { | |||
26 | embed->next = NULL((void*)0); | |||
27 | *embedupd = embed; | |||
28 | embedupd = &embed->next; | |||
29 | } | |||
30 | ||||
31 | static 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 */ | |||
75 | static 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. */ | |||
92 | static 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 | } | |||
97 | RB_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 | ||||
99 | struct yang_modules yang_modules = RB_INITIALIZER(&yang_modules){ { ((void*)0) } }; | |||
100 | ||||
101 | struct 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 | ||||
129 | void 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 | ||||
135 | struct 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 | ||||
143 | int 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 | ||||
183 | next: | |||
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 | ||||
199 | int 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 | ||||
236 | void 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 | ||||
254 | struct 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 | ||||
264 | struct 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 | ||||
285 | struct 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 | ||||
302 | bool_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 | ||||
319 | const 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 | ||||
337 | const 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 | ||||
352 | unsigned 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 | ||||
367 | char *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 | ||||
373 | struct 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 | ||||
406 | exit: | |||
407 | ly_set_free(set, NULL((void*)0)); | |||
408 | ||||
409 | return dnode_ret; | |||
410 | } | |||
411 | ||||
412 | struct 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 | ||||
425 | bool_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 | ||||
439 | bool_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 | ||||
452 | void 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 | ||||
479 | bool_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 | ||||
507 | bool_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 | ||||
524 | bool_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 | ||||
546 | void 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 | ||||
552 | struct 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 | ||||
566 | struct 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 | ||||
575 | void yang_dnode_free(struct lyd_node *dnode) | |||
576 | { | |||
577 | while (dnode->parent) | |||
578 | dnode = lyd_parent(dnode); | |||
579 | lyd_free_all(dnode); | |||
580 | } | |||
581 | ||||
582 | struct 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 | ||||
594 | void 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 | ||||
601 | struct 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 | ||||
611 | struct 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. */ | |||
631 | static 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 | ||||
654 | static 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]; }); | |||
| ||||
| ||||
657 | ||||
658 | memcpy(dst, buf, count); | |||
659 | return count; | |||
660 | } | |||
661 | ||||
662 | LY_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 | ||||
675 | uint8_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 | ||||
685 | const 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 | ||||
710 | void 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 | ||||
721 | struct 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 | ||||
752 | void 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 | ||||
768 | void 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 | ||||
779 | void 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 | ||||
801 | const 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 | ||||
823 | bool_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 | ||||
835 | bool_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 | ||||
862 | const struct lyd_node * | |||
863 | yang_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 | ||||
905 | uint32_t yang_get_list_pos(const struct lyd_node *node) | |||
906 | { | |||
907 | return lyd_list_pos(node); | |||
908 | } | |||
909 | ||||
910 | uint32_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 | ||||
931 | int 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 | ||||
953 | int 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 | ||||
970 | LY_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 | } |