mirror of
				https://git.proxmox.com/git/mirror_frr
				synced 2025-11-04 10:07:04 +00:00 
			
		
		
		
	Ensure that the string has the null terminating character available as well. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
		
			
				
	
	
		
			1156 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1156 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2018  NetDEF, Inc.
 | 
						|
 *                     Renato Westphal
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify it
 | 
						|
 * under the terms of the GNU General Public License as published by the Free
 | 
						|
 * Software Foundation; either version 2 of the License, or (at your option)
 | 
						|
 * any later version.
 | 
						|
 *
 | 
						|
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
						|
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 | 
						|
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 | 
						|
 * more details.
 | 
						|
 *
 | 
						|
 * You should have received a copy of the GNU General Public License along
 | 
						|
 * with this program; see the file COPYING; if not, write to the Free Software
 | 
						|
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 | 
						|
 */
 | 
						|
 | 
						|
#include <zebra.h>
 | 
						|
 | 
						|
#include "base64.h"
 | 
						|
#include "log.h"
 | 
						|
#include "lib_errors.h"
 | 
						|
#include "northbound.h"
 | 
						|
#include "printfrr.h"
 | 
						|
#include "nexthop.h"
 | 
						|
#include "printfrr.h"
 | 
						|
 | 
						|
 | 
						|
#define YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt)                           \
 | 
						|
	({                                                                     \
 | 
						|
		va_list __ap;                                                  \
 | 
						|
		va_start(__ap, (xpath_fmt));                                   \
 | 
						|
		const struct lyd_value *__dvalue =                             \
 | 
						|
			yang_dnode_xpath_get_value(dnode, xpath_fmt, __ap);    \
 | 
						|
		va_end(__ap);                                                  \
 | 
						|
		__dvalue;                                                      \
 | 
						|
	})
 | 
						|
 | 
						|
#define YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt)                           \
 | 
						|
	({                                                                     \
 | 
						|
		va_list __ap;                                                  \
 | 
						|
		va_start(__ap, (xpath_fmt));                                   \
 | 
						|
		const char *__canon =                                          \
 | 
						|
			yang_dnode_xpath_get_canon(dnode, xpath_fmt, __ap);    \
 | 
						|
		va_end(__ap);                                                  \
 | 
						|
		__canon;                                                       \
 | 
						|
	})
 | 
						|
 | 
						|
#define YANG_DNODE_GET_ASSERT(dnode, xpath)                                    \
 | 
						|
	do {                                                                   \
 | 
						|
		if ((dnode) == NULL) {                                         \
 | 
						|
			flog_err(EC_LIB_YANG_DNODE_NOT_FOUND,                  \
 | 
						|
				 "%s: couldn't find %s", __func__, (xpath));   \
 | 
						|
			zlog_backtrace(LOG_ERR);                               \
 | 
						|
			abort();                                               \
 | 
						|
		}                                                              \
 | 
						|
	} while (0)
 | 
						|
 | 
						|
static inline const char *
 | 
						|
yang_dnode_xpath_get_canon(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			   va_list ap)
 | 
						|
{
 | 
						|
	const struct lyd_node_term *__dleaf =
 | 
						|
		(const struct lyd_node_term *)dnode;
 | 
						|
	assert(__dleaf);
 | 
						|
	if (xpath_fmt) {
 | 
						|
		char __xpath[XPATH_MAXLEN];
 | 
						|
		vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap);
 | 
						|
		__dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode,
 | 
						|
								       __xpath);
 | 
						|
		YANG_DNODE_GET_ASSERT(__dleaf, __xpath);
 | 
						|
	}
 | 
						|
	return lyd_get_value(&__dleaf->node);
 | 
						|
}
 | 
						|
 | 
						|
static inline const struct lyd_value *
 | 
						|
