/src/frr/lib/yang_wrappers.c
Line | Count | Source |
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 "base64.h" |
10 | | #include "log.h" |
11 | | #include "lib_errors.h" |
12 | | #include "northbound.h" |
13 | | #include "printfrr.h" |
14 | | #include "nexthop.h" |
15 | | #include "printfrr.h" |
16 | | |
17 | | |
18 | | #define YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt) \ |
19 | 0 | ({ \ |
20 | 0 | va_list __ap; \ |
21 | 0 | va_start(__ap, (xpath_fmt)); \ |
22 | 0 | const struct lyd_value *__dvalue = \ |
23 | 0 | yang_dnode_xpath_get_value(dnode, xpath_fmt, __ap); \ |
24 | 0 | va_end(__ap); \ |
25 | 0 | __dvalue; \ |
26 | 0 | }) |
27 | | |
28 | | #define YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt) \ |
29 | 0 | ({ \ |
30 | 0 | va_list __ap; \ |
31 | 0 | va_start(__ap, (xpath_fmt)); \ |
32 | 0 | const char *__canon = \ |
33 | 0 | yang_dnode_xpath_get_canon(dnode, xpath_fmt, __ap); \ |
34 | 0 | va_end(__ap); \ |
35 | 0 | __canon; \ |
36 | 0 | }) |
37 | | |
38 | | #define YANG_DNODE_GET_ASSERT(dnode, xpath) \ |
39 | 0 | do { \ |
40 | 0 | if ((dnode) == NULL) { \ |
41 | 0 | flog_err(EC_LIB_YANG_DNODE_NOT_FOUND, \ |
42 | 0 | "%s: couldn't find %s", __func__, (xpath)); \ |
43 | 0 | zlog_backtrace(LOG_ERR); \ |
44 | 0 | abort(); \ |
45 | 0 | } \ |
46 | 0 | } while (0) |
47 | | |
48 | | PRINTFRR(2, 0) |
49 | | static inline const char * |
50 | | yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt, |
51 | | va_list ap) |
52 | 0 | { |
53 | 0 | const struct lyd_node_term *__dleaf = |
54 | 0 | (const struct lyd_node_term *)dnode; |
55 | 0 | assert(__dleaf); |
56 | 0 | if (xpath_fmt) { |
57 | 0 | char __xpath[XPATH_MAXLEN]; |
58 | 0 | vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); |
59 | 0 | __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, |
60 | 0 | __xpath); |
61 | 0 | YANG_DNODE_GET_ASSERT(__dleaf, __xpath); |
62 | 0 | } |
63 | 0 | return lyd_get_value(&__dleaf->node); |
64 | 0 | } |
65 | | |
66 | | PRINTFRR(2, 0) |
67 | | static inline const struct lyd_value * |
68 | | yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt, |
69 | | va_list ap) |
70 | 0 | { |
71 | 0 | const struct lyd_node_term *__dleaf = |
72 | 0 | (const struct lyd_node_term *)dnode; |
73 | 0 | assert(__dleaf); |
74 | 0 | if (xpath_fmt) { |
75 | 0 | char __xpath[XPATH_MAXLEN]; |
76 | 0 | vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap); |
77 | 0 | __dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode, |
78 | 0 | __xpath); |
79 | 0 | YANG_DNODE_GET_ASSERT(__dleaf, __xpath); |
80 | 0 | } |
81 | 0 | const struct lyd_value *__dvalue = &__dleaf->value; |
82 | 0 | if (__dvalue->realtype->basetype == LY_TYPE_UNION) |
83 | 0 | __dvalue = &__dvalue->subvalue->value; |
84 | 0 | return __dvalue; |
85 | 0 | } |
86 | | |
87 | | static const char *yang_get_default_value(const char *xpath) |
88 | 0 | { |
89 | 0 | const struct lysc_node *snode; |
90 | 0 | const char *value; |
91 | |
|
92 | 0 | snode = yang_find_snode(ly_native_ctx, xpath, 0); |
93 | 0 | if (snode == NULL) { |
94 | 0 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, |
95 | 0 | "%s: unknown data path: %s", __func__, xpath); |
96 | 0 | zlog_backtrace(LOG_ERR); |
97 | 0 | abort(); |
98 | 0 | } |
99 | | |
100 | 0 | value = yang_snode_get_default(snode); |
101 | 0 | assert(value); |
102 | |
|
103 | 0 | return value; |
104 | 0 | } |
105 | | |
106 | | /* |
107 | | * Primitive type: bool. |
108 | | */ |
109 | | bool yang_str2bool(const char *value) |
110 | 0 | { |
111 | 0 | return strmatch(value, "true"); |
112 | 0 | } |
113 | | |
114 | | struct yang_data *yang_data_new_bool(const char *xpath, bool value) |
115 | 0 | { |
116 | 0 | return yang_data_new(xpath, (value) ? "true" : "false"); |
117 | 0 | } |
118 | | |
119 | | bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt, |
120 | | ...) |
121 | 0 | { |
122 | 0 | const struct lyd_value *dvalue; |
123 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
124 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_BOOL); |
125 | 0 | return dvalue->boolean; |
126 | 0 | } |
127 | | |
128 | | bool yang_get_default_bool(const char *xpath_fmt, ...) |
129 | 0 | { |
130 | 0 | char xpath[XPATH_MAXLEN]; |
131 | 0 | const char *value; |
132 | 0 | va_list ap; |
133 | |
|
134 | 0 | va_start(ap, xpath_fmt); |
135 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
136 | 0 | va_end(ap); |
137 | |
|
138 | 0 | value = yang_get_default_value(xpath); |
139 | 0 | return yang_str2bool(value); |
140 | 0 | } |
141 | | |
142 | | /* |
143 | | * Primitive type: dec64. |
144 | | */ |
145 | | double yang_str2dec64(const char *xpath, const char *value) |
146 | 0 | { |
147 | 0 | double dbl = 0; |
148 | |
|
149 | 0 | if (sscanf(value, "%lf", &dbl) != 1) { |
150 | 0 | flog_err(EC_LIB_YANG_DATA_CONVERT, |
151 | 0 | "%s: couldn't convert string to decimal64 [xpath %s]", |
152 | 0 | __func__, xpath); |
153 | 0 | zlog_backtrace(LOG_ERR); |
154 | 0 | abort(); |
155 | 0 | } |
156 | | |
157 | 0 | return dbl; |
158 | 0 | } |
159 | | |
160 | | struct yang_data *yang_data_new_dec64(const char *xpath, double value) |
161 | 0 | { |
162 | 0 | char value_str[BUFSIZ]; |
163 | |
|
164 | 0 | snprintf(value_str, sizeof(value_str), "%lf", value); |
165 | 0 | return yang_data_new(xpath, value_str); |
166 | 0 | } |
167 | | |
168 | | double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt, |
169 | | ...) |
170 | 0 | { |
171 | 0 | const double denom[19] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, |
172 | 0 | 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, |
173 | 0 | 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, |
174 | 0 | 1e-15, 1e-16, 1e-17, 1e-18}; |
175 | 0 | const struct lysc_type_dec *dectype; |
176 | 0 | const struct lyd_value *dvalue; |
177 | |
|
178 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
179 | 0 | dectype = (const struct lysc_type_dec *)dvalue->realtype; |
180 | 0 | assert(dectype->basetype == LY_TYPE_DEC64); |
181 | 0 | assert(dectype->fraction_digits < sizeof(denom) / sizeof(*denom)); |
182 | 0 | return (double)dvalue->dec64 * denom[dectype->fraction_digits]; |
183 | 0 | } |
184 | | |
185 | | double yang_get_default_dec64(const char *xpath_fmt, ...) |
186 | 0 | { |
187 | 0 | char xpath[XPATH_MAXLEN]; |
188 | 0 | const char *value; |
189 | 0 | va_list ap; |
190 | |
|
191 | 0 | va_start(ap, xpath_fmt); |
192 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
193 | 0 | va_end(ap); |
194 | |
|
195 | 0 | value = yang_get_default_value(xpath); |
196 | 0 | return yang_str2dec64(xpath, value); |
197 | 0 | } |
198 | | |
199 | | /* |
200 | | * Primitive type: enum. |
201 | | */ |
202 | | int yang_str2enum(const char *xpath, const char *value) |
203 | 0 | { |
204 | 0 | const struct lysc_node *snode; |
205 | 0 | const struct lysc_node_leaf *sleaf; |
206 | 0 | const struct lysc_type_enum *type; |
207 | 0 | const struct lysc_type_bitenum_item *enums; |
208 | |
|
209 | 0 | snode = yang_find_snode(ly_native_ctx, xpath, 0); |
210 | 0 | if (snode == NULL) { |
211 | 0 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, |
212 | 0 | "%s: unknown data path: %s", __func__, xpath); |
213 | 0 | zlog_backtrace(LOG_ERR); |
214 | 0 | abort(); |
215 | 0 | } |
216 | | |
217 | 0 | assert(snode->nodetype == LYS_LEAF); |
218 | 0 | sleaf = (const struct lysc_node_leaf *)snode; |
219 | 0 | type = (const struct lysc_type_enum *)sleaf->type; |
220 | 0 | assert(type->basetype == LY_TYPE_ENUM); |
221 | 0 | enums = type->enums; |
222 | 0 | unsigned int count = LY_ARRAY_COUNT(enums); |
223 | 0 | for (unsigned int i = 0; i < count; i++) { |
224 | 0 | if (strmatch(value, enums[i].name)) { |
225 | 0 | assert(CHECK_FLAG(enums[i].flags, LYS_SET_VALUE)); |
226 | 0 | return enums[i].value; |
227 | 0 | } |
228 | 0 | } |
229 | | |
230 | 0 | flog_err(EC_LIB_YANG_DATA_CONVERT, |
231 | 0 | "%s: couldn't convert string to enum [xpath %s]", __func__, |
232 | 0 | xpath); |
233 | 0 | zlog_backtrace(LOG_ERR); |
234 | 0 | abort(); |
235 | 0 | } |
236 | | |
237 | | struct yang_data *yang_data_new_enum(const char *xpath, int value) |
238 | 0 | { |
239 | 0 | const struct lysc_node *snode; |
240 | 0 | const struct lysc_node_leaf *sleaf; |
241 | 0 | const struct lysc_type_enum *type; |
242 | 0 | const struct lysc_type_bitenum_item *enums; |
243 | |
|
244 | 0 | snode = yang_find_snode(ly_native_ctx, xpath, 0); |
245 | 0 | if (snode == NULL) { |
246 | 0 | flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH, |
247 | 0 | "%s: unknown data path: %s", __func__, xpath); |
248 | 0 | zlog_backtrace(LOG_ERR); |
249 | 0 | abort(); |
250 | 0 | } |
251 | | |
252 | 0 | assert(snode->nodetype == LYS_LEAF); |
253 | 0 | sleaf = (const struct lysc_node_leaf *)snode; |
254 | 0 | type = (const struct lysc_type_enum *)sleaf->type; |
255 | 0 | assert(type->basetype == LY_TYPE_ENUM); |
256 | 0 | enums = type->enums; |
257 | 0 | unsigned int count = LY_ARRAY_COUNT(enums); |
258 | 0 | for (unsigned int i = 0; i < count; i++) { |
259 | 0 | if (CHECK_FLAG(enums[i].flags, LYS_SET_VALUE) |
260 | 0 | && value == enums[i].value) |
261 | 0 | return yang_data_new(xpath, enums[i].name); |
262 | 0 | } |
263 | | |
264 | 0 | flog_err(EC_LIB_YANG_DATA_CONVERT, |
265 | 0 | "%s: couldn't convert enum to string [xpath %s]", __func__, |
266 | 0 | xpath); |
267 | 0 | zlog_backtrace(LOG_ERR); |
268 | 0 | abort(); |
269 | 0 | } |
270 | | |
271 | | int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt, |
272 | | ...) |
273 | 0 | { |
274 | 0 | const struct lyd_value *dvalue; |
275 | |
|
276 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
277 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_ENUM); |
278 | 0 | assert(dvalue->enum_item->flags & LYS_SET_VALUE); |
279 | 0 | return dvalue->enum_item->value; |
280 | 0 | } |
281 | | |
282 | | int yang_get_default_enum(const char *xpath_fmt, ...) |
283 | 0 | { |
284 | 0 | char xpath[XPATH_MAXLEN]; |
285 | 0 | const char *value; |
286 | 0 | va_list ap; |
287 | |
|
288 | 0 | va_start(ap, xpath_fmt); |
289 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
290 | 0 | va_end(ap); |
291 | |
|
292 | 0 | value = yang_get_default_value(xpath); |
293 | 0 | return yang_str2enum(xpath, value); |
294 | 0 | } |
295 | | |
296 | | /* |
297 | | * Primitive type: int8. |
298 | | */ |
299 | | int8_t yang_str2int8(const char *value) |
300 | 0 | { |
301 | 0 | return strtol(value, NULL, 10); |
302 | 0 | } |
303 | | |
304 | | struct yang_data *yang_data_new_int8(const char *xpath, int8_t value) |
305 | 0 | { |
306 | 0 | char value_str[BUFSIZ]; |
307 | |
|
308 | 0 | snprintf(value_str, sizeof(value_str), "%d", value); |
309 | 0 | return yang_data_new(xpath, value_str); |
310 | 0 | } |
311 | | |
312 | | int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt, |
313 | | ...) |
314 | 0 | { |
315 | 0 | const struct lyd_value *dvalue; |
316 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
317 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_INT8); |
318 | 0 | return dvalue->int8; |
319 | 0 | } |
320 | | |
321 | | int8_t yang_get_default_int8(const char *xpath_fmt, ...) |
322 | 0 | { |
323 | 0 | char xpath[XPATH_MAXLEN]; |
324 | 0 | const char *value; |
325 | 0 | va_list ap; |
326 | |
|
327 | 0 | va_start(ap, xpath_fmt); |
328 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
329 | 0 | va_end(ap); |
330 | |
|
331 | 0 | value = yang_get_default_value(xpath); |
332 | 0 | return yang_str2int8(value); |
333 | 0 | } |
334 | | |
335 | | /* |
336 | | * Primitive type: int16. |
337 | | */ |
338 | | int16_t yang_str2int16(const char *value) |
339 | 0 | { |
340 | 0 | return strtol(value, NULL, 10); |
341 | 0 | } |
342 | | |
343 | | struct yang_data *yang_data_new_int16(const char *xpath, int16_t value) |
344 | 0 | { |
345 | 0 | char value_str[BUFSIZ]; |
346 | |
|
347 | 0 | snprintf(value_str, sizeof(value_str), "%d", value); |
348 | 0 | return yang_data_new(xpath, value_str); |
349 | 0 | } |
350 | | |
351 | | int16_t yang_dnode_get_int16(const struct lyd_node *dnode, |
352 | | const char *xpath_fmt, ...) |
353 | 0 | { |
354 | 0 | const struct lyd_value *dvalue; |
355 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
356 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_INT16); |
357 | 0 | return dvalue->int16; |
358 | 0 | } |
359 | | |
360 | | int16_t yang_get_default_int16(const char *xpath_fmt, ...) |
361 | 0 | { |
362 | 0 | char xpath[XPATH_MAXLEN]; |
363 | 0 | const char *value; |
364 | 0 | va_list ap; |
365 | |
|
366 | 0 | va_start(ap, xpath_fmt); |
367 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
368 | 0 | va_end(ap); |
369 | |
|
370 | 0 | value = yang_get_default_value(xpath); |
371 | 0 | return yang_str2int16(value); |
372 | 0 | } |
373 | | |
374 | | /* |
375 | | * Primitive type: int32. |
376 | | */ |
377 | | int32_t yang_str2int32(const char *value) |
378 | 0 | { |
379 | 0 | return strtol(value, NULL, 10); |
380 | 0 | } |
381 | | |
382 | | struct yang_data *yang_data_new_int32(const char *xpath, int32_t value) |
383 | 0 | { |
384 | 0 | char value_str[BUFSIZ]; |
385 | |
|
386 | 0 | snprintf(value_str, sizeof(value_str), "%d", value); |
387 | 0 | return yang_data_new(xpath, value_str); |
388 | 0 | } |
389 | | |
390 | | int32_t yang_dnode_get_int32(const struct lyd_node *dnode, |
391 | | const char *xpath_fmt, ...) |
392 | 0 | { |
393 | 0 | const struct lyd_value *dvalue; |
394 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
395 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_INT32); |
396 | 0 | return dvalue->int32; |
397 | 0 | } |
398 | | |
399 | | int32_t yang_get_default_int32(const char *xpath_fmt, ...) |
400 | 0 | { |
401 | 0 | char xpath[XPATH_MAXLEN]; |
402 | 0 | const char *value; |
403 | 0 | va_list ap; |
404 | |
|
405 | 0 | va_start(ap, xpath_fmt); |
406 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
407 | 0 | va_end(ap); |
408 | |
|
409 | 0 | value = yang_get_default_value(xpath); |
410 | 0 | return yang_str2int32(value); |
411 | 0 | } |
412 | | |
413 | | /* |
414 | | * Primitive type: int64. |
415 | | */ |
416 | | int64_t yang_str2int64(const char *value) |
417 | 0 | { |
418 | 0 | return strtoll(value, NULL, 10); |
419 | 0 | } |
420 | | |
421 | | struct yang_data *yang_data_new_int64(const char *xpath, int64_t value) |
422 | 0 | { |
423 | 0 | char value_str[BUFSIZ]; |
424 | |
|
425 | 0 | snprintfrr(value_str, sizeof(value_str), "%" PRId64, value); |
426 | 0 | return yang_data_new(xpath, value_str); |
427 | 0 | } |
428 | | |
429 | | int64_t yang_dnode_get_int64(const struct lyd_node *dnode, |
430 | | const char *xpath_fmt, ...) |
431 | 0 | { |
432 | 0 | const struct lyd_value *dvalue; |
433 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
434 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_INT64); |
435 | 0 | return dvalue->int64; |
436 | 0 | } |
437 | | |
438 | | int64_t yang_get_default_int64(const char *xpath_fmt, ...) |
439 | 0 | { |
440 | 0 | char xpath[XPATH_MAXLEN]; |
441 | 0 | const char *value; |
442 | 0 | va_list ap; |
443 | |
|
444 | 0 | va_start(ap, xpath_fmt); |
445 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
446 | 0 | va_end(ap); |
447 | |
|
448 | 0 | value = yang_get_default_value(xpath); |
449 | 0 | return yang_str2int64(value); |
450 | 0 | } |
451 | | |
452 | | /* |
453 | | * Primitive type: uint8. |
454 | | */ |
455 | | uint8_t yang_str2uint8(const char *value) |
456 | 0 | { |
457 | 0 | return strtoul(value, NULL, 10); |
458 | 0 | } |
459 | | |
460 | | struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value) |
461 | 0 | { |
462 | 0 | char value_str[BUFSIZ]; |
463 | |
|
464 | 0 | snprintf(value_str, sizeof(value_str), "%u", value); |
465 | 0 | return yang_data_new(xpath, value_str); |
466 | 0 | } |
467 | | |
468 | | uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode, |
469 | | const char *xpath_fmt, ...) |
470 | 0 | { |
471 | 0 | const struct lyd_value *dvalue; |
472 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
473 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_UINT8); |
474 | 0 | return dvalue->uint8; |
475 | 0 | } |
476 | | |
477 | | uint8_t yang_get_default_uint8(const char *xpath_fmt, ...) |
478 | 0 | { |
479 | 0 | char xpath[XPATH_MAXLEN]; |
480 | 0 | const char *value; |
481 | 0 | va_list ap; |
482 | |
|
483 | 0 | va_start(ap, xpath_fmt); |
484 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
485 | 0 | va_end(ap); |
486 | |
|
487 | 0 | value = yang_get_default_value(xpath); |
488 | 0 | return yang_str2uint8(value); |
489 | 0 | } |
490 | | |
491 | | /* |
492 | | * Primitive type: uint16. |
493 | | */ |
494 | | uint16_t yang_str2uint16(const char *value) |
495 | 0 | { |
496 | 0 | return strtoul(value, NULL, 10); |
497 | 0 | } |
498 | | |
499 | | struct yang_data *yang_data_new_uint16(const char *xpath, uint16_t value) |
500 | 0 | { |
501 | 0 | char value_str[BUFSIZ]; |
502 | |
|
503 | 0 | snprintf(value_str, sizeof(value_str), "%u", value); |
504 | 0 | return yang_data_new(xpath, value_str); |
505 | 0 | } |
506 | | |
507 | | uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode, |
508 | | const char *xpath_fmt, ...) |
509 | 0 | { |
510 | 0 | const struct lyd_value *dvalue; |
511 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
512 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_UINT16); |
513 | 0 | return dvalue->uint16; |
514 | 0 | } |
515 | | |
516 | | uint16_t yang_get_default_uint16(const char *xpath_fmt, ...) |
517 | 0 | { |
518 | 0 | char xpath[XPATH_MAXLEN]; |
519 | 0 | const char *value; |
520 | 0 | va_list ap; |
521 | |
|
522 | 0 | va_start(ap, xpath_fmt); |
523 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
524 | 0 | va_end(ap); |
525 | |
|
526 | 0 | value = yang_get_default_value(xpath); |
527 | 0 | return yang_str2uint16(value); |
528 | 0 | } |
529 | | |
530 | | /* |
531 | | * Primitive type: uint32. |
532 | | */ |
533 | | uint32_t yang_str2uint32(const char *value) |
534 | 0 | { |
535 | 0 | return strtoul(value, NULL, 10); |
536 | 0 | } |
537 | | |
538 | | struct yang_data *yang_data_new_uint32(const char *xpath, uint32_t value) |
539 | 0 | { |
540 | 0 | char value_str[BUFSIZ]; |
541 | |
|
542 | 0 | snprintf(value_str, sizeof(value_str), "%u", value); |
543 | 0 | return yang_data_new(xpath, value_str); |
544 | 0 | } |
545 | | |
546 | | uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode, |
547 | | const char *xpath_fmt, ...) |
548 | 0 | { |
549 | 0 | const struct lyd_value *dvalue; |
550 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
551 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_UINT32); |
552 | 0 | return dvalue->uint32; |
553 | 0 | } |
554 | | |
555 | | uint32_t yang_get_default_uint32(const char *xpath_fmt, ...) |
556 | 0 | { |
557 | 0 | char xpath[XPATH_MAXLEN]; |
558 | 0 | const char *value; |
559 | 0 | va_list ap; |
560 | |
|
561 | 0 | va_start(ap, xpath_fmt); |
562 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
563 | 0 | va_end(ap); |
564 | |
|
565 | 0 | value = yang_get_default_value(xpath); |
566 | 0 | return yang_str2uint32(value); |
567 | 0 | } |
568 | | |
569 | | /* |
570 | | * Primitive type: uint64. |
571 | | */ |
572 | | uint64_t yang_str2uint64(const char *value) |
573 | 0 | { |
574 | 0 | return strtoull(value, NULL, 10); |
575 | 0 | } |
576 | | |
577 | | struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value) |
578 | 0 | { |
579 | 0 | char value_str[BUFSIZ]; |
580 | |
|
581 | 0 | snprintfrr(value_str, sizeof(value_str), "%" PRIu64, value); |
582 | 0 | return yang_data_new(xpath, value_str); |
583 | 0 | } |
584 | | |
585 | | uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode, |
586 | | const char *xpath_fmt, ...) |
587 | 0 | { |
588 | 0 | const struct lyd_value *dvalue; |
589 | 0 | dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt); |
590 | 0 | assert(dvalue->realtype->basetype == LY_TYPE_UINT64); |
591 | 0 | return dvalue->uint64; |
592 | 0 | } |
593 | | |
594 | | uint64_t yang_get_default_uint64(const char *xpath_fmt, ...) |
595 | 0 | { |
596 | 0 | char xpath[XPATH_MAXLEN]; |
597 | 0 | const char *value; |
598 | 0 | va_list ap; |
599 | |
|
600 | 0 | va_start(ap, xpath_fmt); |
601 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
602 | 0 | va_end(ap); |
603 | |
|
604 | 0 | value = yang_get_default_value(xpath); |
605 | 0 | return yang_str2uint64(value); |
606 | 0 | } |
607 | | |
608 | | /* |
609 | | * Primitive type: string. |
610 | | * |
611 | | * All string wrappers can be used with non-string types. |
612 | | */ |
613 | | struct yang_data *yang_data_new_string(const char *xpath, const char *value) |
614 | 0 | { |
615 | 0 | return yang_data_new(xpath, value); |
616 | 0 | } |
617 | | |
618 | | const char *yang_dnode_get_string(const struct lyd_node *dnode, |
619 | | const char *xpath_fmt, ...) |
620 | 0 | { |
621 | 0 | return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
622 | 0 | } |
623 | | |
624 | | void yang_dnode_get_string_buf(char *buf, size_t size, |
625 | | const struct lyd_node *dnode, |
626 | | const char *xpath_fmt, ...) |
627 | 0 | { |
628 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
629 | 0 | if (strlcpy(buf, canon, size) >= size) { |
630 | 0 | char xpath[XPATH_MAXLEN]; |
631 | |
|
632 | 0 | yang_dnode_get_path(dnode, xpath, sizeof(xpath)); |
633 | 0 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, |
634 | 0 | "%s: value was truncated [xpath %s]", __func__, |
635 | 0 | xpath); |
636 | 0 | } |
637 | 0 | } |
638 | | |
639 | | const char *yang_get_default_string(const char *xpath_fmt, ...) |
640 | 0 | { |
641 | 0 | char xpath[XPATH_MAXLEN]; |
642 | 0 | va_list ap; |
643 | |
|
644 | 0 | va_start(ap, xpath_fmt); |
645 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
646 | 0 | va_end(ap); |
647 | |
|
648 | 0 | return yang_get_default_value(xpath); |
649 | 0 | } |
650 | | |
651 | | void yang_get_default_string_buf(char *buf, size_t size, const char *xpath_fmt, |
652 | | ...) |
653 | 0 | { |
654 | 0 | char xpath[XPATH_MAXLEN]; |
655 | 0 | const char *value; |
656 | 0 | va_list ap; |
657 | |
|
658 | 0 | va_start(ap, xpath_fmt); |
659 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
660 | 0 | va_end(ap); |
661 | |
|
662 | 0 | value = yang_get_default_value(xpath); |
663 | 0 | if (strlcpy(buf, value, size) >= size) |
664 | 0 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, |
665 | 0 | "%s: value was truncated [xpath %s]", __func__, |
666 | 0 | xpath); |
667 | 0 | } |
668 | | |
669 | | /* |
670 | | * Primitive type: binary. |
671 | | */ |
672 | | struct yang_data *yang_data_new_binary(const char *xpath, const char *value, |
673 | | size_t len) |
674 | 0 | { |
675 | 0 | char *value_str; |
676 | 0 | struct base64_encodestate s; |
677 | 0 | int cnt; |
678 | 0 | char *c; |
679 | 0 | struct yang_data *data; |
680 | |
|
681 | 0 | value_str = (char *)malloc(len * 2); |
682 | 0 | base64_init_encodestate(&s); |
683 | 0 | cnt = base64_encode_block(value, len, value_str, &s); |
684 | 0 | c = value_str + cnt; |
685 | 0 | cnt = base64_encode_blockend(c, &s); |
686 | 0 | c += cnt; |
687 | 0 | *c = 0; |
688 | 0 | data = yang_data_new(xpath, value_str); |
689 | 0 | free(value_str); |
690 | 0 | return data; |
691 | 0 | } |
692 | | |
693 | | size_t yang_dnode_get_binary_buf(char *buf, size_t size, |
694 | | const struct lyd_node *dnode, |
695 | | const char *xpath_fmt, ...) |
696 | 0 | { |
697 | 0 | const char *canon; |
698 | 0 | size_t cannon_len; |
699 | 0 | size_t decode_len; |
700 | 0 | size_t ret_len; |
701 | 0 | size_t cnt; |
702 | 0 | char *value_str; |
703 | 0 | struct base64_decodestate s; |
704 | |
|
705 | 0 | canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
706 | 0 | cannon_len = strlen(canon); |
707 | 0 | decode_len = cannon_len + 1; |
708 | 0 | value_str = (char *)malloc(decode_len); |
709 | 0 | base64_init_decodestate(&s); |
710 | 0 | cnt = base64_decode_block(canon, cannon_len, value_str, &s); |
711 | |
|
712 | 0 | ret_len = size > cnt ? cnt : size; |
713 | 0 | memcpy(buf, value_str, ret_len); |
714 | 0 | if (size < cnt) { |
715 | 0 | char xpath[XPATH_MAXLEN]; |
716 | |
|
717 | 0 | yang_dnode_get_path(dnode, xpath, sizeof(xpath)); |
718 | 0 | flog_warn(EC_LIB_YANG_DATA_TRUNCATED, |
719 | 0 | "%s: value was truncated [xpath %s]", __func__, |
720 | 0 | xpath); |
721 | 0 | } |
722 | 0 | free(value_str); |
723 | 0 | return ret_len; |
724 | 0 | } |
725 | | |
726 | | |
727 | | /* |
728 | | * Primitive type: empty. |
729 | | */ |
730 | | struct yang_data *yang_data_new_empty(const char *xpath) |
731 | 0 | { |
732 | 0 | return yang_data_new(xpath, NULL); |
733 | 0 | } |
734 | | |
735 | | bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt, |
736 | | ...) |
737 | 0 | { |
738 | 0 | va_list ap; |
739 | 0 | char xpath[XPATH_MAXLEN]; |
740 | 0 | const struct lyd_node_term *dleaf; |
741 | |
|
742 | 0 | assert(dnode); |
743 | |
|
744 | 0 | va_start(ap, xpath_fmt); |
745 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
746 | 0 | va_end(ap); |
747 | |
|
748 | 0 | dnode = yang_dnode_get(dnode, xpath); |
749 | 0 | if (dnode) { |
750 | 0 | dleaf = (const struct lyd_node_term *)dnode; |
751 | 0 | if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY) |
752 | 0 | return true; |
753 | 0 | } |
754 | | |
755 | 0 | return false; |
756 | 0 | } |
757 | | |
758 | | /* |
759 | | * Derived type: IP prefix. |
760 | | */ |
761 | | void yang_str2prefix(const char *value, union prefixptr prefix) |
762 | 0 | { |
763 | 0 | (void)str2prefix(value, prefix.p); |
764 | 0 | apply_mask(prefix.p); |
765 | 0 | } |
766 | | |
767 | | struct yang_data *yang_data_new_prefix(const char *xpath, |
768 | | union prefixconstptr prefix) |
769 | 0 | { |
770 | 0 | char value_str[PREFIX2STR_BUFFER]; |
771 | |
|
772 | 0 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); |
773 | 0 | return yang_data_new(xpath, value_str); |
774 | 0 | } |
775 | | |
776 | | void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode, |
777 | | const char *xpath_fmt, ...) |
778 | 0 | { |
779 | 0 | const char *canon; |
780 | | /* |
781 | | * Initialize prefix to avoid static analyzer complaints about |
782 | | * uninitialized memory. |
783 | | */ |
784 | 0 | memset(prefix, 0, sizeof(*prefix)); |
785 | | |
786 | | /* XXX ip_prefix is a native type now in ly2, leverage? */ |
787 | 0 | canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
788 | 0 | (void)str2prefix(canon, prefix); |
789 | 0 | } |
790 | | |
791 | | void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...) |
792 | 0 | { |
793 | 0 | char xpath[XPATH_MAXLEN]; |
794 | 0 | const char *value; |
795 | 0 | va_list ap; |
796 | |
|
797 | 0 | va_start(ap, xpath_fmt); |
798 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
799 | 0 | va_end(ap); |
800 | |
|
801 | 0 | value = yang_get_default_value(xpath); |
802 | 0 | yang_str2prefix(value, var); |
803 | 0 | } |
804 | | |
805 | | /* |
806 | | * Derived type: ipv4. |
807 | | */ |
808 | | void yang_str2ipv4(const char *value, struct in_addr *addr) |
809 | 0 | { |
810 | 0 | (void)inet_pton(AF_INET, value, addr); |
811 | 0 | } |
812 | | |
813 | | struct yang_data *yang_data_new_ipv4(const char *xpath, |
814 | | const struct in_addr *addr) |
815 | 0 | { |
816 | 0 | char value_str[INET_ADDRSTRLEN]; |
817 | |
|
818 | 0 | (void)inet_ntop(AF_INET, addr, value_str, sizeof(value_str)); |
819 | 0 | return yang_data_new(xpath, value_str); |
820 | 0 | } |
821 | | |
822 | | void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode, |
823 | | const char *xpath_fmt, ...) |
824 | 0 | { |
825 | | /* XXX libyang2 IPv4 address is a native type now in ly2 */ |
826 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
827 | 0 | (void)inet_pton(AF_INET, canon, addr); |
828 | 0 | } |
829 | | |
830 | | void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...) |
831 | 0 | { |
832 | 0 | char xpath[XPATH_MAXLEN]; |
833 | 0 | const char *value; |
834 | 0 | va_list ap; |
835 | |
|
836 | 0 | va_start(ap, xpath_fmt); |
837 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
838 | 0 | va_end(ap); |
839 | |
|
840 | 0 | value = yang_get_default_value(xpath); |
841 | 0 | yang_str2ipv4(value, var); |
842 | 0 | } |
843 | | |
844 | | /* |
845 | | * Derived type: ipv4p. |
846 | | */ |
847 | | void yang_str2ipv4p(const char *value, union prefixptr prefix) |
848 | 0 | { |
849 | 0 | struct prefix_ipv4 *prefix4 = prefix.p4; |
850 | |
|
851 | 0 | (void)str2prefix_ipv4(value, prefix4); |
852 | 0 | apply_mask_ipv4(prefix4); |
853 | 0 | } |
854 | | |
855 | | struct yang_data *yang_data_new_ipv4p(const char *xpath, |
856 | | union prefixconstptr prefix) |
857 | 0 | { |
858 | 0 | char value_str[PREFIX2STR_BUFFER]; |
859 | |
|
860 | 0 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); |
861 | 0 | return yang_data_new(xpath, value_str); |
862 | 0 | } |
863 | | |
864 | | void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode, |
865 | | const char *xpath_fmt, ...) |
866 | 0 | { |
867 | 0 | struct prefix_ipv4 *prefix4 = prefix.p4; |
868 | | /* XXX libyang2: ipv4/6 address is a native type now in ly2 */ |
869 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
870 | 0 | (void)str2prefix_ipv4(canon, prefix4); |
871 | 0 | } |
872 | | |
873 | | void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...) |
874 | 0 | { |
875 | 0 | char xpath[XPATH_MAXLEN]; |
876 | 0 | const char *value; |
877 | 0 | va_list ap; |
878 | |
|
879 | 0 | va_start(ap, xpath_fmt); |
880 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
881 | 0 | va_end(ap); |
882 | |
|
883 | 0 | value = yang_get_default_value(xpath); |
884 | 0 | yang_str2ipv4p(value, var); |
885 | 0 | } |
886 | | |
887 | | /* |
888 | | * Derived type: ipv6. |
889 | | */ |
890 | | void yang_str2ipv6(const char *value, struct in6_addr *addr) |
891 | 0 | { |
892 | 0 | (void)inet_pton(AF_INET6, value, addr); |
893 | 0 | } |
894 | | |
895 | | struct yang_data *yang_data_new_ipv6(const char *xpath, |
896 | | const struct in6_addr *addr) |
897 | 0 | { |
898 | 0 | char value_str[INET6_ADDRSTRLEN]; |
899 | |
|
900 | 0 | (void)inet_ntop(AF_INET6, addr, value_str, sizeof(value_str)); |
901 | 0 | return yang_data_new(xpath, value_str); |
902 | 0 | } |
903 | | |
904 | | void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode, |
905 | | const char *xpath_fmt, ...) |
906 | 0 | { |
907 | | /* XXX libyang2: IPv6 address is a native type now, leverage. */ |
908 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
909 | 0 | (void)inet_pton(AF_INET6, canon, addr); |
910 | 0 | } |
911 | | |
912 | | void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...) |
913 | 0 | { |
914 | 0 | char xpath[XPATH_MAXLEN]; |
915 | 0 | const char *value; |
916 | 0 | va_list ap; |
917 | |
|
918 | 0 | va_start(ap, xpath_fmt); |
919 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
920 | 0 | va_end(ap); |
921 | |
|
922 | 0 | value = yang_get_default_value(xpath); |
923 | 0 | yang_str2ipv6(value, var); |
924 | 0 | } |
925 | | |
926 | | /* |
927 | | * Derived type: ipv6p. |
928 | | */ |
929 | | void yang_str2ipv6p(const char *value, union prefixptr prefix) |
930 | 0 | { |
931 | 0 | struct prefix_ipv6 *prefix6 = prefix.p6; |
932 | |
|
933 | 0 | (void)str2prefix_ipv6(value, prefix6); |
934 | 0 | apply_mask_ipv6(prefix6); |
935 | 0 | } |
936 | | |
937 | | struct yang_data *yang_data_new_ipv6p(const char *xpath, |
938 | | union prefixconstptr prefix) |
939 | 0 | { |
940 | 0 | char value_str[PREFIX2STR_BUFFER]; |
941 | |
|
942 | 0 | (void)prefix2str(prefix.p, value_str, sizeof(value_str)); |
943 | 0 | return yang_data_new(xpath, value_str); |
944 | 0 | } |
945 | | |
946 | | void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode, |
947 | | const char *xpath_fmt, ...) |
948 | 0 | { |
949 | 0 | struct prefix_ipv6 *prefix6 = prefix.p6; |
950 | | |
951 | | /* XXX IPv6 address is a native type now in ly2 -- can we leverage? */ |
952 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
953 | 0 | (void)str2prefix_ipv6(canon, prefix6); |
954 | 0 | } |
955 | | |
956 | | void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...) |
957 | 0 | { |
958 | 0 | char xpath[XPATH_MAXLEN]; |
959 | 0 | const char *value; |
960 | 0 | va_list ap; |
961 | |
|
962 | 0 | va_start(ap, xpath_fmt); |
963 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
964 | 0 | va_end(ap); |
965 | |
|
966 | 0 | value = yang_get_default_value(xpath); |
967 | 0 | yang_str2ipv6p(value, var); |
968 | 0 | } |
969 | | |
970 | | /* |
971 | | * Derived type: ip. |
972 | | */ |
973 | | void yang_str2ip(const char *value, struct ipaddr *ip) |
974 | 0 | { |
975 | 0 | (void)str2ipaddr(value, ip); |
976 | 0 | } |
977 | | |
978 | | struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr) |
979 | 0 | { |
980 | 0 | size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; |
981 | 0 | char value_str[sz]; |
982 | |
|
983 | 0 | ipaddr2str(addr, value_str, sizeof(value_str)); |
984 | 0 | return yang_data_new(xpath, value_str); |
985 | 0 | } |
986 | | |
987 | | void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode, |
988 | | const char *xpath_fmt, ...) |
989 | 0 | { |
990 | | /* XXX IPv4 address could be a plugin type now in ly2, leverage? */ |
991 | 0 | const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt); |
992 | 0 | (void)str2ipaddr(canon, addr); |
993 | 0 | } |
994 | | |
995 | | void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...) |
996 | 0 | { |
997 | 0 | char xpath[XPATH_MAXLEN]; |
998 | 0 | const char *value; |
999 | 0 | va_list ap; |
1000 | |
|
1001 | 0 | va_start(ap, xpath_fmt); |
1002 | 0 | vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap); |
1003 | 0 | va_end(ap); |
1004 | |
|
1005 | 0 | value = yang_get_default_value(xpath); |
1006 | 0 | yang_str2ip(value, var); |
1007 | 0 | } |
1008 | | |
1009 | | struct yang_data *yang_data_new_mac(const char *xpath, |
1010 | | const struct ethaddr *mac) |
1011 | 0 | { |
1012 | 0 | char value_str[ETHER_ADDR_STRLEN]; |
1013 | |
|
1014 | 0 | prefix_mac2str(mac, value_str, sizeof(value_str)); |
1015 | 0 | return yang_data_new(xpath, value_str); |
1016 | 0 | } |
1017 | | |
1018 | | void yang_str2mac(const char *value, struct ethaddr *mac) |
1019 | 0 | { |
1020 | 0 | (void)prefix_str2mac(value, mac); |
1021 | 0 | } |
1022 | | |
1023 | | struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time) |
1024 | 0 | { |
1025 | 0 | struct tm tm; |
1026 | 0 | char timebuf[MONOTIME_STRLEN]; |
1027 | 0 | struct timeval _time, time_real; |
1028 | 0 | char *ts_dot; |
1029 | 0 | uint16_t buflen; |
1030 | |
|
1031 | 0 | _time.tv_sec = time; |
1032 | 0 | _time.tv_usec = 0; |
1033 | 0 | monotime_to_realtime(&_time, &time_real); |
1034 | |
|
1035 | 0 | gmtime_r(&time_real.tv_sec, &tm); |
1036 | | |
1037 | | /* rfc-3339 format */ |
1038 | 0 | strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm); |
1039 | 0 | buflen = strlen(timebuf); |
1040 | 0 | ts_dot = timebuf + buflen; |
1041 | | |
1042 | | /* microseconds and appends Z */ |
1043 | 0 | snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ", |
1044 | 0 | (unsigned long)time_real.tv_usec); |
1045 | |
|
1046 | 0 | return yang_data_new(xpath, timebuf); |
1047 | 0 | } |
1048 | | |
1049 | | const char *yang_nexthop_type2str(uint32_t ntype) |
1050 | 0 | { |
1051 | 0 | switch (ntype) { |
1052 | 0 | case NEXTHOP_TYPE_IFINDEX: |
1053 | 0 | return "ifindex"; |
1054 | 0 | break; |
1055 | 0 | case NEXTHOP_TYPE_IPV4: |
1056 | 0 | return "ip4"; |
1057 | 0 | break; |
1058 | 0 | case NEXTHOP_TYPE_IPV4_IFINDEX: |
1059 | 0 | return "ip4-ifindex"; |
1060 | 0 | break; |
1061 | 0 | case NEXTHOP_TYPE_IPV6: |
1062 | 0 | return "ip6"; |
1063 | 0 | break; |
1064 | 0 | case NEXTHOP_TYPE_IPV6_IFINDEX: |
1065 | 0 | return "ip6-ifindex"; |
1066 | 0 | break; |
1067 | 0 | case NEXTHOP_TYPE_BLACKHOLE: |
1068 | 0 | return "blackhole"; |
1069 | 0 | break; |
1070 | 0 | default: |
1071 | 0 | return "unknown"; |
1072 | 0 | break; |
1073 | 0 | } |
1074 | 0 | } |
1075 | | |
1076 | | |
1077 | | const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi) |
1078 | 0 | { |
1079 | 0 | if (afi == AFI_IP && safi == SAFI_UNICAST) |
1080 | 0 | return "frr-routing:ipv4-unicast"; |
1081 | 0 | if (afi == AFI_IP6 && safi == SAFI_UNICAST) |
1082 | 0 | return "frr-routing:ipv6-unicast"; |
1083 | 0 | if (afi == AFI_IP && safi == SAFI_MULTICAST) |
1084 | 0 | return "frr-routing:ipv4-multicast"; |
1085 | 0 | if (afi == AFI_IP6 && safi == SAFI_MULTICAST) |
1086 | 0 | return "frr-routing:ipv6-multicast"; |
1087 | 0 | if (afi == AFI_IP && safi == SAFI_MPLS_VPN) |
1088 | 0 | return "frr-routing:l3vpn-ipv4-unicast"; |
1089 | 0 | if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) |
1090 | 0 | return "frr-routing:l3vpn-ipv6-unicast"; |
1091 | 0 | if (afi == AFI_L2VPN && safi == SAFI_EVPN) |
1092 | 0 | return "frr-routing:l2vpn-evpn"; |
1093 | 0 | if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST) |
1094 | 0 | return "frr-routing:ipv4-labeled-unicast"; |
1095 | 0 | if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) |
1096 | 0 | return "frr-routing:ipv6-labeled-unicast"; |
1097 | 0 | if (afi == AFI_IP && safi == SAFI_FLOWSPEC) |
1098 | 0 | return "frr-routing:ipv4-flowspec"; |
1099 | 0 | if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) |
1100 | 0 | return "frr-routing:ipv6-flowspec"; |
1101 | | |
1102 | 0 | return NULL; |
1103 | 0 | } |
1104 | | |
1105 | | void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi) |
1106 | 0 | { |
1107 | 0 | if (strmatch(key, "frr-routing:ipv4-unicast")) { |
1108 | 0 | *afi = AFI_IP; |
1109 | 0 | *safi = SAFI_UNICAST; |
1110 | 0 | } else if (strmatch(key, "frr-routing:ipv6-unicast")) { |
1111 | 0 | *afi = AFI_IP6; |
1112 | 0 | *safi = SAFI_UNICAST; |
1113 | 0 | } else if (strmatch(key, "frr-routing:ipv4-multicast")) { |
1114 | 0 | *afi = AFI_IP; |
1115 | 0 | *safi = SAFI_MULTICAST; |
1116 | 0 | } else if (strmatch(key, "frr-routing:ipv6-multicast")) { |
1117 | 0 | *afi = AFI_IP6; |
1118 | 0 | *safi = SAFI_MULTICAST; |
1119 | 0 | } else if (strmatch(key, "frr-routing:l3vpn-ipv4-unicast")) { |
1120 | 0 | *afi = AFI_IP; |
1121 | 0 | *safi = SAFI_MPLS_VPN; |
1122 | 0 | } else if (strmatch(key, "frr-routing:l3vpn-ipv6-unicast")) { |
1123 | 0 | *afi = AFI_IP6; |
1124 | 0 | *safi = SAFI_MPLS_VPN; |
1125 | 0 | } else if (strmatch(key, "frr-routing:ipv4-labeled-unicast")) { |
1126 | 0 | *afi = AFI_IP; |
1127 | 0 | *safi = SAFI_LABELED_UNICAST; |
1128 | 0 | } else if (strmatch(key, "frr-routing:ipv6-labeled-unicast")) { |
1129 | 0 | *afi = AFI_IP6; |
1130 | 0 | *safi = SAFI_LABELED_UNICAST; |
1131 | 0 | } else if (strmatch(key, "frr-routing:l2vpn-evpn")) { |
1132 | 0 | *afi = AFI_L2VPN; |
1133 | 0 | *safi = SAFI_EVPN; |
1134 | 0 | } else if (strmatch(key, "frr-routing:ipv4-flowspec")) { |
1135 | 0 | *afi = AFI_IP; |
1136 | 0 | *safi = SAFI_FLOWSPEC; |
1137 | 0 | } else if (strmatch(key, "frr-routing:ipv6-flowspec")) { |
1138 | 0 | *afi = AFI_IP6; |
1139 | 0 | *safi = SAFI_FLOWSPEC; |
1140 | 0 | } else { |
1141 | 0 | *afi = AFI_UNSPEC; |
1142 | 0 | *safi = SAFI_UNSPEC; |
1143 | 0 | } |
1144 | 0 | } |