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