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