]> git.proxmox.com Git - mirror_frr.git/blame - lib/yang_wrappers.c
Merge pull request #9846 from idryzhov/lib-zebra-netns
[mirror_frr.git] / lib / yang_wrappers.c
CommitLineData
1c2facd1
RW
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"
566bdaf6 25#include "printfrr.h"
cad46cfd 26#include "nexthop.h"
8d0c8ff5 27#include "printfrr.h"
1c2facd1 28
3bb513c3
CH
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
60static inline const char *
61yang_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
77static inline const struct lyd_value *
78yang_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
1c2facd1
RW
97static const char *yang_get_default_value(const char *xpath)
98{
3bb513c3 99 const struct lysc_node *snode;
1c2facd1
RW
100 const char *value;
101
3bb513c3 102 snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
1c2facd1
RW
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
1c2facd1
RW
116/*
117 * Primitive type: bool.
118 */
119bool yang_str2bool(const char *value)
120{
121 return strmatch(value, "true");
122}
123
124struct yang_data *yang_data_new_bool(const char *xpath, bool value)
125{
d8729f8c 126 return yang_data_new(xpath, (value) ? "true" : "false");
1c2facd1
RW
127}
128
129bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt,
130 ...)
131{
3bb513c3
CH
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;
1c2facd1
RW
136}
137
138bool 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 */
155double 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
170struct 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
178double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt,
179 ...)
180{
3bb513c3
CH
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;
1c2facd1 187
3bb513c3
CH
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];
1c2facd1
RW
193}
194
195double 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 */
212int yang_str2enum(const char *xpath, const char *value)
213{
3bb513c3
CH
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;
1c2facd1 218
3bb513c3 219 snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
1c2facd1
RW
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
3bb513c3
CH
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 }
1c2facd1
RW
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
247struct yang_data *yang_data_new_enum(const char *xpath, int value)
248{
3bb513c3
CH
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;
1c2facd1 253
3bb513c3 254 snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
1c2facd1
RW
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
3bb513c3
CH
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);
1c2facd1
RW
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
281int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt,
282 ...)
283{
3bb513c3 284 const struct lyd_value *dvalue;
1c2facd1 285
3bb513c3
CH
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;
1c2facd1
RW
290}
291
292int 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 */
309int8_t yang_str2int8(const char *value)
310{
311 return strtol(value, NULL, 10);
312}
313
314struct 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
322int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt,
323 ...)
324{
3bb513c3
CH
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;
1c2facd1
RW
329}
330
331int8_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 */
348int16_t yang_str2int16(const char *value)
349{
350 return strtol(value, NULL, 10);
351}
352
353struct 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
361int16_t yang_dnode_get_int16(const struct lyd_node *dnode,
362 const char *xpath_fmt, ...)
363{
3bb513c3
CH
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;
1c2facd1
RW
368}
369
370int16_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 */
387int32_t yang_str2int32(const char *value)
388{
389 return strtol(value, NULL, 10);
390}
391
392struct 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
400int32_t yang_dnode_get_int32(const struct lyd_node *dnode,
401 const char *xpath_fmt, ...)
402{
3bb513c3
CH
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;
1c2facd1
RW
407}
408
409int32_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 */
426int64_t yang_str2int64(const char *value)
427{
428 return strtoll(value, NULL, 10);
429}
430
431struct yang_data *yang_data_new_int64(const char *xpath, int64_t value)
432{
433 char value_str[BUFSIZ];
434
566bdaf6 435 snprintfrr(value_str, sizeof(value_str), "%" PRId64, value);
1c2facd1
RW
436 return yang_data_new(xpath, value_str);
437}
438
439int64_t yang_dnode_get_int64(const struct lyd_node *dnode,
440 const char *xpath_fmt, ...)
441{
3bb513c3
CH
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;
1c2facd1
RW
446}
447
448int64_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 */
465uint8_t yang_str2uint8(const char *value)
466{
467 return strtoul(value, NULL, 10);
468}
469
470struct 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
478uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode,
479 const char *xpath_fmt, ...)
480{
3bb513c3
CH
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;
1c2facd1
RW
485}
486
487uint8_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 */
504uint16_t yang_str2uint16(const char *value)
505{
506 return strtoul(value, NULL, 10);
507}
508
509struct 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
517uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode,
518 const char *xpath_fmt, ...)
519{
3bb513c3
CH
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;
1c2facd1
RW
524}
525
526uint16_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 */
543uint32_t yang_str2uint32(const char *value)
544{
545 return strtoul(value, NULL, 10);
546}
547
548struct 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
556uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode,
557 const char *xpath_fmt, ...)
558{
3bb513c3
CH
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;
1c2facd1
RW
563}
564
565uint32_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 */
582uint64_t yang_str2uint64(const char *value)
583{
584 return strtoull(value, NULL, 10);
585}
586
587struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value)
588{
589 char value_str[BUFSIZ];
590
566bdaf6 591 snprintfrr(value_str, sizeof(value_str), "%" PRIu64, value);
1c2facd1
RW
592 return yang_data_new(xpath, value_str);
593}
594
595uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode,
596 const char *xpath_fmt, ...)
597{
3bb513c3
CH
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;
1c2facd1
RW
602}
603
604uint64_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 */
623struct yang_data *yang_data_new_string(const char *xpath, const char *value)
624{
625 return yang_data_new(xpath, value);
626}
627
628const char *yang_dnode_get_string(const struct lyd_node *dnode,
629 const char *xpath_fmt, ...)
630{
3bb513c3 631 return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
1c2facd1
RW
632}
633
634void yang_dnode_get_string_buf(char *buf, size_t size,
635 const struct lyd_node *dnode,
636 const char *xpath_fmt, ...)
637{
3bb513c3
CH
638 const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
639 if (strlcpy(buf, canon, size) >= size) {
1c2facd1
RW
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
649const 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
661void 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
b71df689
CS
679/*
680 * Primitive type: empty.
681 */
682struct yang_data *yang_data_new_empty(const char *xpath)
683{
684 return yang_data_new(xpath, NULL);
685}
686
47cd2234
CS
687bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt,
688 ...)
689{
690 va_list ap;
691 char xpath[XPATH_MAXLEN];
3bb513c3 692 const struct lyd_node_term *dleaf;
47cd2234
CS
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) {
3bb513c3
CH
702 dleaf = (const struct lyd_node_term *)dnode;
703 if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY)
47cd2234
CS
704 return true;
705 }
706
707 return false;
708}
709
eed84494
RW
710/*
711 * Derived type: IP prefix.
712 */
713void yang_str2prefix(const char *value, union prefixptr prefix)
714{
715 (void)str2prefix(value, prefix.p);
716 apply_mask(prefix.p);
717}
718
719struct 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
46fcb2df 728void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode,
eed84494
RW
729 const char *xpath_fmt, ...)
730{
3bb513c3 731 const char *canon;
46fcb2df
RZ
732 /*
733 * Initialize prefix to avoid static analyzer complaints about
734 * uninitialized memory.
735 */
736 memset(prefix, 0, sizeof(*prefix));
737
3bb513c3
CH
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);
eed84494
RW
741}
742
743void 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
1c2facd1
RW
757/*
758 * Derived type: ipv4.
759 */
760void yang_str2ipv4(const char *value, struct in_addr *addr)
761{
762 (void)inet_pton(AF_INET, value, addr);
763}
764
765struct 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
774void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode,
775 const char *xpath_fmt, ...)
776{
3bb513c3
CH
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);
1c2facd1
RW
780}
781
782void 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 */
799void 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
807struct yang_data *yang_data_new_ipv4p(const char *xpath,
70065793 808 union prefixconstptr prefix)
1c2facd1
RW
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
816void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode,
817 const char *xpath_fmt, ...)
818{
1c2facd1 819 struct prefix_ipv4 *prefix4 = prefix.p4;
3bb513c3
CH
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);
1c2facd1
RW
823}
824
825void 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 */
842void yang_str2ipv6(const char *value, struct in6_addr *addr)
843{
844 (void)inet_pton(AF_INET6, value, addr);
845}
846
847struct 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
856void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode,
857 const char *xpath_fmt, ...)
858{
3bb513c3
CH
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);
1c2facd1
RW
862}
863
864void 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 */
881void 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
889struct yang_data *yang_data_new_ipv6p(const char *xpath,
70065793 890 union prefixconstptr prefix)
1c2facd1
RW
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
898void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode,
899 const char *xpath_fmt, ...)
900{
1c2facd1
RW
901 struct prefix_ipv6 *prefix6 = prefix.p6;
902
3bb513c3
CH
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);
1c2facd1
RW
906}
907
908void 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}
b0584ad3
QY
921
922/*
923 * Derived type: ip.
924 */
925void yang_str2ip(const char *value, struct ipaddr *ip)
926{
927 (void)str2ipaddr(value, ip);
928}
929
930struct 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
939void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
940 const char *xpath_fmt, ...)
941{
3bb513c3
CH
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);
b0584ad3
QY
945}
946
947void 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}
dd9ef518
CS
960
961struct 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
970void yang_str2mac(const char *value, struct ethaddr *mac)
971{
bec74cc8 972 (void)prefix_str2mac(value, mac);
dd9ef518 973}
cad46cfd 974
8d0c8ff5
CS
975struct 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
cad46cfd
CS
1001const 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}
755100ac 1027
1028
1029const 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";
532f9f17
CS
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";
fbace230
CS
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";
755100ac 1053
1054 return NULL;
1055}
1056
1057void 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;
532f9f17
CS
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;
fbace230
CS
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;
755100ac 1092 } else {
1093 *afi = AFI_UNSPEC;
1094 *safi = SAFI_UNSPEC;
1095 }
1096}