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)
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");
116 vp->length = da->flags.length;
118 talloc_set_destructor(vp, _pairfree);
123 /** Create a new valuepair
125 * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
128 * If attr or vendor are uknown will call dict_attruknown to create a dynamic
129 * DICT_ATTR of PW_TYPE_OCTETS.
131 * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
132 * checking @verbatim vp->da->flags.is_unknown @endverbatim.
134 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
135 * @param[in] attr number.
136 * @param[in] vendor number.
137 * @return the new valuepair or NULL on error.
139 VALUE_PAIR *paircreate(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
143 da = dict_attrbyvalue(attr, vendor);
145 da = dict_attrunknown(attr, vendor, true);
151 return pairalloc(ctx, da);
154 /** Free memory used by a valuepair list.
156 * @todo TLV: needs to free all dependents of each VP freed.
158 void pairfree(VALUE_PAIR **vps)
167 for (vp = fr_cursor_init(&cursor, vps);
169 vp = fr_cursor_next(&cursor)) {
177 /** Mark malformed or unrecognised attributed as unknown
179 * @param vp to change DICT_ATTR of.
180 * @return 0 on success (or if already unknown) else -1 on error.
182 int pair2unknown(VALUE_PAIR *vp)
187 if (vp->da->flags.is_unknown) {
191 da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
201 /** Find the pair with the matching DAs
204 VALUE_PAIR *pairfind_da(VALUE_PAIR *vp, DICT_ATTR const *da, int8_t tag)
213 for (i = fr_cursor_init(&cursor, &vp);
215 i = fr_cursor_next(&cursor)) {
217 if ((i->da == da) && (!i->da->flags.has_tag || TAG_EQ(tag, i->tag))) {
226 /** Find the pair with the matching attribute
228 * @todo should take DAs and do a pointer comparison.
230 VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag)
235 /* List head may be NULL if it contains no VPs */
236 if (!vp) return NULL;
240 for (i = fr_cursor_init(&cursor, &vp);
242 i = fr_cursor_next(&cursor)) {
243 if ((i->da->attr == attr) && (i->da->vendor == vendor) && \
244 (!i->da->flags.has_tag || TAG_EQ(tag, i->tag))) {
252 /** Delete matching pairs
254 * Delete matching pairs from the attribute list.
256 * @param[in,out] first VP in list.
257 * @param[in] attr to match.
258 * @param[in] vendor to match.
259 * @param[in] tag to match. TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
261 * @todo should take DAs and do a point comparison.
263 void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor,
266 VALUE_PAIR *i, *next;
267 VALUE_PAIR **last = first;
269 for(i = *first; i; i = next) {
272 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
273 (!i->da->flags.has_tag || TAG_EQ(tag, i->tag))) {
282 /** Add a VP to the end of the list.
284 * Locates the end of 'first', and links an additional VP 'add' at the end.
286 * @param[in] first VP in linked list. Will add new VP to the end of this list.
287 * @param[in] add VP to add to list.
289 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
297 if (*first == NULL) {
301 for(i = *first; i->next; i = i->next)
306 /** Replace all matching VPs
308 * Walks over 'first', and replaces the first VP that matches 'replace'.
310 * @note Memory used by the VP being replaced will be freed.
311 * @note Will not work with unknown attributes.
313 * @param[in,out] first VP in linked list. Will search and replace in this list.
314 * @param[in] replace VP to replace.
316 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
318 VALUE_PAIR *i, *next;
319 VALUE_PAIR **prev = first;
323 if (*first == NULL) {
329 * Not an empty list, so find item if it is there, and
330 * replace it. Note, we always replace the first one, and
331 * we ignore any others that might exist.
333 for(i = *first; i; i = next) {
338 * Found the first attribute, replace it,
341 if ((i->da == replace->da) && (!i->da->flags.has_tag || TAG_EQ(replace->tag, i->tag))) {
345 * Should really assert that replace->next == NULL
347 replace->next = next;
353 * Point to where the attribute should go.
359 * If we got here, we didn't find anything to replace, so
360 * stopped at the last item, which we just append to.
365 int8_t attrtagcmp(void const *a, void const *b)
367 VALUE_PAIR const *my_a = a;
368 VALUE_PAIR const *my_b = b;
375 cmp = fr_pointer_cmp(my_a->da, my_b->da);
376 if (cmp != 0) return cmp;
378 if (my_a->tag < my_b->tag) return -1;
380 if (my_a->tag > my_b->tag) return 1;
385 static void pairsort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
391 * Stopping condition - no more elements left to split
393 if (!source || !source->next) {
401 * Fast advances twice as fast as slow, so when it gets to the end,
402 * slow will point to the middle of the linked list.
420 static VALUE_PAIR *pairsort_merge(VALUE_PAIR *a, VALUE_PAIR *b, fr_cmp_t cmp)
422 VALUE_PAIR *result = NULL;
428 * Compare the DICT_ATTRs and tags
430 if (cmp(a, b) <= 0) {
432 result->next = pairsort_merge(a->next, b, cmp);
435 result->next = pairsort_merge(a, b->next, cmp);
441 /** Sort a linked list of VALUE_PAIRs using merge sort
443 * @param[in,out] vps List of VALUE_PAIRs to sort.
444 * @param[in] cmp to sort with
446 void pairsort(VALUE_PAIR **vps, fr_cmp_t cmp)
448 VALUE_PAIR *head = *vps;
453 * If there's 0-1 elements it must already be sorted.
455 if (!head || !head->next) {
459 pairsort_split(head, &a, &b); /* Split into sublists */
460 pairsort(&a, cmp); /* Traverse left */
461 pairsort(&b, cmp); /* Traverse right */
464 * merge the two sorted lists together
466 *vps = pairsort_merge(a, b, cmp);
469 /** Write an error to the library errorbuff detailing the mismatch
471 * Retrieve output with fr_strerror();
473 * @todo add thread specific talloc contexts.
475 * @param ctx a hack until we have thread specific talloc contexts.
476 * @param failed pair of attributes which didn't match.
478 void pairvalidate_debug(TALLOC_CTX *ctx, VALUE_PAIR const *failed[2])
480 VALUE_PAIR const *filter = failed[0];
481 VALUE_PAIR const *list = failed[1];
485 (void) fr_strerror(); /* Clear any existing messages */
487 if (!fr_assert(!(!filter && !list))) return;
491 fr_strerror_printf("Attribute \"%s\" not found in list", filter->da->name);
495 if (!filter || (filter->da != list->da)) {
496 fr_strerror_printf("Attribute \"%s\" not found in filter", list->da->name);
500 if (!TAG_EQ(filter->tag, list->tag)) {
501 fr_strerror_printf("Attribute \"%s\" tag \"%i\" didn't match filter tag \"%i\"",
502 list->da->name, list->tag, filter->tag);
506 pair = vp_aprint(ctx, filter);
507 value = vp_aprint_value(ctx, list);
509 fr_strerror_printf("Attribute value \"%s\" didn't match filter \"%s\"", value, pair);
517 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
519 * @note will sort both filter and list in place.
521 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
523 * @param filter attributes to check list against.
524 * @param list attributes, probably a request or reply
526 bool pairvalidate(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
528 vp_cursor_t filter_cursor;
529 vp_cursor_t list_cursor;
531 VALUE_PAIR *check, *match;
533 if (!filter && !list) {
538 * This allows us to verify the sets of validate and reply are equal
539 * i.e. we have a validate rule which matches every reply attribute.
541 * @todo this should be removed one we have sets and lists
543 pairsort(&filter, attrtagcmp);
544 pairsort(&list, attrtagcmp);
546 check = fr_cursor_init(&filter_cursor, &filter);
547 match = fr_cursor_init(&list_cursor, &list);
548 while (match || check) {
550 * Lists are of different lengths
552 if ((!match && check) || (check && !match)) goto mismatch;
555 * The lists are sorted, so if the first
556 * attributes aren't of the same type, then we're
559 if (!ATTRIBUTE_EQ(check, match)) goto mismatch;
562 * They're of the same type, but don't have the
563 * same values. This is a problem.
565 * Note that the RFCs say that for attributes of
566 * the same type, order is important.
568 if (paircmp(check, match) != 1) goto mismatch;
570 check = fr_cursor_next(&filter_cursor);
571 match = fr_cursor_next(&list_cursor);
584 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
586 * @note will sort both filter and list in place.
588 * @param failed pointer to an array to write the pointers of the filter/list attributes that didn't match.
590 * @param filter attributes to check list against.
591 * @param list attributes, probably a request or reply
593 bool pairvalidate_relaxed(VALUE_PAIR const *failed[2], VALUE_PAIR *filter, VALUE_PAIR *list)
595 vp_cursor_t filter_cursor;
596 vp_cursor_t list_cursor;
598 VALUE_PAIR *check, *last_check = NULL, *match = NULL;
600 if (!filter && !list) {
605 * This allows us to verify the sets of validate and reply are equal
606 * i.e. we have a validate rule which matches every reply attribute.
608 * @todo this should be removed one we have sets and lists
610 pairsort(&filter, attrtagcmp);
611 pairsort(&list, attrtagcmp);
613 fr_cursor_init(&list_cursor, &list);
614 for (check = fr_cursor_init(&filter_cursor, &filter);
616 check = fr_cursor_next(&filter_cursor)) {
618 * Were processing check attributes of a new type.
620 if (!ATTRIBUTE_EQ(last_check, check)) {
622 * Record the start of the matching attributes in the pair list
623 * For every other operator we require the match to be present
625 match = fr_cursor_next_by_da(&list_cursor, check->da, check->tag);
627 if (check->op == T_OP_CMP_FALSE) continue;
631 fr_cursor_init(&list_cursor, &match);
636 * Now iterate over all attributes of the same type.
638 for (match = fr_cursor_first(&list_cursor);
639 ATTRIBUTE_EQ(match, check);
640 match = fr_cursor_next(&list_cursor)) {
642 * This attribute passed the filter
644 if (!paircmp(check, match)) goto mismatch;
658 /** Copy a single valuepair
660 * Allocate a new valuepair and copy the da from the old vp.
662 * @param[in] ctx for talloc
663 * @param[in] vp to copy.
664 * @return a copy of the input VP or NULL on error.
666 VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
670 if (!vp) return NULL;
674 n = pairalloc(ctx, vp->da);
677 memcpy(n, vp, sizeof(*n));
682 if (vp->type == VT_XLAT) {
683 n->value.xlat = talloc_typed_strdup(n, n->value.xlat);
686 n->da = dict_attr_copy(vp->da, true);
694 switch (vp->da->type) {
697 n->vp_octets = NULL; /* else pairmemcpy will free vp's value */
698 pairmemcpy(n, vp->vp_octets, n->length);
702 n->vp_strvalue = NULL; /* else pairstrnpy will free vp's value */
703 pairstrncpy(n, vp->vp_strvalue, n->length);
715 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
717 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
718 * @param[in] from whence to copy VALUE_PAIRs.
719 * @return the head of the new VALUE_PAIR list or NULL on error.
721 VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from)
723 vp_cursor_t src, dst;
725 VALUE_PAIR *out = NULL, *vp;
727 fr_cursor_init(&dst, &out);
728 for (vp = fr_cursor_init(&src, &from);
730 vp = fr_cursor_next(&src)) {
732 vp = paircopyvp(ctx, vp);
737 fr_cursor_insert(&dst, vp); /* paircopy sets next pointer to NULL */
743 /** Copy matching pairs
745 * Copy pairs of a matching attribute number, vendor number and tag from the
746 * the input list to a new list, and returns the head of this list.
748 * @param[in] ctx for talloc
749 * @param[in] from whence to copy VALUE_PAIRs.
750 * @param[in] attr to match, if 0 input list will not be filtered by attr.
751 * @param[in] vendor to match.
752 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
753 * @return the head of the new VALUE_PAIR list or NULL on error.
755 VALUE_PAIR *paircopy2(TALLOC_CTX *ctx, VALUE_PAIR *from,
756 unsigned int attr, unsigned int vendor, int8_t tag)
758 vp_cursor_t src, dst;
760 VALUE_PAIR *out = NULL, *vp;
762 fr_cursor_init(&dst, &out);
763 for (vp = fr_cursor_init(&src, &from);
765 vp = fr_cursor_next(&src)) {
768 if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
772 if (vp->da->flags.has_tag && TAG_EQ(tag, vp->tag)) {
776 vp = paircopyvp(ctx, vp);
781 fr_cursor_insert(&dst, vp);
787 /** Steal all members of a VALUE_PAIR list
789 * @param[in] ctx to move VALUE_PAIRs into
790 * @param[in] from VALUE_PAIRs to move into the new context.
792 VALUE_PAIR *pairsteal(TALLOC_CTX *ctx, VALUE_PAIR *from)
797 for (vp = fr_cursor_init(&cursor, &from);
799 vp = fr_cursor_next(&cursor)) {
800 (void) talloc_steal(ctx, vp);
806 /** Move pairs from source list to destination list respecting operator
808 * @note This function does some additional magic that's probably not needed
809 * in most places. Consider using radius_pairmove in server code.
811 * @note pairfree should be called on the head of the source list to free
812 * unmoved attributes (if they're no longer needed).
814 * @note Does not respect tags when matching.
816 * @param[in] ctx for talloc
817 * @param[in,out] to destination list.
818 * @param[in,out] from source list.
820 * @see radius_pairmove
822 void pairmove(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
824 VALUE_PAIR *i, *found;
825 VALUE_PAIR *head_new, **tail_new;
826 VALUE_PAIR **tail_from;
828 if (!to || !from || !*from) return;
831 * We're editing the "to" list while we're adding new
832 * attributes to it. We don't want the new attributes to
833 * be edited, so we create an intermediate list to hold
834 * them during the editing process.
837 tail_new = &head_new;
840 * We're looping over the "from" list, moving some
841 * attributes out, but leaving others in place.
844 while ((i = *tail_from) != NULL) {
848 * We never move Fall-Through.
850 if (!i->da->vendor && i->da->attr == PW_FALL_THROUGH) {
851 tail_from = &(i->next);
856 * Unlike previous versions, we treat all other
857 * attributes as normal. i.e. there's no special
858 * treatment for passwords or Hint.
863 * Anything else are operators which
864 * shouldn't occur. We ignore them, and
865 * leave them in place.
868 tail_from = &(i->next);
872 * Add it to the "to" list, but only if
873 * it doesn't already exist.
876 found = pairfind(*to, i->da->attr, i->da->vendor, TAG_ANY);
877 if (!found) goto do_add;
879 tail_from = &(i->next);
883 * Add it to the "to" list, and delete any attribute
884 * of the same vendor/attr which already exists.
887 found = pairfind(*to, i->da->attr, i->da->vendor, TAG_ANY);
888 if (!found) goto do_add;
891 * Do NOT call pairdelete() here,
892 * due to issues with re-writing
893 * "request->username".
895 * Everybody calls pairmove, and
896 * expects it to work. We can't
897 * update request->username here,
898 * so instead we over-write the
899 * vp that it's pointing to.
901 switch (found->da->type) {
906 memcpy(found, i, sizeof(*found));
911 pairmemsteal(found, i->vp_tlv);
916 pairmemsteal(found, i->vp_octets);
921 pairstrsteal(found, i->vp_strvalue);
922 i->vp_strvalue = NULL;
928 * Delete *all* of the attributes
929 * of the same number.
931 pairdelete(&found->next,
933 found->da->vendor, TAG_ANY);
936 * Remove this attribute from the
939 *tail_from = i->next;
945 * Move it from the old list and add it
950 *tail_from = i->next;
952 *tail_new = talloc_steal(ctx, i);
953 tail_new = &(i->next);
956 } /* loop over the "from" list. */
959 * Take the "new" list, and append it to the "to" list.
961 pairadd(to, head_new);
964 /** Move matching pairs between VALUE_PAIR lists
966 * Move pairs of a matching attribute number, vendor number and tag from the
967 * the input list to the output list.
969 * @note pairs which are moved have their parent changed to ctx.
971 * @note pairfree should be called on the head of the old list to free unmoved
972 attributes (if they're no longer needed).
974 * @param[in] ctx for talloc
975 * @param[in,out] to destination list.
976 * @param[in,out] from source list.
977 * @param[in] attr to match. If attribute PW_VENDOR_SPECIFIC and vendor 0,
978 * will match (and therefore copy) only VSAs.
979 * If attribute 0 and vendor 0 will match (and therefore copy) all
981 * @param[in] vendor to match.
982 * @param[in] tag to match, TAG_ANY matches any tag, TAG_NONE matches tagless VPs.
984 void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor, int8_t tag)
986 VALUE_PAIR *to_tail, *i, *next;
987 VALUE_PAIR *iprev = NULL;
990 * Find the last pair in the "to" list and put it in "to_tail".
992 * @todo: replace the "if" with "VALUE_PAIR **tail"
996 for(i = *to; i; i = i->next) {
1004 * Attr/vendor of 0 means "move them all".
1005 * It's better than "pairadd(foo,bar);bar=NULL"
1007 if ((vendor == 0) && (attr == 0)) {
1009 to_tail->next = *from;
1014 for (i = *from; i; i = i->next) {
1015 (void) talloc_steal(ctx, i);
1022 for(i = *from; i; i = next) {
1026 if (i->da->flags.has_tag && TAG_EQ(tag, i->tag)) {
1031 * vendor=0, attr = PW_VENDOR_SPECIFIC means
1032 * "match any vendor attribute".
1034 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1036 * It's a VSA: move it over.
1038 if (i->da->vendor != 0) goto move;
1041 * It's Vendor-Specific: move it over.
1043 if (i->da->attr == attr) goto move;
1046 * It's not a VSA: ignore it.
1053 * If it isn't an exact match, ignore it.
1055 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1062 * Remove the attribute from the "from" list.
1070 * Add the attribute to the "to" list.
1078 (void) talloc_steal(ctx, i);
1082 static char const hextab[] = "0123456789abcdef";
1084 /** Convert string value to native attribute value
1086 * @param vp to assign value to.
1087 * @param value string to convert. Binary safe for variable length values if len is provided.
1088 * @param inlen may be 0 in which case strlen(len) is used to determine length, else inline
1089 * should be the length of the string or sub string to parse.
1090 * @return true on success, else false.
1092 int pairparsevalue(VALUE_PAIR *vp, char const *value, size_t inlen)
1098 if (!value) return -1;
1102 * It's a comparison, not a real VALUE_PAIR, copy the string over verbatim
1104 if ((vp->op == T_OP_REG_EQ) || (vp->op == T_OP_REG_NE)) {
1105 pairstrcpy(vp, value); /* Icky hacky ewww */
1109 len = (inlen == 0) ? strlen(value) : inlen;
1112 * It's a variable length type so we just alloc a new buffer
1113 * of size len and copy.
1115 switch(vp->da->type) {
1116 case PW_TYPE_STRING:
1126 vp->vp_strvalue = p = talloc_memdup(vp, value, len + 1);
1128 talloc_set_type(p, char);
1135 if (c == '\\') switch (*cp) {
1165 c = '\\'; /* no cp++ */
1168 if ((cp[0] >= '0') &&
1174 (sscanf(cp, "%3o", &x) == 1)) {
1183 } /* else at EOL \ --> \ */
1189 vp->length = vp_len;
1193 /* raw octets: 0x01020304... */
1195 if (strcmp(value, "ANY") == 0) {
1198 } /* else it's hex */
1200 case PW_TYPE_OCTETS:
1205 * No 0x prefix, just copy verbatim.
1207 if ((len < 2) || (strncasecmp(value, "0x", 2) != 0)) {
1208 pairmemcpy(vp, (uint8_t const *) value, len);
1213 #ifdef WITH_ASCEND_BINARY
1221 if ((len & 0x01) != 0) {
1222 fr_strerror_printf("Length of Hex String is not even, got %zu bytes", vp->length);
1226 vp->length = len >> 1;
1227 p = talloc_array(vp, uint8_t, vp->length);
1228 if (fr_hex2bin(p, vp->length, value + 2, len) != vp->length) {
1230 fr_strerror_printf("Invalid hex data");
1238 case PW_TYPE_ABINARY:
1239 #ifdef WITH_ASCEND_BINARY
1240 if ((len > 1) && (strncasecmp(value, "0x", 2) == 0)) goto do_octets;
1242 if (ascend_parse_filter(vp, value, len) < 0 ) {
1243 /* Allow ascend_parse_filter's strerror to bubble up */
1249 * If Ascend binary is NOT defined,
1250 * then fall through to raw octets, so that
1251 * the user can at least make them by hand...
1256 /* don't use this! */
1261 if ((len < 2) || (len & 0x01) || (strncasecmp(value, "0x", 2) != 0)) {
1262 fr_strerror_printf("Invalid TLV specification");
1267 vp->length = len >> 1;
1268 p = talloc_array(vp, uint8_t, vp->length);
1270 fr_strerror_printf("No memory");
1273 if (fr_hex2bin(p, vp->length, value + 2, len) != vp->length) {
1274 fr_strerror_printf("Invalid hex data in TLV");
1282 case PW_TYPE_IPV4_ADDR:
1286 if (fr_pton4(&addr, value, inlen, fr_hostname_lookups, false) < 0) return -1;
1289 * We allow v4 addresses to have a /32 suffix as some databases (PostgreSQL)
1290 * print them this way.
1292 if (addr.prefix != 32) {
1293 fr_strerror_printf("Invalid IPv4 mask length \"/%i\". Only \"/32\" permitted "
1294 "for non-prefix types", addr.prefix);
1298 vp->vp_ipaddr = addr.ipaddr.ip4addr.s_addr;
1299 vp->length = sizeof(vp->vp_ipaddr);
1303 case PW_TYPE_IPV4_PREFIX:
1307 if (fr_pton4(&addr, value, inlen, fr_hostname_lookups, false) < 0) return -1;
1309 vp->vp_ipv4prefix[1] = addr.prefix;
1310 memcpy(vp->vp_ipv4prefix + 2, &addr.ipaddr.ip4addr.s_addr, sizeof(vp->vp_ipv4prefix) - 2);
1311 vp->length = sizeof(vp->vp_ipv4prefix);
1315 case PW_TYPE_IPV6_ADDR:
1319 if (fr_pton6(&addr, value, inlen, fr_hostname_lookups, false) < 0) return -1;
1322 * We allow v6 addresses to have a /128 suffix as some databases (PostgreSQL)
1323 * print them this way.
1325 if (addr.prefix != 128) {
1326 fr_strerror_printf("Invalid IPv6 mask length \"/%i\". Only \"/128\" permitted "
1327 "for non-prefix types", addr.prefix);
1331 memcpy(&vp->vp_ipv6addr, &addr.ipaddr.ip6addr.s6_addr, sizeof(vp->vp_ipv6addr));
1332 vp->length = sizeof(vp->vp_ipv6addr);
1336 case PW_TYPE_IPV6_PREFIX:
1340 if (fr_pton6(&addr, value, inlen, fr_hostname_lookups, false) < 0) return -1;
1342 vp->vp_ipv6prefix[1] = addr.prefix;
1343 memcpy(vp->vp_ipv6prefix + 2, &addr.ipaddr.ip6addr.s6_addr, sizeof(vp->vp_ipv6prefix) - 2);
1344 vp->length = sizeof(vp->vp_ipv6prefix);
1353 * It's a fixed size type, copy to a temporary buffer and
1354 * \0 terminate if insize >= 0.
1357 if (len >= sizeof(buffer)) {
1358 fr_strerror_printf("Temporary buffer too small");
1362 memcpy(buffer, value, inlen);
1363 buffer[inlen] = '\0';
1367 switch(vp->da->type) {
1374 * Note that ALL integers are unsigned!
1376 vp->vp_integer = fr_strtoul(value, &p);
1378 if (vp->vp_integer > 255) {
1379 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
1384 if (is_whitespace(p)) break;
1386 goto check_for_value;
1393 * Note that ALL integers are unsigned!
1395 vp->vp_integer = fr_strtoul(value, &p);
1398 if (vp->vp_integer > 65535) {
1399 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1404 if (is_whitespace(p)) break;
1406 goto check_for_value;
1408 case PW_TYPE_INTEGER:
1413 * Note that ALL integers are unsigned!
1415 vp->vp_integer = fr_strtoul(value, &p);
1418 if (is_whitespace(p)) break;
1422 * Look for the named value for the given
1425 if ((dval = dict_valbyname(vp->da->attr, vp->da->vendor, value)) == NULL) {
1426 fr_strerror_printf("Unknown value '%s' for attribute '%s'", value, vp->da->name);
1429 vp->vp_integer = dval->value;
1433 case PW_TYPE_INTEGER64:
1438 * Note that ALL integers are unsigned!
1440 if (sscanf(value, "%" PRIu64, &y) != 1) {
1441 fr_strerror_printf("Invalid value '%s' for attribute '%s'",
1442 value, vp->da->name);
1445 vp->vp_integer64 = y;
1453 * time_t may be 64 bits, whule vp_date
1454 * MUST be 32-bits. We need an
1455 * intermediary variable to handle
1460 if (fr_get_time(value, &date) < 0) {
1461 fr_strerror_printf("failed to parse time string "
1473 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1474 fr_strerror_printf("Failed to parse interface-id string \"%s\"", value);
1480 case PW_TYPE_ETHERNET:
1482 char const *c1, *c2, *cp;
1486 * Convert things which are obviously integers to Ethernet addresses
1488 * We assume the number is the bigendian representation of the
1491 if (is_integer(value)) {
1492 uint64_t integer = htonll(atoll(value));
1494 memcpy(&vp->vp_ether, &integer, sizeof(vp->vp_ether));
1502 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1504 } else if ((cp[1] != '\0') && ((cp[2] == ':') || (cp[2] == '\0'))) {
1505 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1506 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1508 if (*cp == ':') cp++;
1512 if (!c1 || !c2 || (vp_len >= sizeof(vp->vp_ether))) {
1513 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1516 vp->vp_ether[vp_len] = ((c1-hextab)<<4) + (c2-hextab);
1525 * Crazy polymorphic (IPv4/IPv6) attribute type for WiMAX.
1527 * We try and make is saner by replacing the original
1528 * da, with either an IPv4 or IPv6 da type.
1530 * These are not dynamic da, and will have the same vendor
1531 * and attribute as the original.
1533 case PW_TYPE_IP_ADDR:
1535 DICT_ATTR const *da;
1537 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) > 0) {
1538 da = dict_attrbytype(vp->da->attr, vp->da->vendor, PW_TYPE_IPV6_ADDR);
1540 fr_strerror_printf("Cannot find ipv6addr for %s", vp->da->name);
1544 vp->length = 16; /* length of IPv6 address */
1548 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1551 fr_strerror_printf("Cannot find ipaddr for %s", vp->da->name);
1555 if (ip_hton(&ipaddr, AF_INET, value, false) < 0) {
1556 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1560 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1568 case PW_TYPE_SIGNED:
1569 /* Damned code for 1 WiMAX attribute */
1570 vp->vp_signed = (int32_t) strtol(value, NULL, 10);
1578 fr_strerror_printf("unknown attribute type %d", vp->da->type);
1587 /** Use simple heuristics to create an VALUE_PAIR from an unknown address string
1589 * If a DICT_ATTR is not provided for the address type, parsing will fail with
1592 * @param ctx to allocate VP in.
1593 * @param value IPv4/IPv6 address/prefix string.
1594 * @param ipv4 dictionary attribute to use for an IPv4 address.
1595 * @param ipv6 dictionary attribute to use for an IPv6 address.
1596 * @param ipv4_prefix dictionary attribute to use for an IPv4 prefix.
1597 * @param ipv6_prefix dictionary attribute to use for an IPv6 prefix.
1598 * @return NULL on error, or new VALUE_PAIR.
1600 VALUE_PAIR *pairmake_ip(TALLOC_CTX *ctx, char const *value, DICT_ATTR *ipv4, DICT_ATTR *ipv6,
1601 DICT_ATTR *ipv4_prefix, DICT_ATTR *ipv6_prefix)
1604 DICT_ATTR *da = NULL;
1606 if (!fr_assert(ipv4 || ipv6 || ipv4_prefix || ipv6_prefix)) {
1610 /* No point in repeating the work of pairparsevalue */
1611 if (strchr(value, ':')) {
1612 if (strchr(value, '/')) {
1621 if (strchr(value, '/')) {
1631 fr_strerror_printf("Invalid IP value specified, allowed types are %s%s%s%s",
1632 ipv4 ? "ipaddr " : "", ipv6 ? "ipv6addr " : "",
1633 ipv4_prefix ? "ipv4prefix " : "", ipv6_prefix ? "ipv6prefix" : "");
1636 vp = pairalloc(ctx, da);
1637 if (!vp) return NULL;
1638 if (pairparsevalue(vp, value, 0) < 0) {
1647 /** Create a valuepair from an ASCII attribute and value
1649 * Where the attribute name is in the form:
1651 * - Attr-%d.%d.%d...
1652 * - Vendor-%d-Attr-%d
1653 * - VendorName-Attr-%d
1655 * @param ctx for talloc
1656 * @param attribute name to parse.
1657 * @param value to parse (must be a hex string).
1658 * @param op to assign to new valuepair.
1659 * @return new valuepair or NULL on error.
1661 static VALUE_PAIR *pairmake_any(TALLOC_CTX *ctx,
1662 char const *attribute, char const *value,
1666 DICT_ATTR const *da;
1671 da = dict_attrunknownbyname(attribute, true);
1672 if (!da) return NULL;
1675 * Unknown attributes MUST be of type 'octets'
1677 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1678 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1679 "string, not \"%s\"", attribute, value);
1681 dict_attr_free(&da);
1686 * We've now parsed the attribute properly, Let's create
1687 * it. This next stop also looks the attribute up in the
1688 * dictionary, and creates the appropriate type for it.
1690 vp = pairalloc(ctx, da);
1692 dict_attr_free(&da);
1696 vp->op = (op == 0) ? T_OP_EQ : op;
1698 if (!value) return vp;
1700 size = strlen(value + 2);
1701 vp->length = size >> 1;
1702 data = talloc_array(vp, uint8_t, vp->length);
1704 if (fr_hex2bin(data, vp->length, value + 2, size) != vp->length) {
1705 fr_strerror_printf("Invalid hex string");
1710 vp->vp_octets = data;
1716 /** Create a VALUE_PAIR from ASCII strings
1718 * Converts an attribute string identifier (with an optional tag qualifier)
1719 * and value string into a VALUE_PAIR.
1721 * The string value is parsed according to the type of VALUE_PAIR being created.
1723 * @param[in] ctx for talloc
1724 * @param[in] vps list where the attribute will be added (optional)
1725 * @param[in] attribute name.
1726 * @param[in] value attribute value (may be NULL if value will be set later).
1727 * @param[in] op to assign to new VALUE_PAIR.
1728 * @return a new VALUE_PAIR.
1730 VALUE_PAIR *pairmake(TALLOC_CTX *ctx, VALUE_PAIR **vps,
1731 char const *attribute, char const *value, FR_TOKEN op)
1733 DICT_ATTR const *da;
1739 char const *attrname = attribute;
1742 * Check for tags in 'Attribute:Tag' format.
1747 ts = strrchr(attribute, ':');
1749 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1754 strlcpy(buffer, attribute, sizeof(buffer));
1756 ts = strrchr(attrname, ':');
1757 if (!ts) return NULL;
1759 /* Colon found with something behind it */
1760 if (ts[1] == '*' && ts[2] == 0) {
1761 /* Wildcard tag for check items */
1764 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1765 /* It's not a wild card tag */
1766 tag = strtol(ts + 1, &tc, 0);
1767 if (tc && !*tc && TAG_VALID_ZERO(tag))
1771 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1778 * It's not found in the dictionary, so we use
1779 * another method to create the attribute.
1781 da = dict_attrbyname(attrname);
1783 vp = pairmake_any(ctx, attrname, value, op);
1784 if (vp && vps) pairadd(vps, vp);
1788 /* Check for a tag in the 'Merit' format of:
1789 * :Tag:Value. Print an error if we already found
1790 * a tag in the Attribute.
1793 if (value && (*value == ':' && da->flags.has_tag)) {
1794 /* If we already found a tag, this is invalid */
1796 fr_strerror_printf("Duplicate tag %s for attribute %s",
1798 DEBUG("Duplicate tag %s for attribute %s\n",
1802 /* Colon found and attribute allows a tag */
1803 if (value[1] == '*' && value[2] == ':') {
1804 /* Wildcard tag for check items */
1809 tag = strtol(value + 1, &tc, 0);
1810 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1816 vp = pairalloc(ctx, da);
1817 if (!vp) return NULL;
1818 vp->op = (op == 0) ? T_OP_EQ : op;
1823 case T_OP_CMP_FALSE:
1824 vp->vp_strvalue = NULL;
1826 value = NULL; /* ignore it! */
1830 * Regular expression comparison of integer attributes
1831 * does a STRING comparison of the names of their
1832 * integer attributes.
1834 case T_OP_REG_EQ: /* =~ */
1835 case T_OP_REG_NE: /* !~ */
1841 fr_strerror_printf("Regular expressions are not supported");
1847 * Someone else will fill in the value.
1853 compare = regcomp(®, value, REG_EXTENDED);
1855 regerror(compare, ®, buffer, sizeof(buffer));
1856 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1862 vp = pairmake(ctx, NULL, attribute, NULL, op);
1863 if (!vp) return NULL;
1865 if (pairmark_xlat(vp, value) < 0) {
1870 value = NULL; /* ignore it */
1879 * FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
1880 * then the user MAY have typed in the attribute name
1881 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1883 * We probably want to fix pairparsevalue to accept
1884 * octets as values for any attribute.
1886 if (value && (pairparsevalue(vp, value, 0) < 0)) {
1891 if (vps) pairadd(vps, vp);
1895 /** Mark a valuepair for xlat expansion
1897 * Copies xlat source (unprocessed) string to valuepair value,
1898 * and sets value type.
1900 * @param vp to mark for expansion.
1901 * @param value to expand.
1902 * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
1904 int pairmark_xlat(VALUE_PAIR *vp, char const *value)
1909 * valuepair should not already have a value.
1911 if (vp->type != VT_NONE) {
1915 raw = talloc_typed_strdup(vp, value);
1921 vp->value.xlat = raw;
1927 /** Read a single valuepair from a buffer, and advance the pointer
1929 * Sets *eol to T_EOL if end of line was encountered.
1931 * @param[in,out] ptr to read from and update.
1932 * @param[out] raw The struct to write the raw VALUE_PAIR to.
1933 * @return the last token read.
1935 FR_TOKEN pairread(char const **ptr, VALUE_PAIR_RAW *raw)
1939 FR_TOKEN ret = T_OP_INVALID, next, quote;
1942 if (!ptr || !*ptr || !raw) {
1943 fr_strerror_printf("Invalid arguments");
1944 return T_OP_INVALID;
1948 * Skip leading spaces
1951 while ((*p == ' ') || (*p == '\t')) p++;
1954 fr_strerror_printf("No token read where we expected "
1955 "an attribute name");
1956 return T_OP_INVALID;
1960 fr_strerror_printf("Read a comment instead of a token");
1966 * Try to get the attribute name.
1971 uint8_t const *t = (uint8_t const *) p;
1973 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
1975 fr_strerror_printf("Attribute name too long");
1976 return T_OP_INVALID;
1980 * Only ASCII is allowed, and only a subset of that.
1982 if ((*t < 32) || (*t >= 128)) {
1984 fr_strerror_printf("Invalid attribute name");
1985 return T_OP_INVALID;
1989 * This is arguably easier than trying to figure
1990 * out which operators come after the attribute
1991 * name. Yes, our "lexer" is bad.
1993 if (!dict_attr_allowed_chars[(int) *t]) {
2001 * ASCII, but not a valid attribute name.
2003 if (!*raw->l_opand) goto invalid;
2006 * Look for tag (:#). This is different from :=, which
2009 if ((*p == ':') && (isdigit((int) p[1]))) {
2010 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2015 while (isdigit((int) *p)) {
2016 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2026 /* Now we should have an operator here. */
2027 raw->op = gettoken(ptr, buf, sizeof(buf), false);
2028 if (raw->op < T_EQSTART || raw->op > T_EQEND) {
2029 fr_strerror_printf("Expecting operator");
2031 return T_OP_INVALID;
2035 * Read value. Note that empty string values are allowed
2037 quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand), false);
2038 if (quote == T_EOL) {
2039 fr_strerror_printf("Failed to get value");
2041 return T_OP_INVALID;
2045 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
2049 next = gettoken(&p, buf, sizeof(buf), false);
2060 fr_strerror_printf("Expected end of line or comma");
2061 return T_OP_INVALID;
2069 case T_DOUBLE_QUOTED_STRING:
2071 * Only report as double quoted if it contained valid
2072 * a valid xlat expansion.
2074 p = strchr(raw->r_opand, '%');
2075 if (p && (p[1] == '{')) {
2078 raw->quote = T_SINGLE_QUOTED_STRING;
2091 /** Read one line of attribute/value pairs into a list.
2093 * The line may specify multiple attributes separated by commas.
2095 * @note If the function returns T_OP_INVALID, an error has occurred and
2096 * @note the valuepair list should probably be freed.
2098 * @param ctx for talloc
2099 * @param buffer to read valuepairs from.
2100 * @param list where the parsed VALUE_PAIRs will be appended.
2101 * @return the last token parsed, or T_OP_INVALID
2103 FR_TOKEN userparse(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
2105 VALUE_PAIR *vp, *head, **tail;
2107 FR_TOKEN last_token = T_OP_INVALID;
2108 FR_TOKEN previous_token;
2112 * We allow an empty line.
2114 if (buffer[0] == 0) {
2123 raw.l_opand[0] = '\0';
2124 raw.r_opand[0] = '\0';
2126 previous_token = last_token;
2128 last_token = pairread(&p, &raw);
2129 if (last_token == T_OP_INVALID) break;
2131 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
2132 vp = pairmake(ctx, NULL, raw.l_opand, NULL, raw.op);
2134 last_token = T_OP_INVALID;
2137 if (pairmark_xlat(vp, raw.r_opand) < 0) {
2139 last_token = T_OP_INVALID;
2143 vp = pairmake(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
2145 last_token = T_OP_INVALID;
2151 tail = &((*tail)->next);
2152 } while (*p && (last_token == T_COMMA));
2155 * Don't tell the caller that there was a comment.
2157 if (last_token == T_HASH) {
2158 last_token = previous_token;
2161 if (last_token == T_OP_INVALID) {
2164 pairadd(list, head);
2168 * And return the last token which we read.
2174 * Read valuepairs from the fp up to End-Of-File.
2176 int readvp2(VALUE_PAIR **out, TALLOC_CTX *ctx, FILE *fp, bool *pfiledone)
2179 FR_TOKEN last_token = T_EOL;
2183 VALUE_PAIR *vp = NULL;
2185 fr_cursor_init(&cursor, out);
2187 while (fgets(buf, sizeof(buf), fp) != NULL) {
2189 * If we get a '\n' by itself, we assume that's
2190 * the end of that VP
2192 if (buf[0] == '\n') {
2198 * Comments get ignored
2200 if (buf[0] == '#') continue;
2203 * Read all of the attributes on the current line.
2206 last_token = userparse(ctx, buf, &vp);
2208 if (last_token != T_EOL) goto error;
2212 fr_cursor_insert(&cursor, vp);
2221 vp = fr_cursor_first(&cursor);
2222 if (vp) pairfree(&vp);
2227 /** Compare two attribute values
2229 * @param[in] one the first attribute.
2230 * @param[in] two the second attribute.
2231 * @return -1 if one is less than two, 0 if both are equal, 1 if one is more than two, < -1 on error.
2233 int8_t paircmp_value(VALUE_PAIR const *one, VALUE_PAIR const *two)
2235 int64_t compare = 0;
2240 if (one->da->type != two->da->type) {
2241 fr_strerror_printf("Can't compare attribute values of different types");
2246 * After doing the previous check for special comparisons,
2247 * do the per-type comparison here.
2249 switch (one->da->type) {
2250 case PW_TYPE_ABINARY:
2251 case PW_TYPE_OCTETS:
2255 if (one->length > two->length) {
2256 length = one->length;
2258 length = two->length;
2262 compare = memcmp(one->vp_octets, two->vp_octets, length);
2263 if (compare != 0) break;
2267 * Contents are the same. The return code
2268 * is therefore the difference in lengths.
2270 * i.e. "0x00" is smaller than "0x0000"
2272 compare = one->length - two->length;
2276 case PW_TYPE_STRING:
2277 fr_assert(one->vp_strvalue);
2278 fr_assert(two->vp_strvalue);
2279 compare = strcmp(one->vp_strvalue, two->vp_strvalue);
2282 case PW_TYPE_BOOLEAN:
2285 case PW_TYPE_INTEGER:
2287 compare = (int64_t) one->vp_integer - (int64_t) two->vp_integer;
2290 case PW_TYPE_SIGNED:
2291 compare = one->vp_signed - two->vp_signed;
2294 case PW_TYPE_INTEGER64:
2296 * Don't want integer overflow!
2298 if (one->vp_integer64 < two->vp_integer64) {
2300 } else if (one->vp_integer64 > two->vp_integer64) {
2305 case PW_TYPE_ETHERNET:
2306 compare = memcmp(&one->vp_ether, &two->vp_ether, sizeof(one->vp_ether));
2309 case PW_TYPE_IPV4_ADDR:
2310 compare = (int64_t) ntohl(one->vp_ipaddr) - (int64_t) ntohl(two->vp_ipaddr);
2313 case PW_TYPE_IPV6_ADDR:
2314 compare = memcmp(&one->vp_ipv6addr, &two->vp_ipv6addr, sizeof(one->vp_ipv6addr));
2317 case PW_TYPE_IPV6_PREFIX:
2318 compare = memcmp(&one->vp_ipv6prefix, &two->vp_ipv6prefix, sizeof(one->vp_ipv6prefix));
2321 case PW_TYPE_IPV4_PREFIX:
2322 compare = memcmp(&one->vp_ipv4prefix, &two->vp_ipv4prefix, sizeof(one->vp_ipv4prefix));
2326 compare = memcmp(&one->vp_ifid, &two->vp_ifid, sizeof(one->vp_ifid));
2330 * None of the types below should be in the REQUEST
2332 case PW_TYPE_INVALID: /* We should never see these */
2333 case PW_TYPE_IP_ADDR: /* This should of been converted into IPADDR/IPV6ADDR */
2334 case PW_TYPE_IP_PREFIX: /* This should of been converted into IPADDR/IPV6ADDR */
2336 case PW_TYPE_EXTENDED:
2337 case PW_TYPE_LONG_EXTENDED:
2340 case PW_TYPE_TIMEVAL:
2342 fr_assert(0); /* unknown type */
2346 * Do NOT add a default here, as new types are added
2347 * static analysis will warn us they're not handled
2353 } else if (compare < 0) {
2360 * We leverage the fact that IPv4 and IPv6 prefixes both
2361 * have the same format:
2363 * reserved, prefix-len, data...
2365 static int paircmp_op_cidr(FR_TOKEN op, int bytes,
2366 uint8_t one_net, uint8_t const *one,
2367 uint8_t two_net, uint8_t const *two)
2373 * Handle the case of netmasks being identical.
2375 if (one_net == two_net) {
2378 compare = memcmp(one, two, bytes);
2381 * If they're identical return true for
2384 if ((compare == 0) &&
2385 ((op == T_OP_CMP_EQ) ||
2392 * Everything else returns false.
2394 * 10/8 == 24/8 --> false
2395 * 10/8 <= 24/8 --> false
2396 * 10/8 >= 24/8 --> false
2402 * Netmasks are different. That limits the
2403 * possible results, based on the operator.
2413 case T_OP_LT: /* 192/8 < 192.168/16 --> false */
2414 if (one_net < two_net) {
2420 case T_OP_GT: /* 192/16 > 192.168/8 --> false */
2421 if (one_net > two_net) {
2430 if (one_net < two_net) {
2437 * Do the check byte by byte. If the bytes are
2438 * identical, it MAY be a match. If they're different,
2439 * it is NOT a match.
2444 * All leading bytes are identical.
2446 if (common == 0) return true;
2449 * Doing bitmasks takes more work.
2451 if (common < 8) break;
2453 if (one[i] != two[i]) return false;
2461 mask <<= (8 - common);
2465 if ((one[i] & mask) == ((two[i] & mask))) {
2472 /** Compare two attributes using an operator
2474 * @param[in] a the first attribute
2475 * @param[in] op the operator for comparison.
2476 * @param[in] b the second attribute
2477 * @return 1 if true, 0 if false, -1 on error.
2479 int8_t paircmp_op(VALUE_PAIR const *a, FR_TOKEN op, VALUE_PAIR const *b)
2483 if (!a || !b) return -1;
2485 switch (a->da->type) {
2486 case PW_TYPE_IPV4_ADDR:
2487 switch (b->da->type) {
2488 case PW_TYPE_IPV4_ADDR: /* IPv4 and IPv4 */
2491 case PW_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
2492 return paircmp_op_cidr(op, 4, 32, (uint8_t const *) &a->vp_ipaddr,
2493 b->vp_ipv4prefix[1], (uint8_t const *) &b->vp_ipv4prefix + 2);
2496 fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
2501 case PW_TYPE_IPV4_PREFIX: /* IPv4 and IPv4 Prefix */
2502 switch (b->da->type) {
2503 case PW_TYPE_IPV4_ADDR:
2504 return paircmp_op_cidr(op, 4, a->vp_ipv4prefix[1],
2505 (uint8_t const *) &a->vp_ipv4prefix + 2,
2506 32, (uint8_t const *) &b->vp_ipaddr);
2508 case PW_TYPE_IPV4_PREFIX: /* IPv4 Prefix and IPv4 Prefix */
2509 return paircmp_op_cidr(op, 4, a->vp_ipv4prefix[1],
2510 (uint8_t const *) &a->vp_ipv4prefix + 2,
2511 b->vp_ipv4prefix[1], (uint8_t const *) &b->vp_ipv4prefix + 2);
2514 fr_strerror_printf("Cannot compare IPv4 with IPv6 address");
2519 case PW_TYPE_IPV6_ADDR:
2520 switch (b->da->type) {
2521 case PW_TYPE_IPV6_ADDR: /* IPv6 and IPv6 */
2524 case PW_TYPE_IPV6_PREFIX: /* IPv6 and IPv6 Preifx */
2525 return paircmp_op_cidr(op, 16, 128, (uint8_t const *) &a->vp_ipv6addr,
2526 b->vp_ipv6prefix[1], (uint8_t const *) &b->vp_ipv6prefix + 2);
2530 fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
2535 case PW_TYPE_IPV6_PREFIX:
2536 switch (b->da->type) {
2537 case PW_TYPE_IPV6_ADDR: /* IPv6 Prefix and IPv6 */
2538 return paircmp_op_cidr(op, 16, a->vp_ipv6prefix[1],
2539 (uint8_t const *) &a->vp_ipv6prefix + 2,
2540 128, (uint8_t const *) &b->vp_ipv6addr);
2542 case PW_TYPE_IPV6_PREFIX: /* IPv6 Prefix and IPv6 */
2543 return paircmp_op_cidr(op, 16, a->vp_ipv6prefix[1],
2544 (uint8_t const *) &a->vp_ipv6prefix + 2,
2545 b->vp_ipv6prefix[1], (uint8_t const *) &b->vp_ipv6prefix + 2);
2548 fr_strerror_printf("Cannot compare IPv6 with IPv4 address");
2555 compare = paircmp_value(a, b);
2556 if (compare < -1) { /* comparison error */
2562 * Now do the operator comparison.
2566 return (compare == 0);
2569 return (compare != 0);
2572 return (compare < 0);
2575 return (compare > 0);
2578 return (compare <= 0);
2581 return (compare >= 0);
2588 /** Compare two pairs, using the operator from "a"
2590 * i.e. given two attributes, it does:
2592 * (b->data) (a->operator) (a->data)
2594 * e.g. "foo" != "bar"
2596 * @param[in] a the first attribute
2597 * @param[in] b the second attribute
2598 * @return 1 if true, 0 if false, -1 on error.
2600 int8_t paircmp(VALUE_PAIR *a, VALUE_PAIR *b)
2605 if (b) VERIFY_VP(b);
2611 case T_OP_CMP_FALSE:
2615 * a is a regex, compile it, print b to a string,
2616 * and then do string comparisons.
2626 char buffer[MAX_STRING_LEN * 4 + 1];
2628 compare = regcomp(®, a->vp_strvalue, REG_EXTENDED);
2630 regerror(compare, ®, buffer, sizeof(buffer));
2631 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2632 a->da->name, buffer);
2641 vp_prints_value(buffer, sizeof(buffer), b, 0);
2644 * Don't care about substring matches,
2647 compare = regexec(®, buffer, 0, NULL, 0);
2650 if (a->op == T_OP_REG_EQ) {
2651 return (compare == 0);
2654 return (compare != 0);
2658 default: /* we're OK */
2662 return paircmp_op(b, a->op, a);
2665 /** Determine equality of two lists
2667 * This is useful for comparing lists of attributes inserted into a binary tree.
2669 * @param a first list of VALUE_PAIRs.
2670 * @param b second list of VALUE_PAIRs.
2671 * @return -1 if a < b, 0 if the two lists are equal, 1 if a > b, -2 on error.
2673 int8_t pairlistcmp(VALUE_PAIR *a, VALUE_PAIR *b)
2675 vp_cursor_t a_cursor, b_cursor;
2676 VALUE_PAIR *a_p, *b_p;
2679 for (a_p = fr_cursor_init(&a_cursor, &a), b_p = fr_cursor_init(&b_cursor, &b);
2681 a_p = fr_cursor_next(&a_cursor), b_p = fr_cursor_next(&b_cursor)) {
2682 /* Same VP, no point doing expensive checks */
2687 if (a_p->da < b_p->da) {
2690 if (a_p->da > b_p->da) {
2694 if (a_p->tag < b_p->tag) {
2697 if (a_p->tag > b_p->tag) {
2701 ret = paircmp_value(a_p, b_p);
2703 fr_assert(ret >= -1); /* Comparison error */
2720 /** Set the type of the VALUE_PAIR value buffer to match it's DICT_ATTR
2722 * @param vp to fixup.
2724 static void pairtypeset(VALUE_PAIR *vp)
2726 if (!vp->data.ptr) return;
2728 switch(vp->da->type) {
2729 case PW_TYPE_OCTETS:
2731 talloc_set_type(vp->data.ptr, uint8_t);
2734 case PW_TYPE_STRING:
2735 talloc_set_type(vp->data.ptr, char);
2743 /** Copy data into an "octets" data type.
2745 * @param[in,out] vp to update
2746 * @param[in] src data to copy
2747 * @param[in] size of the data, may be 0 in which case previous value will be freed.
2749 void pairmemcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2751 uint8_t *p = NULL, *q;
2756 p = talloc_memdup(vp, src, size);
2758 talloc_set_type(p, uint8_t);
2761 memcpy(&q, &vp->vp_octets, sizeof(q));
2767 if (size > 0) pairtypeset(vp);
2770 /** Reparent an allocated octet buffer to a VALUE_PAIR
2772 * @param[in,out] vp to update
2773 * @param[in] src buffer to steal.
2775 void pairmemsteal(VALUE_PAIR *vp, uint8_t const *src)
2781 memcpy(&q, &vp->vp_octets, sizeof(q));
2784 vp->vp_octets = talloc_steal(vp, src);
2786 vp->length = talloc_array_length(vp->vp_strvalue);
2790 /** Reparent an allocated char buffer to a VALUE_PAIR
2792 * @param[in,out] vp to update
2793 * @param[in] src buffer to steal.
2795 void pairstrsteal(VALUE_PAIR *vp, char const *src)
2801 memcpy(&q, &vp->vp_octets, sizeof(q));
2804 vp->vp_strvalue = talloc_steal(vp, src);
2806 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2810 /** Copy data into an "string" data type.
2812 * @param[in,out] vp to update
2813 * @param[in] src data to copy
2815 void pairstrcpy(VALUE_PAIR *vp, char const *src)
2821 p = talloc_strdup(vp, src);
2825 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2828 vp->vp_strvalue = p;
2830 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2834 /** Copy data into an "string" data type.
2836 * @param[in,out] vp to update.
2837 * @param[in] src data to copy.
2838 * @param[in] len of data to copy.
2840 void pairstrncpy(VALUE_PAIR *vp, char const *src, size_t len)
2846 p = talloc_array(vp, char, len + 1);
2849 memcpy(p, src, len); /* embdedded \0 safe */
2852 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2855 vp->vp_strvalue = p;
2861 /** Copy data from one VP to another
2863 * Allocate a new pair using da, and copy over the value from the specified vp.
2865 * @todo Should be able to do type conversions.
2867 * @param[in,out] vp to update.
2868 * @param[in] da Type of data represented by data.
2869 * @param[in] data to copy.
2870 * @param[in] len of data to copy.
2872 int pairdatacpy(VALUE_PAIR *vp, DICT_ATTR const *da, value_data_t const *data, size_t len)
2878 * The da->types have to be identical, OR the "from" da->type has
2881 if (vp->da->type != da->type) {
2883 * Decode the octets buffer using the RADIUS decoder.
2885 if (da->type == PW_TYPE_OCTETS) {
2886 if (data2vp(vp, NULL, NULL, NULL, vp->da, data->octets, len, len, &vp) < 0) return -1;
2892 * Else if the destination da->type is octets
2894 if (vp->da->type == PW_TYPE_OCTETS) {
2897 VALUE_PAIR const *pvp = vp;
2899 buff = talloc_array(vp, uint8_t, dict_attr_sizes[da->type][1] + 2);
2901 ret = rad_vp2rfc(NULL, NULL, NULL, &pvp, buff, dict_attr_sizes[da->type][1]);
2902 if (ret < 0) return -1;
2904 pairmemcpy(vp, buff + 2, ret - 2);
2913 fr_strerror_printf("Data conversion not supported");
2918 * Clear existing value if there is one
2920 memcpy(&old, &vp->data.ptr, sizeof(old));
2923 switch (vp->da->type) {
2925 case PW_TYPE_OCTETS:
2926 pairmemcpy(vp, data->octets, len);
2929 case PW_TYPE_STRING:
2930 pairstrncpy(vp, data->strvalue, len);
2934 memcpy(&vp->data, data, sizeof(vp->data));
2942 /** Print data into an "string" data type.
2944 * @param[in,out] vp to update
2945 * @param[in] fmt the format string
2947 void pairsprintf(VALUE_PAIR *vp, char const *fmt, ...)
2955 p = talloc_vasprintf(vp, fmt, ap);
2960 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2963 vp->vp_strvalue = p;
2966 vp->length = talloc_array_length(vp->vp_strvalue) - 1;