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" };
42 static VALUE_PAIR *pairalloc(DICT_ATTR *da)
46 vp = malloc(sizeof(*vp));
48 memset(vp, 0, sizeof(*vp));
51 vp->attribute = da->attr;
52 vp->vendor = da->vendor;
54 strlcpy(vp->name, da->name, sizeof(vp->name));
55 vp->flags = da->flags;
59 vp->type = PW_TYPE_OCTETS;
61 memset(&vp->flags, 0, sizeof(vp->flags));
80 vp->length = sizeof(vp->vp_ifid);
83 case PW_TYPE_IPV6ADDR:
84 vp->length = sizeof(vp->vp_ipv6addr);
87 case PW_TYPE_IPV6PREFIX:
88 vp->length = sizeof(vp->vp_ipv6prefix);
101 * Create a new valuepair.
103 VALUE_PAIR *paircreate(int attr, int type)
108 da = dict_attrbyvalue(attr);
109 if ((vp = pairalloc(da)) == NULL) {
110 librad_log("out of memory");
113 vp->operator = T_OP_EQ;
119 if (VENDOR(attr) == 0) {
120 sprintf(vp->name, "Attr-%u", attr);
125 v = dict_vendorbyvalue(VENDOR(attr));
127 sprintf(vp->name, "%s-Attr-%u",
128 v->name, attr & 0xffff);
130 sprintf(vp->name, "Vendor-%u-Attr-%u",
131 VENDOR(attr), attr & 0xffff);
140 * release the memory used by a single attribute-value pair
141 * just a wrapper around free() for now.
143 void pairbasicfree(VALUE_PAIR *pair)
145 /* clear the memory here */
146 memset(pair, 0, sizeof(*pair));
151 * Release the memory used by a list of attribute-value
152 * pairs, and sets the pair pointer to NULL.
154 void pairfree(VALUE_PAIR **pair_ptr)
156 VALUE_PAIR *next, *pair;
158 if (!pair_ptr) return;
161 while (pair != NULL) {
172 * Find the pair with the matching attribute
174 VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
176 while(first && first->attribute != attr)
183 * Delete the pair(s) with the matching attribute
185 void pairdelete(VALUE_PAIR **first, int attr)
187 VALUE_PAIR *i, *next;
188 VALUE_PAIR **last = first;
190 for(i = *first; i; i = next) {
192 if (i->attribute == attr) {
202 * Add a pair at the end of a VALUE_PAIR list.
204 void pairadd(VALUE_PAIR **first, VALUE_PAIR *add)
210 if (*first == NULL) {
214 for(i = *first; i->next; i = i->next)
220 * Add or replace a pair at the end of a VALUE_PAIR list.
222 void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
224 VALUE_PAIR *i, *next;
225 VALUE_PAIR **prev = first;
227 if (*first == NULL) {
233 * Not an empty list, so find item if it is there, and
234 * replace it. Note, we always replace the first one, and
235 * we ignore any others that might exist.
237 for(i = *first; i; i = next) {
241 * Found the first attribute, replace it,
244 if (i->attribute == replace->attribute) {
248 * Should really assert that replace->next == NULL
250 replace->next = next;
256 * Point to where the attribute should go.
262 * If we got here, we didn't find anything to replace, so
263 * stopped at the last item, which we just append to.
269 * Copy just a certain type of pairs.
271 VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
273 VALUE_PAIR *first, *n, **last;
279 if (attr >= 0 && vp->attribute != attr) {
283 if ((n = malloc(sizeof(*n))) == NULL) {
284 librad_log("out of memory");
287 memcpy(n, vp, sizeof(VALUE_PAIR));
300 VALUE_PAIR *paircopy(VALUE_PAIR *vp)
302 return paircopy2(vp, -1);
307 * Move attributes from one list to the other
308 * if not already present.
310 void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
312 VALUE_PAIR **tailto, *i, *j, *next;
313 VALUE_PAIR *tailfrom = NULL;
315 int has_password = 0;
318 * First, see if there are any passwords here, and
319 * point "tailto" to the end of the "to" list.
322 for(i = *to; i; i = i->next) {
323 if (i->attribute == PW_USER_PASSWORD ||
324 i->attribute == PW_CRYPT_PASSWORD)
330 * Loop over the "from" list.
332 for(i = *from; i; i = next) {
336 * If there was a password in the "to" list,
337 * do not move any other password from the
338 * "from" to the "to" list.
341 (i->attribute == PW_USER_PASSWORD ||
342 i->attribute == PW_CRYPT_PASSWORD)) {
347 switch (i->operator) {
349 * These are COMPARISON attributes
350 * from a check list, and are not
351 * supposed to be copied!
369 * If the attribute is already present in "to",
370 * do not move it from "from" to "to". We make
371 * an exception for "Hint" which can appear multiple
372 * times, and we never move "Fall-Through".
374 if (i->attribute == PW_FALL_THROUGH ||
375 (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
377 found = pairfind(*to, i->attribute);
378 switch (i->operator) {
381 * If matching attributes are found,
384 case T_OP_SUB: /* -= */
386 if (!i->vp_strvalue[0] ||
387 (strcmp((char *)found->vp_strvalue,
388 (char *)i->vp_strvalue) == 0)){
389 pairdelete(to, found->attribute);
392 * 'tailto' may have been
396 for(j = *to; j; j = j->next) {
405 /* really HAVE_REGEX_H */
408 * Attr-Name =~ "s/find/replace/"
410 * Very bad code. Barely working,
416 (i->vp_strvalue[0] == 's')) {
423 p = i->vp_strvalue + 1;
424 q = strchr(p + 1, *p);
425 if (!q || (q[strlen(q) - 1] != *p)) {
429 str = strdup(i->vp_strvalue + 2);
432 q[strlen(q) - 1] = '\0';
434 regcomp(®, str, 0);
435 if (regexec(®, found->vp_strvalue,
437 fprintf(stderr, "\"%s\" will have %d to %d replaced with %s\n",
438 found->vp_strvalue, match[0].rm_so,
445 tailfrom = i; /* don't copy it over */
449 case T_OP_EQ: /* = */
451 * FIXME: Tunnel attributes with
452 * different tags are different
457 continue; /* with the loop */
462 * If a similar attribute is found,
463 * replace it with the new one. Otherwise,
464 * add the new one to the list.
466 case T_OP_SET: /* := */
468 VALUE_PAIR *mynext = found->next;
471 * Do NOT call pairdelete()
472 * here, due to issues with
473 * re-writing "request->username".
475 * Everybody calls pairmove,
476 * and expects it to work.
477 * We can't update request->username
478 * here, so instead we over-write
479 * the vp that it's pointing to.
481 memcpy(found, i, sizeof(*found));
482 found->next = mynext;
484 pairdelete(&found->next, found->attribute);
487 * 'tailto' may have been
490 for(j = found; j; j = j->next) {
498 * Add the new element to the list, even
499 * if similar ones already exist.
502 case T_OP_ADD: /* += */
507 tailfrom->next = next;
512 * If ALL of the 'to' attributes have been deleted,
513 * then ensure that the 'tail' is updated to point
528 * Move one kind of attributes from one list to the other
530 void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
532 VALUE_PAIR *to_tail, *i, *next;
533 VALUE_PAIR *iprev = NULL;
536 * Find the last pair in the "to" list and put it in "to_tail".
540 for(i = *to; i; i = i->next)
545 for(i = *from; i; i = next) {
550 * If the attribute to move is NOT a VSA, then it
551 * ignores any attributes which do not match exactly.
553 if ((attr != PW_VENDOR_SPECIFIC) &&
554 (i->attribute != attr)) {
560 * If the attribute to move IS a VSA, then it ignores
561 * any non-VSA attribute.
563 if ((attr == PW_VENDOR_SPECIFIC) &&
564 (VENDOR(i->attribute) == 0)) {
570 * Remove the attribute from the "from" list.
578 * Add the attribute to the "to" list.
591 * Sort of strtok/strsep function.
593 static char *mystrtok(char **ptr, const char *sep)
599 while (**ptr && strchr(sep, **ptr))
604 while (**ptr && strchr(sep, **ptr) == NULL)
612 * Turn printable string into time_t
613 * Returns -1 on error, 0 on OK.
615 static int gettime(const char *valstr, uint32_t *lvalue)
626 * Test for unix timestamp date
628 *lvalue = strtoul(valstr, &tail, 10);
634 memset(tm, 0, sizeof(*tm));
635 tm->tm_isdst = -1; /* don't know, and don't care about DST */
637 strlcpy(buf, valstr, sizeof(buf));
640 f[0] = mystrtok(&p, " \t");
641 f[1] = mystrtok(&p, " \t");
642 f[2] = mystrtok(&p, " \t");
643 f[3] = mystrtok(&p, " \t"); /* may, or may not, be present */
644 if (!f[0] || !f[1] || !f[2]) return -1;
647 * The time has a colon, where nothing else does.
648 * So if we find it, bubble it to the back of the list.
651 for (i = 0; i < 3; i++) {
652 if (strchr(f[i], ':')) {
662 * The month is text, which allows us to find it easily.
665 for (i = 0; i < 3; i++) {
666 if (isalpha( (int) *f[i])) {
668 * Bubble the month to the front of the list
674 for (i = 0; i < 12; i++) {
675 if (strncasecmp(months[i], f[0], 3) == 0) {
683 /* month not found? */
684 if (tm->tm_mon == 12) return -1;
687 * The year may be in f[1], or in f[2]
689 tm->tm_year = atoi(f[1]);
690 tm->tm_mday = atoi(f[2]);
692 if (tm->tm_year >= 1900) {
697 * We can't use 2-digit years any more, they make it
698 * impossible to tell what's the day, and what's the year.
700 if (tm->tm_mday < 1900) return -1;
703 * Swap the year and the day.
706 tm->tm_year = tm->tm_mday - 1900;
711 * If the day is out of range, die.
713 if ((tm->tm_mday < 1) || (tm->tm_mday > 31)) {
718 * There may be %H:%M:%S. Parse it in a hacky way.
721 f[0] = f[3]; /* HH */
722 f[1] = strchr(f[0], ':'); /* find : separator */
723 if (!f[1]) return -1;
725 *(f[1]++) = '\0'; /* nuke it, and point to MM:SS */
727 f[2] = strchr(f[1], ':'); /* find : separator */
729 *(f[2]++) = '\0'; /* nuke it, and point to SS */
731 strcpy(f[2], "0"); /* assignment would discard const */
734 tm->tm_hour = atoi(f[0]);
735 tm->tm_min = atoi(f[1]);
736 tm->tm_sec = atoi(f[2]);
740 * Returns -1 on error.
743 if (t == (time_t) -1) return -1;
752 * Parse a string value into a given VALUE_PAIR
754 * FIXME: we probably want to fix this function to accept
755 * octets as values for any type of attribute. We should then
756 * double-check the parsed value, to be sure it's legal for that
757 * type (length, etc.)
759 VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
766 * Even for integers, dates and ip addresses we
767 * keep the original string in vp->vp_strvalue.
769 strlcpy((char *)vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
770 vp->length = strlen(vp->vp_strvalue);
775 * Already handled above.
781 * It's a comparison, not a real IP.
783 if ((vp->operator == T_OP_REG_EQ) ||
784 (vp->operator == T_OP_REG_NE)) {
789 * FIXME: complain if hostname
790 * cannot be resolved, or resolve later!
792 if ((p = strrchr(value, '+')) != NULL && !p[1]) {
793 cs = s = strdup(value);
796 vp->flags.addport = 1;
803 lrad_ipaddr_t ipaddr;
805 if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
806 librad_log("Failed to find IP address for %s", cs);
810 vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
818 * Note that ALL integers are unsigned!
820 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
822 if (vp->vp_integer > 255) {
823 librad_log("Byte value \"%s\" is larger than 255", value);
831 * Look for the named value for the given
834 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
835 librad_log("Unknown value %s for attribute %s",
839 vp->vp_integer = dval->value;
845 * Note that ALL integers are unsigned!
847 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
849 if (vp->vp_integer > 65535) {
850 librad_log("Byte value \"%s\" is larger than 65535", value);
858 * Look for the named value for the given
861 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
862 librad_log("Unknown value %s for attribute %s",
866 vp->vp_integer = dval->value;
870 case PW_TYPE_INTEGER:
872 * Note that ALL integers are unsigned!
874 vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
881 * Look for the named value for the given
884 if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
885 librad_log("Unknown value %s for attribute %s",
889 vp->vp_integer = dval->value;
894 if (gettime(value, &vp->vp_date) < 0) {
895 librad_log("failed to parse time string "
901 case PW_TYPE_ABINARY:
903 if (strncasecmp(value, "0x", 2) == 0) {
904 vp->type = PW_TYPE_OCTETS;
908 if (ascend_parse_filter(vp) < 0 ) {
909 librad_log("failed to parse Ascend binary attribute: %s",
916 * If Ascend binary is NOT defined,
917 * then fall through to raw octets, so that
918 * the user can at least make them by hand...
922 /* raw octets: 0x01020304... */
924 if (strncasecmp(value, "0x", 2) == 0) {
932 * There is only one character,
935 if ((strlen(cp) & 0x01) != 0) {
936 librad_log("Hex string is not an even length string.");
942 (vp->length < MAX_STRING_LEN)) {
945 if (sscanf(cp, "%02x", &tmp) != 1) {
946 librad_log("Non-hex characters at %c%c", cp[0], cp[1]);
958 if (ifid_aton(value, (unsigned char *) vp->vp_strvalue) == NULL) {
959 librad_log("failed to parse interface-id "
960 "string \"%s\"", value);
964 vp->vp_strvalue[vp->length] = '\0';
967 case PW_TYPE_IPV6ADDR:
968 if (inet_pton(AF_INET6, value, vp->vp_strvalue) <= 0) {
969 librad_log("failed to parse IPv6 address "
970 "string \"%s\"", value);
973 vp->length = 16; /* length of IPv6 address */
974 vp->vp_strvalue[vp->length] = '\0';
979 case PW_TYPE_IPV6PREFIX:
980 p = strchr(value, '/');
981 if (!p || ((p - value) >= 256)) {
982 librad_log("invalid IPv6 prefix "
983 "string \"%s\"", value);
987 char buffer[256], *eptr;
989 memcpy(buffer, value, p - value);
990 buffer[p - value] = '\0';
992 if (inet_pton(AF_INET6, buffer, vp->vp_strvalue + 2) <= 0) {
993 librad_log("failed to parse IPv6 address "
994 "string \"%s\"", value);
998 prefix = strtoul(p + 1, &eptr, 10);
999 if ((prefix > 128) || *eptr) {
1000 librad_log("failed to parse IPv6 address "
1001 "string \"%s\"", value);
1004 vp->vp_strvalue[1] = prefix;
1006 vp->vp_strvalue[0] = '\0';
1007 vp->length = 16 + 2;
1011 librad_log("unknown attribute type %d", vp->type);
1019 * Create a VALUE_PAIR from an ASCII attribute and value,
1020 * where the attribute name is in the form:
1025 static VALUE_PAIR *pairmake_any(const char *attribute, const char *value,
1033 * Unknown attributes MUST be of type 'octets'
1035 if (value && (strncasecmp(value, "0x", 2) != 0)) {
1042 if (strncasecmp(attribute, "Attr-", 5) == 0) {
1043 attr = atoi(attribute + 5);
1045 p += strspn(p, "0123456789");
1046 if (*p != 0) goto error;
1051 } else if (strncasecmp(attribute, "Vendor-", 7) == 0) {
1054 vendor = atoi(attribute + 7);
1055 if ((vendor == 0) || (vendor > 65535)) goto error;
1058 p += strspn(p, "0123456789");
1061 * Not Vendor-%d-Attr-%d
1063 if (strncasecmp(p, "-Attr-", 6) != 0) goto error;
1068 p += strspn(p, "0123456789");
1069 if (*p != 0) goto error;
1071 if ((attr == 0) || (attr > 65535)) goto error;
1073 attr |= (vendor << 16);
1076 * VendorName-Attr-%d
1078 } else if (((p = strchr(attribute, '-')) != NULL) &&
1079 (strncasecmp(p, "-Attr-", 6) == 0)) {
1083 if (((size_t) (p - attribute)) >= sizeof(buffer)) goto error;
1085 memcpy(buffer, attribute, p - attribute);
1086 buffer[p - attribute] = '\0';
1088 vendor = dict_vendorbyname(buffer);
1089 if (vendor == 0) goto error;
1094 p += strspn(p, "0123456789");
1095 if (*p != 0) goto error;
1097 if ((attr == 0) || (attr > 65535)) goto error;
1099 attr |= (vendor << 16);
1101 } else { /* very much unknown: die */
1103 librad_log("Unknown attribute \"%s\"", attribute);
1108 * We've now parsed the attribute properly, Let's create
1109 * it. This next stop also looks the attribute up in the
1110 * dictionary, and creates the appropriate type for it.
1112 if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
1113 librad_log("out of memory");
1117 if (pairparsevalue(vp, value) == NULL) {
1121 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1128 * Create a VALUE_PAIR from an ASCII attribute and value.
1130 VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
1143 * Check for tags in 'Attribute:Tag' format.
1148 ts = strrchr(attribute, ':');
1150 librad_log("Invalid tag for attribute %s", attribute);
1155 /* Colon found with something behind it */
1156 if (ts[1] == '*' && ts[2] == 0) {
1157 /* Wildcard tag for check items */
1160 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
1161 /* It's not a wild card tag */
1162 tag = strtol(ts + 1, &tc, 0);
1163 if (tc && !*tc && TAG_VALID_ZERO(tag))
1167 librad_log("Invalid tag for attribute %s", attribute);
1174 * It's not found in the dictionary, so we use
1175 * another method to create the attribute.
1177 if ((da = dict_attrbyname(attribute)) == NULL) {
1178 return pairmake_any(attribute, value, operator);
1181 if ((vp = pairalloc(da)) == NULL) {
1182 librad_log("out of memory");
1185 vp->operator = (operator == 0) ? T_OP_EQ : operator;
1187 /* Check for a tag in the 'Merit' format of:
1188 * :Tag:Value. Print an error if we already found
1189 * a tag in the Attribute.
1192 if (value && (*value == ':' && da->flags.has_tag)) {
1193 /* If we already found a tag, this is invalid */
1196 librad_log("Duplicate tag %s for attribute %s",
1198 DEBUG("Duplicate tag %s for attribute %s\n",
1203 /* Colon found and attribute allows a tag */
1204 if (value[1] == '*' && value[2] == ':') {
1205 /* Wildcard tag for check items */
1210 tag = strtol(value + 1, &tc, 0);
1211 if (tc && *tc==':' && TAG_VALID_ZERO(tag))
1219 vp->flags.tag = tag;
1222 switch (vp->operator) {
1227 * For =* and !* operators, the value is irrelevant
1231 case T_OP_CMP_FALSE:
1232 vp->vp_strvalue[0] = '\0';
1238 * Regular expression comparison of integer attributes
1239 * does a STRING comparison of the names of their
1240 * integer attributes.
1242 case T_OP_REG_EQ: /* =~ */
1243 case T_OP_REG_NE: /* !~ */
1244 if (vp->type == PW_TYPE_INTEGER) {
1249 * Regular expression match with no regular
1250 * expression is wrong.
1257 res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);
1261 regerror(res, &cre, msg, sizeof(msg));
1262 librad_log("Illegal regular expression in attribute: %s: %s",
1269 librad_log("Regelar expressions not enabled in this build, error in attribute %s",
1277 * FIXME: if (strcasecmp(attribute, vp->name) != 0)
1278 * then the user MAY have typed in the attribute name
1279 * as Vendor-%d-Attr-%d, and the value MAY be octets.
1281 * We probably want to fix pairparsevalue to accept
1282 * octets as values for any attribute.
1284 if (value && (pairparsevalue(vp, value) == NULL)) {
1296 static const int valid_attr_name[256] = {
1297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
1300 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1301 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1302 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1303 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1304 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1307 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1308 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1312 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1316 * Read a valuepair from a buffer, and advance pointer.
1317 * Sets *eol to T_EOL if end of line was encountered.
1319 VALUE_PAIR *pairread(char **ptr, LRAD_TOKEN *eol)
1325 LRAD_TOKEN token, t, xlat;
1329 *eol = T_OP_INVALID;
1332 while ((*p == ' ') || (*p == '\t')) p++;
1335 *eol = T_OP_INVALID;
1336 librad_log("No token read where we expected an attribute name");
1342 librad_log("Read a comment instead of a token");
1347 for (len = 0; len < sizeof(attr); len++) {
1348 if (valid_attr_name[(int)*p]) {
1355 if (len == sizeof(attr)) {
1356 *eol = T_OP_INVALID;
1357 librad_log("Attribute name is too long");
1362 * We may have Foo-Bar:= stuff, so back up.
1364 if (attr[len - 1] == ':') {
1372 /* Now we should have an operator here. */
1373 token = gettoken(ptr, buf, sizeof(buf));
1374 if (token < T_EQSTART || token > T_EQEND) {
1375 librad_log("expecting operator");
1379 /* Read value. Note that empty string values are allowed */
1380 xlat = gettoken(ptr, value, sizeof(value));
1381 if (xlat == T_EOL) {
1382 librad_log("failed to get value");
1387 * Peek at the next token. Must be T_EOL, T_COMMA, or T_HASH
1390 t = gettoken(&p, buf, sizeof(buf));
1391 if (t != T_EOL && t != T_COMMA && t != T_HASH) {
1392 librad_log("Expected end of line or comma");
1404 * Make the full pair now.
1407 vp = pairmake(attr, value, token);
1413 case T_DOUBLE_QUOTED_STRING:
1414 p = strchr(value, '%');
1415 if (p && (p[1] == '{')) {
1416 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1417 librad_log("Value too long");
1420 vp = pairmake(attr, NULL, token);
1422 *eol = T_OP_INVALID;
1426 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1427 vp->flags.do_xlat = 1;
1430 vp = pairmake(attr, value, token);
1436 * Mark the pair to be allocated later.
1438 case T_BACK_QUOTED_STRING:
1439 if (strlen(value) >= sizeof(vp->vp_strvalue)) {
1440 librad_log("Value too long");
1444 vp = pairmake(attr, NULL, token);
1446 *eol = T_OP_INVALID;
1450 vp->flags.do_xlat = 1;
1451 strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
1457 * If we didn't make a pair, return an error.
1460 *eol = T_OP_INVALID;
1468 * Read one line of attribute/value pairs. This might contain
1469 * multiple pairs seperated by comma's.
1471 LRAD_TOKEN userparse(char *buffer, VALUE_PAIR **first_pair)
1475 LRAD_TOKEN last_token = T_OP_INVALID;
1476 LRAD_TOKEN previous_token;
1479 * We allow an empty line.
1486 previous_token = last_token;
1487 if ((vp = pairread(&p, &last_token)) == NULL) {
1490 pairadd(first_pair, vp);
1491 } while (*p && (last_token == T_COMMA));
1494 * Don't tell the caller that there was a comment.
1496 if (last_token == T_HASH) {
1497 return previous_token;
1501 * And return the last token which we read.
1507 * Read valuepairs from the fp up to End-Of-File.
1509 * Hmm... this function is only used by radclient..
1511 VALUE_PAIR *readvp2(FILE *fp, int *pfiledone, const char *errprefix)
1514 LRAD_TOKEN last_token = T_EOL;
1521 while (!error && fgets(buf, sizeof(buf), fp) != NULL) {
1523 * If we get a '\n' by itself, we assume that's
1524 * the end of that VP
1526 if ((buf[0] == '\n') && (list)) {
1529 if ((buf[0] == '\n') && (!list)) {
1534 * Comments get ignored
1536 if (buf[0] == '#') continue;
1539 * Read all of the attributes on the current line.
1542 last_token = userparse(buf, &vp);
1544 if (last_token != T_EOL) {
1545 librad_perror("%s", errprefix);
1556 if (error) pairfree(&list);
1560 return error ? NULL: list;
1566 * Compare two pairs, using the operator from "one".
1568 * i.e. given two attributes, it does:
1570 * (two->data) (one->operator) (one->data)
1572 * e.g. "foo" != "bar"
1574 * Returns true (comparison is true), or false (comparison is not true);
1576 int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
1580 switch (one->operator) {
1582 return (two != NULL);
1584 case T_OP_CMP_FALSE:
1585 return (two == NULL);
1588 * One is a regex, compile it, print two to a string,
1589 * and then do string comparisons.
1593 #ifndef HAVE_REGEX_H
1598 char buffer[MAX_STRING_LEN * 4 + 1];
1600 compare = regcomp(®, one->vp_strvalue,
1603 regerror(compare, ®, buffer, sizeof(buffer));
1604 librad_log("Illegal regular expression in attribute: %s: %s",
1609 vp_prints_value(buffer, sizeof(buffer), two, 0);
1612 * Don't care about substring matches,
1615 compare = regexec(®, buffer, 0, NULL, 0);
1618 if (one->operator == T_OP_REG_EQ) return (compare == 0);
1619 return (compare != 0);
1623 default: /* we're OK */
1628 * After doing the previous check for special comparisons,
1629 * do the per-type comparison here.
1631 switch (one->type) {
1632 case PW_TYPE_ABINARY:
1633 case PW_TYPE_OCTETS:
1636 const uint8_t *p, *q;
1638 if (one->length < two->length) {
1639 length = one->length;
1641 length = two->length;
1647 compare = ((int) *p) - ((int) *q);
1648 if (compare != 0) goto type_switch;
1652 * Contents are the same. The return code
1653 * is therefore the difference in lengths.
1655 * i.e. "0x00" is smaller than "0x0000"
1657 compare = two->length - one->length;
1661 case PW_TYPE_STRING:
1662 if (one->flags.caseless) {
1663 compare = strcasecmp(two->vp_strvalue,
1666 compare = strcmp(two->vp_strvalue,
1673 case PW_TYPE_INTEGER:
1675 compare = two->vp_integer - one->vp_integer;
1678 case PW_TYPE_IPADDR:
1679 compare = ntohl(two->vp_ipaddr) - ntohl(one->vp_ipaddr);
1682 case PW_TYPE_IPV6ADDR:
1683 compare = memcmp(&two->vp_ipv6addr, &one->vp_ipv6addr,
1684 sizeof(two->vp_ipv6addr));
1687 case PW_TYPE_IPV6PREFIX:
1688 compare = memcmp(&two->vp_ipv6prefix, &one->vp_ipv6prefix,
1689 sizeof(two->vp_ipv6prefix));
1693 compare = memcmp(&two->vp_ifid, &one->vp_ifid,
1694 sizeof(two->vp_ifid));
1698 return 0; /* unknown type */
1702 * Now do the operator comparison.
1705 switch (one->operator) {
1707 return (compare == 0);
1710 return (compare != 0);
1713 return (compare < 0);
1716 return (compare > 0);
1719 return (compare <= 0);
1722 return (compare >= 0);