]> git.proxmox.com Git - mirror_frr.git/blob - lib/yang_wrappers.c
Merge pull request #6753 from mjstapp/fix_zebra_backup_sa
[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 /*
796 * Derived type: IP prefix.
797 */
798 void yang_str2prefix(const char *value, union prefixptr prefix)
799 {
800 (void)str2prefix(value, prefix.p);
801 apply_mask(prefix.p);
802 }
803
804 struct yang_data *yang_data_new_prefix(const char *xpath,
805 union prefixconstptr prefix)
806 {
807 char value_str[PREFIX2STR_BUFFER];
808
809 (void)prefix2str(prefix.p, value_str, sizeof(value_str));
810 return yang_data_new(xpath, value_str);
811 }
812
813 void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode,
814 const char *xpath_fmt, ...)
815 {
816 const struct lyd_node_leaf_list *dleaf;
817
818 assert(dnode);
819 if (xpath_fmt) {
820 va_list ap;
821 char xpath[XPATH_MAXLEN];
822
823 va_start(ap, xpath_fmt);
824 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
825 va_end(ap);
826 dnode = yang_dnode_get(dnode, xpath);
827 YANG_DNODE_GET_ASSERT(dnode, xpath);
828 }
829
830 /*
831 * Initialize prefix to avoid static analyzer complaints about
832 * uninitialized memory.
833 */
834 memset(prefix, 0, sizeof(*prefix));
835
836 dleaf = (const struct lyd_node_leaf_list *)dnode;
837 assert(dleaf->value_type == LY_TYPE_STRING);
838 (void)str2prefix(dleaf->value_str, prefix);
839 }
840
841 void yang_get_default_prefix(union prefixptr 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_str2prefix(value, var);
853 }
854
855 /*
856 * Derived type: ipv4.
857 */
858 void yang_str2ipv4(const char *value, struct in_addr *addr)
859 {
860 (void)inet_pton(AF_INET, value, addr);
861 }
862
863 struct yang_data *yang_data_new_ipv4(const char *xpath,
864 const struct in_addr *addr)
865 {
866 char value_str[INET_ADDRSTRLEN];
867
868 (void)inet_ntop(AF_INET, addr, value_str, sizeof(value_str));
869 return yang_data_new(xpath, value_str);
870 }
871
872 void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode,
873 const char *xpath_fmt, ...)
874 {
875 const struct lyd_node_leaf_list *dleaf;
876
877 assert(dnode);
878 if (xpath_fmt) {
879 va_list ap;
880 char xpath[XPATH_MAXLEN];
881
882 va_start(ap, xpath_fmt);
883 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
884 va_end(ap);
885 dnode = yang_dnode_get(dnode, xpath);
886 YANG_DNODE_GET_ASSERT(dnode, xpath);
887 }
888
889 dleaf = (const struct lyd_node_leaf_list *)dnode;
890 assert(dleaf->value_type == LY_TYPE_STRING);
891 (void)inet_pton(AF_INET, dleaf->value_str, addr);
892 }
893
894 void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...)
895 {
896 char xpath[XPATH_MAXLEN];
897 const char *value;
898 va_list ap;
899
900 va_start(ap, xpath_fmt);
901 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
902 va_end(ap);
903
904 value = yang_get_default_value(xpath);
905 yang_str2ipv4(value, var);
906 }
907
908 /*
909 * Derived type: ipv4p.
910 */
911 void yang_str2ipv4p(const char *value, union prefixptr prefix)
912 {
913 struct prefix_ipv4 *prefix4 = prefix.p4;
914
915 (void)str2prefix_ipv4(value, prefix4);
916 apply_mask_ipv4(prefix4);
917 }
918
919 struct yang_data *yang_data_new_ipv4p(const char *xpath,
920 union prefixconstptr prefix)
921 {
922 char value_str[PREFIX2STR_BUFFER];
923
924 (void)prefix2str(prefix.p, value_str, sizeof(value_str));
925 return yang_data_new(xpath, value_str);
926 }
927
928 void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode,
929 const char *xpath_fmt, ...)
930 {
931 const struct lyd_node_leaf_list *dleaf;
932 struct prefix_ipv4 *prefix4 = prefix.p4;
933
934 assert(dnode);
935 if (xpath_fmt) {
936 va_list ap;
937 char xpath[XPATH_MAXLEN];
938
939 va_start(ap, xpath_fmt);
940 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
941 va_end(ap);
942 dnode = yang_dnode_get(dnode, xpath);
943 YANG_DNODE_GET_ASSERT(dnode, xpath);
944 }
945
946 dleaf = (const struct lyd_node_leaf_list *)dnode;
947 assert(dleaf->value_type == LY_TYPE_STRING);
948 (void)str2prefix_ipv4(dleaf->value_str, prefix4);
949 }
950
951 void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...)
952 {
953 char xpath[XPATH_MAXLEN];
954 const char *value;
955 va_list ap;
956
957 va_start(ap, xpath_fmt);
958 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
959 va_end(ap);
960
961 value = yang_get_default_value(xpath);
962 yang_str2ipv4p(value, var);
963 }
964
965 /*
966 * Derived type: ipv6.
967 */
968 void yang_str2ipv6(const char *value, struct in6_addr *addr)
969 {
970 (void)inet_pton(AF_INET6, value, addr);
971 }
972
973 struct yang_data *yang_data_new_ipv6(const char *xpath,
974 const struct in6_addr *addr)
975 {
976 char value_str[INET6_ADDRSTRLEN];
977
978 (void)inet_ntop(AF_INET6, addr, value_str, sizeof(value_str));
979 return yang_data_new(xpath, value_str);
980 }
981
982 void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode,
983 const char *xpath_fmt, ...)
984 {
985 const struct lyd_node_leaf_list *dleaf;
986
987 assert(dnode);
988 if (xpath_fmt) {
989 va_list ap;
990 char xpath[XPATH_MAXLEN];
991
992 va_start(ap, xpath_fmt);
993 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
994 va_end(ap);
995 dnode = yang_dnode_get(dnode, xpath);
996 YANG_DNODE_GET_ASSERT(dnode, xpath);
997 }
998
999 dleaf = (const struct lyd_node_leaf_list *)dnode;
1000 assert(dleaf->value_type == LY_TYPE_STRING);
1001 (void)inet_pton(AF_INET6, dleaf->value_str, addr);
1002 }
1003
1004 void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...)
1005 {
1006 char xpath[XPATH_MAXLEN];
1007 const char *value;
1008 va_list ap;
1009
1010 va_start(ap, xpath_fmt);
1011 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
1012 va_end(ap);
1013
1014 value = yang_get_default_value(xpath);
1015 yang_str2ipv6(value, var);
1016 }
1017
1018 /*
1019 * Derived type: ipv6p.
1020 */
1021 void yang_str2ipv6p(const char *value, union prefixptr prefix)
1022 {
1023 struct prefix_ipv6 *prefix6 = prefix.p6;
1024
1025 (void)str2prefix_ipv6(value, prefix6);
1026 apply_mask_ipv6(prefix6);
1027 }
1028
1029 struct yang_data *yang_data_new_ipv6p(const char *xpath,
1030 union prefixconstptr prefix)
1031 {
1032 char value_str[PREFIX2STR_BUFFER];
1033
1034 (void)prefix2str(prefix.p, value_str, sizeof(value_str));
1035 return yang_data_new(xpath, value_str);
1036 }
1037
1038 void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode,
1039 const char *xpath_fmt, ...)
1040 {
1041 const struct lyd_node_leaf_list *dleaf;
1042 struct prefix_ipv6 *prefix6 = prefix.p6;
1043
1044 assert(dnode);
1045 if (xpath_fmt) {
1046 va_list ap;
1047 char xpath[XPATH_MAXLEN];
1048
1049 va_start(ap, xpath_fmt);
1050 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
1051 va_end(ap);
1052 dnode = yang_dnode_get(dnode, xpath);
1053 YANG_DNODE_GET_ASSERT(dnode, xpath);
1054 }
1055
1056 dleaf = (const struct lyd_node_leaf_list *)dnode;
1057 assert(dleaf->value_type == LY_TYPE_STRING);
1058 (void)str2prefix_ipv6(dleaf->value_str, prefix6);
1059 }
1060
1061 void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...)
1062 {
1063 char xpath[XPATH_MAXLEN];
1064 const char *value;
1065 va_list ap;
1066
1067 va_start(ap, xpath_fmt);
1068 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
1069 va_end(ap);
1070
1071 value = yang_get_default_value(xpath);
1072 yang_str2ipv6p(value, var);
1073 }
1074
1075 /*
1076 * Derived type: ip.
1077 */
1078 void yang_str2ip(const char *value, struct ipaddr *ip)
1079 {
1080 (void)str2ipaddr(value, ip);
1081 }
1082
1083 struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr)
1084 {
1085 size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
1086 char value_str[sz];
1087
1088 ipaddr2str(addr, value_str, sizeof(value_str));
1089 return yang_data_new(xpath, value_str);
1090 }
1091
1092 void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
1093 const char *xpath_fmt, ...)
1094 {
1095 const struct lyd_node_leaf_list *dleaf;
1096
1097 assert(dnode);
1098 if (xpath_fmt) {
1099 va_list ap;
1100 char xpath[XPATH_MAXLEN];
1101
1102 va_start(ap, xpath_fmt);
1103 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
1104 va_end(ap);
1105 dnode = yang_dnode_get(dnode, xpath);
1106 YANG_DNODE_GET_ASSERT(dnode, xpath);
1107 }
1108
1109 dleaf = (const struct lyd_node_leaf_list *)dnode;
1110 assert(dleaf->value_type == LY_TYPE_STRING);
1111 (void)str2ipaddr(dleaf->value_str, addr);
1112 }
1113
1114 void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
1115 {
1116 char xpath[XPATH_MAXLEN];
1117 const char *value;
1118 va_list ap;
1119
1120 va_start(ap, xpath_fmt);
1121 vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
1122 va_end(ap);
1123
1124 value = yang_get_default_value(xpath);
1125 yang_str2ip(value, var);
1126 }
1127
1128 struct yang_data *yang_data_new_mac(const char *xpath,
1129 const struct ethaddr *mac)
1130 {
1131 char value_str[ETHER_ADDR_STRLEN];
1132
1133 prefix_mac2str(mac, value_str, sizeof(value_str));
1134 return yang_data_new(xpath, value_str);
1135 }
1136
1137 void yang_str2mac(const char *value, struct ethaddr *mac)
1138 {
1139 (void)prefix_str2mac(value, mac);
1140 }
1141
1142 struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time)
1143 {
1144 struct tm tm;
1145 char timebuf[MONOTIME_STRLEN];
1146 struct timeval _time, time_real;
1147 char *ts_dot;
1148 uint16_t buflen;
1149
1150 _time.tv_sec = time;
1151 _time.tv_usec = 0;
1152 monotime_to_realtime(&_time, &time_real);
1153
1154 gmtime_r(&time_real.tv_sec, &tm);
1155
1156 /* rfc-3339 format */
1157 strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm);
1158 buflen = strlen(timebuf);
1159 ts_dot = timebuf + buflen;
1160
1161 /* microseconds and appends Z */
1162 snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ",
1163 (unsigned long)time_real.tv_usec);
1164
1165 return yang_data_new(xpath, timebuf);
1166 }
1167
1168 const char *yang_nexthop_type2str(uint32_t ntype)
1169 {
1170 switch (ntype) {
1171 case NEXTHOP_TYPE_IFINDEX:
1172 return "ifindex";
1173 break;
1174 case NEXTHOP_TYPE_IPV4:
1175 return "ip4";
1176 break;
1177 case NEXTHOP_TYPE_IPV4_IFINDEX:
1178 return "ip4-ifindex";
1179 break;
1180 case NEXTHOP_TYPE_IPV6:
1181 return "ip6";
1182 break;
1183 case NEXTHOP_TYPE_IPV6_IFINDEX:
1184 return "ip6-ifindex";
1185 break;
1186 case NEXTHOP_TYPE_BLACKHOLE:
1187 return "blackhole";
1188 break;
1189 default:
1190 return "unknown";
1191 break;
1192 }
1193 }
1194
1195
1196 const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi)
1197 {
1198 if (afi == AFI_IP && safi == SAFI_UNICAST)
1199 return "frr-routing:ipv4-unicast";
1200 if (afi == AFI_IP6 && safi == SAFI_UNICAST)
1201 return "frr-routing:ipv6-unicast";
1202 if (afi == AFI_IP && safi == SAFI_MULTICAST)
1203 return "frr-routing:ipv4-multicast";
1204 if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
1205 return "frr-routing:ipv6-multicast";
1206
1207 return NULL;
1208 }
1209
1210 void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi)
1211 {
1212 if (strmatch(key, "frr-routing:ipv4-unicast")) {
1213 *afi = AFI_IP;
1214 *safi = SAFI_UNICAST;
1215 } else if (strmatch(key, "frr-routing:ipv6-unicast")) {
1216 *afi = AFI_IP6;
1217 *safi = SAFI_UNICAST;
1218 } else if (strmatch(key, "frr-routing:ipv4-multicast")) {
1219 *afi = AFI_IP;
1220 *safi = SAFI_MULTICAST;
1221 } else if (strmatch(key, "frr-routing:ipv6-multicast")) {
1222 *afi = AFI_IP6;
1223 *safi = SAFI_MULTICAST;
1224 } else {
1225 *afi = AFI_UNSPEC;
1226 *safi = SAFI_UNSPEC;
1227 }
1228 }