yang_dnode_xpath_get_value(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			   va_list ap)
 | 
						|
{
 | 
						|
	const struct lyd_node_term *__dleaf =
 | 
						|
		(const struct lyd_node_term *)dnode;
 | 
						|
	assert(__dleaf);
 | 
						|
	if (xpath_fmt) {
 | 
						|
		char __xpath[XPATH_MAXLEN];
 | 
						|
		vsnprintf(__xpath, sizeof(__xpath), xpath_fmt, ap);
 | 
						|
		__dleaf = (const struct lyd_node_term *)yang_dnode_get(dnode,
 | 
						|
								       __xpath);
 | 
						|
		YANG_DNODE_GET_ASSERT(__dleaf, __xpath);
 | 
						|
	}
 | 
						|
	const struct lyd_value *__dvalue = &__dleaf->value;
 | 
						|
	if (__dvalue->realtype->basetype == LY_TYPE_UNION)
 | 
						|
		__dvalue = &__dvalue->subvalue->value;
 | 
						|
	return __dvalue;
 | 
						|
}
 | 
						|
 | 
						|
static const char *yang_get_default_value(const char *xpath)
 | 
						|
{
 | 
						|
	const struct lysc_node *snode;
 | 
						|
	const char *value;
 | 
						|
 | 
						|
	snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
 | 
						|
	if (snode == NULL) {
 | 
						|
		flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH,
 | 
						|
			 "%s: unknown data path: %s", __func__, xpath);
 | 
						|
		zlog_backtrace(LOG_ERR);
 | 
						|
		abort();
 | 
						|
	}
 | 
						|
 | 
						|
	value = yang_snode_get_default(snode);
 | 
						|
	assert(value);
 | 
						|
 | 
						|
	return value;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: bool.
 | 
						|
 */
 | 
						|
bool yang_str2bool(const char *value)
 | 
						|
{
 | 
						|
	return strmatch(value, "true");
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_bool(const char *xpath, bool value)
 | 
						|
{
 | 
						|
	return yang_data_new(xpath, (value) ? "true" : "false");
 | 
						|
}
 | 
						|
 | 
						|
bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			 ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_BOOL);
 | 
						|
	return dvalue->boolean;
 | 
						|
}
 | 
						|
 | 
						|
