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:
107 vp->length = sizeof(vp->vp_ifid);
110 case PW_TYPE_IPV6ADDR:
111 vp->length = sizeof(vp->vp_ipv6addr);
114 case PW_TYPE_IPV6PREFIX:
115 vp->length = sizeof(vp->vp_ipv6prefix);
118 case PW_TYPE_ETHERNET:
119 vp->length = sizeof(vp->vp_ether);
132 * Create a new valuepair.
134 VALUE_PAIR *paircreate(int attr, int type)
139 da = dict_attrbyvalue(attr);
140 if ((vp = pairalloc(da)) == NULL) {
141 librad_log("out of memory");
144 vp->operator = T_OP_EQ;
147 * It isn't in the dictionary: update the name.
150 char *p = (char *) (vp + 1);
152 vp->vendor = VENDOR(attr);
153 vp->attribute = attr;
155 vp->type = type; /* be forgiving */
157 if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute)) {
167 * release the memory used by a single attribute-value pair
168 * just a wrapper around free() for now.
170 void pairbasicfree(VALUE_PAIR *pair)
172 /* clear the memory here */
173 memset(pair, 0, sizeof(*pair));
178 * Release the memory used by a list of attribute-value
179 * pairs, and sets the pair pointer to NULL.
181 void pairfree(VALUE_PAIR **pair_ptr)
183 VALUE_PAIR *next, *pair;
185 if (!pair_ptr) return;
188 while (pair != NULL) {
199 * Find the pair with the matching attribute
201 VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
203 while(first && first->attribute != attr)
210 * Delete the pair(s) with the matching attribute
212 void pairdelete(VALUE_PAIR **first, int attr)
214 VALUE_PAIR *i, *next;
215 VALUE_PAIR **last = first;
217 for(i = *first; i; i = next) {
219 if (i->attribute == attr) {
229 * Add a pair at the end of a VALUE_PAIR list.
231 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
237 if (*first == NULL) {
241 for(i = *first; i->next; i = i->next)
247 * Add or replace a pair at the end of a VALUE_PAIR list.
249 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
251 VALUE_PAIR *i, *next;
252 VALUE_PAIR **prev = first;
254 if (*first == NULL) {
260 * Not an empty list, so find item if it is there, and
261 * replace it. Note, we always replace the first one, and
262 * we ignore any others that might exist.
264 for(i = *first; i; i = next) {
268 * Found the first attribute, replace it,
271 if (i->attribute == replace->attribute) {
275 * Should really assert that replace->next == NULL
277 replace->next = next;
283 * Point to where the attribute should go.
289 * If we got here, we didn't find anything to replace, so
290 * stopped at the last item, which we just append to.
296 * Copy just a certain type of pairs.
298 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
300 VALUE_PAIR *first, *n, **last;
308 if (attr >= 0 && vp->attribute != attr) {
313 if (!vp->flags.unknown_attr) {
316 name_len = FR_VP_NAME_PAD;
319 if ((n = malloc(sizeof(*n))) == NULL) {
320 librad_log("out of memory");
323 memcpy(n, vp, sizeof(*n) + name_len);
336 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
338 return paircopy2(vp, -1);
343 * Move attributes from one list to the other
344 * if not already present.
346 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
348 VALUE_PAIR **tailto, *i, *j, *next;
349 VALUE_PAIR *tailfrom = NULL;
351 int has_password = 0;
354 * First, see if there are any passwords here, and
355 * point "tailto" to the end of the "to" list.
358 for(i = *to; i; i = i->next) {
359 if (i->attribute == PW_USER_PASSWORD ||
360 i->attribute == PW_CRYPT_PASSWORD)
366 * Loop over the "from" list.
368 for(i = *from; i; i = next) {
372 * If there was a password in the "to" list,
373 * do not move any other password from the
374 * "from" to the "to" list.
377 (i->attribute == PW_USER_PASSWORD ||
378 i->attribute == PW_CRYPT_PASSWORD)) {
383 switch (i->operator) {
385 * These are COMPARISON attributes
386 * from a check list, and are not
387 * supposed to be copied!
405 * If the attribute is already present in "to",
406 * do not move it from "from" to "to". We make
407 * an exception for "Hint" which can appear multiple
408 * times, and we never move "Fall-Through".
410 if (i->attribute == PW_FALL_THROUGH ||
411 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
413 found = pairfind(*to, i->attribute);
414 switch (i->operator) {
417 * If matching attributes are found,
420 case T_OP_SUB: /* -= */
422 if (!i->vp_strvalue[0] ||
423 (strcmp((char *)found->vp_strvalue,
424 (char *)i->vp_strvalue) == 0)){
425 pairdelete(to, found->attribute);
428 * 'tailto' may have been
432 for(j = *to; j; j = j->next) {
441 /* really HAVE_REGEX_H */
444 * Attr-Name =~ "s/find/replace/"
446 * Very bad code. Barely working,
452 (i->vp_strvalue[0] == 's')) {
459 p = i->vp_strvalue + 1;
460 q = strchr(p + 1, *p);
461 if (!q || (q[strlen(q) - 1] != *p)) {
465 str = strdup(i->vp_strvalue + 2);
468 q[strlen(q) - 1] = '\0';
470 regcomp(®, str, 0);
471 if (regexec(®, found->vp_strvalue,
473 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
474 found->vp_strvalue, match[0].rm_so,
481 tailfrom = i; /* don't copy it over */
485 case T_OP_EQ: /* = */
487 * FIXME: Tunnel attributes with
488 * different tags are different
493 continue; /* with the loop */
498 * If a similar attribute is found,
499 * replace it with the new one. Otherwise,
500 * add the new one to the list.
502 case T_OP_SET: /* := */
504 VALUE_PAIR *mynext = found->next;
507 * Do NOT call pairdelete()
508 * here, due to issues with
509 * re-writing "request->username".
511 * Everybody calls pairmove,
512 * and expects it to work.
513 * We can't update request->username
514 * here, so instead we over-write
515 * the vp that it's pointing to.
517 memcpy(found, i, sizeof(*found));
518 found->next = mynext;
520 pairdelete(&found->next, found->attribute);
523 * 'tailto' may have been
526 for(j = found; j; j = j->next) {
534 * Add the new element to the list, even
535 * if similar ones already exist.
538 case T_OP_ADD: /* += */
543 tailfrom->next = next;
548 * If ALL of the 'to' attributes have been deleted,
549 * then ensure that the 'tail' is updated to point
564 * Move one kind of attributes from one list to the other
566 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
568 VALUE_PAIR *to_tail, *i, *next;
569 VALUE_PAIR *iprev = NULL;
572 * Find the last pair in the "to" list and put it in "to_tail".
576 for(i = *to; i; i = i->next)
581 for(i = *from; i; i = next) {
586 * If the attribute to move is NOT a VSA, then it
587 * ignores any attributes which do not match exactly.
589 if ((attr != PW_VENDOR_SPECIFIC) &&
590 (i->attribute != attr)) {
596 * If the attribute to move IS a VSA, then it ignores
597 * any non-VSA attribute.
599 if ((attr == PW_VENDOR_SPECIFIC) &&
600 (VENDOR(i->attribute) == 0)) {
606 * Remove the attribute from the "from" list.
614 * Add the attribute to the "to" list.
627 * Sort of strtok/strsep function.
629 static char *mystrtok(char **ptr, const char *sep)
635 while (**ptr && strchr(sep, **ptr))
640 while (**ptr && strchr(sep, **ptr) == NULL)
648 * Turn printable string into time_t
649 * Returns -1 on error, 0 on OK.
651 static int gettime(const char *valstr, time_t *date)
662 * Test for unix timestamp date
664 *date = strtoul(valstr, &tail, 10);
670 memset(tm, 0, sizeof(*tm));
671 tm->tm_isdst = -1; /* don't know, and don't care about DST */
673 strlcpy(buf, valstr, sizeof(buf));
676 f[0] = mystrtok(&p, " \t");
677 f[1] = mystrtok(&p, " \t");
678 f[2] = mystrtok(&p, " \t");
679 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
680 if (!f[0] || !f[1] || !f[2]) return -1;
683 * The time has a colon, where nothing else does.
684 * So if we find it, bubble it to the back of the list.
687 for (i = 0; i < 3; i++) {
688 if (strchr(f[i], ':')) {
698 * The month is text, which allows us to find it easily.
701 for (i = 0; i < 3; i++) {
702 if (isalpha( (int) *f[i])) {
704 * Bubble the month to the front of the list
710 for (i = 0; i < 12; i++) {
711 if (strncasecmp(months[i], f[0], 3) == 0) {
719 /* month not found? */
720 if (tm->tm_mon == 12) return -1;
723 * The year may be in f[1], or in f[2]
725 tm->tm_year = atoi(f[1]);
726 tm->tm_mday = atoi(f[2]);
728 if (tm->tm_year >= 1900) {
733 * We can't use 2-digit years any more, they make it
734 * impossible to tell what's the day, and what's the year.
736 if (tm->tm_mday < 1900) return -1;
739 * Swap the year and the day.
742 tm->tm_year = tm->tm_mday - 1900;
747 * If the day is out of range, die.
749 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
754 * There may be %H:%M:%S. Parse it in a hacky way.
757 f[0] = f[3]; /* HH */
758 f[1] = strchr(f[0], ':'); /* find : separator */
759 if (!f[1]) return -1;
761 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
763 f[2] = strchr(f[1], ':'); /* find : separator */
765 *(f[2]++) = '\0'; /* nuke it, and point to SS */
767 strcpy(f[2], "0"); /* assignment would discard const */
770 tm->tm_hour = atoi(f[0]);
771 tm->tm_min = atoi(f[1]);
772 tm->tm_sec = atoi(f[2]);
776 * Returns -1 on error.
779 if (t == (time_t) -1) return -1;
786 static const char *hextab = "0123456789abcdef";
789 * Parse a string value into a given VALUE_PAIR
791 * FIXME: we probably want to fix this function to accept
792 * octets as values for any type of attribute. We should then
793 * double-check the parsed value, to be sure it's legal for that
794 * type (length, etc.)
796 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
805 * Even for integers, dates and ip addresses we
806 * keep the original string in vp->vp_strvalue.
808 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
809 vp->length = strlen(vp->vp_strvalue);
820 while (*cp && (length < sizeof(vp->vp_strvalue))) {
850 c = '\\'; /* no cp++ */
853 if ((cp[0] >= '0') &&
859 (sscanf(cp, "%3o", &x) == 1)) {
862 } /* else just do '\\' */
873 * It's a comparison, not a real IP.
875 if ((vp->operator == T_OP_REG_EQ) ||
876 (vp->operator == T_OP_REG_NE)) {
881 * FIXME: complain if hostname
882 * cannot be resolved, or resolve later!
885 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
886 cs = s = strdup(value);
890 vp->flags.addport = 1;
899 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
901 librad_log("Failed to find IP address for %s", cs);
905 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
912 if ((value[0] == '0') && (value[1] == 'x')) {
917 * Note that ALL integers are unsigned!
919 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
921 if (vp->vp_integer > 255) {
922 librad_log("Byte value \"%s\" is larger than 255", value);
930 * Look for the named value for the given
933 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
934 librad_log("Unknown value %s for attribute %s",
938 vp->vp_integer = dval->value;
944 * Note that ALL integers are unsigned!
946 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
948 if (vp->vp_integer > 65535) {
949 librad_log("Byte value \"%s\" is larger than 65535", value);
957 * Look for the named value for the given
960 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
961 librad_log("Unknown value %s for attribute %s",
965 vp->vp_integer = dval->value;
969 case PW_TYPE_INTEGER:
971 * Note that ALL integers are unsigned!
973 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
980 * Look for the named value for the given
983 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
984 librad_log("Unknown value %s for attribute %s",
988 vp->vp_integer = dval->value;
995 * time_t may be 64 bits, whule vp_date
996 * MUST be 32-bits. We need an
997 * intermediary variable to handle
1002 if (gettime(value, &date) < 0) {
1003 librad_log("failed to parse time string "
1013 case PW_TYPE_ABINARY:
1014 #ifdef ASCEND_BINARY
1015 if (strncasecmp(value, "0x", 2) == 0) {
1016 vp->type = PW_TYPE_OCTETS;
1020 if (ascend_parse_filter(vp) < 0 ) {
1021 librad_log("failed to parse Ascend binary attribute: %s",
1028 * If Ascend binary is NOT defined,
1029 * then fall through to raw octets, so that
1030 * the user can at least make them by hand...
1034 /* raw octets: 0x01020304... */
1035 case PW_TYPE_OCTETS:
1036 if (strncasecmp(value, "0x", 2) == 0) {
1044 * There is only one character,
1047 if ((strlen(cp) & 0x01) != 0) {
1048 librad_log("Hex string is not an even length string.");
1054 (vp->length < MAX_STRING_LEN)) {
1057 if (sscanf(cp, "%02x", &tmp) != 1) {
1058 librad_log("Non-hex characters at %c%c", cp[0], cp[1]);
1070 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1071 librad_log("failed to parse interface-id "
1072 "string \"%s\"", value);
1078 case PW_TYPE_IPV6ADDR:
1079 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
1080 librad_log("failed to parse IPv6 address "
1081 "string \"%s\"", value);
1084 vp->length = 16; /* length of IPv6 address */
1087 case PW_TYPE_IPV6PREFIX:
1088 p = strchr(value, '/');
1089 if (!p || ((p - value) >= 256)) {
1090 librad_log("invalid IPv6 prefix "
1091 "string \"%s\"", value);
1094 unsigned int prefix;
1095 char buffer[256], *eptr;
1097 memcpy(buffer, value, p - value);
1098 buffer[p - value] = '\0';
1100 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1101 librad_log("failed to parse IPv6 address "
1102 "string \"%s\"", value);
1106 prefix = strtoul(p + 1, &eptr, 10);
1107 if ((prefix > 128) || *eptr) {
1108 librad_log("failed to parse IPv6 address "
1109 "string \"%s\"", value);
1112 vp->vp_octets[1] = prefix;
1114 vp->vp_octets[0] = '\0';
1115 vp->length = 16 + 2;
1118 case PW_TYPE_ETHERNET:
1120 const char *c1, *c2;
1127 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1129 } else if ((cp[1] != '\0') &&
1132 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1133 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1135 if (*cp == ':') cp++;
1139 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1140 librad_log("failed to parse Ethernet address \"%s\"", value);
1143 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1154 librad_log("unknown attribute type %d", vp->type);
1162 * Create a VALUE_PAIR from an ASCII attribute and value,
1163 * where the attribute name is in the form:
1167 * VendorName-Attr-%d
1169 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1174 const char *p = attribute;
1180 * Unknown attributes MUST be of type 'octets'
1182 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1183 librad_log("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1187 da = dict_attrbyname(attribute);
1196 * Pull off vendor prefix first.
1198 if (strncasecmp(p, "Attr-", 5) != 0) {
1199 if (strncasecmp(p, "Vendor-", 7) == 0) {
1200 vendor = (int) strtol(p + 7, &q, 10);
1201 if ((vendor == 0) || (vendor > 65535)) {
1202 librad_log("Invalid vendor value in attribute name \"%s\"", attribute);
1208 } else { /* must be vendor name */
1214 librad_log("Invalid vendor name in attribute name \"%s\"", attribute);
1218 if ((size_t) (q - p) >= sizeof(buffer)) {
1219 librad_log("Vendor name too long in attribute name \"%s\"", attribute);
1223 memcpy(buffer, p, (q - p));
1224 buffer[q - p] = '\0';
1226 vendor = dict_vendorbyname(buffer);
1228 librad_log("Unknown vendor name in attribute name \"%s\"", attribute);
1236 librad_log("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1245 if (strncasecmp(p, "Attr-", 5) != 0) {
1246 librad_log("Invalid format in attribute name \"%s\"", attribute);
1250 attr = strtol(p + 5, &q, 10);
1253 * Invalid, or trailing text after number.
1255 if ((attr == 0) || *q) {
1256 librad_log("Invalid value in attribute name \"%s\"", attribute);
1261 * Double-check the size of attr.
1264 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1269 librad_log("Invalid attribute number in attribute name \"%s\"", attribute);
1273 } else switch (dv->type) {
1275 if (attr > 255) goto attr_error;
1279 if (attr > 65535) goto attr_error;
1282 case 4: /* Internal limitations! */
1283 if (attr > 65535) goto attr_error;
1287 librad_log("Internal sanity check failed");
1292 attr |= vendor << 16;
1296 * We've now parsed the attribute properly, Let's create
1297 * it. This next stop also looks the attribute up in the
1298 * dictionary, and creates the appropriate type for it.
1300 if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
1301 librad_log("out of memory");
1305 size = strlen(value + 2);
1308 * We may be reading something like Attr-5. i.e.
1309 * who-ever wrote the text didn't understand it, but we
1314 if (size == (vp->length * 2)) break;
1315 vp->type = PW_TYPE_OCTETS;
1318 case PW_TYPE_STRING:
1319 case PW_TYPE_OCTETS:
1320 case PW_TYPE_ABINARY:
1321 vp->length = size >> 1;
1325 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1326 librad_log("Invalid hex string");
1332 * Move contents around based on type. This is
1333 * to work around the historical use of "lvalue".
1337 case PW_TYPE_IPADDR:
1338 case PW_TYPE_INTEGER:
1339 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1340 vp->vp_strvalue[0] = '\0';
1347 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1354 * Create a VALUE_PAIR from an ASCII attribute and value.
1356 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1369 * Check for tags in 'Attribute:Tag' format.
1374 ts = strrchr(attribute, ':');
1376 librad_log("Invalid tag for attribute %s", attribute);
1381 /* Colon found with something behind it */
1382 if (ts[1] == '*' && ts[2] == 0) {
1383 /* Wildcard tag for check items */
1386 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1387 /* It's not a wild card tag */
1388 tag = strtol(ts + 1, &tc, 0);
1389 if (tc && !*tc && TAG_VALID_ZERO(tag))
1393 librad_log("Invalid tag for attribute %s", attribute);
1400 * It's not found in the dictionary, so we use
1401 * another method to create the attribute.
1403 if ((da = dict_attrbyname(attribute)) == NULL) {
1404 return pairmake_any(attribute, value, operator);
1407 if ((value[0] == '0') && (value[1] == 'x') &&
1408 (da->type != PW_TYPE_OCTETS)) {
1409 return pairmake_any(attribute, value, operator);
1412 if ((vp = pairalloc(da)) == NULL) {
1413 librad_log("out of memory");
1416 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1418 /* Check for a tag in the 'Merit' format of:
1419 * :Tag:Value. Print an error if we already found
1420 * a tag in the Attribute.
1423 if (value && (*value == ':' && da->flags.has_tag)) {
1424 /* If we already found a tag, this is invalid */
1427 librad_log("Duplicate tag %s for attribute %s",
1429 DEBUG("Duplicate tag %s for attribute %s\n",
1434 /* Colon found and attribute allows a tag */
1435 if (value[1] == '*' && value[2] == ':') {
1436 /* Wildcard tag for check items */
1441 tag = strtol(value + 1, &tc, 0);
1442 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1450 vp->flags.tag = tag;
1453 switch (vp->operator) {
1458 * For =* and !* operators, the value is irrelevant
1462 case T_OP_CMP_FALSE:
1463 vp->vp_strvalue[0] = '\0';
1469 * Regular expression comparison of integer attributes
1470 * does a STRING comparison of the names of their
1471 * integer attributes.
1473 case T_OP_REG_EQ: /* =~ */
1474 case T_OP_REG_NE: /* !~ */
1475 if (vp->type == PW_TYPE_INTEGER) {
1480 * Regular expression match with no regular
1481 * expression is wrong.
1488 res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);
1492 regerror(res, &cre, msg, sizeof(msg));
1493 librad_log("Illegal regular expression in attribute: %s: %s",
1500 librad_log("Regelar expressions not enabled in this build, error in attribute %s",
1508 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1509 * then the user MAY have typed in the attribute name
1510 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1512 * We probably want to fix pairparsevalue to accept
1513 * octets as values for any attribute.
1515 if (value && (pairparsevalue(vp, value) == NULL)) {
1527 static const int valid_attr_name[256] = {
1528 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1529 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1530 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1531 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1532 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1533 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1534 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1535 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1536 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1537 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1538 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1539 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1540 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1541 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1542 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1543 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1547 * Read a valuepair from a buffer, and advance pointer.
1548 * Sets *eol to T_EOL if end of line was encountered.
1550 VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol)
1554 char value[512], *q;
1556 FR_TOKEN token, t, xlat;
1560 *eol = T_OP_INVALID;
1563 while ((*p == ' ') || (*p == '\t')) p++;
1566 *eol = T_OP_INVALID;
1567 librad_log("No token read where we expected an attribute name");
1573 librad_log("Read a comment instead of a token");
1578 for (len = 0; len < sizeof(attr); len++) {
1579 if (valid_attr_name[(int)*p]) {
1586 if (len == sizeof(attr)) {
1587 *eol = T_OP_INVALID;
1588 librad_log("Attribute name is too long");
1593 * We may have Foo-Bar:= stuff, so back up.
1595 if (attr[len - 1] == ':') {
1603 /* Now we should have an operator here. */
1604 token = gettoken(ptr, buf, sizeof(buf));
1605 if (token < T_EQSTART || token > T_EQEND) {
1606 librad_log("expecting operator");
1610 /* Read value. Note that empty string values are allowed */
1611 xlat = gettoken(ptr, value, sizeof(value));
1612 if (xlat == T_EOL) {
1613 librad_log("failed to get value");
1618 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1621 t = gettoken(&p, buf, sizeof(buf));
1622 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1623 librad_log("Expected end of line or comma");
1635 * Make the full pair now.
1638 vp = pairmake(attr, value, token);
1644 case T_DOUBLE_QUOTED_STRING:
1645 p = strchr(value, '%');
1646 if (p && (p[1] == '{')) {
1647 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1648 librad_log("Value too long");
1651 vp = pairmake(attr, NULL, token);
1653 *eol = T_OP_INVALID;
1657 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1658 vp->flags.do_xlat = 1;
1661 vp = pairmake(attr, value, token);
1667 * Mark the pair to be allocated later.
1669 case T_BACK_QUOTED_STRING:
1670 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1671 librad_log("Value too long");
1675 vp = pairmake(attr, NULL, token);
1677 *eol = T_OP_INVALID;
1681 vp->flags.do_xlat = 1;
1682 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1688 * If we didn't make a pair, return an error.
1691 *eol = T_OP_INVALID;
1699 * Read one line of attribute/value pairs. This might contain
1700 * multiple pairs seperated by comma's.
1702 FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
1706 FR_TOKEN last_token = T_OP_INVALID;
1707 FR_TOKEN previous_token;
1710 * We allow an empty line.
1717 previous_token = last_token;
1718 if ((vp = pairread(&p, &last_token)) == NULL) {
1721 pairadd(first_pair, vp);
1722 } while (*p && (last_token == T_COMMA));
1725 * Don't tell the caller that there was a comment.
1727 if (last_token == T_HASH) {
1728 return previous_token;
1732 * And return the last token which we read.
1738 * Read valuepairs from the fp up to End-Of-File.
1740 * Hmm... this function is only used by radclient..
1742 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1745 FR_TOKEN last_token = T_EOL;
1752 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1754 * If we get a '\n' by itself, we assume that's
1755 * the end of that VP
1757 if ((buf[0] == '\n') && (list)) {
1760 if ((buf[0] == '\n') && (!list)) {
1765 * Comments get ignored
1767 if (buf[0] == '#') continue;
1770 * Read all of the attributes on the current line.
1773 last_token = userparse(buf, &vp);
1775 if (last_token != T_EOL) {
1776 librad_perror("%s", errprefix);
1787 if (error) pairfree(&list);
1791 return error ? NULL: list;
1797 * Compare two pairs, using the operator from "one".
1799 * i.e. given two attributes, it does:
1801 * (two->data) (one->operator) (one->data)
1803 * e.g. "foo" != "bar"
1805 * Returns true (comparison is true), or false (comparison is not true);
1807 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1811 switch (one->operator) {
1813 return (two != NULL);
1815 case T_OP_CMP_FALSE:
1816 return (two == NULL);
1819 * One is a regex, compile it, print two to a string,
1820 * and then do string comparisons.
1824 #ifndef HAVE_REGEX_H
1829 char buffer[MAX_STRING_LEN * 4 + 1];
1831 compare = regcomp(®, one->vp_strvalue,
1834 regerror(compare, ®, buffer, sizeof(buffer));
1835 librad_log("Illegal regular expression in attribute: %s: %s",
1840 vp_prints_value(buffer, sizeof(buffer), two, 0);
1843 * Don't care about substring matches,
1846 compare = regexec(®, buffer, 0, NULL, 0);
1849 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1850 return (compare != 0);
1854 default: /* we're OK */
1859 * After doing the previous check for special comparisons,
1860 * do the per-type comparison here.
1862 switch (one->type) {
1863 case PW_TYPE_ABINARY:
1864 case PW_TYPE_OCTETS:
1867 const uint8_t *p, *q;
1869 if (one->length < two->length) {
1870 length = one->length;
1872 length = two->length;
1878 compare = ((int) *p) - ((int) *q);
1879 if (compare != 0) goto type_switch;
1883 * Contents are the same. The return code
1884 * is therefore the difference in lengths.
1886 * i.e. "0x00" is smaller than "0x0000"
1888 compare = two->length - one->length;
1892 case PW_TYPE_STRING:
1893 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
1898 case PW_TYPE_INTEGER:
1900 compare = two->vp_integer - one->vp_integer;
1903 case PW_TYPE_IPADDR:
1904 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1907 case PW_TYPE_IPV6ADDR:
1908 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1909 sizeof(two->vp_ipv6addr));
1912 case PW_TYPE_IPV6PREFIX:
1913 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
1914 sizeof(two->vp_ipv6prefix));
1918 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
1919 sizeof(two->vp_ifid));
1923 return 0; /* unknown type */
1927 * Now do the operator comparison.
1930 switch (one->operator) {
1932 return (compare == 0);
1935 return (compare != 0);
1938 return (compare < 0);
1941 return (compare > 0);
1944 return (compare <= 0);
1947 return (compare >= 0);