2 * valuepair.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>
29 #ifdef HAVE_PCREPOSIX_H
31 # include <pcreposix.h>
32 #elif defined(HAVE_REGEX_H)
37 * For POSIX Regular expressions.
38 * (0) Means no extended regular expressions.
39 * REG_EXTENDED means use extended regular expressions.
42 # define REG_EXTENDED (0)
46 # define REG_NOSUB (0)
50 #define attribute_eq(_x, _y) ((_x && _y) && (_x->da == _y->da) && (_x->tag == _y->tag))
54 * @note Do not call directly, use talloc_free instead.
59 static int _pairfree(VALUE_PAIR *vp) {
61 * The lack of DA means something has gone wrong
64 fr_strerror_printf("VALUE_PAIR has NULL DICT_ATTR pointer (probably already freed)");
66 * Only free the DICT_ATTR if it was dynamically allocated
67 * and was marked for free when the VALUE_PAIR is freed.
69 * @fixme This is an awful hack and needs to be removed once DICT_ATTRs are allocated by talloc.
71 } else if (vp->da->flags.vp_free) {
72 dict_attr_free(&(vp->da));
76 vp->vp_integer = 0xf4eef4ee;
80 talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL);
85 /** Dynamically allocate a new attribute
87 * Allocates a new attribute and a new dictionary attr if no DA is provided.
89 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
90 * @param[in] da Specifies the dictionary attribute to build the VP from.
91 * @return a new value pair or NULL if an error occurred.
93 VALUE_PAIR *pairalloc(TALLOC_CTX *ctx, DICT_ATTR const *da)
98 * Caller must specify a da else we don't know what the attribute type is.
101 fr_strerror_printf("Invalid arguments");
105 vp = talloc_zero(ctx, VALUE_PAIR);
107 fr_strerror_printf("Out of memory");
115 vp->length = da->flags.length;
117 talloc_set_destructor(vp, _pairfree);
122 /** Create a new valuepair
124 * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
127 * If attr or vendor are uknown will call dict_attruknown to create a dynamic
128 * DICT_ATTR of PW_TYPE_OCTETS.
130 * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
131 * checking @verbatim vp->da->flags.is_unknown @endverbatim.
133 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
134 * @param[in] attr number.
135 * @param[in] vendor number.
136 * @return the new valuepair or NULL on error.
138 VALUE_PAIR *paircreate(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
142 da = dict_attrbyvalue(attr, vendor);
144 da = dict_attrunknown(attr, vendor, true);
150 return pairalloc(ctx, da);
153 /** Free memory used by a valuepair list.
155 * @todo TLV: needs to free all dependents of each VP freed.
157 void pairfree(VALUE_PAIR **vps)
166 for (vp = fr_cursor_init(&cursor, vps);
168 vp = fr_cursor_next(&cursor)) {
176 /** Mark malformed or unrecognised attributed as unknown
178 * @param vp to change DICT_ATTR of.
179 * @return 0 on success (or if already unknown) else -1 on error.
181 int pair2unknown(VALUE_PAIR *vp)
186 if (vp->da->flags.is_unknown) {
190 da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
199 /** Find the pair with the matching DAs
202 VALUE_PAIR *pairfind_da(VALUE_PAIR *vp, DICT_ATTR const *da, int8_t tag)
211 for (i = fr_cursor_init(&cursor, &vp);
213 i = fr_cursor_next(&cursor)) {
215 if ((i->da == da) && (!i->da->flags.has_tag || (tag == TAG_ANY) || (i->tag == tag))) {
224 /** Find the pair with the matching attribute
226 * @todo should take DAs and do a pointer comparison.
228 VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag)
235 for (i = fr_cursor_init(&cursor, &vp);
237 i = fr_cursor_next(&cursor)) {
238 if ((i->da->attr == attr) && (i->da->vendor == vendor) && \
239 (!i->da->flags.has_tag || (tag == TAG_ANY) || (i->tag == tag))) {
247 /** Delete matching pairs
249 * Delete matching pairs from the attribute list.
251 * @param[in,out] first VP in list.
252 * @param[in] attr to match.
253 * @param[in] vendor to match.
254 * @param[in] tag to match. TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
256 * @todo should take DAs and do a point comparison.
258 void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor,
261 VALUE_PAIR *i, *next;
262 VALUE_PAIR **last = first;
264 for(i = *first; i; i = next) {
267 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
269 (i->da->flags.has_tag && (i->tag == tag)))) {
278 /** Add a VP to the end of the list.
280 * Locates the end of 'first', and links an additional VP 'add' at the end.
282 * @param[in] first VP in linked list. Will add new VP to the end of this list.
283 * @param[in] add VP to add to list.
285 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
293 if (*first == NULL) {
297 for(i = *first; i->next; i = i->next)
302 /** Replace all matching VPs
304 * Walks over 'first', and replaces the first VP that matches 'replace'.
306 * @note Memory used by the VP being replaced will be freed.
307 * @note Will not work with unknown attributes.
309 * @param[in,out] first VP in linked list. Will search and replace in this list.
310 * @param[in] replace VP to replace.
312 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
314 VALUE_PAIR *i, *next;
315 VALUE_PAIR **prev = first;
319 if (*first == NULL) {
325 * Not an empty list, so find item if it is there, and
326 * replace it. Note, we always replace the first one, and
327 * we ignore any others that might exist.
329 for(i = *first; i; i = next) {
334 * Found the first attribute, replace it,
337 if ((i->da == replace->da) &&
338 (!i->da->flags.has_tag || (i->tag == replace->tag))
343 * Should really assert that replace->next == NULL
345 replace->next = next;
351 * Point to where the attribute should go.
357 * If we got here, we didn't find anything to replace, so
358 * stopped at the last item, which we just append to.
363 int8_t attrtagcmp(void const *a, void const *b)
365 VALUE_PAIR const *my_a = a;
366 VALUE_PAIR const *my_b = b;
373 cmp = fr_pointer_cmp(my_a->da, my_b->da);
375 if (cmp != 0) return cmp;
377 if (my_a->tag < my_b->tag) {
381 if (my_a->tag > my_b->tag) {
388 static void pairsort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
394 * Stopping condition - no more elements left to split
396 if (!source || !source->next) {
404 * Fast advances twice as fast as slow, so when it gets to the end,
405 * slow will point to the middle of the linked list.
423 static VALUE_PAIR *pairsort_merge(VALUE_PAIR *a, VALUE_PAIR *b, fr_cmp_t cmp)
425 VALUE_PAIR *result = NULL;
431 * Compare the DICT_ATTRs and tags
433 if (cmp(a, b) <= 0) {
435 result->next = pairsort_merge(a->next, b, cmp);
438 result->next = pairsort_merge(a, b->next, cmp);
444 /** Sort a linked list of VALUE_PAIRs using merge sort
446 * @param[in,out] vps List of VALUE_PAIRs to sort.
447 * @param[in] cmp to sort with
449 void pairsort(VALUE_PAIR **vps, fr_cmp_t cmp)
451 VALUE_PAIR *head = *vps;
456 * If there's 0-1 elements it must already be sorted.
458 if (!head || !head->next) {
462 pairsort_split(head, &a, &b); /* Split into sublists */
463 pairsort(&a, cmp); /* Traverse left */
464 pairsort(&b, cmp); /* Traverse right */
467 * merge the two sorted lists together
469 *vps = pairsort_merge(a, b, cmp);
472 /** Write an error to the library errorbuff detailing the mismatch
474 * Retrieve output with fr_strerror();
476 * @todo add thread specific talloc contexts.
478 * @param ctx a hack until we have thread specific talloc contexts.
479 * @param failed pair of attributes which didn't match.
481 void pairvalidate_debug(TALLOC_CTX *ctx, VALUE_PAIR const *failed[2])
483 VALUE_PAIR const *filter = failed[0];
484 VALUE_PAIR const *list = failed[1];
488 (void) fr_strerror(); /* Clear any existing messages */
490 if (!fr_assert(!(!filter && !list))) return;
494 fr_strerror_printf("Attribute \"%s\" not found in list", filter->da->name);
498 if (!filter || (filter->da != list->da)) {
499 fr_strerror_printf("Attribute \"%s\" not found in filter", list->da->name);
503 if (filter->tag != list->tag) {
504 fr_strerror_printf("Attribute \"%s\" tag \"%i\" didn't match filter tag \"%i\"",
505 list->da->name, list->tag, list->tag);
509 pair = vp_aprint(ctx, filter);
510 value = vp_aprint_value(ctx, list);
512 fr_strerror_printf("Attribute value \"%s\" didn't match filter \"%s\"", value, pair);
520 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
522 * @note will sort both filter and list in place.
524 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
526 * @param filter attributes to check list against.
527 * @param list attributes, probably a request or reply
529 bool pairvalidate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
531 vp_cursor_t filter_cursor;
532 vp_cursor_t list_cursor;
534 VALUE_PAIR *check, *match;
536 if (!filter && !list) {
541 * This allows us to verify the sets of validate and reply are equal
542 * i.e. we have a validate rule which matches every reply attribute.
544 * @todo this should be removed one we have sets and lists
546 pairsort(&filter, attrtagcmp);
547 pairsort(&list, attrtagcmp);
549 check = fr_cursor_init(&filter_cursor, &filter);
550 match = fr_cursor_init(&list_cursor, &list);
553 if (!match && !check) goto mismatch;
556 * The lists are sorted, so if the first
557 * attributes aren't of the same type, then we're
560 if (!attribute_eq(check, match)) goto mismatch;
563 * They're of the same type, but don't have the
564 * same values. This is a problem.
566 * Note that the RFCs say that for attributes of
567 * the same type, order is important.
569 if (!paircmp(check, match)) goto mismatch;
571 check = fr_cursor_next(&filter_cursor);
572 match = fr_cursor_next(&list_cursor);
575 * One list ended earlier than the others, they
578 if (!match || !check) break;
591 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
593 * @note will sort both filter and list in place.
595 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
597 * @param filter attributes to check list against.
598 * @param list attributes, probably a request or reply
600 bool pairvalidate_relaxed(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
602 vp_cursor_t filter_cursor;
603 vp_cursor_t list_cursor;
605 VALUE_PAIR *check, *last_check = NULL, *match = NULL;
607 if (!filter && !list) {
612 * This allows us to verify the sets of validate and reply are equal
613 * i.e. we have a validate rule which matches every reply attribute.
615 * @todo this should be removed one we have sets and lists
617 pairsort(&filter, attrtagcmp);
618 pairsort(&list, attrtagcmp);
620 fr_cursor_init(&list_cursor, &list);
621 for (check = fr_cursor_init(&filter_cursor, &filter);
623 check = fr_cursor_next(&filter_cursor)) {
625 * Were processing check attributes of a new type.
627 if (!attribute_eq(last_check, check)) {
629 * Record the start of the matching attributes in the pair list
630 * For every other operator we require the match to be present
632 match = fr_cursor_next_by_da(&list_cursor, check->da, check->tag);
634 if (check->op == T_OP_CMP_FALSE) continue;
638 fr_cursor_init(&list_cursor, &match);
643 * Now iterate over all attributes of the same type.
645 for (match = fr_cursor_first(&list_cursor);
646 attribute_eq(match, check);
647 match = fr_cursor_next(&list_cursor)) {
649 * This attribute passed the filter
651 if (!paircmp(check, match)) goto mismatch;
665 /** Copy a single valuepair
667 * Allocate a new valuepair and copy the da from the old vp.
669 * @param[in] ctx for talloc
670 * @param[in] vp to copy.
671 * @return a copy of the input VP or NULL on error.
673 VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
677 if (!vp) return NULL;
681 n = pairalloc(ctx, vp->da);
684 memcpy(n, vp, sizeof(*n));
689 if (vp->type == VT_XLAT) {
690 n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
693 n->da = dict_attr_copy(vp->da, true);
701 if (n->data.ptr) switch (n->da->type) {
704 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
705 talloc_set_type(n->vp_octets, uint8_t);
709 n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1); /* NULL byte */
710 talloc_set_type(n->vp_strvalue, char);
720 /** Copy data from one VP to another
722 * Allocate a new pair using da, and copy over the value from the specified
725 * @todo Should be able to do type conversions.
727 * @param[in] ctx for talloc
728 * @param[in] da of new attribute to alloc.
729 * @param[in] vp to copy data from.
730 * @return the new valuepair.
732 VALUE_PAIR *paircopyvpdata(TALLOC_CTX *ctx, DICT_ATTR const *da, VALUE_PAIR const *vp)
736 if (!vp) return NULL;
741 * The types have to be identical, OR the "from" VP has
744 if (da->type != vp->da->type) {
747 VALUE_PAIR const **pvp;
749 if (vp->da->type == PW_TYPE_OCTETS) {
751 * Decode the data. It may be wrong!
753 if (rad_data2vp(da->attr, da->vendor, vp->vp_octets, vp->length, &n) < 0) {
762 * Else the destination type is octets
764 switch (vp->da->type) {
766 return NULL; /* can't do it */
768 case PW_TYPE_INTEGER:
772 case PW_TYPE_IPV6ADDR:
773 case PW_TYPE_IPV6PREFIX:
776 case PW_TYPE_ETHERNET:
778 case PW_TYPE_INTEGER64:
779 case PW_TYPE_IPV4PREFIX:
783 n = pairalloc(ctx, da);
786 p = talloc_array(n, uint8_t, dict_attr_sizes[vp->da->type][1] + 2);
789 length = rad_vp2attr(NULL, NULL, NULL, pvp, p, dict_attr_sizes[vp->da->type][1]);
795 pairmemcpy(n, p + 2, length - 2);
800 n = pairalloc(ctx, da);
803 memcpy(n, vp, sizeof(*n));
806 if (n->type == VT_XLAT) {
807 n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
810 if (n->data.ptr) switch (n->da->type) {
813 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
814 talloc_set_type(n->vp_octets, uint8_t);
818 n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1); /* NULL byte */
819 talloc_set_type(n->vp_strvalue, char);
834 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
836 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
837 * @param[in] from whence to copy VALUE_PAIRs.
838 * @return the head of the new VALUE_PAIR list or NULL on error.
840 VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from)
842 vp_cursor_t src, dst;
844 VALUE_PAIR *out = NULL, *vp;
846 fr_cursor_init(&dst, &out);
847 for (vp = fr_cursor_init(&src, &from);
849 vp = fr_cursor_next(&src)) {
851 vp = paircopyvp(ctx, vp);
856 fr_cursor_insert(&dst, vp); /* paircopy sets next pointer to NULL */
862 /** Copy matching pairs
864 * Copy pairs of a matching attribute number, vendor number and tag from the
865 * the input list to a new list, and returns the head of this list.
867 * @param[in] ctx for talloc
868 * @param[in] from whence to copy VALUE_PAIRs.
869 * @param[in] attr to match, if 0 input list will not be filtered by attr.
870 * @param[in] vendor to match.
871 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
872 * @return the head of the new VALUE_PAIR list or NULL on error.
874 VALUE_PAIR *paircopy2(TALLOC_CTX *ctx, VALUE_PAIR *from,
875 unsigned int attr, unsigned int vendor, int8_t tag)
877 vp_cursor_t src, dst;
879 VALUE_PAIR *out = NULL, *vp;
881 fr_cursor_init(&dst, &out);
882 for (vp = fr_cursor_init(&src, &from);
884 vp = fr_cursor_next(&src)) {
887 if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
891 if ((tag != TAG_ANY) && vp->da->flags.has_tag && (vp->tag != tag)) {
895 vp = paircopyvp(ctx, vp);
900 fr_cursor_insert(&dst, vp);
906 /** Steal all members of a VALUE_PAIR list
908 * @param[in] ctx to move VALUE_PAIRs into
909 * @param[in] from VALUE_PAIRs to move into the new context.
911 VALUE_PAIR *pairsteal(TALLOC_CTX *ctx, VALUE_PAIR *from)
916 for (vp = fr_cursor_init(&cursor, &from);
918 vp = fr_cursor_next(&cursor)) {
919 (void) talloc_steal(ctx, vp);
925 /** Move pairs from source list to destination list respecting operator
927 * @note This function does some additional magic that's probably not needed
928 * in most places. Consider using radius_pairmove in server code.
930 * @note pairfree should be called on the head of the source list to free
931 * unmoved attributes (if they're no longer needed).
933 * @note Does not respect tags when matching.
935 * @param[in] ctx for talloc
936 * @param[in,out] to destination list.
937 * @param[in,out] from source list.
939 * @see radius_pairmove
941 void pairmove(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
943 VALUE_PAIR *i, *found;
944 VALUE_PAIR *head_new, **tail_new;
945 VALUE_PAIR **tail_from;
947 if (!to || !from || !*from) return;
950 * We're editing the "to" list while we're adding new
951 * attributes to it. We don't want the new attributes to
952 * be edited, so we create an intermediate list to hold
953 * them during the editing process.
956 tail_new = &head_new;
959 * We're looping over the "from" list, moving some
960 * attributes out, but leaving others in place.
963 while ((i = *tail_from) != NULL) {
967 * We never move Fall-Through.
969 if (!i->da->vendor && i->da->attr == PW_FALL_THROUGH) {
970 tail_from = &(i->next);
975 * Unlike previous versions, we treat all other
976 * attributes as normal. i.e. there's no special
977 * treatment for passwords or Hint.
982 * Anything else are operators which
983 * shouldn't occur. We ignore them, and
984 * leave them in place.
987 tail_from = &(i->next);
991 * Add it to the "to" list, but only if
992 * it doesn't already exist.
995 found = pairfind(*to, i->da->attr, i->da->vendor,
997 if (!found) goto do_add;
999 tail_from = &(i->next);
1003 * Add it to the "to" list, and delete any attribute
1004 * of the same vendor/attr which already exists.
1007 found = pairfind(*to, i->da->attr, i->da->vendor,
1009 if (!found) goto do_add;
1012 * Do NOT call pairdelete() here,
1013 * due to issues with re-writing
1014 * "request->username".
1016 * Everybody calls pairmove, and
1017 * expects it to work. We can't
1018 * update request->username here,
1019 * so instead we over-write the
1020 * vp that it's pointing to.
1022 switch (found->da->type) {
1027 memcpy(found, i, sizeof(*found));
1032 pairmemsteal(found, i->vp_tlv);
1036 case PW_TYPE_OCTETS:
1037 pairmemsteal(found, i->vp_octets);
1038 i->vp_octets = NULL;
1041 case PW_TYPE_STRING:
1042 pairstrsteal(found, i->vp_strvalue);
1043 i->vp_strvalue = NULL;
1044 found->tag = i->tag;
1049 * Delete *all* of the attributes
1050 * of the same number.
1052 pairdelete(&found->next,
1054 found->da->vendor, TAG_ANY);
1057 * Remove this attribute from the
1060 *tail_from = i->next;
1066 * Move it from the old list and add it
1071 *tail_from = i->next;
1073 *tail_new = talloc_steal(ctx, i);
1074 tail_new = &(i->next);
1077 } /* loop over the "from" list. */
1080 * Take the "new" list, and append it to the "to" list.
1082 pairadd(to, head_new);
1085 /** Move matching pairs between VALUE_PAIR lists
1087 * Move pairs of a matching attribute number, vendor number and tag from the
1088 * the input list to the output list.
1090 * @note pairfree should be called on the head of the old list to free unmoved
1091 attributes (if they're no longer needed).
1093 * @param[in] ctx for talloc
1094 * @param[in,out] to destination list.
1095 * @param[in,out] from source list.
1096 * @param[in] attr to match, if PW_VENDOR_SPECIFIC and vendor 0, only VSAs will
1097 * be copied. If 0 and 0, all attributes will match
1098 * @param[in] vendor to match.
1099 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
1101 void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor, int8_t tag)
1103 VALUE_PAIR *to_tail, *i, *next;
1104 VALUE_PAIR *iprev = NULL;
1107 * Find the last pair in the "to" list and put it in "to_tail".
1109 * @todo: replace the "if" with "VALUE_PAIR **tail"
1113 for(i = *to; i; i = i->next) {
1121 * Attr/vendor of 0 means "move them all".
1122 * It's better than "pairadd(foo,bar);bar=NULL"
1124 if ((vendor == 0) && (attr == 0)) {
1126 to_tail->next = *from;
1131 for (i = *from; i; i = i->next) {
1132 (void) talloc_steal(ctx, i);
1139 for(i = *from; i; i = next) {
1143 if ((tag != TAG_ANY) && i->da->flags.has_tag &&
1149 * vendor=0, attr = PW_VENDOR_SPECIFIC means
1150 * "match any vendor attribute".
1152 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1154 * It's a VSA: move it over.
1156 if (i->da->vendor != 0) goto move;
1159 * It's Vendor-Specific: move it over.
1161 if (i->da->attr == attr) goto move;
1164 * It's not a VSA: ignore it.
1171 * If it isn't an exact match, ignore it.
1173 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1180 * Remove the attribute from the "from" list.
1188 * Add the attribute to the "to" list.
1196 (void) talloc_steal(ctx, i);
1200 static char const *hextab = "0123456789abcdef";
1202 bool pairparsevalue(VALUE_PAIR *vp, char const *value)
1205 char const *cp, *cs;
1211 if (!value) return false;
1215 * It's a comparison, not a real VALUE_PAIR, copy the string over verbatim
1217 if ((vp->op == T_OP_REG_EQ) || (vp->op == T_OP_REG_NE)) {
1218 pairstrcpy(vp, value); /* Icky hacky ewww */
1222 switch(vp->da->type) {
1223 case PW_TYPE_STRING:
1227 p = talloc_typed_strdup(vp, value);
1228 vp->vp_strvalue = p;
1235 if (c == '\\') switch (*cp) {
1265 c = '\\'; /* no cp++ */
1268 if ((cp[0] >= '0') &&
1274 (sscanf(cp, "%3o", &x) == 1)) {
1283 } /* else at EOL \ --> \ */
1289 vp->length = length;
1292 case PW_TYPE_IPADDR:
1294 * FIXME: complain if hostname
1295 * cannot be resolved, or resolve later!
1303 * Convert things which are obviously integers to IP addresses
1305 * We assume the number is the bigendian representation of the
1308 if (is_integer(value)) {
1309 vp->vp_ipaddr = htonl(atol(value));
1314 * Certain applications/databases print IPv4 addresses with a
1315 * /32 suffix. Strip it off if the mask is 32, else error out.
1317 p = strchr(value, '/');
1319 if ((p[1] != '3') || (p[2] != '2') || (p[3] != '\0')) {
1320 fr_strerror_printf("Invalid IP address suffix \"%s\". Only '/32' permitted "
1321 "for non-prefix types", p);
1325 strlcpy(ipv4, value, sizeof(ipv4));
1326 ipv4[p - value] = '\0';
1332 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
1333 fr_strerror_printf("Failed to find IP address for %s", cs);
1337 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1346 * Note that ALL integers are unsigned!
1348 vp->vp_integer = fr_strtoul(value, &p);
1350 if (vp->vp_integer > 255) {
1351 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
1356 if (is_whitespace(p)) break;
1357 goto check_for_value;
1361 * Note that ALL integers are unsigned!
1363 vp->vp_integer = fr_strtoul(value, &p);
1366 if (vp->vp_integer > 65535) {
1367 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1372 if (is_whitespace(p)) break;
1373 goto check_for_value;
1375 case PW_TYPE_INTEGER:
1377 * Note that ALL integers are unsigned!
1379 vp->vp_integer = fr_strtoul(value, &p);
1382 if (is_whitespace(p)) break;
1386 * Look for the named value for the given
1389 if ((dval = dict_valbyname(vp->da->attr, vp->da->vendor, value)) == NULL) {
1390 fr_strerror_printf("Unknown value '%s' for attribute '%s'", value, vp->da->name);
1393 vp->vp_integer = dval->value;
1396 case PW_TYPE_INTEGER64:
1398 * Note that ALL integers are unsigned!
1400 if (sscanf(value, "%" PRIu64, &y) != 1) {
1401 fr_strerror_printf("Invalid value '%s' for attribute '%s'",
1402 value, vp->da->name);
1405 vp->vp_integer64 = y;
1407 length = strspn(value, "0123456789");
1408 if (is_whitespace(value + length)) break;
1414 * time_t may be 64 bits, whule vp_date
1415 * MUST be 32-bits. We need an
1416 * intermediary variable to handle
1421 if (fr_get_time(value, &date) < 0) {
1422 fr_strerror_printf("failed to parse time string "
1432 case PW_TYPE_ABINARY:
1433 #ifdef WITH_ASCEND_BINARY
1434 if (strncasecmp(value, "0x", 2) == 0) {
1438 if (ascend_parse_filter(vp, value) < 0 ) {
1439 /* Allow ascend_parse_filter's strerror to bubble up */
1445 * If Ascend binary is NOT defined,
1446 * then fall through to raw octets, so that
1447 * the user can at least make them by hand...
1450 /* raw octets: 0x01020304... */
1452 if (strcmp(value, "ANY") == 0) {
1455 } /* else it's hex */
1457 case PW_TYPE_OCTETS:
1458 if (strncasecmp(value, "0x", 2) == 0) {
1462 #ifdef WITH_ASCEND_BINARY
1467 vp->length = size >> 1;
1468 us = talloc_array(vp, uint8_t, vp->length);
1473 if ((size & 0x01) != 0) {
1474 fr_strerror_printf("Hex string is not an even length string");
1478 if (fr_hex2bin(us, cp, vp->length) != vp->length) {
1479 fr_strerror_printf("Invalid hex data");
1484 pairmemcpy(vp, (const uint8_t *) value, strlen(value));
1489 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1490 fr_strerror_printf("Failed to parse interface-id string \"%s\"", value);
1496 case PW_TYPE_IPV6ADDR:
1500 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1503 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1505 fr_strerror_printf("failed to parse IPv6 address "
1506 "string \"%s\": %s", value, buffer);
1509 vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
1510 vp->length = 16; /* length of IPv6 address */
1514 case PW_TYPE_IPV6PREFIX:
1515 p = strchr(value, '/');
1516 if (!p || ((p - value) >= 256)) {
1517 fr_strerror_printf("invalid IPv6 prefix string \"%s\"", value);
1520 unsigned int prefix;
1521 char buffer[256], *eptr;
1523 memcpy(buffer, value, p - value);
1524 buffer[p - value] = '\0';
1526 if (inet_pton(AF_INET6, buffer, vp->vp_ipv6prefix + 2) <= 0) {
1527 fr_strerror_printf("failed to parse IPv6 address string \"%s\"", value);
1531 prefix = strtoul(p + 1, &eptr, 10);
1532 if ((prefix > 128) || *eptr) {
1533 fr_strerror_printf("failed to parse IPv6 address string \"%s\"", value);
1536 vp->vp_ipv6prefix[1] = prefix;
1539 struct in6_addr addr;
1541 addr = fr_ipaddr_mask6((struct in6_addr *)(&vp->vp_ipv6prefix[2]), prefix);
1542 memcpy(vp->vp_ipv6prefix + 2, &addr, sizeof(addr));
1545 vp->length = 16 + 2;
1548 case PW_TYPE_IPV4PREFIX:
1549 p = strchr(value, '/');
1552 * 192.0.2.2 is parsed as if it was /32
1555 vp->vp_ipv4prefix[1] = 32;
1557 if (inet_pton(AF_INET, value, vp->vp_ipv4prefix + 2) <= 0) {
1558 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1561 vp->length = sizeof(vp->vp_ipv4prefix);
1566 * Otherwise parse the prefix
1568 if ((p - value) >= 256) {
1569 fr_strerror_printf("invalid IPv4 prefix string \"%s\"", value);
1572 unsigned int prefix;
1573 char buffer[256], *eptr;
1575 memcpy(buffer, value, p - value);
1576 buffer[p - value] = '\0';
1578 if (inet_pton(AF_INET, buffer, vp->vp_ipv4prefix + 2) <= 0) {
1579 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1583 prefix = strtoul(p + 1, &eptr, 10);
1584 if ((prefix > 32) || *eptr) {
1585 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1588 vp->vp_ipv4prefix[1] = prefix;
1591 struct in_addr addr;
1593 addr = fr_ipaddr_mask((struct in_addr *)(&vp->vp_ipv4prefix[2]), prefix);
1594 memcpy(vp->vp_ipv4prefix + 2, &addr, sizeof(addr));
1597 vp->length = sizeof(vp->vp_ipv4prefix);
1600 case PW_TYPE_ETHERNET:
1602 char const *c1, *c2;
1605 * Convert things which are obviously integers to Ethernet addresses
1607 * We assume the number is the bigendian representation of the
1610 if (is_integer(value)) {
1611 uint64_t integer = htonll(atoll(value));
1613 memcpy(&vp->vp_ether, &integer, sizeof(vp->vp_ether));
1622 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1624 } else if ((cp[1] != '\0') &&
1627 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1628 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1630 if (*cp == ':') cp++;
1634 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1635 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1638 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1646 * Crazy polymorphic (IPv4/IPv6) attribute type for WiMAX.
1648 * We try and make is saner by replacing the original
1649 * da, with either an IPv4 or IPv6 da type.
1651 * These are not dynamic da, and will have the same vendor
1652 * and attribute as the original.
1654 case PW_TYPE_COMBO_IP:
1656 DICT_ATTR const *da;
1658 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) > 0) {
1659 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1662 fr_strerror_printf("Cannot find ipv6addr for %s", vp->da->name);
1666 vp->length = 16; /* length of IPv6 address */
1670 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1673 fr_strerror_printf("Cannot find ipaddr for %s", vp->da->name);
1677 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1678 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1682 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1690 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1691 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1695 case PW_TYPE_TLV: /* don't use this! */
1696 if (strncasecmp(value, "0x", 2) != 0) {
1697 fr_strerror_printf("Invalid TLV specification");
1700 length = strlen(value + 2) / 2;
1701 if (vp->length < length) {
1702 TALLOC_FREE(vp->vp_tlv);
1704 vp->vp_tlv = talloc_array(vp, uint8_t, length);
1706 fr_strerror_printf("No memory");
1709 if (fr_hex2bin(vp->vp_tlv, value + 2, length) != length) {
1710 fr_strerror_printf("Invalid hex data in TLV");
1713 vp->length = length;
1720 fr_strerror_printf("unknown attribute type %d", vp->da->type);
1729 /** Use simple heuristics to create an VALUE_PAIR from an unknown address string
1731 * If a DICT_ATTR is not provided for the address type, parsing will fail with
1734 * @param ctx to allocate VP in.
1735 * @param value IPv4/IPv6 address/prefix string.
1736 * @param ipv4 dictionary attribute to use for an IPv4 address.
1737 * @param ipv6 dictionary attribute to use for an IPv6 address.
1738 * @param ipv4_prefix dictionary attribute to use for an IPv4 prefix.
1739 * @param ipv6_prefix dictionary attribute to use for an IPv6 prefix.
1740 * @return NULL on error, or new VALUE_PAIR.
1742 VALUE_PAIR *pairmake_ip(TALLOC_CTX *ctx, char const *value, DICT_ATTR *ipv4, DICT_ATTR *ipv6,
1743 DICT_ATTR *ipv4_prefix, DICT_ATTR *ipv6_prefix)
1746 DICT_ATTR *da = NULL;
1748 if (!fr_assert(ipv4 || ipv6 || ipv4_prefix || ipv6_prefix)) {
1752 /* No point in repeating the work of pairparsevalue */
1753 if (strchr(value, ':')) {
1754 if (strchr(value, '/')) {
1763 if (strchr(value, '/')) {
1773 fr_strerror_printf("Invalid IP value specified, allowed types are %s%s%s%s",
1774 ipv4 ? "ipaddr " : "", ipv6 ? "ipv6addr " : "",
1775 ipv4_prefix ? "ipv4prefix " : "", ipv6_prefix ? "ipv6prefix" : "");
1778 vp = pairalloc(ctx, da);
1779 if (!vp) return NULL;
1780 if (!pairparsevalue(vp, value)) {
1789 /** Create a valuepair from an ASCII attribute and value
1791 * Where the attribute name is in the form:
1793 * - Attr-%d.%d.%d...
1794 * - Vendor-%d-Attr-%d
1795 * - VendorName-Attr-%d
1797 * @param ctx for talloc
1798 * @param attribute name to parse.
1799 * @param value to parse (must be a hex string).
1800 * @param op to assign to new valuepair.
1801 * @return new valuepair or NULL on error.
1803 static VALUE_PAIR *pairmake_any(TALLOC_CTX *ctx,
1804 char const *attribute, char const *value,
1808 DICT_ATTR const *da;
1813 da = dict_attrunknownbyname(attribute, true);
1814 if (!da) return NULL;
1817 * Unknown attributes MUST be of type 'octets'
1819 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1820 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1821 "string, not \"%s\"", attribute, value);
1823 dict_attr_free(&da);
1828 * We've now parsed the attribute properly, Let's create
1829 * it. This next stop also looks the attribute up in the
1830 * dictionary, and creates the appropriate type for it.
1832 vp = pairalloc(ctx, da);
1834 dict_attr_free(&da);
1838 vp->op = (op == 0) ? T_OP_EQ : op;
1840 if (!value) return vp;
1842 size = strlen(value + 2);
1843 vp->length = size >> 1;
1844 data = talloc_array(vp, uint8_t, vp->length);
1846 if (fr_hex2bin(data, value + 2, size) != vp->length) {
1847 fr_strerror_printf("Invalid hex string");
1852 vp->vp_octets = data;
1858 /** Create a VALUE_PAIR from ASCII strings
1860 * Converts an attribute string identifier (with an optional tag qualifier)
1861 * and value string into a VALUE_PAIR.
1863 * The string value is parsed according to the type of VALUE_PAIR being created.
1865 * @param[in] ctx for talloc
1866 * @param[in] vps list where the attribute will be added (optional)
1867 * @param[in] attribute name.
1868 * @param[in] value attribute value (may be NULL if value will be set later).
1869 * @param[in] op to assign to new VALUE_PAIR.
1870 * @return a new VALUE_PAIR.
1872 VALUE_PAIR *pairmake(TALLOC_CTX *ctx, VALUE_PAIR **vps,
1873 char const *attribute, char const *value, FR_TOKEN op)
1875 DICT_ATTR const *da;
1881 char const *attrname = attribute;
1884 * Check for tags in 'Attribute:Tag' format.
1889 ts = strrchr(attribute, ':');
1891 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1896 strlcpy(buffer, attribute, sizeof(buffer));
1898 ts = strrchr(attrname, ':');
1899 if (!ts) return NULL;
1901 /* Colon found with something behind it */
1902 if (ts[1] == '*' && ts[2] == 0) {
1903 /* Wildcard tag for check items */
1906 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1907 /* It's not a wild card tag */
1908 tag = strtol(ts + 1, &tc, 0);
1909 if (tc && !*tc && TAG_VALID_ZERO(tag))
1913 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1920 * It's not found in the dictionary, so we use
1921 * another method to create the attribute.
1923 da = dict_attrbyname(attrname);
1925 vp = pairmake_any(ctx, attrname, value, op);
1926 if (vp && vps) pairadd(vps, vp);
1930 /* Check for a tag in the 'Merit' format of:
1931 * :Tag:Value. Print an error if we already found
1932 * a tag in the Attribute.
1935 if (value && (*value == ':' && da->flags.has_tag)) {
1936 /* If we already found a tag, this is invalid */
1938 fr_strerror_printf("Duplicate tag %s for attribute %s",
1940 DEBUG("Duplicate tag %s for attribute %s\n",
1944 /* Colon found and attribute allows a tag */
1945 if (value[1] == '*' && value[2] == ':') {
1946 /* Wildcard tag for check items */
1951 tag = strtol(value + 1, &tc, 0);
1952 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1958 vp = pairalloc(ctx, da);
1959 if (!vp) return NULL;
1960 vp->op = (op == 0) ? T_OP_EQ : op;
1965 case T_OP_CMP_FALSE:
1966 vp->vp_strvalue = NULL;
1968 value = NULL; /* ignore it! */
1972 * Regular expression comparison of integer attributes
1973 * does a STRING comparison of the names of their
1974 * integer attributes.
1976 case T_OP_REG_EQ: /* =~ */
1977 case T_OP_REG_NE: /* !~ */
1983 fr_strerror_printf("Regular expressions are not supported");
1989 * Someone else will fill in the value.
1995 compare = regcomp(®, value, REG_EXTENDED);
1997 regerror(compare, ®, buffer, sizeof(buffer));
1998 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2004 vp = pairmake(ctx, NULL, attribute, NULL, op);
2005 if (!vp) return NULL;
2007 if (pairmark_xlat(vp, value) < 0) {
2012 value = NULL; /* ignore it */
2021 * FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
2022 * then the user MAY have typed in the attribute name
2023 * as Vendor-%d-Attr-%d, and the value MAY be octets.
2025 * We probably want to fix pairparsevalue to accept
2026 * octets as values for any attribute.
2028 if (value && !pairparsevalue(vp, value)) {
2033 if (vps) pairadd(vps, vp);
2037 /** Mark a valuepair for xlat expansion
2039 * Copies xlat source (unprocessed) string to valuepair value,
2040 * and sets value type.
2042 * @param vp to mark for expansion.
2043 * @param value to expand.
2044 * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
2046 int pairmark_xlat(VALUE_PAIR *vp, char const *value)
2051 * valuepair should not already have a value.
2053 if (vp->type != VT_NONE) {
2057 raw = talloc_typed_strdup(vp, value);
2063 vp->value.xlat = raw;
2069 /** Read a single valuepair from a buffer, and advance the pointer
2071 * Sets *eol to T_EOL if end of line was encountered.
2073 * @param[in,out] ptr to read from and update.
2074 * @param[out] raw The struct to write the raw VALUE_PAIR to.
2075 * @return the last token read.
2077 FR_TOKEN pairread(char const **ptr, VALUE_PAIR_RAW *raw)
2081 FR_TOKEN ret = T_OP_INVALID, next, quote;
2084 if (!ptr || !*ptr || !raw) {
2085 fr_strerror_printf("Invalid arguments");
2086 return T_OP_INVALID;
2090 * Skip leading spaces
2093 while ((*p == ' ') || (*p == '\t')) p++;
2096 fr_strerror_printf("No token read where we expected "
2097 "an attribute name");
2098 return T_OP_INVALID;
2102 fr_strerror_printf("Read a comment instead of a token");
2108 * Try to get the attribute name.
2113 uint8_t const *t = (uint8_t const *) p;
2115 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2117 fr_strerror_printf("Attribute name too long");
2118 return T_OP_INVALID;
2122 * Only ASCII is allowed, and only a subset of that.
2124 if ((*t < 32) || (*t >= 128)) {
2126 fr_strerror_printf("Invalid attribute name");
2127 return T_OP_INVALID;
2131 * This is arguably easier than trying to figure
2132 * out which operators come after the attribute
2133 * name. Yes, our "lexer" is bad.
2135 if (!dict_attr_allowed_chars[(int) *t]) {
2143 * ASCII, but not a valid attribute name.
2145 if (!*raw->l_opand) goto invalid;
2148 * Look for tag (:#). This is different from :=, which
2151 if ((*p == ':') && (isdigit((int) p[1]))) {
2152 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2157 while (isdigit((int) *p)) {
2158 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2168 /* Now we should have an operator here. */
2169 raw->op = gettoken(ptr, buf, sizeof(buf), false);
2170 if (raw->op < T_EQSTART || raw->op > T_EQEND) {
2171 fr_strerror_printf("Expecting operator");
2173 return T_OP_INVALID;
2177 * Read value. Note that empty string values are allowed
2179 quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand), false);
2180 if (quote == T_EOL) {
2181 fr_strerror_printf("Failed to get value");
2183 return T_OP_INVALID;
2187 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
2191 next = gettoken(&p, buf, sizeof(buf), false);
2202 fr_strerror_printf("Expected end of line or comma");
2203 return T_OP_INVALID;
2211 case T_DOUBLE_QUOTED_STRING:
2213 * Only report as double quoted if it contained valid
2214 * a valid xlat expansion.
2216 p = strchr(raw->r_opand, '%');
2217 if (p && (p[1] == '{')) {
2220 raw->quote = T_SINGLE_QUOTED_STRING;
2233 /** Read one line of attribute/value pairs into a list.
2235 * The line may specify multiple attributes separated by commas.
2237 * @note If the function returns T_OP_INVALID, an error has occurred and
2238 * @note the valuepair list should probably be freed.
2240 * @param ctx for talloc
2241 * @param buffer to read valuepairs from.
2242 * @param list where the parsed VALUE_PAIRs will be appended.
2243 * @return the last token parsed, or T_OP_INVALID
2245 FR_TOKEN userparse(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
2247 VALUE_PAIR *vp, *head, **tail;
2249 FR_TOKEN last_token = T_OP_INVALID;
2250 FR_TOKEN previous_token;
2254 * We allow an empty line.
2256 if (buffer[0] == 0) {
2265 raw.l_opand[0] = '\0';
2266 raw.r_opand[0] = '\0';
2268 previous_token = last_token;
2270 last_token = pairread(&p, &raw);
2271 if (last_token == T_OP_INVALID) break;
2273 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
2274 vp = pairmake(ctx, NULL, raw.l_opand, NULL, raw.op);
2276 last_token = T_OP_INVALID;
2279 if (pairmark_xlat(vp, raw.r_opand) < 0) {
2281 last_token = T_OP_INVALID;
2285 vp = pairmake(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
2287 last_token = T_OP_INVALID;
2293 tail = &((*tail)->next);
2294 } while (*p && (last_token == T_COMMA));
2297 * Don't tell the caller that there was a comment.
2299 if (last_token == T_HASH) {
2300 last_token = previous_token;
2303 if (last_token == T_OP_INVALID) {
2306 pairadd(list, head);
2310 * And return the last token which we read.
2316 * Read valuepairs from the fp up to End-Of-File.
2318 int readvp2(VALUE_PAIR **out, TALLOC_CTX *ctx, FILE *fp, bool *pfiledone)
2321 FR_TOKEN last_token = T_EOL;
2325 VALUE_PAIR *vp = NULL;
2327 fr_cursor_init(&cursor, out);
2329 while (fgets(buf, sizeof(buf), fp) != NULL) {
2331 * If we get a '\n' by itself, we assume that's
2332 * the end of that VP
2334 if (buf[0] == '\n') {
2340 * Comments get ignored
2342 if (buf[0] == '#') continue;
2345 * Read all of the attributes on the current line.
2348 last_token = userparse(ctx, buf, &vp);
2350 if (last_token != T_EOL) goto error;
2354 fr_cursor_insert(&cursor, vp);
2363 vp = fr_cursor_first(&cursor);
2364 if (vp) pairfree(&vp);
2369 /** Compare two attribute values
2371 * @param[in] one the first attribute.
2372 * @param[in] two the second attribute.
2373 * @return -1 if one is less than two, 0 if both are equal, 1 if one is more than two, < -1 on error.
2375 int8_t paircmp_value(VALUE_PAIR const *one, VALUE_PAIR const *two)
2377 int64_t compare = 0;
2382 if (one->da->type != two->da->type) {
2383 fr_strerror_printf("Can't compare attribute values of different types");
2388 * After doing the previous check for special comparisons,
2389 * do the per-type comparison here.
2391 switch (one->da->type) {
2392 case PW_TYPE_ABINARY:
2393 case PW_TYPE_OCTETS:
2397 if (one->length > two->length) {
2398 length = one->length;
2400 length = two->length;
2404 compare = memcmp(one->vp_octets, two->vp_octets, length);
2405 if (compare != 0) break;
2409 * Contents are the same. The return code
2410 * is therefore the difference in lengths.
2412 * i.e. "0x00" is smaller than "0x0000"
2414 compare = one->length - two->length;
2418 case PW_TYPE_STRING:
2419 fr_assert(one->vp_strvalue);
2420 fr_assert(two->vp_strvalue);
2421 compare = strcmp(one->vp_strvalue, two->vp_strvalue);
2426 case PW_TYPE_INTEGER:
2428 compare = (int64_t) one->vp_integer - (int64_t) two->vp_integer;
2431 case PW_TYPE_SIGNED:
2432 compare = one->vp_signed - two->vp_signed;
2435 case PW_TYPE_INTEGER64:
2437 * Don't want integer overflow!
2439 if (one->vp_integer64 < two->vp_integer64) {
2441 } else if (one->vp_integer64 > two->vp_integer64) {
2446 case PW_TYPE_ETHERNET:
2447 compare = memcmp(&one->vp_ether, &two->vp_ether, sizeof(one->vp_ether));
2450 case PW_TYPE_IPADDR:
2451 compare = (int64_t) ntohl(one->vp_ipaddr) - (int64_t) ntohl(two->vp_ipaddr);
2454 case PW_TYPE_IPV6ADDR:
2455 compare = memcmp(&one->vp_ipv6addr, &two->vp_ipv6addr, sizeof(one->vp_ipv6addr));
2458 case PW_TYPE_IPV6PREFIX:
2459 compare = memcmp(&one->vp_ipv6prefix, &two->vp_ipv6prefix, sizeof(one->vp_ipv6prefix));
2462 case PW_TYPE_IPV4PREFIX:
2463 compare = memcmp(&one->vp_ipv4prefix, &two->vp_ipv4prefix, sizeof(one->vp_ipv4prefix));
2467 compare = memcmp(&one->vp_ifid, &two->vp_ifid, sizeof(one->vp_ifid));
2471 * None of the types below should be in the REQUEST
2473 case PW_TYPE_COMBO_IP: /* This should of been converted into IPADDR/IPV6ADDR */
2475 case PW_TYPE_EXTENDED:
2476 case PW_TYPE_LONG_EXTENDED:
2479 case PW_TYPE_INVALID: /* We should never see these */
2481 fr_assert(0); /* unknown type */
2485 * Do NOT add a default here, as new types are added
2486 * static analysis will warn us they're not handled
2492 } else if (compare < 0) {
2499 * We leverage the fact that IPv4 and IPv6 prefixes both
2500 * have the same format:
2502 * reserved, prefix-len, data...
2504 static int paircmp_op_cidr(FR_TOKEN op, int bytes,
2505 uint8_t one_net, uint8_t const *one,
2506 uint8_t two_net, uint8_t const *two)
2512 * Handle the case of netmasks being identical.
2514 if (one_net == two_net) {
2517 compare = memcmp(one, two, bytes);
2520 * If they're identical return true for
2523 if ((compare == 0) &&
2524 ((op == T_OP_CMP_EQ) ||
2531 * Everything else returns false.
2533 * 10/8 == 24/8 --> false
2534 * 10/8 <= 24/8 --> false
2535 * 10/8 >= 24/8 --> false
2541 * Netmasks are different. That limits the
2542 * possible results, based on the operator.
2552 case T_OP_LT: /* 192/8 < 192.168/16 --> false */
2553 if (one_net < two_net) {
2559 case T_OP_GT: /* 192/16 > 192.168/8 --> false */
2560 if (one_net > two_net) {
2569 if (one_net < two_net) {
2576 * Do the check byte by byte. If the bytes are
2577 * identical, it MAY be a match. If they're different,
2578 * it is NOT a match.
2583 * All leading bytes are identical.
2585 if (common == 0) return true;
2588 * Doing bitmasks takes more work.
2590 if (common < 8) break;
2592 if (one[i] != two[i]) return false;
2600 mask <<= (8 - common);
2604 if ((one[i] & mask) == ((two[i] & mask))) {
2611 /** Compare two attributes using an operator
2613 * @param[in] a the first attribute
2614 * @param[in] op the operator for comparison.
2615 * @param[in] b the second attribute
2616 * @return 1 if true, 0 if false, -1 on error.
2618 int8_t paircmp_op(VALUE_PAIR const *a, FR_TOKEN op, VALUE_PAIR const *b)
2622 if (!a || !b) return -1;
2624 switch (a->da->type) {
2625 case PW_TYPE_IPADDR:
2626 switch (b->da->type) {
2627 case PW_TYPE_IPADDR: /* IPv4 and IPv4 */
2630 case PW_TYPE_IPV4PREFIX: /* IPv4 and IPv4 Prefix */
2631 return paircmp_op_cidr(op, 4, 32, (uint8_t const *) &a->vp_ipaddr,
2632 b->vp_ipv4prefix[1], (uint8_t const *) &b->vp_ipv4prefix + 2);
2635 fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
2640 case PW_TYPE_IPV4PREFIX: /* IPv4 and IPv4 Prefix */
2641 switch (b->da->type) {
2642 case PW_TYPE_IPADDR:
2643 return paircmp_op_cidr(op, 4, a->vp_ipv4prefix[1],
2644 (uint8_t const *) &a->vp_ipv4prefix + 2,
2645 32, (uint8_t const *) &b->vp_ipaddr);
2647 case PW_TYPE_IPV4PREFIX: /* IPv4 Prefix and IPv4 Prefix */
2648 return paircmp_op_cidr(op, 4, a->vp_ipv4prefix[1],
2649 (uint8_t const *) &a->vp_ipv4prefix + 2,
2650 b->vp_ipv4prefix[1], (uint8_t const *) &b->vp_ipv4prefix + 2);
2653 fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
2658 case PW_TYPE_IPV6ADDR:
2659 switch (b->da->type) {
2660 case PW_TYPE_IPV6ADDR: /* IPv6 and IPv6 */
2663 case PW_TYPE_IPV6PREFIX: /* IPv6 and IPv6 Preifx */
2664 return paircmp_op_cidr(op, 16, 128, (uint8_t const *) &a->vp_ipv6addr,
2665 b->vp_ipv6prefix[1], (uint8_t const *) &b->vp_ipv6prefix + 2);
2669 fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
2674 case PW_TYPE_IPV6PREFIX:
2675 switch (b->da->type) {
2676 case PW_TYPE_IPV6ADDR: /* IPv6 Prefix and IPv6 */
2677 return paircmp_op_cidr(op, 16, a->vp_ipv6prefix[1],
2678 (uint8_t const *) &a->vp_ipv6prefix + 2,
2679 128, (uint8_t const *) &b->vp_ipv6addr);
2681 case PW_TYPE_IPV6PREFIX: /* IPv6 Prefix and IPv6 */
2682 return paircmp_op_cidr(op, 16, a->vp_ipv6prefix[1],
2683 (uint8_t const *) &a->vp_ipv6prefix + 2,
2684 b->vp_ipv6prefix[1], (uint8_t const *) &b->vp_ipv6prefix + 2);
2687 fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
2694 compare = paircmp_value(a, b);
2695 if (compare < -1) { /* comparison error */
2701 * Now do the operator comparison.
2705 return (compare == 0);
2708 return (compare != 0);
2711 return (compare < 0);
2714 return (compare > 0);
2717 return (compare <= 0);
2720 return (compare >= 0);
2727 /** Compare two pairs, using the operator from "a"
2729 * i.e. given two attributes, it does:
2731 * (b->data) (a->operator) (a->data)
2733 * e.g. "foo" != "bar"
2735 * @param[in] a the first attribute
2736 * @param[in] b the second attribute
2737 * @return 1 if true, 0 if false, -1 on error.
2739 int8_t paircmp(VALUE_PAIR *a, VALUE_PAIR *b)
2744 if (b) VERIFY_VP(b);
2750 case T_OP_CMP_FALSE:
2754 * a is a regex, compile it, print b to a string,
2755 * and then do string comparisons.
2765 char buffer[MAX_STRING_LEN * 4 + 1];
2767 compare = regcomp(®, a->vp_strvalue, REG_EXTENDED);
2769 regerror(compare, ®, buffer, sizeof(buffer));
2770 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2771 a->da->name, buffer);
2780 vp_prints_value(buffer, sizeof(buffer), b, 0);
2783 * Don't care about substring matches,
2786 compare = regexec(®, buffer, 0, NULL, 0);
2789 if (a->op == T_OP_REG_EQ) {
2790 return (compare == 0);
2793 return (compare != 0);
2797 default: /* we're OK */
2801 return paircmp_op(b, a->op, a);
2804 /** Determine equality of two lists
2806 * This is useful for comparing lists of attributes inserted into a binary tree.
2808 * @param a first list of VALUE_PAIRs.
2809 * @param b second list of VALUE_PAIRs.
2810 * @return -1 if a < b, 0 if the two lists are equal, 1 if a > b, -2 on error.
2812 int8_t pairlistcmp(VALUE_PAIR *a, VALUE_PAIR *b)
2814 vp_cursor_t a_cursor, b_cursor;
2815 VALUE_PAIR *a_p, *b_p;
2818 for (a_p = fr_cursor_init(&a_cursor, &a), b_p = fr_cursor_init(&b_cursor, &b);
2820 a_p = fr_cursor_next(&a_cursor), b_p = fr_cursor_next(&b_cursor)) {
2821 /* Same VP, no point doing expensive checks */
2826 if (a_p->da < b_p->da) {
2829 if (a_p->da > b_p->da) {
2833 if (a_p->tag < b_p->tag) {
2836 if (a_p->tag > b_p->tag) {
2840 ret = paircmp_value(a_p, b_p);
2842 fr_assert(ret >= -1); /* Comparison error */
2859 /** Set the type of the VALUE_PAIR value buffer to match it's DICT_ATTR
2861 * @param vp to fixup.
2863 static void pairtypeset(VALUE_PAIR *vp)
2865 if (!vp->data.ptr) return;
2867 switch(vp->da->type) {
2868 case PW_TYPE_OCTETS:
2870 talloc_set_type(vp->data.ptr, uint8_t);
2873 case PW_TYPE_STRING:
2874 talloc_set_type(vp->data.ptr, char);
2882 /** Copy data into an "octets" data type.
2884 * @param[in,out] vp to update
2885 * @param[in] src data to copy
2886 * @param[in] size of the data, may be 0 in which case previous value will be freed.
2888 void pairmemcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2890 uint8_t *p = NULL, *q;
2895 p = talloc_memdup(vp, src, size);
2897 talloc_set_type(p, uint8_t);
2900 memcpy(&q, &vp->vp_octets, sizeof(q));
2906 if (size > 0) pairtypeset(vp);
2909 /** Reparent an allocated octet buffer to a VALUE_PAIR
2911 * @param[in,out] vp to update
2912 * @param[in] src buffer to steal.
2914 void pairmemsteal(VALUE_PAIR *vp, uint8_t const *src)
2920 memcpy(&q, &vp->vp_octets, sizeof(q));
2923 vp->vp_octets = talloc_steal(vp, src);
2925 vp->length = talloc_array_length(vp->vp_strvalue);
2929 /** Reparent an allocated char buffer to a VALUE_PAIR
2931 * @param[in,out] vp to update
2932 * @param[in] src buffer to steal.
2934 void pairstrsteal(VALUE_PAIR *vp, char const *src)
2940 memcpy(&q, &vp->vp_octets, sizeof(q));
2943 vp->vp_strvalue = talloc_steal(vp, src);
2945 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2949 /** Copy data into an "string" data type.
2951 * @param[in,out] vp to update
2952 * @param[in] src data to copy
2954 void pairstrcpy(VALUE_PAIR *vp, char const *src)
2960 p = talloc_strdup(vp, src);
2964 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2967 vp->vp_strvalue = p;
2969 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2973 /** Copy data into an "string" data type.
2975 * @param[in,out] vp to update.
2976 * @param[in] src data to copy.
2977 * @param[in] len of data to copy.
2979 void pairstrncpy(VALUE_PAIR *vp, char const *src, size_t len)
2985 p = talloc_array(vp, char, len + 1);
2986 memcpy(p, src, len); /* embdedded \0 safe */
2991 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2994 vp->vp_strvalue = p;
3000 /** Print data into an "string" data type.
3002 * @param[in,out] vp to update
3003 * @param[in] fmt the format string
3005 void pairsprintf(VALUE_PAIR *vp, char const *fmt, ...)
3013 p = talloc_vasprintf(vp, fmt, ap);
3018 memcpy(&q, &vp->vp_strvalue, sizeof(q));
3021 vp->vp_strvalue = p;
3024 vp->length = talloc_array_length(vp->vp_strvalue) - 1;