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.
151 char *p = (char *) (vp + 1);
153 vp->vendor = VENDOR(attr);
154 vp->attribute = attr;
156 vp->type = type; /* be forgiving */
161 v = dict_vendorbyvalue(vp->vendor);
163 snprintf(p, FR_VP_NAME_LEN, "%s-", v->name);
165 snprintf(p, FR_VP_NAME_LEN, "Vendor-%u-", vp->vendor);
169 if (len == FR_VP_NAME_LEN) {
175 snprintf(p + len, FR_VP_NAME_LEN - len, "Attr-%u",
177 len += strlen(p + len);
178 if (len == FR_VP_NAME_LEN) {
188 * release the memory used by a single attribute-value pair
189 * just a wrapper around free() for now.
191 void pairbasicfree(VALUE_PAIR *pair)
193 /* clear the memory here */
194 memset(pair, 0, sizeof(*pair));
199 * Release the memory used by a list of attribute-value
200 * pairs, and sets the pair pointer to NULL.
202 void pairfree(VALUE_PAIR **pair_ptr)
204 VALUE_PAIR *next, *pair;
206 if (!pair_ptr) return;
209 while (pair != NULL) {
220 * Find the pair with the matching attribute
222 VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
224 while(first && first->attribute != attr)
231 * Delete the pair(s) with the matching attribute
233 void pairdelete(VALUE_PAIR **first, int attr)
235 VALUE_PAIR *i, *next;
236 VALUE_PAIR **last = first;
238 for(i = *first; i; i = next) {
240 if (i->attribute == attr) {
250 * Add a pair at the end of a VALUE_PAIR list.
252 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
258 if (*first == NULL) {
262 for(i = *first; i->next; i = i->next)
268 * Add or replace a pair at the end of a VALUE_PAIR list.
270 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
272 VALUE_PAIR *i, *next;
273 VALUE_PAIR **prev = first;
275 if (*first == NULL) {
281 * Not an empty list, so find item if it is there, and
282 * replace it. Note, we always replace the first one, and
283 * we ignore any others that might exist.
285 for(i = *first; i; i = next) {
289 * Found the first attribute, replace it,
292 if (i->attribute == replace->attribute) {
296 * Should really assert that replace->next == NULL
298 replace->next = next;
304 * Point to where the attribute should go.
310 * If we got here, we didn't find anything to replace, so
311 * stopped at the last item, which we just append to.
317 * Copy just a certain type of pairs.
319 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
321 VALUE_PAIR *first, *n, **last;
329 if (attr >= 0 && vp->attribute != attr) {
334 if (!vp->flags.unknown_attr) {
337 name_len = FR_VP_NAME_PAD;
340 if ((n = malloc(sizeof(*n))) == NULL) {
341 librad_log("out of memory");
344 memcpy(n, vp, sizeof(*n) + name_len);
357 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
359 return paircopy2(vp, -1);
364 * Move attributes from one list to the other
365 * if not already present.
367 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
369 VALUE_PAIR **tailto, *i, *j, *next;
370 VALUE_PAIR *tailfrom = NULL;
372 int has_password = 0;
375 * First, see if there are any passwords here, and
376 * point "tailto" to the end of the "to" list.
379 for(i = *to; i; i = i->next) {
380 if (i->attribute == PW_USER_PASSWORD ||
381 i->attribute == PW_CRYPT_PASSWORD)
387 * Loop over the "from" list.
389 for(i = *from; i; i = next) {
393 * If there was a password in the "to" list,
394 * do not move any other password from the
395 * "from" to the "to" list.
398 (i->attribute == PW_USER_PASSWORD ||
399 i->attribute == PW_CRYPT_PASSWORD)) {
404 switch (i->operator) {
406 * These are COMPARISON attributes
407 * from a check list, and are not
408 * supposed to be copied!
426 * If the attribute is already present in "to",
427 * do not move it from "from" to "to". We make
428 * an exception for "Hint" which can appear multiple
429 * times, and we never move "Fall-Through".
431 if (i->attribute == PW_FALL_THROUGH ||
432 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
434 found = pairfind(*to, i->attribute);
435 switch (i->operator) {
438 * If matching attributes are found,
441 case T_OP_SUB: /* -= */
443 if (!i->vp_strvalue[0] ||
444 (strcmp((char *)found->vp_strvalue,
445 (char *)i->vp_strvalue) == 0)){
446 pairdelete(to, found->attribute);
449 * 'tailto' may have been
453 for(j = *to; j; j = j->next) {
462 /* really HAVE_REGEX_H */
465 * Attr-Name =~ "s/find/replace/"
467 * Very bad code. Barely working,
473 (i->vp_strvalue[0] == 's')) {
480 p = i->vp_strvalue + 1;
481 q = strchr(p + 1, *p);
482 if (!q || (q[strlen(q) - 1] != *p)) {
486 str = strdup(i->vp_strvalue + 2);
489 q[strlen(q) - 1] = '\0';
491 regcomp(®, str, 0);
492 if (regexec(®, found->vp_strvalue,
494 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
495 found->vp_strvalue, match[0].rm_so,
502 tailfrom = i; /* don't copy it over */
506 case T_OP_EQ: /* = */
508 * FIXME: Tunnel attributes with
509 * different tags are different
514 continue; /* with the loop */
519 * If a similar attribute is found,
520 * replace it with the new one. Otherwise,
521 * add the new one to the list.
523 case T_OP_SET: /* := */
525 VALUE_PAIR *mynext = found->next;
528 * Do NOT call pairdelete()
529 * here, due to issues with
530 * re-writing "request->username".
532 * Everybody calls pairmove,
533 * and expects it to work.
534 * We can't update request->username
535 * here, so instead we over-write
536 * the vp that it's pointing to.
538 memcpy(found, i, sizeof(*found));
539 found->next = mynext;
541 pairdelete(&found->next, found->attribute);
544 * 'tailto' may have been
547 for(j = found; j; j = j->next) {
555 * Add the new element to the list, even
556 * if similar ones already exist.
559 case T_OP_ADD: /* += */
564 tailfrom->next = next;
569 * If ALL of the 'to' attributes have been deleted,
570 * then ensure that the 'tail' is updated to point
585 * Move one kind of attributes from one list to the other
587 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
589 VALUE_PAIR *to_tail, *i, *next;
590 VALUE_PAIR *iprev = NULL;
593 * Find the last pair in the "to" list and put it in "to_tail".
597 for(i = *to; i; i = i->next)
602 for(i = *from; i; i = next) {
607 * If the attribute to move is NOT a VSA, then it
608 * ignores any attributes which do not match exactly.
610 if ((attr != PW_VENDOR_SPECIFIC) &&
611 (i->attribute != attr)) {
617 * If the attribute to move IS a VSA, then it ignores
618 * any non-VSA attribute.
620 if ((attr == PW_VENDOR_SPECIFIC) &&
621 (VENDOR(i->attribute) == 0)) {
627 * Remove the attribute from the "from" list.
635 * Add the attribute to the "to" list.
648 * Sort of strtok/strsep function.
650 static char *mystrtok(char **ptr, const char *sep)
656 while (**ptr && strchr(sep, **ptr))
661 while (**ptr && strchr(sep, **ptr) == NULL)
669 * Turn printable string into time_t
670 * Returns -1 on error, 0 on OK.
672 static int gettime(const char *valstr, time_t *date)
683 * Test for unix timestamp date
685 *date = strtoul(valstr, &tail, 10);
691 memset(tm, 0, sizeof(*tm));
692 tm->tm_isdst = -1; /* don't know, and don't care about DST */
694 strlcpy(buf, valstr, sizeof(buf));
697 f[0] = mystrtok(&p, " \t");
698 f[1] = mystrtok(&p, " \t");
699 f[2] = mystrtok(&p, " \t");
700 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
701 if (!f[0] || !f[1] || !f[2]) return -1;
704 * The time has a colon, where nothing else does.
705 * So if we find it, bubble it to the back of the list.
708 for (i = 0; i < 3; i++) {
709 if (strchr(f[i], ':')) {
719 * The month is text, which allows us to find it easily.
722 for (i = 0; i < 3; i++) {
723 if (isalpha( (int) *f[i])) {
725 * Bubble the month to the front of the list
731 for (i = 0; i < 12; i++) {
732 if (strncasecmp(months[i], f[0], 3) == 0) {
740 /* month not found? */
741 if (tm->tm_mon == 12) return -1;
744 * The year may be in f[1], or in f[2]
746 tm->tm_year = atoi(f[1]);
747 tm->tm_mday = atoi(f[2]);
749 if (tm->tm_year >= 1900) {
754 * We can't use 2-digit years any more, they make it
755 * impossible to tell what's the day, and what's the year.
757 if (tm->tm_mday < 1900) return -1;
760 * Swap the year and the day.
763 tm->tm_year = tm->tm_mday - 1900;
768 * If the day is out of range, die.
770 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
775 * There may be %H:%M:%S. Parse it in a hacky way.
778 f[0] = f[3]; /* HH */
779 f[1] = strchr(f[0], ':'); /* find : separator */
780 if (!f[1]) return -1;
782 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
784 f[2] = strchr(f[1], ':'); /* find : separator */
786 *(f[2]++) = '\0'; /* nuke it, and point to SS */
788 strcpy(f[2], "0"); /* assignment would discard const */
791 tm->tm_hour = atoi(f[0]);
792 tm->tm_min = atoi(f[1]);
793 tm->tm_sec = atoi(f[2]);
797 * Returns -1 on error.
800 if (t == (time_t) -1) return -1;
807 static const char *hextab = "0123456789abcdef";
810 * Parse a string value into a given VALUE_PAIR
812 * FIXME: we probably want to fix this function to accept
813 * octets as values for any type of attribute. We should then
814 * double-check the parsed value, to be sure it's legal for that
815 * type (length, etc.)
817 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
826 * Even for integers, dates and ip addresses we
827 * keep the original string in vp->vp_strvalue.
829 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
830 vp->length = strlen(vp->vp_strvalue);
841 while (*cp && (length < sizeof(vp->vp_strvalue))) {
871 c = '\\'; /* no cp++ */
874 if ((cp[0] >= '0') &&
880 (sscanf(cp, "%3o", &x) == 1)) {
883 } /* else just do '\\' */
894 * It's a comparison, not a real IP.
896 if ((vp->operator == T_OP_REG_EQ) ||
897 (vp->operator == T_OP_REG_NE)) {
902 * FIXME: complain if hostname
903 * cannot be resolved, or resolve later!
905 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
906 cs = s = strdup(value);
909 vp->flags.addport = 1;
918 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
919 librad_log("Failed to find IP address for %s", cs);
923 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
930 if ((value[0] == '0') && (value[1] == 'x')) {
935 * Note that ALL integers are unsigned!
937 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
939 if (vp->vp_integer > 255) {
940 librad_log("Byte value \"%s\" is larger than 255", value);
948 * Look for the named value for the given
951 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
952 librad_log("Unknown value %s for attribute %s",
956 vp->vp_integer = dval->value;
962 * Note that ALL integers are unsigned!
964 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
966 if (vp->vp_integer > 65535) {
967 librad_log("Byte value \"%s\" is larger than 65535", value);
975 * Look for the named value for the given
978 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
979 librad_log("Unknown value %s for attribute %s",
983 vp->vp_integer = dval->value;
987 case PW_TYPE_INTEGER:
989 * Note that ALL integers are unsigned!
991 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
998 * Look for the named value for the given
1001 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
1002 librad_log("Unknown value %s for attribute %s",
1006 vp->vp_integer = dval->value;
1013 * time_t may be 64 bits, whule vp_date
1014 * MUST be 32-bits. We need an
1015 * intermediary variable to handle
1020 if (gettime(value, &date) < 0) {
1021 librad_log("failed to parse time string "
1031 case PW_TYPE_ABINARY:
1032 #ifdef ASCEND_BINARY
1033 if (strncasecmp(value, "0x", 2) == 0) {
1034 vp->type = PW_TYPE_OCTETS;
1038 if (ascend_parse_filter(vp) < 0 ) {
1039 librad_log("failed to parse Ascend binary attribute: %s",
1046 * If Ascend binary is NOT defined,
1047 * then fall through to raw octets, so that
1048 * the user can at least make them by hand...
1052 /* raw octets: 0x01020304... */
1053 case PW_TYPE_OCTETS:
1054 if (strncasecmp(value, "0x", 2) == 0) {
1062 * There is only one character,
1065 if ((strlen(cp) & 0x01) != 0) {
1066 librad_log("Hex string is not an even length string.");
1072 (vp->length < MAX_STRING_LEN)) {
1075 if (sscanf(cp, "%02x", &tmp) != 1) {
1076 librad_log("Non-hex characters at %c%c", cp[0], cp[1]);
1088 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1089 librad_log("failed to parse interface-id "
1090 "string \"%s\"", value);
1096 case PW_TYPE_IPV6ADDR:
1097 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
1098 librad_log("failed to parse IPv6 address "
1099 "string \"%s\"", value);
1102 vp->length = 16; /* length of IPv6 address */
1105 case PW_TYPE_IPV6PREFIX:
1106 p = strchr(value, '/');
1107 if (!p || ((p - value) >= 256)) {
1108 librad_log("invalid IPv6 prefix "
1109 "string \"%s\"", value);
1112 unsigned int prefix;
1113 char buffer[256], *eptr;
1115 memcpy(buffer, value, p - value);
1116 buffer[p - value] = '\0';
1118 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1119 librad_log("failed to parse IPv6 address "
1120 "string \"%s\"", value);
1124 prefix = strtoul(p + 1, &eptr, 10);
1125 if ((prefix > 128) || *eptr) {
1126 librad_log("failed to parse IPv6 address "
1127 "string \"%s\"", value);
1130 vp->vp_octets[1] = prefix;
1132 vp->vp_octets[0] = '\0';
1133 vp->length = 16 + 2;
1136 case PW_TYPE_ETHERNET:
1138 const char *c1, *c2;
1145 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1147 } else if ((cp[1] != '\0') &&
1150 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1151 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1153 if (*cp == ':') cp++;
1157 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1158 librad_log("failed to parse Ethernet address \"%s\"", value);
1161 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1172 librad_log("unknown attribute type %d", vp->type);
1180 * Create a VALUE_PAIR from an ASCII attribute and value,
1181 * where the attribute name is in the form:
1185 * VendorName-Attr-%d
1187 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1192 const char *p = attribute;
1197 * Unknown attributes MUST be of type 'octets'
1199 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1200 librad_log("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1207 * Pull off vendor prefix first.
1209 if (strncasecmp(p, "Attr-", 5) != 0) {
1210 if (strncasecmp(p, "Vendor-", 7) == 0) {
1211 vendor = (int) strtol(p + 7, &q, 10);
1212 if ((vendor == 0) || (vendor > 65535)) {
1213 librad_log("Invalid vendor value in attribute name \"%s\"", attribute);
1219 } else { /* must be vendor name */
1224 librad_log("Invalid vendor name in attribute name \"%s\"", attribute);
1228 if ((q - p) >= sizeof(buffer)) {
1229 librad_log("Vendor name too long in attribute name \"%s\"", attribute);
1233 memcpy(buffer, p, (q - p));
1234 buffer[q - p] = '\0';
1236 vendor = dict_vendorbyname(buffer);
1238 librad_log("Unknown vendor name in attribute name \"%s\"", attribute);
1246 librad_log("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1255 if (strncasecmp(p, "Attr-", 5) != 0) {
1256 librad_log("Invalid format in attribute name \"%s\"", attribute);
1260 attr = strtol(p + 5, &q, 10);
1263 * Invalid, or trailing text after number.
1265 if ((attr == 0) || *q) {
1266 librad_log("Invalid value in attribute name \"%s\"", attribute);
1271 * Double-check the size of attr.
1274 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1279 librad_log("Invalid attribute number in attribute name \"%s\"", attribute);
1283 } else switch (dv->type) {
1285 if (attr > 255) goto attr_error;
1289 if (attr > 65535) goto attr_error;
1292 case 4: /* Internal limitations! */
1293 if (attr > 65535) goto attr_error;
1297 librad_log("Internal sanity check failed");
1302 attr |= vendor << 16;
1305 * We've now parsed the attribute properly, Let's create
1306 * it. This next stop also looks the attribute up in the
1307 * dictionary, and creates the appropriate type for it.
1309 if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
1310 librad_log("out of memory");
1314 size = strlen(value + 2);
1317 * We may be reading something like Attr-5. i.e.
1318 * who-ever wrote the text didn't understand it, but we
1323 if (size == (vp->length * 2)) break;
1324 vp->type = PW_TYPE_OCTETS;
1327 case PW_TYPE_STRING:
1328 case PW_TYPE_OCTETS:
1329 case PW_TYPE_ABINARY:
1330 vp->length = size >> 1;
1334 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1335 librad_log("Invalid hex string");
1341 * Move contents around based on type. This is
1342 * to work around the historical use of "lvalue".
1346 case PW_TYPE_IPADDR:
1347 case PW_TYPE_INTEGER:
1348 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1349 vp->vp_strvalue[0] = '\0';
1356 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1363 * Create a VALUE_PAIR from an ASCII attribute and value.
1365 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1378 * Check for tags in 'Attribute:Tag' format.
1383 ts = strrchr(attribute, ':');
1385 librad_log("Invalid tag for attribute %s", attribute);
1390 /* Colon found with something behind it */
1391 if (ts[1] == '*' && ts[2] == 0) {
1392 /* Wildcard tag for check items */
1395 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1396 /* It's not a wild card tag */
1397 tag = strtol(ts + 1, &tc, 0);
1398 if (tc && !*tc && TAG_VALID_ZERO(tag))
1402 librad_log("Invalid tag for attribute %s", attribute);
1409 * It's not found in the dictionary, so we use
1410 * another method to create the attribute.
1412 if ((da = dict_attrbyname(attribute)) == NULL) {
1413 return pairmake_any(attribute, value, operator);
1416 if ((vp = pairalloc(da)) == NULL) {
1417 librad_log("out of memory");
1420 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1422 /* Check for a tag in the 'Merit' format of:
1423 * :Tag:Value. Print an error if we already found
1424 * a tag in the Attribute.
1427 if (value && (*value == ':' && da->flags.has_tag)) {
1428 /* If we already found a tag, this is invalid */
1431 librad_log("Duplicate tag %s for attribute %s",
1433 DEBUG("Duplicate tag %s for attribute %s\n",
1438 /* Colon found and attribute allows a tag */
1439 if (value[1] == '*' && value[2] == ':') {
1440 /* Wildcard tag for check items */
1445 tag = strtol(value + 1, &tc, 0);
1446 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1454 vp->flags.tag = tag;
1457 switch (vp->operator) {
1462 * For =* and !* operators, the value is irrelevant
1466 case T_OP_CMP_FALSE:
1467 vp->vp_strvalue[0] = '\0';
1473 * Regular expression comparison of integer attributes
1474 * does a STRING comparison of the names of their
1475 * integer attributes.
1477 case T_OP_REG_EQ: /* =~ */
1478 case T_OP_REG_NE: /* !~ */
1479 if (vp->type == PW_TYPE_INTEGER) {
1484 * Regular expression match with no regular
1485 * expression is wrong.
1492 res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);
1496 regerror(res, &cre, msg, sizeof(msg));
1497 librad_log("Illegal regular expression in attribute: %s: %s",
1504 librad_log("Regelar expressions not enabled in this build, error in attribute %s",
1512 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1513 * then the user MAY have typed in the attribute name
1514 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1516 * We probably want to fix pairparsevalue to accept
1517 * octets as values for any attribute.
1519 if (value && (pairparsevalue(vp, value) == NULL)) {
1531 static const int valid_attr_name[256] = {
1532 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1533 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1534 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1535 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1536 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1537 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1538 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1539 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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,
1544 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1545 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1546 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1547 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1551 * Read a valuepair from a buffer, and advance pointer.
1552 * Sets *eol to T_EOL if end of line was encountered.
1554 VALUE_PAIR *pairread(char **ptr, FR_TOKEN *eol)
1560 FR_TOKEN token, t, xlat;
1564 *eol = T_OP_INVALID;
1567 while ((*p == ' ') || (*p == '\t')) p++;
1570 *eol = T_OP_INVALID;
1571 librad_log("No token read where we expected an attribute name");
1577 librad_log("Read a comment instead of a token");
1582 for (len = 0; len < sizeof(attr); len++) {
1583 if (valid_attr_name[(int)*p]) {
1590 if (len == sizeof(attr)) {
1591 *eol = T_OP_INVALID;
1592 librad_log("Attribute name is too long");
1597 * We may have Foo-Bar:= stuff, so back up.
1599 if (attr[len - 1] == ':') {
1607 /* Now we should have an operator here. */
1608 token = gettoken(ptr, buf, sizeof(buf));
1609 if (token < T_EQSTART || token > T_EQEND) {
1610 librad_log("expecting operator");
1614 /* Read value. Note that empty string values are allowed */
1615 xlat = gettoken(ptr, value, sizeof(value));
1616 if (xlat == T_EOL) {
1617 librad_log("failed to get value");
1622 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1625 t = gettoken(&p, buf, sizeof(buf));
1626 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1627 librad_log("Expected end of line or comma");
1639 * Make the full pair now.
1642 vp = pairmake(attr, value, token);
1648 case T_DOUBLE_QUOTED_STRING:
1649 p = strchr(value, '%');
1650 if (p && (p[1] == '{')) {
1651 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1652 librad_log("Value too long");
1655 vp = pairmake(attr, NULL, token);
1657 *eol = T_OP_INVALID;
1661 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1662 vp->flags.do_xlat = 1;
1665 vp = pairmake(attr, value, token);
1671 * Mark the pair to be allocated later.
1673 case T_BACK_QUOTED_STRING:
1674 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1675 librad_log("Value too long");
1679 vp = pairmake(attr, NULL, token);
1681 *eol = T_OP_INVALID;
1685 vp->flags.do_xlat = 1;
1686 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1692 * If we didn't make a pair, return an error.
1695 *eol = T_OP_INVALID;
1703 * Read one line of attribute/value pairs. This might contain
1704 * multiple pairs seperated by comma's.
1706 FR_TOKEN userparse(char *buffer, VALUE_PAIR **first_pair)
1710 FR_TOKEN last_token = T_OP_INVALID;
1711 FR_TOKEN previous_token;
1714 * We allow an empty line.
1721 previous_token = last_token;
1722 if ((vp = pairread(&p, &last_token)) == NULL) {
1725 pairadd(first_pair, vp);
1726 } while (*p && (last_token == T_COMMA));
1729 * Don't tell the caller that there was a comment.
1731 if (last_token == T_HASH) {
1732 return previous_token;
1736 * And return the last token which we read.
1742 * Read valuepairs from the fp up to End-Of-File.
1744 * Hmm... this function is only used by radclient..
1746 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1749 FR_TOKEN last_token = T_EOL;
1756 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1758 * If we get a '\n' by itself, we assume that's
1759 * the end of that VP
1761 if ((buf[0] == '\n') && (list)) {
1764 if ((buf[0] == '\n') && (!list)) {
1769 * Comments get ignored
1771 if (buf[0] == '#') continue;
1774 * Read all of the attributes on the current line.
1777 last_token = userparse(buf, &vp);
1779 if (last_token != T_EOL) {
1780 librad_perror("%s", errprefix);
1791 if (error) pairfree(&list);
1795 return error ? NULL: list;
1801 * Compare two pairs, using the operator from "one".
1803 * i.e. given two attributes, it does:
1805 * (two->data) (one->operator) (one->data)
1807 * e.g. "foo" != "bar"
1809 * Returns true (comparison is true), or false (comparison is not true);
1811 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1815 switch (one->operator) {
1817 return (two != NULL);
1819 case T_OP_CMP_FALSE:
1820 return (two == NULL);
1823 * One is a regex, compile it, print two to a string,
1824 * and then do string comparisons.
1828 #ifndef HAVE_REGEX_H
1833 char buffer[MAX_STRING_LEN * 4 + 1];
1835 compare = regcomp(®, one->vp_strvalue,
1838 regerror(compare, ®, buffer, sizeof(buffer));
1839 librad_log("Illegal regular expression in attribute: %s: %s",
1844 vp_prints_value(buffer, sizeof(buffer), two, 0);
1847 * Don't care about substring matches,
1850 compare = regexec(®, buffer, 0, NULL, 0);
1853 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1854 return (compare != 0);
1858 default: /* we're OK */
1863 * After doing the previous check for special comparisons,
1864 * do the per-type comparison here.
1866 switch (one->type) {
1867 case PW_TYPE_ABINARY:
1868 case PW_TYPE_OCTETS:
1871 const uint8_t *p, *q;
1873 if (one->length < two->length) {
1874 length = one->length;
1876 length = two->length;
1882 compare = ((int) *p) - ((int) *q);
1883 if (compare != 0) goto type_switch;
1887 * Contents are the same. The return code
1888 * is therefore the difference in lengths.
1890 * i.e. "0x00" is smaller than "0x0000"
1892 compare = two->length - one->length;
1896 case PW_TYPE_STRING:
1897 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
1902 case PW_TYPE_INTEGER:
1904 compare = two->vp_integer - one->vp_integer;
1907 case PW_TYPE_IPADDR:
1908 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1911 case PW_TYPE_IPV6ADDR:
1912 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1913 sizeof(two->vp_ipv6addr));
1916 case PW_TYPE_IPV6PREFIX:
1917 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
1918 sizeof(two->vp_ipv6prefix));
1922 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
1923 sizeof(two->vp_ifid));
1927 return 0; /* unknown type */
1931 * Now do the operator comparison.
1934 switch (one->operator) {
1936 return (compare == 0);
1939 return (compare != 0);
1942 return (compare < 0);
1945 return (compare > 0);
1948 return (compare <= 0);
1951 return (compare >= 0);