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