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