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)
211 while(first && (first->attribute != attr) && (first->vendor != vendor))
218 * Delete the pair(s) with the matching attribute
220 void pairdelete(VALUE_PAIR **first, int attr, int vendor)
222 VALUE_PAIR *i, *next;
223 VALUE_PAIR **last = first;
225 for(i = *first; i; i = next) {
227 if ((i->attribute == attr) && (i->vendor == vendor)) {
237 * Add a pair at the end of a VALUE_PAIR list.
239 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
245 if (*first == NULL) {
249 for(i = *first; i->next; i = i->next)
255 * Add or replace a pair at the end of a VALUE_PAIR list.
257 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
259 VALUE_PAIR *i, *next;
260 VALUE_PAIR **prev = first;
262 if (*first == NULL) {
268 * Not an empty list, so find item if it is there, and
269 * replace it. Note, we always replace the first one, and
270 * we ignore any others that might exist.
272 for(i = *first; i; i = next) {
276 * Found the first attribute, replace it,
279 if (i->attribute == replace->attribute) {
283 * Should really assert that replace->next == NULL
285 replace->next = next;
291 * Point to where the attribute should go.
297 * If we got here, we didn't find anything to replace, so
298 * stopped at the last item, which we just append to.
307 VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
312 if (!vp->flags.unknown_attr) {
315 name_len = FR_VP_NAME_PAD;
318 if ((n = malloc(sizeof(*n) + name_len)) == NULL) {
319 fr_strerror_printf("out of memory");
322 memcpy(n, vp, sizeof(*n) + name_len);
325 if ((n->type == PW_TYPE_TLV) &&
326 (n->vp_tlv != NULL)) {
327 n->vp_tlv = malloc(n->length);
328 memcpy(n->vp_tlv, vp->vp_tlv, n->length);
336 * Copy just a certain type of pairs.
338 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr, int vendor)
340 VALUE_PAIR *first, *n, **last;
347 (vp->attribute != attr) && (vp->vendor != vendor)) {
353 if (!n) return first;
365 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
367 return paircopy2(vp, -1, 0);
372 * Move attributes from one list to the other
373 * if not already present.
375 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
377 VALUE_PAIR **tailto, *i, *j, *next;
378 VALUE_PAIR *tailfrom = NULL;
380 int has_password = 0;
383 * First, see if there are any passwords here, and
384 * point "tailto" to the end of the "to" list.
387 for(i = *to; i; i = i->next) {
388 if (i->attribute == PW_USER_PASSWORD ||
389 i->attribute == PW_CRYPT_PASSWORD)
395 * Loop over the "from" list.
397 for(i = *from; i; i = next) {
401 * If there was a password in the "to" list,
402 * do not move any other password from the
403 * "from" to the "to" list.
406 (i->attribute == PW_USER_PASSWORD ||
407 i->attribute == PW_CRYPT_PASSWORD)) {
412 switch (i->operator) {
414 * These are COMPARISON attributes
415 * from a check list, and are not
416 * supposed to be copied!
434 * If the attribute is already present in "to",
435 * do not move it from "from" to "to". We make
436 * an exception for "Hint" which can appear multiple
437 * times, and we never move "Fall-Through".
439 if (i->attribute == PW_FALL_THROUGH ||
440 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
442 found = pairfind(*to, i->attribute, i->vendor);
443 switch (i->operator) {
446 * If matching attributes are found,
449 case T_OP_SUB: /* -= */
451 if (!i->vp_strvalue[0] ||
452 (strcmp((char *)found->vp_strvalue,
453 (char *)i->vp_strvalue) == 0)){
454 pairdelete(to, found->attribute, found->vendor);
457 * 'tailto' may have been
461 for(j = *to; j; j = j->next) {
470 /* really HAVE_REGEX_H */
473 * Attr-Name =~ "s/find/replace/"
475 * Very bad code. Barely working,
481 (i->vp_strvalue[0] == 's')) {
488 p = i->vp_strvalue + 1;
489 q = strchr(p + 1, *p);
490 if (!q || (q[strlen(q) - 1] != *p)) {
494 str = strdup(i->vp_strvalue + 2);
497 q[strlen(q) - 1] = '\0';
499 regcomp(®, str, 0);
500 if (regexec(®, found->vp_strvalue,
502 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
503 found->vp_strvalue, match[0].rm_so,
510 tailfrom = i; /* don't copy it over */
514 case T_OP_EQ: /* = */
516 * FIXME: Tunnel attributes with
517 * different tags are different
522 continue; /* with the loop */
527 * If a similar attribute is found,
528 * replace it with the new one. Otherwise,
529 * add the new one to the list.
531 case T_OP_SET: /* := */
533 VALUE_PAIR *mynext = found->next;
536 * Do NOT call pairdelete()
537 * here, due to issues with
538 * re-writing "request->username".
540 * Everybody calls pairmove,
541 * and expects it to work.
542 * We can't update request->username
543 * here, so instead we over-write
544 * the vp that it's pointing to.
546 memcpy(found, i, sizeof(*found));
547 found->next = mynext;
549 pairdelete(&found->next, found->attribute, found->vendor);
552 * 'tailto' may have been
555 for(j = found; j; j = j->next) {
563 * Add the new element to the list, even
564 * if similar ones already exist.
567 case T_OP_ADD: /* += */
572 tailfrom->next = next;
577 * If ALL of the 'to' attributes have been deleted,
578 * then ensure that the 'tail' is updated to point
593 * Move one kind of attributes from one list to the other
595 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr, int vendor)
597 VALUE_PAIR *to_tail, *i, *next;
598 VALUE_PAIR *iprev = NULL;
601 * Find the last pair in the "to" list and put it in "to_tail".
605 for(i = *to; i; i = i->next)
610 for(i = *from; i; i = next) {
614 * vendor=0, attr = PW_VENDOR_SPECIFIC means
615 * "match any vendor attribute". Otherwise, do
618 if (((vendor != 0) || (attr != PW_VENDOR_SPECIFIC)) &&
619 (i->attribute != attr) && (i->vendor != vendor)) {
625 * If the attribute to move IS a VSA, then it ignores
626 * any non-VSA attribute.
628 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC) &&
635 * Remove the attribute from the "from" list.
643 * Add the attribute to the "to" list.
656 * Sort of strtok/strsep function.
658 static char *mystrtok(char **ptr, const char *sep)
664 while (**ptr && strchr(sep, **ptr))
669 while (**ptr && strchr(sep, **ptr) == NULL)
677 * Turn printable string into time_t
678 * Returns -1 on error, 0 on OK.
680 static int gettime(const char *valstr, time_t *date)
691 * Test for unix timestamp date
693 *date = strtoul(valstr, &tail, 10);
699 memset(tm, 0, sizeof(*tm));
700 tm->tm_isdst = -1; /* don't know, and don't care about DST */
702 strlcpy(buf, valstr, sizeof(buf));
705 f[0] = mystrtok(&p, " \t");
706 f[1] = mystrtok(&p, " \t");
707 f[2] = mystrtok(&p, " \t");
708 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
709 if (!f[0] || !f[1] || !f[2]) return -1;
712 * The time has a colon, where nothing else does.
713 * So if we find it, bubble it to the back of the list.
716 for (i = 0; i < 3; i++) {
717 if (strchr(f[i], ':')) {
727 * The month is text, which allows us to find it easily.
730 for (i = 0; i < 3; i++) {
731 if (isalpha( (int) *f[i])) {
733 * Bubble the month to the front of the list
739 for (i = 0; i < 12; i++) {
740 if (strncasecmp(months[i], f[0], 3) == 0) {
748 /* month not found? */
749 if (tm->tm_mon == 12) return -1;
752 * The year may be in f[1], or in f[2]
754 tm->tm_year = atoi(f[1]);
755 tm->tm_mday = atoi(f[2]);
757 if (tm->tm_year >= 1900) {
762 * We can't use 2-digit years any more, they make it
763 * impossible to tell what's the day, and what's the year.
765 if (tm->tm_mday < 1900) return -1;
768 * Swap the year and the day.
771 tm->tm_year = tm->tm_mday - 1900;
776 * If the day is out of range, die.
778 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
783 * There may be %H:%M:%S. Parse it in a hacky way.
786 f[0] = f[3]; /* HH */
787 f[1] = strchr(f[0], ':'); /* find : separator */
788 if (!f[1]) return -1;
790 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
792 f[2] = strchr(f[1], ':'); /* find : separator */
794 *(f[2]++) = '\0'; /* nuke it, and point to SS */
796 strcpy(f[2], "0"); /* assignment would discard const */
799 tm->tm_hour = atoi(f[0]);
800 tm->tm_min = atoi(f[1]);
801 tm->tm_sec = atoi(f[2]);
805 * Returns -1 on error.
808 if (t == (time_t) -1) return -1;
815 static const char *hextab = "0123456789abcdef";
818 * Parse a string value into a given VALUE_PAIR
820 * FIXME: we probably want to fix this function to accept
821 * octets as values for any type of attribute. We should then
822 * double-check the parsed value, to be sure it's legal for that
823 * type (length, etc.)
825 static uint32_t getint(const char *value, char **end)
827 if ((value[0] == '0') && (value[1] == 'x')) {
828 return strtoul(value, end, 16);
831 return strtoul(value, end, 10);
834 static int check_for_whitespace(const char *value)
837 if (!isspace((int) *value)) return 0;
846 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
854 if (!value) return NULL;
857 * Even for integers, dates and ip addresses we
858 * keep the original string in vp->vp_strvalue.
860 if (vp->type != PW_TYPE_TLV) {
861 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
862 vp->length = strlen(vp->vp_strvalue);
874 while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) {
904 c = '\\'; /* no cp++ */
907 if ((cp[0] >= '0') &&
913 (sscanf(cp, "%3o", &x) == 1)) {
916 } /* else just do '\\' */
927 * It's a comparison, not a real IP.
929 if ((vp->operator == T_OP_REG_EQ) ||
930 (vp->operator == T_OP_REG_NE)) {
935 * FIXME: complain if hostname
936 * cannot be resolved, or resolve later!
939 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
940 cs = s = strdup(value);
944 vp->flags.addport = 1;
953 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
955 fr_strerror_printf("Failed to find IP address for %s", cs);
959 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
969 * Note that ALL integers are unsigned!
971 vp->vp_integer = getint(value, &p);
973 if (vp->vp_integer > 255) {
974 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
979 if (check_for_whitespace(p)) break;
980 goto check_for_value;
984 * Note that ALL integers are unsigned!
986 vp->vp_integer = getint(value, &p);
989 if (vp->vp_integer > 65535) {
990 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
995 if (check_for_whitespace(p)) break;
996 goto check_for_value;
998 case PW_TYPE_INTEGER:
1000 * Note that ALL integers are unsigned!
1002 vp->vp_integer = getint(value, &p);
1005 if (check_for_whitespace(p)) break;
1009 * Look for the named value for the given
1012 if ((dval = dict_valbyname(vp->attribute, vp->vendor, value)) == NULL) {
1013 fr_strerror_printf("Unknown value %s for attribute %s",
1017 vp->vp_integer = dval->value;
1023 * time_t may be 64 bits, whule vp_date
1024 * MUST be 32-bits. We need an
1025 * intermediary variable to handle
1030 if (gettime(value, &date) < 0) {
1031 fr_strerror_printf("failed to parse time string "
1041 case PW_TYPE_ABINARY:
1042 #ifdef ASCEND_BINARY
1043 if (strncasecmp(value, "0x", 2) == 0) {
1044 vp->type = PW_TYPE_OCTETS;
1048 if (ascend_parse_filter(vp) < 0 ) {
1049 fr_strerror_printf("failed to parse Ascend binary attribute: %s",
1056 * If Ascend binary is NOT defined,
1057 * then fall through to raw octets, so that
1058 * the user can at least make them by hand...
1062 /* raw octets: 0x01020304... */
1063 case PW_TYPE_OCTETS:
1064 if (strncasecmp(value, "0x", 2) == 0) {
1072 * There is only one character,
1075 if ((strlen(cp) & 0x01) != 0) {
1076 fr_strerror_printf("Hex string is not an even length string.");
1082 (vp->length < MAX_STRING_LEN)) {
1085 if (sscanf(cp, "%02x", &tmp) != 1) {
1086 fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]);
1098 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1099 fr_strerror_printf("failed to parse interface-id "
1100 "string \"%s\"", value);
1106 case PW_TYPE_IPV6ADDR:
1107 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
1108 fr_strerror_printf("failed to parse IPv6 address "
1109 "string \"%s\"", value);
1112 vp->length = 16; /* length of IPv6 address */
1115 case PW_TYPE_IPV6PREFIX:
1116 p = strchr(value, '/');
1117 if (!p || ((p - value) >= 256)) {
1118 fr_strerror_printf("invalid IPv6 prefix "
1119 "string \"%s\"", value);
1122 unsigned int prefix;
1123 char buffer[256], *eptr;
1125 memcpy(buffer, value, p - value);
1126 buffer[p - value] = '\0';
1128 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1129 fr_strerror_printf("failed to parse IPv6 address "
1130 "string \"%s\"", value);
1134 prefix = strtoul(p + 1, &eptr, 10);
1135 if ((prefix > 128) || *eptr) {
1136 fr_strerror_printf("failed to parse IPv6 address "
1137 "string \"%s\"", value);
1140 vp->vp_octets[1] = prefix;
1142 vp->vp_octets[0] = '\0';
1143 vp->length = 16 + 2;
1146 case PW_TYPE_ETHERNET:
1148 const char *c1, *c2;
1155 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1157 } else if ((cp[1] != '\0') &&
1160 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1161 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1163 if (*cp == ':') cp++;
1167 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1168 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1171 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1178 case PW_TYPE_COMBO_IP:
1179 if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
1180 vp->type = PW_TYPE_IPV6ADDR;
1181 vp->length = 16; /* length of IPv6 address */
1182 vp->vp_strvalue[vp->length] = '\0';
1187 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1188 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1192 vp->type = PW_TYPE_IPADDR;
1193 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1198 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1199 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1203 case PW_TYPE_TLV: /* don't use this! */
1204 if (strncasecmp(value, "0x", 2) != 0) {
1205 fr_strerror_printf("Invalid TLV specification");
1208 length = strlen(value + 2) / 2;
1209 if (vp->length < length) {
1213 vp->vp_tlv = malloc(length);
1215 fr_strerror_printf("No memory");
1218 if (fr_hex2bin(value + 2, vp->vp_tlv,
1219 length) != length) {
1220 fr_strerror_printf("Invalid hex data in TLV");
1223 vp->length = length;
1230 fr_strerror_printf("unknown attribute type %d", vp->type);
1238 * Create a VALUE_PAIR from an ASCII attribute and value,
1239 * where the attribute name is in the form:
1243 * VendorName-Attr-%d
1245 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1250 const char *p = attribute;
1255 * Unknown attributes MUST be of type 'octets'
1257 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1258 fr_strerror_printf("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1265 * Pull off vendor prefix first.
1267 if (strncasecmp(p, "Attr-", 5) != 0) {
1268 if (strncasecmp(p, "Vendor-", 7) == 0) {
1269 vendor = (int) strtol(p + 7, &q, 10);
1270 if ((vendor == 0) || (vendor > 65535)) {
1271 fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
1277 } else { /* must be vendor name */
1283 fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", attribute);
1287 if ((size_t) (q - p) >= sizeof(buffer)) {
1288 fr_strerror_printf("Vendor name too long in attribute name \"%s\"", attribute);
1292 memcpy(buffer, p, (q - p));
1293 buffer[q - p] = '\0';
1295 vendor = dict_vendorbyname(buffer);
1297 fr_strerror_printf("Unknown vendor name in attribute name \"%s\"", attribute);
1305 fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1314 if (strncasecmp(p, "Attr-", 5) != 0) {
1315 fr_strerror_printf("Invalid format in attribute name \"%s\"", attribute);
1319 attr = strtol(p + 5, &q, 10);
1322 * Invalid, or trailing text after number.
1324 if ((attr == 0) || *q) {
1325 fr_strerror_printf("Invalid value in attribute name \"%s\"", attribute);
1330 * Double-check the size of attr.
1333 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1338 fr_strerror_printf("Invalid attribute number in attribute name \"%s\"", attribute);
1342 } else switch (dv->type) {
1344 if (attr > 255) goto attr_error;
1348 if (attr > 65535) goto attr_error;
1351 case 4: /* Internal limitations! */
1352 if (attr > 65535) goto attr_error;
1356 fr_strerror_printf("Internal sanity check failed");
1362 * We've now parsed the attribute properly, Let's create
1363 * it. This next stop also looks the attribute up in the
1364 * dictionary, and creates the appropriate type for it.
1366 if ((vp = paircreate(attr, vendor, PW_TYPE_OCTETS)) == NULL) {
1367 fr_strerror_printf("out of memory");
1371 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1372 if (!value) return vp;
1374 size = strlen(value + 2);
1377 * We may be reading something like Attr-5. i.e.
1378 * who-ever wrote the text didn't understand it, but we
1383 if (size == (vp->length * 2)) break;
1384 vp->type = PW_TYPE_OCTETS;
1387 case PW_TYPE_STRING:
1388 case PW_TYPE_OCTETS:
1389 case PW_TYPE_ABINARY:
1390 vp->length = size >> 1;
1394 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1395 fr_strerror_printf("Invalid hex string");
1401 * Move contents around based on type. This is
1402 * to work around the historical use of "lvalue".
1406 case PW_TYPE_IPADDR:
1407 case PW_TYPE_INTEGER:
1408 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1409 vp->vp_strvalue[0] = '\0';
1421 * Create a VALUE_PAIR from an ASCII attribute and value.
1423 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1431 const char *attrname = attribute;
1434 * Check for tags in 'Attribute:Tag' format.
1439 ts = strrchr(attribute, ':');
1441 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1446 strlcpy(buffer, attribute, sizeof(buffer));
1448 ts = strrchr(attrname, ':');
1450 /* Colon found with something behind it */
1451 if (ts[1] == '*' && ts[2] == 0) {
1452 /* Wildcard tag for check items */
1455 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1456 /* It's not a wild card tag */
1457 tag = strtol(ts + 1, &tc, 0);
1458 if (tc && !*tc && TAG_VALID_ZERO(tag))
1462 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1469 * It's not found in the dictionary, so we use
1470 * another method to create the attribute.
1472 if ((da = dict_attrbyname(attrname)) == NULL) {
1473 return pairmake_any(attrname, value, operator);
1476 if ((vp = pairalloc(da)) == NULL) {
1477 fr_strerror_printf("out of memory");
1480 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1482 /* Check for a tag in the 'Merit' format of:
1483 * :Tag:Value. Print an error if we already found
1484 * a tag in the Attribute.
1487 if (value && (*value == ':' && da->flags.has_tag)) {
1488 /* If we already found a tag, this is invalid */
1490 fr_strerror_printf("Duplicate tag %s for attribute %s",
1492 DEBUG("Duplicate tag %s for attribute %s\n",
1497 /* Colon found and attribute allows a tag */
1498 if (value[1] == '*' && value[2] == ':') {
1499 /* Wildcard tag for check items */
1504 tag = strtol(value + 1, &tc, 0);
1505 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1513 vp->flags.tag = tag;
1516 switch (vp->operator) {
1521 * For =* and !* operators, the value is irrelevant
1525 case T_OP_CMP_FALSE:
1526 vp->vp_strvalue[0] = '\0';
1532 * Regular expression comparison of integer attributes
1533 * does a STRING comparison of the names of their
1534 * integer attributes.
1536 case T_OP_REG_EQ: /* =~ */
1537 case T_OP_REG_NE: /* !~ */
1539 fr_strerror_printf("No regular expression found in %s",
1545 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1546 vp->length = strlen(vp->vp_strvalue);
1548 * If anything goes wrong, this is a run-time error,
1549 * not a compile-time error.
1556 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1557 * then the user MAY have typed in the attribute name
1558 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1560 * We probably want to fix pairparsevalue to accept
1561 * octets as values for any attribute.
1563 if (value && (pairparsevalue(vp, value) == NULL)) {
1575 static const int valid_attr_name[256] = {
1576 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1577 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1578 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1579 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1580 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1581 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1582 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1583 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1584 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1585 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1586 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1587 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1588 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1589 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1590 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1591 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1595 * Read a valuepair from a buffer, and advance pointer.
1596 * Sets *eol to T_EOL if end of line was encountered.
1598 VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol)
1602 char value[1024], *q;
1604 FR_TOKEN token, t, xlat;
1608 *eol = T_OP_INVALID;
1611 while ((*p == ' ') || (*p == '\t')) p++;
1614 *eol = T_OP_INVALID;
1615 fr_strerror_printf("No token read where we expected an attribute name");
1621 fr_strerror_printf("Read a comment instead of a token");
1626 for (len = 0; len < sizeof(attr); len++) {
1627 if (valid_attr_name[(int)*p]) {
1634 if (len == sizeof(attr)) {
1635 *eol = T_OP_INVALID;
1636 fr_strerror_printf("Attribute name is too long");
1641 * We may have Foo-Bar:= stuff, so back up.
1643 if ((len > 0) && (attr[len - 1] == ':')) {
1651 /* Now we should have an operator here. */
1652 token = gettoken(ptr, buf, sizeof(buf));
1653 if (token < T_EQSTART || token > T_EQEND) {
1654 fr_strerror_printf("expecting operator");
1658 /* Read value. Note that empty string values are allowed */
1659 xlat = gettoken(ptr, value, sizeof(value));
1660 if (xlat == T_EOL) {
1661 fr_strerror_printf("failed to get value");
1666 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1669 t = gettoken(&p, buf, sizeof(buf));
1670 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1671 fr_strerror_printf("Expected end of line or comma");
1683 * Make the full pair now.
1686 vp = pairmake(attr, value, token);
1692 case T_DOUBLE_QUOTED_STRING:
1693 p = strchr(value, '%');
1694 if (p && (p[1] == '{')) {
1695 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1696 fr_strerror_printf("Value too long");
1699 vp = pairmake(attr, NULL, token);
1701 *eol = T_OP_INVALID;
1705 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1706 vp->flags.do_xlat = 1;
1710 * Parse && escape it, as defined by the
1713 vp = pairmake(attr, value, token);
1715 *eol = T_OP_INVALID;
1721 case T_SINGLE_QUOTED_STRING:
1722 vp = pairmake(attr, NULL, token);
1724 *eol = T_OP_INVALID;
1729 * String and octet types get copied verbatim.
1731 if ((vp->type == PW_TYPE_STRING) ||
1732 (vp->type == PW_TYPE_OCTETS)) {
1733 strlcpy(vp->vp_strvalue, value,
1734 sizeof(vp->vp_strvalue));
1735 vp->length = strlen(vp->vp_strvalue);
1738 * Everything else gets parsed: it's
1739 * DATA, not a string!
1741 } else if (!pairparsevalue(vp, value)) {
1743 *eol = T_OP_INVALID;
1749 * Mark the pair to be allocated later.
1751 case T_BACK_QUOTED_STRING:
1752 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1753 fr_strerror_printf("Value too long");
1757 vp = pairmake(attr, NULL, token);
1759 *eol = T_OP_INVALID;
1763 vp->flags.do_xlat = 1;
1764 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1770 * If we didn't make a pair, return an error.
1773 *eol = T_OP_INVALID;
1781 * Read one line of attribute/value pairs. This might contain
1782 * multiple pairs seperated by comma's.
1784 FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
1788 FR_TOKEN last_token = T_OP_INVALID;
1789 FR_TOKEN previous_token;
1792 * We allow an empty line.
1799 previous_token = last_token;
1800 if ((vp = pairread(&p, &last_token)) == NULL) {
1803 pairadd(first_pair, vp);
1804 } while (*p && (last_token == T_COMMA));
1807 * Don't tell the caller that there was a comment.
1809 if (last_token == T_HASH) {
1810 return previous_token;
1814 * And return the last token which we read.
1820 * Read valuepairs from the fp up to End-Of-File.
1822 * Hmm... this function is only used by radclient..
1824 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1827 FR_TOKEN last_token = T_EOL;
1834 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1836 * If we get a '\n' by itself, we assume that's
1837 * the end of that VP
1839 if ((buf[0] == '\n') && (list)) {
1842 if ((buf[0] == '\n') && (!list)) {
1847 * Comments get ignored
1849 if (buf[0] == '#') continue;
1852 * Read all of the attributes on the current line.
1855 last_token = userparse(buf, &vp);
1857 if (last_token != T_EOL) {
1858 fr_perror("%s", errprefix);
1869 if (error) pairfree(&list);
1873 return error ? NULL: list;
1879 * Compare two pairs, using the operator from "one".
1881 * i.e. given two attributes, it does:
1883 * (two->data) (one->operator) (one->data)
1885 * e.g. "foo" != "bar"
1887 * Returns true (comparison is true), or false (comparison is not true);
1889 * FIXME: Ignores tags!
1891 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1895 switch (one->operator) {
1897 return (two != NULL);
1899 case T_OP_CMP_FALSE:
1900 return (two == NULL);
1903 * One is a regex, compile it, print two to a string,
1904 * and then do string comparisons.
1908 #ifndef HAVE_REGEX_H
1913 char buffer[MAX_STRING_LEN * 4 + 1];
1915 compare = regcomp(®, one->vp_strvalue,
1918 regerror(compare, ®, buffer, sizeof(buffer));
1919 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1924 vp_prints_value(buffer, sizeof(buffer), two, 0);
1927 * Don't care about substring matches,
1930 compare = regexec(®, buffer, 0, NULL, 0);
1933 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1934 return (compare != 0);
1938 default: /* we're OK */
1943 * After doing the previous check for special comparisons,
1944 * do the per-type comparison here.
1946 switch (one->type) {
1947 case PW_TYPE_ABINARY:
1948 case PW_TYPE_OCTETS:
1952 if (one->length < two->length) {
1953 length = one->length;
1955 length = two->length;
1959 compare = memcmp(two->vp_octets, one->vp_octets,
1961 if (compare != 0) break;
1965 * Contents are the same. The return code
1966 * is therefore the difference in lengths.
1968 * i.e. "0x00" is smaller than "0x0000"
1970 compare = two->length - one->length;
1974 case PW_TYPE_STRING:
1975 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
1980 case PW_TYPE_INTEGER:
1982 compare = two->vp_integer - one->vp_integer;
1985 case PW_TYPE_IPADDR:
1986 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1989 case PW_TYPE_IPV6ADDR:
1990 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1991 sizeof(two->vp_ipv6addr));
1994 case PW_TYPE_IPV6PREFIX:
1995 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
1996 sizeof(two->vp_ipv6prefix));
2000 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
2001 sizeof(two->vp_ifid));
2005 return 0; /* unknown type */
2009 * Now do the operator comparison.
2011 switch (one->operator) {
2013 return (compare == 0);
2016 return (compare != 0);
2019 return (compare < 0);
2022 return (compare > 0);
2025 return (compare <= 0);
2028 return (compare >= 0);