28RCSID(
"$Id: a6db746ba7611bcb6c0159a8aaea715ff119a463 $")
30#include <freeradius-devel/util/atexit.h>
31#include <freeradius-devel/util/debug.h>
33#include <freeradius-devel/util/misc.h>
34#include <freeradius-devel/util/proto.h>
35#include <freeradius-devel/util/value.h>
37#include <freeradius-devel/server/dependency.h>
38#include <freeradius-devel/server/main_loop.h>
39#include <freeradius-devel/server/snmp.h>
41#include <freeradius-devel/protocol/snmp/freeradius.h>
65#define FR_FREERADIUS_SNMP_TYPE_OBJECT 0
67#define SNMP_MAP_TERMINATOR { .name = NULL, .da = NULL, .type = 0 }
106static int reset_state = FR_RADIUS_AUTH_SERV_CONFIG_RESET_VALUE_RUNNING;
170 switch (
in->vb_uint32) {
171 case FR_RADIUS_AUTH_SERV_CONFIG_RESET_VALUE_RESET:
177 return -(FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_VALUE);
200 if (index_num == 0)
return 1;
202 if (!client)
return 1;
204 *snmp_ctx_out = client;
236 if (client->
ipaddr.
af != AF_INET)
return 0;
237 memcpy(&
out->vb_ip, &client->
ipaddr,
sizeof(
out->vb_ip));
269 { .
name =
"Radius-Auth-Client-Index",
270 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_INTEGER,
272 { .name =
"Radius-Auth-Client-Address",
273 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_IPADDRESS,
275 { .name =
"Radius-Auth-Client-ID",
276 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_STRING,
278 { .name =
"Radius-Auth-Serv-Access-Requests",
279 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
280 .offset = offsetof(
fr_stats_t, total_requests),
282 { .name =
"Radius-Auth-Serv-Dup-Access-Requests",
283 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
284 .offset = offsetof(
fr_stats_t, total_dup_requests),
286 { .name =
"Radius-Auth-Serv-Access-Accepts",
287 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
288 .offset = offsetof(
fr_stats_t, total_access_accepts),
290 { .name =
"Radius-Auth-Serv-Access-Rejects",
291 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
292 .offset = offsetof(
fr_stats_t, total_access_rejects),
294 { .name =
"Radius-Auth-Serv-Access-Challenges",
295 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
296 .offset = offsetof(
fr_stats_t, total_access_challenges),
298 { .name =
"Radius-Auth-Serv-Malformed-Access-Requests",
299 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
300 .offset = offsetof(
fr_stats_t, total_malformed_requests),
302 { .name =
"Radius-Auth-Serv-Bad-Authenticators",
303 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
304 .offset = offsetof(
fr_stats_t, total_bad_authenticators),
306 { .name =
"Radius-Auth-Serv-Packets-Dropped",
307 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
308 .offset = offsetof(
fr_stats_t, total_packets_dropped),
310 { .name =
"Radius-Auth-Serv-Unknown-Types",
311 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
312 .offset = offsetof(
fr_stats_t, total_unknown_types),
318 { .
name =
"Radius-Auth-Client-Entry",
326 { .
name =
"Radius-Auth-Serv-Ident",
327 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_STRING,
329 { .name =
"Radius-Auth-Serv-Up-Time",
330 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_TIMETICKS,
332 { .name =
"Radius-Auth-Serv-Reset-Time",
333 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_TIMETICKS,
335 { .name =
"Radius-Auth-Serv-Config-Reset",
336 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_INTEGER,
339 { .name =
"Radius-Auth-Serv-Total-Access-Requests",
340 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
341 .offset = offsetof(
fr_stats_t, total_requests),
343 { .name =
"Radius-Auth-Serv-Total-Invalid-Requests",
344 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
345 .offset = offsetof(
fr_stats_t, total_invalid_requests),
347 { .name =
"Radius-Auth-Serv-Total-Dup-Access-Requests",
348 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
349 .offset = offsetof(
fr_stats_t, total_dup_requests),
351 { .name =
"Radius-Auth-Serv-Total-Access-Accepts",
352 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
353 .offset = offsetof(
fr_stats_t, total_access_accepts),
355 { .name =
"Radius-Auth-Serv-Total-Access-Rejects",
356 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
357 .offset = offsetof(
fr_stats_t, total_access_rejects),
359 { .name =
"Radius-Auth-Serv-Total-Access-Challenges",
360 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
361 .offset = offsetof(
fr_stats_t, total_access_challenges),
363 { .name =
"Radius-Auth-Serv-Total-Malformed-Access-Requests",
364 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
365 .offset = offsetof(
fr_stats_t, total_malformed_requests),
367 { .name =
"Radius-Auth-Serv-Total-Bad-Authenticators",
368 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
369 .offset = offsetof(
fr_stats_t, total_bad_authenticators),
371 { .name =
"Radius-Auth-Serv-Total-Packets-Dropped",
372 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
373 .offset = offsetof(
fr_stats_t, total_packets_dropped),
375 { .name =
"Radius-Auth-Serv-Total-Unknown-Types",
376 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
377 .offset = offsetof(
fr_stats_t, total_unknown_types),
379 { .name =
"Radius-Auth-Client-table",
386 { .
name =
"Radius-Auth-Serv",
393 { .
name =
"Radius-Auth-Serv-Mib-Objects",
400 { .
name =
"Radius-Auth-Serv-Mib",
407 { .
name =
"Radius-Authentication",
414 { .
name =
"Radius-Mib",
421 { .
name =
"FreeRADIUS-Mib-2",
428 { .
name =
"FreeRADIUS-Mgmt",
435 { .
name =
"FreeRADIUS-Internet",
442 { .
name =
"FreeRADIUS-Dod",
449 { .
name =
"FreeRADIUS-Org",
456 { .
name =
"FreeRADIUS-Iso",
465 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op);
487 if (p->
da->attr == da->attr)
return p;
491 m = p + ((q - p) / 2);
494 if (m->da->attr < da->attr) p = m + 1;
495 else if (m->da->attr == da->attr)
break;
497 m = p + ((q - p) / 2);
499 if (p > q)
return NULL;
520 da_stack->
da[i] = map_p->
da;
521 map_p = map_p->
child;
529 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op,
539 void *this_snmp_ctx = NULL;
542 for (i = index_num; i < UINT32_MAX; i++) {
546 tmp_ctx = talloc_new(request);
552 ret = map->
index(tmp_ctx, &this_snmp_ctx, map, snmp_ctx, i);
560 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) {
572 map->
child, this_snmp_ctx, snmp_op);
573 TALLOC_FREE(tmp_ctx);
575 if (ret < 0)
return ret;
577 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT)
goto invalid;
590 this_snmp_ctx = NULL;
620 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
628 if (map[0].last < &map[1]) {
646 fr_strerror_printf(
"Bad index attribute: Index attribute \"%s\" should be a integer, "
647 "but is a %s", da_stack->
da[
depth]->name,
660 index_num =
vp->vp_uint32;
676 &map[1], snmp_ctx, snmp_op,
683 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
723 map_p, snmp_ctx, snmp_op,
731 map_p->
child, snmp_ctx, snmp_op);
732 if (ret < 0)
return ret;
734 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT)
goto invalid;
735 if (++map_p <= map[0].last)
continue;
745 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
769 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT:
770 if (map_p == map[0].last) {
784 map_p->
child, snmp_ctx, snmp_op);
789 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GET:
814 if (map_p->
get(request->reply, &
data, map_p, snmp_ctx) < 0)
goto error;
821 vp->vp_uint32 = map_p->
type;
826 case FR_FREERADIUS_SNMP_OPERATION_VALUE_SET:
832 vp->vp_uint32 = FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE;
838 ret = map_p->
set(map_p, snmp_ctx, &
vp->data);
839 if (ret < 0)
switch (-(ret)) {
840 case FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE:
841 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_TYPE:
842 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_LENGTH:
843 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_VALUE:
844 case FR_FREERADIUS_SNMP_FAILURE_VALUE_INCONSISTENT_VALUE:
846 vp->vp_uint32 = -(ret);
881 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
893 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) {
909 map, snmp_ctx, snmp_op);
919 map, snmp_ctx, snmp_op);
928 map, snmp_ctx, snmp_op);
933 fr_dcursor_t request_cursor, op_cursor, out_cursor, reply_cursor;
952 RDEBUG2(
"Processing SNMP stats request");
967 if (!
vp->
da->flags.is_unknown)
continue;
971 WARN(
"Failed converting \"%s\" to a known attribute",
vp->
da->name);
975 RDEBUG2(
"Unknown attribute \"%s\" resolves to \"%s\"",
vp->
da->name, da->name);
983 RPWARN(
"Failed converting unknown attribute to known attribute");
1016 switch (op->vp_uint32) {
1017 case FR_FREERADIUS_SNMP_OPERATION_VALUE_PING:
1018 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GET:
1019 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT:
1020 case FR_FREERADIUS_SNMP_OPERATION_VALUE_SET:
1024 ERROR(
"Invalid operation %u", op->vp_uint32);
1046 da_stack.
da[da_stack.
depth - 1],
false);
1068 for (i = 0; map[i].
name; i++) {
1076 ERROR(
"Incomplete dictionary: Missing definition for \"%s\"", map[i].
name);
1081 if (ret < 0)
return -1;
1088 ERROR(
"Incomplete dictionary: Missing definition for \"%s\"", map[i].
name);
1100 memmove(&map[1], map,
sizeof(*map) * i);
1101 memset(&map[0], 0,
sizeof(*map));
1102 map[0].
name =
"Not the map offset you were looking for";
1103 map[0].last = &map[i];
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
Insert a single item at the end of the list.
static void fr_dcursor_merge(fr_dcursor_t *cursor, fr_dcursor_t *to_append)
Moves items from one cursor to another.
static void * fr_dcursor_next_peek(fr_dcursor_t *cursor)
Return the next iterator item without advancing the cursor.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
static void * fr_dcursor_head(fr_dcursor_t *cursor)
Rewind cursor to the start of the list.
static int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
Insert a single item at the start of the list.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
char const * radiusd_version_short
fr_dict_attr_t const * fr_dict_attr_unknown_resolve(fr_dict_t const *dict, fr_dict_attr_t const *da)
Check to see if we can convert a nested TLV structure to known attributes.
#define fr_dict_autofree(_to_free)
fr_dict_attr_t const * fr_dict_attr_common_parent(fr_dict_attr_t const *a, fr_dict_attr_t const *b, bool is_ancestor)
Find a common ancestor that two TLV type attributes share.
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_attr_err_t *err, fr_dict_attr_t const *parent, char const *attr))
Locate a fr_dict_attr_t by its name.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
#define fr_dict_autoload(_to_load)
#define FR_DICT_MAX_TLV_STACK
Maximum TLV stack size.
#define DICT_AUTOLOAD_TERMINATOR
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
fr_ipaddr_t ipaddr
IPv4/IPv6 address of the host.
fr_stats_t auth
Authentication stats.
char const * longname
Client identifier.
int number
Unique client number.
Describes a host allowed to send packets to the server.
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
void main_loop_signal_raise(int flag)
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_TLV
Contains nested attributes.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
ssize_t fr_dict_attr_oid_print(fr_sbuff_t *out, fr_dict_attr_t const *ancestor, fr_dict_attr_t const *da, bool numeric)
static uint8_t depth(fr_minmax_heap_index_t i)
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_reinit_from_da(fr_pair_list_t *list, fr_pair_t *vp, fr_dict_attr_t const *da)
Re-initialise an attribute with a different da.
void fr_proto_da_stack_build(fr_da_stack_t *stack, fr_dict_attr_t const *da)
Build a complete DA stack from the da back to the root.
#define FR_SBUFF_OUT(_start, _len_or_end)
#define fr_sbuff_in_char(_sbuff,...)
fr_stats_t radius_auth_stats
fr_snmp_get_func_t get
Function to retrieve value.
static fr_snmp_map_t snmp_auth_serv[]
fr_snmp_index_func_t index
Function for traversing indexes.
static fr_snmp_map_t snmp_radius_mib[]
static ssize_t snmp_process_tlv(fr_dcursor_t *out, request_t *request, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
static fr_snmp_map_t snmp_auth_client_entry[]
static fr_snmp_map_t snmp_mgmt[]
static fr_snmp_map_t const * snmp_map_search(fr_snmp_map_t const map[], fr_dict_attr_t const *da)
Perform a binary search to find a map matching a da.
static int _fr_snmp_init(UNUSED void *uctx)
static fr_snmp_map_t snmp_auth_serv_mib[]
static int snmp_value_uptime_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, UNUSED void *snmp_ctx)
static fr_time_t start_time
static int snmp_config_reset_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, UNUSED void *snmp_ctx)
char const * name
Attribute number.
static int snmp_auth_client_stats_offset_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, fr_snmp_map_t const *map, void *snmp_ctx)
fr_snmp_set_func_t set
Function to write a new value.
static fr_time_t reset_time
static fr_dict_t const * dict_snmp
static fr_dict_attr_t const * attr_snmp_root
static fr_snmp_map_t snmp_auth_serv_counters[]
static void snmp_next_leaf(fr_da_stack_t *da_stack, unsigned int depth, fr_snmp_map_t const *map)
Perform depth first traversal of the tree until we hit a leaf node.
int(* fr_snmp_index_func_t)(TALLOC_CTX *ctx, void **snmp_ctx_out, fr_snmp_map_t const *map, void const *snmp_ctx_in, uint32_t index)
int(* fr_snmp_set_func_t)(fr_snmp_map_t const *map, void *snmp_ctx, fr_value_box_t *data)
#define FR_FREERADIUS_SNMP_TYPE_OBJECT
static ssize_t snmp_process_index(fr_dcursor_t *out, request_t *request, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op, uint32_t index_num)
static int snmp_client_ipv4addr_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, void *snmp_ctx)
static fr_snmp_map_t snmp_iso[]
static int _fr_snmp_init_r(fr_snmp_map_t map[], fr_dict_attr_t const *parent)
Internal SNMP initialisation function (used for recursion)
static fr_snmp_map_t snmp_mib_2[]
fr_dict_attr_autoload_t snmp_dict_attr[]
int fr_snmp_process(request_t *request)
static int snmp_config_reset_set(NDEBUG_UNUSED fr_snmp_map_t const *map, UNUSED void *snmp_ctx, fr_value_box_t *in)
static ssize_t snmp_process_leaf(fr_dcursor_t *out, request_t *request, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
static fr_snmp_map_t snmp_authentication[]
static int snmp_auth_stats_offset_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, fr_snmp_map_t const *map, UNUSED void *snmp_ctx)
static int snmp_client_index_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, UNUSED fr_snmp_map_t const *map, void *snmp_ctx)
int(* fr_snmp_get_func_t)(TALLOC_CTX *ctx, fr_value_box_t *out, fr_snmp_map_t const *map, void *snmp_ctx)
static int _fr_snmp_free(UNUSED void *uctx)
static fr_snmp_map_t snmp_org[]
static int snmp_client_index(UNUSED TALLOC_CTX *ctx, void **snmp_ctx_out, UNUSED fr_snmp_map_t const *map, NDEBUG_UNUSED void const *snmp_ctx_in, uint32_t index_num)
static fr_snmp_map_t snmp_dod[]
static int snmp_value_serv_ident_get(TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, UNUSED void *snmp_ctx)
int fr_snmp_init(void)
Initialise the tree of SNMP map structures used to attach callbacks to OIDs.
static fr_dict_attr_t const * attr_snmp_failure
unsigned int type
SNMP type - More specific than attribute type.
static fr_dict_attr_t const * attr_snmp_type
static ssize_t snmp_process(fr_dcursor_t *out, request_t *request, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
Traverse a tree of SNMP maps.
fr_dict_autoload_t snmp_dict[]
fr_snmp_map_t * child
Child map.
static int snmp_config_reset_time_get(UNUSED TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, UNUSED void *snmp_ctx)
static ssize_t snmp_process_index_attr(fr_dcursor_t *out, request_t *request, fr_da_stack_t *da_stack, unsigned int depth, fr_dcursor_t *cursor, fr_snmp_map_t const *map, void *snmp_ctx, unsigned int snmp_op)
fr_dict_attr_t const * da
Dictionary attribute (resolved from attribute number).
static int snmp_client_id_get(TALLOC_CTX *ctx, fr_value_box_t *out, NDEBUG_UNUSED fr_snmp_map_t const *map, void *snmp_ctx)
static fr_dict_attr_t const * attr_snmp_operation
static fr_snmp_map_t snmp_auth_serv_mib_objects[]
static fr_snmp_map_t snmp_internet[]
#define SNMP_MAP_TERMINATOR
static fr_snmp_map_t snmp_auth_client_entry_counters[]
Maps a fr_pair_t to the source of a value.
fr_client_t * client_findbynumber(UNUSED const fr_client_list_t *clients, UNUSED int number)
fr_aka_sim_id_type_t type
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
static int64_t fr_time_delta_to_csec(fr_time_delta_t delta)
#define fr_time_sub(_a, _b)
Subtract one time from another.
A time delta, a difference in time measured in nanoseconds.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
#define fr_pair_dcursor_by_ancestor_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes descended from the specified fr_dict_attr_t.
#define FR_PROTO_STACK_PRINT(_stack, _depth)
uint8_t depth
Deepest attribute in the stack.
fr_dict_attr_t const * da[FR_DICT_MAX_TLV_STACK+1]
The stack.
Structure for holding the stack of dictionary attributes being encoded.
char const * fr_strerror(void)
Get the last library error.
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
int fr_value_box_bstrdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated talloced buffer to a fr_value_box_t.
int fr_value_box_asprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt,...)
Print a formatted string using our internal printf wrapper and assign it to a value box.
int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
Copy value data verbatim moving any buffers to the specified context.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
static size_t char ** out