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 type)
146 da = dict_attrbyvalue(attr);
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);
159 vp->vendor = VENDOR(attr);
160 vp->attribute = attr;
162 vp->type = type; /* be forgiving */
164 if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute)) {
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)
211 while(first && first->attribute != attr)
218 * Delete the pair(s) with the matching attribute
220 void pairdelete(VALUE_PAIR **first, int attr)
222 VALUE_PAIR *i, *next;
223 VALUE_PAIR **last = first;
225 for(i = *first; i; i = next) {
227 if (i->attribute == attr) {
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)
340 VALUE_PAIR *first, *n, **last;
346 if (attr >= 0 && vp->attribute != attr) {
352 if (!n) return first;
364 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
366 return paircopy2(vp, -1);
371 * Move attributes from one list to the other
372 * if not already present.
374 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
376 VALUE_PAIR **tailto, *i, *j, *next;
377 VALUE_PAIR *tailfrom = NULL;
379 int has_password = 0;
382 * First, see if there are any passwords here, and
383 * point "tailto" to the end of the "to" list.
386 for(i = *to; i; i = i->next) {
387 if (i->attribute == PW_USER_PASSWORD ||
388 i->attribute == PW_CRYPT_PASSWORD)
394 * Loop over the "from" list.
396 for(i = *from; i; i = next) {
400 * If there was a password in the "to" list,
401 * do not move any other password from the
402 * "from" to the "to" list.
405 (i->attribute == PW_USER_PASSWORD ||
406 i->attribute == PW_CRYPT_PASSWORD)) {
411 switch (i->operator) {
413 * These are COMPARISON attributes
414 * from a check list, and are not
415 * supposed to be copied!
433 * If the attribute is already present in "to",
434 * do not move it from "from" to "to". We make
435 * an exception for "Hint" which can appear multiple
436 * times, and we never move "Fall-Through".
438 if (i->attribute == PW_FALL_THROUGH ||
439 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
441 found = pairfind(*to, i->attribute);
442 switch (i->operator) {
445 * If matching attributes are found,
448 case T_OP_SUB: /* -= */
450 if (!i->vp_strvalue[0] ||
451 (strcmp((char *)found->vp_strvalue,
452 (char *)i->vp_strvalue) == 0)){
453 pairdelete(to, found->attribute);
456 * 'tailto' may have been
460 for(j = *to; j; j = j->next) {
469 /* really HAVE_REGEX_H */
472 * Attr-Name =~ "s/find/replace/"
474 * Very bad code. Barely working,
480 (i->vp_strvalue[0] == 's')) {
487 p = i->vp_strvalue + 1;
488 q = strchr(p + 1, *p);
489 if (!q || (q[strlen(q) - 1] != *p)) {
493 str = strdup(i->vp_strvalue + 2);
496 q[strlen(q) - 1] = '\0';
498 regcomp(®, str, 0);
499 if (regexec(®, found->vp_strvalue,
501 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
502 found->vp_strvalue, match[0].rm_so,
509 tailfrom = i; /* don't copy it over */
513 case T_OP_EQ: /* = */
515 * FIXME: Tunnel attributes with
516 * different tags are different
521 continue; /* with the loop */
526 * If a similar attribute is found,
527 * replace it with the new one. Otherwise,
528 * add the new one to the list.
530 case T_OP_SET: /* := */
532 VALUE_PAIR *mynext = found->next;
535 * Do NOT call pairdelete()
536 * here, due to issues with
537 * re-writing "request->username".
539 * Everybody calls pairmove,
540 * and expects it to work.
541 * We can't update request->username
542 * here, so instead we over-write
543 * the vp that it's pointing to.
545 memcpy(found, i, sizeof(*found));
546 found->next = mynext;
548 pairdelete(&found->next, found->attribute);
551 * 'tailto' may have been
554 for(j = found; j; j = j->next) {
562 * Add the new element to the list, even
563 * if similar ones already exist.
566 case T_OP_ADD: /* += */
571 tailfrom->next = next;
576 * If ALL of the 'to' attributes have been deleted,
577 * then ensure that the 'tail' is updated to point
592 * Move one kind of attributes from one list to the other
594 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
596 VALUE_PAIR *to_tail, *i, *next;
597 VALUE_PAIR *iprev = NULL;
600 * Find the last pair in the "to" list and put it in "to_tail".
604 for(i = *to; i; i = i->next)
609 for(i = *from; i; i = next) {
614 * If the attribute to move is NOT a VSA, then it
615 * ignores any attributes which do not match exactly.
617 if ((attr != PW_VENDOR_SPECIFIC) &&
618 (i->attribute != attr)) {
624 * If the attribute to move IS a VSA, then it ignores
625 * any non-VSA attribute.
627 if ((attr == PW_VENDOR_SPECIFIC) &&
628 (VENDOR(i->attribute) == 0)) {
634 * Remove the attribute from the "from" list.
642 * Add the attribute to the "to" list.
655 * Sort of strtok/strsep function.
657 static char *mystrtok(char **ptr, const char *sep)
663 while (**ptr && strchr(sep, **ptr))
668 while (**ptr && strchr(sep, **ptr) == NULL)
676 * Turn printable string into time_t
677 * Returns -1 on error, 0 on OK.
679 static int gettime(const char *valstr, time_t *date)
690 * Test for unix timestamp date
692 *date = strtoul(valstr, &tail, 10);
698 memset(tm, 0, sizeof(*tm));
699 tm->tm_isdst = -1; /* don't know, and don't care about DST */
701 strlcpy(buf, valstr, sizeof(buf));
704 f[0] = mystrtok(&p, " \t");
705 f[1] = mystrtok(&p, " \t");
706 f[2] = mystrtok(&p, " \t");
707 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
708 if (!f[0] || !f[1] || !f[2]) return -1;
711 * The time has a colon, where nothing else does.
712 * So if we find it, bubble it to the back of the list.
715 for (i = 0; i < 3; i++) {
716 if (strchr(f[i], ':')) {
726 * The month is text, which allows us to find it easily.
729 for (i = 0; i < 3; i++) {
730 if (isalpha( (int) *f[i])) {
732 * Bubble the month to the front of the list
738 for (i = 0; i < 12; i++) {
739 if (strncasecmp(months[i], f[0], 3) == 0) {
747 /* month not found? */
748 if (tm->tm_mon == 12) return -1;
751 * The year may be in f[1], or in f[2]
753 tm->tm_year = atoi(f[1]);
754 tm->tm_mday = atoi(f[2]);
756 if (tm->tm_year >= 1900) {
761 * We can't use 2-digit years any more, they make it
762 * impossible to tell what's the day, and what's the year.
764 if (tm->tm_mday < 1900) return -1;
767 * Swap the year and the day.
770 tm->tm_year = tm->tm_mday - 1900;
775 * If the day is out of range, die.
777 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
782 * There may be %H:%M:%S. Parse it in a hacky way.
785 f[0] = f[3]; /* HH */
786 f[1] = strchr(f[0], ':'); /* find : separator */
787 if (!f[1]) return -1;
789 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
791 f[2] = strchr(f[1], ':'); /* find : separator */
793 *(f[2]++) = '\0'; /* nuke it, and point to SS */
795 strcpy(f[2], "0"); /* assignment would discard const */
798 tm->tm_hour = atoi(f[0]);
799 tm->tm_min = atoi(f[1]);
800 tm->tm_sec = atoi(f[2]);
804 * Returns -1 on error.
807 if (t == (time_t) -1) return -1;
814 static const char *hextab = "0123456789abcdef";
817 * Parse a string value into a given VALUE_PAIR
819 * FIXME: we probably want to fix this function to accept
820 * octets as values for any type of attribute. We should then
821 * double-check the parsed value, to be sure it's legal for that
822 * type (length, etc.)
824 static uint32_t getint(const char *value, char **end)
826 if ((value[0] == '0') && (value[1] == 'x')) {
827 return strtoul(value, end, 16);
830 return strtoul(value, end, 10);
833 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
841 if (!value) return NULL;
844 * Even for integers, dates and ip addresses we
845 * keep the original string in vp->vp_strvalue.
847 if (vp->type != PW_TYPE_TLV) {
848 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
849 vp->length = strlen(vp->vp_strvalue);
861 while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) {
891 c = '\\'; /* no cp++ */
894 if ((cp[0] >= '0') &&
900 (sscanf(cp, "%3o", &x) == 1)) {
903 } /* else just do '\\' */
914 * It's a comparison, not a real IP.
916 if ((vp->operator == T_OP_REG_EQ) ||
917 (vp->operator == T_OP_REG_NE)) {
922 * FIXME: complain if hostname
923 * cannot be resolved, or resolve later!
926 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
927 cs = s = strdup(value);
931 vp->flags.addport = 1;
940 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
942 fr_strerror_printf("Failed to find IP address for %s", cs);
946 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
954 * Note that ALL integers are unsigned!
956 vp->vp_integer = getint(value, &p);
958 if (vp->vp_integer > 255) {
959 fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
967 * Look for the named value for the given
970 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
971 fr_strerror_printf("Unknown value %s for attribute %s",
975 vp->vp_integer = dval->value;
981 * Note that ALL integers are unsigned!
983 vp->vp_integer = getint(value, &p);
985 if (vp->vp_integer > 65535) {
986 fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
994 * Look for the named value for the given
997 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
998 fr_strerror_printf("Unknown value %s for attribute %s",
1002 vp->vp_integer = dval->value;
1006 case PW_TYPE_INTEGER:
1008 * Note that ALL integers are unsigned!
1010 vp->vp_integer = getint(value, &p);
1017 * Look for the named value for the given
1020 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
1021 fr_strerror_printf("Unknown value %s for attribute %s",
1025 vp->vp_integer = dval->value;
1032 * time_t may be 64 bits, whule vp_date
1033 * MUST be 32-bits. We need an
1034 * intermediary variable to handle
1039 if (gettime(value, &date) < 0) {
1040 fr_strerror_printf("failed to parse time string "
1050 case PW_TYPE_ABINARY:
1051 #ifdef ASCEND_BINARY
1052 if (strncasecmp(value, "0x", 2) == 0) {
1053 vp->type = PW_TYPE_OCTETS;
1057 if (ascend_parse_filter(vp) < 0 ) {
1058 fr_strerror_printf("failed to parse Ascend binary attribute: %s",
1065 * If Ascend binary is NOT defined,
1066 * then fall through to raw octets, so that
1067 * the user can at least make them by hand...
1071 /* raw octets: 0x01020304... */
1072 case PW_TYPE_OCTETS:
1073 if (strncasecmp(value, "0x", 2) == 0) {
1081 * There is only one character,
1084 if ((strlen(cp) & 0x01) != 0) {
1085 fr_strerror_printf("Hex string is not an even length string.");
1091 (vp->length < MAX_STRING_LEN)) {
1094 if (sscanf(cp, "%02x", &tmp) != 1) {
1095 fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]);
1107 if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
1108 fr_strerror_printf("failed to parse interface-id "
1109 "string \"%s\"", value);
1115 case PW_TYPE_IPV6ADDR:
1116 if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
1117 fr_strerror_printf("failed to parse IPv6 address "
1118 "string \"%s\"", value);
1121 vp->length = 16; /* length of IPv6 address */
1124 case PW_TYPE_IPV6PREFIX:
1125 p = strchr(value, '/');
1126 if (!p || ((p - value) >= 256)) {
1127 fr_strerror_printf("invalid IPv6 prefix "
1128 "string \"%s\"", value);
1131 unsigned int prefix;
1132 char buffer[256], *eptr;
1134 memcpy(buffer, value, p - value);
1135 buffer[p - value] = '\0';
1137 if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
1138 fr_strerror_printf("failed to parse IPv6 address "
1139 "string \"%s\"", value);
1143 prefix = strtoul(p + 1, &eptr, 10);
1144 if ((prefix > 128) || *eptr) {
1145 fr_strerror_printf("failed to parse IPv6 address "
1146 "string \"%s\"", value);
1149 vp->vp_octets[1] = prefix;
1151 vp->vp_octets[0] = '\0';
1152 vp->length = 16 + 2;
1155 case PW_TYPE_ETHERNET:
1157 const char *c1, *c2;
1164 c2 = memchr(hextab, tolower((int) cp[0]), 16);
1166 } else if ((cp[1] != '\0') &&
1169 c1 = memchr(hextab, tolower((int) cp[0]), 16);
1170 c2 = memchr(hextab, tolower((int) cp[1]), 16);
1172 if (*cp == ':') cp++;
1176 if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
1177 fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
1180 vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
1187 case PW_TYPE_COMBO_IP:
1188 if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
1189 vp->type = PW_TYPE_IPV6ADDR;
1190 vp->length = 16; /* length of IPv6 address */
1191 vp->vp_strvalue[vp->length] = '\0';
1196 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
1197 fr_strerror_printf("Failed to find IPv4 address for %s", value);
1201 vp->type = PW_TYPE_IPADDR;
1202 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
1207 case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
1208 vp->vp_signed = (int32_t) strtol(value, &p, 10);
1212 case PW_TYPE_TLV: /* don't use this! */
1213 if (strncasecmp(value, "0x", 2) != 0) {
1214 fr_strerror_printf("Invalid TLV specification");
1217 length = strlen(value + 2) / 2;
1218 if (vp->length < length) {
1222 vp->vp_tlv = malloc(length);
1224 fr_strerror_printf("No memory");
1227 if (fr_hex2bin(value + 2, vp->vp_tlv,
1228 length) != length) {
1229 fr_strerror_printf("Invalid hex data in TLV");
1232 vp->length = length;
1239 fr_strerror_printf("unknown attribute type %d", vp->type);
1247 * Create a VALUE_PAIR from an ASCII attribute and value,
1248 * where the attribute name is in the form:
1252 * VendorName-Attr-%d
1254 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1259 const char *p = attribute;
1264 * Unknown attributes MUST be of type 'octets'
1266 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1267 fr_strerror_printf("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
1274 * Pull off vendor prefix first.
1276 if (strncasecmp(p, "Attr-", 5) != 0) {
1277 if (strncasecmp(p, "Vendor-", 7) == 0) {
1278 vendor = (int) strtol(p + 7, &q, 10);
1279 if ((vendor == 0) || (vendor > 65535)) {
1280 fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
1286 } else { /* must be vendor name */
1292 fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", attribute);
1296 if ((size_t) (q - p) >= sizeof(buffer)) {
1297 fr_strerror_printf("Vendor name too long in attribute name \"%s\"", attribute);
1301 memcpy(buffer, p, (q - p));
1302 buffer[q - p] = '\0';
1304 vendor = dict_vendorbyname(buffer);
1306 fr_strerror_printf("Unknown vendor name in attribute name \"%s\"", attribute);
1314 fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", attribute);
1323 if (strncasecmp(p, "Attr-", 5) != 0) {
1324 fr_strerror_printf("Invalid format in attribute name \"%s\"", attribute);
1328 attr = strtol(p + 5, &q, 10);
1331 * Invalid, or trailing text after number.
1333 if ((attr == 0) || *q) {
1334 fr_strerror_printf("Invalid value in attribute name \"%s\"", attribute);
1339 * Double-check the size of attr.
1342 DICT_VENDOR *dv = dict_vendorbyvalue(vendor);
1347 fr_strerror_printf("Invalid attribute number in attribute name \"%s\"", attribute);
1351 } else switch (dv->type) {
1353 if (attr > 255) goto attr_error;
1357 if (attr > 65535) goto attr_error;
1360 case 4: /* Internal limitations! */
1361 if (attr > 65535) goto attr_error;
1365 fr_strerror_printf("Internal sanity check failed");
1370 attr |= vendor << 16;
1373 * We've now parsed the attribute properly, Let's create
1374 * it. This next stop also looks the attribute up in the
1375 * dictionary, and creates the appropriate type for it.
1377 if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
1378 fr_strerror_printf("out of memory");
1382 size = strlen(value + 2);
1385 * We may be reading something like Attr-5. i.e.
1386 * who-ever wrote the text didn't understand it, but we
1391 if (size == (vp->length * 2)) break;
1392 vp->type = PW_TYPE_OCTETS;
1395 case PW_TYPE_STRING:
1396 case PW_TYPE_OCTETS:
1397 case PW_TYPE_ABINARY:
1398 vp->length = size >> 1;
1402 if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
1403 fr_strerror_printf("Invalid hex string");
1409 * Move contents around based on type. This is
1410 * to work around the historical use of "lvalue".
1414 case PW_TYPE_IPADDR:
1415 case PW_TYPE_INTEGER:
1416 memcpy(&vp->lvalue, vp->vp_octets, sizeof(vp->lvalue));
1417 vp->vp_strvalue[0] = '\0';
1424 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1431 * Create a VALUE_PAIR from an ASCII attribute and value.
1433 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1441 const char *attrname = attribute;
1444 * Check for tags in 'Attribute:Tag' format.
1449 ts = strrchr(attribute, ':');
1451 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1456 strlcpy(buffer, attribute, sizeof(buffer));
1458 ts = strrchr(attrname, ':');
1460 /* Colon found with something behind it */
1461 if (ts[1] == '*' && ts[2] == 0) {
1462 /* Wildcard tag for check items */
1465 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1466 /* It's not a wild card tag */
1467 tag = strtol(ts + 1, &tc, 0);
1468 if (tc && !*tc && TAG_VALID_ZERO(tag))
1472 fr_strerror_printf("Invalid tag for attribute %s", attribute);
1479 * It's not found in the dictionary, so we use
1480 * another method to create the attribute.
1482 if ((da = dict_attrbyname(attrname)) == NULL) {
1483 return pairmake_any(attrname, value, operator);
1486 if ((vp = pairalloc(da)) == NULL) {
1487 fr_strerror_printf("out of memory");
1490 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1492 /* Check for a tag in the 'Merit' format of:
1493 * :Tag:Value. Print an error if we already found
1494 * a tag in the Attribute.
1497 if (value && (*value == ':' && da->flags.has_tag)) {
1498 /* If we already found a tag, this is invalid */
1501 fr_strerror_printf("Duplicate tag %s for attribute %s",
1503 DEBUG("Duplicate tag %s for attribute %s\n",
1508 /* Colon found and attribute allows a tag */
1509 if (value[1] == '*' && value[2] == ':') {
1510 /* Wildcard tag for check items */
1515 tag = strtol(value + 1, &tc, 0);
1516 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1524 vp->flags.tag = tag;
1527 switch (vp->operator) {
1532 * For =* and !* operators, the value is irrelevant
1536 case T_OP_CMP_FALSE:
1537 vp->vp_strvalue[0] = '\0';
1543 * Regular expression comparison of integer attributes
1544 * does a STRING comparison of the names of their
1545 * integer attributes.
1547 case T_OP_REG_EQ: /* =~ */
1548 case T_OP_REG_NE: /* !~ */
1549 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1550 vp->length = strlen(vp->vp_strvalue);
1552 * If anything goes wrong, this is a run-time error,
1553 * not a compile-time error.
1560 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1561 * then the user MAY have typed in the attribute name
1562 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1564 * We probably want to fix pairparsevalue to accept
1565 * octets as values for any attribute.
1567 if (value && (pairparsevalue(vp, value) == NULL)) {
1579 static const int valid_attr_name[256] = {
1580 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1581 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1582 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1583 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1584 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1585 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1586 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1587 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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,
1592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1595 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1599 * Read a valuepair from a buffer, and advance pointer.
1600 * Sets *eol to T_EOL if end of line was encountered.
1602 VALUE_PAIR *pairread(const char **ptr, FR_TOKEN *eol)
1606 char value[1024], *q;
1608 FR_TOKEN token, t, xlat;
1612 *eol = T_OP_INVALID;
1615 while ((*p == ' ') || (*p == '\t')) p++;
1618 *eol = T_OP_INVALID;
1619 fr_strerror_printf("No token read where we expected an attribute name");
1625 fr_strerror_printf("Read a comment instead of a token");
1630 for (len = 0; len < sizeof(attr); len++) {
1631 if (valid_attr_name[(int)*p]) {
1638 if (len == sizeof(attr)) {
1639 *eol = T_OP_INVALID;
1640 fr_strerror_printf("Attribute name is too long");
1645 * We may have Foo-Bar:= stuff, so back up.
1647 if (attr[len - 1] == ':') {
1655 /* Now we should have an operator here. */
1656 token = gettoken(ptr, buf, sizeof(buf));
1657 if (token < T_EQSTART || token > T_EQEND) {
1658 fr_strerror_printf("expecting operator");
1662 /* Read value. Note that empty string values are allowed */
1663 xlat = gettoken(ptr, value, sizeof(value));
1664 if (xlat == T_EOL) {
1665 fr_strerror_printf("failed to get value");
1670 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1673 t = gettoken(&p, buf, sizeof(buf));
1674 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1675 fr_strerror_printf("Expected end of line or comma");
1687 * Make the full pair now.
1690 vp = pairmake(attr, value, token);
1696 case T_DOUBLE_QUOTED_STRING:
1697 p = strchr(value, '%');
1698 if (p && (p[1] == '{')) {
1699 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1700 fr_strerror_printf("Value too long");
1703 vp = pairmake(attr, NULL, token);
1705 *eol = T_OP_INVALID;
1709 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1710 vp->flags.do_xlat = 1;
1714 * Parse && escape it, as defined by the
1717 vp = pairmake(attr, value, token);
1719 *eol = T_OP_INVALID;
1725 case T_SINGLE_QUOTED_STRING:
1726 vp = pairmake(attr, NULL, token);
1728 *eol = T_OP_INVALID;
1733 * String and octet types get copied verbatim.
1735 if ((vp->type == PW_TYPE_STRING) ||
1736 (vp->type == PW_TYPE_OCTETS)) {
1737 strlcpy(vp->vp_strvalue, value,
1738 sizeof(vp->vp_strvalue));
1739 vp->length = strlen(vp->vp_strvalue);
1742 * Everything else gets parsed: it's
1743 * DATA, not a string!
1745 } else if (!pairparsevalue(vp, value)) {
1747 *eol = T_OP_INVALID;
1753 * Mark the pair to be allocated later.
1755 case T_BACK_QUOTED_STRING:
1756 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1757 fr_strerror_printf("Value too long");
1761 vp = pairmake(attr, NULL, token);
1763 *eol = T_OP_INVALID;
1767 vp->flags.do_xlat = 1;
1768 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1774 * If we didn't make a pair, return an error.
1777 *eol = T_OP_INVALID;
1785 * Read one line of attribute/value pairs. This might contain
1786 * multiple pairs seperated by comma's.
1788 FR_TOKEN userparse(const char *buffer, VALUE_PAIR **first_pair)
1792 FR_TOKEN last_token = T_OP_INVALID;
1793 FR_TOKEN previous_token;
1796 * We allow an empty line.
1803 previous_token = last_token;
1804 if ((vp = pairread(&p, &last_token)) == NULL) {
1807 pairadd(first_pair, vp);
1808 } while (*p && (last_token == T_COMMA));
1811 * Don't tell the caller that there was a comment.
1813 if (last_token == T_HASH) {
1814 return previous_token;
1818 * And return the last token which we read.
1824 * Read valuepairs from the fp up to End-Of-File.
1826 * Hmm... this function is only used by radclient..
1828 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1831 FR_TOKEN last_token = T_EOL;
1838 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1840 * If we get a '\n' by itself, we assume that's
1841 * the end of that VP
1843 if ((buf[0] == '\n') && (list)) {
1846 if ((buf[0] == '\n') && (!list)) {
1851 * Comments get ignored
1853 if (buf[0] == '#') continue;
1856 * Read all of the attributes on the current line.
1859 last_token = userparse(buf, &vp);
1861 if (last_token != T_EOL) {
1862 fr_perror("%s", errprefix);
1873 if (error) pairfree(&list);
1877 return error ? NULL: list;
1883 * Compare two pairs, using the operator from "one".
1885 * i.e. given two attributes, it does:
1887 * (two->data) (one->operator) (one->data)
1889 * e.g. "foo" != "bar"
1891 * Returns true (comparison is true), or false (comparison is not true);
1893 * FIXME: Ignores tags!
1895 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1899 switch (one->operator) {
1901 return (two != NULL);
1903 case T_OP_CMP_FALSE:
1904 return (two == NULL);
1907 * One is a regex, compile it, print two to a string,
1908 * and then do string comparisons.
1912 #ifndef HAVE_REGEX_H
1917 char buffer[MAX_STRING_LEN * 4 + 1];
1919 compare = regcomp(®, one->vp_strvalue,
1922 regerror(compare, ®, buffer, sizeof(buffer));
1923 fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
1928 vp_prints_value(buffer, sizeof(buffer), two, 0);
1931 * Don't care about substring matches,
1934 compare = regexec(®, buffer, 0, NULL, 0);
1937 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1938 return (compare != 0);
1942 default: /* we're OK */
1947 * After doing the previous check for special comparisons,
1948 * do the per-type comparison here.
1950 switch (one->type) {
1951 case PW_TYPE_ABINARY:
1952 case PW_TYPE_OCTETS:
1956 if (one->length < two->length) {
1957 length = one->length;
1959 length = two->length;
1963 compare = memcmp(two->vp_octets, one->vp_octets,
1965 if (compare != 0) break;
1969 * Contents are the same. The return code
1970 * is therefore the difference in lengths.
1972 * i.e. "0x00" is smaller than "0x0000"
1974 compare = two->length - one->length;
1978 case PW_TYPE_STRING:
1979 compare = strcmp(two->vp_strvalue, one->vp_strvalue);
1984 case PW_TYPE_INTEGER:
1986 compare = two->vp_integer - one->vp_integer;
1989 case PW_TYPE_IPADDR:
1990 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1993 case PW_TYPE_IPV6ADDR:
1994 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1995 sizeof(two->vp_ipv6addr));
1998 case PW_TYPE_IPV6PREFIX:
1999 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
2000 sizeof(two->vp_ipv6prefix));
2004 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
2005 sizeof(two->vp_ifid));
2009 return 0; /* unknown type */
2013 * Now do the operator comparison.
2015 switch (one->operator) {
2017 return (compare == 0);
2020 return (compare != 0);
2023 return (compare < 0);
2026 return (compare > 0);
2029 return (compare <= 0);
2032 return (compare >= 0);