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