case PW_TYPE_INTEGER:
case PW_TYPE_IPADDR:
case PW_TYPE_DATE:
+ case PW_TYPE_SIGNED:
vp->length = 4;
break;
vp->length = sizeof(vp->vp_ether);
break;
+ case PW_TYPE_TLV:
+ vp->vp_tlv = NULL;
+ vp->length = 0;
+ break;
+
+ case PW_TYPE_COMBO_IP:
default:
vp->length = 0;
break;
return vp;
}
+/*
+ * Create a new valuepair.
+ */
+VALUE_PAIR *paircreate_raw(int attr, int vendor, int type, VALUE_PAIR *vp)
+{
+ char *p = (char *) (vp + 1);
+
+ if (!vp->flags.unknown_attr) {
+ pairfree(&vp);
+ return NULL;
+ }
+
+ vp->vendor = vendor;
+ vp->attribute = attr;
+ vp->operator = T_OP_EQ;
+ vp->name = p;
+ vp->type = type;
+ vp->length = 0;
+ memset(&vp->flags, 0, sizeof(vp->flags));
+ vp->flags.unknown_attr = 1;
+
+ if (!vp_print_name(p, FR_VP_NAME_LEN, vp->attribute, vp->vendor)) {
+ free(vp);
+ return NULL;
+ }
+
+ return vp;
+}
/*
* Create a new valuepair.
*/
-VALUE_PAIR *paircreate(int attr, int type)
+VALUE_PAIR *paircreate(int attr, int vendor, int type)
{
VALUE_PAIR *vp;
DICT_ATTR *da;
- da = dict_attrbyvalue(attr);
+ da = dict_attrbyvalue(attr, vendor);
if ((vp = pairalloc(da)) == NULL) {
- librad_log("out of memory");
+ fr_strerror_printf("out of memory");
return NULL;
}
vp->operator = T_OP_EQ;
/*
* It isn't in the dictionary: update the name.
*/
- if (!da) {
- size_t len = 0;
- char *p = (char *) (vp + 1);
-
- vp->vendor = VENDOR(attr);
- vp->attribute = attr;
- vp->name = p;
- vp->type = type; /* be forgiving */
-
- if (vp->vendor) {
- DICT_VENDOR *v;
-
- v = dict_vendorbyvalue(vp->vendor);
- if (v) {
- snprintf(p, FR_VP_NAME_LEN, "%s-", v->name);
- } else {
- snprintf(p, FR_VP_NAME_LEN, "Vendor-%u-", vp->vendor);
- }
-
- len = strlen(p);
- if (len == FR_VP_NAME_LEN) {
- free(vp);
- return NULL;
- }
- }
-
- snprintf(p + len, FR_VP_NAME_LEN - len, "Attr-%u",
- attr & 0xffff);
- len += strlen(p + len);
- if (len == FR_VP_NAME_LEN) {
- free(vp);
- return NULL;
- }
- }
+ if (!da) return paircreate_raw(attr, vendor, type, vp);
return vp;
}
*/
void pairbasicfree(VALUE_PAIR *pair)
{
+ if (pair->type == PW_TYPE_TLV) free(pair->vp_tlv);
/* clear the memory here */
memset(pair, 0, sizeof(*pair));
free(pair);
/*
* Find the pair with the matching attribute
*/
-VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
+VALUE_PAIR * pairfind(VALUE_PAIR *first, unsigned int attr, unsigned int vendor)
{
- while(first && first->attribute != attr)
+ while (first) {
+ if ((first->attribute == attr) && (first->vendor == vendor)) {
+ return first;
+ }
first = first->next;
- return first;
+ }
+
+ return NULL;
}
/*
* Delete the pair(s) with the matching attribute
*/
-void pairdelete(VALUE_PAIR **first, int attr)
+void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor)
{
VALUE_PAIR *i, *next;
VALUE_PAIR **last = first;
for(i = *first; i; i = next) {
next = i->next;
- if (i->attribute == attr) {
+ if ((i->attribute == attr) && (i->vendor == vendor)) {
*last = next;
pairbasicfree(i);
} else {
* Found the first attribute, replace it,
* and return.
*/
- if (i->attribute == replace->attribute) {
+ if ((i->attribute == replace->attribute) &&
+ (i->vendor == replace->vendor)) {
*prev = replace;
/*
*prev = replace;
}
+
+/*
+ * Copy just one VP.
+ */
+VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp)
+{
+ size_t name_len;
+ VALUE_PAIR *n;
+
+ if (!vp->flags.unknown_attr) {
+ name_len = 0;
+ } else {
+ name_len = FR_VP_NAME_PAD;
+ }
+
+ if ((n = malloc(sizeof(*n) + name_len)) == NULL) {
+ fr_strerror_printf("out of memory");
+ return NULL;
+ }
+ memcpy(n, vp, sizeof(*n) + name_len);
+
+ /*
+ * Reset the name field to point to the NEW attribute,
+ * rather than to the OLD one.
+ */
+ if (vp->flags.unknown_attr) n->name = (char *) (n + 1);
+
+ n->next = NULL;
+
+ if ((n->type == PW_TYPE_TLV) &&
+ (n->vp_tlv != NULL)) {
+ n->vp_tlv = malloc(n->length);
+ memcpy(n->vp_tlv, vp->vp_tlv, n->length);
+ }
+
+ return n;
+}
+
+
/*
* Copy just a certain type of pairs.
*/
-VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
+VALUE_PAIR *paircopy2(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor)
{
VALUE_PAIR *first, *n, **last;
last = &first;
while (vp) {
- size_t name_len;
-
- if (attr >= 0 && vp->attribute != attr) {
+ if ((attr > 0) &&
+ !((vp->attribute == attr) && (vp->vendor == vendor))) {
vp = vp->next;
continue;
}
- if (!vp->flags.unknown_attr) {
- name_len = 0;
- } else {
- name_len = FR_VP_NAME_PAD;
- }
-
- if ((n = malloc(sizeof(*n))) == NULL) {
- librad_log("out of memory");
- return first;
- }
- memcpy(n, vp, sizeof(*n) + name_len);
- n->next = NULL;
+ n = paircopyvp(vp);
+ if (!n) return first;
*last = n;
last = &n->next;
vp = vp->next;
*/
VALUE_PAIR *paircopy(VALUE_PAIR *vp)
{
- return paircopy2(vp, -1);
+ return paircopy2(vp, 0, 0);
}
if (i->attribute == PW_FALL_THROUGH ||
(i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE)) {
- found = pairfind(*to, i->attribute);
+ found = pairfind(*to, i->attribute, i->vendor);
switch (i->operator) {
/*
if (!i->vp_strvalue[0] ||
(strcmp((char *)found->vp_strvalue,
(char *)i->vp_strvalue) == 0)){
- pairdelete(to, found->attribute);
+ pairdelete(to, found->attribute, found->vendor);
/*
* 'tailto' may have been
memcpy(found, i, sizeof(*found));
found->next = mynext;
- pairdelete(&found->next, found->attribute);
+ pairdelete(&found->next, found->attribute, found->vendor);
/*
* 'tailto' may have been
/*
* Move one kind of attributes from one list to the other
*/
-void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
+void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, unsigned int attr, unsigned int vendor)
{
VALUE_PAIR *to_tail, *i, *next;
VALUE_PAIR *iprev = NULL;
for(i = *from; i; i = next) {
next = i->next;
-
/*
- * If the attribute to move is NOT a VSA, then it
- * ignores any attributes which do not match exactly.
+ * vendor=0, attr = PW_VENDOR_SPECIFIC means
+ * "match any vendor attribute".
*/
- if ((attr != PW_VENDOR_SPECIFIC) &&
- (i->attribute != attr)) {
+ if ((vendor == 0) && (attr == PW_VENDOR_SPECIFIC)) {
+ /*
+ * It's a VSA: move it over.
+ */
+ if (i->vendor != 0) goto move;
+
+ /*
+ * It's Vendor-Specific: move it over.
+ */
+ if (i->attribute == attr) goto move;
+
+ /*
+ * It's not a VSA: ignore it.
+ */
iprev = i;
continue;
}
/*
- * If the attribute to move IS a VSA, then it ignores
- * any non-VSA attribute.
+ * If it isn't an exact match, ignore it.
*/
- if ((attr == PW_VENDOR_SPECIFIC) &&
- (VENDOR(i->attribute) == 0)) {
+ if (!((i->vendor == vendor) && (i->attribute == attr))) {
iprev = i;
continue;
}
+ move:
/*
* Remove the attribute from the "from" list.
*/
f[2] = strchr(f[1], ':'); /* find : separator */
if (f[2]) {
*(f[2]++) = '\0'; /* nuke it, and point to SS */
- } else {
- strcpy(f[2], "0"); /* assignment would discard const */
- }
+ tm->tm_sec = atoi(f[2]);
+ } /* else leave it as zero */
tm->tm_hour = atoi(f[0]);
tm->tm_min = atoi(f[1]);
- tm->tm_sec = atoi(f[2]);
}
/*
* double-check the parsed value, to be sure it's legal for that
* type (length, etc.)
*/
+static uint32_t getint(const char *value, char **end)
+{
+ if ((value[0] == '0') && (value[1] == 'x')) {
+ return strtoul(value, end, 16);
+ }
+
+ return strtoul(value, end, 10);
+}
+
+static int check_for_whitespace(const char *value)
+{
+ while (*value) {
+ if (!isspace((int) *value)) return 0;
+
+ value++;
+ }
+
+ return 1;
+}
+
+
VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value)
{
char *p, *s=0;
size_t length;
DICT_VALUE *dval;
+ if (!value) return NULL;
+
/*
* Even for integers, dates and ip addresses we
* keep the original string in vp->vp_strvalue.
*/
- strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
- vp->length = strlen(vp->vp_strvalue);
+ if (vp->type != PW_TYPE_TLV) {
+ strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
+ vp->length = strlen(vp->vp_strvalue);
+ }
switch(vp->type) {
case PW_TYPE_STRING:
cp = value;
length = 0;
- while (*cp && (length < sizeof(vp->vp_strvalue))) {
+ while (*cp && (length < (sizeof(vp->vp_strvalue) - 1))) {
char c = *cp++;
if (c == '\\') {
c = '\'';
cp++;
break;
+ case '\\':
+ c = '\\';
+ cp++;
+ break;
case '`':
c = '`';
cp++;
*p++ = c;
length++;
}
+ vp->vp_strvalue[length] = '\0';
vp->length = length;
break;
* FIXME: complain if hostname
* cannot be resolved, or resolve later!
*/
+ s = NULL;
if ((p = strrchr(value, '+')) != NULL && !p[1]) {
cs = s = strdup(value);
+ if (!s) return NULL;
p = strrchr(s, '+');
*p = 0;
vp->flags.addport = 1;
fr_ipaddr_t ipaddr;
if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
- librad_log("Failed to find IP address for %s", cs);
+ free(s);
+ fr_strerror_printf("Failed to find IP address for %s", cs);
return NULL;
}
vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
}
- if (s) free(s);
+ free(s);
vp->length = 4;
break;
case PW_TYPE_BYTE:
- if ((value[0] == '0') && (value[1] == 'x')) {
- goto do_octets;
- }
+ vp->length = 1;
/*
* Note that ALL integers are unsigned!
*/
- vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
+ vp->vp_integer = getint(value, &p);
if (!*p) {
if (vp->vp_integer > 255) {
- librad_log("Byte value \"%s\" is larger than 255", value);
+ fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
return NULL;
}
- vp->length = 1;
break;
}
-
- /*
- * Look for the named value for the given
- * attribute.
- */
- if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
- librad_log("Unknown value %s for attribute %s",
- value, vp->name);
- return NULL;
- }
- vp->vp_integer = dval->value;
- vp->length = 1;
- break;
+ if (check_for_whitespace(p)) break;
+ goto check_for_value;
case PW_TYPE_SHORT:
/*
* Note that ALL integers are unsigned!
*/
- vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
+ vp->vp_integer = getint(value, &p);
+ vp->length = 2;
if (!*p) {
if (vp->vp_integer > 65535) {
- librad_log("Byte value \"%s\" is larger than 65535", value);
+ fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
return NULL;
}
- vp->length = 2;
break;
}
-
- /*
- * Look for the named value for the given
- * attribute.
- */
- if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
- librad_log("Unknown value %s for attribute %s",
- value, vp->name);
- return NULL;
- }
- vp->vp_integer = dval->value;
- vp->length = 2;
- break;
+ if (check_for_whitespace(p)) break;
+ goto check_for_value;
case PW_TYPE_INTEGER:
/*
* Note that ALL integers are unsigned!
*/
- vp->vp_integer = (uint32_t) strtoul(value, &p, 10);
- if (!*p) {
- vp->length = 4;
- break;
- }
+ vp->vp_integer = getint(value, &p);
+ vp->length = 4;
+ if (!*p) break;
+ if (check_for_whitespace(p)) break;
+ check_for_value:
/*
* Look for the named value for the given
* attribute.
*/
- if ((dval = dict_valbyname(vp->attribute, value)) == NULL) {
- librad_log("Unknown value %s for attribute %s",
+ if ((dval = dict_valbyname(vp->attribute, vp->vendor, value)) == NULL) {
+ fr_strerror_printf("Unknown value %s for attribute %s",
value, vp->name);
return NULL;
}
vp->vp_integer = dval->value;
- vp->length = 4;
break;
case PW_TYPE_DATE:
time_t date;
if (gettime(value, &date) < 0) {
- librad_log("failed to parse time string "
+ fr_strerror_printf("failed to parse time string "
"\"%s\"", value);
return NULL;
}
}
if (ascend_parse_filter(vp) < 0 ) {
- librad_log("failed to parse Ascend binary attribute: %s",
- librad_errstr);
+ fr_strerror_printf("failed to parse Ascend binary attribute: %s",
+ fr_strerror());
return NULL;
}
break;
* then fall through to raw octets, so that
* the user can at least make them by hand...
*/
-#endif
do_octets:
+#endif
/* raw octets: 0x01020304... */
case PW_TYPE_OCTETS:
if (strncasecmp(value, "0x", 2) == 0) {
* die.
*/
if ((strlen(cp) & 0x01) != 0) {
- librad_log("Hex string is not an even length string.");
+ fr_strerror_printf("Hex string is not an even length string.");
return NULL;
}
unsigned int tmp;
if (sscanf(cp, "%02x", &tmp) != 1) {
- librad_log("Non-hex characters at %c%c", cp[0], cp[1]);
+ fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]);
return NULL;
}
case PW_TYPE_IFID:
if (ifid_aton(value, (void *) &vp->vp_ifid) == NULL) {
- librad_log("failed to parse interface-id "
+ fr_strerror_printf("failed to parse interface-id "
"string \"%s\"", value);
return NULL;
}
break;
case PW_TYPE_IPV6ADDR:
- if (inet_pton(AF_INET6, value, &vp->vp_ipv6addr) <= 0) {
- librad_log("failed to parse IPv6 address "
- "string \"%s\"", value);
- return NULL;
+ {
+ fr_ipaddr_t ipaddr;
+
+ if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
+ char buffer[1024];
+
+ strlcpy(buffer, fr_strerror(), sizeof(buffer));
+
+ fr_strerror_printf("failed to parse IPv6 address "
+ "string \"%s\": %s", value, buffer);
+ return NULL;
+ }
+ vp->vp_ipv6addr = ipaddr.ipaddr.ip6addr;
+ vp->length = 16; /* length of IPv6 address */
}
- vp->length = 16; /* length of IPv6 address */
break;
case PW_TYPE_IPV6PREFIX:
p = strchr(value, '/');
if (!p || ((p - value) >= 256)) {
- librad_log("invalid IPv6 prefix "
+ fr_strerror_printf("invalid IPv6 prefix "
"string \"%s\"", value);
return NULL;
} else {
buffer[p - value] = '\0';
if (inet_pton(AF_INET6, buffer, vp->vp_octets + 2) <= 0) {
- librad_log("failed to parse IPv6 address "
+ fr_strerror_printf("failed to parse IPv6 address "
"string \"%s\"", value);
return NULL;
}
prefix = strtoul(p + 1, &eptr, 10);
if ((prefix > 128) || *eptr) {
- librad_log("failed to parse IPv6 address "
+ fr_strerror_printf("failed to parse IPv6 address "
"string \"%s\"", value);
return NULL;
}
c1 = c2 = NULL;
}
if (!c1 || !c2 || (length >= sizeof(vp->vp_ether))) {
- librad_log("failed to parse Ethernet address \"%s\"", value);
+ fr_strerror_printf("failed to parse Ethernet address \"%s\"", value);
return NULL;
}
vp->vp_ether[length] = ((c1-hextab)<<4) + (c2-hextab);
vp->length = 6;
break;
+ case PW_TYPE_COMBO_IP:
+ if (inet_pton(AF_INET6, value, vp->vp_strvalue) > 0) {
+ vp->type = PW_TYPE_IPV6ADDR;
+ vp->length = 16; /* length of IPv6 address */
+ vp->vp_strvalue[vp->length] = '\0';
+
+ } else {
+ fr_ipaddr_t ipaddr;
+
+ if (ip_hton(value, AF_INET, &ipaddr) < 0) {
+ fr_strerror_printf("Failed to find IPv4 address for %s", value);
+ return NULL;
+ }
+
+ vp->type = PW_TYPE_IPADDR;
+ vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
+ vp->length = 4;
+ }
+ break;
+
+ case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */
+ vp->vp_signed = (int32_t) strtol(value, &p, 10);
+ vp->length = 4;
+ break;
+
+ case PW_TYPE_TLV: /* don't use this! */
+ if (strncasecmp(value, "0x", 2) != 0) {
+ fr_strerror_printf("Invalid TLV specification");
+ return NULL;
+ }
+ length = strlen(value + 2) / 2;
+ if (vp->length < length) {
+ free(vp->vp_tlv);
+ vp->vp_tlv = NULL;
+ }
+ vp->vp_tlv = malloc(length);
+ if (!vp->vp_tlv) {
+ fr_strerror_printf("No memory");
+ return NULL;
+ }
+ if (fr_hex2bin(value + 2, vp->vp_tlv,
+ length) != length) {
+ fr_strerror_printf("Invalid hex data in TLV");
+ return NULL;
+ }
+ vp->length = length;
+ break;
+
/*
* Anything else.
*/
default:
- librad_log("unknown attribute type %d", vp->type);
+ fr_strerror_printf("unknown attribute type %d", vp->type);
return NULL;
}
* Unknown attributes MUST be of type 'octets'
*/
if (value && (strncasecmp(value, "0x", 2) != 0)) {
- librad_log("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
+ fr_strerror_printf("Invalid octet string \"%s\" for attribute name \"%s\"", value, attribute);
return NULL;
}
- attr = vendor = 0;
+ vendor = 0;
/*
* Pull off vendor prefix first.
if (strncasecmp(p, "Attr-", 5) != 0) {
if (strncasecmp(p, "Vendor-", 7) == 0) {
vendor = (int) strtol(p + 7, &q, 10);
- if ((vendor == 0) || (vendor > 65535)) {
- librad_log("Invalid vendor value in attribute name \"%s\"", attribute);
+ if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
+ fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", attribute);
return NULL;
}
p = q;
} else { /* must be vendor name */
- q = strchr(p, '-');
char buffer[256];
+ q = strchr(p, '-');
+
if (!q) {
- librad_log("Invalid vendor name in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", attribute);
return NULL;
}
if ((size_t) (q - p) >= sizeof(buffer)) {
- librad_log("Vendor name too long in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Vendor name too long in attribute name \"%s\"", attribute);
return NULL;
}
vendor = dict_vendorbyname(buffer);
if (!vendor) {
- librad_log("Unknown vendor name in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Unknown vendor name in attribute name \"%s\"", attribute);
return NULL;
}
}
if (*p != '-') {
- librad_log("Invalid text following vendor definition in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", attribute);
return NULL;
}
p++;
* Attr-%d
*/
if (strncasecmp(p, "Attr-", 5) != 0) {
- librad_log("Invalid format in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Invalid format in attribute name \"%s\"", attribute);
return NULL;
}
* Invalid, or trailing text after number.
*/
if ((attr == 0) || *q) {
- librad_log("Invalid value in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Invalid value in attribute name \"%s\"", attribute);
return NULL;
}
if (!dv) {
if (attr > 255) {
attr_error:
- librad_log("Invalid attribute number in attribute name \"%s\"", attribute);
+ fr_strerror_printf("Invalid attribute number in attribute name \"%s\"", attribute);
return NULL;
}
if (attr > 65535) goto attr_error;
break;
- case 4: /* Internal limitations! */
- if (attr > 65535) goto attr_error;
+ case 4:
break;
default:
- librad_log("Internal sanity check failed");
+ fr_strerror_printf("Internal sanity check failed");
return NULL;
}
}
- attr |= vendor << 16;
-
/*
* We've now parsed the attribute properly, Let's create
* it. This next stop also looks the attribute up in the
* dictionary, and creates the appropriate type for it.
*/
- if ((vp = paircreate(attr, PW_TYPE_OCTETS)) == NULL) {
- librad_log("out of memory");
+ if ((vp = paircreate(attr, vendor, PW_TYPE_OCTETS)) == NULL) {
+ fr_strerror_printf("out of memory");
return NULL;
}
+ vp->operator = (operator == 0) ? T_OP_EQ : operator;
+ if (!value) return vp;
+
size = strlen(value + 2);
/*
}
if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) {
- librad_log("Invalid hex string");
+ fr_strerror_printf("Invalid hex string");
free(vp);
return NULL;
}
break;
}
- vp->operator = (operator == 0) ? T_OP_EQ : operator;
-
return vp;
}
char *tc, *ts;
signed char tag;
int found_tag;
-#ifdef HAVE_REGEX_H
- int res;
- regex_t cre;
-#endif
+ char buffer[64];
+ const char *attrname = attribute;
/*
* Check for tags in 'Attribute:Tag' format.
ts = strrchr(attribute, ':');
if (ts && !ts[1]) {
- librad_log("Invalid tag for attribute %s", attribute);
+ fr_strerror_printf("Invalid tag for attribute %s", attribute);
return NULL;
}
if (ts && ts[1]) {
+ strlcpy(buffer, attribute, sizeof(buffer));
+ attrname = buffer;
+ ts = strrchr(attrname, ':');
+
/* Colon found with something behind it */
if (ts[1] == '*' && ts[2] == 0) {
/* Wildcard tag for check items */
*ts = 0;
else tag = 0;
} else {
- librad_log("Invalid tag for attribute %s", attribute);
+ fr_strerror_printf("Invalid tag for attribute %s", attribute);
return NULL;
}
found_tag = 1;
* It's not found in the dictionary, so we use
* another method to create the attribute.
*/
- if ((da = dict_attrbyname(attribute)) == NULL) {
- return pairmake_any(attribute, value, operator);
+ if ((da = dict_attrbyname(attrname)) == NULL) {
+ return pairmake_any(attrname, value, operator);
}
if ((vp = pairalloc(da)) == NULL) {
- librad_log("out of memory");
+ fr_strerror_printf("out of memory");
return NULL;
}
vp->operator = (operator == 0) ? T_OP_EQ : operator;
if (value && (*value == ':' && da->flags.has_tag)) {
/* If we already found a tag, this is invalid */
if(found_tag) {
- pairbasicfree(vp);
- librad_log("Duplicate tag %s for attribute %s",
+ fr_strerror_printf("Duplicate tag %s for attribute %s",
value, vp->name);
DEBUG("Duplicate tag %s for attribute %s\n",
value, vp->name);
+ pairbasicfree(vp);
return NULL;
-
}
/* Colon found and attribute allows a tag */
if (value[1] == '*' && value[2] == ':') {
*/
case T_OP_REG_EQ: /* =~ */
case T_OP_REG_NE: /* !~ */
- if (vp->type == PW_TYPE_INTEGER) {
- return vp;
- }
-#ifdef HAVE_REGEX_H
- /*
- * Regular expression match with no regular
- * expression is wrong.
- */
if (!value) {
- pairfree(&vp);
+ fr_strerror_printf("No regular expression found in %s",
+ vp->name);
+ pairbasicfree(vp);
return NULL;
}
+
+ strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
+ vp->length = strlen(vp->vp_strvalue);
+ /*
+ * If anything goes wrong, this is a run-time error,
+ * not a compile-time error.
+ */
+ return vp;
- res = regcomp(&cre, value, REG_EXTENDED|REG_NOSUB);
- if (res != 0) {
- char msg[128];
-
- regerror(res, &cre, msg, sizeof(msg));
- librad_log("Illegal regular expression in attribute: %s: %s",
- vp->name, msg);
- pairbasicfree(vp);
- return NULL;
- }
- regfree(&cre);
-#else
- librad_log("Regelar expressions not enabled in this build, error in attribute %s",
- vp->name);
- pairbasicfree(vp);
- return NULL;
-#endif
}
/*
{
char buf[64];
char attr[64];
- char value[512], *q;
+ char value[1024], *q;
const char *p;
FR_TOKEN token, t, xlat;
VALUE_PAIR *vp;
if (!*p) {
*eol = T_OP_INVALID;
- librad_log("No token read where we expected an attribute name");
+ fr_strerror_printf("No token read where we expected an attribute name");
return NULL;
}
if (*p == '#') {
*eol = T_HASH;
- librad_log("Read a comment instead of a token");
+ fr_strerror_printf("Read a comment instead of a token");
return NULL;
}
if (len == sizeof(attr)) {
*eol = T_OP_INVALID;
- librad_log("Attribute name is too long");
+ fr_strerror_printf("Attribute name is too long");
return NULL;
}
/*
* We may have Foo-Bar:= stuff, so back up.
*/
- if (attr[len - 1] == ':') {
+ if ((len > 0) && (attr[len - 1] == ':')) {
p--;
len--;
}
/* Now we should have an operator here. */
token = gettoken(ptr, buf, sizeof(buf));
if (token < T_EQSTART || token > T_EQEND) {
- librad_log("expecting operator");
+ fr_strerror_printf("expecting operator");
return NULL;
}
/* Read value. Note that empty string values are allowed */
xlat = gettoken(ptr, value, sizeof(value));
if (xlat == T_EOL) {
- librad_log("failed to get value");
+ fr_strerror_printf("failed to get value");
return NULL;
}
p = *ptr;
t = gettoken(&p, buf, sizeof(buf));
if (t != T_EOL && t != T_COMMA && t != T_HASH) {
- librad_log("Expected end of line or comma");
+ fr_strerror_printf("Expected end of line or comma");
return NULL;
}
p = strchr(value, '%');
if (p && (p[1] == '{')) {
if (strlen(value) >= sizeof(vp->vp_strvalue)) {
- librad_log("Value too long");
+ fr_strerror_printf("Value too long");
return NULL;
}
vp = pairmake(attr, NULL, token);
vp->flags.do_xlat = 1;
vp->length = 0;
} else {
+ /*
+ * Parse && escape it, as defined by the
+ * data type.
+ */
vp = pairmake(attr, value, token);
+ if (!vp) {
+ *eol = T_OP_INVALID;
+ return NULL;
+ }
}
break;
+ case T_SINGLE_QUOTED_STRING:
+ vp = pairmake(attr, NULL, token);
+ if (!vp) {
+ *eol = T_OP_INVALID;
+ return NULL;
+ }
+
+ /*
+ * String and octet types get copied verbatim.
+ */
+ if ((vp->type == PW_TYPE_STRING) ||
+ (vp->type == PW_TYPE_OCTETS)) {
+ strlcpy(vp->vp_strvalue, value,
+ sizeof(vp->vp_strvalue));
+ vp->length = strlen(vp->vp_strvalue);
+
+ /*
+ * Everything else gets parsed: it's
+ * DATA, not a string!
+ */
+ } else if (!pairparsevalue(vp, value)) {
+ pairfree(&vp);
+ *eol = T_OP_INVALID;
+ return NULL;
+ }
+ break;
/*
* Mark the pair to be allocated later.
*/
case T_BACK_QUOTED_STRING:
if (strlen(value) >= sizeof(vp->vp_strvalue)) {
- librad_log("Value too long");
+ fr_strerror_printf("Value too long");
return NULL;
}
last_token = userparse(buf, &vp);
if (!vp) {
if (last_token != T_EOL) {
- librad_perror("%s", errprefix);
+ fr_perror("%s", errprefix);
error = 1;
break;
}
* e.g. "foo" != "bar"
*
* Returns true (comparison is true), or false (comparison is not true);
+ *
+ * FIXME: Ignores tags!
*/
int paircmp(VALUE_PAIR *one, VALUE_PAIR *two)
{
REG_EXTENDED);
if (compare != 0) {
regerror(compare, ®, buffer, sizeof(buffer));
- librad_log("Illegal regular expression in attribute: %s: %s",
+ fr_strerror_printf("Illegal regular expression in attribute: %s: %s",
one->name, buffer);
return -1;
}
case PW_TYPE_OCTETS:
{
size_t length;
- const uint8_t *p, *q;
if (one->length < two->length) {
length = one->length;
length = two->length;
}
- p = two->vp_octets;
- q = one->vp_octets;
- while (length) {
- compare = ((int) *p) - ((int) *q);
- if (compare != 0) goto type_switch;
+ if (length) {
+ compare = memcmp(two->vp_octets, one->vp_octets,
+ length);
+ if (compare != 0) break;
}
/*
/*
* Now do the operator comparison.
*/
- type_switch:
switch (one->operator) {
case T_OP_CMP_EQ:
return (compare == 0);