28RCSID(
"$Id: eda926ec56b4c1e04b26f859349bfccd2a71109c $")
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);
201 if (!client)
return 1;
203 *snmp_ctx_out = client;
235 if (client->
ipaddr.
af != AF_INET)
return 0;
236 memcpy(&
out->vb_ip, &client->
ipaddr,
sizeof(
out->vb_ip));
268 { .
name =
"Radius-Auth-Client-Index",
269 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_INTEGER,
271 { .name =
"Radius-Auth-Client-Address",
272 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_IPADDRESS,
274 { .name =
"Radius-Auth-Client-ID",
275 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_STRING,
277 { .name =
"Radius-Auth-Serv-Access-Requests",
278 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
279 .offset = offsetof(
fr_stats_t, total_requests),
281 { .name =
"Radius-Auth-Serv-Dup-Access-Requests",
282 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
283 .offset = offsetof(
fr_stats_t, total_dup_requests),
285 { .name =
"Radius-Auth-Serv-Access-Accepts",
286 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
287 .offset = offsetof(
fr_stats_t, total_access_accepts),
289 { .name =
"Radius-Auth-Serv-Access-Rejects",
290 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
291 .offset = offsetof(
fr_stats_t, total_access_rejects),
293 { .name =
"Radius-Auth-Serv-Access-Challenges",
294 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
295 .offset = offsetof(
fr_stats_t, total_access_challenges),
297 { .name =
"Radius-Auth-Serv-Malformed-Access-Requests",
298 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
299 .offset = offsetof(
fr_stats_t, total_malformed_requests),
301 { .name =
"Radius-Auth-Serv-Bad-Authenticators",
302 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
303 .offset = offsetof(
fr_stats_t, total_bad_authenticators),
305 { .name =
"Radius-Auth-Serv-Packets-Dropped",
306 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
307 .offset = offsetof(
fr_stats_t, total_packets_dropped),
309 { .name =
"Radius-Auth-Serv-Unknown-Types",
310 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
311 .offset = offsetof(
fr_stats_t, total_unknown_types),
317 { .
name =
"Radius-Auth-Client-Entry",
325 { .
name =
"Radius-Auth-Serv-Ident",
326 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_STRING,
328 { .name =
"Radius-Auth-Serv-Up-Time",
329 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_TIMETICKS,
331 { .name =
"Radius-Auth-Serv-Reset-Time",
332 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_TIMETICKS,
334 { .name =
"Radius-Auth-Serv-Config-Reset",
335 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_INTEGER,
338 { .name =
"Radius-Auth-Serv-Total-Access-Requests",
339 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
340 .offset = offsetof(
fr_stats_t, total_requests),
342 { .name =
"Radius-Auth-Serv-Total-Invalid-Requests",
343 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
344 .offset = offsetof(
fr_stats_t, total_invalid_requests),
346 { .name =
"Radius-Auth-Serv-Total-Dup-Access-Requests",
347 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
348 .offset = offsetof(
fr_stats_t, total_dup_requests),
350 { .name =
"Radius-Auth-Serv-Total-Access-Accepts",
351 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
352 .offset = offsetof(
fr_stats_t, total_access_accepts),
354 { .name =
"Radius-Auth-Serv-Total-Access-Rejects",
355 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
356 .offset = offsetof(
fr_stats_t, total_access_rejects),
358 { .name =
"Radius-Auth-Serv-Total-Access-Challenges",
359 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
360 .offset = offsetof(
fr_stats_t, total_access_challenges),
362 { .name =
"Radius-Auth-Serv-Total-Malformed-Access-Requests",
363 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
364 .offset = offsetof(
fr_stats_t, total_malformed_requests),
366 { .name =
"Radius-Auth-Serv-Total-Bad-Authenticators",
367 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
368 .offset = offsetof(
fr_stats_t, total_bad_authenticators),
370 { .name =
"Radius-Auth-Serv-Total-Packets-Dropped",
371 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
372 .offset = offsetof(
fr_stats_t, total_packets_dropped),
374 { .name =
"Radius-Auth-Serv-Total-Unknown-Types",
375 .type = FR_FREERADIUS_SNMP_TYPE_VALUE_COUNTER,
376 .offset = offsetof(
fr_stats_t, total_unknown_types),
378 { .name =
"Radius-Auth-Client-table",
385 { .
name =
"Radius-Auth-Serv",
392 { .
name =
"Radius-Auth-Serv-Mib-Objects",
399 { .
name =
"Radius-Auth-Serv-Mib",
406 { .
name =
"Radius-Authentication",
413 { .
name =
"Radius-Mib",
420 { .
name =
"FreeRADIUS-Mib-2",
427 { .
name =
"FreeRADIUS-Mgmt",
434 { .
name =
"FreeRADIUS-Internet",
441 { .
name =
"FreeRADIUS-Dod",
448 { .
name =
"FreeRADIUS-Org",
455 { .
name =
"FreeRADIUS-Iso",
464 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op);
486 if (p->
da->attr == da->attr)
return p;
490 m = p + ((q - p) / 2);
493 if (m->da->attr < da->attr) p = m + 1;
494 else if (m->da->attr == da->attr)
break;
496 m = p + ((q - p) / 2);
498 if (p > q)
return NULL;
519 da_stack->
da[i] = map_p->
da;
520 map_p = map_p->
child;
528 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op,
538 void *this_snmp_ctx = NULL;
541 for (i = index_num; i < UINT32_MAX; i++) {
545 tmp_ctx = talloc_new(request);
551 ret = map->
index(tmp_ctx, &this_snmp_ctx, map, snmp_ctx, i);
559 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) {
571 map->
child, this_snmp_ctx, snmp_op);
572 TALLOC_FREE(tmp_ctx);
574 if (ret < 0)
return ret;
576 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT)
goto invalid;
589 this_snmp_ctx = NULL;
619 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
627 if (map[0].last < &map[1]) {
645 fr_strerror_printf(
"Bad index attribute: Index attribute \"%s\" should be a integer, "
646 "but is a %s", da_stack->
da[
depth]->name,
655 index_num =
vp->vp_uint32;
671 &map[1], snmp_ctx, snmp_op,
678 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
718 map_p, snmp_ctx, snmp_op,
726 map_p->
child, snmp_ctx, snmp_op);
727 if (ret < 0)
return ret;
729 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT)
goto invalid;
730 if (++map_p <= map[0].last)
continue;
740 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
764 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT:
765 if (map_p == map[0].last) {
768 if (map_p->
da ==
vp->
da) {
779 map_p->
child, snmp_ctx, snmp_op);
784 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GET:
809 if (map_p->
get(request->reply, &
data, map_p, snmp_ctx) < 0)
goto error;
816 vp->vp_uint32 = map_p->
type;
821 case FR_FREERADIUS_SNMP_OPERATION_VALUE_SET:
827 vp->vp_uint32 = FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE;
833 ret = map_p->
set(map_p, snmp_ctx, &
vp->data);
834 if (ret < 0)
switch (-(ret)) {
835 case FR_FREERADIUS_SNMP_FAILURE_VALUE_NOT_WRITABLE:
836 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_TYPE:
837 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_LENGTH:
838 case FR_FREERADIUS_SNMP_FAILURE_VALUE_WRONG_VALUE:
839 case FR_FREERADIUS_SNMP_FAILURE_VALUE_INCONSISTENT_VALUE:
841 vp->vp_uint32 = -(ret);
876 fr_snmp_map_t const *map,
void *snmp_ctx,
unsigned int snmp_op)
888 if (snmp_op != FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT) {
904 map, snmp_ctx, snmp_op);
914 map, snmp_ctx, snmp_op);
923 map, snmp_ctx, snmp_op);
928 fr_dcursor_t request_cursor, op_cursor, out_cursor, reply_cursor;
947 RDEBUG2(
"Processing SNMP stats request");
962 if (!
vp->
da->flags.is_unknown)
continue;
966 WARN(
"Failed converting \"%s\" to a known attribute",
vp->
da->name);
970 RDEBUG2(
"Unknown attribute \"%s\" resolves to \"%s\"",
vp->
da->name, da->name);
978 RPWARN(
"Failed converting unknown attribute to known attribute");
1011 switch (op->vp_uint32) {
1012 case FR_FREERADIUS_SNMP_OPERATION_VALUE_PING:
1013 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GET:
1014 case FR_FREERADIUS_SNMP_OPERATION_VALUE_GETNEXT:
1015 case FR_FREERADIUS_SNMP_OPERATION_VALUE_SET:
1019 ERROR(
"Invalid operation %u",
vp->vp_uint32);
1041 da_stack.
da[da_stack.
depth - 1],
false);
1063 for (i = 0; map[i].
name; i++) {
1071 ERROR(
"Incomplete dictionary: Missing definition for \"%s\"", map[i].
name);
1076 if (ret < 0)
return -1;
1083 ERROR(
"Incomplete dictionary: Missing definition for \"%s\"", map[i].
name);
1095 memmove(&map[1], map,
sizeof(*map) * i);
1096 memset(&map[0], 0,
sizeof(*map));
1097 map[0].
name =
"Not the map offset you were looking for";
1098 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.
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
#define fr_time()
Allow us to arbitrarily manipulate time.
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