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