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
23 #include <freeradius-devel/ident.h>
26 #include <freeradius-devel/libradius.h>
38 static const char *months[] = {
39 "jan", "feb", "mar", "apr", "may", "jun",
40 "jul", "aug", "sep", "oct", "nov", "dec" };
43 * This padding is necessary only for attributes that are NOT
44 * in the dictionary, and then only because the rest of the
45 * code accesses vp->name directly, rather than through an
48 * The name padding only has to large enough for:
50 * Vendor-65535-Attr-65535
52 * i.e. 23 characters, plus a zero. We add another 8 bytes for
53 * padding, because the VALUE_PAIR structure may be un-aligned.
55 * The result is that for the normal case, the server uses a less
56 * memory (36 bytes * number of VALUE_PAIRs).
58 #define FR_VP_NAME_PAD (32)
59 #define FR_VP_NAME_LEN (24)
61 VALUE_PAIR *pairalloc(DICT_ATTR *da)
67 * Not in the dictionary: the name is allocated AFTER
68 * the VALUE_PAIR struct.
70 if (!da) name_len = FR_VP_NAME_PAD;
72 vp = malloc(sizeof(*vp) + name_len);
74 memset(vp, 0, sizeof(*vp));
77 vp->attribute = da->attr;
78 vp->vendor = da->vendor;
81 vp->flags = da->flags;
85 vp->type = PW_TYPE_OCTETS;
87 memset(&vp->flags, 0, sizeof(vp->flags));
88 vp->flags.unknown_attr = 1;
100 case PW_TYPE_INTEGER:
108 vp->length = sizeof(vp->vp_ifid);
111 case PW_TYPE_IPV6ADDR:
112 vp->length = sizeof(vp->vp_ipv6addr);
115 case PW_TYPE_IPV6PREFIX:
116 vp->length = sizeof(vp->vp_ipv6prefix);
119 case PW_TYPE_ETHERNET:
120 vp->length = sizeof(vp->vp_ether);
128 case PW_TYPE_COMBO_IP:
139 * Create a new valuepair.
141 VALUE_PAIR *paircreate(int attr, int vendor, int type)
146 da = dict_attrbyvalue(attr, vendor);
147 if ((vp = pairalloc(da)) == NULL) {
148 fr_strerror_printf("out of memory");
151 vp->operator = T_OP_EQ;
154 * It isn't in the dictionary: update the name.
157 char *p = (char *) (vp + 1);
160 vp->attribute = attr;
162 vp->type = type; /* be forgiving */
164 if (!vp_print_name(p, FR_VP_NAME_LEN, attr, vendor)) {
174 * release the memory used by a single attribute-value pair
175 * just a wrapper around free() for now.
177 void pairbasicfree(VALUE_PAIR *pair)
179 if (pair->type == PW_TYPE_TLV) free(pair->vp_tlv);
180 /* clear the memory here */
181 memset(pair, 0, sizeof(*pair));
186 * Release the memory used by a list of attribute-value
187 * pairs, and sets the pair pointer to NULL.
189 void pairfree(VALUE_PAIR **pair_ptr)
191 VALUE_PAIR *next, *pair;
193 if (!pair_ptr) return;
196 while (pair != NULL) {
207 * Find the pair with the matching attribute
209 VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr, int vendor)
212 if ((first->attribute == attr) && (first->vendor == vendor)) {
223 * Delete the pair(s) with the matching attribute
225 void pairdelete(VALUE_PAIR **first, int attr, int vendor)
227 VALUE_PAIR *i, *next;
228 VALUE_PAIR **last = first;
230 for(i = *first; i; i = next) {
232 if ((i->attribute == attr) && (i->vendor == vendor)) {
242 * Add a pair at the end of a VALUE_PAIR list.
244 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
250 if (*first == NULL) {
254 for(i = *first; i->next; i = i->next)
260 * Add or replace a pair at the end of a VALUE_PAIR list.
262 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
264 VALUE_PAIR *i, *next;
265 VALUE_PAIR **prev = first;
267 if (*first == NULL) {
273 * Not an empty list, so find item if it is there, and
274 * replace it. Note, we always replace the first one, and
275 * we ignore any others that might exist.
277 for(i = *first; i; i = next) {
281 * Found the first attribute, replace it,
284 if ((i->attribute == replace->attribute) &&
285 (i->vendor == replace->vendor)) {
289 * Should really assert that replace->next == NULL
291 replace->next = next;
297 * Point to where the attribute should go.
303 * If we got here, we didn't find anything to replace, so
304 * stopped at the last item, which we just append to.
313 VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
318 if (!vp->flags.unknown_attr) {
321 name_len = FR_VP_NAME_PAD;
324 if ((n = malloc(sizeof(*n) + name_len)) == NULL) {
325 fr_strerror_printf("out of memory");
328 memcpy(n, vp, sizeof(*n) + name_len);
331 if ((n->type == PW_TYPE_TLV) &&
332 (n->vp_tlv != NULL)) {
333 n->vp_tlv = malloc(n->length);
334 memcpy(n->vp_tlv, vp->vp_tlv, n->length);
342 * Copy just a certain type of pairs.
344 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr, int vendor)
346 VALUE_PAIR *first, *n, **last;
353 !((vp->attribute == attr) && (vp->vendor == vendor))) {
359 if (!n) return first;
371 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
373 return paircopy2(vp, -1, 0);
378 * Move attributes from one list to the other
379 * if not already present.
381 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
383 VALUE_PAIR **tailto, *i, *j, *next;
384 VALUE_PAIR *tailfrom = NULL;
386 int has_password = 0;
389 * First, see if there are any passwords here, and
390 * point "tailto" to the end of the "to" list.
393 for(i = *to; i; i = i->next) {
394 if (i->attribute == PW_USER_PASSWORD ||
395 i->attribute == PW_CRYPT_PASSWORD)
401 * Loop over the "from" list.
403 for(i = *from; i; i = next) {
407 * If there was a password in the "to" list,
408 * do not move any other password from the
409 * "from" to the "to" list.
412 (i->attribute == PW_USER_PASSWORD ||
413 i->attribute == PW_CRYPT_PASSWORD)) {
418 switch (i->operator) {
420 * These are COMPARISON attributes
421 * from a check list, and are not
422 * supposed to be copied!
440 * If the attribute is already present in "to",
441 * do not move it from "from" to "to". We make
442 * an exception for "Hint" which can appear multiple
443 * times, and we never move "Fall-Through".
445 if (i->attribute == PW_FALL_THROUGH ||
446 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
448 found = pairfind(*to, i->attribute, i->vendor);
449 switch (i->operator) {
452 * If matching attributes are found,
455 case T_OP_SUB: /* -= */
457 if (!i->vp_strvalue[0] ||
458 (strcmp((char *)found->vp_strvalue,
459 (char *)i->vp_strvalue) == 0)){
460 pairdelete(to, found->attribute, found->vendor);
463 * 'tailto' may have been
467 for(j = *to; j; j = j->next) {
476 /* really HAVE_REGEX_H */
479 * Attr-Name =~ "s/find/replace/"
481 * Very bad code. Barely working,
487 (i->vp_strvalue[0] == 's')) {
494 p = i->vp_strvalue + 1;
495 q = strchr(p + 1, *p);
496 if (!q || (q[strlen(q) - 1] != *p)) {
500 str = strdup(i->vp_strvalue + 2);
503 q[strlen(q) - 1] = '\0';
505 regcomp(®, str, 0);
506 if (regexec(®, found->vp_strvalue,
508 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
509 found->vp_strvalue, match[0].rm_so,
516 tailfrom = i; /* don't copy it over */
520 case T_OP_EQ: /* = */
522 * FIXME: Tunnel attributes with
523 * different tags are different
528 continue; /* with the loop */
533 * If a similar attribute is found,
534 * replace it with the new one. Otherwise,
535 * add the new one to the list.
537 case T_OP_SET: /* := */
539 VALUE_PAIR *mynext = found->next;
542 * Do NOT call pairdelete()
543 * here, due to issues with
544 * re-writing "request->username".
546 * Everybody calls pairmove,
547 * and expects it to work.
548 * We can't update request->username
549 * here, so instead we over-write
550 * the vp that it's pointing to.
552 memcpy(found, i, sizeof(*found));
553 found->next = mynext;
555 pairdelete(&found->next, found->attribute, found->vendor);
558 * 'tailto' may have been
561 for(j = found; j; j = j->next) {
569 * Add the new element to the list, even
570 * if similar ones already exist.
573 case T_OP_ADD: /* += */
578 tailfrom->next = next;
583 * If ALL of the 'to' attributes have been deleted,
584 * then ensure that the 'tail' is updated to point
599 * Move one kind of attributes from one list to the other
601 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr, int vendor)
603 VALUE_PAIR *to_tail, *i, *next;
604 VALUE_PAIR *iprev = NULL;
607 * Find the last pair in the "to" list and put it in "to_tail".
611 for(i = *to; i; i = i->next)
616 for(i = *from; i; i = next) {
620 * vendor=0, attr = PW_VENDOR_SPECIFIC means
621 * "match any vendor attribute".
623 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
625 * It's a VSA: move it over.
627 if (i->vendor != 0) goto move;
630 * It's Vendor-Specific: move it over.
632 if (i->attribute == attr) goto move;
635 * It's not a VSA: ignore it.
642 * If it isn't an exact match, ignore it.
644 if (!((i->vendor == vendor) && (i->attribute == attr))) {
651 * Remove the attribute from the "from" list.
659 * Add the attribute to the "to" list.
672 * Sort of strtok/strsep function.
674 static char *mystrtok(char **ptr, const char *sep)
680 while (**ptr && strchr(sep, **ptr))
685 while (**ptr && strchr(sep, **ptr) == NULL)
693 * Turn printable string into time_t
694 * Returns -1 on error, 0 on OK.
696 static int gettime(const char *valstr, time_t *date)
707 * Test for unix timestamp date
709 *date = strtoul(valstr, &tail, 10);
715 memset(tm, 0, sizeof(*tm));
716 tm->tm_isdst = -1; /* don't know, and don't care about DST */
718 strlcpy(buf, valstr, sizeof(buf));
721 f[0] = mystrtok(&p, " \t");
722 f[1] = mystrtok(&p, " \t");
723 f[2] = mystrtok(&p, " \t");
724 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
725 if (!f[0] || !f[1] || !f[2]) return -1;
728 * The time has a colon, where nothing else does.
729 * So if we find it, bubble it to the back of the list.
732 for (i = 0; i < 3; i++) {
733 if (strchr(f[i], ':')) {
743 * The month is text, which allows us to find it easily.
746 for (i = 0; i < 3; i++) {
747 if (isalpha( (int) *f[i])) {
749 * Bubble the month to the front of the list
755 for (i = 0; i < 12; i++) {
756 if (strncasecmp(months[i], f[0], 3) == 0) {
764 /* month not found? */
765 if (tm->tm_mon == 12) return -1;
768 * The year may be in f[1], or in f[2]
770 tm->tm_year = atoi(f[1]);
771 tm->tm_mday = atoi(f[2]);
773 if (tm->tm_year >= 1900) {
778 * We can't use 2-digit years any more, they make it
779 * impossible to tell what's the day, and what's the year.
781 if (tm->tm_mday < 1900) return -1;
784 * Swap the year and the day.
787 tm->tm_year = tm->tm_mday - 1900;
792 * If the day is out of range, die.
794 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
799 * There may be %H:%M:%S. Parse it in a hacky way.
802 f[0] = f[3]; /* HH */
803 f[1] = strchr(f[0], ':'); /* find : separator */
804 if (!f[1]) return -1;
806 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
808 f[2] = strchr(f[1], ':'); /* find : separator */
810 *(f[2]++) = '\0'; /* nuke it, and point to SS */
811 tm->tm_sec = atoi(f[2]);
812 } /* else leave it as zero */
814 tm->tm_hour = atoi(f[0]);
815 tm->tm_min = atoi(f[1]);
819 * Returns -1 on error.
822 if (t == (time_t) -1) return -1;
829 static const char *hextab = "0123456789abcdef";
832 * Parse a string value into a given VALUE_PAIR
834 * FIXME: we probably want to fix this function to accept
835 * octets as values for any type of attribute. We should then
836 * double-check the parsed value, to be sure it's legal for that
837 * type (length, etc.)
839 static uint32_t getint(const char *value, char **end)
841 if ((value[0] == '0') && (value[1] == 'x')) {
842 return strtoul(value, end, 16);
845 return strtoul(value, end, 10);
848 static int check_for_whitespace(const char *value)
851 if (!isspace((int) *value)) return 0;
860 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
868 if (!value) return NULL;
871 * Even for integers, dates and ip addresses we
872 * keep the original string in vp->vp_strvalue.
874 if (vp->type != PW_TYPE_TLV) {
875 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
876 vp->length = strlen(vp->vp_strvalue);
888 while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) {
918 c = '\\'; /* no cp++ */
921 if ((cp[0] >= '0') &&
927 (sscanf(cp, "%3o", &x) == 1)) {
930 } /* else just do '\\' */
936 vp->vp_strvalue[length] = '\0';
942 * It's a comparison, not a real IP.
944 if ((vp->operator == T_OP_REG_EQ) ||
945 (vp->operator == T_OP_REG_NE)) {
950 * FIXME: complain if hostname
951 * cannot be resolved, or resolve later!
954 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
955 cs = s = strdup(value);
959 vp->flags.addport = 1;
968 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
970 fr_strerror_printf("Failed to find IP address for %s", cs);
974 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
984 * Note that ALL integers are unsigned!
986 vp->vp_integer = getint(value, &p);
988 if (vp->vp_integer > 255) {
989 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
994 if (check_for_whitespace(p)) break;
995 goto check_for_value;
999 * Note that ALL integers are unsigned!
1001 vp->vp_integer = getint(value, &p);
1004 if (vp->vp_integer > 65535) {
1005 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1010 if (check_for_whitespace(p)) break;
1011 goto check_for_value;
1013 case PW_TYPE_INTEGER:
1015 * Note that ALL integers are unsigned!
1017 vp->vp_integer = getint(value, &p);
1020 if (check_for_whitespace(p)) break;
1024 * Look for the named value for the given
1027 if ((dval = dict_valbyname(vp->attribute, vp->vendor, value)) == NULL) {
1028 fr_strerror_printf("Unknown value %s for attribute %s",
1032 vp->vp_integer = dval->value;
1038 * time_t may be 64 bits, whule vp_date
1039 * MUST be 32-bits. We need an
1040 * intermediary variable to handle
1045 if (gettime(value, &date) < 0) {
1046 fr_strerror_printf("failed to parse time string "
1056 case PW_TYPE_ABINARY:
1057 #ifdef ASCEND_BINARY
1058 if (strncasecmp(value, "0x", 2) == 0) {
1059 vp->type = PW_TYPE_OCTETS;
1063 if (ascend_parse_filter(vp) < 0 ) {
1064 fr_strerror_printf("failed to parse Ascend binary attribute: %s",
1071 * If Ascend binary is NOT defined,
1072 * then fall through to raw octets, so that
1073 * the user can at least make them by hand...
1077 /* raw octets: 0x01020304... */
1078 case PW_TYPE_OCTETS:
1079 if (strncasecmp(value, "0x", 2) == 0) {
1087 * There is only one character,
1090 if ((strlen(cp) & 0x01) != 0) {
1091 fr_strerror_printf("Hex string is not an even length string.");
1097 (vp->length < MAX_STRING_LEN)) {
1100 if (sscanf(cp, "%02x", &tmp) != 1) {
1101 fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]);
1113 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1114 fr_strerror_printf("failed to parse interface-id "
1115 "string \"%s\"", value);
1121 case PW_TYPE_IPV6ADDR:
1125 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1128 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1130 fr_strerror_printf("failed to parse IPv6 address "
1131 "string \"%s\": %s", value, buffer);
1134 vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
1135 vp->length = 16; /* length of IPv6 address */
1139 case PW_TYPE_IPV6PREFIX:
1140 p = strchr(value, '/');
1141 if (!p || ((p - value) >= 256)) {
1142 fr_strerror_printf("invalid IPv6 prefix "
1143 "string \"%s\"", value);
1146 unsigned int prefix;
1147 char buffer[256], *eptr;
1149 memcpy(buffer, value, p - value);
1150 buffer[p - value] = '\0';
1152 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1153 fr_strerror_printf("failed to parse IPv6 address "
1154 "string \"%s\"", value);
1158 prefix = strtoul(p + 1, &eptr, 10);
1159 if ((prefix > 128) || *eptr) {
1160 fr_strerror_printf("failed to parse IPv6 address "
1161 "string \"%s\"", value);
1164 vp->vp_octets[1] = prefix;
1166 vp->vp_octets[0] = '\0';
1167 vp->length = 16 + 2;
1170 case PW_TYPE_ETHERNET:
1172 const char *c1, *c2;
1179 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1181 } else if ((cp[1] != '\0') &&
1184 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1185 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1187 if (*cp == ':') cp++;
1191 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1192 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1195 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1202 case PW_TYPE_COMBO_IP:
1203 if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
1204 vp->type = PW_TYPE_IPV6ADDR;
1205 vp->length = 16; /* length of IPv6 address */
1206 vp->vp_strvalue[vp->length] = '\0';
1211 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1212 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1216 vp->type = PW_TYPE_IPADDR;
1217 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1222 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1223 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1227 case PW_TYPE_TLV: /* don't use this! */
1228 if (strncasecmp(value, "0x", 2) != 0) {
1229 fr_strerror_printf("Invalid TLV specification");
1232 length = strlen(value + 2) / 2;
1233 if (vp->length < length) {
1237 vp->vp_tlv = malloc(length);
1239 fr_strerror_printf("No memory");
1242 if (fr_hex2bin(value + 2, vp->vp_tlv,
1243 length) != length) {
1244 fr_strerror_printf("Invalid hex data in TLV");
1247 vp->length = length;
1254 fr_strerror_printf("unknown attribute type %d", vp->type);
1262 * Create a VALUE_PAIR from an ASCII attribute and value,
1263 * where the attribute name is in the form:
1267 * VendorName-Attr-%d
1269 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1274 const char *p = attribute;
1279 * Unknown attributes MUST be of type 'octets'
1281 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1282 fr_strerror_printf("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1289 * Pull off vendor prefix first.
1291 if (strncasecmp(p, "Attr-", 5) != 0) {
1292 if (strncasecmp(p, "Vendor-", 7) == 0) {
1293 vendor = (int) strtol(p + 7, &q, 10);
1294 if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
1295 fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
1301 } else { /* must be vendor name */
1307 fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", attribute);
1311 if ((size_t) (q - p) >= sizeof(buffer)) {
1312 fr_strerror_printf("Vendor name too long in attribute name \"%s\"", attribute);
1316 memcpy(buffer, p, (q - p));
1317 buffer[q - p] = '\0';
1319 vendor = dict_vendorbyname(buffer);
1321 fr_strerror_printf("Unknown vendor name in attribute name \"%s\"", attribute);
1329 fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1338 if (strncasecmp(p, "Attr-", 5) != 0) {
1339 fr_strerror_printf("Invalid format in attribute name \"%s\"", attribute);
1343 attr = strtol(p + 5, &q, 10);
1346 * Invalid, or trailing text after number.
1348 if ((attr == 0) || *q) {
1349 fr_strerror_printf("Invalid value in attribute name \"%s\"", attribute);
1354 * Double-check the size of attr.
1357 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1362 fr_strerror_printf("Invalid attribute number in attribute name \"%s\"", attribute);
1366 } else switch (dv->type) {
1368 if (attr > 255) goto attr_error;
1372 if (attr > 65535) goto attr_error;
1379 fr_strerror_printf("Internal sanity check failed");
1385 * We've now parsed the attribute properly, Let's create
1386 * it. This next stop also looks the attribute up in the
1387 * dictionary, and creates the appropriate type for it.
1389 if ((vp = paircreate(attr, vendor, PW_TYPE_OCTETS)) == NULL) {
1390 fr_strerror_printf("out of memory");
1394 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1395 if (!value) return vp;
1397 size = strlen(value + 2);
1400 * We may be reading something like Attr-5. i.e.
1401 * who-ever wrote the text didn't understand it, but we
1406 if (size == (vp->length * 2)) break;
1407 vp->type = PW_TYPE_OCTETS;
1410 case PW_TYPE_STRING:
1411 case PW_TYPE_OCTETS:
1412 case PW_TYPE_ABINARY:
1413 vp->length = size >> 1;
1417 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1418 fr_strerror_printf("Invalid hex string");
1424 * Move contents around based on type. This is
1425 * to work around the historical use of "lvalue".
1429 case PW_TYPE_IPADDR:
1430 case PW_TYPE_INTEGER:
1431 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1432 vp->vp_strvalue[0] = '\0';
1444 * Create a VALUE_PAIR from an ASCII attribute and value.
1446 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1454 const char *attrname = attribute;
1457 * Check for tags in 'Attribute:Tag' format.
1462 ts = strrchr(attribute, ':');
1464 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1469 strlcpy(buffer, attribute, sizeof(buffer));
1471 ts = strrchr(attrname, ':');
1473 /* Colon found with something behind it */
1474 if (ts[1] == '*' && ts[2] == 0) {
1475 /* Wildcard tag for check items */
1478 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1479 /* It's not a wild card tag */
1480 tag = strtol(ts + 1, &tc, 0);
1481 if (tc && !*tc && TAG_VALID_ZERO(tag))
1485 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1492 * It's not found in the dictionary, so we use
1493 * another method to create the attribute.
1495 if ((da = dict_attrbyname(attrname)) == NULL) {
1496 return pairmake_any(attrname, value, operator);
1499 if ((vp = pairalloc(da)) == NULL) {
1500 fr_strerror_printf("out of memory");
1503 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1505 /* Check for a tag in the 'Merit' format of:
1506 * :Tag:Value. Print an error if we already found
1507 * a tag in the Attribute.
1510 if (value && (*value == ':' && da->flags.has_tag)) {
1511 /* If we already found a tag, this is invalid */
1513 fr_strerror_printf("Duplicate tag %s for attribute %s",
1515 DEBUG("Duplicate tag %s for attribute %s\n",
1520 /* Colon found and attribute allows a tag */
1521 if (value[1] == '*' && value[2] == ':') {
1522 /* Wildcard tag for check items */
1527 tag = strtol(value + 1, &tc, 0);
1528 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1536 vp->flags.tag = tag;
1539 switch (vp->operator) {
1544 * For =* and !* operators, the value is irrelevant
1548 case T_OP_CMP_FALSE:
1549 vp->vp_strvalue[0] = '\0';
1555 * Regular expression comparison of integer attributes
1556 * does a STRING comparison of the names of their
1557 * integer attributes.
1559 case T_OP_REG_EQ: /* =~ */
1560 case T_OP_REG_NE: /* !~ */
1562 fr_strerror_printf("No regular expression found in %s",
1568 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1569 vp->length = strlen(vp->vp_strvalue);
1571 * If anything goes wrong, this is a run-time error,
1572 * not a compile-time error.
1579 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1580 * then the user MAY have typed in the attribute name
1581 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1583 * We probably want to fix pairparsevalue to accept
1584 * octets as values for any attribute.
1586 if (value && (pairparsevalue(vp, value) == NULL)) {
1598 static const int valid_attr_name[256] = {
1599 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1600 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1601 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1602 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1603 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1604 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1605 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1606 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1607 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1608 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1609 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1610 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1611 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1612 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1613 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1614 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1618 * Read a valuepair from a buffer, and advance pointer.
1619 * Sets *eol to T_EOL if end of line was encountered.
1621 VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol)
1625 char value[1024], *q;
1627 FR_TOKEN token, t, xlat;
1631 *eol = T_OP_INVALID;
1634 while ((*p == ' ') || (*p == '\t')) p++;
1637 *eol = T_OP_INVALID;
1638 fr_strerror_printf("No token read where we expected an attribute name");
1644 fr_strerror_printf("Read a comment instead of a token");
1649 for (len = 0; len < sizeof(attr); len++) {
1650 if (valid_attr_name[(int)*p]) {
1657 if (len == sizeof(attr)) {
1658 *eol = T_OP_INVALID;
1659 fr_strerror_printf("Attribute name is too long");
1664 * We may have Foo-Bar:= stuff, so back up.
1666 if ((len > 0) && (attr[len - 1] == ':')) {
1674 /* Now we should have an operator here. */
1675 token = gettoken(ptr, buf, sizeof(buf));
1676 if (token < T_EQSTART || token > T_EQEND) {
1677 fr_strerror_printf("expecting operator");
1681 /* Read value. Note that empty string values are allowed */
1682 xlat = gettoken(ptr, value, sizeof(value));
1683 if (xlat == T_EOL) {
1684 fr_strerror_printf("failed to get value");
1689 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1692 t = gettoken(&p, buf, sizeof(buf));
1693 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1694 fr_strerror_printf("Expected end of line or comma");
1706 * Make the full pair now.
1709 vp = pairmake(attr, value, token);
1715 case T_DOUBLE_QUOTED_STRING:
1716 p = strchr(value, '%');
1717 if (p && (p[1] == '{')) {
1718 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1719 fr_strerror_printf("Value too long");
1722 vp = pairmake(attr, NULL, token);
1724 *eol = T_OP_INVALID;
1728 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1729 vp->flags.do_xlat = 1;
1733 * Parse && escape it, as defined by the
1736 vp = pairmake(attr, value, token);
1738 *eol = T_OP_INVALID;
1744 case T_SINGLE_QUOTED_STRING:
1745 vp = pairmake(attr, NULL, token);
1747 *eol = T_OP_INVALID;
1752 * String and octet types get copied verbatim.
1754 if ((vp->type == PW_TYPE_STRING) ||
1755 (vp->type == PW_TYPE_OCTETS)) {
1756 strlcpy(vp->vp_strvalue, value,
1757 sizeof(vp->vp_strvalue));
1758 vp->length = strlen(vp->vp_strvalue);
1761 * Everything else gets parsed: it's
1762 * DATA, not a string!
1764 } else if (!pairparsevalue(vp, value)) {
1766 *eol = T_OP_INVALID;
1772 * Mark the pair to be allocated later.
1774 case T_BACK_QUOTED_STRING:
1775 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1776 fr_strerror_printf("Value too long");
1780 vp = pairmake(attr, NULL, token);
1782 *eol = T_OP_INVALID;
1786 vp->flags.do_xlat = 1;
1787 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1793 * If we didn't make a pair, return an error.
1796 *eol = T_OP_INVALID;
1804 * Read one line of attribute/value pairs. This might contain
1805 * multiple pairs seperated by comma's.
1807 FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
1811 FR_TOKEN last_token = T_OP_INVALID;
1812 FR_TOKEN previous_token;
1815 * We allow an empty line.
1822 previous_token = last_token;
1823 if ((vp = pairread(&p, &last_token)) == NULL) {
1826 pairadd(first_pair, vp);
1827 } while (*p && (last_token == T_COMMA));
1830 * Don't tell the caller that there was a comment.
1832 if (last_token == T_HASH) {
1833 return previous_token;
1837 * And return the last token which we read.
1843 * Read valuepairs from the fp up to End-Of-File.
1845 * Hmm... this function is only used by radclient..
1847 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1850 FR_TOKEN last_token = T_EOL;
1857 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1859 * If we get a '\n' by itself, we assume that's
1860 * the end of that VP
1862 if ((buf[0] == '\n') && (list)) {
1865 if ((buf[0] == '\n') && (!list)) {
1870 * Comments get ignored
1872 if (buf[0] == '#') continue;
1875 * Read all of the attributes on the current line.
1878 last_token = userparse(buf, &vp);
1880 if (last_token != T_EOL) {
1881 fr_perror("%s", errprefix);
1892 if (error) pairfree(&list);
1896 return error ? NULL: list;
1902 * Compare two pairs, using the operator from "one".
1904 * i.e. given two attributes, it does:
1906 * (two->data) (one->operator) (one->data)
1908 * e.g. "foo" != "bar"
1910 * Returns true (comparison is true), or false (comparison is not true);
1912 * FIXME: Ignores tags!
1914 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1918 switch (one->operator) {
1920 return (two != NULL);
1922 case T_OP_CMP_FALSE:
1923 return (two == NULL);
1926 * One is a regex, compile it, print two to a string,
1927 * and then do string comparisons.
1931 #ifndef HAVE_REGEX_H
1936 char buffer[MAX_STRING_LEN * 4 + 1];
1938 compare = regcomp(®, one->vp_strvalue,
1941 regerror(compare, ®, buffer, sizeof(buffer));
1942 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1947 vp_prints_value(buffer, sizeof(buffer), two, 0);
1950 * Don't care about substring matches,
1953 compare = regexec(®, buffer, 0, NULL, 0);
1956 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1957 return (compare != 0);
1961 default: /* we're OK */
1966 * After doing the previous check for special comparisons,
1967 * do the per-type comparison here.
1969 switch (one->type) {
1970 case PW_TYPE_ABINARY:
1971 case PW_TYPE_OCTETS:
1975 if (one->length < two->length) {
1976 length = one->length;
1978 length = two->length;
1982 compare = memcmp(two->vp_octets, one->vp_octets,
1984 if (compare != 0) break;
1988 * Contents are the same. The return code
1989 * is therefore the difference in lengths.
1991 * i.e. "0x00" is smaller than "0x0000"
1993 compare = two->length - one->length;
1997 case PW_TYPE_STRING:
1998 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
2003 case PW_TYPE_INTEGER:
2005 compare = two->vp_integer - one->vp_integer;
2008 case PW_TYPE_IPADDR:
2009 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
2012 case PW_TYPE_IPV6ADDR:
2013 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
2014 sizeof(two->vp_ipv6addr));
2017 case PW_TYPE_IPV6PREFIX:
2018 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
2019 sizeof(two->vp_ipv6prefix));
2023 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
2024 sizeof(two->vp_ifid));
2028 return 0; /* unknown type */
2032 * Now do the operator comparison.
2034 switch (one->operator) {
2036 return (compare == 0);
2039 return (compare != 0);
2042 return (compare < 0);
2045 return (compare > 0);
2048 return (compare <= 0);
2051 return (compare >= 0);