24 RCSID(
"$Id: 0ee32e8060ed6aa63d359be131147e9a7f62c19e $")
26 #define _PAIR_PRIVATE 1
27 #define _PAIR_INLINE 1
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/misc.h>
31 #include <freeradius-devel/util/pair.h>
32 #include <freeradius-devel/util/pair_legacy.h>
33 #include <freeradius-devel/util/proto.h>
34 #include <freeradius-devel/util/regex.h>
38 #include <freeradius-devel/util/pair_inline.c>
54 fr_pair_order_list_talloc_init(&list->order);
56 #ifdef WITH_VERIFY_PTR
57 list->verified =
true;
72 talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL);
88 if (likely(
vp->
da != NULL))
switch (
vp->vp_type) {
104 memset(
vp, 0,
sizeof(*
vp));
135 fr_pair_order_list_entry_init(
vp);
149 memset(
vp, 0,
sizeof(*
vp));
206 memset(&
vp->data, 0xff,
sizeof(
vp->data));
212 if (
sizeof(
vp->pad)) memset(
vp->pad, 0,
sizeof(
vp->pad));
222 vp->vp_group.is_child =
true;
223 fr_pair_order_list_talloc_init_children(
vp, &
vp->vp_group.order);
260 if (
unlikely(da->flags.is_unknown)) {
297 if (da->flags.is_unknown) {
321 if (
vp->
da && !
vp->
da->flags.is_raw) {
322 if (
vp->
da == da)
return 0;
421 for (i = start; i <= da->depth; i++) {
422 find = da_stack.
da[i];
436 if (!
vp || (
vp->
da == da)) {
440 if (find == da)
return vp;
445 cur_list = &
vp->vp_group;
469 if (da->depth <= 1) {
525 nvp = talloc_steal(ctx,
vp);
534 #define IN_A_LIST_MSG "Pair %pV is already in a list, and cannot be moved"
535 #define NOT_IN_THIS_LIST_MSG "Pair %pV is not in the given list"
548 if (fr_pair_order_list_in_a_list(
vp)) {
571 if (fr_pair_order_list_in_a_list(
vp)) {
604 if (!unknown)
return -1;
633 if (c->
da == da)
break;
673 unsigned int count = 0;
750 if (da !=
vp->
da)
continue;
752 if (idx == 0)
return vp;
793 find = &da_stack.
da[prev->
da->depth - 1];
797 find = &da_stack.
da[0];
821 if ((*find) == da)
return next;
826 cur_list = &
next->vp_group;
835 if (cur_list == list)
break;
878 if (!da)
return NULL;
904 if (!da)
return NULL;
921 return &
vp->vp_group;
931 if (!
vp)
return NULL;
933 parent = fr_pair_order_list_parent(
vp);
946 if (!list)
return NULL;
958 if (!list)
return NULL;
983 fr_pair_order_list_set_head(tlist,
vp);
1008 while (
parent && (tlist !=
vp->order_entry.entry.list_head)) {
1009 tlist = &
parent->order.head;
1013 fr_assert(
vp->order_entry.entry.list_head == tlist);
1020 fr_pair_order_list_set_head(NULL,
vp);
1024 if (&
parent->order.head.dlist_head == list)
return 0;
1048 if (!
vp)
goto next_parent_sibling;
1064 next_parent_sibling:
1066 if (!parent_list)
return NULL;
1073 if (parent_list == list)
return NULL;
1078 goto next_parent_sibling;
1107 return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order),
1128 return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order),
1147 return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order),
1178 list = &
vp->vp_group;
1180 return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order),
1185 return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order),
1271 if (!
vp)
return NULL;
1318 #ifdef WITH_VERIFY_PTR
1319 fr_assert(!fr_pair_order_list_in_a_list(to_add));
1320 list->verified =
false;
1323 if (fr_pair_order_list_in_a_list(to_add)) {
1328 fr_pair_order_list_insert_head(&list->order, to_add);
1349 #ifdef WITH_VERIFY_PTR
1350 fr_assert(!fr_pair_order_list_in_a_list(to_add));
1351 list->verified =
false;
1354 if (fr_pair_order_list_in_a_list(to_add)) {
1359 fr_pair_order_list_insert_tail(&list->order, to_add);
1377 #ifdef WITH_VERIFY_PTR
1378 fr_assert(!fr_pair_order_list_in_a_list(to_add));
1379 list->verified =
false;
1382 if (fr_pair_order_list_in_a_list(to_add)) {
1387 if (pos && !fr_pair_order_list_in_list(&list->order, pos)) {
1392 fr_pair_order_list_insert_after(&list->order, pos, to_add);
1410 #ifdef WITH_VERIFY_PTR
1411 fr_assert(!fr_pair_order_list_in_a_list(to_add));
1412 fr_assert(!pos || fr_pair_order_list_in_a_list(pos));
1413 list->verified =
false;
1416 if (fr_pair_order_list_in_a_list(to_add)) {
1421 if (pos && !fr_pair_order_list_in_list(&list->order, pos)) {
1426 fr_pair_order_list_insert_before(&list->order, pos, to_add);
1444 #ifdef WITH_VERIFY_PTR
1446 fr_assert(fr_pair_order_list_in_a_list(to_replace));
1447 list->verified =
false;
1528 TALLOC_CTX *pair_ctx = ctx;
1536 find = &da_stack.
da[0];
1563 if ((*find) == da) {
1571 list = &
vp->vp_group;
1602 TALLOC_CTX *pair_ctx =
parent;
1608 if (da->depth <= 1) {
1630 list = &
parent->vp_group;
1631 find = &da_stack.
da[
parent->da->depth];
1637 "But it is not an acestor and is of type %s",
parent->da->name, da->name,
1641 find = &da_stack.
da[0];
1666 if ((*find) == da) {
1674 list = &
vp->vp_group;
1736 find = &da_stack.
da[0];
1759 if ((*find) == da) {
1771 cur_list = &
next->vp_group;
1780 if (cur_list == list)
break;
1852 return CMP(my_a->
da, my_b->
da);
1867 unsigned int i,
min;
1884 for (i = 0; i <
min; i++) {
1885 rcode =
CMP(da_stack_a.
da[i]->attr, da_stack_b.
da[i]->attr);
1886 if (rcode != 0)
return rcode;
1894 rcode =
CMP(my_a->
da->depth, my_b->
da->depth);
1895 if (rcode != 0)
return rcode;
1900 rcode =
CMP(my_a->
da->parent->attr, my_b->
da->parent->attr);
1901 if (rcode != 0)
return rcode;
1906 return CMP(my_a->
da->attr, my_b->
da->attr);
1936 if ((da_a->parent->flags.is_root) && (da_b->parent->flags.is_root))
return pair_cmp_by_num(vp_a, vp_b);
1941 for (i = 0; (da_a = da_stack_a.
da[i]) && (da_b = da_stack_b.
da[i]); i++) {
1942 cmp =
CMP(da_a->attr, da_b->attr);
1943 if (cmp != 0)
return cmp;
1951 return (da_a && !da_b) - (!da_a && da_b);
1992 if (!b)
return false;
2001 slen = regex_compile(NULL, &preg, a->vp_strvalue, talloc_array_length(a->vp_strvalue) - 1,
2017 slen = regex_exec(preg,
value, talloc_array_length(
value) - 1, NULL);
2021 if (slen < 0)
return -1;
2028 if (!b)
return false;
2057 if (a_p == b_p)
continue;
2059 ret = (a_p->
da < b_p->
da) - (a_p->
da > b_p->
da);
2060 if (ret != 0)
return ret;
2062 switch (a_p->vp_type) {
2065 if (ret != 0)
return ret;
2078 if (!a_p && !b_p)
return 0;
2079 if (!a_p)
return -1;
2109 if (!filter || (filter->
da != list->
da)) {
2145 while (match ||
check) {
2149 if (!match || !
check)
goto mismatch;
2165 switch (
check->vp_type) {
2207 fr_pair_t *last_check = NULL, *match = NULL;
2248 switch (
check->vp_type) {
2286 if (child->vp_immutable)
return true;
2330 fr_pair_order_list_talloc_free_to_tail(&to->order, first_added);
2334 if (!first_added) first_added = new_vp;
2367 if (!
value)
goto fail;
2378 fr_value_box_list_talloc_free_to_tail(&dst->vb_group, first_added);
2384 if (!first_added) first_added =
value;
2385 fr_value_box_list_insert_tail(&dst->vb_group,
value);
2410 unsigned int cnt = 0;
2429 fr_pair_order_list_talloc_free_to_tail(&to->order, first_added);
2433 if (!first_added) first_added = new_vp;
2513 unsigned int cnt = 0;
2537 switch (
vp->vp_type) {
2545 while ((child = fr_pair_order_list_pop_tail(&
vp->vp_group.order))) {
2573 dst->data.secret |= src->
da->flags.secret | dst->
da->flags.secret;
2599 switch (
vp->vp_type) {
2616 tainted) < 0)
return -1;
3134 if (
vp->
da->flags.has_value)
switch (
vp->vp_type) {
3136 return vp->vp_bool ?
"yes" :
"no";
3140 if (enumv)
return enumv->
name;
3162 if (
vp->
da &&
vp->
da->flags.has_value &&
3172 #ifdef WITH_VERIFY_PTR
3187 "CONSISTENCY CHECK FAILED %s[%u]: pair does not have the correct parentage "
3201 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" should be parented by %s, but is parented by %s",
3209 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" structural (non-group) type contains itself",
3216 switch (
vp->vp_type) {
3222 if (!
vp->vp_octets)
break;
3224 if (!talloc_get_type(
vp->vp_ptr,
uint8_t)) {
3225 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" data buffer type should be "
3226 "uint8_t but is %s",
file,
line,
vp->
da->name, talloc_get_name(
vp->vp_ptr));
3229 len = talloc_array_length(
vp->vp_octets);
3230 if (
vp->vp_length > len) {
3231 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" length %zu is greater than "
3232 "uint8_t data buffer length %zu",
file,
line,
vp->
da->name,
vp->vp_length, len);
3235 parent = talloc_parent(
vp->vp_ptr);
3238 "parented by fr_pair_t %p, instead parented by %p (%s)",
3250 if (!
vp->vp_octets)
break;
3252 if (!talloc_get_type(
vp->vp_ptr,
char)) {
3253 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" data buffer type should be "
3254 "char but is %s",
file,
line,
vp->
da->name, talloc_get_name(
vp->vp_ptr));
3257 len = (talloc_array_length(
vp->vp_strvalue) - 1);
3258 if (
vp->vp_length > len) {
3259 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" length %zu is greater than "
3260 "char buffer length %zu",
file,
line,
vp->
da->name,
vp->vp_length, len);
3263 if (
vp->vp_strvalue[
vp->vp_length] !=
'\0') {
3268 parent = talloc_parent(
vp->vp_ptr);
3271 "parented by fr_pair_t %p, instead parented by %p (%s)",
3280 if (
vp->vp_ip.af != AF_INET) {
3281 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" address family is not "
3282 "set correctly for IPv4 address. Expected %i got %i",
3284 AF_INET,
vp->vp_ip.af);
3286 if (
vp->vp_ip.prefix != 32) {
3288 "set correctly for IPv4 address. Expected %i got %i",
3290 32,
vp->vp_ip.prefix);
3295 if (
vp->vp_ip.af != AF_INET6) {
3296 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" address family is not "
3297 "set correctly for IPv6 address. Expected %i got %i",
3299 AF_INET6,
vp->vp_ip.af);
3301 if (
vp->vp_ip.prefix != 128) {
3303 "set correctly for IPv6 address. Expected %i got %i",
3305 128,
vp->vp_ip.prefix);
3311 if (
vp->vp_group.verified)
break;
3314 TALLOC_CTX *
parent = talloc_parent(child);
3317 "CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" should be parented "
3318 "by fr_pair_t \"%s\". Expected talloc parent %p (%s) got %p (%s)",
3320 child->da->name,
vp->
da->name,
3321 vp, talloc_get_name(
vp),
3328 "CONSISTENCY CHECK FAILED %s[%u]: fr_pair_t \"%s\" should be parented "
3329 "by fr_pair_t \"%s\", but it is instead parented by \"%s\"",
3331 child->da->name, child->da->parent->name,
vp->
da->name);
3333 fr_pair_verify(
file,
line, &
vp->vp_group, child);
3344 if (
vp->
da->flags.is_unknown ||
vp->vp_raw) {
3353 "dictionary pointer %p \"%s\" (%s) "
3354 "and global dictionary pointer %p \"%s\" (%s) differ",
3362 if (
vp->vp_raw ||
vp->
da->flags.is_unknown) {
3370 char data_type_int[10], da_type_int[10];
3372 snprintf(data_type_int,
sizeof(data_type_int),
"%i",
vp->vp_type);
3373 snprintf(da_type_int,
sizeof(da_type_int),
"%i",
vp->vp_type);
3376 "data type (%s) does not match da type (%s)",
3390 void fr_pair_list_verify(
char const *
file,
int line, TALLOC_CTX
const *expected,
fr_pair_list_t const *list)
3400 if (list->verified)
return;
3412 "CONSISTENCY CHECK FAILED %s[%u]: Looping list found. Fast pointer hit "
3413 "slow pointer at \"%s\"",
3416 parent = talloc_parent(slow);
3417 if (expected && (
parent != expected)) {
3422 fr_fatal_assert_fail(
"CONSISTENCY CHECK FAILED %s[%u]: Expected fr_pair_t \"%s\" to be parented "
3423 "by %p (%s), instead parented by %p (%s)\n",
3425 expected, talloc_get_name(expected),
3436 parent = talloc_parent(slow);
3437 if (expected && (
parent != expected))
goto bad_parent;
3454 switch (
vp->vp_type) {
3463 vp->vp_tainted =
true;
3480 return da ==
vp->
da;
3527 if (da->flags.is_root || (da->parent ==
in->da)) {
3536 if (!
parent)
return NULL;
3551 if (!
vp)
return NULL;
3557 if (
item && da->parent->flags.is_root) {
3583 .tainted = box->tainted,
3604 fprintf(fp,
"%s = {\n",
vp->
da->name);
3625 fprintf(fp,
"%s = {\n",
vp->
da->name);
static int const char * fmt
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
static void * _fr_dcursor_init(fr_dcursor_t *cursor, fr_dlist_head_t const *head, fr_dcursor_iter_t iter, fr_dcursor_iter_t peek, void const *iter_uctx, fr_dcursor_insert_t insert, fr_dcursor_remove_t remove, void const *mod_uctx, bool is_const)
Setup a cursor to iterate over attribute items in dlists.
fr_dcursor_eval_t void const * uctx
void *(* fr_dcursor_iter_t)(fr_dlist_head_t *list, void *to_eval, void *uctx)
Callback for implementing custom iterators.
fr_dcursor_iter_t void * current
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
int fr_log_talloc_report(TALLOC_CTX const *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
#define fr_fatal_assert_fail(_msg,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define fr_fatal_assert_msg(_x, _fmt,...)
Calls panic_action ifndef NDEBUG, else logs error and causes the server to exit immediately with code...
static fr_dict_attr_t * fr_dict_attr_unknown_copy(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
fr_dict_attr_t * fr_dict_attr_unknown_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da))
Copy a known or unknown attribute to produce an unknown attribute with the specified name.
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.
void fr_dict_attr_verify(char const *file, int line, fr_dict_attr_t const *da)
bool fr_dict_attr_can_contain(fr_dict_attr_t const *parent, fr_dict_attr_t const *child)
See if a structural da is allowed to contain another da.
fr_dict_enum_value_t * fr_dict_enum_by_value(fr_dict_attr_t const *da, fr_value_box_t const *value)
Lookup the structure representing an enum value in a fr_dict_attr_t.
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_value_box_t const * value
Enum value (what name maps to).
void fr_dict_attr_unknown_free(fr_dict_attr_t const **da)
Free dynamically allocated (unknown attributes)
static fr_dict_attr_t * fr_dict_attr_unknown_raw_afrom_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
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.
#define fr_dict_attr_is_key_field(_da)
char const * name
Enum name.
Value of an enumerated attribute.
unsigned int offset
Positive offset from start of structure to fr_dlist_t.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
fr_dlist_t entry
Struct holding the head and tail of the list.
Head of a doubly linked list.
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
@ FR_TYPE_COMBO_IP_PREFIX
IPv4 or IPv6 address prefix depending on length.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_BOOL
A truth value.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_OCTETS
Raw octets.
@ FR_TYPE_GROUP
A grouping of other attributes.
static uint8_t depth(fr_minmax_heap_index_t i)
void * memset_explicit(void *ptr, int ch, size_t len)
bool fr_pair_matches_da(void const *item, void const *uctx)
Evaluation function for matching if vp matches a given da.
int fr_pair_insert_before(fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *to_add)
Add a VP before another VP.
int fr_pair_list_copy_by_da(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *da, unsigned int count)
Duplicate pairs in a list matching the specified da.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
static void pair_init_from_da(fr_pair_t *vp, fr_dict_attr_t const *da)
Continue initialising an fr_pair_t assigning a da.
int fr_pair_value_bstrn_append(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Append bytes from a buffer to an existing "string" type value pair.
int fr_pair_list_cmp(fr_pair_list_t const *a, fr_pair_list_t const *b)
Determine equality of two lists.
int fr_pair_value_memdup_buffer(fr_pair_t *vp, uint8_t const *src, bool tainted)
Copy data from a talloced buffer into an "octets" data type.
unsigned int fr_pair_count_by_da(fr_pair_list_t const *list, fr_dict_attr_t const *da)
Return the number of instances of a given da in the specified list.
void fr_pair_list_tainted(fr_pair_list_t *list)
Mark up a list of VPs as tainted.
#define NOT_IN_THIS_LIST_MSG
fr_pair_t * fr_pair_find_by_child_num_idx(fr_pair_list_t const *list, fr_dict_attr_t const *parent, unsigned int attr, unsigned int idx)
Find the pair with the matching child attribute at a given index.
int fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and append)
static void fprintf_pair_list(FILE *fp, fr_pair_list_t const *list, int depth)
int fr_pair_value_enum_box(fr_value_box_t const **out, fr_pair_t *vp)
Get value box of a VP, optionally prefer enum value.
int fr_pair_value_aprintf(fr_pair_t *vp, char const *fmt,...)
Print data into an "string" data type.
int fr_pair_delete_by_da_nested(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list, and prune any empty branches.
void fr_fprintf_pair_list(FILE *fp, fr_pair_list_t const *list)
fr_pair_t * fr_pair_alloc_null(TALLOC_CTX *ctx)
Dynamically allocate a new attribute with no fr_dict_attr_t assigned.
int fr_pair_value_mem_append(fr_pair_t *vp, uint8_t *src, size_t len, bool tainted)
Append bytes from a buffer to an existing "octets" type value pair.
fr_pair_t * fr_pair_parent(fr_pair_t const *vp)
Return a pointer to the parent pair.
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.
static int8_t pair_cmp_by_num(void const *a, void const *b)
Order attributes by their attribute number, and tag.
int fr_pair_list_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from)
Duplicate a list of pairs.
int fr_pair_steal_prepend(TALLOC_CTX *list_ctx, fr_pair_list_t *list, fr_pair_t *vp)
Change a vp's talloc ctx and insert it into a new list.
static fr_pair_t * pair_alloc_parent(fr_pair_t *in, fr_pair_t *item, fr_dict_attr_t const *da)
Find or allocate a parent attribute.
int fr_pair_value_mem_append_buffer(fr_pair_t *vp, uint8_t *src, bool tainted)
Append a talloced buffer to an existing "octets" type value pair.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
fr_pair_t * fr_pair_find_last_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the last pair with a matching da.
void fr_pair_validate_debug(fr_pair_t const *failed[2])
Write an error to the library errorbuff detailing the mismatch.
int fr_pair_value_strdup(fr_pair_t *vp, char const *src, bool tainted)
Copy data into an "string" data type.
static int _pair_list_dcursor_insert(fr_dlist_head_t *list, void *to_insert, UNUSED void *uctx)
Keep attr tree and sublists synced on cursor insert.
int fr_pair_value_bstrdup_buffer_shallow(fr_pair_t *vp, char const *src, bool tainted)
Assign a string to a "string" type value pair.
void fr_pair_init_null(fr_pair_t *vp)
Initialise fields in an fr_pair_t without assigning a da.
fr_pair_t * _fr_pair_dcursor_by_da_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dict_attr_t const *da, bool is_const)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
int8_t fr_pair_cmp_by_parent_num(void const *a, void const *b)
Order attributes by their parent(s), attribute number, and tag.
fr_pair_t * fr_pair_find_by_child_num(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *parent, unsigned int attr)
Find the pair with the matching child attribute.
int fr_pair_cmp(fr_pair_t const *a, fr_pair_t const *b)
Compare two pairs, using the operator from "a".
int fr_pair_value_bstrndup_shallow(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Assign a string to a "string" type value pair.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
int fr_pair_delete_by_da(fr_pair_list_t *list, fr_dict_attr_t const *da)
Delete matching pairs from the specified list.
char const * fr_pair_value_enum(fr_pair_t const *vp, char buff[20])
Return a const buffer for an enum type attribute.
static void pair_init_null(fr_pair_t *vp)
Initialise fields in an fr_pair_t without assigning a da.
void fr_pair_replace(fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp)
Replace a given VP.
int fr_pair_value_bstrdup_buffer(fr_pair_t *vp, char const *src, bool tainted)
Copy a nul terminated talloced buffer a "string" type value pair.
int fr_pair_update_by_da_parent(fr_pair_t *parent, fr_pair_t **out, fr_dict_attr_t const *da)
Return the first fr_pair_t matching the fr_dict_attr_t or alloc a new fr_pair_t and its subtree (and ...
int fr_pair_list_copy_by_ancestor(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_dict_attr_t const *parent_da)
Duplicate pairs in a list where the da is a descendant of parent_da.
static int _fr_pair_free(fr_pair_t *vp)
Free a fr_pair_t.
bool fr_pair_validate(fr_pair_t const *failed[2], fr_pair_list_t *filter, fr_pair_list_t *list)
Uses fr_pair_cmp to verify all fr_pair_ts in list match the filter defined by check.
int fr_pair_steal_append(TALLOC_CTX *list_ctx, fr_pair_list_t *list, fr_pair_t *vp)
Change a vp's talloc ctx and insert it into a new list.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_value_mem_realloc(fr_pair_t *vp, uint8_t **out, size_t size)
Change the length of a buffer for a "octets" type value pair.
fr_pair_t * fr_pair_afrom_da_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da)
Create a pair (and all intermediate parents), and append it to the list.
fr_pair_t * fr_pair_afrom_child_num(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, unsigned int attr)
Create a new valuepair.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
void fr_fprintf_pair(FILE *fp, char const *msg, fr_pair_t const *vp)
int fr_pair_value_bstr_alloc(fr_pair_t *vp, char **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "string" type value pair.
int fr_pair_value_bstr_append_buffer(fr_pair_t *vp, char const *src, bool tainted)
Append a talloced buffer to an existing "string" type value pair.
static void * fr_pair_iter_next_by_da(fr_dlist_head_t *list, void *current, void *uctx)
Iterate over pairs with a specified da.
int fr_pair_value_bstr_realloc(fr_pair_t *vp, char **out, size_t size)
Change the length of a buffer for a "string" type value pair.
fr_pair_t * _fr_pair_dcursor_by_ancestor_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dict_attr_t const *da, bool is_const)
Initialise a cursor that will return only attributes descended from the specified fr_dict_attr_t.
bool fr_pair_immutable(fr_pair_t const *vp)
void fr_pair_value_clear(fr_pair_t *vp)
Free/zero out value (or children) of a given VP.
static void * _fr_pair_iter_next_value(fr_dlist_head_t *list, void *current, UNUSED void *uctx)
Iterate over pairs.
fr_pair_list_t * fr_pair_children(fr_pair_t *vp)
Get the child list of a group.
int fr_pair_delete(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list and free.
int fr_pair_append_by_da_parent(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t, adding the parent attributes if required.
fr_pair_t * fr_pair_find_by_da_idx(fr_pair_list_t const *list, fr_dict_attr_t const *da, unsigned int idx)
Find a pair with a matching da at a given index.
int fr_pair_sublist_copy(TALLOC_CTX *ctx, fr_pair_list_t *to, fr_pair_list_t const *from, fr_pair_t const *start, unsigned int count)
Duplicate a list of pairs starting at a particular item.
static fr_dlist_head_t value_dlist
int fr_pair_delete_by_child_num(fr_pair_list_t *list, fr_dict_attr_t const *parent, unsigned int attr)
Delete matching pairs from the specified list.
int fr_pair_value_copy(fr_pair_t *dst, fr_pair_t *src)
Copy the value from one pair to another.
fr_pair_list_t * fr_pair_list_alloc(TALLOC_CTX *ctx)
Allocate a new pair list on the heap.
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.
int fr_pair_steal(TALLOC_CTX *ctx, fr_pair_t *vp)
Steal one VP.
static void * _fr_pair_iter_next_dcursor_value(UNUSED fr_dlist_head_t *list, void *current, void *uctx)
Iterate over pairs.
fr_pair_t * fr_pair_copy(TALLOC_CTX *ctx, fr_pair_t const *vp)
Copy a single valuepair.
int fr_pair_value_memdup_shallow(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a "octets" type value pair.
bool fr_pair_validate_relaxed(fr_pair_t const *failed[2], fr_pair_list_t *filter, fr_pair_list_t *list)
Uses fr_pair_cmp to verify all fr_pair_ts in list match the filter defined by check.
fr_pair_t * _fr_pair_dcursor_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_iter_t iter, void const *uctx, bool is_const)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
fr_pair_list_t * fr_pair_parent_list(fr_pair_t const *vp)
Return a pointer to the parent pair list.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
int fr_pair_value_mem_alloc(fr_pair_t *vp, uint8_t **out, size_t size, bool tainted)
Pre-allocate a memory buffer for a "octets" type value pair.
int fr_pair_value_strtrim(fr_pair_t *vp)
Trim the length of the string buffer to match the length of the C string.
int fr_pair_insert_after(fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *to_add)
Add a VP after another VP.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
int fr_pair_prepend(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the start of the list.
static void * fr_pair_iter_next_by_ancestor(fr_dlist_head_t *list, void *current, void *uctx)
Iterate over pairs which are decedents of the specified da.
static int _pair_list_dcursor_remove(NDEBUG_UNUSED fr_dlist_head_t *list, void *to_remove, UNUSED void *uctx)
Keep attr tree and sublists synced on cursor removal.
void fr_pair_list_afrom_box(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_dict_t const *dict, fr_value_box_t *box)
Parse a list of VPs from a value box.
fr_value_box_t * fr_pair_dcursor_nested_init(fr_dcursor_t *cursor, fr_dcursor_t *parent)
Initialises a special dcursor over another cursor which returns fr_pair_t, but we return fr_value_box...
void fr_pair_list_steal(TALLOC_CTX *ctx, fr_pair_list_t *list)
Steal a list of pairs to a new context.
fr_pair_t * fr_pair_list_parent(fr_pair_list_t const *list)
Return a pointer to the parent pair which contains this list.
fr_pair_t * fr_pair_list_iter_leaf(fr_pair_list_t *list, fr_pair_t *vp)
Iterates over the leaves of a list.
int fr_pair_raw_afrom_pair(fr_pair_t *vp, uint8_t const *data, size_t data_len)
Mark malformed attribute as raw.
fr_value_box_t * fr_pair_dcursor_value_init(fr_dcursor_t *cursor)
Initialises a special dcursor over a fr_pair_list_t, but which returns fr_value_box_t.
int8_t fr_pair_cmp_by_da(void const *a, void const *b)
Order attributes by their da, and tag.
static const char spaces[]
int fr_pair_value_memdup_buffer_shallow(fr_pair_t *vp, uint8_t const *src, bool tainted)
Assign a talloced buffer to a "octets" type value pair.
int fr_pair_value_strdup_shallow(fr_pair_t *vp, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a vp, but don't copy it.
int fr_pair_prepend_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Alloc a new fr_pair_t (and prepend)
fr_pair_t * _fr_pair_dcursor_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, bool is_const)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
fr_pair_t * fr_pair_root_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
A special allocation function which disables child autofree.
fr_pair_t * fr_pair_afrom_da_depth_nested(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *da, int start)
Create a pair (and all intermediate parents), and append it to the list.
int fr_pair_list_copy_to_box(fr_value_box_t *dst, fr_pair_list_t *from)
Copy the contents of a pair list to a set of value-boxes.
fr_slen_t fr_pair_list_afrom_substr(fr_pair_parse_t const *root, fr_pair_parse_t *relative, fr_sbuff_t *in)
Parse a fr_pair_list_t from a substring.
struct fr_pair_parse_s fr_pair_parse_t
ssize_t fr_fprintf(FILE *fp, char const *fmt,...)
Special version of fprintf which implements custom format specifiers.
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 check(_handle, _len_p)
static size_t min(size_t x, size_t y)
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
Set of parsing rules for *unescape_until functions.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
bool _CONST is_child
is a child of a VP
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.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
#define talloc_get_type_abort_const
#define FR_TLIST_FUNCS(_name, _element_type, _element_entry)
Define type specific wrapper functions for tlists.
static fr_tlist_head_t * fr_tlist_head_from_dlist(fr_dlist_head_t *dlist_head)
Get a fr_tlist_head_t from a fr_dlist_head_t.
#define FR_TLIST_HEAD(_name)
Expands to the type name used for the head wrapper structure.
char const * fr_tokens[T_TOKEN_LAST]
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
#define ATTRIBUTE_EQ(_x, _y)
#define fr_pair_cmp_op(_op, _a, _b)
Compare two attributes using and operator.
fr_pair_t * fr_pair_remove(fr_pair_list_t *list, fr_pair_t *vp)
Remove fr_pair_t from a list without freeing.
static fr_slen_t fr_pair_aprint(TALLOC_CTX *ctx, char **out, fr_dict_attr_t const *parent, fr_pair_t const *vp) 1(fr_pair_print
bool fr_pair_list_empty(fr_pair_list_t const *list)
Is a valuepair list empty.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
void fr_pair_list_sort(fr_pair_list_t *list, fr_cmp_t cmp)
Sort a doubly linked list of fr_pair_ts using merge sort.
#define fr_pair_list_foreach(_list_head, _iter)
Iterate over the contents of a fr_pair_list_t.
void fr_pair_list_free(fr_pair_list_t *list)
Free memory used by a valuepair list.
#define PAIR_VERIFY_WITH_LIST(_l, _x)
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
fr_pair_t * fr_pair_list_prev(fr_pair_list_t const *list, fr_pair_t const *item))
Get the previous item in a valuepair list before a specific entry.
#define PAIR_LIST_VERIFY(_x)
size_t fr_pair_list_num_elements(fr_pair_list_t const *list)
Get the length of a list of fr_pair_t.
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.
void fr_strerror_clear(void)
Clears all pending messages from the talloc pools.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_printf_push(_fmt,...)
Add a message to an existing stack of messages at the tail.
#define fr_strerror_const(_msg)
fr_table_num_ordered_t const fr_type_table[]
Map data types to names representing those types.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
#define fr_type_is_group(_x)
#define fr_type_is_structural(_x)
#define FR_TYPE_STRUCTURAL
#define fr_type_is_leaf(_x)
void fr_value_box_memdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, bool tainted)
Assign a talloced buffer to a box, but don't copy it.
int fr_value_box_vasprintf(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, bool tainted, char const *fmt, va_list ap)
Print a formatted string using our internal printf wrapper and assign it to a value box.
int fr_value_box_bstrn_append(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, size_t len, bool tainted)
Append bytes from a buffer to an existing fr_value_box_t.
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
int fr_value_box_strtrim(TALLOC_CTX *ctx, fr_value_box_t *vb)
Trim the length of the string buffer to match the length of the C string.
int fr_value_box_mem_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, bool tainted)
Append a talloc buffer to an existing fr_value_box_t.
int fr_value_box_mem_alloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Pre-allocate an octets buffer for filling by the caller.
int fr_value_box_memdup_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, bool tainted)
Copy a talloced buffer to a fr_value_box_t.
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_mem_realloc(TALLOC_CTX *ctx, uint8_t **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int8_t fr_value_box_cmp(fr_value_box_t const *a, fr_value_box_t const *b)
Compare two values.
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
int fr_value_box_cast_in_place(TALLOC_CTX *ctx, fr_value_box_t *vb, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv)
Convert one type of fr_value_box_t to another in place.
int fr_value_box_mem_append(TALLOC_CTX *ctx, fr_value_box_t *dst, uint8_t const *src, size_t len, bool tainted)
Append data to an existing fr_value_box_t.
void fr_value_box_memdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Assign a buffer to a box, but don't copy it.
void fr_value_box_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
int fr_value_box_bstr_append_buffer(TALLOC_CTX *ctx, fr_value_box_t *dst, char const *src, bool tainted)
Append a talloced buffer to an existing fr_value_box_t.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
int fr_value_box_bstr_alloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, fr_dict_attr_t const *enumv, size_t len, bool tainted)
Alloc and assign an empty \0 terminated string to a fr_value_box_t.
void fr_value_box_clear(fr_value_box_t *data)
Clear/free any existing value and metadata.
int fr_value_box_bstr_realloc(TALLOC_CTX *ctx, char **out, fr_value_box_t *dst, size_t len)
Change the length of a buffer already allocated to a value box.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_bstrdup_buffer_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a talloced buffer containing a nul terminated string to a box, but don't copy it.
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
int fr_value_box_memdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, uint8_t const *src, size_t len, bool tainted)
Copy a buffer to a fr_value_box_t.
#define fr_box_is_numeric(_x)
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
static size_t char fr_sbuff_t size_t inlen
#define fr_value_box_init(_vb, _type, _enumv, _tainted)
Initialise a fr_value_box_t.
static size_t char ** out