bool yang_get_default_bool(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2bool(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: dec64.
 | 
						|
 */
 | 
						|
double yang_str2dec64(const char *xpath, const char *value)
 | 
						|
{
 | 
						|
	double dbl = 0;
 | 
						|
 | 
						|
	if (sscanf(value, "%lf", &dbl) != 1) {
 | 
						|
		flog_err(EC_LIB_YANG_DATA_CONVERT,
 | 
						|
			 "%s: couldn't convert string to decimal64 [xpath %s]",
 | 
						|
			 __func__, xpath);
 | 
						|
		zlog_backtrace(LOG_ERR);
 | 
						|
		abort();
 | 
						|
	}
 | 
						|
 | 
						|
	return dbl;
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_dec64(const char *xpath, double value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%lf", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
double yang_dnode_get_dec64(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			    ...)
 | 
						|
{
 | 
						|
	const double denom[19] = {1e0,   1e-1,  1e-2,  1e-3,  1e-4,
 | 
						|
				  1e-5,  1e-6,  1e-7,  1e-8,  1e-9,
 | 
						|
				  1e-10, 1e-11, 1e-12, 1e-13, 1e-14,
 | 
						|
				  1e-15, 1e-16, 1e-17, 1e-18};
 | 
						|
	const struct lysc_type_dec *dectype;
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	dectype = (const struct lysc_type_dec *)dvalue->realtype;
 | 
						|
	assert(dectype->basetype == LY_TYPE_DEC64);
 | 
						|
	assert(dectype->fraction_digits < sizeof(denom) / sizeof(*denom));
 | 
						|
	return (double)dvalue->dec64 * denom[dectype->fraction_digits];
 | 
						|
}
 | 
						|
 | 
						|
double yang_get_default_dec64(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2dec64(xpath, value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: enum.
 | 
						|
 */
 | 
						|
int yang_str2enum(const char *xpath, const char *value)
 | 
						|
{
 | 
						|
	const struct lysc_node *snode;
 | 
						|
	const struct lysc_node_leaf *sleaf;
 | 
						|
	const struct lysc_type_enum *type;
 | 
						|
	const struct lysc_type_bitenum_item *enums;
 | 
						|
 | 
						|
	snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
 | 
						|
	if (snode == NULL) {
 | 
						|
		flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH,
 | 
						|
			 "%s: unknown data path: %s", __func__, xpath);
 | 
						|
		zlog_backtrace(LOG_ERR);
 | 
						|
		abort();
 | 
						|
	}
 | 
						|
 | 
						|
	assert(snode->nodetype == LYS_LEAF);
 | 
						|
	sleaf = (const struct lysc_node_leaf *)snode;
 | 
						|
	type = (const struct lysc_type_enum *)sleaf->type;
 | 
						|
	assert(type->basetype == LY_TYPE_ENUM);
 | 
						|
	enums = type->enums;
 | 
						|
	unsigned int count = LY_ARRAY_COUNT(enums);
 | 
						|
	for (unsigned int i = 0; i < count; i++) {
 | 
						|
		if (strmatch(value, enums[i].name)) {
 | 
						|
			assert(CHECK_FLAG(enums[i].flags, LYS_SET_VALUE));
 | 
						|
			return enums[i].value;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	flog_err(EC_LIB_YANG_DATA_CONVERT,
 | 
						|
		 "%s: couldn't convert string to enum [xpath %s]", __func__,
 | 
						|
		 xpath);
 | 
						|
	zlog_backtrace(LOG_ERR);
 | 
						|
	abort();
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_enum(const char *xpath, int value)
 | 
						|
{
 | 
						|
	const struct lysc_node *snode;
 | 
						|
	const struct lysc_node_leaf *sleaf;
 | 
						|
	const struct lysc_type_enum *type;
 | 
						|
	const struct lysc_type_bitenum_item *enums;
 | 
						|
 | 
						|
	snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
 | 
						|
	if (snode == NULL) {
 | 
						|
		flog_err(EC_LIB_YANG_UNKNOWN_DATA_PATH,
 | 
						|
			 "%s: unknown data path: %s", __func__, xpath);
 | 
						|
		zlog_backtrace(LOG_ERR);
 | 
						|
		abort();
 | 
						|
	}
 | 
						|
 | 
						|
	assert(snode->nodetype == LYS_LEAF);
 | 
						|
	sleaf = (const struct lysc_node_leaf *)snode;
 | 
						|
	type = (const struct lysc_type_enum *)sleaf->type;
 | 
						|
	assert(type->basetype == LY_TYPE_ENUM);
 | 
						|
	enums = type->enums;
 | 
						|
	unsigned int count = LY_ARRAY_COUNT(enums);
 | 
						|
	for (unsigned int i = 0; i < count; i++) {
 | 
						|
		if (CHECK_FLAG(enums[i].flags, LYS_SET_VALUE)
 | 
						|
		    && value == enums[i].value)
 | 
						|
			return yang_data_new(xpath, enums[i].name);
 | 
						|
	}
 | 
						|
 | 
						|
	flog_err(EC_LIB_YANG_DATA_CONVERT,
 | 
						|
		 "%s: couldn't convert enum to string [xpath %s]", __func__,
 | 
						|
		 xpath);
 | 
						|
	zlog_backtrace(LOG_ERR);
 | 
						|
	abort();
 | 
						|
}
 | 
						|
 | 
						|
int yang_dnode_get_enum(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_ENUM);
 | 
						|
	assert(dvalue->enum_item->flags & LYS_SET_VALUE);
 | 
						|
	return dvalue->enum_item->value;
 | 
						|
}
 | 
						|
 | 
						|
int yang_get_default_enum(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2enum(xpath, value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: int8.
 | 
						|
 */
 | 
						|
int8_t yang_str2int8(const char *value)
 | 
						|
{
 | 
						|
	return strtol(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_int8(const char *xpath, int8_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%d", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
int8_t yang_dnode_get_int8(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			   ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_INT8);
 | 
						|
	return dvalue->int8;
 | 
						|
}
 | 
						|
 | 
						|
int8_t yang_get_default_int8(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2int8(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: int16.
 | 
						|
 */
 | 
						|
int16_t yang_str2int16(const char *value)
 | 
						|
{
 | 
						|
	return strtol(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_int16(const char *xpath, int16_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%d", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
int16_t yang_dnode_get_int16(const struct lyd_node *dnode,
 | 
						|
			     const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_INT16);
 | 
						|
	return dvalue->int16;
 | 
						|
}
 | 
						|
 | 
						|
int16_t yang_get_default_int16(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2int16(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: int32.
 | 
						|
 */
 | 
						|
int32_t yang_str2int32(const char *value)
 | 
						|
{
 | 
						|
	return strtol(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_int32(const char *xpath, int32_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%d", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
int32_t yang_dnode_get_int32(const struct lyd_node *dnode,
 | 
						|
			     const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_INT32);
 | 
						|
	return dvalue->int32;
 | 
						|
}
 | 
						|
 | 
						|
int32_t yang_get_default_int32(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2int32(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: int64.
 | 
						|
 */
 | 
						|
int64_t yang_str2int64(const char *value)
 | 
						|
{
 | 
						|
	return strtoll(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_int64(const char *xpath, int64_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintfrr(value_str, sizeof(value_str), "%" PRId64, value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
int64_t yang_dnode_get_int64(const struct lyd_node *dnode,
 | 
						|
			     const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_INT64);
 | 
						|
	return dvalue->int64;
 | 
						|
}
 | 
						|
 | 
						|
int64_t yang_get_default_int64(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2int64(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: uint8.
 | 
						|
 */
 | 
						|
uint8_t yang_str2uint8(const char *value)
 | 
						|
{
 | 
						|
	return strtoul(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_uint8(const char *xpath, uint8_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%u", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
uint8_t yang_dnode_get_uint8(const struct lyd_node *dnode,
 | 
						|
			     const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_UINT8);
 | 
						|
	return dvalue->uint8;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t yang_get_default_uint8(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2uint8(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: uint16.
 | 
						|
 */
 | 
						|
uint16_t yang_str2uint16(const char *value)
 | 
						|
{
 | 
						|
	return strtoul(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_uint16(const char *xpath, uint16_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%u", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
uint16_t yang_dnode_get_uint16(const struct lyd_node *dnode,
 | 
						|
			       const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_UINT16);
 | 
						|
	return dvalue->uint16;
 | 
						|
}
 | 
						|
 | 
						|
uint16_t yang_get_default_uint16(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2uint16(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: uint32.
 | 
						|
 */
 | 
						|
uint32_t yang_str2uint32(const char *value)
 | 
						|
{
 | 
						|
	return strtoul(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_uint32(const char *xpath, uint32_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintf(value_str, sizeof(value_str), "%u", value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
uint32_t yang_dnode_get_uint32(const struct lyd_node *dnode,
 | 
						|
			       const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_UINT32);
 | 
						|
	return dvalue->uint32;
 | 
						|
}
 | 
						|
 | 
						|
uint32_t yang_get_default_uint32(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2uint32(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: uint64.
 | 
						|
 */
 | 
						|
uint64_t yang_str2uint64(const char *value)
 | 
						|
{
 | 
						|
	return strtoull(value, NULL, 10);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_uint64(const char *xpath, uint64_t value)
 | 
						|
{
 | 
						|
	char value_str[BUFSIZ];
 | 
						|
 | 
						|
	snprintfrr(value_str, sizeof(value_str), "%" PRIu64, value);
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
uint64_t yang_dnode_get_uint64(const struct lyd_node *dnode,
 | 
						|
			       const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const struct lyd_value *dvalue;
 | 
						|
	dvalue = YANG_DNODE_XPATH_GET_VALUE(dnode, xpath_fmt);
 | 
						|
	assert(dvalue->realtype->basetype == LY_TYPE_UINT64);
 | 
						|
	return dvalue->uint64;
 | 
						|
}
 | 
						|
 | 
						|
uint64_t yang_get_default_uint64(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	return yang_str2uint64(value);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: string.
 | 
						|
 *
 | 
						|
 * All string wrappers can be used with non-string types.
 | 
						|
 */
 | 
						|
struct yang_data *yang_data_new_string(const char *xpath, const char *value)
 | 
						|
{
 | 
						|
	return yang_data_new(xpath, value);
 | 
						|
}
 | 
						|
 | 
						|
const char *yang_dnode_get_string(const struct lyd_node *dnode,
 | 
						|
				  const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	return YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_string_buf(char *buf, size_t size,
 | 
						|
			       const struct lyd_node *dnode,
 | 
						|
			       const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	if (strlcpy(buf, canon, size) >= size) {
 | 
						|
		char xpath[XPATH_MAXLEN];
 | 
						|
 | 
						|
		yang_dnode_get_path(dnode, xpath, sizeof(xpath));
 | 
						|
		flog_warn(EC_LIB_YANG_DATA_TRUNCATED,
 | 
						|
			  "%s: value was truncated [xpath %s]", __func__,
 | 
						|
			  xpath);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
const char *yang_get_default_string(const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	return yang_get_default_value(xpath);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_string_buf(char *buf, size_t size, const char *xpath_fmt,
 | 
						|
				 ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	if (strlcpy(buf, value, size) >= size)
 | 
						|
		flog_warn(EC_LIB_YANG_DATA_TRUNCATED,
 | 
						|
			  "%s: value was truncated [xpath %s]", __func__,
 | 
						|
			  xpath);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: binary.
 | 
						|
 */
 | 
						|
struct yang_data *yang_data_new_binary(const char *xpath, const char *value,
 | 
						|
				       size_t len)
 | 
						|
{
 | 
						|
	char *value_str;
 | 
						|
	struct base64_encodestate s;
 | 
						|
	int cnt;
 | 
						|
	char *c;
 | 
						|
	struct yang_data *data;
 | 
						|
 | 
						|
	value_str = (char *)malloc(len * 2);
 | 
						|
	base64_init_encodestate(&s);
 | 
						|
	cnt = base64_encode_block(value, len, value_str, &s);
 | 
						|
	c = value_str + cnt;
 | 
						|
	cnt = base64_encode_blockend(c, &s);
 | 
						|
	c += cnt;
 | 
						|
	*c = 0;
 | 
						|
	data = yang_data_new(xpath, value_str);
 | 
						|
	free(value_str);
 | 
						|
	return data;
 | 
						|
}
 | 
						|
 | 
						|
size_t yang_dnode_get_binary_buf(char *buf, size_t size,
 | 
						|
				 const struct lyd_node *dnode,
 | 
						|
				 const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const char *canon;
 | 
						|
	size_t cannon_len;
 | 
						|
	size_t decode_len;
 | 
						|
	size_t ret_len;
 | 
						|
	size_t cnt;
 | 
						|
	char *value_str;
 | 
						|
	struct base64_decodestate s;
 | 
						|
 | 
						|
	canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	cannon_len = strlen(canon);
 | 
						|
	decode_len = cannon_len + 1;
 | 
						|
	value_str = (char *)malloc(decode_len);
 | 
						|
	base64_init_decodestate(&s);
 | 
						|
	cnt = base64_decode_block(canon, cannon_len, value_str, &s);
 | 
						|
 | 
						|
	ret_len = size > cnt ? cnt : size;
 | 
						|
	memcpy(buf, value_str, ret_len);
 | 
						|
	if (size < cnt) {
 | 
						|
		char xpath[XPATH_MAXLEN];
 | 
						|
 | 
						|
		yang_dnode_get_path(dnode, xpath, sizeof(xpath));
 | 
						|
		flog_warn(EC_LIB_YANG_DATA_TRUNCATED,
 | 
						|
			  "%s: value was truncated [xpath %s]", __func__,
 | 
						|
			  xpath);
 | 
						|
	}
 | 
						|
	free(value_str);
 | 
						|
	return ret_len;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
 * Primitive type: empty.
 | 
						|
 */
 | 
						|
struct yang_data *yang_data_new_empty(const char *xpath)
 | 
						|
{
 | 
						|
	return yang_data_new(xpath, NULL);
 | 
						|
}
 | 
						|
 | 
						|
bool yang_dnode_get_empty(const struct lyd_node *dnode, const char *xpath_fmt,
 | 
						|
			  ...)
 | 
						|
{
 | 
						|
	va_list ap;
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const struct lyd_node_term *dleaf;
 | 
						|
 | 
						|
	assert(dnode);
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	dnode = yang_dnode_get(dnode, xpath);
 | 
						|
	if (dnode) {
 | 
						|
		dleaf = (const struct lyd_node_term *)dnode;
 | 
						|
		if (dleaf->value.realtype->basetype == LY_TYPE_EMPTY)
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: IP prefix.
 | 
						|
 */
 | 
						|
void yang_str2prefix(const char *value, union prefixptr prefix)
 | 
						|
{
 | 
						|
	(void)str2prefix(value, prefix.p);
 | 
						|
	apply_mask(prefix.p);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_prefix(const char *xpath,
 | 
						|
				       union prefixconstptr prefix)
 | 
						|
{
 | 
						|
	char value_str[PREFIX2STR_BUFFER];
 | 
						|
 | 
						|
	(void)prefix2str(prefix.p, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_prefix(struct prefix *prefix, const struct lyd_node *dnode,
 | 
						|
			   const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	const char *canon;
 | 
						|
	/*
 | 
						|
	 * Initialize prefix to avoid static analyzer complaints about
 | 
						|
	 * uninitialized memory.
 | 
						|
	 */
 | 
						|
	memset(prefix, 0, sizeof(*prefix));
 | 
						|
 | 
						|
	/* XXX ip_prefix is a native type now in ly2, leverage? */
 | 
						|
	canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)str2prefix(canon, prefix);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_prefix(union prefixptr var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2prefix(value, var);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: ipv4.
 | 
						|
 */
 | 
						|
void yang_str2ipv4(const char *value, struct in_addr *addr)
 | 
						|
{
 | 
						|
	(void)inet_pton(AF_INET, value, addr);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_ipv4(const char *xpath,
 | 
						|
				     const struct in_addr *addr)
 | 
						|
{
 | 
						|
	char value_str[INET_ADDRSTRLEN];
 | 
						|
 | 
						|
	(void)inet_ntop(AF_INET, addr, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_ipv4(struct in_addr *addr, const struct lyd_node *dnode,
 | 
						|
			 const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	/* XXX libyang2 IPv4 address is a native type now in ly2 */
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)inet_pton(AF_INET, canon, addr);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_ipv4(struct in_addr *var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2ipv4(value, var);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: ipv4p.
 | 
						|
 */
 | 
						|
void yang_str2ipv4p(const char *value, union prefixptr prefix)
 | 
						|
{
 | 
						|
	struct prefix_ipv4 *prefix4 = prefix.p4;
 | 
						|
 | 
						|
	(void)str2prefix_ipv4(value, prefix4);
 | 
						|
	apply_mask_ipv4(prefix4);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_ipv4p(const char *xpath,
 | 
						|
				      union prefixconstptr prefix)
 | 
						|
{
 | 
						|
	char value_str[PREFIX2STR_BUFFER];
 | 
						|
 | 
						|
	(void)prefix2str(prefix.p, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_ipv4p(union prefixptr prefix, const struct lyd_node *dnode,
 | 
						|
			  const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	struct prefix_ipv4 *prefix4 = prefix.p4;
 | 
						|
	/* XXX libyang2: ipv4/6 address is a native type now in ly2 */
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)str2prefix_ipv4(canon, prefix4);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_ipv4p(union prefixptr var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2ipv4p(value, var);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: ipv6.
 | 
						|
 */
 | 
						|
void yang_str2ipv6(const char *value, struct in6_addr *addr)
 | 
						|
{
 | 
						|
	(void)inet_pton(AF_INET6, value, addr);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_ipv6(const char *xpath,
 | 
						|
				     const struct in6_addr *addr)
 | 
						|
{
 | 
						|
	char value_str[INET6_ADDRSTRLEN];
 | 
						|
 | 
						|
	(void)inet_ntop(AF_INET6, addr, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_ipv6(struct in6_addr *addr, const struct lyd_node *dnode,
 | 
						|
			 const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	/* XXX libyang2: IPv6 address is a native type now, leverage. */
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)inet_pton(AF_INET6, canon, addr);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_ipv6(struct in6_addr *var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2ipv6(value, var);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: ipv6p.
 | 
						|
 */
 | 
						|
void yang_str2ipv6p(const char *value, union prefixptr prefix)
 | 
						|
{
 | 
						|
	struct prefix_ipv6 *prefix6 = prefix.p6;
 | 
						|
 | 
						|
	(void)str2prefix_ipv6(value, prefix6);
 | 
						|
	apply_mask_ipv6(prefix6);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_ipv6p(const char *xpath,
 | 
						|
				      union prefixconstptr prefix)
 | 
						|
{
 | 
						|
	char value_str[PREFIX2STR_BUFFER];
 | 
						|
 | 
						|
	(void)prefix2str(prefix.p, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_ipv6p(union prefixptr prefix, const struct lyd_node *dnode,
 | 
						|
			  const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	struct prefix_ipv6 *prefix6 = prefix.p6;
 | 
						|
 | 
						|
	/* XXX IPv6 address is a native type now in ly2 -- can we leverage? */
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)str2prefix_ipv6(canon, prefix6);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_ipv6p(union prefixptr var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2ipv6p(value, var);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Derived type: ip.
 | 
						|
 */
 | 
						|
void yang_str2ip(const char *value, struct ipaddr *ip)
 | 
						|
{
 | 
						|
	(void)str2ipaddr(value, ip);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_ip(const char *xpath, const struct ipaddr *addr)
 | 
						|
{
 | 
						|
	size_t sz = IS_IPADDR_V4(addr) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN;
 | 
						|
	char value_str[sz];
 | 
						|
 | 
						|
	ipaddr2str(addr, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_dnode_get_ip(struct ipaddr *addr, const struct lyd_node *dnode,
 | 
						|
		       const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	/* XXX IPv4 address could be a plugin type now in ly2, leverage? */
 | 
						|
	const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
 | 
						|
	(void)str2ipaddr(canon, addr);
 | 
						|
}
 | 
						|
 | 
						|
void yang_get_default_ip(struct ipaddr *var, const char *xpath_fmt, ...)
 | 
						|
{
 | 
						|
	char xpath[XPATH_MAXLEN];
 | 
						|
	const char *value;
 | 
						|
	va_list ap;
 | 
						|
 | 
						|
	va_start(ap, xpath_fmt);
 | 
						|
	vsnprintf(xpath, sizeof(xpath), xpath_fmt, ap);
 | 
						|
	va_end(ap);
 | 
						|
 | 
						|
	value = yang_get_default_value(xpath);
 | 
						|
	yang_str2ip(value, var);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_mac(const char *xpath,
 | 
						|
				    const struct ethaddr *mac)
 | 
						|
{
 | 
						|
	char value_str[ETHER_ADDR_STRLEN];
 | 
						|
 | 
						|
	prefix_mac2str(mac, value_str, sizeof(value_str));
 | 
						|
	return yang_data_new(xpath, value_str);
 | 
						|
}
 | 
						|
 | 
						|
void yang_str2mac(const char *value, struct ethaddr *mac)
 | 
						|
{
 | 
						|
	(void)prefix_str2mac(value, mac);
 | 
						|
}
 | 
						|
 | 
						|
struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time)
 | 
						|
{
 | 
						|
	struct tm tm;
 | 
						|
	char timebuf[MONOTIME_STRLEN];
 | 
						|
	struct timeval _time, time_real;
 | 
						|
	char *ts_dot;
 | 
						|
	uint16_t buflen;
 | 
						|
 | 
						|
	_time.tv_sec = time;
 | 
						|
	_time.tv_usec = 0;
 | 
						|
	monotime_to_realtime(&_time, &time_real);
 | 
						|
 | 
						|
	gmtime_r(&time_real.tv_sec, &tm);
 | 
						|
 | 
						|
	/* rfc-3339 format */
 | 
						|
	strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm);
 | 
						|
	buflen = strlen(timebuf);
 | 
						|
	ts_dot = timebuf + buflen;
 | 
						|
 | 
						|
	/* microseconds and appends Z */
 | 
						|
	snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ",
 | 
						|
		   (unsigned long)time_real.tv_usec);
 | 
						|
 | 
						|
	return yang_data_new(xpath, timebuf);
 | 
						|
}
 | 
						|
 | 
						|
const char *yang_nexthop_type2str(uint32_t ntype)
 | 
						|
{
 | 
						|
	switch (ntype) {
 | 
						|
	case NEXTHOP_TYPE_IFINDEX:
 | 
						|
		return "ifindex";
 | 
						|
		break;
 | 
						|
	case NEXTHOP_TYPE_IPV4:
 | 
						|
		return "ip4";
 | 
						|
		break;
 | 
						|
	case NEXTHOP_TYPE_IPV4_IFINDEX:
 | 
						|
		return "ip4-ifindex";
 | 
						|
		break;
 | 
						|
	case NEXTHOP_TYPE_IPV6:
 | 
						|
		return "ip6";
 | 
						|
		break;
 | 
						|
	case NEXTHOP_TYPE_IPV6_IFINDEX:
 | 
						|
		return "ip6-ifindex";
 | 
						|
		break;
 | 
						|
	case NEXTHOP_TYPE_BLACKHOLE:
 | 
						|
		return "blackhole";
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		return "unknown";
 | 
						|
		break;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
const char *yang_afi_safi_value2identity(afi_t afi, safi_t safi)
 | 
						|
{
 | 
						|
	if (afi == AFI_IP && safi == SAFI_UNICAST)
 | 
						|
		return "frr-routing:ipv4-unicast";
 | 
						|
	if (afi == AFI_IP6 && safi == SAFI_UNICAST)
 | 
						|
		return "frr-routing:ipv6-unicast";
 | 
						|
	if (afi == AFI_IP && safi == SAFI_MULTICAST)
 | 
						|
		return "frr-routing:ipv4-multicast";
 | 
						|
	if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
 | 
						|
		return "frr-routing:ipv6-multicast";
 | 
						|
	if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
 | 
						|
		return "frr-routing:l3vpn-ipv4-unicast";
 | 
						|
	if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
 | 
						|
		return "frr-routing:l3vpn-ipv6-unicast";
 | 
						|
	if (afi == AFI_L2VPN && safi == SAFI_EVPN)
 | 
						|
		return "frr-routing:l2vpn-evpn";
 | 
						|
	if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
 | 
						|
		return "frr-routing:ipv4-labeled-unicast";
 | 
						|
	if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
 | 
						|
		return "frr-routing:ipv6-labeled-unicast";
 | 
						|
	if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
 | 
						|
		return "frr-routing:ipv4-flowspec";
 | 
						|
	if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
 | 
						|
		return "frr-routing:ipv6-flowspec";
 | 
						|
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
void yang_afi_safi_identity2value(const char *key, afi_t *afi, safi_t *safi)
 | 
						|
{
 | 
						|
	if (strmatch(key, "frr-routing:ipv4-unicast")) {
 | 
						|
		*afi = AFI_IP;
 | 
						|
		*safi = SAFI_UNICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv6-unicast")) {
 | 
						|
		*afi = AFI_IP6;
 | 
						|
		*safi = SAFI_UNICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv4-multicast")) {
 | 
						|
		*afi = AFI_IP;
 | 
						|
		*safi = SAFI_MULTICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv6-multicast")) {
 | 
						|
		*afi = AFI_IP6;
 | 
						|
		*safi = SAFI_MULTICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:l3vpn-ipv4-unicast")) {
 | 
						|
		*afi = AFI_IP;
 | 
						|
		*safi = SAFI_MPLS_VPN;
 | 
						|
	} else if (strmatch(key, "frr-routing:l3vpn-ipv6-unicast")) {
 | 
						|
		*afi = AFI_IP6;
 | 
						|
		*safi = SAFI_MPLS_VPN;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv4-labeled-unicast")) {
 | 
						|
		*afi = AFI_IP;
 | 
						|
		*safi = SAFI_LABELED_UNICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv6-labeled-unicast")) {
 | 
						|
		*afi = AFI_IP6;
 | 
						|
		*safi = SAFI_LABELED_UNICAST;
 | 
						|
	} else if (strmatch(key, "frr-routing:l2vpn-evpn")) {
 | 
						|
		*afi = AFI_L2VPN;
 | 
						|
		*safi = SAFI_EVPN;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv4-flowspec")) {
 | 
						|
		*afi = AFI_IP;
 | 
						|
		*safi = SAFI_FLOWSPEC;
 | 
						|
	} else if (strmatch(key, "frr-routing:ipv6-flowspec")) {
 | 
						|
		*afi = AFI_IP6;
 | 
						|
		*safi = SAFI_FLOWSPEC;
 | 
						|
	} else {
 | 
						|
		*afi = AFI_UNSPEC;
 | 
						|
		*safi = SAFI_UNSPEC;
 | 
						|
	}
 | 
						|
}
 |