2 * pair.c Functions to handle VALUE_PAIRs
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
25 #include <freeradius-devel/libradius.h>
26 #include <freeradius-devel/regex.h>
32 * @note Do not call directly, use talloc_free instead.
37 static int _fr_pair_free(VALUE_PAIR *vp) {
39 vp->vp_integer = 0xf4eef4ee;
43 talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL);
48 static VALUE_PAIR *fr_pair_alloc(TALLOC_CTX *ctx)
52 vp = talloc_zero(ctx, VALUE_PAIR);
54 fr_strerror_printf("Out of memory");
62 talloc_set_destructor(vp, _fr_pair_free);
68 /** Dynamically allocate a new attribute
70 * Allocates a new attribute and a new dictionary attr if no DA is provided.
72 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
73 * @param[in] da Specifies the dictionary attribute to build the VP from.
74 * @return a new value pair or NULL if an error occurred.
76 VALUE_PAIR *fr_pair_afrom_da(TALLOC_CTX *ctx, DICT_ATTR const *da)
81 * Caller must specify a da else we don't know what the attribute type is.
84 fr_strerror_printf("Invalid arguments");
88 vp = fr_pair_alloc(ctx);
90 fr_strerror_printf("Out of memory");
95 * Use the 'da' to initialize more fields.
98 vp->vp_length = da->flags.length;
103 /** Create a new valuepair
105 * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
108 * If attr or vendor are uknown will call dict_attruknown to create a dynamic
109 * DICT_ATTR of PW_TYPE_OCTETS.
111 * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
112 * checking @verbatim vp->da->flags.is_unknown @endverbatim.
114 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
115 * @param[in] attr number.
116 * @param[in] vendor number.
117 * @return the new valuepair or NULL on error.
119 VALUE_PAIR *fr_pair_afrom_num(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
123 da = dict_attrbyvalue(attr, vendor);
127 vp = fr_pair_alloc(ctx);
128 if (!vp) return NULL;
131 * Ensure that the DA is parented by the VP.
133 da = dict_unknown_afrom_fields(vp, attr, vendor);
143 return fr_pair_afrom_da(ctx, da);
146 /** Free memory used by a valuepair list.
148 * @todo TLV: needs to free all dependents of each VP freed.
150 void fr_pair_list_free(VALUE_PAIR **vps)
159 for (vp = fr_cursor_init(&cursor, vps);
161 vp = fr_cursor_next(&cursor)) {
169 /** Mark malformed or unrecognised attributed as unknown
171 * @param vp to change DICT_ATTR of.
172 * @return 0 on success (or if already unknown) else -1 on error.
174 int fr_pair_to_unknown(VALUE_PAIR *vp)
179 if (vp->da->flags.is_unknown) {
183 da = dict_unknown_afrom_fields(vp, vp->da->attr, vp->da->vendor);
193 /** Find the pair with the matching DAs
196 VALUE_PAIR *fr_pair_find_by_da(VALUE_PAIR *vp, DICT_ATTR const *da, int8_t tag)
204 (void) fr_cursor_init(&cursor, &vp);
205 return fr_cursor_next_by_da(&cursor, da, tag);
209 /** Find the pair with the matching attribute
211 * @todo should take DAs and do a pointer comparison.
213 VALUE_PAIR *fr_pair_find_by_num(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag)
217 /* List head may be NULL if it contains no VPs */
218 if (!vp) return NULL;
222 (void) fr_cursor_init(&cursor, &vp);
223 return fr_cursor_next_by_num(&cursor, attr, vendor, tag);
226 /** Delete matching pairs
228 * Delete matching pairs from the attribute list.
230 * @param[in,out] first VP in list.
231 * @param[in] attr to match.
232 * @param[in] vendor to match.
233 * @param[in] tag to match. TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
235 * @todo should take DAs and do a point comparison.
237 void fr_pair_delete_by_num(VALUE_PAIR **first, unsigned int attr, unsigned int vendor, int8_t tag)
239 VALUE_PAIR *i, *next;
240 VALUE_PAIR **last = first;
242 for(i = *first; i; i = next) {
245 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
246 (!i->da->flags.has_tag || TAG_EQ(tag, i->tag))) {
255 /** Add a VP to the end of the list.
257 * Locates the end of 'first', and links an additional VP 'add' at the end.
259 * @param[in] first VP in linked list. Will add new VP to the end of this list.
260 * @param[in] add VP to add to list.
262 void fr_pair_add(VALUE_PAIR **first, VALUE_PAIR *add)
270 if (*first == NULL) {
275 for (i = *first; i->next; i = i->next) {
276 #ifdef WITH_VERIFY_PTR
279 * The same VP should never by added multiple times
289 /** Replace all matching VPs
291 * Walks over 'first', and replaces the first VP that matches 'replace'.
293 * @note Memory used by the VP being replaced will be freed.
294 * @note Will not work with unknown attributes.
296 * @param[in,out] first VP in linked list. Will search and replace in this list.
297 * @param[in] replace VP to replace.
299 void fr_pair_replace(VALUE_PAIR **first, VALUE_PAIR *replace)
301 VALUE_PAIR *i, *next;
302 VALUE_PAIR **prev = first;
306 if (*first == NULL) {
312 * Not an empty list, so find item if it is there, and
313 * replace it. Note, we always replace the first one, and
314 * we ignore any others that might exist.
316 for(i = *first; i; i = next) {
321 * Found the first attribute, replace it,
324 if ((i->da == replace->da) && (!i->da->flags.has_tag || TAG_EQ(replace->tag, i->tag))) {
328 * Should really assert that replace->next == NULL
330 replace->next = next;
336 * Point to where the attribute should go.
342 * If we got here, we didn't find anything to replace, so
343 * stopped at the last item, which we just append to.
348 int8_t fr_pair_cmp_by_da_tag(void const *a, void const *b)
350 VALUE_PAIR const *my_a = a;
351 VALUE_PAIR const *my_b = b;
358 cmp = fr_pointer_cmp(my_a->da, my_b->da);
359 if (cmp != 0) return cmp;
361 if (my_a->tag < my_b->tag) return -1;
363 if (my_a->tag > my_b->tag) return 1;
368 static void fr_pair_list_sort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
374 * Stopping condition - no more elements left to split
376 if (!source || !source->next) {
384 * Fast advances twice as fast as slow, so when it gets to the end,
385 * slow will point to the middle of the linked list.
403 static VALUE_PAIR *fr_pair_list_sort_merge(VALUE_PAIR *a, VALUE_PAIR *b, fr_cmp_t cmp)
405 VALUE_PAIR *result = NULL;
411 * Compare the DICT_ATTRs and tags
413 if (cmp(a, b) <= 0) {
415 result->next = fr_pair_list_sort_merge(a->next, b, cmp);
418 result->next = fr_pair_list_sort_merge(a, b->next, cmp);
424 /** Sort a linked list of VALUE_PAIRs using merge sort
426 * @param[in,out] vps List of VALUE_PAIRs to sort.
427 * @param[in] cmp to sort with
429 void fr_pair_list_sort(VALUE_PAIR **vps, fr_cmp_t cmp)
431 VALUE_PAIR *head = *vps;
436 * If there's 0-1 elements it must already be sorted.
438 if (!head || !head->next) {
442 fr_pair_list_sort_split(head, &a, &b); /* Split into sublists */
443 fr_pair_list_sort(&a, cmp); /* Traverse left */
444 fr_pair_list_sort(&b, cmp); /* Traverse right */
447 * merge the two sorted lists together
449 *vps = fr_pair_list_sort_merge(a, b, cmp);
452 /** Write an error to the library errorbuff detailing the mismatch
454 * Retrieve output with fr_strerror();
456 * @todo add thread specific talloc contexts.
458 * @param ctx a hack until we have thread specific talloc contexts.
459 * @param failed pair of attributes which didn't match.
461 void fr_pair_validate_debug(TALLOC_CTX *ctx, VALUE_PAIR const *failed[2])
463 VALUE_PAIR const *filter = failed[0];
464 VALUE_PAIR const *list = failed[1];
468 (void) fr_strerror(); /* Clear any existing messages */
470 if (!fr_assert(!(!filter && !list))) return;
474 fr_strerror_printf("Attribute \"%s\" not found in list", filter->da->name);
478 if (!filter || (filter->da != list->da)) {
479 fr_strerror_printf("Attribute \"%s\" not found in filter", list->da->name);
483 if (!TAG_EQ(filter->tag, list->tag)) {
484 fr_strerror_printf("Attribute \"%s\" tag \"%i\" didn't match filter tag \"%i\"",
485 list->da->name, list->tag, filter->tag);
490 value = vp_aprints_value(ctx, list, '"');
491 str = vp_aprints(ctx, filter, '"');
493 fr_strerror_printf("Attribute value \"%s\" didn't match filter: %s", value, str);
501 /** Uses fr_pair_cmp to verify all VALUE_PAIRs in list match the filter defined by check
503 * @note will sort both filter and list in place.
505 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
507 * @param filter attributes to check list against.
508 * @param list attributes, probably a request or reply
510 bool fr_pair_validate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
512 vp_cursor_t filter_cursor;
513 vp_cursor_t list_cursor;
515 VALUE_PAIR *check, *match;
517 if (!filter && !list) {
522 * This allows us to verify the sets of validate and reply are equal
523 * i.e. we have a validate rule which matches every reply attribute.
525 * @todo this should be removed one we have sets and lists
527 fr_pair_list_sort(&filter, fr_pair_cmp_by_da_tag);
528 fr_pair_list_sort(&list, fr_pair_cmp_by_da_tag);
530 check = fr_cursor_init(&filter_cursor, &filter);
531 match = fr_cursor_init(&list_cursor, &list);
532 while (match || check) {
534 * Lists are of different lengths
536 if (!match || !check) goto mismatch;
539 * The lists are sorted, so if the first
540 * attributes aren't of the same type, then we're
543 if (!ATTRIBUTE_EQ(check, match)) goto mismatch;
546 * They're of the same type, but don't have the
547 * same values. This is a problem.
549 * Note that the RFCs say that for attributes of
550 * the same type, order is important.
552 if (fr_pair_cmp(check, match) != 1) goto mismatch;
554 check = fr_cursor_next(&filter_cursor);
555 match = fr_cursor_next(&list_cursor);
568 /** Uses fr_pair_cmp to verify all VALUE_PAIRs in list match the filter defined by check
570 * @note will sort both filter and list in place.
572 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
574 * @param filter attributes to check list against.
575 * @param list attributes, probably a request or reply
577 bool fr_pair_validate_relaxed(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
579 vp_cursor_t filter_cursor;
580 vp_cursor_t list_cursor;
582 VALUE_PAIR *check, *last_check = NULL, *match = NULL;
584 if (!filter && !list) {
589 * This allows us to verify the sets of validate and reply are equal
590 * i.e. we have a validate rule which matches every reply attribute.
592 * @todo this should be removed one we have sets and lists
594 fr_pair_list_sort(&filter, fr_pair_cmp_by_da_tag);
595 fr_pair_list_sort(&list, fr_pair_cmp_by_da_tag);
597 fr_cursor_init(&list_cursor, &list);
598 for (check = fr_cursor_init(&filter_cursor, &filter);
600 check = fr_cursor_next(&filter_cursor)) {
602 * Were processing check attributes of a new type.
604 if (!ATTRIBUTE_EQ(last_check, check)) {
606 * Record the start of the matching attributes in the pair list
607 * For every other operator we require the match to be present
609 match = fr_cursor_next_by_da(&list_cursor, check->da, check->tag);
611 if (check->op == T_OP_CMP_FALSE) continue;
615 fr_cursor_init(&list_cursor, &match);
620 * Now iterate over all attributes of the same type.
622 for (match = fr_cursor_first(&list_cursor);
623 ATTRIBUTE_EQ(match, check);
624 match = fr_cursor_next(&list_cursor)) {
626 * This attribute passed the filter
628 if (!fr_pair_cmp(check, match)) goto mismatch;
642 /** Copy a single valuepair
644 * Allocate a new valuepair and copy the da from the old vp.
646 * @param[in] ctx for talloc
647 * @param[in] vp to copy.
648 * @return a copy of the input VP or NULL on error.
650 VALUE_PAIR *fr_pair_copy(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
654 if (!vp) return NULL;
658 n = fr_pair_afrom_da(ctx, vp->da);
661 memcpy(n, vp, sizeof(*n));
664 * If the DA is unknown, steal "n" to "ctx". This does
665 * nothing for "n", but will also copy the unknown "da".
667 if (n->da->flags.is_unknown) {
668 fr_pair_steal(ctx, n);
674 * If it's an xlat, copy the raw string and return early,
675 * so we don't pre-expand or otherwise mangle the VALUE_PAIR.
677 if (vp->type == VT_XLAT) {
678 n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
682 switch (vp->da->type) {
684 n->vp_octets = NULL; /* else fr_pair_value_memcpy will free vp's value */
685 fr_pair_value_memcpy(n, vp->vp_octets, n->vp_length);
689 n->vp_strvalue = NULL; /* else pairstrnpy will free vp's value */
690 fr_pair_value_bstrncpy(n, vp->vp_strvalue, n->vp_length);
702 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
704 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
705 * @param[in] from whence to copy VALUE_PAIRs.
706 * @return the head of the new VALUE_PAIR list or NULL on error.
708 VALUE_PAIR *fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
710 vp_cursor_t src, dst;
712 VALUE_PAIR *out = NULL, *vp;
714 fr_cursor_init(&dst, &out);
715 for (vp = fr_cursor_init(&src, &from);
717 vp = fr_cursor_next(&src)) {
719 vp = fr_pair_copy(ctx, vp);
721 fr_pair_list_free(&out);
724 fr_cursor_insert(&dst, vp); /* fr_pair_list_copy sets next pointer to NULL */
730 /** Copy matching pairs
732 * Copy pairs of a matching attribute number, vendor number and tag from the
733 * the input list to a new list, and returns the head of this list.
735 * @param[in] ctx for talloc
736 * @param[in] from whence to copy VALUE_PAIRs.
737 * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
738 * will match (and therefore copy) only VSAs.
739 * If attribute 0 and vendor 0 will match (and therefore copy) all
741 * @param[in] vendor to match.
742 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
743 * @return the head of the new VALUE_PAIR list or NULL on error.
745 VALUE_PAIR *fr_pair_list_copy_by_num(TALLOC_CTX *ctx, VALUE_PAIR *from,
746 unsigned int attr, unsigned int vendor, int8_t tag)
748 vp_cursor_t src, dst;
750 VALUE_PAIR *out = NULL, *vp;
752 fr_cursor_init(&dst, &out);
753 for (vp = fr_cursor_init(&src, &from);
755 vp = fr_cursor_next(&src)) {
758 if (vp->da->flags.has_tag && !TAG_EQ(tag, vp->tag)) {
763 * Attr/vendor of 0 means "move them all".
764 * It's better than "fr_pair_copy(foo,bar);bar=NULL"
766 if ((attr == 0) && (vendor == 0)) {
771 * vendor=0, attr = PW_VENDOR_SPECIFIC means
772 * "match any vendor attribute".
774 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
776 * It's a VSA: copy it over.
778 if (vp->da->vendor != 0) goto do_copy;
781 * It's Vendor-Specific: copy it over.
783 if (vp->da->attr == attr) goto do_copy;
786 * It's not a VSA: ignore it.
791 if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
796 vp = fr_pair_copy(ctx, vp);
798 fr_pair_list_free(&out);
801 fr_cursor_insert(&dst, vp);
809 * @param[in] ctx to move VALUE_PAIR into
810 * @param[in] vp VALUE_PAIR to move into the new context.
812 void fr_pair_steal(TALLOC_CTX *ctx, VALUE_PAIR *vp)
814 (void) talloc_steal(ctx, vp);
817 * The DA may be unknown. If we're stealing the VPs to a
818 * different context, copy the unknown DA. We use the VP
819 * as a context here instead of "ctx", so that when the
820 * VP is freed, so is the DA.
822 * Since we have no introspection into OTHER VPs using
823 * the same DA, we can't have multiple VPs use the same
824 * DA. So we might as well tie it to this VP.
826 if (vp->da->flags.is_unknown) {
831 size = talloc_get_size(vp->da);
833 p = talloc_zero_array(vp, char, size);
834 da = (DICT_ATTR *) p;
835 talloc_set_type(p, DICT_ATTR);
836 memcpy(da, vp->da, size);
841 /** Move pairs from source list to destination list respecting operator
843 * @note This function does some additional magic that's probably not needed
844 * in most places. Consider using radius_pairmove in server code.
846 * @note fr_pair_list_free should be called on the head of the source list to free
847 * unmoved attributes (if they're no longer needed).
849 * @note Does not respect tags when matching.
851 * @param[in] ctx for talloc
852 * @param[in,out] to destination list.
853 * @param[in,out] from source list.
855 * @see radius_pairmove
857 void fr_pair_list_move(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
859 VALUE_PAIR *i, *found;
860 VALUE_PAIR *head_new, **tail_new;
861 VALUE_PAIR **tail_from;
863 if (!to || !from || !*from) return;
866 * We're editing the "to" list while we're adding new
867 * attributes to it. We don't want the new attributes to
868 * be edited, so we create an intermediate list to hold
869 * them during the editing process.
872 tail_new = &head_new;
875 * We're looping over the "from" list, moving some
876 * attributes out, but leaving others in place.
879 while ((i = *tail_from) != NULL) {
885 * We never move Fall-Through.
887 if (!i->da->vendor && i->da->attr == PW_FALL_THROUGH) {
888 tail_from = &(i->next);
893 * Unlike previous versions, we treat all other
894 * attributes as normal. i.e. there's no special
895 * treatment for passwords or Hint.
900 * Anything else are operators which
901 * shouldn't occur. We ignore them, and
902 * leave them in place.
905 tail_from = &(i->next);
909 * Add it to the "to" list, but only if
910 * it doesn't already exist.
913 found = fr_pair_find_by_da(*to, i->da, TAG_ANY);
914 if (!found) goto do_add;
916 tail_from = &(i->next);
920 * Add it to the "to" list, and delete any attribute
921 * of the same vendor/attr which already exists.
924 found = fr_pair_find_by_da(*to, i->da, TAG_ANY);
925 if (!found) goto do_add;
928 * Do NOT call fr_pair_delete_by_num() here,
929 * due to issues with re-writing
930 * "request->username".
932 * Everybody calls fr_pair_move, and
933 * expects it to work. We can't
934 * update request->username here,
935 * so instead we over-write the
936 * vp that it's pointing to.
938 switch (found->da->type) {
941 memcpy(found, i, sizeof(*found));
946 fr_pair_value_memsteal(found, i->vp_octets);
951 fr_pair_value_strsteal(found, i->vp_strvalue);
952 i->vp_strvalue = NULL;
958 * Delete *all* of the attributes
959 * of the same number.
961 fr_pair_delete_by_num(&found->next,
963 found->da->vendor, TAG_ANY);
966 * Remove this attribute from the
969 *tail_from = i->next;
971 fr_pair_list_free(&i);
975 * Move it from the old list and add it
980 *tail_from = i->next;
983 fr_pair_steal(ctx, i);
984 tail_new = &(i->next);
987 } /* loop over the "from" list. */
990 * Take the "new" list, and append it to the "to" list.
992 fr_pair_add(to, head_new);
995 /** Move matching pairs between VALUE_PAIR lists
997 * Move pairs of a matching attribute number, vendor number and tag from the
998 * the input list to the output list.
1000 * @note fr_pair_list_free should be called on the head of the old list to free unmoved
1001 attributes (if they're no longer needed).
1003 * @param[in] ctx for talloc
1004 * @param[in,out] to destination list.
1005 * @param[in,out] from source list.
1006 * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
1007 * will match (and therefore copy) only VSAs.
1008 * If attribute 0 and vendor 0 will match (and therefore copy) all
1010 * @param[in] vendor to match.
1011 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
1012 * @param[in] move if set to "true", VPs are moved. If set to "false", VPs are copied, and the old one deleted.
1014 static void fr_pair_list_move_by_num_internal(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
1015 unsigned int attr, unsigned int vendor, int8_t tag,
1018 VALUE_PAIR *to_tail, *i, *next, *this;
1019 VALUE_PAIR *iprev = NULL;
1022 * Find the last pair in the "to" list and put it in "to_tail".
1024 * @todo: replace the "if" with "VALUE_PAIR **tail"
1028 for(i = *to; i; i = i->next) {
1036 * Attr/vendor of 0 means "move them all".
1037 * It's better than "fr_pair_add(foo,bar);bar=NULL"
1039 if ((vendor == 0) && (attr == 0)) {
1041 to_tail->next = *from;
1046 for (i = *from; i; i = i->next) {
1047 fr_pair_steal(ctx, i);
1054 for(i = *from; i; i = next) {
1058 if (i->da->flags.has_tag && !TAG_EQ(tag, i->tag)) {
1064 * vendor=0, attr = PW_VENDOR_SPECIFIC means
1065 * "match any vendor attribute".
1067 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1069 * It's a VSA: move it over.
1071 if (i->da->vendor != 0) goto move;
1074 * It's Vendor-Specific: move it over.
1076 if (i->da->attr == attr) goto move;
1079 * It's not a VSA: ignore it.
1086 * If it isn't an exact match, ignore it.
1088 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1095 * Remove the attribute from the "from" list.
1105 this = fr_pair_copy(ctx, i);
1109 * Add the attribute to the "to" list.
1112 to_tail->next = this;
1119 fr_pair_steal(ctx, i);
1127 /** Move matching pairs between VALUE_PAIR lists
1129 * Move pairs of a matching attribute number, vendor number and tag from the
1130 * the input list to the output list.
1132 * @note pairs which are moved have their parent changed to ctx.
1134 * @note fr_pair_list_free should be called on the head of the old list to free unmoved
1135 attributes (if they're no longer needed).
1137 * @param[in] ctx for talloc
1138 * @param[in,out] to destination list.
1139 * @param[in,out] from source list.
1140 * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
1141 * will match (and therefore copy) only VSAs.
1142 * If attribute 0 and vendor 0 will match (and therefore copy) all
1144 * @param[in] vendor to match.
1145 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
1147 void fr_pair_list_move_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
1148 unsigned int attr, unsigned int vendor, int8_t tag)
1150 fr_pair_list_move_by_num_internal(ctx, to, from, attr, vendor, tag, true);
1154 /** Copy / delete matching pairs between VALUE_PAIR lists
1156 * Move pairs of a matching attribute number, vendor number and tag from the
1157 * the input list to the output list. Like fr_pair_list_move_by_num(), but
1158 * instead does copy / delete.
1160 * @note The pair is NOT reparented. It is copied and deleted.
1162 * @note fr_pair_list_free should be called on the head of the old list to free unmoved
1163 attributes (if they're no longer needed).
1165 * @param[in] ctx for talloc
1166 * @param[in,out] to destination list.
1167 * @param[in,out] from source list.
1168 * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
1169 * will match (and therefore copy) only VSAs.
1170 * If attribute 0 and vendor 0 will match (and therefore copy) all
1172 * @param[in] vendor to match.
1173 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
1175 void fr_pair_list_mcopy_by_num(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from,
1176 unsigned int attr, unsigned int vendor, int8_t tag)
1178 fr_pair_list_move_by_num_internal(ctx, to, from, attr, vendor, tag, false);
1182 /** Convert string value to native attribute value
1184 * @param vp to assign value to.
1185 * @param value string to convert. Binary safe for variable length values if len is provided.
1186 * @param inlen may be < 0 in which case strlen(len) is used to determine length, else inline
1187 * should be the length of the string or sub string to parse.
1188 * @return 0 on success -1 on error.
1190 int fr_pair_value_from_str(VALUE_PAIR *vp, char const *value, size_t inlen)
1196 if (!value) return -1;
1198 type = vp->da->type;
1201 * We presume that the input data is from a double quoted
1202 * string, and needs escaping
1204 ret = value_data_from_str(vp, &vp->data, &type, vp->da, value, inlen, '"');
1205 if (ret < 0) return -1;
1208 * If we parsed to a different type than the DA associated with
1209 * the VALUE_PAIR we now need to fixup the DA.
1211 if (type != vp->da->type) {
1212 DICT_ATTR const *da;
1214 da = dict_attrbytype(vp->da->attr, vp->da->vendor, type);
1216 fr_strerror_printf("Cannot find %s variant of attribute \"%s\"",
1217 fr_int2str(dict_attr_types, type, "<INVALID>"), vp->da->name);
1223 vp->vp_length = ret;
1231 /** Use simple heuristics to create an VALUE_PAIR from an unknown address string
1233 * If a DICT_ATTR is not provided for the address type, parsing will fail with
1236 * @param ctx to allocate VP in.
1237 * @param value IPv4/IPv6 address/prefix string.
1238 * @param ipv4 dictionary attribute to use for an IPv4 address.
1239 * @param ipv6 dictionary attribute to use for an IPv6 address.
1240 * @param ipv4_prefix dictionary attribute to use for an IPv4 prefix.
1241 * @param ipv6_prefix dictionary attribute to use for an IPv6 prefix.
1242 * @return NULL on error, or new VALUE_PAIR.
1244 VALUE_PAIR *fr_pair_afrom_ip_str(TALLOC_CTX *ctx, char const *value, DICT_ATTR *ipv4, DICT_ATTR *ipv6,
1245 DICT_ATTR *ipv4_prefix, DICT_ATTR *ipv6_prefix)
1248 DICT_ATTR *da = NULL;
1250 if (!fr_assert(ipv4 || ipv6 || ipv4_prefix || ipv6_prefix)) {
1254 /* No point in repeating the work of fr_pair_value_from_str */
1255 if (strchr(value, ':')) {
1256 if (strchr(value, '/')) {
1265 if (strchr(value, '/')) {
1275 fr_strerror_printf("Invalid IP value specified, allowed types are %s%s%s%s",
1276 ipv4 ? "ipaddr " : "", ipv6 ? "ipv6addr " : "",
1277 ipv4_prefix ? "ipv4prefix " : "", ipv6_prefix ? "ipv6prefix" : "");
1280 vp = fr_pair_afrom_da(ctx, da);
1281 if (!vp) return NULL;
1282 if (fr_pair_value_from_str(vp, value, -1) < 0) {
1291 /** Create a valuepair from an ASCII attribute and value
1293 * Where the attribute name is in the form:
1295 * - Attr-%d.%d.%d...
1296 * - Vendor-%d-Attr-%d
1297 * - VendorName-Attr-%d
1299 * @param ctx for talloc
1300 * @param attribute name to parse.
1301 * @param value to parse (must be a hex string).
1302 * @param op to assign to new valuepair.
1303 * @return new valuepair or NULL on error.
1305 static VALUE_PAIR *fr_pair_make_unknown(TALLOC_CTX *ctx,
1306 char const *attribute, char const *value,
1309 VALUE_PAIR *vp, *vp2;
1310 DICT_ATTR const *da;
1316 vp = fr_pair_alloc(ctx);
1317 if (!vp) return NULL;
1319 vp->da = dict_unknown_afrom_str(vp, attribute);
1326 * No value. Nothing more to do.
1328 if (!value) return vp;
1331 * Unknown attributes MUST be of type 'octets'
1333 if (strncasecmp(value, "0x", 2) != 0) {
1334 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1335 "string, not \"%s\"", attribute, value);
1341 * Convert the hex data to binary.
1343 size = strlen(value + 2);
1345 vp->vp_length = size >> 1;
1346 vp->vp_octets = data = talloc_array(vp, uint8_t, vp->vp_length);
1348 vp->op = (op == 0) ? T_OP_EQ : op;
1350 if (fr_hex2bin(data, vp->vp_length, value + 2, size) != vp->vp_length) {
1351 fr_strerror_printf("Invalid hex string");
1357 * It's still unknown, return it as-is.
1359 da = dict_attrbyvalue(vp->da->attr, vp->da->vendor);
1363 * It MIGHT be known. See if we can decode the raw data
1364 * into a valid attribute.
1366 len = data2vp(ctx, NULL, NULL, NULL, da,
1367 vp->vp_octets, vp->vp_length, vp->vp_length,
1369 if (len <= 0) return vp;
1372 * It's still unknown. Return the original VP.
1374 if (vp2->da->flags.is_unknown) {
1375 fr_pair_list_free(&vp2);
1380 * Didn't parse all of it. Return the "unknown" one.
1382 * FIXME: it COULD have parsed 2 attributes and
1383 * then not the third, so returning 2 "knowns"
1384 * and 1 "unknown" is likely preferable.
1386 if ((size_t) len < vp->vp_length) {
1387 fr_pair_list_free(&vp2);
1391 fr_pair_list_free(&vp);
1396 /** Create a VALUE_PAIR from ASCII strings
1398 * Converts an attribute string identifier (with an optional tag qualifier)
1399 * and value string into a VALUE_PAIR.
1401 * The string value is parsed according to the type of VALUE_PAIR being created.
1403 * @param[in] ctx for talloc
1404 * @param[in] vps list where the attribute will be added (optional)
1405 * @param[in] attribute name.
1406 * @param[in] value attribute value (may be NULL if value will be set later).
1407 * @param[in] op to assign to new VALUE_PAIR.
1408 * @return a new VALUE_PAIR.
1410 VALUE_PAIR *fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps,
1411 char const *attribute, char const *value, FR_TOKEN op)
1413 DICT_ATTR const *da;
1419 char const *attrname = attribute;
1422 * Check for tags in 'Attribute:Tag' format.
1427 ts = strrchr(attribute, ':');
1429 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1434 strlcpy(buffer, attribute, sizeof(buffer));
1436 ts = strrchr(attrname, ':');
1437 if (!ts) return NULL;
1439 /* Colon found with something behind it */
1440 if (ts[1] == '*' && ts[2] == 0) {
1441 /* Wildcard tag for check items */
1444 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1445 /* It's not a wild card tag */
1446 tag = strtol(ts + 1, &tc, 0);
1447 if (tc && !*tc && TAG_VALID_ZERO(tag))
1451 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1458 * It's not found in the dictionary, so we use
1459 * another method to create the attribute.
1461 da = dict_attrbyname(attrname);
1463 vp = fr_pair_make_unknown(ctx, attrname, value, op);
1464 if (vp && vps) fr_pair_add(vps, vp);
1468 /* Check for a tag in the 'Merit' format of:
1469 * :Tag:Value. Print an error if we already found
1470 * a tag in the Attribute.
1473 if (value && (*value == ':' && da->flags.has_tag)) {
1474 /* If we already found a tag, this is invalid */
1476 fr_strerror_printf("Duplicate tag %s for attribute %s",
1478 DEBUG("Duplicate tag %s for attribute %s\n",
1482 /* Colon found and attribute allows a tag */
1483 if (value[1] == '*' && value[2] == ':') {
1484 /* Wildcard tag for check items */
1489 tag = strtol(value + 1, &tc, 0);
1490 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1496 vp = fr_pair_afrom_da(ctx, da);
1497 if (!vp) return NULL;
1498 vp->op = (op == 0) ? T_OP_EQ : op;
1503 case T_OP_CMP_FALSE:
1504 vp->vp_strvalue = NULL;
1506 value = NULL; /* ignore it! */
1510 * Regular expression comparison of integer attributes
1511 * does a STRING comparison of the names of their
1512 * integer attributes.
1514 case T_OP_REG_EQ: /* =~ */
1515 case T_OP_REG_NE: /* !~ */
1518 fr_strerror_printf("Regular expressions are not supported");
1525 * Someone else will fill in the value.
1531 slen = regex_compile(ctx, &preg, value, strlen(value), false, false, false, true);
1533 fr_strerror_printf("Error at offset %zu compiling regex for %s: %s", -slen,
1534 attribute, fr_strerror());
1539 vp = fr_pair_make(ctx, NULL, attribute, NULL, op);
1540 if (!vp) return NULL;
1542 if (fr_pair_mark_xlat(vp, value) < 0) {
1547 value = NULL; /* ignore it */
1556 * We allow this for stupidity, but it's really a bad idea.
1558 if (vp->da->type == PW_TYPE_TLV) {
1560 DICT_ATTR const *unknown;
1561 VALUE_PAIR *head = NULL;
1562 VALUE_PAIR **tail = &head;
1569 unknown = dict_unknown_afrom_fields(vp, vp->da->attr, vp->da->vendor);
1578 * Parse it as an unknown type, i.e. octets.
1580 if (fr_pair_value_from_str(vp, value, -1) < 0) {
1586 * It's badly formatted. Treat it as unknown.
1588 if (rad_tlv_ok(vp->vp_octets, vp->vp_length, 1, 1) < 0) {
1595 len = rad_data2vp_tlvs(ctx, NULL, NULL, NULL, da, vp->vp_octets,
1596 vp->vp_length, tail);
1607 * FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
1608 * then the user MAY have typed in the attribute name
1609 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1611 * We probably want to fix fr_pair_value_from_str to accept
1612 * octets as values for any attribute.
1614 if (value && (fr_pair_value_from_str(vp, value, -1) < 0)) {
1620 if (vps) fr_pair_add(vps, vp);
1624 /** Mark a valuepair for xlat expansion
1626 * Copies xlat source (unprocessed) string to valuepair value,
1627 * and sets value type.
1629 * @param vp to mark for expansion.
1630 * @param value to expand.
1631 * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
1633 int fr_pair_mark_xlat(VALUE_PAIR *vp, char const *value)
1638 * valuepair should not already have a value.
1640 if (vp->type != VT_NONE) {
1641 fr_strerror_printf("Pair already has a value");
1645 raw = talloc_typed_strdup(vp, value);
1647 fr_strerror_printf("Out of memory");
1652 vp->value.xlat = raw;
1659 /** Read a single valuepair from a buffer, and advance the pointer
1661 * Returns T_EOL if end of line was encountered.
1663 * @param[in,out] ptr to read from and update.
1664 * @param[out] raw The struct to write the raw VALUE_PAIR to.
1665 * @return the last token read.
1667 FR_TOKEN fr_pair_raw_from_str(char const **ptr, VALUE_PAIR_RAW *raw)
1671 FR_TOKEN ret = T_INVALID, next, quote;
1674 if (!ptr || !*ptr || !raw) {
1675 fr_strerror_printf("Invalid arguments");
1680 * Skip leading spaces
1683 while ((*p == ' ') || (*p == '\t')) p++;
1686 fr_strerror_printf("No token read where we expected "
1687 "an attribute name");
1691 if (*p == '#') return T_HASH;
1694 * Try to get the attribute name.
1699 uint8_t const *t = (uint8_t const *) p;
1701 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1703 fr_strerror_printf("Attribute name too long");
1708 * This is arguably easier than trying to figure
1709 * out which operators come after the attribute
1710 * name. Yes, our "lexer" is bad.
1712 if (!dict_attr_allowed_chars[(unsigned int) *t]) {
1717 * Attribute:=value is NOT
1723 if ((*p == ':') && (!isdigit((int) p[1]))) {
1731 * Haven't found any valid characters in the name.
1733 if (!*raw->l_opand) {
1734 fr_strerror_printf("Invalid attribute name");
1739 * Look for tag (:#). This is different from :=, which
1742 if ((*p == ':') && (isdigit((int) p[1]))) {
1743 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1748 while (isdigit((int) *p)) {
1749 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1759 /* Now we should have an operator here. */
1760 raw->op = gettoken(ptr, buf, sizeof(buf), false);
1761 if (raw->op < T_EQSTART || raw->op > T_EQEND) {
1762 fr_strerror_printf("Expecting operator");
1768 * Read value. Note that empty string values are allowed
1770 quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand), false);
1771 if (quote == T_EOL) {
1772 fr_strerror_printf("Failed to get value");
1778 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1782 next = gettoken(&p, buf, sizeof(buf), false);
1796 fr_strerror_printf("Expected end of line or comma");
1805 case T_DOUBLE_QUOTED_STRING:
1807 * Only report as double quoted if it contained valid
1808 * a valid xlat expansion.
1810 p = strchr(raw->r_opand, '%');
1811 if (p && (p[1] == '{')) {
1814 raw->quote = T_SINGLE_QUOTED_STRING;
1819 case T_SINGLE_QUOTED_STRING:
1820 case T_BACK_QUOTED_STRING:
1826 fr_strerror_printf("Failed to find expected value on right hand side");
1833 /** Read one line of attribute/value pairs into a list.
1835 * The line may specify multiple attributes separated by commas.
1837 * @note If the function returns T_INVALID, an error has occurred and
1838 * @note the valuepair list should probably be freed.
1840 * @param ctx for talloc
1841 * @param buffer to read valuepairs from.
1842 * @param list where the parsed VALUE_PAIRs will be appended.
1843 * @return the last token parsed, or T_INVALID
1845 FR_TOKEN fr_pair_list_afrom_str(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
1847 VALUE_PAIR *vp, *head, **tail;
1849 FR_TOKEN last_token = T_INVALID;
1853 * We allow an empty line.
1855 if (buffer[0] == 0) {
1864 raw.l_opand[0] = '\0';
1865 raw.r_opand[0] = '\0';
1867 last_token = fr_pair_raw_from_str(&p, &raw);
1870 * JUST a hash. Don't try to create a VP.
1871 * Let the caller determine if an empty list is OK.
1873 if (last_token == T_HASH) {
1877 if (last_token == T_INVALID) break;
1879 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
1880 vp = fr_pair_make(ctx, NULL, raw.l_opand, NULL, raw.op);
1882 last_token = T_INVALID;
1885 if (fr_pair_mark_xlat(vp, raw.r_opand) < 0) {
1887 last_token = T_INVALID;
1891 vp = fr_pair_make(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
1893 last_token = T_INVALID;
1899 tail = &((*tail)->next);
1900 } while (*p && (last_token == T_COMMA));
1902 if (last_token == T_INVALID) {
1903 fr_pair_list_free(&head);
1905 fr_pair_add(list, head);
1909 * And return the last token which we read.
1915 * Read valuepairs from the fp up to End-Of-File.
1917 int fr_pair_list_afrom_file(TALLOC_CTX *ctx, VALUE_PAIR **out, FILE *fp, bool *pfiledone)
1920 FR_TOKEN last_token = T_EOL;
1924 VALUE_PAIR *vp = NULL;
1925 fr_cursor_init(&cursor, out);
1927 while (fgets(buf, sizeof(buf), fp) != NULL) {
1929 * If we get a '\n' by itself, we assume that's
1930 * the end of that VP
1932 if (buf[0] == '\n') {
1941 * Comments get ignored
1943 if (buf[0] == '#') continue;
1946 * Read all of the attributes on the current line.
1949 last_token = fr_pair_list_afrom_str(ctx, buf, &vp);
1951 if (last_token != T_EOL) goto error;
1955 fr_cursor_merge(&cursor, vp);
1964 vp = fr_cursor_first(&cursor);
1965 if (vp) fr_pair_list_free(&vp);
1970 /** Compare two pairs, using the operator from "a"
1972 * i.e. given two attributes, it does:
1974 * (b->data) (a->operator) (a->data)
1976 * e.g. "foo" != "bar"
1978 * @param[in] a the first attribute
1979 * @param[in] b the second attribute
1980 * @return 1 if true, 0 if false, -1 on error.
1982 int fr_pair_cmp(VALUE_PAIR *a, VALUE_PAIR *b)
1987 if (b) VERIFY_VP(b);
1993 case T_OP_CMP_FALSE:
1997 * a is a regex, compile it, print b to a string,
1998 * and then do string comparisons.
2005 if (!b) return false;
2012 if (!fr_assert(a->da->type == PW_TYPE_STRING)) return -1;
2014 slen = regex_compile(NULL, &preg, a->value.xlat, talloc_array_length(a->value.xlat) - 1, false, false, false, true);
2016 fr_strerror_printf("Error at offset %zu compiling regex for %s: %s",
2017 -slen, a->da->name, fr_strerror());
2020 value = vp_aprints_value(NULL, b, '\0');
2027 * Don't care about substring matches, oh well...
2029 slen = regex_exec(preg, value, talloc_array_length(value) - 1, NULL, NULL);
2033 if (slen < 0) return -1;
2034 if (a->op == T_OP_REG_EQ) return (int)slen;
2039 default: /* we're OK */
2040 if (!b) return false;
2044 return fr_pair_cmp_op(a->op, b, a);
2047 /** Determine equality of two lists
2049 * This is useful for comparing lists of attributes inserted into a binary tree.
2051 * @param a first list of VALUE_PAIRs.
2052 * @param b second list of VALUE_PAIRs.
2053 * @return -1 if a < b, 0 if the two lists are equal, 1 if a > b, -2 on error.
2055 int fr_pair_list_cmp(VALUE_PAIR *a, VALUE_PAIR *b)
2057 vp_cursor_t a_cursor, b_cursor;
2058 VALUE_PAIR *a_p, *b_p;
2061 for (a_p = fr_cursor_init(&a_cursor, &a), b_p = fr_cursor_init(&b_cursor, &b);
2063 a_p = fr_cursor_next(&a_cursor), b_p = fr_cursor_next(&b_cursor)) {
2064 /* Same VP, no point doing expensive checks */
2069 if (a_p->da < b_p->da) {
2072 if (a_p->da > b_p->da) {
2076 if (a_p->tag < b_p->tag) {
2079 if (a_p->tag > b_p->tag) {
2083 ret = value_data_cmp(a_p->da->type, &a_p->data, a_p->vp_length,
2084 b_p->da->type, &b_p->data, b_p->vp_length);
2086 fr_assert(ret >= -1); /* Comparison error */
2103 /** Set the type of the VALUE_PAIR value buffer to match it's DICT_ATTR
2105 * @param vp to fixup.
2107 static void fr_pair_value_set_type(VALUE_PAIR *vp)
2109 if (!vp->data.ptr) return;
2111 switch (vp->da->type) {
2112 case PW_TYPE_OCTETS:
2113 talloc_set_type(vp->data.ptr, uint8_t);
2116 case PW_TYPE_STRING:
2117 talloc_set_type(vp->data.ptr, char);
2125 /** Copy data into an "octets" data type.
2127 * @param[in,out] vp to update
2128 * @param[in] src data to copy
2129 * @param[in] size of the data, may be 0 in which case previous value will be freed.
2131 void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2133 uint8_t *p = NULL, *q;
2138 p = talloc_memdup(vp, src, size);
2140 talloc_set_type(p, uint8_t);
2143 memcpy(&q, &vp->vp_octets, sizeof(q));
2147 vp->vp_length = size;
2149 if (size > 0) fr_pair_value_set_type(vp);
2152 /** Reparent an allocated octet buffer to a VALUE_PAIR
2154 * @param[in,out] vp to update
2155 * @param[in] src buffer to steal.
2157 void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
2163 memcpy(&q, &vp->vp_octets, sizeof(q));
2166 vp->vp_octets = talloc_steal(vp, src);
2168 vp->vp_length = talloc_array_length(vp->vp_strvalue);
2169 fr_pair_value_set_type(vp);
2172 /** Reparent an allocated char buffer to a VALUE_PAIR
2174 * @param[in,out] vp to update
2175 * @param[in] src buffer to steal.
2177 void fr_pair_value_strsteal(VALUE_PAIR *vp, char const *src)
2183 memcpy(&q, &vp->vp_octets, sizeof(q));
2186 vp->vp_strvalue = talloc_steal(vp, src);
2188 vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2189 fr_pair_value_set_type(vp);
2192 /** Copy data into an "string" data type.
2194 * @param[in,out] vp to update
2195 * @param[in] src data to copy
2197 void fr_pair_value_strcpy(VALUE_PAIR *vp, char const *src)
2203 p = talloc_strdup(vp, src);
2207 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2210 vp->vp_strvalue = p;
2212 vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2213 fr_pair_value_set_type(vp);
2216 /** Copy data into an "string" data type.
2218 * @note unlike the original strncpy, this function does not stop
2219 * if it finds \0 bytes embedded in the string.
2221 * @param[in,out] vp to update.
2222 * @param[in] src data to copy.
2223 * @param[in] len of data to copy.
2225 void fr_pair_value_bstrncpy(VALUE_PAIR *vp, void const *src, size_t len)
2231 p = talloc_array(vp, char, len + 1);
2234 memcpy(p, src, len); /* embdedded \0 safe */
2237 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2240 vp->vp_strvalue = p;
2242 vp->vp_length = len;
2243 fr_pair_value_set_type(vp);
2246 /** Print data into an "string" data type.
2248 * @param[in,out] vp to update
2249 * @param[in] fmt the format string
2251 void fr_pair_value_sprintf(VALUE_PAIR *vp, char const *fmt, ...)
2259 p = talloc_vasprintf(vp, fmt, ap);
2264 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2267 vp->vp_strvalue = p;
2270 vp->vp_length = talloc_array_length(vp->vp_strvalue) - 1;
2271 fr_pair_value_set_type(vp);
2274 #ifdef WITH_VERIFY_PTR
2276 * Verify a VALUE_PAIR
2278 inline void fr_pair_verify(char const *file, int line, VALUE_PAIR const *vp)
2281 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR pointer was NULL", file, line);
2286 (void) talloc_get_type_abort(vp, VALUE_PAIR);
2289 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR da pointer was NULL", file, line);
2294 if (vp->data.ptr) switch (vp->da->type) {
2295 case PW_TYPE_OCTETS:
2300 if (!talloc_get_type(vp->data.ptr, uint8_t)) {
2301 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" data buffer type should be "
2302 "uint8_t but is %s\n", file, line, vp->da->name, talloc_get_name(vp->data.ptr));
2303 (void) talloc_get_type_abort(vp->data.ptr, uint8_t);
2306 len = talloc_array_length(vp->vp_octets);
2307 if (vp->vp_length > len) {
2308 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" length %zu is greater than "
2309 "uint8_t data buffer length %zu\n", file, line, vp->da->name, vp->vp_length, len);
2314 parent = talloc_parent(vp->data.ptr);
2316 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer is not "
2317 "parented by VALUE_PAIR %p, instead parented by %p (%s)\n",
2318 file, line, vp->da->name,
2319 vp, parent, parent ? talloc_get_name(parent) : "NULL");
2326 case PW_TYPE_STRING:
2331 if (!talloc_get_type(vp->data.ptr, char)) {
2332 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" data buffer type should be "
2333 "char but is %s\n", file, line, vp->da->name, talloc_get_name(vp->data.ptr));
2334 (void) talloc_get_type_abort(vp->data.ptr, char);
2337 len = (talloc_array_length(vp->vp_strvalue) - 1);
2338 if (vp->vp_length > len) {
2339 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" length %zu is greater than "
2340 "char buffer length %zu\n", file, line, vp->da->name, vp->vp_length, len);
2345 if (vp->vp_strvalue[vp->vp_length] != '\0') {
2346 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer not \\0 "
2347 "terminated\n", file, line, vp->da->name);
2352 parent = talloc_parent(vp->data.ptr);
2354 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR \"%s\" char buffer is not "
2355 "parented by VALUE_PAIR %p, instead parented by %p (%s)\n",
2356 file, line, vp->da->name,
2357 vp, parent, parent ? talloc_get_name(parent) : "NULL");
2368 if (vp->da->flags.is_unknown) {
2369 (void) talloc_get_type_abort(vp->da, DICT_ATTR);
2371 DICT_ATTR const *da;
2374 * Attribute may be present with multiple names
2376 da = dict_attrbyname(vp->da->name);
2378 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR attribute %p \"%s\" (%s) "
2379 "not found in global dictionary",
2380 file, line, vp->da, vp->da->name,
2381 fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
2386 if (da->type == PW_TYPE_COMBO_IP_ADDR) {
2387 da = dict_attrbytype(vp->da->attr, vp->da->vendor, vp->da->type);
2389 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR attribute %p \"%s\" "
2390 "variant (%s) not found in global dictionary",
2391 file, line, vp->da, vp->da->name,
2392 fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
2400 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: VALUE_PAIR "
2401 "dictionary pointer %p \"%s\" (%s) "
2402 "and global dictionary pointer %p \"%s\" (%s) differ",
2403 file, line, vp->da, vp->da->name,
2404 fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"),
2405 da, da->name, fr_int2str(dict_attr_types, da->type, "<INVALID>"));
2413 * Verify a pair list
2415 void fr_pair_list_verify(char const *file, int line, TALLOC_CTX *expected, VALUE_PAIR *vps)
2421 for (vp = fr_cursor_init(&cursor, &vps);
2423 vp = fr_cursor_next(&cursor)) {
2426 parent = talloc_parent(vp);
2427 if (expected && (parent != expected)) {
2428 FR_FAULT_LOG("CONSISTENCY CHECK FAILED %s[%u]: Expected VALUE_PAIR \"%s\" to be parented "
2429 "by %p (%s), instead parented by %p (%s)\n",
2430 file, line, vp->da->name,
2431 expected, talloc_get_name(expected),
2432 parent, parent ? talloc_get_name(parent) : "NULL");
2434 fr_log_talloc_report(expected);
2435 if (parent) fr_log_talloc_report(parent);