The libconfd
library manages data values
such as elements received over the NETCONF protocol. This man page
describes how these values as well as the XML paths
(confd_hkeypath_t) identifying the values are
represented in the C language.
The following enum
defines the different
types. These are used to represent data model types from several
different sources - see the section DATA MODEL TYPES
at the end of this manual page for a full specification of how the
data model types map to these types.
enum confd_vtype { C_NOEXISTS = 1, /* end marker */ C_XMLTAG = 2, /* struct xml_tag */ C_SYMBOL = 3, /* not yet used */ C_STR = 4, /* NUL-terminated strings */ C_BUF = 5, /* confd_buf_t (string ...) */ C_INT8 = 6, /* int8_t (int8) */ C_INT16 = 7, /* int16_t (int16) */ C_INT32 = 8, /* int32_t (int32) */ C_INT64 = 9, /* int64_t (int64) */ C_UINT8 = 10, /* u_int8_t (uint8) */ C_UINT16 = 11, /* u_int16_t (uint16) */ C_UINT32 = 12, /* u_int32_t (uint32) */ C_UINT64 = 13, /* u_int64_t (uint64) */ C_DOUBLE = 14, /* double (xs:float,xs:double) */ C_IPV4 = 15, /* struct in_addr in NBO */ /* (inet:ipv4-address) */ C_IPV6 = 16, /* struct in6_addr in NBO */ /* (inet:ipv6-address) */ C_BOOL = 17, /* int (boolean) */ C_QNAME = 18, /* struct confd_qname (xs:QName) */ C_DATETIME = 19, /* struct confd_datetime */ /* (yang:date-and-time) */ C_DATE = 20, /* struct confd_date (xs:date) */ C_TIME = 23, /* struct confd_time (xs:time) */ C_DURATION = 27, /* struct confd_duration (xs:duration) */ C_ENUM_VALUE = 28, /* int32_t (enumeration) */ C_BIT32 = 29, /* u_int32_t (bits size 32) */ C_BIT64 = 30, /* u_int64_t (bits size 64) */ C_LIST = 31, /* confd_list (leaf-list) */ C_XMLBEGIN = 32, /* struct xml_tag, start of container or */ /* list entry */ C_XMLEND = 33, /* struct xml_tag, end of container or */ /* list entry */ C_OBJECTREF = 34, /* struct confd_hkeypath* */ /* (instance-identifier) */ C_UNION = 35, /* (union) - not used in API functions */ C_PTR = 36, /* see cdb_get_values in confd_lib_cdb(3) */ C_CDBBEGIN = 37, /* as C_XMLBEGIN, with CDB instance index */ C_OID = 38, /* struct confd_snmp_oid* */ /* (yang:object-identifier) */ C_BINARY = 39, /* confd_buf_t (binary ...) */ C_IPV4PREFIX = 40, /* struct confd_ipv4_prefix */ /* (inet:ipv4-prefix) */ C_IPV6PREFIX = 41, /* struct confd_ipv6_prefix */ /* (inet:ipv6-prefix) */ C_DEFAULT = 42, /* default value indicator */ C_DECIMAL64 = 43, /* struct confd_decimal64 (decimal64) */ C_IDENTITYREF = 44, /* struct confd_identityref (identityref) */ C_XMLBEGINDEL = 45, /* as C_XMLBEGIN, but for a deleted list */ /* entry */ C_DQUAD = 46, /* struct confd_dotted_quad */ /* (yang:dotted-quad) */ C_HEXSTR = 47, /* confd_buf_t (yang:hex-string) */ C_IPV4_AND_PLEN = 48, /* struct confd_ipv4_prefix */ /* (tailf:ipv4-address-and-prefix-length) */ C_IPV6_AND_PLEN = 49, /* struct confd_ipv6_prefix */ /* (tailf:ipv6-address-and-prefix-length) */ C_MAXTYPE /* maximum marker; add new values above */ };
A concrete value is represented as a confd_value_t C struct:
typedef struct confd_value { enum confd_vtype type; /* as defined above */ union { struct xml_tag xmltag; u_int32_t symbol; confd_buf_t buf; confd_buf_const_t c_buf; char *s; const char *c_s; int8_t i8; int16_t i16; int32_t i32; int64_t i64; u_int8_t u8; u_int16_t u16; u_int32_t u32; u_int64_t u64; double d; struct in_addr ip; struct in6_addr ip6; int boolean; struct confd_qname qname; struct confd_datetime datetime; struct confd_date date; struct confd_time time; struct confd_duration duration; int32_t enumvalue; u_int32_t b32; u_int64_t b64; struct confd_list list; struct confd_hkeypath *hkp; struct confd_vptr ptr; struct confd_snmp_oid *oidp; struct confd_ipv4_prefix ipv4prefix; struct confd_ipv6_prefix ipv6prefix; struct confd_decimal64 d64; struct confd_identityref idref; struct confd_dotted_quad dquad; u_int32_t enumhash; /* backwards compat */ } val; } confd_value_t;
C_NOEXISTS
This is used internally by ConfD, as an end marker in confd_hkeypath_t arrays, and as a "value does not exist" indicator in arrays of values.
C_DEFAULT
This is used to indicate that an element with a default value defined in the data model does not have a value set. When reading data from ConfD, we will only get this indication if we specifically request it, otherwise the default value is returned.
C_XMLTAG
An C_XMLTAG value is represented as a struct:
When a YANG module is compiled by the confdc(1) compiler, the
--emit-h
flag is used to generate a .h file
containing definitions for all the nodes in the module.
For example if we compile the following YANG module:
# cat blaster.yang module blaster { namespace "http://tail-f.com/ns/blaster"; prefix blaster; import tailf-common { prefix tailf; } typedef Fruit { type enumeration { enum apple; enum orange; enum pear; } } container tiny { tailf:callpoint xcp; leaf foo { type int8; } leaf bad { type int16; } } } # confdc -c blaster.yang # confdc --emit-h blaster.h blaster.fxs
We get the following contents in blaster.h
# cat blaster.h /* * BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE * This file has been auto-generated by the confdc compiler. * Source: blaster.fxs * BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE BEWARE */ #ifndef _BLASTER_H_ #define _BLASTER_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef blaster__ns #define blaster__ns 670579579 #define blaster__ns_id "http://tail-f.com/ns/blaster" #define blaster__ns_uri "http://tail-f.com/ns/blaster" #endif #define blaster_orange 1 #define blaster_apple 0 #define blaster_pear 2 #define blaster_foo 161968632 #define blaster_tiny 1046642021 #define blaster_bad 1265139696 #define blaster__callpointid_xcp "xcp" #ifdef __cplusplus } #endif #endif
The integers in the .h file are used in the
struct xml_tag, thus the container node
tiny
is
represented as a xml_tag C struct
{tag=1046642021, ns=670579579}
or, using the
#defines {tag=blaster_tiny, ns=blaster__ns}
.
Each callpoint, actionpoint, and validate statement also yields a preprocessor symbol. If the symbol is used rather than the literal string in calls to ConfD, the C compiler will catch the potential problem when the id in the data model has changed but the C code hasn't been updated.
Sometimes we wish to retrieve a string representation of
defined hash values. This can be done with the function
confd_hash2str()
, see the USING
SCHEMA INFORMATION section below.
C_BUF
This type is used to represent the YANG built-in type string and the xs:token type. The struct which is used is:
typedef struct confd_buf { unsigned int size; unsigned char *ptr; } confd_buf_t;
Strings passed to the application from ConfD are always NUL-terminated. When values of this type are received by the callback functions in confd_lib_dp(3), the ptr field is a pointer to libconfd private memory, and the data will not survive unless copied by the application.
To create and extract values of type C_BUF we do:
confd_value_t myval; char *x; int len; CONFD_SET_BUF(&myval, "foo", 3) x = CONFD_GET_BUFPTR(&myval); len = CONFD_GET_BUFSIZE(&myval);
It is important to realize that C_BUF data received by
the application through either
maapi_get_elem()
or
cdb_get()
which are of type C_BUF must
be freed by the application.
C_STR
This tag is never received by the application. Values
and keys received in the various data callbacks (See
confd_register_data_cb()
in confd_lib_dp(3) never have
this type. It is only used when the application replies with
values to ConfD. (See
confd_data_reply_value()
in confd_lib_dp(3)).
It is used to represent regular NUL-terminated char* values. Example:
confd_value_t myval; myval.type = C_STR; myval.val.s = "Zaphod"; /* or alternatively and recommended */ CONFD_SET_STR(&myval, "Beeblebrox");
C_INT8
Used to represent the YANG built-in type int8, which is a signed 8 bit integer. The corresponding C type is int8_t. Example:
int8_t ival; confd_value_t myval; CONFD_SET_INT8(&myval, -32); ival = CONFD_GET_INT8(&myval);
C_INT16
Used to represent the YANG built-in type int16, which is a signed 16 bit integer. The corresponding C type is int16_t. Example:
int16_t ival; confd_value_t myval; CONFD_SET_INT16(&myval, -3277); ival = CONFD_GET_INT16(&myval);
C_INT32
Used to represent the YANG built-in type int32, which is a signed 32 bit integer. The corresponding C type is int32_t. Example:
int32_t ival; confd_value_t myval; CONFD_SET_INT32(&myval, -77732); ival = CONFD_GET_INT32(&myval);
C_INT64
Used to represent the YANG built-in type int64, which is a signed 64 bit integer. The corresponding C type is int64_t. Example:
int64_t ival; confd_value_t myval; CONFD_SET_INT64(&myval, -32); ival = CONFD_GET_INT64(&myval);
C_UINT8
Used to represent the YANG built-in type uint8, which is an unsigned 8 bit integer. The corresponding C type is u_int8_t. Example:
u_int8_t ival; confd_value_t myval; CONFD_SET_UINT8(&myval, 32); ival = CONFD_GET_UINT8(&myval);
C_UINT16
Used to represent the YANG built-in type uint16, which is an unsigned 16 bit integer. The corresponding C type is u_int16_t. Example:
u_int16_t ival; confd_value_t myval; CONFD_SET_UINT16(&myval, 3277); ival = CONFD_GET_UINT16(&myval);
C_UINT32
Used to represent the YANG built-in type uint32, which is an unsigned 32 bit integer. The corresponding C type is u_int32_t. Example:
u_int32_t ival; confd_value_t myval; CONFD_SET_UINT32(&myval, 77732); ival = CONFD_GET_UINT32(&myval);
C_UINT64
Used to represent the YANG built-in type uint64, which is an unsigned 64 bit integer. The corresponding C type is u_int64_t. Example:
u_int64_t ival; confd_value_t myval; CONFD_SET_UINT64(&myval, 32); ival = CONFD_GET_UINT64(&myval);
C_DOUBLE
Used to represent the XML schema types xs:decimal, xs:float and xs:double. They are all coerced into the C type double. Example:
double d; confd_value_t myval; CONFD_SET_DOUBLE(&myval, 3.14); d = CONFD_GET_DOUBLE(&myval);
C_BOOL
Used to represent the YANG built-in type
boolean. The C representation is an integer
with 0
representing false and non-zero
representing true. Example:
int bool confd_value_t myval; CONFD_SET_BOOL(&myval, 1); b = CONFD_GET_BOOL(&myval);
C_QNAME
Used to represent XML Schema type xs:QName which consists of a pair of strings, prefix and a name. Data is allocated by the library as for C_BUF. Example:
unsigned char* prefix, *name; int prefix_len, name_len; confd_value_t myval; CONFD_SET_QNAME(&myval, "myprefix", 8, "myname", 6); prefix = CONFD_GET_QNAME_PREFIX_PTR(&myval); prefix_len = CONFD_GET_QNAME_PREFIX_SIZE(&myval); name = CONFD_GET_QNAME_NAME_PTR(&myval); name_len = CONFD_GET_QNAME_NAME_SIZE(&myval);
C_DATETIME
Used to represent the YANG type yang:date-and-time. The C representation is a struct:
struct confd_datetime { int16_t year; u_int8_t month; u_int8_t day; u_int8_t hour; u_int8_t min; u_int8_t sec; u_int32_t micro; int8_t timezone; int8_t timezone_minutes; };
ConfD does not try to convert the data values into timezone independent C structs. The timezone and timezone_minutes fields are integers where:
timezone == 0 && timezone_minutes == 0
represents UTC. This corresponds to a timezone specification in the string form of "Z" or "+00:00".
-14 <= timezone && timezone <= 14
represents an offset in hours from UTC. In this
case timezone_minutes
represents
a fraction of an hour in minutes if the offset from
UTC isn't an integral number of hours, otherwise it is
0. If timezone != 0
, its sign
gives the direction of the offset, and
timezone_minutes
is always
>= 0
- otherwise the sign of
timezone_minutes
gives the
direction of the offset. E.g. timezone == 5
&& timezone_minutes == 30
corresponds to a timezone specification in the
string form of "+05:30".
timezone == CONFD_TIMEZONE_UNDEF
means that the string form indicates lack of timezone information with "-00:00".
It is up to the application to transform these structs
into more UNIX friendly structs such as struct
tm from
<time.h>
. Example:
#include <time.h> confd_value_t myval; struct confd_datetime dt; struct tm *tm = localtime(time(NULL)); dt.year = tm->tm_year + 1900; dt.month = tm->tm_mon + 1; dt.day = tm->tm_mday; dt->hour = tm->tm_hour; dt.min = tm->tm_min; dt->sec = tm->tm_sec; dt.micro = 0; dt.timezone = CONFD_TIMEZONE_UNDEF; CONFD_SET_DATETIME(&myval, dt); dt = CONFD_GET_DATETIME(&myval);
C_DATE
Used to represent the XML Schema type xs:date. The C representation is a struct:
struct confd_date { int16_t year; u_int8_t month; u_int8_t day; int8_t timezone; int8_t timezone_minutes; };
Example:
confd_value_t myval; struct confd_date dt; dt.year = 1960, dt.month = 3, dt.day = 31; dt.timezone = CONFD_TIMEZONE_UNDEF; CONFD_SET_DATE(&myval, dt); dt = CONFD_GET_DATE(&myval);
C_TIME
Used to represent the XML Schema type xs:time. The C representation is a struct:
struct confd_time { u_int8_t hour; u_int8_t min; u_int8_t sec; u_int32_t micro; int8_t timezone; int8_t timezone_minutes; };
Example:
confd_value_t myval; struct confd_time dt; dt.hour = 19, dt.min = 3, dt.sec = 31; dt.timezone = CONFD_TIMEZONE_UNDEF; CONFD_SET_TIME(&myval, dt); dt = CONFD_GET_TIME(&myval);
C_DURATION
Used to represent the XML Schema type xs:duration. The C representation is a struct:
struct confd_duration { u_int32_t years; u_int32_t months; u_int32_t days; u_int32_t hours; u_int32_t mins; u_int32_t secs; u_int32_t micros; };
Example of something that is supposed to last 3 seconds:
confd_value_t myval; struct confd_duration dt; memset(&dt, 0, sizeof(struct confd_duration)); dt.secs = 3; CONFD_SET_DURATION(&myval, dt); dt = CONFD_GET_DURATION(&myval);
C_IPV4
Used to represent the YANG type inet:ipv4-address. The C representation is a struct in_addr Example:
struct in_addr ip; confd_value_t myval; ip.s_addr = inet_addr("192.168.1.2"); CONFD_SET_IPV4(&myval, ip); ip = CONFD_GET_IPV4(&myval);
C_IPV6
Used to represent the YANG type inet:ipv6-address. The C representation is as struct in6_addr Example:
struct in6_addr ip6; confd_value_t myval; inet_pton(AF_INET6, "FFFF::192.168.42.2", &ip6); CONFD_SET_IPV6(&myval, ip6); ip6 = CONFD_GET_IPV6(&myval);
C_ENUM_VALUE
Used to represent the YANG built-in type enumeration - like the Fruit enumeration from the beginning of this man page.
enum fruit { ORANGE = blaster_orange, APPLE = blaster_apple, PEAR = blaster_pear }; enum fruit f; confd_value_t myval; CONFD_SET_ENUM_VALUE(&myval, APPLE); f = CONFD_GET_ENUM_VALUE(&myval);
Thus leafs that have type enumeration in
the YANG module do not have values that are strings in the C
code, but integer values according to the YANG standard.
The file generated by confdc --emit-h
includes #define
symbols for these integer values.
C_BIT32
, C_BIT64
Used to represent the YANG built-in type bits. In C the value representation for a bitmask is either a 32 bit or a 64 bit unsigned integer, depending on the highest bit position assigned.
u_int32_t mask = 77; confd_value_t myval; CONFD_SET_BIT32(&myval, mask); mask = CONFD_GET_BIT32(&myval);
C_LIST
Used to represent a YANG leaf-list
. In C the
value representation for is:
Similar to the C_BUF type, the confd library will
allocate data when an element of type C_LIST
is retrieved via maapi_get_elem()
or
cdb_get()
. Using
confd_free_value()
(see confd_lib_lib(3))
to free
allocated data is especially convenient for C_LIST, as the
individual list elements may also have allocated data (e.g.
a YANG leaf-list
of type string).
To set a value of type C_LIST we have to populate the list array separately, for example:
confd_value_t arr[5]; confd_value_t v; confd_value_t *vp; int i, size; for (i=0; i<5; i++) CONFD_SET_INT32(&arr[i], i); CONFD_SET_LIST(&v, &arr[0], 5); vp = CONFD_GET_LIST(&v); size = CONFD_GET_LISTSIZE(&v);
C_XMLBEGIN
, C_XMLEND
These are only used in the "Tagged Value Array" format for representing XML structures, see below. The representation is the same as for C_XMLTAG.
C_OBJECTREF
This is used to represent the YANG built-in type
instance-identifier.
Values are represented as
confd_hkeypath_t pointers. Data is allocated
by the library as for C_BUF. When we read an
instance-identifier via
e.g. cdb_get()
we can retrieve the
pointer to the keypath as:
confd_value_t v; confd_hkeypath_t *hkp; cdb_get(sock, &v, mypath); hkp = CONFD_GET_OBJECTREF(&v);
To retrieve the value which is identified by the instance-identifier we can e.g. use the "%h" modifier in the format string used with the CDB and MAAPI API functions.
C_OID
This is used to represent the YANG yang:object-identifier and yang:object-identifier-128 types, i.e. SNMP Object Identifiers. The value is a pointer to a struct:
Data is allocated by the library as for C_BUF. When
using values of this type, we set or get the
len
element, and the individual OID
elements in the oid
array. This
example will store the string "0.1.2" in
buf
:
struct confd_snmp_oid myoid; confd_value_t myval; char buf[BUFSIZ]; int i; for (i = 0; i < 3; i++) myoid.oid[i] = i; myoid.len = 3; CONFD_SET_OID(&myval, &myoid); confd_pp_value(buf, sizeof(buf), &myval);
C_BINARY
This type is used to represent arbitrary binary data. The YANG built-in type binary, the ConfD built-in types tailf:hex-list and tailf:octet-list, and the XML Schema primitive type xs:hexBinary all use this type. The value representation is the same as for C_BUF. Binary (C_BINARY) data received by the application from ConfD is always NUL terminated, but since the data may also contain NUL bytes, it is generally necessary to use the size given by the representation.
Data is also allocated by the library as for C_BUF. Example:
confd_value_t myval, myval2; unsigned char *bin; int len; bin = CONFD_GET_BINARY_PTR(&myval); len = CONFD_GET_BINARY_SIZE(&myval); CONFD_SET_BINARY(&myval2, bin, len);
C_IPV4PREFIX
Used to represent the YANG data type inet:ipv4-prefix. The C representation is a struct as follows:
struct confd_ipv4_prefix { struct in_addr ip; u_int8_t len; };
Example:
struct confd_ipv4_prefix prefix; confd_value_t myval; prefix.ip.s_addr = inet_addr("10.0.0.0"); prefix.len = 8; CONFD_SET_IPV4PREFIX(&myval, prefix); prefix = CONFD_GET_IPV4PREFIX(&myval);
C_IPV6PREFIX
Used to represent the YANG data type inet:ipv6-prefix. The C representation is a struct as follows:
struct confd_ipv6_prefix { struct in6_addr ip6; u_int8_t len; };
Example:
struct confd_ipv6_prefix prefix; confd_value_t myval; inet_pton(AF_INET6, "2001:DB8::1428:57A8", &prefix.ip6); prefix.len = 125; CONFD_SET_IPV6PREFIX(&myval, prefix); prefix = CONFD_GET_IPV6PREFIX(&myval);
C_DECIMAL64
Used to represent the YANG built-in type decimal64, which is a decimal number with 64 bits of precision. The C representation is a struct as follows:
The value
element is scaled with the
value of the fraction_digits
element, to be
able to represent it as a 64-bit integer. Note that
fraction_digits
is a constant for any given
instance of a
decimal64 type. It is provided whenever we receive a
C_DECIMAL64 from ConfD. When we provide a C_DECIMAL64 to
ConfD, we can set fraction_digits
either to
the correct value or to 0 - however the
value
element must always be correctly
scaled. See also
confd_get_decimal64_fraction_digits()
in
the confd_lib_lib(3)
man page.
Example:
struct confd_decimal64 d64; confd_value_t myval; d64.value = 314159; d64.fraction_digits = 5; CONFD_SET_DECIMAL64(&myval, d64); d64 = CONFD_GET_DECIMAL64(&myval);
C_IDENTITYREF
Used to represent the YANG built-in type
identityref, which references an existing
identity
.
The C representation is a struct as follows:
The ns
and id
elements are hash values that represent the namespace of the
module that defines the identity, and the identity within that
module.
Example:
struct confd_identityref idref; confd_value_t myval; idref.ns = des__ns; idref.id = des_des3 CONFD_SET_IDENTITYREF(&myval, idref); idref = CONFD_GET_IDENTITYREF(&myval);
C_DQUAD
Used to represent the YANG data type yang:dotted-quad. The C representation is a struct as follows:
Example:
struct confd_dotted_quad dquad; confd_value_t myval; dquad.quad[0] = 1; dquad.quad[1] = 2; dquad.quad[2] = 3; dquad.quad[3] = 4; CONFD_SET_DQUAD(&myval, dquad); dquad = CONFD_GET_DQUAD(&myval);
C_HEXSTR
Used to represent the YANG data type yang:hex-string. The value representation is the same as for C_BUF and C_BINARY. C_HEXSTR data received by the application from ConfD is always NUL terminated, but since the data may also contain NUL bytes, it is generally necessary to use the size given by the representation.
typedef struct confd_buf { unsigned int size; unsigned char *ptr; } confd_buf_t;
Data is also allocated by the library as for C_BUF/C_BINARY. Example:
confd_value_t myval, myval2; unsigned char *hex; int len; hex = CONFD_GET_HEXSTR_PTR(&myval); len = CONFD_GET_HEXSTR_SIZE(&myval); CONFD_SET_HEXSTR(&myval2, bin, len);
C_IPV4_AND_PLEN
Used to represent the ConfD built-in data type tailf:ipv4-address-and-prefix-length. The C representation is the same struct that is used for C_IPV4PREFIX, as follows:
struct confd_ipv4_prefix { struct in_addr ip; u_int8_t len; };
Example:
struct confd_ipv4_prefix ip_and_len; confd_value_t myval; ip_and_len.ip.s_addr = inet_addr("172.16.1.2"); ip_and_len.len = 16; CONFD_SET_IPV4_AND_PLEN(&myval, ip_and_len); ip_and_len = CONFD_GET_IPV4_AND_PLEN(&myval);
C_IPV6_AND_PLEN
Used to represent the ConfD built-in data type tailf:ipv6-address-and-prefix-length. The C representation is the same struct that is used for C_IPV6PREFIX, as follows:
struct confd_ipv6_prefix { struct in6_addr ip6; u_int8_t len; };
Example:
struct confd_ipv6_prefix ip_and_len; confd_value_t myval; inet_pton(AF_INET6, "2001:DB8::1428:57A8", &ip_and_len.ip6); ip_and_len.len = 64; CONFD_SET_IPV6_AND_PLEN(&myval, ip_and_len); ip_and_len = CONFD_GET_IPV6_AND_PLEN(&myval);
Almost all of the callback functions the user is supposed write for the confd_lib_dp(3) library takes a parameter of type confd_hkeypath_t. This type includes an array of the type confd_value_t described above. The confd_hkeypath_t is defined as a C struct:
Where:
#define MAXDEPTH 20 /* max depth of data model tree (max KP length + 1) */ #define MAXKEYLEN 9 /* max number of key elems (max keys + 1) */
For example, assume we have a YANG module with:
container servers { tailf:callpoint mycp; list server { key name; max-elements 64; leaf name { type string; } leaf ip { type inet:ip-address; } leaf port { type inet:port-number; } } }
Assuming a server
entry with the name
"www" exists, then the path
/servers/server{www}/ip
is valid and
identifies the ip
leaf in the server entry whose
key is "www".
The confd_hkeypath_t which corresponds to
/servers/server{www}/ip
is received in
reverse order so the following holds assuming the variable holding
a pointer to the keypath is called hkp.
hkp->v[0][0]
is the last element,
the "ip" element. It is a data model node, and
CONFD_GET_XMLTAG(&hkp->v[0][0])
will
evaluate to a hashed integer (which can be found in the confdc
generated .h file as a #define)
hkp->v[1][0]
is the next element in
the path. The key element is called "name". This is a
string value - thus strcmp("www",
CONFD_GET_BUFPTR(&hkp->v[1][0])) == 0
holds.
If we had chosen to use multiple keys in our data model - for example if we had chosen to use both the "name" and the "ip" leafs as keys:
key "name ip";
The hkeypaths would be different since two keys are
required. A valid path identifying a port
leaf would be
/servers/server{www 10.2.3.4}/port
. In this case we can
get to the ip
part of the key with:
struct in_addr ip; ip = CONFD_GET_IPV4(&hkp->v[1][1])
We can define new types in addition to those listed in the TYPEDEFS section above. This can be useful if none of the predefined types, nor a derivation of one of those types via standard YANG restrictions, is suitable. Of course it is always possible to define a type as a derivation of string and have the application parse the string whenever a value needs to be processed, but with a user-defined type ConfD will do the string <-> value translation just as for the predefined types.
A user-defined type will always have a value representation
that uses a confd_value_t with one of the enum
confd_vtype values listed above, but the textual
representation and the range(s) of allowed values are defined by
the user. The misc/user_type
example in the
collection delivered with the ConfD release shows implementation of
several user-defined types - it will be useful to refer
to it for the description below.
The choice of confd_vtype to use for the value representation can be whatever suits the actual data values best, with one exception:
The C_LIST confd_vtype value can not be used for a leaf that is a key in a YANG list. The "normal" C_LIST usage is only for representation of leaf-lists, and a leaf-list can of course not be a key. Thus the ConfD code is not prepared to handle this kind of "value" for a key. It is a strong recommendation to never use C_LIST for a user-defined type, since even if the type is not initially used for key leafs, subsequent development may see a need for this, at which point it may be cumbersome to change to a different representation.
The example uses C_INT32, C_IPV4PREFIX, and C_IPV6PREFIX for the value representation of the respective types, but in many cases the opaque byte array provided by C_BINARY will be most suitable - this can e.g. be mapped to/from an arbitrary C struct.
When we want to implement a user-defined type, we need to
specify the type as string, and add a
tailf:typepoint
statement - see tailf_yang_extensions(5).
We can use tailf:typepoint
wherever a built-in or
derived type can be specified, i.e. as sub-statement to
typedef
, leaf
, or leaf-list
:
typedef myType { type string; tailf:typepoint my_type; } container c { leaf one { type myType; } leaf two { type string; tailf:typepoint two_type; } }
The argument to the tailf:typepoint
statement is
used to locate the type implementation, similar to how "callpoints" are
used to locate data providers, but the actual mechanism is
different, as described below.
To actually implement the type definition, we need to write three callback functions that are defined in the struct confd_type:
struct confd_type { /* If a derived type point at the parent */ struct confd_type *parent; /* not used in confspecs, but used in YANG */ struct confd_type *defval; /* parse value located in str, and validate. * returns CONFD_TRUE if value is syntactically correct * and CONFD_FALSE otherwise. */ int (*str_to_val)(struct confd_type *self, struct confd_type_ctx *ctx, const char *str, unsigned int len, confd_value_t *v); /* print the value to str. * does not print more than len bytes, including trailing NUL. * return value as snprintf - i.e. if the value is correct for * the type, it returns the length of the string form regardless * of the len limit - otherwise it returns a negative number. * thus, the NUL terminated output has been completely written * if and only if the returned value is nonnegative and less * than len. * If strp is non-NULL and the string form is constant (i.e. * C_ENUM_VALUE), a pointer to the string is stored in *strp. */ int (*val_to_str)(struct confd_type *self, struct confd_type_ctx *ctx, const confd_value_t *v, char *str, unsigned int len, const char **strp); /* returns CONFD_TRUE if value is correct, otherwise CONFD_FALSE */ int (*validate)(struct confd_type *self, struct confd_type_ctx *ctx, const confd_value_t *v); /* data optionally used by the callbacks */ void *opaque; };
I.e. str_to_val()
and
val_to_str()
are responsible for the string to
value and value to string translations, respectively, and
validate()
may be called to verify that a given
value adheres to any restrictions on the values allowed for the
type. The errstr
element in the struct
confd_type_ctx *ctx
passed to these functions can be
used to return an error message when the function fails - in this
case errstr
must be set to the address of a
dynamically allocated string. The other elements in
ctx
are currently unused.
Including user-defined types in a YANG union
may
need some special consideration. Per the YANG specification, the
string form of a value is matched against the union member types in
the order they are specified until a match is found, and this
procedure determines the type of the value. A corresponding
procedure is used by ConfD when the value needs to be converted to a
string, but this conversion does not include any evaluation of
restrictions etc - the values are assumed to be correct for their
type. Thus the val_to_str()
function for the
member types are tried in order until one succeeds, and the
resulting string is used. This means that a)
val_to_str()
must verify that the value is of
the correct type, i.e. that it has the expected
confd_vtype, and b) if the value representation is the
same for multiple member types, there is no guarantee that the same
member type as for the string to value conversion is chosen.
The opaque
element in the struct
confd_type can be used for any auxiliary (static) data needed
by the functions (on invocation they can reference it as
self->opaque). The parent
and
defval
elements are not used in this context, and
should be NULL.
The str_to_val()
function
must allocate space (using e.g. malloc(3))
for the actual data value for those confd_value_t types that are
listed as having allocated data above, i.e. C_BUF, C_QNAME,
C_LIST, C_OBJECTREF, C_OID, C_BINARY, and C_HEXSTR.
We make the implementation available to ConfD by creating
one or more shared objects (.so files) containing the above
callback functions. Each shared object may implement one or more
types, and at startup the ConfD daemon will search the directories
specified for /confdConfig/loadPath
in
confd.conf
for files with a
name that match the pattern "confd_type*.so" and load them.
Each shared object must also implement an "init" callback:
When the object has been loaded, ConfD will call this
function. It must return a pointer to an array of type callback
structures via the cbs
argument, and the
number of elements in the array as return value. The
struct confd_type_cbs is defined as:
These structures are then used by ConfD to locate the
implementation of a given type, by searching for a
typepoint
string that matches the
tailf:typepoint
argument in the YANG data model.
Since our callbacks are executed directly by the ConfD daemon, it is critically important that they do not have a negative impact on the daemon. No other processing can be done by ConfD while the callbacks are executed, and e.g. a NULL pointer dereference in one of the callbacks will cause ConfD to crash. Thus they should be simple, purely algorithmic functions, never referencing any external resources.
When user-defined types are present, the ConfD daemon also needs to load the libconfd.so shared library, otherwise used only by applications. This means that either this library must be in one of the system directories that are searched by the OS runtime loader (typically /lib and /usr/lib), or its location must be given by setting the LD_LIBRARY_PATH environment variable before starting ConfD.
The above is enough for ConfD to use the types that we have defined, but the libconfd library can also do local string<->value translation if we have loaded the schema information, as described in the USING SCHEMA INFORMATION section below. For this to work for user-defined types, we must register the type definitions with the library, using one of these functions:
Here we must pass the hash value for the namespace where the
type is defined as nshash
, and the name of
the type from a typedef
statement
(i.e. not the typepoint name if they are
different) as name
. Thus we can not use this
function to register a user-defined type that is specified "inline"
in a leaf
or leaf-list
statement, since
we don't have a name for the type.
This function takes a pointer to a schema node (see the
section USING
SCHEMA INFORMATION) that uses the type instead of namespace
and type name. It is necessary to use this for registration of
user-defined types that are specified "inline", but it can also be
used for user-defined types specified via typedef
. In
the latter case it will be equivalent to calling
confd_register_ns_type()
for the typedef,
i.e. a single registration will apply to all nodes using the
typedef.
The functions can only be called after
confd_load_schemas()
or
maapi_load_schemas()
(see below) has been
called, and if
confd_load_schemas()
/
maapi_load_schemas()
is called again, the registration must be re-done. The
misc/user_type
example shows a way to use the
exact same code for the shared object and for this
registration.
Schema upgrades when the data is stored in CDB requires special consideration for user-defined types. Normally CDB can handle any type changes automatically, and this is true also when changing to/from/between user-defined types, provided that the following requirements are fulfilled:
A given typepoint name always refers to the exact same implementation - i.e. same value representation, same range restrictions, etc.
Shared objects providing implementations for all the typepoint ids used in the new and the old schema are made available to ConfD.
I.e. if we change the implementation of a type, we also change the typepoint name, and keep the old implementation around. If requirement 1 isn't fulfilled, we can end up with the case of e.g. a changed value representation between schema versions even though the types are indistinguishable for CDB. This can still be handled by using MAAPI to modify CDB during the upgrade as described in the User Guide, but if that is not done, CDB will just carry the old values over, which in effect results in a corrupt database.
Schema information from the data model can be loaded from the
ConfD daemon at runtime using the
maapi_load_schemas()
function, see the confd_lib_maapi(3)
manual page. Information for all namespaces loaded into ConfD is
then made available. In many cases it may be more convenient to
use the confd_load_schemas()
utility
function. For details about this function and those discussed
below, see confd_lib_lib(3).
After loading the data, we can call
confd_get_nslist()
to find which namespaces
are known to the library as a result.
Note that all pointers
returned (directly or indirectly) by the functions discussed here
reference dynamically allocated memory maintained by the library -
they will become invalid if
confd_load_schemas()
or
maapi_load_schemas()
is subsequently called
again.
The confdc(1) compiler can also optionally generate a C header file that has #define symbols for the integer values corresponding to data model nodes and enumerations.
When the schema information has been made available to the
library, we can format an arbitrary instance of a
confd_value_t value using
confd_pp_value()
or
confd_ns_pp_value()
, or an arbitrary hkeypath
using confd_pp_kpath()
or
confd_xpath_pp_kpath()
. We can also get a
pointer to the string representing a data model node
using confd_hash2str()
.
Furthermore a tree representation of the data model is available, which contains a struct confd_cs_node for every node in the data model. There is one tree for each namespace that has toplevel elements.
/* flag bits in confd_cs_node_info */ #define CS_NODE_IS_LIST (1 << 0) #define CS_NODE_IS_WRITE (1 << 1) #define CS_NODE_IS_CDB (1 << 2) #define CS_NODE_IS_ACTION (1 << 3) #define CS_NODE_IS_PARAM (1 << 4) #define CS_NODE_IS_RESULT (1 << 5) #define CS_NODE_IS_NOTIF (1 << 6) #define CS_NODE_IS_CASE (1 << 7) #define CS_NODE_IS_CONTAINER (1 << 8) #define CS_NODE_HAS_WHEN (1 << 9) #define CS_NODE_HAS_DISPLAY_WHEN (1 << 10) #define CS_NODE_HAS_META_DATA (1 << 11) #define CS_NODE_IS_WRITE_ALL (1 << 12) #define CS_NODE_IS_DYN CS_NODE_IS_LIST /* backwards compat */ /* cmp values in confd_cs_node_info */ #define CS_NODE_CMP_NORMAL 0 #define CS_NODE_CMP_SNMP 1 #define CS_NODE_CMP_SNMP_IMPLIED 2 #define CS_NODE_CMP_USER 3 #define CS_NODE_CMP_UNSORTED 4 struct confd_cs_node_info { u_int32_t *keys; int minOccurs; int maxOccurs; /* -1 if unbounded */ enum confd_vtype shallow_type; struct confd_type *type; confd_value_t *defval; struct confd_cs_choice *choices; int flags; u_int8_t cmp; struct confd_cs_meta_data *meta_data; }; struct confd_cs_meta_data { char* key; char* value; }; struct confd_cs_node { u_int32_t tag; u_int32_t ns; struct confd_cs_node_info info; struct confd_cs_node *parent; struct confd_cs_node *children; struct confd_cs_node *next; void *opaque; /* private user data */ }; struct confd_cs_choice { u_int32_t tag; u_int32_t ns; int minOccurs; struct confd_cs_case *default_case; struct confd_cs_node *parent; /* NULL if parent is case */ struct confd_cs_case *cases; struct confd_cs_choice *next; struct confd_cs_case *case_parent; /* NULL if parent is node */ }; struct confd_cs_case { u_int32_t tag; u_int32_t ns; struct confd_cs_node *first; struct confd_cs_node *last; struct confd_cs_choice *parent; struct confd_cs_case *next; struct confd_cs_choice *choices; };
Each confd_cs_node is linked to its
related nodes: parent
is a pointer to the
parent node, next
is a pointer to the next
sibling node, and children
is a pointer to
the first child node - for each of these, a NULL pointer has the
obvious meaning.
Each confd_cs_node also contains an
information structure: For a list node,
the keys
field is a zero-terminated array of
integers - these are the tag
values for the
children nodes that are key elements. This makes it possible to
find the name of a key element in a keypath. If the
confd_cs_node is not a list node, the
keys
field is NULL. The
shallow_type
field gives the "primitive" type
for the element, i.e. the enum confd_vtype value that
is used in the confd_value_t representation.
Typed leaf nodes also carry a complete type definition via
the type
pointer, which can be used with the
conf_str2val()
and
confd_val2str()
functions, as well as the
leaf's default value (if any) via the defval
pointer.
If the YANG choice
statement is used in the data model,
additional structures are created by the schema
loading. For list and container nodes that have choice
statements, the choices
element in
confd_cs_node_info is a pointer to a linked
list of confd_cs_choice structures
representing the choices. Each
confd_cs_choice has a pointer to the parent
node and a cases
pointer to a linked
list of confd_cs_case structures representing
the cases for that choice. Finally, each
confd_cs_case structure has pointers to the
parent confd_cs_choice structure, and to the
confd_cs_node structures representing the
first and last element in the case. Those
confd_cs_node structures, i.e. the "toplevel"
elements of a case, have the CS_NODE_IS_CASE flag set.
Note that it is possible for a case to be "empty", i.e. there are no
elements in the case - then the first
and
last
pointers in the confd_cs_case
structure are NULL.
For a list node, the sort order
is indicated by the cmp
element in
confd_cs_node_info. The value CS_NODE_CMP_NORMAL
means an ordinary, system ordered, list. CS_NODE_CMP_SNMP is
system ordered, but ordered according to SNMP lexicographical
order, and CS_NODE_CMP_SNMP_IMPLIED is an SNMP lexicographical
order where the last key has an IMPLIED keyword.
CS_NODE_CMP_UNSORTED is system ordered, but is not sorted. The
value CS_NODE_CMP_USER denotes an "ordered-by user" list.
If the tailf:meta-data
extension is used for a
node, the meta_data
element points to an array of
struct confd_cs_meta_data, otherwise it is NULL.
In the array, the key
element is the argument
of tailf:meta-data
, and the value
element is the argument of the tailf:meta-value
substatement, if any - otherwise it is NULL. The end of the array
is indicated by a struct where the key
element
is NULL.
Action and notification specifications are included in the
tree in the same way as the config/data elements - they are
indicated by the CS_NODE_IS_ACTION flag being set on the
action
node, and the CS_NODE_IS_NOTIF flag being set on
the notification
node, respectively. Furthermore the
nodes corresponding to the sub-statements of the action's
input
statement have the CS_NODE_IS_PARAM flag
set, and those corresponding to the sub-statements of the action's
output
statement have the CS_NODE_IS_RESULT flag
set. Note that the input
and output
statements do not have corresponding nodes in the tree.
The confd_find_cs_root()
function
returns the root of the tree for a given namespace, and the
confd_find_cs_node()
,
confd_find_cs_node_child()
, and
confd_cs_node_cd()
functions are useful for
navigating the tree. Assume that we have the following
data model:
container servers { list server { key name; max-elements 64; leaf name { type string; } leaf ip { type inet:ip-address; } leaf port { type inet:port-number; } } }
Then, given the keypath
/servers/server{www}
in
confd_hkeypath_t form, a call to
confd_find_cs_node()
would return a
struct confd_cs_node, i.e. a pointer into
the tree, as in:
struct confd_cs_node *csp; char *name; csp = confd_find_cs_node(mykeypath, mykeypath->len); name = confd_hash2str(csp->info.keys[0])
and the C variable name
will have the
value "name"
. These functions make it
possible to format keypaths in various ways.
If we have a keypath which identifies a node below
the one we are interested in,
such as /servers/server{www}/ip
, we can use
the len
parameter as in
confd_find_cs_node(kp, 3)
where
3
is the length of the keypath we wish to
consider.
The equivalent of the above
confd_find_cs_node()
example, but using a
string keypath, could be written as:
csp = confd_cs_node_cd(confd_find_cs_root(mynamespace), "/servers/server{www}");
The type
field in the struct
confd_cs_node_info can be used for data model aware string
<-> value translations. E.g. assuming that we have a
confd_hkeypath_t *kp representing the element
/servers/server{www}/ip
, we can do the
following:
confd_value_t v; csp = confd_find_cs_node(kp, kp->len); confd_str2val(csp->info.type, "10.0.0.1", &v);
The confd_value_t v will then be filled in with
the corresponding C_IPV4 value. This technique is generally
necessary for translating C_ENUM_VALUE values to the corresponding
strings (or vice versa), since there isn't a type-independent
mapping. But confd_val2str()
(or
confd_str2val()
) can always do the translation,
since it is given the full type information. E.g. this will store
the string "nonVolatile" in buf
:
confd_value_t v; char buf[64]; CONFD_SET_ENUM_VALUE(&v, 3); root = confd_find_cs_root(SNMP_COMMUNITY_MIB__ns); csp = confd_cs_node_cd(root, "/SNMP-COMMUNITY-MIB/snmpCommunityTable/" "snmpCommunityEntry/snmpCommunityStorageType"); confd_val2str(csp->info.type, &v, buf, sizeof(buf));
The type information can also be found by using the
confd_find_ns_type()
function to look up the
type name as a string in the namespace where it is defined -
i.e. we could alternatively have achieved the same result
with:
CONFD_SET_ENUM_VALUE(&v, 3); type = confd_find_ns_type(SNMPv2_TC__ns, "StorageType"); confd_val2str(type, &v, buf, sizeof(buf));
If we give 0
for the
nshash
argument to
confd_find_ns_type()
, the type name will be
looked up among the ConfD built-in types (i.e. the YANG built-in
types, the types defined in the YANG "tailf-common" module, and the
types defined in the pre-defined "confd" and/or "xs" namespaces) -
e.g. the type information for /servers/server{www}/name
could be found with confd_find_ns_type(0,
"string")
.
Two different methods are used to represent a subtree of data nodes. "Value Array" describes a format that is simpler but has some limitations, while "Tagged Value Array" describes a format that is more complex but can represent an arbitrary subtree.
The simpler format is an array of confd_value_t elements corresponding to the complete contents of a list entry or container. The content of sub-list entries cannot be represented. The array is populated through a "depth first" traversal of the data tree as follows:
Optional leafs or presence
containers that do not
exist use a single array element, with type C_NOEXISTS (value
ignored).
List nodes use a single array element, with type C_NOEXISTS (value ignored), regardless of the actual number of entries or their contents.
Leafs with a type other than empty use an array element with their type and value as usual.
Leafs of type empty
use an array element with type C_XMLTAG, and
tag
and ns
set according
to the leaf name.
Containers use one array element with type
C_XMLTAG, and tag
and
ns
set according to the element name,
followed by array elements for the sub-nodes according to
this list.
Note that the list or container node corresponding to the complete array is not included in the array, and that there is no array element for the "end" of a container.
As an example, the array corresponding to the
/servers/server{www}
list entry above could
be populated as:
confd_value_t v[3]; struct in_addr ip; CONFD_SET_STR(&v[0], "www"); ip.s_addr = inet_addr("192.168.1.2"); CONFD_SET_IPV4(&v[1], ip); CONFD_SET_UINT16(&v[2], 80);
This format uses an array of confd_tag_value_t elements. This is a structure defined as:
I.e. each value element is associated with the struct
xml_tag that identifies the node in the data model. The
ns
element of the struct xml_tag
can normally be set to 0, with the meaning "current
namespace". The array is populated, normally through a "depth
first" traversal of the data tree, as follows:
Optional leafs or presence
containers that do not
exist are omitted entirely from the array.
List and container nodes use one array element where the
value has type C_XMLBEGIN, and tag
and
ns
set according to the node name,
followed by array elements for the sub-nodes according to
this list, followed by one array element where the value has
type C_XMLEND, and tag
and
ns
set according to the node
name.
Leafs with a type other than empty use an array element with their type and value as usual.
Leafs of type empty
use an array element where the
value has type C_XMLTAG, and tag
and
ns
set according to the leaf name.
Note that the list or container node corresponding to the complete array is not included in the array. In some usages, non-optional nodes may also be omitted from the array - refer to the relevant API documentation to see whether this is allowed and the semantics of doing so.
A set of CONFD_SET_TAG_XXX() macros corresponding to the
CONFD_SET_XXX() macros described above are provided - these set
the ns
element to 0 and the
tag
element to their second argument. The
array corresponding to the
/servers/server{www}
list entry above could
be populated as:
confd_tag_value_t tv[3]; struct in_addr ip; CONFD_SET_TAG_STR(&tv[0], servers_name, "www"); ip.s_addr = inet_addr("192.168.1.2"); CONFD_SET_TAG_IPV4(&tv[1], servers_ip, ip); CONFD_SET_TAG_UINT16(&tv[2], servers_port, 80);
There are also macros to access the components of the confd_tag_value_t elements:
confd_tag_value_t tv; u_int16_t port; if (CONFD_GET_TAG_TAG(&tv) == servers_port) port = CONFD_GET_UINT16(CONFD_GET_TAG_VALUE(&tv));
This section describes the types that can be
used in YANG data modeling, and their C representation.
Also listed is the corresponding SMIv2 type, which is
used when a data model is translated into a MIB. In several cases,
the data model type cannot easily be translated into a native SMIv2
type. In those cases, the type OCTET STRING
is used in the translation. The SNMP agent in ConfD will in those
cases send the string representation of the value over SNMP. For
example, the xs:float value
3.14
is sent as the string "3.14".
These subsections describe the following sets of types, which can be used with YANG data modeling:
These types are built-in to the YANG language, and also built-in to ConfD.
A signed 8-bit integer.
value.type
= C_INT8
union element = i8
C type = int8_t
SMIv2 type = Integer32 (-128 .. 127)
A signed 16-bit integer.
value.type
= C_INT16
union element = i16
C type = int16_t
SMIv2 type = Integer32 (-32768 .. 32767)
A signed 32-bit integer.
value.type
= C_INT32
union element = i32
C type = int32_t
SMIv2 type = Integer32
A signed 64-bit integer.
value.type
= C_INT64
union element = i64
C type = int64_t
SMIv2 type = OCTET STRING
An unsigned 8-bit integer.
value.type
= C_UINT8
union element = u8
C type = u_int8_t
SMIv2 type = Unsigned32 (0 .. 255)
An unsigned 16-bit integer.
value.type
= C_UINT16
union element = u16
C type = u_int16_t
SMIv2 type = Unsigned32 (0 .. 65535)
An unsigned 32-bit integer.
value.type
= C_UINT32
union element = u32
C type = u_int32_t
SMIv2 type = Unsigned32
An unsigned 64-bit integer.
value.type
= C_UINT64
union element = u64
C type = u_int64_t
SMIv2 type = OCTET STRING
A decimal number with 64 bits of precision. The C
representation uses a struct with a 64-bit signed integer for
the scaled value, and an unsigned 8-bit integer in the range
1..18 for the number of fraction digits specified by the
fraction-digits
sub-statement.
value.type
= C_DECIMAL64
union element = d64
C type = struct confd_decimal64
SMIv2 type = OCTET STRING
The string type is represented as a struct confd_buf_t when received from ConfD in the C code. I.e. it is NUL-terminated and also has a size given.
However, when the C code wants to produce a value of the string type it is possible to use a confd_value_t with the value type C_BUF or C_STR (which requires a NUL-terminated string)
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The boolean values "true" and "false".
value.type
= C_BOOL
union element = boolean
C type = int
SMIv2 type = TruthValue
Enumerated strings with associated numeric values. The C representation uses the numeric values.
value.type
= C_ENUM_VALUE
union element = enumvalue
C type = int32_t
SMIv2 type = INTEGER
A set of bits or flags. Depending on the highest
argument given to a position
sub-statement,
the C representation uses either C_BIT32 or C_BIT64.
value.type
= C_BIT32 or C_BIT64
union element = b32
or
b64
C type = u_int32_t or u_int64_t
SMIv2 type = Unsigned32 or OCTET STRING
Any binary data.
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
A reference to an abstract identity.
value.type
= C_IDENTITYREF
union element = idref
C type = struct confd_identityref
SMIv2 type = OCTET STRING
The union type has no special
confd_value_t representation - elements are
represented as one of the member types according to the current
value instantiation. This means that for unions that comprise
different "primitive" types, applications must check the
type
element to determine the type, and
the type safe alternatives to the
cdb_get()
and
maapi_get_elem()
functions can not be
used.
The SMIv2 type is an OCTET STRING.
The instance-identifier built-in type is used to uniquely identify a particular instance node in the data tree. The syntax for an instance-identifier is a subset of the XPath abbreviated syntax.
value.type
= C_OBJECTREF
union element = hkp
C type = confd_hkeypath_t
SMIv2 type = OCTET STRING
This module contains a collection of generally useful derived
YANG data types. They are defined in the urn:ietf:params:xml:ns:yang:ietf-yang-types
namespace.
32-bit counters, corresponding to the Counter32 type and the ZeroBasedCounter32 textual convention of the SMIv2.
value.type
= C_UINT32
union element = u32
C type = u_int32_t
SMIv2 type = Counter32
64-bit counters, corresponding to the Counter64 type and the ZeroBasedCounter64 textual convention of the SMIv2.
value.type
= C_UINT64
union element = u64
C type = u_int64_t
SMIv2 type = Counter64
32-bit gauge value, corresponding to the Gauge32 type of the SMIv2.
value.type
= C_UINT32
union element = u32
C type = u_int32_t
SMIv2 type = Counter32
64-bit gauge value, corresponding to the CounterBasedGauge64 SMIv2 textual convention.
value.type
= C_UINT64
union element = u64
C type = u_int64_t
SMIv2 type = Counter64
An SNMP OBJECT IDENTIFIER (OID). This is a sequence of integers which identifies an object instance for example "1.3.6.1.4.1.24961.1".
The tailf:value-length
restriction is
measured in integer elements for
object-identifier and
object-identifier-128.
value.type
= C_OID
union element = oidp
C type = confd_snmp_oid
SMIv2 type = OBJECT IDENTIFIER
A YANG identifier string as defined by the 'identifier' rule in Section 12 of RFC 6020.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The date-and-time type is a profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.
value.type
= C_DATETIME
union element = datetime
C type = struct confd_datetime
SMIv2 type = DateAndTime
Time ticks and time stamps, measured in hundredths of seconds. Corresponding to the TimeTicks type and the TimeStamp textual convention of the SMIv2.
value.type
= C_UINT32
union element = u32
C type = u_int32_t
SMIv2 type = Counter32
Represents media- or physical-level addresses represented as a sequence octets, each octet represented by two hexadecimal digits. Octets are separated by colons.
The tailf:value-length
restriction is
measured in number of octets for
phys-address.
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The mac-address type represents an IEEE 802 MAC address.
The length of the ConfD C_BINARY representation is always 6.
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
This type represents an XPATH 1.0 expression.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
A hexadecimal string with octets represented as hex digits separated by colons.
The tailf:value-length
restriction is
measured in number of octets for
hex-string.
value.type
= C_HEXSTR
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
A Universally Unique Identifier in the string representation defined in RFC 4122.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
An unsigned 32-bit number expressed in the dotted-quad notation.
value.type
= C_DQUAD
union element = dquad
C type = struct confd_dotted_quad
SMIv2 type = OCTET STRING
This module contains a collection of generally useful derived
YANG data types for Internet addresses and related things. They are
defined in the urn:ietf:params:xml:ns:yang:inet-types
namespace.
This value represents the version of the IP protocol.
value.type
= C_ENUM_VALUE
union element = enumvalue
C type = int32_t
SMIv2 type = INTEGER
The dscp type represents a Differentiated Services Code-Point.
value.type
= C_UINT8
union element = u8
C type = u_int8_t
SMIv2 type = Unsigned32 (0 .. 255)
The flow-label type represents flow identifier or Flow Label in an IPv6 packet header.
value.type
= C_UINT32
union element = u32
C type = u_int32_t
SMIv2 type = Unsigned32
The port-number type represents a 16-bit port number of an Internet transport layer protocol such as UDP, TCP, DCCP or SCTP.
The value space and representation is identical to the built-in uint16 type.
The as-number type represents autonomous system numbers which identify an Autonomous System (AS).
The value space and representation is identical to the built-in uint32 type.
The ip-address type represents an IP address and is IP version neutral. The format of the textual representations implies the IP version.
This is a union of the inet:ipv4-address and inet:ipv6-address types defined below. The representation is thus identical to the representation for one of these types.
The SMIv2 type is an OCTET STRING (SIZE (4|16)).
The ipv4-address type represents an IPv4 address in dotted-quad notation.
The use of a zone index is not supported by ConfD.
value.type
= C_IPV4
union element = ip
C type = struct in_addr
SMIv2 type = IpAddress
The ipv6-address type represents an IPv6 address in full, mixed, shortened and shortened mixed notation.
The use of a zone index is not supported by ConfD.
value.type
= C_IPV6
union element = ip6
C type = struct in6_addr
SMIv2 type = IPV6-MIB:Ipv6Address
The ip-prefix type represents an IP prefix and is IP version neutral. The format of the textual representations implies the IP version.
This is a union of the inet:ipv4-prefix and inet:ipv6-prefix types defined below. The representation is thus identical to the representation for one of these types.
The SMIv2 type is an OCTET STRING (SIZE (5|17)).
The ipv4-prefix type represents an IPv4 address prefix. The prefix length is given by the number following the slash character and must be less than or equal to 32.
A prefix length value of n corresponds to an IP address mask which has n contiguous 1-bits from the most significant bit (MSB) and all other bits set to 0.
The IPv4 address represented in dotted quad notation must have all bits that do not belong to the prefix set to zero.
An example: 10.0.0.0/8
value.type
= C_IPV4PREFIX
union element = ipv4prefix
C type = struct confd_ipv4_prefix
SMIv2 type = OCTET STRING (SIZE (5))
The ipv6-prefix type represents an IPv6 address prefix. The prefix length is given by the number following the slash character and must be less than or equal 128.
A prefix length value of n corresponds to an IP address mask which has n contiguous 1-bits from the most significant bit (MSB) and all other bits set to 0.
The IPv6 address must have all bits that do not belong to the prefix set to zero.
An example: 2001:DB8::1428:57AB/125
value.type
= C_IPV6PREFIX
union element = ipv6prefix
C type = struct confd_ipv6_prefix
SMIv2 type = OCTET STRING (SIZE (17))
The domain-name type represents a DNS domain name. The name SHOULD be fully qualified whenever possible.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The host type represents either an IP address or a DNS domain name.
This is a union of the inet:ip-address and inet:domain-name types defined above. The representation is thus identical to the representation for one of these types.
The SMIv2 type is an OCTET STRING, which contains the textual representation of the domain name or address.
The uri type represents a Uniform Resource Identifier (URI) as defined by STD 66.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
This module defines a type for storing passwords using a hash
function, and features to indicate which hash functions are
supported by an implementation. The type is defined in the urn:ietf:params:xml:ns:yang:iana-crypt-hash
namespace.
The crypt-hash type is used to store passwords using a hash function. The algorithms for applying the hash function and encoding the result are implemented in various UNIX systems as the function crypt(3). A value of this type matches one of the forms:
$0$<clear text password> $<id>$<salt>$<password hash> $<id>$<parameter>$<salt>$<password hash>
The "$0$" prefix indicates that the value is clear text. When such a value is received by the server, a hash value is calculated, and the string "$<id>$<salt>$" or $<id>$<parameter>$<salt>$ is prepended to the result. This value is stored in the configuration data store.
If a value starting with "$<id>$", where <id> is not "0", is received, the server knows that the value already represents a hashed value, and stores it as is in the data store.
In the Tail-f implementation, this type is logically a
union of the types tailf:md5-digest-string,
tailf:sha-256-digest-string, and tailf:sha-512-digest-string -
see the section The
tailf-common YANG module below. All the hashed values
of these types are accepted, and the choice of algorithm to
use for hashing clear text is specified via the
/confdConfig/cryptHash/algorithm
parameter in
confd.conf
(see confd.conf(5)). If the
algorithm is set to "sha-256" or "sha-512", it can be tuned
via the /confdConfig/cryptHash/rounds
parameter in
confd.conf
.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
This module defines Tail-f common YANG types, that are built-in to ConfD.
A value that represents a number of bytes. An example could be S1G8M7K956B; meaning 1GB+8MB+7KB+956B = 1082138556 bytes. The value must start with an S. Any byte magnifier can be left out, i.e. S1K1B equals 1025 bytes. The order is significant though, i.e. S1B56G is not a valid byte size.
The value space and representation is identical to the built-in uint64 type.
A list of dot-separated octets for example "192.168.255.1.0".
The tailf:value-length
restriction is
measured in number of octets for
octet-list.
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
A list of colon-separated hexa-decimal octets for example "4F:4C:41:71".
The tailf:value-length
restriction is
measured in octets of binary data for
hex-list.
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The md5-digest-string type automatically computes a MD5 digest for a value adhering to this type.
This is best explained using an example. Suppose we have a leaf:
leaf key { type tailf:md5-digest-string; }
A valid configuration is:
<key>$0$In god we trust.</key>
The "$0$" prefix indicates that this is plain text and that this value should be represented as a MD5 digest from now. ConfD computes a MD5 digest for the value and prepends "$1$<salt>$", where <salt> is a random eight character salt used to generate the digest. When this value later on is fetched from ConfD the following is returned:
<key>$1$fB$ndk2z/PIS0S1SvzWLqTJb.</key>
A value adhering to md5-digest-string must have "$0$" or a "$1$<salt>$" prefix.
The digest algorithm is the same as the md5 crypt function used for encrypting passwords for various UNIX systems, e.g. http://www.freebsd.org/cgi/cvsweb.cgi/~checkout~/src/lib/libcrypt/crypt.c?rev=1.5&content-type=text/plain
The pattern
restriction can not be used
with this type.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The sha-256-digest-string type automatically computes a SHA-256 digest for a value adhering to this type. A value of this type matches one of the forms:
$0$<clear text password> $5$<salt>$<password hash> $5$rounds=<number>$<salt>$<password hash>
The "$0$" prefix indicates that this is plain text. When
a plain text value is received by the server, a SHA-256 digest
is calculated, and the string "$5$<salt>$" is prepended
to the result, where <salt> is a random 16 character
salt used to generate the digest. This value is stored in the
configuration data store. The algorithm can be tuned via the
/confdConfig/cryptHash/rounds
parameter in
confd.conf
(see confd.conf(5)), which if
set to a number other than the default will cause
"$5$rounds=<number>$<salt>$" to be prepended
instead of only "$5$<salt>$".
If a value starting with "$5$" is received, the server knows that the value already represents a SHA-256 digest, and stores it as is in the data store.
The digest algorithm used is the same as the SHA-256 crypt function used for encrypting passwords for various UNIX systems, see e.g. http://www.akkadia.org/drepper/SHA-crypt.txt
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The sha-512-digest-string type automatically computes a SHA-512 digest for a value adhering to this type. A value of this type matches one of the forms:
$0$<clear text password> $6$<salt>$<password hash> $6$rounds=<number>$<salt>$<password hash>
The "$0$" prefix indicates that this is plain text. When
a plain text value is received by the server, a SHA-512 digest
is calculated, and the string "$6$<salt>$" is prepended
to the result, where <salt> is a random 16 character
salt used to generate the digest. This value is stored in the
configuration data store. The algorithm can be tuned via the
/confdConfig/cryptHash/rounds
parameter in
confd.conf
(see confd.conf(5)), which if
set to a number other than the default will cause
"$6$rounds=<number>$<salt>$" to be prepended
instead of only "$6$<salt>$".
If a value starting with "$6$" is received, the server knows that the value already represents a SHA-512 digest, and stores it as is in the data store.
The digest algorithm used is the same as the SHA-512 crypt function used for encrypting passwords for various UNIX systems, see e.g. http://www.akkadia.org/drepper/SHA-crypt.txt
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The des3-cbc-encrypted-string type automatically encrypts a value adhering to this type using DES in CBC mode followed by a base64 conversion. If the value isn't encrypted already, that is.
This is best explained using an example. Suppose we have a leaf:
leaf enc { type tailf:des3-cbc-encrypted-string; }
A valid configuration is:
<enc>$0$In god we trust.</enc>
The "$0$" prefix indicates that this is plain text. When a plain text value is received by the server, the value is DES3/Base64 encrypted, and the string "$7$" is prepended. The resulting string is stored in the configuration data store.
When a value of this type is read, the encrypted value is always returned. In the example above, the following value could be returned:
<enc>$7$Qxxsn8BVzxphCdflqRwZm6noKKmt0QoSWnRnhcXqocg=</enc>
If a value starting with "$7$" is received, the server knows that the value is already encrypted, and stores it as is in the data store.
A value adhering to this type must have a "$0$" or a "$7$" prefix.
ConfD uses a configurable set of encryption keys to
encrypt the string. For details, see the description of
the encryptedStrings
configurable in the confd.conf(5) manual
page.
The pattern
restriction can not be used
with this type.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The aes-cfb-128-encrypted-string works exactly like des3-cbc-encrypted-string but AES/128bits in CFB mode is used to encrypt the string. The prefix for encrypted values is "$8$".
The pattern
restriction can not be used
with this type.
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
The ip-address-and-prefix-length type represents a combination of an IP address and a prefix length and is IP version neutral. The format of the textual representations implies the IP version.
This is a union of the tailf:ipv4-address-and-prefix-length and tailf:ipv6-address-and-prefix-length types defined below. The representation is thus identical to the representation for one of these types.
The SMIv2 type is an OCTET STRING (SIZE (5|17)).
The ipv4-address-and-prefix-length type represents a combination of an IPv4 address and a prefix length. The prefix length is given by the number following the slash character and must be less than or equal to 32.
An example: 172.16.1.2/16
value.type
= C_IPV4_AND_PLEN
union element = ipv4prefix
C type = struct confd_ipv4_prefix
SMIv2 type = OCTET STRING (SIZE (5))
The ipv6-address-and-prefix-length type represents a combination of an IPv6 address and a prefix length. The prefix length is given by the number following the slash character and must be less than or equal to 128.
An example: 2001:DB8::1428:57AB/64
value.type
= C_IPV6_AND_PLEN
union element = ipv6prefix
C type = struct confd_ipv6_prefix
SMIv2 type = OCTET STRING (SIZE (17))
"This module contains useful XML Schema Datatypes that are not covered by YANG types directly.
value.type
= C_DURATION
union element = duration
C type = struct confd_duration
SMIv2 type = OCTET STRING
value.type
= C_DATE
union element = date
C type = struct confd_date
SMIv2 type = OCTET STRING
value.type
= C_TIME
union element = time
C type = struct confd_time
SMIv2 type = OCTET STRING
value.type
= C_BUF
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
value.type
= C_BINARY
union element = buf
C type = confd_buf_t
SMIv2 type = OCTET STRING
value.type
= C_QNAME
union element =qname
C type = struct confd_qname
SMIv2 type = <not applicable>
value.type
= C_DOUBLE
union element = d
C type = double
SMIv2 type = OCTET STRING