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