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