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 = FREE_MAGIC;
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.
100 if (!da) return NULL;
102 vp = talloc_zero(ctx, VALUE_PAIR);
104 fr_strerror_printf("Out of memory");
112 vp->length = da->flags.length;
114 talloc_set_destructor(vp, _pairfree);
119 /** Create a new valuepair
121 * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
124 * If attr or vendor are uknown will call dict_attruknown to create a dynamic
125 * DICT_ATTR of PW_TYPE_OCTETS.
127 * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
128 * checking @verbatim vp->da->flags.is_unknown @endverbatim.
130 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
131 * @param[in] attr number.
132 * @param[in] vendor number.
133 * @return the new valuepair or NULL on error.
135 VALUE_PAIR *paircreate(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
139 da = dict_attrbyvalue(attr, vendor);
141 da = dict_attrunknown(attr, vendor, true);
147 return pairalloc(ctx, da);
150 /** Free memory used by a valuepair list.
152 * @todo TLV: needs to free all dependents of each VP freed.
154 void pairfree(VALUE_PAIR **vps)
163 for (vp = paircursor(&cursor, vps);
165 vp = pairnext(&cursor)) {
173 /** Mark malformed or unrecognised attributed as unknown
175 * @param vp to change DICT_ATTR of.
176 * @return 0 on success (or if already unknown) else -1 on error.
178 int pair2unknown(VALUE_PAIR *vp)
183 if (vp->da->flags.is_unknown) {
187 da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
197 /** Find the pair with the matching attribute
199 * @todo should take DAs and do a pointer comparison.
201 VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor,
207 for (i = paircursor(&cursor, &vp);
209 i = pairnext(&cursor)) {
211 if ((i->da->attr == attr) && (i->da->vendor == vendor)
212 && ((tag == TAG_ANY) || (i->da->flags.has_tag &&
221 /** Setup a cursor to iterate over attribute pairs
223 * @param cursor Where to initialise the cursor (uses existing structure).
224 * @param node to start from.
226 VALUE_PAIR *paircursorc(vp_cursor_t *cursor, VALUE_PAIR const * const *node)
228 memset(cursor, 0, sizeof(*cursor));
230 if (!node || !cursor) {
234 memcpy(&cursor->first, &node, sizeof(cursor->first));
235 cursor->current = *cursor->first;
237 if (cursor->current) {
238 VERIFY_VP(cursor->current);
239 cursor->next = cursor->current->next;
242 return cursor->current;
245 VALUE_PAIR *pairfirst(vp_cursor_t *cursor)
247 cursor->current = *cursor->first;
249 if (cursor->current) {
250 VERIFY_VP(cursor->current);
251 cursor->next = cursor->current->next;
252 if (cursor->next) VERIFY_VP(cursor->next);
253 cursor->found = NULL;
256 return cursor->current;
259 /** Iterate over attributes of a given type in the pairlist
263 VALUE_PAIR *pairfindnext(vp_cursor_t *cursor, unsigned int attr, unsigned int vendor, int8_t tag)
267 i = pairfind(!cursor->found ? cursor->current : cursor->found->next, attr, vendor, tag);
270 cursor->current = NULL;
275 cursor->next = i->next;
282 /** Retrieve the next VALUE_PAIR
286 VALUE_PAIR *pairnext(vp_cursor_t *cursor)
288 cursor->current = cursor->next;
289 if (cursor->current) {
290 VERIFY_VP(cursor->current);
293 * Set this now in case 'current' gets freed before
294 * pairnext is called again.
296 cursor->next = cursor->current->next;
299 * Next call to pairfindnext will start from the current
300 * position in the list, not the last found instance.
302 cursor->found = NULL;
305 return cursor->current;
308 VALUE_PAIR *paircurrent(vp_cursor_t *cursor)
310 if (cursor->current) {
311 VERIFY_VP(cursor->current);
314 return cursor->current;
319 * @todo don't use with pairdelete
321 void pairinsert(vp_cursor_t *cursor, VALUE_PAIR *add)
332 * Cursor was initialised with a pointer to a NULL value_pair
334 if (!*cursor->first) {
335 *cursor->first = add;
336 cursor->current = add;
337 cursor->next = cursor->current->next;
343 * We don't yet know where the last VALUE_PAIR is
345 * Assume current is closer to the end of the list and use that if available.
348 cursor->last = cursor->current ? cursor->current : *cursor->first;
351 VERIFY_VP(cursor->last);
354 * Something outside of the cursor added another VALUE_PAIR
356 if (cursor->last->next) {
357 for (i = cursor->last; i; i = i->next) {
364 * Either current was never set, or something iterated to the end of the
367 if (!cursor->current) {
368 cursor->current = add;
371 cursor->last->next = add;
374 /** Remove the current pair
376 * @todo this is really inefficient and should be fixed...
378 * @param cursor to remove the current pair from.
379 * @return NULL on error, else the VALUE_PAIR we just removed.
381 VALUE_PAIR *pairremove(vp_cursor_t *cursor)
383 VALUE_PAIR *vp, **last;
385 vp = paircurrent(cursor);
390 last = cursor->first;
391 while (*last != vp) {
392 last = &(*last)->next;
395 pairnext(cursor); /* Advance the cursor past the one were about to delete */
403 /** Delete matching pairs
405 * Delete matching pairs from the attribute list.
407 * @param[in,out] first VP in list.
408 * @param[in] attr to match.
409 * @param[in] vendor to match.
410 * @param[in] tag to match. TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
412 * @todo should take DAs and do a point comparison.
414 void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor,
417 VALUE_PAIR *i, *next;
418 VALUE_PAIR **last = first;
420 for(i = *first; i; i = next) {
423 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
425 (i->da->flags.has_tag && (i->tag == tag)))) {
434 /** Add a VP to the end of the list.
436 * Locates the end of 'first', and links an additional VP 'add' at the end.
438 * @param[in] first VP in linked list. Will add new VP to the end of this list.
439 * @param[in] add VP to add to list.
441 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
449 if (*first == NULL) {
453 for(i = *first; i->next; i = i->next)
458 /** Replace all matching VPs
460 * Walks over 'first', and replaces the first VP that matches 'replace'.
462 * @note Memory used by the VP being replaced will be freed.
463 * @note Will not work with unknown attributes.
465 * @param[in,out] first VP in linked list. Will search and replace in this list.
466 * @param[in] replace VP to replace.
468 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
470 VALUE_PAIR *i, *next;
471 VALUE_PAIR **prev = first;
475 if (*first == NULL) {
481 * Not an empty list, so find item if it is there, and
482 * replace it. Note, we always replace the first one, and
483 * we ignore any others that might exist.
485 for(i = *first; i; i = next) {
490 * Found the first attribute, replace it,
493 if ((i->da == replace->da) &&
494 (!i->da->flags.has_tag || (i->tag == replace->tag))
499 * Should really assert that replace->next == NULL
501 replace->next = next;
507 * Point to where the attribute should go.
513 * If we got here, we didn't find anything to replace, so
514 * stopped at the last item, which we just append to.
519 static void pairsort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
525 * Stopping condition - no more elements left to split
527 if (!source || !source->next) {
535 * Fast advances twice as fast as slow, so when it gets to the end,
536 * slow will point to the middle of the linked list.
554 static VALUE_PAIR *pairsort_merge(VALUE_PAIR *a, VALUE_PAIR *b, bool with_tag)
556 VALUE_PAIR *result = NULL;
562 * Compare the DICT_ATTRs and tags
564 if ((with_tag && (a->tag < b->tag)) || (a->da <= b->da)) {
566 result->next = pairsort_merge(a->next, b, with_tag);
569 result->next = pairsort_merge(a, b->next, with_tag);
575 /** Sort a linked list of VALUE_PAIRs using merge sort
577 * @param[in,out] vps List of VALUE_PAIRs to sort.
578 * @param[in] with_tag sort by tag then by DICT_ATTR
580 void pairsort(VALUE_PAIR **vps, bool with_tag)
582 VALUE_PAIR *head = *vps;
587 * If there's 0-1 elements it must already be sorted.
589 if (!head || !head->next) {
593 pairsort_split(head, &a, &b); /* Split into sublists */
594 pairsort(&a, with_tag); /* Traverse left */
595 pairsort(&b, with_tag); /* Traverse right */
598 * merge the two sorted lists together
600 *vps = pairsort_merge(a, b, with_tag);
603 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
605 * @param filter attributes to check list against.
606 * @param list attributes, probably a request or reply
608 bool pairvalidate(VALUE_PAIR *filter, VALUE_PAIR *list)
610 vp_cursor_t filter_cursor;
611 vp_cursor_t list_cursor;
613 VALUE_PAIR *check, *match;
615 if (!filter && !list) {
618 if (!filter || !list) {
623 * This allows us to verify the sets of validate and reply are equal
624 * i.e. we have a validate rule which matches every reply attribute.
626 * @todo this should be removed one we have sets and lists
628 pairsort(&filter, true);
629 pairsort(&list, true);
631 match = paircursor(&list_cursor, &list);
632 check = paircursor(&filter_cursor, &filter);
636 * The lists are sorted, so if the first
637 * attributes aren't of the same type, then we're
640 if (!attribute_eq(check, match)) {
645 * They're of the same type, but don't have the
646 * same values. This is a problem.
648 * Note that the RFCs say that for attributes of
649 * the same type, order is important.
651 if (!paircmp(check, match)) {
655 match = pairnext(&list_cursor);
656 check = pairnext(&filter_cursor);
658 if (!match && !check) break;
661 * One list ended earlier than the others, they
664 if (!match || !check) {
672 /** Copy a single valuepair
674 * Allocate a new valuepair and copy the da from the old vp.
676 * @param[in] ctx for talloc
677 * @param[in] vp to copy.
678 * @return a copy of the input VP or NULL on error.
680 VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
684 if (!vp) return NULL;
688 n = pairalloc(ctx, vp->da);
690 fr_strerror_printf("out of memory");
694 memcpy(n, vp, sizeof(*n));
699 if (vp->type == VT_XLAT) {
700 n->value.xlat = talloc_strdup(n, n->value.xlat);
703 n->da = dict_attr_copy(vp->da, true);
711 if ((n->da->type == PW_TYPE_TLV) ||
712 (n->da->type == PW_TYPE_OCTETS)) {
713 if (n->vp_octets != NULL) {
714 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
717 } else if (n->da->type == PW_TYPE_STRING) {
718 if (n->vp_strvalue != NULL) {
720 * Equivalent to, and faster than strdup.
722 n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1);
729 /** Copy data from one VP to another
731 * Allocate a new pair using da, and copy over the value from the specified
734 * @todo Should be able to do type conversions.
736 * @param[in] ctx for talloc
737 * @param[in] da of new attribute to alloc.
738 * @param[in] vp to copy data from.
739 * @return the new valuepair.
741 VALUE_PAIR *paircopyvpdata(TALLOC_CTX *ctx, DICT_ATTR const *da, VALUE_PAIR const *vp)
745 if (!vp) return NULL;
750 * The types have to be identical, OR the "from" VP has
753 if (da->type != vp->da->type) {
756 VALUE_PAIR const **pvp;
758 if (vp->da->type == PW_TYPE_OCTETS) {
760 * Decode the data. It may be wrong!
762 if (rad_data2vp(da->attr, da->vendor, vp->vp_octets, vp->length, &n) < 0) {
771 * Else the destination type is octets
773 switch (vp->da->type) {
775 return NULL; /* can't do it */
777 case PW_TYPE_INTEGER:
781 case PW_TYPE_IPV6ADDR:
782 case PW_TYPE_IPV6PREFIX:
785 case PW_TYPE_ETHERNET:
787 case PW_TYPE_INTEGER64:
788 case PW_TYPE_IPV4PREFIX:
792 n = pairalloc(ctx, da);
795 p = talloc_array(n, uint8_t, dict_attr_sizes[vp->da->type][1] + 2);
798 length = rad_vp2attr(NULL, NULL, NULL, pvp, p, dict_attr_sizes[vp->da->type][1]);
804 pairmemcpy(n, p + 2, length - 2);
809 n = pairalloc(ctx, da);
814 memcpy(n, vp, sizeof(*n));
817 if (n->type == VT_XLAT) {
818 n->value.xlat = talloc_strdup(n, n->value.xlat);
821 switch (n->da->type) {
824 if (n->vp_octets != NULL) {
825 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
830 if (n->vp_strvalue != NULL) {
831 n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1); /* NULL byte */
844 /** Copy matching pairs
846 * Copy pairs of a matching attribute number, vendor number and tag from the
847 * the input list to a new list, and returns the head of this list.
849 * @param[in] ctx for talloc
850 * @param[in] from whence to copy VALUE_PAIRs.
851 * @param[in] attr to match, if 0 input list will not be filtered by attr.
852 * @param[in] vendor to match.
853 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
854 * @return the head of the new VALUE_PAIR list or NULL on error.
856 VALUE_PAIR *paircopy2(TALLOC_CTX *ctx, VALUE_PAIR *from,
857 unsigned int attr, unsigned int vendor, int8_t tag)
859 vp_cursor_t src, dst;
861 VALUE_PAIR *out = NULL, *vp;
863 paircursor(&dst, &out);
864 for (vp = paircursor(&src, &from);
866 vp = pairnext(&src)) {
869 if ((vp->da->attr != attr) || (vp->da->vendor != vendor)) {
873 if ((tag != TAG_ANY) && vp->da->flags.has_tag && (vp->tag != tag)) {
877 vp = paircopyvp(ctx, vp);
882 pairinsert(&dst, vp);
891 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
893 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
894 * @param[in] from whence to copy VALUE_PAIRs.
895 * @return the head of the new VALUE_PAIR list or NULL on error.
897 VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from)
899 vp_cursor_t src, dst;
901 VALUE_PAIR *out = NULL, *vp;
903 paircursor(&dst, &out);
904 for (vp = paircursor(&src, &from);
906 vp = pairnext(&src)) {
908 vp = paircopyvp(ctx, vp);
913 pairinsert(&dst, vp); /* paircopy sets next pointer to NULL */
919 /** Move pairs from source list to destination list respecting operator
921 * @note This function does some additional magic that's probably not needed
922 * in most places. Consider using radius_pairmove in server code.
924 * @note pairfree should be called on the head of the source list to free
925 * unmoved attributes (if they're no longer needed).
927 * @note Does not respect tags when matching.
929 * @param[in] ctx for talloc
930 * @param[in,out] to destination list.
931 * @param[in,out] from source list.
933 * @see radius_pairmove
935 void pairmove(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
937 VALUE_PAIR *i, *found;
938 VALUE_PAIR *head_new, **tail_new;
939 VALUE_PAIR **tail_from;
941 if (!to || !from || !*from) return;
944 * We're editing the "to" list while we're adding new
945 * attributes to it. We don't want the new attributes to
946 * be edited, so we create an intermediate list to hold
947 * them during the editing process.
950 tail_new = &head_new;
953 * We're looping over the "from" list, moving some
954 * attributes out, but leaving others in place.
957 while ((i = *tail_from) != NULL) {
961 * We never move Fall-Through.
963 if (!i->da->vendor && i->da->attr == PW_FALL_THROUGH) {
964 tail_from = &(i->next);
969 * Unlike previous versions, we treat all other
970 * attributes as normal. i.e. there's no special
971 * treatment for passwords or Hint.
976 * Anything else are operators which
977 * shouldn't occur. We ignore them, and
978 * leave them in place.
981 tail_from = &(i->next);
985 * Add it to the "to" list, but only if
986 * it doesn't already exist.
989 found = pairfind(*to, i->da->attr, i->da->vendor,
991 if (!found) goto do_add;
993 tail_from = &(i->next);
997 * Add it to the "to" list, and delete any attribute
998 * of the same vendor/attr which already exists.
1001 found = pairfind(*to, i->da->attr, i->da->vendor,
1003 if (!found) goto do_add;
1006 * Do NOT call pairdelete() here,
1007 * due to issues with re-writing
1008 * "request->username".
1010 * Everybody calls pairmove, and
1011 * expects it to work. We can't
1012 * update request->username here,
1013 * so instead we over-write the
1014 * vp that it's pointing to.
1016 switch (found->da->type) {
1021 memcpy(found, i, sizeof(*found));
1026 pairmemsteal(found, i->vp_tlv);
1030 case PW_TYPE_OCTETS:
1031 pairmemsteal(found, i->vp_octets);
1032 i->vp_octets = NULL;
1035 case PW_TYPE_STRING:
1036 pairstrsteal(found, i->vp_strvalue);
1037 i->vp_strvalue = NULL;
1038 found->tag = i->tag;
1043 * Delete *all* of the attributes
1044 * of the same number.
1046 pairdelete(&found->next,
1048 found->da->vendor, TAG_ANY);
1051 * Remove this attribute from the
1054 *tail_from = i->next;
1060 * Move it from the old list and add it
1065 *tail_from = i->next;
1067 *tail_new = talloc_steal(ctx, i);
1068 tail_new = &(i->next);
1071 } /* loop over the "from" list. */
1074 * Take the "new" list, and append it to the "to" list.
1076 pairadd(to, head_new);
1079 /** Move matching pairs between VALUE_PAIR lists
1081 * Move pairs of a matching attribute number, vendor number and tag from the
1082 * the input list to the output list.
1084 * @note pairfree should be called on the head of the old list to free unmoved
1085 attributes (if they're no longer needed).
1087 * @param[in] ctx for talloc
1088 * @param[in,out] to destination list.
1089 * @param[in,out] from source list.
1090 * @param[in] attr to match, if PW_VENDOR_SPECIFIC and vendor 0, only VSAs will
1091 * be copied. If 0 and 0, all attributes will match
1092 * @param[in] vendor to match.
1093 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
1095 void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor, int8_t tag)
1097 VALUE_PAIR *to_tail, *i, *next;
1098 VALUE_PAIR *iprev = NULL;
1101 * Find the last pair in the "to" list and put it in "to_tail".
1103 * @todo: replace the "if" with "VALUE_PAIR **tail"
1107 for(i = *to; i; i = i->next) {
1115 * Attr/vendor of 0 means "move them all".
1116 * It's better than "pairadd(foo,bar);bar=NULL"
1118 if ((vendor == 0) && (attr == 0)) {
1120 to_tail->next = *from;
1125 for (i = *from; i; i = i->next) {
1126 (void) talloc_steal(ctx, i);
1133 for(i = *from; i; i = next) {
1137 if ((tag != TAG_ANY) && i->da->flags.has_tag &&
1143 * vendor=0, attr = PW_VENDOR_SPECIFIC means
1144 * "match any vendor attribute".
1146 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1148 * It's a VSA: move it over.
1150 if (i->da->vendor != 0) goto move;
1153 * It's Vendor-Specific: move it over.
1155 if (i->da->attr == attr) goto move;
1158 * It's not a VSA: ignore it.
1165 * If it isn't an exact match, ignore it.
1167 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1174 * Remove the attribute from the "from" list.
1182 * Add the attribute to the "to" list.
1190 (void) talloc_steal(ctx, i);
1194 static char const *hextab = "0123456789abcdef";
1196 bool pairparsevalue(VALUE_PAIR *vp, char const *value)
1199 char const *cp, *cs;
1205 if (!value) return false;
1209 * It's a comparison, not a real VALUE_PAIR, copy the string over verbatim
1211 if ((vp->op == T_OP_REG_EQ) || (vp->op == T_OP_REG_NE)) {
1212 pairstrcpy(vp, value); /* Icky hacky ewww */
1216 switch(vp->da->type) {
1217 case PW_TYPE_STRING:
1221 p = talloc_strdup(vp, value);
1222 vp->vp_strvalue = p;
1260 c = '\\'; /* no cp++ */
1263 if ((cp[0] >= '0') &&
1269 (sscanf(cp, "%3o", &x) == 1)) {
1272 } /* else just do '\\' */
1279 vp->length = length;
1282 case PW_TYPE_IPADDR:
1284 * FIXME: complain if hostname
1285 * cannot be resolved, or resolve later!
1293 * Convert things which are obviously integers to IP addresses
1295 * We assume the number is the bigendian representation of the
1298 if (fr_integer_check(value)) {
1299 vp->vp_ipaddr = htonl(atol(value));
1304 * Certain applications/databases print IPv4 addresses with a
1305 * /32 suffix. Strip it off if the mask is 32, else error out.
1307 p = strchr(value, '/');
1309 if ((p[1] != '3') || (p[2] != '2') || (p[3] != '\0')) {
1310 fr_strerror_printf("Invalid IP address suffix \"%s\". Only '/32' permitted "
1311 "for non-prefix types", p);
1315 strlcpy(ipv4, value, sizeof(ipv4));
1316 ipv4[p - value] = '\0';
1322 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
1323 fr_strerror_printf("Failed to find IP address for %s", cs);
1327 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1336 * Note that ALL integers are unsigned!
1338 vp->vp_integer = fr_strtoul(value, &p);
1340 if (vp->vp_integer > 255) {
1341 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
1346 if (fr_whitespace_check(p)) break;
1347 goto check_for_value;
1351 * Note that ALL integers are unsigned!
1353 vp->vp_integer = fr_strtoul(value, &p);
1356 if (vp->vp_integer > 65535) {
1357 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1362 if (fr_whitespace_check(p)) break;
1363 goto check_for_value;
1365 case PW_TYPE_INTEGER:
1367 * Note that ALL integers are unsigned!
1369 vp->vp_integer = fr_strtoul(value, &p);
1372 if (fr_whitespace_check(p)) break;
1376 * Look for the named value for the given
1379 if ((dval = dict_valbyname(vp->da->attr, vp->da->vendor, value)) == NULL) {
1380 fr_strerror_printf("Unknown value '%s' for attribute '%s'", value, vp->da->name);
1383 vp->vp_integer = dval->value;
1386 case PW_TYPE_INTEGER64:
1388 * Note that ALL integers are unsigned!
1390 if (sscanf(value, "%" PRIu64, &y) != 1) {
1391 fr_strerror_printf("Invalid value '%s' for attribute '%s'",
1392 value, vp->da->name);
1395 vp->vp_integer64 = y;
1397 length = strspn(value, "0123456789");
1398 if (fr_whitespace_check(value + length)) break;
1404 * time_t may be 64 bits, whule vp_date
1405 * MUST be 32-bits. We need an
1406 * intermediary variable to handle
1411 if (fr_get_time(value, &date) < 0) {
1412 fr_strerror_printf("failed to parse time string "
1422 case PW_TYPE_ABINARY:
1423 #ifdef WITH_ASCEND_BINARY
1424 if (strncasecmp(value, "0x", 2) == 0) {
1428 if (ascend_parse_filter(vp, value) < 0 ) {
1429 /* Allow ascend_parse_filter's strerror to bubble up */
1435 * If Ascend binary is NOT defined,
1436 * then fall through to raw octets, so that
1437 * the user can at least make them by hand...
1440 /* raw octets: 0x01020304... */
1442 if (strcmp(value, "ANY") == 0) {
1445 } /* else it's hex */
1447 case PW_TYPE_OCTETS:
1448 if (strncasecmp(value, "0x", 2) == 0) {
1452 #ifdef WITH_ASCEND_BINARY
1457 vp->length = size >> 1;
1458 us = talloc_array(vp, uint8_t, vp->length);
1463 if ((size & 0x01) != 0) {
1464 fr_strerror_printf("Hex string is not an even length string");
1468 if (fr_hex2bin(us, cp, vp->length) != vp->length) {
1469 fr_strerror_printf("Invalid hex data");
1474 pairstrcpy(vp, value);
1479 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1480 fr_strerror_printf("Failed to parse interface-id string \"%s\"", value);
1486 case PW_TYPE_IPV6ADDR:
1490 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1493 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1495 fr_strerror_printf("failed to parse IPv6 address "
1496 "string \"%s\": %s", value, buffer);
1499 vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
1500 vp->length = 16; /* length of IPv6 address */
1504 case PW_TYPE_IPV6PREFIX:
1505 p = strchr(value, '/');
1506 if (!p || ((p - value) >= 256)) {
1507 fr_strerror_printf("invalid IPv6 prefix string \"%s\"", value);
1510 unsigned int prefix;
1511 char buffer[256], *eptr;
1513 memcpy(buffer, value, p - value);
1514 buffer[p - value] = '\0';
1516 if (inet_pton(AF_INET6, buffer, vp->vp_ipv6prefix + 2) <= 0) {
1517 fr_strerror_printf("failed to parse IPv6 address string \"%s\"", value);
1521 prefix = strtoul(p + 1, &eptr, 10);
1522 if ((prefix > 128) || *eptr) {
1523 fr_strerror_printf("failed to parse IPv6 address string \"%s\"", value);
1526 vp->vp_ipv6prefix[1] = prefix;
1529 struct in6_addr addr;
1531 addr = fr_ipaddr_mask6((struct in6_addr *)(&vp->vp_ipv6prefix[2]), prefix);
1532 memcpy(vp->vp_ipv6prefix + 2, &addr, sizeof(addr));
1535 vp->length = 16 + 2;
1538 case PW_TYPE_IPV4PREFIX:
1539 p = strchr(value, '/');
1542 * 192.0.2.2 is parsed as if it was /32
1545 vp->vp_ipv4prefix[1] = 32;
1547 if (inet_pton(AF_INET, value, vp->vp_ipv4prefix + 2) <= 0) {
1548 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1551 vp->length = sizeof(vp->vp_ipv4prefix);
1556 * Otherwise parse the prefix
1558 if ((p - value) >= 256) {
1559 fr_strerror_printf("invalid IPv4 prefix string \"%s\"", value);
1562 unsigned int prefix;
1563 char buffer[256], *eptr;
1565 memcpy(buffer, value, p - value);
1566 buffer[p - value] = '\0';
1568 if (inet_pton(AF_INET, buffer, vp->vp_ipv4prefix + 2) <= 0) {
1569 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1573 prefix = strtoul(p + 1, &eptr, 10);
1574 if ((prefix > 32) || *eptr) {
1575 fr_strerror_printf("failed to parse IPv4 address string \"%s\"", value);
1578 vp->vp_ipv4prefix[1] = prefix;
1581 struct in_addr addr;
1583 addr = fr_ipaddr_mask((struct in_addr *)(&vp->vp_ipv4prefix[2]), prefix);
1584 memcpy(vp->vp_ipv4prefix + 2, &addr, sizeof(addr));
1587 vp->length = sizeof(vp->vp_ipv4prefix);
1590 case PW_TYPE_ETHERNET:
1592 char const *c1, *c2;
1595 * Convert things which are obviously integers to Ethernet addresses
1597 * We assume the number is the bigendian representation of the
1600 if (fr_integer_check(value)) {
1601 uint64_t integer = htonll(atoll(value));
1603 memcpy(&vp->vp_ether, &integer, sizeof(vp->vp_ether));
1612 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1614 } else if ((cp[1] != '\0') &&
1617 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1618 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1620 if (*cp == ':') cp++;
1624 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1625 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1628 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1636 * Crazy polymorphic (IPv4/IPv6) attribute type for WiMAX.
1638 * We try and make is saner by replacing the original
1639 * da, with either an IPv4 or IPv6 da type.
1641 * These are not dynamic da, and will have the same vendor
1642 * and attribute as the original.
1644 case PW_TYPE_COMBO_IP:
1646 DICT_ATTR const *da;
1648 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) > 0) {
1649 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1652 fr_strerror_printf("Cannot find ipv6addr for %s", vp->da->name);
1656 vp->length = 16; /* length of IPv6 address */
1660 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1663 fr_strerror_printf("Cannot find ipaddr for %s", vp->da->name);
1667 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1668 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1672 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1680 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1681 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1685 case PW_TYPE_TLV: /* don't use this! */
1686 if (strncasecmp(value, "0x", 2) != 0) {
1687 fr_strerror_printf("Invalid TLV specification");
1690 length = strlen(value + 2) / 2;
1691 if (vp->length < length) {
1692 TALLOC_FREE(vp->vp_tlv);
1694 vp->vp_tlv = talloc_array(vp, uint8_t, length);
1696 fr_strerror_printf("No memory");
1699 if (fr_hex2bin(vp->vp_tlv, value + 2, length) != length) {
1700 fr_strerror_printf("Invalid hex data in TLV");
1703 vp->length = length;
1710 fr_strerror_printf("unknown attribute type %d", vp->da->type);
1719 /** Create a valuepair from an ASCII attribute and value
1721 * Where the attribute name is in the form:
1723 * - Attr-%d.%d.%d...
1724 * - Vendor-%d-Attr-%d
1725 * - VendorName-Attr-%d
1727 * @param ctx for talloc
1728 * @param attribute name to parse.
1729 * @param value to parse (must be a hex string).
1730 * @param op to assign to new valuepair.
1731 * @return new valuepair or NULL on error.
1733 static VALUE_PAIR *pairmake_any(TALLOC_CTX *ctx,
1734 char const *attribute, char const *value,
1738 DICT_ATTR const *da;
1743 da = dict_attrunknownbyname(attribute, true);
1744 if (!da) return NULL;
1747 * Unknown attributes MUST be of type 'octets'
1749 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1750 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1751 "string, not \"%s\"", attribute, value);
1753 dict_attr_free(&da);
1758 * We've now parsed the attribute properly, Let's create
1759 * it. This next stop also looks the attribute up in the
1760 * dictionary, and creates the appropriate type for it.
1762 vp = pairalloc(ctx, da);
1764 dict_attr_free(&da);
1768 vp->op = (op == 0) ? T_OP_EQ : op;
1770 if (!value) return vp;
1772 size = strlen(value + 2);
1773 vp->length = size >> 1;
1774 data = talloc_array(vp, uint8_t, vp->length);
1776 if (fr_hex2bin(data, value + 2, size) != vp->length) {
1777 fr_strerror_printf("Invalid hex string");
1782 vp->vp_octets = data;
1788 /** Create a VALUE_PAIR from ASCII strings
1790 * Converts an attribute string identifier (with an optional tag qualifier)
1791 * and value string into a VALUE_PAIR.
1793 * The string value is parsed according to the type of VALUE_PAIR being created.
1795 * @param[in] ctx for talloc
1796 * @param[in] vps list where the attribute will be added (optional)
1797 * @param[in] attribute name.
1798 * @param[in] value attribute value (may be NULL if value will be set later).
1799 * @param[in] op to assign to new VALUE_PAIR.
1800 * @return a new VALUE_PAIR.
1802 VALUE_PAIR *pairmake(TALLOC_CTX *ctx, VALUE_PAIR **vps,
1803 char const *attribute, char const *value, FR_TOKEN op)
1805 DICT_ATTR const *da;
1811 char const *attrname = attribute;
1814 * Check for tags in 'Attribute:Tag' format.
1819 ts = strrchr(attribute, ':');
1821 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1826 strlcpy(buffer, attribute, sizeof(buffer));
1828 ts = strrchr(attrname, ':');
1829 if (!ts) return NULL;
1831 /* Colon found with something behind it */
1832 if (ts[1] == '*' && ts[2] == 0) {
1833 /* Wildcard tag for check items */
1836 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1837 /* It's not a wild card tag */
1838 tag = strtol(ts + 1, &tc, 0);
1839 if (tc && !*tc && TAG_VALID_ZERO(tag))
1843 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1850 * It's not found in the dictionary, so we use
1851 * another method to create the attribute.
1853 da = dict_attrbyname(attrname);
1855 vp = pairmake_any(ctx, attrname, value, op);
1856 if (vp && vps) pairadd(vps, vp);
1860 /* Check for a tag in the 'Merit' format of:
1861 * :Tag:Value. Print an error if we already found
1862 * a tag in the Attribute.
1865 if (value && (*value == ':' && da->flags.has_tag)) {
1866 /* If we already found a tag, this is invalid */
1868 fr_strerror_printf("Duplicate tag %s for attribute %s",
1870 DEBUG("Duplicate tag %s for attribute %s\n",
1874 /* Colon found and attribute allows a tag */
1875 if (value[1] == '*' && value[2] == ':') {
1876 /* Wildcard tag for check items */
1881 tag = strtol(value + 1, &tc, 0);
1882 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1888 vp = pairalloc(ctx, da);
1893 vp->op = (op == 0) ? T_OP_EQ : op;
1901 case T_OP_CMP_FALSE:
1902 vp->vp_strvalue = NULL;
1904 value = NULL; /* ignore it! */
1908 * Regular expression comparison of integer attributes
1909 * does a STRING comparison of the names of their
1910 * integer attributes.
1912 case T_OP_REG_EQ: /* =~ */
1913 case T_OP_REG_NE: /* !~ */
1915 fr_strerror_printf("Regular expressions are not supported");
1921 * Someone else will fill in the value.
1931 compare = regcomp(®, value, REG_EXTENDED);
1933 regerror(compare, ®, buffer, sizeof(buffer));
1934 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1940 vp = pairmake(ctx, NULL, attribute, NULL, op);
1941 if (!vp) return NULL;
1943 if (pairmark_xlat(vp, value) < 0) {
1948 value = NULL; /* ignore it */
1954 * FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
1955 * then the user MAY have typed in the attribute name
1956 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1958 * We probably want to fix pairparsevalue to accept
1959 * octets as values for any attribute.
1961 if (value && !pairparsevalue(vp, value)) {
1966 if (vps) pairadd(vps, vp);
1970 /** Mark a valuepair for xlat expansion
1972 * Copies xlat source (unprocessed) string to valuepair value,
1973 * and sets value type.
1975 * @param vp to mark for expansion.
1976 * @param value to expand.
1977 * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
1979 int pairmark_xlat(VALUE_PAIR *vp, char const *value)
1984 * valuepair should not already have a value.
1986 if (vp->type != VT_NONE) {
1990 raw = talloc_strdup(vp, value);
1996 vp->value.xlat = raw;
2002 /** Read a single valuepair from a buffer, and advance the pointer
2004 * Sets *eol to T_EOL if end of line was encountered.
2006 * @param[in,out] ptr to read from and update.
2007 * @param[out] raw The struct to write the raw VALUE_PAIR to.
2008 * @return the last token read.
2010 FR_TOKEN pairread(char const **ptr, VALUE_PAIR_RAW *raw)
2014 FR_TOKEN ret = T_OP_INVALID, next, quote;
2017 if (!ptr || !*ptr || !raw) {
2018 fr_strerror_printf("Invalid arguments");
2019 return T_OP_INVALID;
2023 * Skip leading spaces
2026 while ((*p == ' ') || (*p == '\t')) p++;
2029 fr_strerror_printf("No token read where we expected "
2030 "an attribute name");
2031 return T_OP_INVALID;
2035 fr_strerror_printf("Read a comment instead of a token");
2041 * Try to get the attribute name.
2046 uint8_t const *t = (uint8_t const *) p;
2048 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2050 fr_strerror_printf("Attribute name too long");
2051 return T_OP_INVALID;
2055 * Only ASCII is allowed, and only a subset of that.
2057 if ((*t < 32) || (*t >= 128)) {
2059 fr_strerror_printf("Invalid attribute name");
2060 return T_OP_INVALID;
2064 * This is arguably easier than trying to figure
2065 * out which operators come after the attribute
2066 * name. Yes, our "lexer" is bad.
2068 if (!dict_attr_allowed_chars[(int) *t]) {
2076 * ASCII, but not a valid attribute name.
2078 if (!*raw->l_opand) goto invalid;
2081 * Look for tag (:#). This is different from :=, which
2084 if ((*p == ':') && (isdigit((int) p[1]))) {
2085 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2090 while (isdigit((int) *p)) {
2091 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2101 /* Now we should have an operator here. */
2102 raw->op = gettoken(ptr, buf, sizeof(buf));
2103 if (raw->op < T_EQSTART || raw->op > T_EQEND) {
2104 fr_strerror_printf("Expecting operator");
2106 return T_OP_INVALID;
2110 * Read value. Note that empty string values are allowed
2112 quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand));
2113 if (quote == T_EOL) {
2114 fr_strerror_printf("Failed to get value");
2116 return T_OP_INVALID;
2120 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
2124 next = gettoken(&p, buf, sizeof(buf));
2135 fr_strerror_printf("Expected end of line or comma");
2136 return T_OP_INVALID;
2144 case T_DOUBLE_QUOTED_STRING:
2146 * Only report as double quoted if it contained valid
2147 * a valid xlat expansion.
2149 p = strchr(raw->r_opand, '%');
2150 if (p && (p[1] == '{')) {
2153 raw->quote = T_SINGLE_QUOTED_STRING;
2166 /** Read one line of attribute/value pairs into a list.
2168 * The line may specify multiple attributes separated by commas.
2170 * @note If the function returns T_OP_INVALID, an error has occurred and
2171 * @note the valuepair list should probably be freed.
2173 * @param ctx for talloc
2174 * @param buffer to read valuepairs from.
2175 * @param list where the parsed VALUE_PAIRs will be appended.
2176 * @return the last token parsed, or T_OP_INVALID
2178 FR_TOKEN userparse(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
2180 VALUE_PAIR *vp, *head, **tail;
2182 FR_TOKEN last_token = T_OP_INVALID;
2183 FR_TOKEN previous_token;
2187 * We allow an empty line.
2189 if (buffer[0] == 0) {
2198 raw.l_opand[0] = '\0';
2199 raw.r_opand[0] = '\0';
2201 previous_token = last_token;
2203 last_token = pairread(&p, &raw);
2204 if (last_token == T_OP_INVALID) break;
2206 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
2207 vp = pairmake(ctx, NULL, raw.l_opand, NULL, raw.op);
2209 last_token = T_OP_INVALID;
2212 if (pairmark_xlat(vp, raw.r_opand) < 0) {
2214 last_token = T_OP_INVALID;
2218 vp = pairmake(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
2220 last_token = T_OP_INVALID;
2226 tail = &((*tail)->next);
2227 } while (*p && (last_token == T_COMMA));
2230 * Don't tell the caller that there was a comment.
2232 if (last_token == T_HASH) {
2233 last_token = previous_token;
2236 if (last_token == T_OP_INVALID) {
2239 pairadd(list, head);
2243 * And return the last token which we read.
2249 * Read valuepairs from the fp up to End-Of-File.
2251 * Hmm... this function is only used by radclient..
2253 VALUE_PAIR *readvp2(TALLOC_CTX *ctx, FILE *fp, bool *pfiledone, char const *errprefix)
2256 FR_TOKEN last_token = T_EOL;
2263 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
2265 * If we get a '\n' by itself, we assume that's
2266 * the end of that VP
2268 if ((buf[0] == '\n') && (list)) {
2271 if ((buf[0] == '\n') && (!list)) {
2276 * Comments get ignored
2278 if (buf[0] == '#') continue;
2281 * Read all of the attributes on the current line.
2284 last_token = userparse(ctx, buf, &vp);
2286 if (last_token != T_EOL) {
2287 fr_perror("%s", errprefix);
2298 if (error) pairfree(&list);
2306 * We leverage the fact that IPv4 and IPv6 prefixes both
2307 * have the same format:
2309 * reserved, prefix-len, data...
2311 static int paircmp_cidr(FR_TOKEN op, int bytes, uint8_t const *one, uint8_t const *two)
2317 * Handle the case of netmasks being identical.
2319 if (one[1] == two[1]) {
2322 compare = memcmp(one + 2, two + 2, bytes);
2325 * If they're identical return true for
2328 if ((compare == 0) &&
2329 ((op == T_OP_CMP_EQ) ||
2336 * Everything else returns false.
2338 * 10/8 == 24/8 --> false
2339 * 10/8 <= 24/8 --> false
2340 * 10/8 >= 24/8 --> false
2346 * Netmasks are different. That limits the
2347 * possible results, based on the operator.
2357 case T_OP_LT: /* 192/8 < 192.168/16 --> false */
2358 if (one[1] < two[1]) {
2364 case T_OP_GT: /* 192/16 > 192.168/8 --> false */
2365 if (one[1] > two[1]) {
2374 if (one[1] < two[1]) {
2381 * Do the check byte by byte. If the bytes are
2382 * identical, it MAY be a match. If they're different,
2383 * it is NOT a match.
2386 while (i < (2 + bytes)) {
2388 * All leading bytes are identical.
2390 if (common == 0) return true;
2393 * Doing bitmasks takes more work.
2395 if (common < 8) break;
2397 if (one[i] != two[i]) return false;
2405 mask <<= (8 - common);
2409 if ((one[i] & mask) == ((two[i] & mask))) {
2417 * Compare two pairs, using the operator from "one".
2419 * i.e. given two attributes, it does:
2421 * (two->data) (one->operator) (one->data)
2423 * e.g. "foo" != "bar"
2425 * Returns true (comparison is true), or false (comparison is not true);
2427 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
2436 return (two != NULL);
2438 case T_OP_CMP_FALSE:
2439 return (two == NULL);
2442 * One is a regex, compile it, print two to a string,
2443 * and then do string comparisons.
2452 char buffer[MAX_STRING_LEN * 4 + 1];
2454 compare = regcomp(®, one->vp_strvalue, REG_EXTENDED);
2456 regerror(compare, ®, buffer, sizeof(buffer));
2457 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2458 one->da->name, buffer);
2462 vp_prints_value(buffer, sizeof(buffer), two, 0);
2465 * Don't care about substring matches,
2468 compare = regexec(®, buffer, 0, NULL, 0);
2471 if (one->op == T_OP_REG_EQ) return (compare == 0);
2472 return (compare != 0);
2476 default: /* we're OK */
2480 return paircmp_op(two, one->op, one);
2483 /* Compare two attributes
2485 * @param[in] one the first attribute
2486 * @param[in] op the operator for comparison
2487 * @param[in] two the second attribute
2488 * @return < 0 if one is less than two, 0 if both are equal, > 0 if one is more than two.
2490 int paircmp_op(VALUE_PAIR const *one, FR_TOKEN op, VALUE_PAIR const *two)
2498 * Can't compare two attributes of differing types
2500 * FIXME: maybe do checks for IP OP IP/mask ??
2502 if (one->da->type != two->da->type) {
2503 return one->da->type - two->da->type;
2507 * After doing the previous check for special comparisons,
2508 * do the per-type comparison here.
2510 switch (one->da->type) {
2511 case PW_TYPE_ABINARY:
2512 case PW_TYPE_OCTETS:
2516 if (one->length > two->length) {
2517 length = one->length;
2519 length = two->length;
2523 compare = memcmp(one->vp_octets, two->vp_octets,
2525 if (compare != 0) break;
2529 * Contents are the same. The return code
2530 * is therefore the difference in lengths.
2532 * i.e. "0x00" is smaller than "0x0000"
2534 compare = one->length - two->length;
2538 case PW_TYPE_STRING:
2539 compare = strcmp(one->vp_strvalue, two->vp_strvalue);
2544 case PW_TYPE_INTEGER:
2546 if (one->vp_integer < two->vp_integer) {
2548 } else if (one->vp_integer == two->vp_integer) {
2555 case PW_TYPE_SIGNED:
2556 if (one->vp_signed < two->vp_signed) {
2558 } else if (one->vp_signed == two->vp_signed) {
2565 case PW_TYPE_INTEGER64:
2567 * Don't want integer overflow!
2569 if (one->vp_integer64 < two->vp_integer64) {
2571 } else if (one->vp_integer64 > two->vp_integer64) {
2578 case PW_TYPE_ETHERNET:
2579 compare = memcmp(&one->vp_ether, &two->vp_ether,
2580 sizeof(one->vp_ether));
2583 case PW_TYPE_IPADDR:
2584 if (ntohl(one->vp_ipaddr) < ntohl(two->vp_ipaddr)) {
2586 } else if (one->vp_ipaddr == two->vp_ipaddr) {
2593 case PW_TYPE_IPV6ADDR:
2594 compare = memcmp(&one->vp_ipv6addr, &two->vp_ipv6addr,
2595 sizeof(one->vp_ipv6addr));
2598 case PW_TYPE_IPV6PREFIX:
2599 return paircmp_cidr(op, 16,
2600 (uint8_t const *) &one->vp_ipv6prefix,
2601 (uint8_t const *) &two->vp_ipv6prefix);
2603 case PW_TYPE_IPV4PREFIX:
2604 return paircmp_cidr(op, 4,
2605 (uint8_t const *) &one->vp_ipv4prefix,
2606 (uint8_t const *) &two->vp_ipv4prefix);
2609 compare = memcmp(&one->vp_ifid, &two->vp_ifid, sizeof(one->vp_ifid));
2613 * None of the types below should be in the REQUEST
2615 case PW_TYPE_COMBO_IP: /* This should of been converted into IPADDR/IPV6ADDR */
2617 case PW_TYPE_EXTENDED:
2618 case PW_TYPE_LONG_EXTENDED:
2621 case PW_TYPE_INVALID: /* We should never see these */
2623 fr_assert(0); /* unknown type */
2627 * Do NOT add a default here, as new types are added
2628 * static analysis will warn us they're not handled
2633 * Now do the operator comparison.
2637 return (compare == 0);
2640 return (compare != 0);
2643 return (compare < 0);
2646 return (compare > 0);
2649 return (compare <= 0);
2652 return (compare >= 0);
2659 /** Copy data into an "octets" data type.
2661 * @param[in,out] vp to update
2662 * @param[in] src data to copy
2663 * @param[in] size of the data
2665 void pairmemcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2671 p = talloc_memdup(vp, src, size);
2674 memcpy(&q, &vp->vp_octets, sizeof(q));
2681 /** Reparent an allocated octet buffer to a VALUE_PAIR
2683 * @param[in,out] vp to update
2684 * @param[in] src buffer to steal.
2686 void pairmemsteal(VALUE_PAIR *vp, uint8_t const *src)
2691 memcpy(&q, &vp->vp_octets, sizeof(q));
2694 vp->vp_octets = talloc_steal(vp, src);
2696 vp->length = talloc_array_length(vp->vp_octets);
2699 /** Reparent an allocated char buffer to a VALUE_PAIR
2701 * @param[in,out] vp to update
2702 * @param[in] src buffer to steal.
2704 void pairstrsteal(VALUE_PAIR *vp, char const *src)
2709 memcpy(&q, &vp->vp_octets, sizeof(q));
2712 vp->vp_strvalue = talloc_steal(vp, src);
2714 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2717 /** Copy data into an "string" data type.
2719 * @param[in,out] vp to update
2720 * @param[in] src data to copy
2722 void pairstrcpy(VALUE_PAIR *vp, char const *src)
2728 p = talloc_strdup(vp, src);
2731 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2734 vp->vp_strvalue = p;
2736 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2740 /** Print data into an "string" data type.
2742 * @param[in,out] vp to update
2743 * @param[in] fmt the format string
2745 void pairsprintf(VALUE_PAIR *vp, char const *fmt, ...)
2753 p = talloc_vasprintf(vp, fmt, ap);
2758 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2761 vp->vp_strvalue = p;
2764 vp->length = talloc_array_length(vp->vp_strvalue) - 1;