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 static char const *months[] = {
51 "jan", "feb", "mar", "apr", "may", "jun",
52 "jul", "aug", "sep", "oct", "nov", "dec" };
54 #define attribute_eq(_x, _y) ((_x && _y) && (_x->da == _y->da) && (_x->tag == _y->tag))
58 * @note Do not call directly, use talloc_free instead.
63 static int _pairfree(VALUE_PAIR *vp) {
65 * The lack of DA means something has gone wrong
68 fr_strerror_printf("VALUE_PAIR has NULL DICT_ATTR pointer (probably already freed)");
70 * Only free the DICT_ATTR if it was dynamically allocated
71 * and was marked for free when the VALUE_PAIR is freed.
73 * @fixme This is an awful hack and needs to be removed once DICT_ATTRs are allocated by talloc.
75 } else if (vp->da->flags.vp_free) {
76 dict_attr_free(&(vp->da));
80 vp->vp_integer = FREE_MAGIC;
84 talloc_report_depth_cb(NULL, 0, -1, fr_talloc_verify_cb, NULL);
89 /** Dynamically allocate a new attribute
91 * Allocates a new attribute and a new dictionary attr if no DA is provided.
93 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
94 * @param[in] da Specifies the dictionary attribute to build the VP from.
95 * @return a new value pair or NULL if an error occurred.
97 VALUE_PAIR *pairalloc(TALLOC_CTX *ctx, DICT_ATTR const *da)
102 * Caller must specify a da else we don't know what the attribute type is.
104 if (!da) return NULL;
106 vp = talloc_zero(ctx, VALUE_PAIR);
108 fr_strerror_printf("Out of memory");
116 talloc_set_destructor(vp, _pairfree);
121 /** Create a new valuepair
123 * If attr and vendor match a dictionary entry then a VP with that DICT_ATTR
126 * If attr or vendor are uknown will call dict_attruknown to create a dynamic
127 * DICT_ATTR of PW_TYPE_OCTETS.
129 * Which type of DICT_ATTR the VALUE_PAIR was created with can be determined by
130 * checking @verbatim vp->da->flags.is_unknown @endverbatim.
132 * @param[in] ctx for allocated memory, usually a pointer to a RADIUS_PACKET
133 * @param[in] attr number.
134 * @param[in] vendor number.
135 * @return the new valuepair or NULL on error.
137 VALUE_PAIR *paircreate(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
141 da = dict_attrbyvalue(attr, vendor);
143 da = dict_attrunknown(attr, vendor, true);
149 return pairalloc(ctx, da);
152 /** Free memory used by a valuepair list.
154 * @todo TLV: needs to free all dependents of each VP freed.
156 void pairfree(VALUE_PAIR **vps)
165 for (vp = paircursor(&cursor, vps);
167 vp = pairnext(&cursor)) {
175 /** Mark malformed or unrecognised attributed as unknown
177 * @param vp to change DICT_ATTR of.
178 * @return 0 on success (or if already unknown) else -1 on error.
180 int pair2unknown(VALUE_PAIR *vp)
185 if (vp->da->flags.is_unknown) {
189 da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
199 /** Find the pair with the matching attribute
201 * @todo should take DAs and do a pointer comparison.
203 VALUE_PAIR *pairfind(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor,
209 for (i = paircursor(&cursor, &vp);
211 i = pairnext(&cursor)) {
213 if ((i->da->attr == attr) && (i->da->vendor == vendor)
214 && ((tag == TAG_ANY) || (i->da->flags.has_tag &&
223 /** Setup a cursor to iterate over attribute pairs
225 * @param cursor Where to initialise the cursor (uses existing structure).
226 * @param node to start from.
228 VALUE_PAIR *paircursorc(vp_cursor_t *cursor, VALUE_PAIR const * const *node)
230 memset(cursor, 0, sizeof(*cursor));
232 if (!node || !cursor) {
236 memcpy(&cursor->first, &node, sizeof(cursor->first));
237 cursor->current = *cursor->first;
239 if (cursor->current) {
240 VERIFY_VP(cursor->current);
241 cursor->next = cursor->current->next;
244 return cursor->current;
247 VALUE_PAIR *pairfirst(vp_cursor_t *cursor)
249 cursor->current = *cursor->first;
251 if (cursor->current) {
252 VERIFY_VP(cursor->current);
253 cursor->next = cursor->current->next;
254 if (cursor->next) VERIFY_VP(cursor->next);
255 cursor->found = NULL;
258 return cursor->current;
261 /** Iterate over attributes of a given type in the pairlist
265 VALUE_PAIR *pairfindnext(vp_cursor_t *cursor, unsigned int attr, unsigned int vendor, int8_t tag)
269 i = pairfind(!cursor->found ? cursor->current : cursor->found->next, attr, vendor, tag);
272 cursor->current = NULL;
277 cursor->next = i->next;
284 /** Retrieve the next VALUE_PAIR
288 VALUE_PAIR *pairnext(vp_cursor_t *cursor)
290 cursor->current = cursor->next;
291 if (cursor->current) {
292 VERIFY_VP(cursor->current);
295 * Set this now in case 'current' gets freed before
296 * pairnext is called again.
298 cursor->next = cursor->current->next;
301 * Next call to pairfindnext will start from the current
302 * position in the list, not the last found instance.
304 cursor->found = NULL;
307 return cursor->current;
310 VALUE_PAIR *paircurrent(vp_cursor_t *cursor)
312 if (cursor->current) {
313 VERIFY_VP(cursor->current);
316 return cursor->current;
321 * @todo don't use with pairdelete
323 void pairinsert(vp_cursor_t *cursor, VALUE_PAIR *add)
334 * Cursor was initialised with a pointer to a NULL value_pair
336 if (!*cursor->first) {
337 *cursor->first = add;
338 cursor->current = add;
339 cursor->next = cursor->current->next;
345 * We don't yet know where the last VALUE_PAIR is
347 * Assume current is closer to the end of the list and use that if available.
350 cursor->last = cursor->current ? cursor->current : *cursor->first;
353 VERIFY_VP(cursor->last);
356 * Something outside of the cursor added another VALUE_PAIR
358 if (cursor->last->next) {
359 for (i = cursor->last; i; i = i->next) {
366 * Either current was never set, or something iterated to the end of the
369 if (!cursor->current) {
370 cursor->current = add;
373 cursor->last->next = add;
376 /** Remove the current pair
378 * @todo this is really inefficient and should be fixed...
380 * @param cursor to remove the current pair from.
381 * @return NULL on error, else the VALUE_PAIR we just removed.
383 VALUE_PAIR *pairremove(vp_cursor_t *cursor)
385 VALUE_PAIR *vp, **last;
387 vp = paircurrent(cursor);
392 last = cursor->first;
393 while (*last != vp) {
394 last = &(*last)->next;
397 pairnext(cursor); /* Advance the cursor past the one were about to delete */
405 /** Delete matching pairs
407 * Delete matching pairs from the attribute list.
409 * @param[in,out] first VP in list.
410 * @param[in] attr to match.
411 * @param[in] vendor to match.
412 * @param[in] tag to match. TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
414 * @todo should take DAs and do a point comparison.
416 void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor,
419 VALUE_PAIR *i, *next;
420 VALUE_PAIR **last = first;
422 for(i = *first; i; i = next) {
425 if ((i->da->attr == attr) && (i->da->vendor == vendor) &&
427 (i->da->flags.has_tag && (i->tag == tag)))) {
436 /** Add a VP to the end of the list.
438 * Locates the end of 'first', and links an additional VP 'add' at the end.
440 * @param[in] first VP in linked list. Will add new VP to the end of this list.
441 * @param[in] add VP to add to list.
443 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
451 if (*first == NULL) {
455 for(i = *first; i->next; i = i->next)
460 /** Replace all matching VPs
462 * Walks over 'first', and replaces the first VP that matches 'replace'.
464 * @note Memory used by the VP being replaced will be freed.
465 * @note Will not work with unknown attributes.
467 * @param[in,out] first VP in linked list. Will search and replace in this list.
468 * @param[in] replace VP to replace.
470 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
472 VALUE_PAIR *i, *next;
473 VALUE_PAIR **prev = first;
477 if (*first == NULL) {
483 * Not an empty list, so find item if it is there, and
484 * replace it. Note, we always replace the first one, and
485 * we ignore any others that might exist.
487 for(i = *first; i; i = next) {
492 * Found the first attribute, replace it,
495 if ((i->da == replace->da) &&
496 (!i->da->flags.has_tag || (i->tag == replace->tag))
501 * Should really assert that replace->next == NULL
503 replace->next = next;
509 * Point to where the attribute should go.
515 * If we got here, we didn't find anything to replace, so
516 * stopped at the last item, which we just append to.
521 static void pairsort_split(VALUE_PAIR *source, VALUE_PAIR **front, VALUE_PAIR **back)
527 * Stopping condition - no more elements left to split
529 if (!source || !source->next) {
537 * Fast advances twice as fast as slow, so when it gets to the end,
538 * slow will point to the middle of the linked list.
556 static VALUE_PAIR *pairsort_merge(VALUE_PAIR *a, VALUE_PAIR *b, bool with_tag)
558 VALUE_PAIR *result = NULL;
564 * Compare the DICT_ATTRs and tags
566 if ((with_tag && (a->tag < b->tag)) || (a->da <= b->da)) {
568 result->next = pairsort_merge(a->next, b, with_tag);
571 result->next = pairsort_merge(a, b->next, with_tag);
577 /** Sort a linked list of VALUE_PAIRs using merge sort
579 * @param[in,out] vps List of VALUE_PAIRs to sort.
580 * @param[in] with_tag sort by tag then by DICT_ATTR
582 void pairsort(VALUE_PAIR **vps, bool with_tag)
584 VALUE_PAIR *head = *vps;
589 * If there's 0-1 elements it must already be sorted.
591 if (!head || !head->next) {
595 pairsort_split(head, &a, &b); /* Split into sublists */
596 pairsort(&a, with_tag); /* Traverse left */
597 pairsort(&b, with_tag); /* Traverse right */
600 * merge the two sorted lists together
602 *vps = pairsort_merge(a, b, with_tag);
605 /** Uses paircmp to verify all VALUE_PAIRs in list match the filter defined by check
607 * @param filter attributes to check list against.
608 * @param list attributes, probably a request or reply
610 bool pairvalidate(VALUE_PAIR *filter, VALUE_PAIR *list)
612 vp_cursor_t filter_cursor;
613 vp_cursor_t list_cursor;
615 VALUE_PAIR *check, *match, *last_check = NULL, *last_match;
617 if (!filter && !list) {
620 if (!filter || !list) {
625 * This allows us to verify the sets of validate and reply are equal
626 * i.e. we have a validate rule which matches every reply attribute.
628 * @todo this should be removed one we have sets and lists
630 pairsort(&filter, true);
631 pairsort(&list, true);
633 paircursor(&list_cursor, &list);
634 for (check = paircursor(&filter_cursor, &filter);
636 check = pairnext(&filter_cursor)) {
638 * Were processing check attributes of a new type.
640 if (attribute_eq(last_check, check)) {
642 * The lists have gone out of sync so we know the sets
643 * of list and filter are not equal.
645 if (!attribute_eq(paircurrent(&list_cursor), paircurrent(&filter_cursor))) {
649 last_match = paircurrent(&list_cursor);
650 paircursor(&list_cursor, &last_match); /* not strictly needed */
654 for (match = pairfirst(&list_cursor);
655 attribute_eq(match, check);
656 match = pairnext(&list_cursor)) {
658 * This attribute passed the filter
660 if (!paircmp(check, match)) {
667 * There were additional VALUE_PAIRS left in the list
669 if (paircurrent(&list_cursor)) {
676 /** Copy a single valuepair
678 * Allocate a new valuepair and copy the da from the old vp.
680 * @param[in] ctx for talloc
681 * @param[in] vp to copy.
682 * @return a copy of the input VP or NULL on error.
684 VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
688 if (!vp) return NULL;
692 n = pairalloc(ctx, vp->da);
694 fr_strerror_printf("out of memory");
698 memcpy(n, vp, sizeof(*n));
703 if (vp->type == VT_XLAT) {
704 n->value.xlat = talloc_strdup(n, n->value.xlat);
707 n->da = dict_attr_copy(vp->da, true);
715 if ((n->da->type == PW_TYPE_TLV) ||
716 (n->da->type == PW_TYPE_OCTETS)) {
717 if (n->vp_octets != NULL) {
718 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
721 } else if (n->da->type == PW_TYPE_STRING) {
722 if (n->vp_strvalue != NULL) {
724 * Equivalent to, and faster than strdup.
726 n->vp_strvalue = talloc_memdup(n, vp->vp_octets, n->length + 1);
733 /** Copy data from one VP to another
735 * Allocate a new pair using da, and copy over the value from the specified
738 * @todo Should be able to do type conversions.
740 * @param[in] ctx for talloc
741 * @param[in] da of new attribute to alloc.
742 * @param[in] vp to copy data from.
743 * @return the new valuepair.
745 VALUE_PAIR *paircopyvpdata(TALLOC_CTX *ctx, DICT_ATTR const *da, VALUE_PAIR const *vp)
749 if (!vp) return NULL;
754 * The types have to be identical, OR the "from" VP has
757 if (da->type != vp->da->type) {
760 VALUE_PAIR const **pvp;
762 if (vp->da->type == PW_TYPE_OCTETS) {
764 * Decode the data. It may be wrong!
766 if (rad_data2vp(da->attr, da->vendor, vp->vp_octets, vp->length, &n) < 0) {
775 * Else the destination type is octets
777 switch (vp->da->type) {
779 return NULL; /* can't do it */
781 case PW_TYPE_INTEGER:
785 case PW_TYPE_IPV6ADDR:
786 case PW_TYPE_IPV6PREFIX:
789 case PW_TYPE_ETHERNET:
791 case PW_TYPE_INTEGER64:
792 case PW_TYPE_IPV4PREFIX:
796 n = pairalloc(ctx, da);
799 p = talloc_array(n, uint8_t, dict_attr_sizes[vp->da->type][1] + 2);
802 length = rad_vp2attr(NULL, NULL, NULL, pvp, p, dict_attr_sizes[vp->da->type][1]);
808 pairmemcpy(n, p + 2, length - 2);
813 n = pairalloc(ctx, da);
818 memcpy(n, vp, sizeof(*n));
821 if (n->type == VT_XLAT) {
822 n->value.xlat = talloc_strdup(n, n->value.xlat);
825 switch (n->da->type) {
828 if (n->vp_octets != NULL) {
829 n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
834 if (n->vp_strvalue != NULL) {
835 n->vp_strvalue = talloc_memdup(n, vp->vp_strvalue, n->length + 1); /* NULL byte */
848 /** Copy matching pairs
850 * Copy pairs of a matching attribute number, vendor number and tag from the
851 * the input list to a new list, and returns the head of this list.
853 * @param[in] ctx for talloc
854 * @param[in] from whence to copy VALUE_PAIRs.
855 * @param[in] attr to match, if 0 input list will not be filtered by attr.
856 * @param[in] vendor to match.
857 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
858 * @return the head of the new VALUE_PAIR list or NULL on error.
860 VALUE_PAIR *paircopy2(TALLOC_CTX *ctx, VALUE_PAIR *from,
861 unsigned int attr, unsigned int vendor, int8_t tag)
863 vp_cursor_t src, dst;
865 VALUE_PAIR *out = NULL, *vp;
867 paircursor(&dst, &out);
868 for (vp = paircursor(&src, &from);
870 vp = pairnext(&src)) {
873 if ((attr > 0) && ((vp->da->attr != attr) || (vp->da->vendor != vendor))) {
877 if ((tag != TAG_ANY) && vp->da->flags.has_tag && (vp->tag != tag)) {
881 vp = paircopyvp(ctx, vp);
886 pairinsert(&dst, vp);
895 * Copy all pairs from 'from' regardless of tag, attribute or vendor.
897 * @param[in] ctx for new VALUE_PAIRs to be allocated in.
898 * @param[in] from whence to copy VALUE_PAIRs.
899 * @return the head of the new VALUE_PAIR list or NULL on error.
901 VALUE_PAIR *paircopy(TALLOC_CTX *ctx, VALUE_PAIR *from)
903 vp_cursor_t src, dst;
905 VALUE_PAIR *out = NULL, *vp;
907 paircursor(&dst, &out);
908 for (vp = paircursor(&src, &from);
910 vp = pairnext(&src)) {
912 vp = paircopyvp(ctx, vp);
917 pairinsert(&dst, vp); /* paircopy sets next pointer to NULL */
923 /** Move pairs from source list to destination list respecting operator
925 * @note This function does some additional magic that's probably not needed
926 * in most places. Consider using radius_pairmove in server code.
928 * @note pairfree should be called on the head of the source list to free
929 * unmoved attributes (if they're no longer needed).
931 * @note Does not respect tags when matching.
933 * @param[in] ctx for talloc
934 * @param[in,out] to destination list.
935 * @param[in,out] from source list.
937 * @see radius_pairmove
939 void pairmove(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from)
941 VALUE_PAIR **tailto, *i, *j, *next;
942 VALUE_PAIR *tailfrom = NULL;
944 int has_password = 0;
946 if (!to || !from || !*from) return;
949 * First, see if there are any passwords here, and
950 * point "tailto" to the end of the "to" list.
953 if (*to) for (i = *to; i; i = i->next) {
955 if (!i->da->vendor &&
956 (i->da->attr == PW_USER_PASSWORD ||
957 i->da->attr == PW_CRYPT_PASSWORD))
963 * Loop over the "from" list.
965 for (i = *from; i; i = next) {
970 * If there was a password in the "to" list,
971 * do not move any other password from the
972 * "from" to the "to" list.
974 if (has_password && !i->da->vendor &&
975 (i->da->attr == PW_USER_PASSWORD ||
976 i->da->attr == PW_CRYPT_PASSWORD)) {
983 * These are COMPARISON attributes
984 * from a check list, and are not
985 * supposed to be copied!
1005 * If the attribute is already present in "to",
1006 * do not move it from "from" to "to". We make
1007 * an exception for "Hint" which can appear multiple
1008 * times, and we never move "Fall-Through".
1010 if (i->da->attr == PW_FALL_THROUGH ||
1011 (i->da->attr != PW_HINT && i->da->attr != PW_FRAMED_ROUTE)) {
1014 found = pairfind(*to, i->da->attr, i->da->vendor,
1020 * If matching attributes are found,
1023 case T_OP_SUB: /* -= */
1025 if (!i->vp_strvalue[0] ||
1026 (strcmp(found->vp_strvalue,
1027 i->vp_strvalue) == 0)){
1034 * 'tailto' may have been
1038 for(j = *to; j; j = j->next) {
1046 case T_OP_EQ: /* = */
1048 * FIXME: Tunnel attributes with
1049 * different tags are different
1054 continue; /* with the loop */
1059 * If a similar attribute is found,
1060 * replace it with the new one. Otherwise,
1061 * add the new one to the list.
1063 case T_OP_SET: /* := */
1065 VALUE_PAIR *mynext = found->next;
1068 * Do NOT call pairdelete()
1069 * here, due to issues with
1070 * re-writing "request->username".
1072 * Everybody calls pairmove,
1073 * and expects it to work.
1074 * We can't update request->username
1075 * here, so instead we over-write
1076 * the vp that it's pointing to.
1078 memcpy(found, i, sizeof(*found));
1079 found->next = mynext;
1081 pairdelete(&found->next,
1083 found->da->vendor, TAG_ANY);
1086 * 'tailto' may have been
1089 for(j = found; j; j = j->next) {
1097 * Add the new element to the list, even
1098 * if similar ones already exist.
1101 case T_OP_ADD: /* += */
1106 tailfrom->next = next;
1111 * If ALL of the 'to' attributes have been deleted,
1112 * then ensure that the 'tail' is updated to point
1122 (void) talloc_steal(ctx, i);
1127 /** Move matching pairs between VALUE_PAIR lists
1129 * Move pairs of a matching attribute number, vendor number and tag from the
1130 * the input list to the output list.
1132 * @note pairfree should be called on the head of the old list to free unmoved
1133 attributes (if they're no longer needed).
1135 * @param[in] ctx for talloc
1136 * @param[in,out] to destination list.
1137 * @param[in,out] from source list.
1138 * @param[in] attr to match, if PW_VENDOR_SPECIFIC and vendor 0, only VSAs will
1139 * be copied. If 0 and 0, all attributes will match
1140 * @param[in] vendor to match.
1141 * @param[in] tag to match, TAG_ANY matches any tag, TAG_UNUSED matches tagless VPs.
1143 void pairfilter(TALLOC_CTX *ctx, VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor, int8_t tag)
1145 VALUE_PAIR *to_tail, *i, *next;
1146 VALUE_PAIR *iprev = NULL;
1149 * Find the last pair in the "to" list and put it in "to_tail".
1151 * @todo: replace the "if" with "VALUE_PAIR **tail"
1155 for(i = *to; i; i = i->next) {
1163 * Attr/vendor of 0 means "move them all".
1164 * It's better than "pairadd(foo,bar);bar=NULL"
1166 if ((vendor == 0) && (attr == 0)) {
1168 to_tail->next = *from;
1173 for (i = *from; i; i = i->next) {
1174 (void) talloc_steal(ctx, i);
1181 for(i = *from; i; i = next) {
1185 if ((tag != TAG_ANY) && i->da->flags.has_tag &&
1191 * vendor=0, attr = PW_VENDOR_SPECIFIC means
1192 * "match any vendor attribute".
1194 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
1196 * It's a VSA: move it over.
1198 if (i->da->vendor != 0) goto move;
1201 * It's Vendor-Specific: move it over.
1203 if (i->da->attr == attr) goto move;
1206 * It's not a VSA: ignore it.
1213 * If it isn't an exact match, ignore it.
1215 if (!((i->da->vendor == vendor) && (i->da->attr == attr))) {
1222 * Remove the attribute from the "from" list.
1230 * Add the attribute to the "to" list.
1238 (void) talloc_steal(ctx, i);
1244 * Sort of strtok/strsep function.
1246 static char *mystrtok(char **ptr, char const *sep)
1252 while (**ptr && strchr(sep, **ptr))
1257 while (**ptr && strchr(sep, **ptr) == NULL)
1265 * Turn printable string into time_t
1266 * Returns -1 on error, 0 on OK.
1268 static int gettime(char const *valstr, time_t *date)
1272 struct tm *tm, s_tm;
1279 * Test for unix timestamp date
1281 *date = strtoul(valstr, &tail, 10);
1282 if (*tail == '\0') {
1287 memset(tm, 0, sizeof(*tm));
1288 tm->tm_isdst = -1; /* don't know, and don't care about DST */
1290 strlcpy(buf, valstr, sizeof(buf));
1293 f[0] = mystrtok(&p, " \t");
1294 f[1] = mystrtok(&p, " \t");
1295 f[2] = mystrtok(&p, " \t");
1296 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
1297 if (!f[0] || !f[1] || !f[2]) return -1;
1300 * The time has a colon, where nothing else does.
1301 * So if we find it, bubble it to the back of the list.
1304 for (i = 0; i < 3; i++) {
1305 if (strchr(f[i], ':')) {
1315 * The month is text, which allows us to find it easily.
1318 for (i = 0; i < 3; i++) {
1319 if (isalpha( (int) *f[i])) {
1321 * Bubble the month to the front of the list
1327 for (i = 0; i < 12; i++) {
1328 if (strncasecmp(months[i], f[0], 3) == 0) {
1336 /* month not found? */
1337 if (tm->tm_mon == 12) return -1;
1340 * The year may be in f[1], or in f[2]
1342 tm->tm_year = atoi(f[1]);
1343 tm->tm_mday = atoi(f[2]);
1345 if (tm->tm_year >= 1900) {
1346 tm->tm_year -= 1900;
1350 * We can't use 2-digit years any more, they make it
1351 * impossible to tell what's the day, and what's the year.
1353 if (tm->tm_mday < 1900) return -1;
1356 * Swap the year and the day.
1359 tm->tm_year = tm->tm_mday - 1900;
1364 * If the day is out of range, die.
1366 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
1371 * There may be %H:%M:%S. Parse it in a hacky way.
1374 f[0] = f[3]; /* HH */
1375 f[1] = strchr(f[0], ':'); /* find : separator */
1376 if (!f[1]) return -1;
1378 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
1380 f[2] = strchr(f[1], ':'); /* find : separator */
1382 *(f[2]++) = '\0'; /* nuke it, and point to SS */
1383 tm->tm_sec = atoi(f[2]);
1384 } /* else leave it as zero */
1386 tm->tm_hour = atoi(f[0]);
1387 tm->tm_min = atoi(f[1]);
1391 * Returns -1 on error.
1394 if (t == (time_t) -1) return -1;
1401 static char const *hextab = "0123456789abcdef";
1404 * Parse a string value into a given VALUE_PAIR
1406 * FIXME: we probably want to fix this function to accept
1407 * octets as values for any type of attribute. We should then
1408 * double-check the parsed value, to be sure it's legal for that
1409 * type (length, etc.)
1411 static uint32_t getint(char const *value, char **end)
1413 if ((value[0] == '0') && (value[1] == 'x')) {
1414 return strtoul(value, end, 16);
1417 return strtoul(value, end, 10);
1420 static int check_for_whitespace(char const *value)
1423 if (!isspace((int) *value)) return 0;
1432 bool pairparsevalue(VALUE_PAIR *vp, char const *value)
1435 char const *cp, *cs;
1441 if (!value) return false;
1445 * It's a comparison, not a real VALUE_PAIR, copy the string over verbatim
1447 if ((vp->op == T_OP_REG_EQ) || (vp->op == T_OP_REG_NE)) {
1448 pairstrcpy(vp, value); /* Icky hacky ewww */
1452 switch(vp->da->type) {
1453 case PW_TYPE_STRING:
1457 p = talloc_strdup(vp, value);
1458 vp->vp_strvalue = p;
1496 c = '\\'; /* no cp++ */
1499 if ((cp[0] >= '0') &&
1505 (sscanf(cp, "%3o", &x) == 1)) {
1508 } /* else just do '\\' */
1515 vp->length = length;
1518 case PW_TYPE_IPADDR:
1520 * FIXME: complain if hostname
1521 * cannot be resolved, or resolve later!
1529 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
1530 fr_strerror_printf("Failed to find IP address for %s", cs);
1534 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1543 * Note that ALL integers are unsigned!
1545 vp->vp_integer = getint(value, &p);
1547 if (vp->vp_integer > 255) {
1548 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
1553 if (check_for_whitespace(p)) break;
1554 goto check_for_value;
1558 * Note that ALL integers are unsigned!
1560 vp->vp_integer = getint(value, &p);
1563 if (vp->vp_integer > 65535) {
1564 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1569 if (check_for_whitespace(p)) break;
1570 goto check_for_value;
1572 case PW_TYPE_INTEGER:
1574 * Note that ALL integers are unsigned!
1576 vp->vp_integer = getint(value, &p);
1579 if (check_for_whitespace(p)) break;
1583 * Look for the named value for the given
1586 if ((dval = dict_valbyname(vp->da->attr, vp->da->vendor, value)) == NULL) {
1587 fr_strerror_printf("Unknown value %s for attribute %s",
1588 value, vp->da->name);
1591 vp->vp_integer = dval->value;
1594 case PW_TYPE_INTEGER64:
1596 * Note that ALL integers are unsigned!
1598 if (sscanf(value, "%" PRIu64, &y) != 1) {
1599 fr_strerror_printf("Invalid value %s for attribute %s",
1600 value, vp->da->name);
1603 vp->vp_integer64 = y;
1605 length = strspn(value, "0123456789");
1606 if (check_for_whitespace(value + length)) break;
1612 * time_t may be 64 bits, whule vp_date
1613 * MUST be 32-bits. We need an
1614 * intermediary variable to handle
1619 if (gettime(value, &date) < 0) {
1620 fr_strerror_printf("failed to parse time string "
1630 case PW_TYPE_ABINARY:
1631 #ifdef WITH_ASCEND_BINARY
1632 if (strncasecmp(value, "0x", 2) == 0) {
1636 if (ascend_parse_filter(vp) < 0 ) {
1639 snprintf(buffer, sizeof(buffer), "failed to parse Ascend binary attribute: %s", fr_strerror());
1640 fr_strerror_printf("%s", buffer);
1646 * If Ascend binary is NOT defined,
1647 * then fall through to raw octets, so that
1648 * the user can at least make them by hand...
1651 /* raw octets: 0x01020304... */
1653 if (strcmp(value, "ANY") == 0) {
1656 } /* else it's hex */
1658 case PW_TYPE_OCTETS:
1659 if (strncasecmp(value, "0x", 2) == 0) {
1663 #ifdef WITH_ASCEND_BINARY
1668 vp->length = size >> 1;
1669 us = talloc_array(vp, uint8_t, vp->length);
1674 if ((size & 0x01) != 0) {
1675 fr_strerror_printf("Hex string is not an even length string");
1679 if (fr_hex2bin(us, cp, vp->length) != vp->length) {
1680 fr_strerror_printf("Invalid hex data");
1685 pairstrcpy(vp, value);
1690 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1691 fr_strerror_printf("failed to parse interface-id "
1692 "string \"%s\"", value);
1698 case PW_TYPE_IPV6ADDR:
1702 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1705 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1707 fr_strerror_printf("failed to parse IPv6 address "
1708 "string \"%s\": %s", value, buffer);
1711 vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
1712 vp->length = 16; /* length of IPv6 address */
1716 case PW_TYPE_IPV6PREFIX:
1717 p = strchr(value, '/');
1718 if (!p || ((p - value) >= 256)) {
1719 fr_strerror_printf("invalid IPv6 prefix "
1720 "string \"%s\"", value);
1723 unsigned int prefix;
1724 char buffer[256], *eptr;
1726 memcpy(buffer, value, p - value);
1727 buffer[p - value] = '\0';
1729 if (inet_pton(AF_INET6, buffer, vp->vp_ipv6prefix + 2) <= 0) {
1730 fr_strerror_printf("failed to parse IPv6 address "
1731 "string \"%s\"", value);
1735 prefix = strtoul(p + 1, &eptr, 10);
1736 if ((prefix > 128) || *eptr) {
1737 fr_strerror_printf("failed to parse IPv6 address "
1738 "string \"%s\"", value);
1741 vp->vp_ipv6prefix[1] = prefix;
1743 vp->length = 16 + 2;
1746 case PW_TYPE_IPV4PREFIX:
1747 p = strchr(value, '/');
1750 * 192.0.2.2 is parsed as if it was /32
1753 vp->vp_ipv4prefix[1] = 32;
1755 if (inet_pton(AF_INET, value, vp->vp_ipv4prefix + 2) <= 0) {
1756 fr_strerror_printf("failed to parse IPv4 address "
1757 "string \"%s\"", value);
1760 vp->length = sizeof(vp->vp_ipv4prefix);
1765 * Otherwise parse the prefix
1767 if ((p - value) >= 256) {
1768 fr_strerror_printf("invalid IPv4 prefix "
1769 "string \"%s\"", value);
1772 unsigned int prefix;
1773 char buffer[256], *eptr;
1775 memcpy(buffer, value, p - value);
1776 buffer[p - value] = '\0';
1778 if (inet_pton(AF_INET, buffer, vp->vp_ipv4prefix + 2) <= 0) {
1779 fr_strerror_printf("failed to parse IPv4 address "
1780 "string \"%s\"", value);
1784 prefix = strtoul(p + 1, &eptr, 10);
1785 if ((prefix > 32) || *eptr) {
1786 fr_strerror_printf("failed to parse IPv4 address "
1787 "string \"%s\"", value);
1790 vp->vp_ipv4prefix[1] = prefix;
1793 uint32_t addr, mask;
1795 memcpy(&addr, vp->vp_ipv4prefix + 2, sizeof(addr));
1797 mask <<= (32 - prefix);
1802 memcpy(vp->vp_ipv4prefix + 2, &addr, sizeof(addr));
1805 vp->length = sizeof(vp->vp_ipv4prefix);
1808 case PW_TYPE_ETHERNET:
1810 char const *c1, *c2;
1817 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1819 } else if ((cp[1] != '\0') &&
1822 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1823 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1825 if (*cp == ':') cp++;
1829 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1830 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1833 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1841 * Crazy polymorphic (IPv4/IPv6) attribute type for WiMAX.
1843 * We try and make is saner by replacing the original
1844 * da, with either an IPv4 or IPv6 da type.
1846 * These are not dynamic da, and will have the same vendor
1847 * and attribute as the original.
1849 case PW_TYPE_COMBO_IP:
1851 DICT_ATTR const *da;
1853 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) > 0) {
1854 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1860 vp->length = 16; /* length of IPv6 address */
1864 da = dict_attrbytype(vp->da->attr, vp->da->vendor,
1870 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1871 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1875 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1883 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1884 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1888 case PW_TYPE_TLV: /* don't use this! */
1889 if (strncasecmp(value, "0x", 2) != 0) {
1890 fr_strerror_printf("Invalid TLV specification");
1893 length = strlen(value + 2) / 2;
1894 if (vp->length < length) {
1895 TALLOC_FREE(vp->vp_tlv);
1897 vp->vp_tlv = talloc_array(vp, uint8_t, length);
1899 fr_strerror_printf("No memory");
1902 if (fr_hex2bin(vp->vp_tlv, value + 2, length) != length) {
1903 fr_strerror_printf("Invalid hex data in TLV");
1906 vp->length = length;
1913 fr_strerror_printf("unknown attribute type %d", vp->da->type);
1922 /** Create a valuepair from an ASCII attribute and value
1924 * Where the attribute name is in the form:
1926 * - Attr-%d.%d.%d...
1927 * - Vendor-%d-Attr-%d
1928 * - VendorName-Attr-%d
1930 * @param ctx for talloc
1931 * @param attribute name to parse.
1932 * @param value to parse (must be a hex string).
1933 * @param op to assign to new valuepair.
1934 * @return new valuepair or NULL on error.
1936 static VALUE_PAIR *pairmake_any(TALLOC_CTX *ctx,
1937 char const *attribute, char const *value,
1941 DICT_ATTR const *da;
1946 da = dict_attrunknownbyname(attribute, true);
1947 if (!da) return NULL;
1950 * Unknown attributes MUST be of type 'octets'
1952 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1953 fr_strerror_printf("Unknown attribute \"%s\" requires a hex "
1954 "string, not \"%s\"", attribute, value);
1956 dict_attr_free(&da);
1961 * We've now parsed the attribute properly, Let's create
1962 * it. This next stop also looks the attribute up in the
1963 * dictionary, and creates the appropriate type for it.
1965 vp = pairalloc(ctx, da);
1967 dict_attr_free(&da);
1971 vp->op = (op == 0) ? T_OP_EQ : op;
1973 if (!value) return vp;
1975 size = strlen(value + 2);
1976 vp->length = size >> 1;
1977 data = talloc_array(vp, uint8_t, vp->length);
1979 if (fr_hex2bin(data, value + 2, size) != vp->length) {
1980 fr_strerror_printf("Invalid hex string");
1985 vp->vp_octets = data;
1991 /** Create a VALUE_PAIR from ASCII strings
1993 * Converts an attribute string identifier (with an optional tag qualifier)
1994 * and value string into a VALUE_PAIR.
1996 * The string value is parsed according to the type of VALUE_PAIR being created.
1998 * @param[in] ctx for talloc
1999 * @param[in] vps list where the attribute will be added (optional)
2000 * @param[in] attribute name.
2001 * @param[in] value attribute value.
2002 * @param[in] op to assign to new VALUE_PAIR.
2003 * @return a new VALUE_PAIR.
2005 VALUE_PAIR *pairmake(TALLOC_CTX *ctx, VALUE_PAIR **vps,
2006 char const *attribute, char const *value, FR_TOKEN op)
2008 DICT_ATTR const *da;
2014 char const *attrname = attribute;
2017 * Check for tags in 'Attribute:Tag' format.
2022 ts = strrchr(attribute, ':');
2024 fr_strerror_printf("Invalid tag for attribute %s", attribute);
2029 strlcpy(buffer, attribute, sizeof(buffer));
2031 ts = strrchr(attrname, ':');
2032 if (!ts) return NULL;
2034 /* Colon found with something behind it */
2035 if (ts[1] == '*' && ts[2] == 0) {
2036 /* Wildcard tag for check items */
2039 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
2040 /* It's not a wild card tag */
2041 tag = strtol(ts + 1, &tc, 0);
2042 if (tc && !*tc && TAG_VALID_ZERO(tag))
2046 fr_strerror_printf("Invalid tag for attribute %s", attribute);
2053 * It's not found in the dictionary, so we use
2054 * another method to create the attribute.
2056 da = dict_attrbyname(attrname);
2058 vp = pairmake_any(ctx, attrname, value, op);
2059 if (vp && vps) pairadd(vps, vp);
2063 /* Check for a tag in the 'Merit' format of:
2064 * :Tag:Value. Print an error if we already found
2065 * a tag in the Attribute.
2068 if (value && (*value == ':' && da->flags.has_tag)) {
2069 /* If we already found a tag, this is invalid */
2071 fr_strerror_printf("Duplicate tag %s for attribute %s",
2073 DEBUG("Duplicate tag %s for attribute %s\n",
2077 /* Colon found and attribute allows a tag */
2078 if (value[1] == '*' && value[2] == ':') {
2079 /* Wildcard tag for check items */
2084 tag = strtol(value + 1, &tc, 0);
2085 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
2091 vp = pairalloc(ctx, da);
2096 vp->op = (op == 0) ? T_OP_EQ : op;
2104 case T_OP_CMP_FALSE:
2105 vp->vp_strvalue = NULL;
2107 value = NULL; /* ignore it! */
2111 * Regular expression comparison of integer attributes
2112 * does a STRING comparison of the names of their
2113 * integer attributes.
2115 case T_OP_REG_EQ: /* =~ */
2116 case T_OP_REG_NE: /* !~ */
2118 fr_strerror_printf("Regular expressions are not supported");
2124 * Someone else will fill in the value.
2134 compare = regcomp(®, value, REG_EXTENDED);
2136 regerror(compare, ®, buffer, sizeof(buffer));
2137 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2143 vp = pairmake(ctx, NULL, attribute, NULL, op);
2144 if (!vp) return NULL;
2146 if (pairmark_xlat(vp, value) < 0) {
2151 value = NULL; /* ignore it */
2157 * FIXME: if (strcasecmp(attribute, vp->da->name) != 0)
2158 * then the user MAY have typed in the attribute name
2159 * as Vendor-%d-Attr-%d, and the value MAY be octets.
2161 * We probably want to fix pairparsevalue to accept
2162 * octets as values for any attribute.
2164 if (value && !pairparsevalue(vp, value)) {
2169 if (vps) pairadd(vps, vp);
2173 /** Mark a valuepair for xlat expansion
2175 * Copies xlat source (unprocessed) string to valuepair value,
2176 * and sets value type.
2178 * @param vp to mark for expansion.
2179 * @param value to expand.
2180 * @return 0 if marking succeeded or -1 if vp already had a value, or OOM.
2182 int pairmark_xlat(VALUE_PAIR *vp, char const *value)
2187 * valuepair should not already have a value.
2189 if (vp->type != VT_NONE) {
2193 raw = talloc_strdup(vp, value);
2199 vp->value.xlat = raw;
2205 /** Read a single valuepair from a buffer, and advance the pointer
2207 * Sets *eol to T_EOL if end of line was encountered.
2209 * @param[in,out] ptr to read from and update.
2210 * @param[out] raw The struct to write the raw VALUE_PAIR to.
2211 * @return the last token read.
2213 FR_TOKEN pairread(char const **ptr, VALUE_PAIR_RAW *raw)
2217 FR_TOKEN ret = T_OP_INVALID, next, quote;
2220 if (!ptr || !*ptr || !raw) {
2221 fr_strerror_printf("Invalid arguments");
2222 return T_OP_INVALID;
2226 * Skip leading spaces
2229 while ((*p == ' ') || (*p == '\t')) p++;
2232 fr_strerror_printf("No token read where we expected "
2233 "an attribute name");
2234 return T_OP_INVALID;
2238 fr_strerror_printf("Read a comment instead of a token");
2244 * Try to get the attribute name.
2249 uint8_t const *t = (uint8_t const *) p;
2251 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2253 fr_strerror_printf("Attribute name too long");
2254 return T_OP_INVALID;
2258 * Only ASCII is allowed, and only a subset of that.
2260 if ((*t < 32) || (*t >= 128)) {
2262 fr_strerror_printf("Invalid attribute name");
2263 return T_OP_INVALID;
2267 * This is arguably easier than trying to figure
2268 * out which operators come after the attribute
2269 * name. Yes, our "lexer" is bad.
2271 if (!dict_attr_allowed_chars[(int) *t]) {
2279 * ASCII, but not a valid attribute name.
2281 if (!*raw->l_opand) goto invalid;
2284 * Look for tag (:#). This is different from :=, which
2287 if ((*p == ':') && (isdigit((int) p[1]))) {
2288 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2293 while (isdigit((int) *p)) {
2294 if (q >= (raw->l_opand + sizeof(raw->l_opand))) {
2304 /* Now we should have an operator here. */
2305 raw->op = gettoken(ptr, buf, sizeof(buf));
2306 if (raw->op < T_EQSTART || raw->op > T_EQEND) {
2307 fr_strerror_printf("Expecting operator");
2309 return T_OP_INVALID;
2313 * Read value. Note that empty string values are allowed
2315 quote = gettoken(ptr, raw->r_opand, sizeof(raw->r_opand));
2316 if (quote == T_EOL) {
2317 fr_strerror_printf("Failed to get value");
2319 return T_OP_INVALID;
2323 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
2327 next = gettoken(&p, buf, sizeof(buf));
2338 fr_strerror_printf("Expected end of line or comma");
2339 return T_OP_INVALID;
2347 case T_DOUBLE_QUOTED_STRING:
2349 * Only report as double quoted if it contained valid
2350 * a valid xlat expansion.
2352 p = strchr(raw->r_opand, '%');
2353 if (p && (p[1] == '{')) {
2356 raw->quote = T_SINGLE_QUOTED_STRING;
2369 /** Read one line of attribute/value pairs into a list.
2371 * The line may specify multiple attributes separated by commas.
2373 * @note If the function returns T_OP_INVALID, an error has occurred and
2374 * @note the valuepair list should probably be freed.
2376 * @param ctx for talloc
2377 * @param buffer to read valuepairs from.
2378 * @param list where the parsed VALUE_PAIRs will be appended.
2379 * @return the last token parsed, or T_OP_INVALID
2381 FR_TOKEN userparse(TALLOC_CTX *ctx, char const *buffer, VALUE_PAIR **list)
2383 VALUE_PAIR *vp, *head, **tail;
2385 FR_TOKEN last_token = T_OP_INVALID;
2386 FR_TOKEN previous_token;
2390 * We allow an empty line.
2400 raw.l_opand[0] = '\0';
2401 raw.r_opand[0] = '\0';
2403 previous_token = last_token;
2405 last_token = pairread(&p, &raw);
2406 if (last_token == T_OP_INVALID) break;
2408 if (raw.quote == T_DOUBLE_QUOTED_STRING) {
2409 vp = pairmake(ctx, NULL, raw.l_opand, NULL, raw.op);
2411 last_token = T_OP_INVALID;
2414 if (pairmark_xlat(vp, raw.r_opand) < 0) {
2420 vp = pairmake(ctx, NULL, raw.l_opand, raw.r_opand, raw.op);
2422 last_token = T_OP_INVALID;
2428 tail = &((*tail)->next);
2429 } while (*p && (last_token == T_COMMA));
2432 * Don't tell the caller that there was a comment.
2434 if (last_token == T_HASH) {
2435 last_token = previous_token;
2438 if (last_token == T_OP_INVALID) {
2441 pairadd(list, head);
2445 * And return the last token which we read.
2451 * Read valuepairs from the fp up to End-Of-File.
2453 * Hmm... this function is only used by radclient..
2455 VALUE_PAIR *readvp2(TALLOC_CTX *ctx, FILE *fp, int *pfiledone, char const *errprefix)
2458 FR_TOKEN last_token = T_EOL;
2465 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
2467 * If we get a '\n' by itself, we assume that's
2468 * the end of that VP
2470 if ((buf[0] == '\n') && (list)) {
2473 if ((buf[0] == '\n') && (!list)) {
2478 * Comments get ignored
2480 if (buf[0] == '#') continue;
2483 * Read all of the attributes on the current line.
2486 last_token = userparse(ctx, buf, &vp);
2488 if (last_token != T_EOL) {
2489 fr_perror("%s", errprefix);
2500 if (error) pairfree(&list);
2504 return error ? NULL: list;
2508 * We leverage the fact that IPv4 and IPv6 prefixes both
2509 * have the same format:
2511 * reserved, prefix-len, data...
2513 static int paircmp_cidr(FR_TOKEN op, int bytes, uint8_t const *one, uint8_t const *two)
2519 * Handle the case of netmasks being identical.
2521 if (one[1] == two[1]) {
2524 compare = memcmp(one + 2, two + 2, bytes);
2527 * If they're identical return true for
2530 if ((compare == 0) &&
2531 ((op == T_OP_CMP_EQ) ||
2538 * Everything else returns false.
2540 * 10/8 == 24/8 --> false
2541 * 10/8 <= 24/8 --> false
2542 * 10/8 >= 24/8 --> false
2548 * Netmasks are different. That limits the
2549 * possible results, based on the operator.
2559 case T_OP_LT: /* 192/8 < 192.168/16 --> false */
2560 if (one[1] < two[1]) {
2566 case T_OP_GT: /* 192/16 > 192.168/8 --> false */
2567 if (one[1] > two[1]) {
2576 if (one[1] < two[1]) {
2583 * Do the check byte by byte. If the bytes are
2584 * identical, it MAY be a match. If they're different,
2585 * it is NOT a match.
2588 while (i < (2 + bytes)) {
2590 * All leading bytes are identical.
2592 if (common == 0) return true;
2595 * Doing bitmasks takes more work.
2597 if (common < 8) break;
2599 if (one[i] != two[i]) return false;
2607 mask <<= (8 - common);
2611 if ((one[i] & mask) == ((two[i] & mask))) {
2619 * Compare two pairs, using the operator from "one".
2621 * i.e. given two attributes, it does:
2623 * (two->data) (one->operator) (one->data)
2625 * e.g. "foo" != "bar"
2627 * Returns true (comparison is true), or false (comparison is not true);
2629 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
2638 return (two != NULL);
2640 case T_OP_CMP_FALSE:
2641 return (two == NULL);
2644 * One is a regex, compile it, print two to a string,
2645 * and then do string comparisons.
2654 char buffer[MAX_STRING_LEN * 4 + 1];
2656 compare = regcomp(®, one->vp_strvalue, REG_EXTENDED);
2658 regerror(compare, ®, buffer, sizeof(buffer));
2659 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
2660 one->da->name, buffer);
2664 vp_prints_value(buffer, sizeof(buffer), two, 0);
2667 * Don't care about substring matches,
2670 compare = regexec(®, buffer, 0, NULL, 0);
2673 if (one->op == T_OP_REG_EQ) return (compare == 0);
2674 return (compare != 0);
2678 default: /* we're OK */
2682 return paircmp_op(two, one->op, one);
2685 /* Compare two attributes
2687 * @param[in] one the first attribute
2688 * @param[in] op the operator for comparison
2689 * @param[in] two the second attribute
2690 * @return true if ONE OP TWO is true, else false.
2692 int paircmp_op(VALUE_PAIR const *one, FR_TOKEN op, VALUE_PAIR const *two)
2700 * Can't compare two attributes of differing types
2702 * FIXME: maybe do checks for IP OP IP/mask ??
2704 if (one->da->type != two->da->type) {
2705 return one->da->type - two->da->type;
2709 * After doing the previous check for special comparisons,
2710 * do the per-type comparison here.
2712 switch (one->da->type) {
2713 case PW_TYPE_ABINARY:
2714 case PW_TYPE_OCTETS:
2718 if (one->length > two->length) {
2719 length = one->length;
2721 length = two->length;
2725 compare = memcmp(one->vp_octets, two->vp_octets,
2727 if (compare != 0) break;
2731 * Contents are the same. The return code
2732 * is therefore the difference in lengths.
2734 * i.e. "0x00" is smaller than "0x0000"
2736 compare = one->length - two->length;
2740 case PW_TYPE_STRING:
2741 compare = strcmp(one->vp_strvalue, two->vp_strvalue);
2746 case PW_TYPE_INTEGER:
2748 if (one->vp_integer < two->vp_integer) {
2750 } else if (one->vp_integer == two->vp_integer) {
2757 case PW_TYPE_INTEGER64:
2759 * Don't want integer overflow!
2761 if (one->vp_integer64 < two->vp_integer64) {
2763 } else if (one->vp_integer64 > two->vp_integer64) {
2769 case PW_TYPE_IPADDR:
2770 if (ntohl(one->vp_ipaddr) < ntohl(two->vp_ipaddr)) {
2772 } else if (one->vp_ipaddr == two->vp_ipaddr) {
2779 case PW_TYPE_IPV6ADDR:
2780 compare = memcmp(&one->vp_ipv6addr, &two->vp_ipv6addr,
2781 sizeof(one->vp_ipv6addr));
2784 case PW_TYPE_IPV6PREFIX:
2785 return paircmp_cidr(op, 16,
2786 (uint8_t const *) &one->vp_ipv6prefix,
2787 (uint8_t const *) &two->vp_ipv6prefix);
2789 case PW_TYPE_IPV4PREFIX:
2790 return paircmp_cidr(op, 4,
2791 (uint8_t const *) &one->vp_ipv4prefix,
2792 (uint8_t const *) &two->vp_ipv4prefix);
2795 compare = memcmp(&one->vp_ifid, &two->vp_ifid,
2796 sizeof(one->vp_ifid));
2800 return 0; /* unknown type */
2804 * Now do the operator comparison.
2808 return (compare == 0);
2811 return (compare != 0);
2814 return (compare < 0);
2817 return (compare > 0);
2820 return (compare <= 0);
2823 return (compare >= 0);
2832 /** Copy data into an "octets" data type.
2834 * @param[in,out] vp to update
2835 * @param[in] src data to copy
2836 * @param[in] size of the data
2838 void pairmemcpy(VALUE_PAIR *vp, uint8_t const *src, size_t size)
2844 p = talloc_memdup(vp, src, size);
2847 memcpy(&q, &vp->vp_octets, sizeof(q));
2854 /** Reparent an allocated octet buffer to a VALUE_PAIR
2856 * @param[in,out] vp to update
2857 * @param[in] src buffer to steal.
2859 void pairmemsteal(VALUE_PAIR *vp, uint8_t *src)
2864 memcpy(&q, &vp->vp_octets, sizeof(q));
2867 vp->vp_octets = talloc_steal(vp, src);
2869 vp->length = talloc_array_length(vp->vp_octets);
2872 /** Reparent an allocated char buffer to a VALUE_PAIR
2874 * @param[in,out] vp to update
2875 * @param[in] src buffer to steal.
2877 void pairstrsteal(VALUE_PAIR *vp, char *src)
2882 memcpy(&q, &vp->vp_octets, sizeof(q));
2885 vp->vp_strvalue = talloc_steal(vp, src);
2887 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2890 /** Copy data into an "string" data type.
2892 * @param[in,out] vp to update
2893 * @param[in] src data to copy
2895 void pairstrcpy(VALUE_PAIR *vp, char const *src)
2901 p = talloc_strdup(vp, src);
2904 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2907 vp->vp_strvalue = p;
2909 vp->length = talloc_array_length(vp->vp_strvalue) - 1;
2913 /** Print data into an "string" data type.
2915 * @param[in,out] vp to update
2916 * @param[in] fmt the format string
2918 void pairsprintf(VALUE_PAIR *vp, char const *fmt, ...)
2926 p = talloc_vasprintf(vp, fmt, ap);
2931 memcpy(&q, &vp->vp_strvalue, sizeof(q));
2934 vp->vp_strvalue = p;
2937 vp->length = talloc_array_length(vp->vp_strvalue) - 1;