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