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