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:
138 * Create a new valuepair.
140 VALUE_PAIR *paircreate_raw(int attr, int vendor, int type, VALUE_PAIR *vp)
142 char *p = (char *) (vp + 1);
144 if (!vp->flags.unknown_attr) {
150 vp->attribute = attr;
151 vp->operator = T_OP_EQ;
155 memset(&vp->flags, 0, sizeof(vp->flags));
156 vp->flags.unknown_attr = 1;
158 if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute, vp->vendor)) {
167 * Create a new valuepair.
169 VALUE_PAIR *paircreate(int attr, int vendor, int type)
174 da = dict_attrbyvalue(attr, vendor);
175 if ((vp = pairalloc(da)) == NULL) {
176 fr_strerror_printf("out of memory");
179 vp->operator = T_OP_EQ;
182 * It isn't in the dictionary: update the name.
184 if (!da) return paircreate_raw(attr, vendor, type, vp);
190 * release the memory used by a single attribute-value pair
191 * just a wrapper around free() for now.
193 void pairbasicfree(VALUE_PAIR *pair)
195 if (pair->type == PW_TYPE_TLV) free(pair->vp_tlv);
196 /* clear the memory here */
197 memset(pair, 0, sizeof(*pair));
202 * Release the memory used by a list of attribute-value
203 * pairs, and sets the pair pointer to NULL.
205 void pairfree(VALUE_PAIR **pair_ptr)
207 VALUE_PAIR *next, *pair;
209 if (!pair_ptr) return;
212 while (pair != NULL) {
223 * Find the pair with the matching attribute
225 VALUE_PAIR * pairfind(VALUE_PAIR *first, unsigned int attr, unsigned int vendor)
228 if ((first->attribute == attr) && (first->vendor == vendor)) {
239 * Delete the pair(s) with the matching attribute
241 void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor)
243 VALUE_PAIR *i, *next;
244 VALUE_PAIR **last = first;
246 for(i = *first; i; i = next) {
248 if ((i->attribute == attr) && (i->vendor == vendor)) {
258 * Add a pair at the end of a VALUE_PAIR list.
260 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
266 if (*first == NULL) {
270 for(i = *first; i->next; i = i->next)
276 * Add or replace a pair at the end of a VALUE_PAIR list.
278 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
280 VALUE_PAIR *i, *next;
281 VALUE_PAIR **prev = first;
283 if (*first == NULL) {
289 * Not an empty list, so find item if it is there, and
290 * replace it. Note, we always replace the first one, and
291 * we ignore any others that might exist.
293 for(i = *first; i; i = next) {
297 * Found the first attribute, replace it,
300 if ((i->attribute == replace->attribute) &&
301 (i->vendor == replace->vendor)) {
305 * Should really assert that replace->next == NULL
307 replace->next = next;
313 * Point to where the attribute should go.
319 * If we got here, we didn't find anything to replace, so
320 * stopped at the last item, which we just append to.
329 VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
334 if (!vp->flags.unknown_attr) {
337 name_len = FR_VP_NAME_PAD;
340 if ((n = malloc(sizeof(*n) + name_len)) == NULL) {
341 fr_strerror_printf("out of memory");
344 memcpy(n, vp, sizeof(*n) + name_len);
347 * Reset the name field to point to the NEW attribute,
348 * rather than to the OLD one.
350 if (vp->flags.unknown_attr) n->name = (char *) (n + 1);
354 if ((n->type == PW_TYPE_TLV) &&
355 (n->vp_tlv != NULL)) {
356 n->vp_tlv = malloc(n->length);
357 memcpy(n->vp_tlv, vp->vp_tlv, n->length);
365 * Copy just a certain type of pairs.
367 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor)
369 VALUE_PAIR *first, *n, **last;
376 !((vp->attribute == attr) && (vp->vendor == vendor))) {
382 if (!n) return first;
394 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
396 return paircopy2(vp, 0, 0);
401 * Move attributes from one list to the other
402 * if not already present.
404 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
406 VALUE_PAIR **tailto, *i, *j, *next;
407 VALUE_PAIR *tailfrom = NULL;
409 int has_password = 0;
412 * First, see if there are any passwords here, and
413 * point "tailto" to the end of the "to" list.
416 for(i = *to; i; i = i->next) {
417 if (i->attribute == PW_USER_PASSWORD ||
418 i->attribute == PW_CRYPT_PASSWORD)
424 * Loop over the "from" list.
426 for(i = *from; i; i = next) {
430 * If there was a password in the "to" list,
431 * do not move any other password from the
432 * "from" to the "to" list.
435 (i->attribute == PW_USER_PASSWORD ||
436 i->attribute == PW_CRYPT_PASSWORD)) {
441 switch (i->operator) {
443 * These are COMPARISON attributes
444 * from a check list, and are not
445 * supposed to be copied!
463 * If the attribute is already present in "to",
464 * do not move it from "from" to "to". We make
465 * an exception for "Hint" which can appear multiple
466 * times, and we never move "Fall-Through".
468 if (i->attribute == PW_FALL_THROUGH ||
469 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
471 found = pairfind(*to, i->attribute, i->vendor);
472 switch (i->operator) {
475 * If matching attributes are found,
478 case T_OP_SUB: /* -= */
480 if (!i->vp_strvalue[0] ||
481 (strcmp((char *)found->vp_strvalue,
482 (char *)i->vp_strvalue) == 0)){
483 pairdelete(to, found->attribute, found->vendor);
486 * 'tailto' may have been
490 for(j = *to; j; j = j->next) {
499 /* really HAVE_REGEX_H */
502 * Attr-Name =~ "s/find/replace/"
504 * Very bad code. Barely working,
510 (i->vp_strvalue[0] == 's')) {
517 p = i->vp_strvalue + 1;
518 q = strchr(p + 1, *p);
519 if (!q || (q[strlen(q) - 1] != *p)) {
523 str = strdup(i->vp_strvalue + 2);
526 q[strlen(q) - 1] = '\0';
528 regcomp(®, str, 0);
529 if (regexec(®, found->vp_strvalue,
531 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
532 found->vp_strvalue, match[0].rm_so,
539 tailfrom = i; /* don't copy it over */
543 case T_OP_EQ: /* = */
545 * FIXME: Tunnel attributes with
546 * different tags are different
551 continue; /* with the loop */
556 * If a similar attribute is found,
557 * replace it with the new one. Otherwise,
558 * add the new one to the list.
560 case T_OP_SET: /* := */
562 VALUE_PAIR *mynext = found->next;
565 * Do NOT call pairdelete()
566 * here, due to issues with
567 * re-writing "request->username".
569 * Everybody calls pairmove,
570 * and expects it to work.
571 * We can't update request->username
572 * here, so instead we over-write
573 * the vp that it's pointing to.
575 memcpy(found, i, sizeof(*found));
576 found->next = mynext;
578 pairdelete(&found->next, found->attribute, found->vendor);
581 * 'tailto' may have been
584 for(j = found; j; j = j->next) {
592 * Add the new element to the list, even
593 * if similar ones already exist.
596 case T_OP_ADD: /* += */
601 tailfrom->next = next;
606 * If ALL of the 'to' attributes have been deleted,
607 * then ensure that the 'tail' is updated to point
622 * Move one kind of attributes from one list to the other
624 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor)
626 VALUE_PAIR *to_tail, *i, *next;
627 VALUE_PAIR *iprev = NULL;
630 * Find the last pair in the "to" list and put it in "to_tail".
634 for(i = *to; i; i = i->next)
639 for(i = *from; i; i = next) {
643 * vendor=0, attr = PW_VENDOR_SPECIFIC means
644 * "match any vendor attribute".
646 if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
648 * It's a VSA: move it over.
650 if (i->vendor != 0) goto move;
653 * It's Vendor-Specific: move it over.
655 if (i->attribute == attr) goto move;
658 * It's not a VSA: ignore it.
665 * If it isn't an exact match, ignore it.
667 if (!((i->vendor == vendor) && (i->attribute == attr))) {
674 * Remove the attribute from the "from" list.
682 * Add the attribute to the "to" list.
695 * Sort of strtok/strsep function.
697 static char *mystrtok(char **ptr, const char *sep)
703 while (**ptr && strchr(sep, **ptr))
708 while (**ptr && strchr(sep, **ptr) == NULL)
716 * Turn printable string into time_t
717 * Returns -1 on error, 0 on OK.
719 static int gettime(const char *valstr, time_t *date)
730 * Test for unix timestamp date
732 *date = strtoul(valstr, &tail, 10);
738 memset(tm, 0, sizeof(*tm));
739 tm->tm_isdst = -1; /* don't know, and don't care about DST */
741 strlcpy(buf, valstr, sizeof(buf));
744 f[0] = mystrtok(&p, " \t");
745 f[1] = mystrtok(&p, " \t");
746 f[2] = mystrtok(&p, " \t");
747 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
748 if (!f[0] || !f[1] || !f[2]) return -1;
751 * The time has a colon, where nothing else does.
752 * So if we find it, bubble it to the back of the list.
755 for (i = 0; i < 3; i++) {
756 if (strchr(f[i], ':')) {
766 * The month is text, which allows us to find it easily.
769 for (i = 0; i < 3; i++) {
770 if (isalpha( (int) *f[i])) {
772 * Bubble the month to the front of the list
778 for (i = 0; i < 12; i++) {
779 if (strncasecmp(months[i], f[0], 3) == 0) {
787 /* month not found? */
788 if (tm->tm_mon == 12) return -1;
791 * The year may be in f[1], or in f[2]
793 tm->tm_year = atoi(f[1]);
794 tm->tm_mday = atoi(f[2]);
796 if (tm->tm_year >= 1900) {
801 * We can't use 2-digit years any more, they make it
802 * impossible to tell what's the day, and what's the year.
804 if (tm->tm_mday < 1900) return -1;
807 * Swap the year and the day.
810 tm->tm_year = tm->tm_mday - 1900;
815 * If the day is out of range, die.
817 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
822 * There may be %H:%M:%S. Parse it in a hacky way.
825 f[0] = f[3]; /* HH */
826 f[1] = strchr(f[0], ':'); /* find : separator */
827 if (!f[1]) return -1;
829 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
831 f[2] = strchr(f[1], ':'); /* find : separator */
833 *(f[2]++) = '\0'; /* nuke it, and point to SS */
834 tm->tm_sec = atoi(f[2]);
835 } /* else leave it as zero */
837 tm->tm_hour = atoi(f[0]);
838 tm->tm_min = atoi(f[1]);
842 * Returns -1 on error.
845 if (t == (time_t) -1) return -1;
852 static const char *hextab = "0123456789abcdef";
855 * Parse a string value into a given VALUE_PAIR
857 * FIXME: we probably want to fix this function to accept
858 * octets as values for any type of attribute. We should then
859 * double-check the parsed value, to be sure it's legal for that
860 * type (length, etc.)
862 static uint32_t getint(const char *value, char **end)
864 if ((value[0] == '0') && (value[1] == 'x')) {
865 return strtoul(value, end, 16);
868 return strtoul(value, end, 10);
871 static int check_for_whitespace(const char *value)
874 if (!isspace((int) *value)) return 0;
883 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
891 if (!value) return NULL;
894 * Even for integers, dates and ip addresses we
895 * keep the original string in vp->vp_strvalue.
897 if (vp->type != PW_TYPE_TLV) {
898 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
899 vp->length = strlen(vp->vp_strvalue);
911 while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) {
945 c = '\\'; /* no cp++ */
948 if ((cp[0] >= '0') &&
954 (sscanf(cp, "%3o", &x) == 1)) {
957 } /* else just do '\\' */
963 vp->vp_strvalue[length] = '\0';
969 * It's a comparison, not a real IP.
971 if ((vp->operator == T_OP_REG_EQ) ||
972 (vp->operator == T_OP_REG_NE)) {
977 * FIXME: complain if hostname
978 * cannot be resolved, or resolve later!
981 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
982 cs = s = strdup(value);
986 vp->flags.addport = 1;
995 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
997 fr_strerror_printf("Failed to find IP address for %s", cs);
1001 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1011 * Note that ALL integers are unsigned!
1013 vp->vp_integer = getint(value, &p);
1015 if (vp->vp_integer > 255) {
1016 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
1021 if (check_for_whitespace(p)) break;
1022 goto check_for_value;
1026 * Note that ALL integers are unsigned!
1028 vp->vp_integer = getint(value, &p);
1031 if (vp->vp_integer > 65535) {
1032 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
1037 if (check_for_whitespace(p)) break;
1038 goto check_for_value;
1040 case PW_TYPE_INTEGER:
1042 * Note that ALL integers are unsigned!
1044 vp->vp_integer = getint(value, &p);
1047 if (check_for_whitespace(p)) break;
1051 * Look for the named value for the given
1054 if ((dval = dict_valbyname(vp->attribute, vp->vendor, value)) == NULL) {
1055 fr_strerror_printf("Unknown value %s for attribute %s",
1059 vp->vp_integer = dval->value;
1065 * time_t may be 64 bits, whule vp_date
1066 * MUST be 32-bits. We need an
1067 * intermediary variable to handle
1072 if (gettime(value, &date) < 0) {
1073 fr_strerror_printf("failed to parse time string "
1083 case PW_TYPE_ABINARY:
1084 #ifdef ASCEND_BINARY
1085 if (strncasecmp(value, "0x", 2) == 0) {
1086 vp->type = PW_TYPE_OCTETS;
1090 if (ascend_parse_filter(vp) < 0 ) {
1091 fr_strerror_printf("failed to parse Ascend binary attribute: %s",
1098 * If Ascend binary is NOT defined,
1099 * then fall through to raw octets, so that
1100 * the user can at least make them by hand...
1104 /* raw octets: 0x01020304... */
1105 case PW_TYPE_OCTETS:
1106 if (strncasecmp(value, "0x", 2) == 0) {
1114 * There is only one character,
1117 if ((strlen(cp) & 0x01) != 0) {
1118 fr_strerror_printf("Hex string is not an even length string.");
1124 (vp->length < MAX_STRING_LEN)) {
1127 if (sscanf(cp, "%02x", &tmp) != 1) {
1128 fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]);
1140 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1141 fr_strerror_printf("failed to parse interface-id "
1142 "string \"%s\"", value);
1148 case PW_TYPE_IPV6ADDR:
1152 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1155 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1157 fr_strerror_printf("failed to parse IPv6 address "
1158 "string \"%s\": %s", value, buffer);
1161 vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
1162 vp->length = 16; /* length of IPv6 address */
1166 case PW_TYPE_IPV6PREFIX:
1167 p = strchr(value, '/');
1168 if (!p || ((p - value) >= 256)) {
1169 fr_strerror_printf("invalid IPv6 prefix "
1170 "string \"%s\"", value);
1173 unsigned int prefix;
1174 char buffer[256], *eptr;
1176 memcpy(buffer, value, p - value);
1177 buffer[p - value] = '\0';
1179 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1180 fr_strerror_printf("failed to parse IPv6 address "
1181 "string \"%s\"", value);
1185 prefix = strtoul(p + 1, &eptr, 10);
1186 if ((prefix > 128) || *eptr) {
1187 fr_strerror_printf("failed to parse IPv6 address "
1188 "string \"%s\"", value);
1191 vp->vp_octets[1] = prefix;
1193 vp->vp_octets[0] = '\0';
1194 vp->length = 16 + 2;
1197 case PW_TYPE_ETHERNET:
1199 const char *c1, *c2;
1206 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1208 } else if ((cp[1] != '\0') &&
1211 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1212 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1214 if (*cp == ':') cp++;
1218 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1219 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1222 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1229 case PW_TYPE_COMBO_IP:
1230 if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
1231 vp->type = PW_TYPE_IPV6ADDR;
1232 vp->length = 16; /* length of IPv6 address */
1233 vp->vp_strvalue[vp->length] = '\0';
1238 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1239 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1243 vp->type = PW_TYPE_IPADDR;
1244 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1249 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1250 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1254 case PW_TYPE_TLV: /* don't use this! */
1255 if (strncasecmp(value, "0x", 2) != 0) {
1256 fr_strerror_printf("Invalid TLV specification");
1259 length = strlen(value + 2) / 2;
1260 if (vp->length < length) {
1264 vp->vp_tlv = malloc(length);
1266 fr_strerror_printf("No memory");
1269 if (fr_hex2bin(value + 2, vp->vp_tlv,
1270 length) != length) {
1271 fr_strerror_printf("Invalid hex data in TLV");
1274 vp->length = length;
1281 fr_strerror_printf("unknown attribute type %d", vp->type);
1289 * Create a VALUE_PAIR from an ASCII attribute and value,
1290 * where the attribute name is in the form:
1294 * VendorName-Attr-%d
1296 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1301 const char *p = attribute;
1306 * Unknown attributes MUST be of type 'octets'
1308 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1309 fr_strerror_printf("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1316 * Pull off vendor prefix first.
1318 if (strncasecmp(p, "Attr-", 5) != 0) {
1319 if (strncasecmp(p, "Vendor-", 7) == 0) {
1320 vendor = (int) strtol(p + 7, &q, 10);
1321 if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
1322 fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
1328 } else { /* must be vendor name */
1334 fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", attribute);
1338 if ((size_t) (q - p) >= sizeof(buffer)) {
1339 fr_strerror_printf("Vendor name too long in attribute name \"%s\"", attribute);
1343 memcpy(buffer, p, (q - p));
1344 buffer[q - p] = '\0';
1346 vendor = dict_vendorbyname(buffer);
1348 fr_strerror_printf("Unknown vendor name in attribute name \"%s\"", attribute);
1356 fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1365 if (strncasecmp(p, "Attr-", 5) != 0) {
1366 fr_strerror_printf("Invalid format in attribute name \"%s\"", attribute);
1370 attr = strtol(p + 5, &q, 10);
1373 * Invalid, or trailing text after number.
1375 if ((attr == 0) || *q) {
1376 fr_strerror_printf("Invalid value in attribute name \"%s\"", attribute);
1381 * Double-check the size of attr.
1384 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1389 fr_strerror_printf("Invalid attribute number in attribute name \"%s\"", attribute);
1393 } else switch (dv->type) {
1395 if (attr > 255) goto attr_error;
1399 if (attr > 65535) goto attr_error;
1406 fr_strerror_printf("Internal sanity check failed");
1412 * We've now parsed the attribute properly, Let's create
1413 * it. This next stop also looks the attribute up in the
1414 * dictionary, and creates the appropriate type for it.
1416 if ((vp = paircreate(attr, vendor, PW_TYPE_OCTETS)) == NULL) {
1417 fr_strerror_printf("out of memory");
1421 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1422 if (!value) return vp;
1424 size = strlen(value + 2);
1427 * We may be reading something like Attr-5. i.e.
1428 * who-ever wrote the text didn't understand it, but we
1433 if (size == (vp->length * 2)) break;
1434 vp->type = PW_TYPE_OCTETS;
1437 case PW_TYPE_STRING:
1438 case PW_TYPE_OCTETS:
1439 case PW_TYPE_ABINARY:
1440 vp->length = size >> 1;
1444 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1445 fr_strerror_printf("Invalid hex string");
1451 * Move contents around based on type. This is
1452 * to work around the historical use of "lvalue".
1456 case PW_TYPE_IPADDR:
1457 case PW_TYPE_INTEGER:
1458 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1459 vp->vp_strvalue[0] = '\0';
1471 * Create a VALUE_PAIR from an ASCII attribute and value.
1473 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1481 const char *attrname = attribute;
1484 * Check for tags in 'Attribute:Tag' format.
1489 ts = strrchr(attribute, ':');
1491 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1496 strlcpy(buffer, attribute, sizeof(buffer));
1498 ts = strrchr(attrname, ':');
1500 /* Colon found with something behind it */
1501 if (ts[1] == '*' && ts[2] == 0) {
1502 /* Wildcard tag for check items */
1505 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1506 /* It's not a wild card tag */
1507 tag = strtol(ts + 1, &tc, 0);
1508 if (tc && !*tc && TAG_VALID_ZERO(tag))
1512 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1519 * It's not found in the dictionary, so we use
1520 * another method to create the attribute.
1522 if ((da = dict_attrbyname(attrname)) == NULL) {
1523 return pairmake_any(attrname, value, operator);
1526 if ((vp = pairalloc(da)) == NULL) {
1527 fr_strerror_printf("out of memory");
1530 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1532 /* Check for a tag in the 'Merit' format of:
1533 * :Tag:Value. Print an error if we already found
1534 * a tag in the Attribute.
1537 if (value && (*value == ':' && da->flags.has_tag)) {
1538 /* If we already found a tag, this is invalid */
1540 fr_strerror_printf("Duplicate tag %s for attribute %s",
1542 DEBUG("Duplicate tag %s for attribute %s\n",
1547 /* Colon found and attribute allows a tag */
1548 if (value[1] == '*' && value[2] == ':') {
1549 /* Wildcard tag for check items */
1554 tag = strtol(value + 1, &tc, 0);
1555 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1563 vp->flags.tag = tag;
1566 switch (vp->operator) {
1571 * For =* and !* operators, the value is irrelevant
1575 case T_OP_CMP_FALSE:
1576 vp->vp_strvalue[0] = '\0';
1582 * Regular expression comparison of integer attributes
1583 * does a STRING comparison of the names of their
1584 * integer attributes.
1586 case T_OP_REG_EQ: /* =~ */
1587 case T_OP_REG_NE: /* !~ */
1589 fr_strerror_printf("No regular expression found in %s",
1595 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1596 vp->length = strlen(vp->vp_strvalue);
1598 * If anything goes wrong, this is a run-time error,
1599 * not a compile-time error.
1606 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1607 * then the user MAY have typed in the attribute name
1608 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1610 * We probably want to fix pairparsevalue to accept
1611 * octets as values for any attribute.
1613 if (value && (pairparsevalue(vp, value) == NULL)) {
1625 static const int valid_attr_name[256] = {
1626 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1627 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1628 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1629 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1630 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1631 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1632 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1633 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1635 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1636 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1637 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1638 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1640 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1641 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1645 * Read a valuepair from a buffer, and advance pointer.
1646 * Sets *eol to T_EOL if end of line was encountered.
1648 VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol)
1652 char value[1024], *q;
1654 FR_TOKEN token, t, xlat;
1658 *eol = T_OP_INVALID;
1661 while ((*p == ' ') || (*p == '\t')) p++;
1664 *eol = T_OP_INVALID;
1665 fr_strerror_printf("No token read where we expected an attribute name");
1671 fr_strerror_printf("Read a comment instead of a token");
1676 for (len = 0; len < sizeof(attr); len++) {
1677 if (valid_attr_name[(int)*p]) {
1684 if (len == sizeof(attr)) {
1685 *eol = T_OP_INVALID;
1686 fr_strerror_printf("Attribute name is too long");
1691 * We may have Foo-Bar:= stuff, so back up.
1693 if ((len > 0) && (attr[len - 1] == ':')) {
1701 /* Now we should have an operator here. */
1702 token = gettoken(ptr, buf, sizeof(buf));
1703 if (token < T_EQSTART || token > T_EQEND) {
1704 fr_strerror_printf("expecting operator");
1708 /* Read value. Note that empty string values are allowed */
1709 xlat = gettoken(ptr, value, sizeof(value));
1710 if (xlat == T_EOL) {
1711 fr_strerror_printf("failed to get value");
1716 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1719 t = gettoken(&p, buf, sizeof(buf));
1720 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1721 fr_strerror_printf("Expected end of line or comma");
1733 * Make the full pair now.
1736 vp = pairmake(attr, value, token);
1742 case T_DOUBLE_QUOTED_STRING:
1743 p = strchr(value, '%');
1744 if (p && (p[1] == '{')) {
1745 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1746 fr_strerror_printf("Value too long");
1749 vp = pairmake(attr, NULL, token);
1751 *eol = T_OP_INVALID;
1755 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1756 vp->flags.do_xlat = 1;
1760 * Parse && escape it, as defined by the
1763 vp = pairmake(attr, value, token);
1765 *eol = T_OP_INVALID;
1771 case T_SINGLE_QUOTED_STRING:
1772 vp = pairmake(attr, NULL, token);
1774 *eol = T_OP_INVALID;
1779 * String and octet types get copied verbatim.
1781 if ((vp->type == PW_TYPE_STRING) ||
1782 (vp->type == PW_TYPE_OCTETS)) {
1783 strlcpy(vp->vp_strvalue, value,
1784 sizeof(vp->vp_strvalue));
1785 vp->length = strlen(vp->vp_strvalue);
1788 * Everything else gets parsed: it's
1789 * DATA, not a string!
1791 } else if (!pairparsevalue(vp, value)) {
1793 *eol = T_OP_INVALID;
1799 * Mark the pair to be allocated later.
1801 case T_BACK_QUOTED_STRING:
1802 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1803 fr_strerror_printf("Value too long");
1807 vp = pairmake(attr, NULL, token);
1809 *eol = T_OP_INVALID;
1813 vp->flags.do_xlat = 1;
1814 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1820 * If we didn't make a pair, return an error.
1823 *eol = T_OP_INVALID;
1831 * Read one line of attribute/value pairs. This might contain
1832 * multiple pairs seperated by comma's.
1834 FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
1838 FR_TOKEN last_token = T_OP_INVALID;
1839 FR_TOKEN previous_token;
1842 * We allow an empty line.
1849 previous_token = last_token;
1850 if ((vp = pairread(&p, &last_token)) == NULL) {
1853 pairadd(first_pair, vp);
1854 } while (*p && (last_token == T_COMMA));
1857 * Don't tell the caller that there was a comment.
1859 if (last_token == T_HASH) {
1860 return previous_token;
1864 * And return the last token which we read.
1870 * Read valuepairs from the fp up to End-Of-File.
1872 * Hmm... this function is only used by radclient..
1874 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1877 FR_TOKEN last_token = T_EOL;
1884 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1886 * If we get a '\n' by itself, we assume that's
1887 * the end of that VP
1889 if ((buf[0] == '\n') && (list)) {
1892 if ((buf[0] == '\n') && (!list)) {
1897 * Comments get ignored
1899 if (buf[0] == '#') continue;
1902 * Read all of the attributes on the current line.
1905 last_token = userparse(buf, &vp);
1907 if (last_token != T_EOL) {
1908 fr_perror("%s", errprefix);
1919 if (error) pairfree(&list);
1923 return error ? NULL: list;
1929 * Compare two pairs, using the operator from "one".
1931 * i.e. given two attributes, it does:
1933 * (two->data) (one->operator) (one->data)
1935 * e.g. "foo" != "bar"
1937 * Returns true (comparison is true), or false (comparison is not true);
1939 * FIXME: Ignores tags!
1941 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1945 switch (one->operator) {
1947 return (two != NULL);
1949 case T_OP_CMP_FALSE:
1950 return (two == NULL);
1953 * One is a regex, compile it, print two to a string,
1954 * and then do string comparisons.
1958 #ifndef HAVE_REGEX_H
1963 char buffer[MAX_STRING_LEN * 4 + 1];
1965 compare = regcomp(®, one->vp_strvalue,
1968 regerror(compare, ®, buffer, sizeof(buffer));
1969 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1974 vp_prints_value(buffer, sizeof(buffer), two, 0);
1977 * Don't care about substring matches,
1980 compare = regexec(®, buffer, 0, NULL, 0);
1983 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1984 return (compare != 0);
1988 default: /* we're OK */
1993 * After doing the previous check for special comparisons,
1994 * do the per-type comparison here.
1996 switch (one->type) {
1997 case PW_TYPE_ABINARY:
1998 case PW_TYPE_OCTETS:
2002 if (one->length < two->length) {
2003 length = one->length;
2005 length = two->length;
2009 compare = memcmp(two->vp_octets, one->vp_octets,
2011 if (compare != 0) break;
2015 * Contents are the same. The return code
2016 * is therefore the difference in lengths.
2018 * i.e. "0x00" is smaller than "0x0000"
2020 compare = two->length - one->length;
2024 case PW_TYPE_STRING:
2025 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
2030 case PW_TYPE_INTEGER:
2032 compare = two->vp_integer - one->vp_integer;
2035 case PW_TYPE_IPADDR:
2036 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
2039 case PW_TYPE_IPV6ADDR:
2040 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
2041 sizeof(two->vp_ipv6addr));
2044 case PW_TYPE_IPV6PREFIX:
2045 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
2046 sizeof(two->vp_ipv6prefix));
2050 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
2051 sizeof(two->vp_ifid));
2055 return 0; /* unknown type */
2059 * Now do the operator comparison.
2061 switch (one->operator) {
2063 return (compare == 0);
2066 return (compare != 0);
2069 return (compare < 0);
2072 return (compare > 0);
2075 return (compare <= 0);
2078 return (compare >= 0);