*
* Copyright 2000,2006 The FreeRADIUS server project
*/
-
-#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/libradius.h>
*/
typedef struct dict_stat_t {
struct dict_stat_t *next;
- char *name;
- time_t mtime;
+ struct stat stat_buf;
} dict_stat_t;
-static char *stat_root_dir = NULL;
-static char *stat_root_file = NULL;
-
static dict_stat_t *stat_head = NULL;
static dict_stat_t *stat_tail = NULL;
const FR_NAME_NUMBER dict_attr_types[] = {
{ "integer", PW_TYPE_INTEGER },
{ "string", PW_TYPE_STRING },
- { "ipaddr", PW_TYPE_IPADDR },
+ { "ipaddr", PW_TYPE_IPV4_ADDR },
{ "date", PW_TYPE_DATE },
{ "abinary", PW_TYPE_ABINARY },
{ "octets", PW_TYPE_OCTETS },
{ "ifid", PW_TYPE_IFID },
- { "ipv6addr", PW_TYPE_IPV6ADDR },
- { "ipv6prefix", PW_TYPE_IPV6PREFIX },
+ { "ipv6addr", PW_TYPE_IPV6_ADDR },
+ { "ipv6prefix", PW_TYPE_IPV6_PREFIX },
{ "byte", PW_TYPE_BYTE },
{ "short", PW_TYPE_SHORT },
{ "ether", PW_TYPE_ETHERNET },
- { "combo-ip", PW_TYPE_COMBO_IP },
+ { "combo-ip", PW_TYPE_IP_ADDR },
{ "tlv", PW_TYPE_TLV },
{ "signed", PW_TYPE_SIGNED },
{ "extended", PW_TYPE_EXTENDED },
{ "int32", PW_TYPE_SIGNED },
{ "integer64", PW_TYPE_INTEGER64 },
{ "uint64", PW_TYPE_INTEGER64 },
- { "ipv4prefix", PW_TYPE_IPV4PREFIX },
+ { "ipv4prefix", PW_TYPE_IPV4_PREFIX },
+ { "cidr", PW_TYPE_IPV4_PREFIX },
+ { "vsa", PW_TYPE_VSA },
{ NULL, 0 }
};
+/*
+ * Map data types to min / max data sizes.
+ */
+const size_t dict_attr_sizes[PW_TYPE_MAX][2] = {
+ [PW_TYPE_INVALID] = { ~0, 0 },
+ [PW_TYPE_STRING] = { 0, ~0 },
+ [PW_TYPE_INTEGER] = {4, 4 },
+ [PW_TYPE_IPV4_ADDR] = {4, 4},
+ [PW_TYPE_DATE] = {4, 4},
+ [PW_TYPE_ABINARY] = {32, ~0},
+ [PW_TYPE_OCTETS] = {0, ~0},
+ [PW_TYPE_IFID] = {8, 8},
+ [PW_TYPE_IPV6_ADDR] = { 16, 16},
+ [PW_TYPE_IPV6_PREFIX] = {2, 18},
+ [PW_TYPE_BYTE] = {1, 1},
+ [PW_TYPE_SHORT] = {2, 2},
+ [PW_TYPE_ETHERNET] = {6, 6},
+ [PW_TYPE_SIGNED] = {4, 4},
+ [PW_TYPE_IP_ADDR] = {4, 16},
+ [PW_TYPE_TLV] = {2, ~0},
+ [PW_TYPE_EXTENDED] = {2, ~0},
+ [PW_TYPE_LONG_EXTENDED] = {3, ~0},
+ [PW_TYPE_EVS] = {6, ~0},
+ [PW_TYPE_INTEGER64] = {8, 8},
+ [PW_TYPE_IPV4_PREFIX] = {6, 6},
+ [PW_TYPE_VSA] = {4, ~0}
+};
/*
* For packing multiple TLV numbers into one 32-bit integer. The
* number into the upper 8 bits of the "vendor" field.
*
* e.g. OID attribute vendor
- * 241.1 1 (241 << 8)
- * 241.26.9.1 1 (241 << 8) | (9)
- * 241.1.2 1 | (2 << 8) (241 << 8)
+ * 241.1 1 (241 << 24)
+ * 241.26.9.1 1 (241 << 24) | (9)
+ * 241.1.2 1 | (2 << 8) (241 << 24)
*/
#define MAX_TLV_NEST (4)
/*
#define FNV_MAGIC_INIT (0x811c9dc5)
#define FNV_MAGIC_PRIME (0x01000193)
-static uint32_t dict_hashname(const char *name)
+static uint32_t dict_hashname(char const *name)
{
uint32_t hash = FNV_MAGIC_INIT;
- const char *p;
+ char const *p;
for (p = name; *p != '\0'; p++) {
- int c = *(const unsigned char *) p;
+ int c = *(unsigned char const *) p;
if (isalpha(c)) c = tolower(c);
hash *= FNV_MAGIC_PRIME;
/*
* Hash callback functions.
*/
-static uint32_t dict_attr_name_hash(const void *data)
+static uint32_t dict_attr_name_hash(void const *data)
{
- return dict_hashname(((const DICT_ATTR *)data)->name);
+ return dict_hashname(((DICT_ATTR const *)data)->name);
}
-static int dict_attr_name_cmp(const void *one, const void *two)
+static int dict_attr_name_cmp(void const *one, void const *two)
{
- const DICT_ATTR *a = one;
- const DICT_ATTR *b = two;
+ DICT_ATTR const *a = one;
+ DICT_ATTR const *b = two;
return strcasecmp(a->name, b->name);
}
-static uint32_t dict_attr_value_hash(const void *data)
+static uint32_t dict_attr_value_hash(void const *data)
{
uint32_t hash;
- const DICT_ATTR *attr = data;
+ DICT_ATTR const *attr = data;
hash = fr_hash(&attr->vendor, sizeof(attr->vendor));
return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);
}
-static int dict_attr_value_cmp(const void *one, const void *two)
+static int dict_attr_value_cmp(void const *one, void const *two)
{
- const DICT_ATTR *a = one;
- const DICT_ATTR *b = two;
+ DICT_ATTR const *a = one;
+ DICT_ATTR const *b = two;
if (a->vendor < b->vendor) return -1;
if (a->vendor > b->vendor) return +1;
return a->attr - b->attr;
}
-static uint32_t dict_attr_combo_hash(const void *data)
+static uint32_t dict_attr_combo_hash(void const *data)
{
uint32_t hash;
- const DICT_ATTR *attr = data;
+ DICT_ATTR const *attr = data;
hash = fr_hash(&attr->vendor, sizeof(attr->vendor));
hash = fr_hash_update(&attr->type, sizeof(attr->type), hash);
return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);
}
-static int dict_attr_combo_cmp(const void *one, const void *two)
+static int dict_attr_combo_cmp(void const *one, void const *two)
{
- const DICT_ATTR *a = one;
- const DICT_ATTR *b = two;
+ DICT_ATTR const *a = one;
+ DICT_ATTR const *b = two;
if (a->type < b->type) return -1;
if (a->type > b->type) return +1;
return a->attr - b->attr;
}
-static uint32_t dict_vendor_name_hash(const void *data)
+static uint32_t dict_vendor_name_hash(void const *data)
{
- return dict_hashname(((const DICT_VENDOR *)data)->name);
+ return dict_hashname(((DICT_VENDOR const *)data)->name);
}
-static int dict_vendor_name_cmp(const void *one, const void *two)
+static int dict_vendor_name_cmp(void const *one, void const *two)
{
- const DICT_VENDOR *a = one;
- const DICT_VENDOR *b = two;
+ DICT_VENDOR const *a = one;
+ DICT_VENDOR const *b = two;
return strcasecmp(a->name, b->name);
}
-static uint32_t dict_vendor_value_hash(const void *data)
+static uint32_t dict_vendor_value_hash(void const *data)
{
- return fr_hash(&(((const DICT_VENDOR *)data)->vendorpec),
- sizeof(((const DICT_VENDOR *)data)->vendorpec));
+ return fr_hash(&(((DICT_VENDOR const *)data)->vendorpec),
+ sizeof(((DICT_VENDOR const *)data)->vendorpec));
}
-static int dict_vendor_value_cmp(const void *one, const void *two)
+static int dict_vendor_value_cmp(void const *one, void const *two)
{
- const DICT_VENDOR *a = one;
- const DICT_VENDOR *b = two;
+ DICT_VENDOR const *a = one;
+ DICT_VENDOR const *b = two;
return a->vendorpec - b->vendorpec;
}
-static uint32_t dict_value_name_hash(const void *data)
+static uint32_t dict_value_name_hash(void const *data)
{
uint32_t hash;
- const DICT_VALUE *dval = data;
+ DICT_VALUE const *dval = data;
hash = dict_hashname(dval->name);
hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
return fr_hash_update(&dval->attr, sizeof(dval->attr), hash);
}
-static int dict_value_name_cmp(const void *one, const void *two)
+static int dict_value_name_cmp(void const *one, void const *two)
{
int rcode;
- const DICT_VALUE *a = one;
- const DICT_VALUE *b = two;
+ DICT_VALUE const *a = one;
+ DICT_VALUE const *b = two;
rcode = a->attr - b->attr;
if (rcode != 0) return rcode;
return strcasecmp(a->name, b->name);
}
-static uint32_t dict_value_value_hash(const void *data)
+static uint32_t dict_value_value_hash(void const *data)
{
uint32_t hash;
- const DICT_VALUE *dval = data;
+ DICT_VALUE const *dval = data;
hash = fr_hash(&dval->attr, sizeof(dval->attr));
hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
return fr_hash_update(&dval->value, sizeof(dval->value), hash);
}
-static int dict_value_value_cmp(const void *one, const void *two)
+static int dict_value_value_cmp(void const *one, void const *two)
{
int rcode;
- const DICT_VALUE *a = one;
- const DICT_VALUE *b = two;
+ DICT_VALUE const *a = one;
+ DICT_VALUE const *b = two;
if (a->vendor < b->vendor) return -1;
if (a->vendor > b->vendor) return +1;
{
dict_stat_t *this, *next;
- free(stat_root_dir);
- stat_root_dir = NULL;
- free(stat_root_file);
- stat_root_file = NULL;
-
if (!stat_head) {
stat_tail = NULL;
return;
for (this = stat_head; this != NULL; this = next) {
next = this->next;
- free(this->name);
free(this);
}
/*
* Add an entry to the list of stat buffers.
*/
-static void dict_stat_add(const char *name, const struct stat *stat_buf)
+static void dict_stat_add(struct stat const *stat_buf)
{
dict_stat_t *this;
if (!this) return;
memset(this, 0, sizeof(*this));
- this->name = strdup(name);
- this->mtime = stat_buf->st_mtime;
+ memcpy(&(this->stat_buf), stat_buf, sizeof(this->stat_buf));
if (!stat_head) {
stat_head = stat_tail = this;
* See if any dictionaries have changed. If not, don't
* do anything.
*/
-static int dict_stat_check(const char *root_dir, const char *root_file)
+static int dict_stat_check(char const *dir, char const *file)
{
- struct stat buf;
+ struct stat stat_buf;
dict_stat_t *this;
+ char buffer[2048];
- if (!stat_root_dir) return 0;
- if (!stat_root_file) return 0;
-
- if (strcmp(root_dir, stat_root_dir) != 0) return 0;
- if (strcmp(root_file, stat_root_file) != 0) return 0;
+ /*
+ * Nothing cached, all files are new.
+ */
+ if (!stat_head) return 0;
- if (!stat_head) return 0; /* changed, reload */
+ /*
+ * Stat the file.
+ */
+ snprintf(buffer, sizeof(buffer), "%s/%s", dir, file);
+ if (stat(buffer, &stat_buf) < 0) return 0;
+ /*
+ * Find the cache entry.
+ * FIXME: use a hash table.
+ * FIXME: check dependencies, via children.
+ * if A loads B and B changes, we probably want
+ * to reload B at the minimum.
+ */
for (this = stat_head; this != NULL; this = this->next) {
- if (stat(this->name, &buf) < 0) return 0;
+ if (this->stat_buf.st_dev != stat_buf.st_dev) continue;
+ if (this->stat_buf.st_ino != stat_buf.st_ino) continue;
+
+ /*
+ * The file has changed. Re-read it.
+ */
+ if (this->stat_buf.st_mtime < stat_buf.st_mtime) return 0;
- if (buf.st_mtime != this->mtime) return 0;
+ /*
+ * The file is the same. Ignore it.
+ */
+ return 1;
}
- return 1;
+ /*
+ * Not in the cache.
+ */
+ return 0;
}
typedef struct fr_pool_t {
/*
* Add vendor to the list.
*/
-int dict_addvendor(const char *name, unsigned int value)
+int dict_addvendor(char const *name, unsigned int value)
{
size_t length;
DICT_VENDOR *dv;
return 0;
}
+
+/*
+ * [a-zA-Z0-9_-:.]+
+ */
+const int dict_attr_allowed_chars[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+
/*
* Add an attribute to the dictionary.
*/
-int dict_addattr(const char *name, int attr, unsigned int vendor, int type,
+int dict_addattr(char const *name, int attr, unsigned int vendor, PW_TYPE type,
ATTR_FLAGS flags)
{
size_t namelen;
static int max_attr = 0;
- const char *p;
- const DICT_ATTR *da;
+ uint8_t const *p;
+ DICT_ATTR const *da;
DICT_ATTR *n;
-
+
namelen = strlen(name);
if (namelen >= DICT_ATTR_MAX_NAME_LEN) {
fr_strerror_printf("dict_addattr: attribute name too long");
return -1;
}
- for (p = name; *p != '\0'; p++) {
- if (*p < ' ') {
- fr_strerror_printf("dict_addattr: attribute name cannot contain control characters");
- return -1;
- }
-
- if ((*p == '"') || (*p == '\\')) {
- fr_strerror_printf("dict_addattr: attribute name cannot contain quotation or backslash");
- return -1;
- }
-
- if ((*p == '<') || (*p == '>') || (*p == '&')) {
- fr_strerror_printf("dict_addattr: attribute name cannot contain XML control characters");
+ for (p = (uint8_t const *) name; *p != '\0'; p++) {
+ if (!dict_attr_allowed_chars[*p]) {
+ fr_strerror_printf("dict_addattr: Invalid character '%c' in attribute name", *p);
return -1;
}
}
*/
if (flags.extended || flags.long_extended || flags.evs) {
if (vendor && (vendor < FR_MAX_VENDOR)) {
- fr_strerror_printf("dict_addattr: VSAs cannot use the \"extended\" or \"evs\" attribute formats.");
+ fr_strerror_printf("dict_addattr: VSAs cannot use the \"extended\" or \"evs\" attribute formats");
return -1;
}
if (flags.has_tag
|| flags.array
#endif
|| (flags.encrypt != FLAG_ENCRYPT_NONE)) {
- fr_strerror_printf("dict_addattr: The \"extended\" attributes MUST NOT have any flags set.");
+ fr_strerror_printf("dict_addattr: The \"extended\" attributes MUST NOT have any flags set");
return -1;
}
}
return -1;
}
}
-
+
+ /*
+ * Allow for generic pointers
+ */
+ switch (type) {
+ default:
+ break;
+
+ case PW_TYPE_STRING:
+ case PW_TYPE_OCTETS:
+ case PW_TYPE_TLV:
+ flags.is_pointer = true;
+ break;
+ }
+
if (attr < 0) {
fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (less than zero)");
return -1;
return -1;
}
+ if (vendor && flags.concat) {
+ fr_strerror_printf("VSAs cannot have the \"concat\" flag set");
+ return -1;
+ }
+
+ if (flags.concat && (type != PW_TYPE_OCTETS)) {
+ fr_strerror_printf("The \"concat\" flag can only be set for attributes of type \"octets\"");
+ return -1;
+ }
+
+ if (flags.concat && (flags.has_tag || flags.array || flags.is_tlv || flags.has_tlv ||
+ flags.length || flags.evs || flags.extended || flags.long_extended ||
+ (flags.encrypt != FLAG_ENCRYPT_NONE))) {
+ fr_strerror_printf("The \"concat\" flag cannot be used with any other flag");
+ return -1;
+ }
+
if ((vendor & (FR_MAX_VENDOR -1)) != 0) {
DICT_VENDOR *dv;
static DICT_VENDOR *last_vendor = NULL;
* properly.
*/
if ((dv->type == 1) && (attr >= 256) && !flags.is_tlv) {
- fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 255).");
+ fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 255)");
return -1;
} /* else 256..65535 are allowed */
}
/*
- * These flags are inhereited inherited
- * from the parent.
+ * These flags are inherited from the
+ * parent.
*/
flags.extended = da->flags.extended;
flags.long_extended = da->flags.long_extended;
*/
if ((n = fr_pool_alloc(sizeof(*n) + namelen)) == NULL) {
oom:
- fr_strerror_printf("dict_adnttr: out of memory");
+ fr_strerror_printf("dict_addattr: out of memory");
return -1;
}
a = fr_hash_table_finddata(attributes_byname, n);
if (a && (strcasecmp(a->name, n->name) == 0)) {
if (a->attr != n->attr) {
- fr_strerror_printf("dict_adnttr: Duplicate attribute name %s", name);
+ fr_strerror_printf("dict_addattr: Duplicate attribute name %s", name);
fr_pool_free(n);
return -1;
}
fr_hash_table_delete(attributes_byvalue, a);
if (!fr_hash_table_replace(attributes_byname, n)) {
- fr_strerror_printf("dict_adnttr: Internal error storing attribute %s", name);
+ fr_strerror_printf("dict_addattr: Internal error storing attribute %s", name);
fr_pool_free(n);
return -1;
}
* by value) we want to use the NEW name.
*/
if (!fr_hash_table_replace(attributes_byvalue, n)) {
- fr_strerror_printf("dict_adnttr: Failed inserting attribute name %s", name);
+ fr_strerror_printf("dict_addattr: Failed inserting attribute name %s", name);
return -1;
}
/*
* Hacks for combo-IP
*/
- if (n->type == PW_TYPE_COMBO_IP) {
+ if (n->type == PW_TYPE_IP_ADDR) {
DICT_ATTR *v4, *v6;
- v4 = malloc(sizeof(*v4));
+ v4 = fr_pool_alloc(sizeof(*v4));
if (!v4) goto oom;
- v6 = malloc(sizeof(*v6));
- if (!v6) {
- free(v4);
- goto oom;
- }
+ v6 = fr_pool_alloc(sizeof(*v6));
+ if (!v6) goto oom;
memcpy(v4, n, sizeof(*v4));
- v4->type = PW_TYPE_IPADDR;
+ v4->type = PW_TYPE_IPV4_ADDR;
memcpy(v6, n, sizeof(*v6));
- v6->type = PW_TYPE_IPV6ADDR;
-
- if (fr_hash_table_insert(attributes_combo, v4)) {
- fr_strerror_printf("dict_adnttr: Failed inserting attribute name %s", name);
- free(v4);
- free(v6);
+ v6->type = PW_TYPE_IPV6_ADDR;
+ if (!fr_hash_table_replace(attributes_combo, v4)) {
+ fr_strerror_printf("dict_addattr: Failed inserting attribute name %s - IPv4", name);
return -1;
}
- if (fr_hash_table_insert(attributes_combo, v6)) {
- fr_strerror_printf("dict_adnttr: Failed inserting attribute name %s", name);
- free(v6);
+ if (!fr_hash_table_replace(attributes_combo, v6)) {
+ fr_strerror_printf("dict_addattr: Failed inserting attribute name %s - IPv6", name);
return -1;
}
}
/*
* Add a value for an attribute to the dictionary.
*/
-int dict_addvalue(const char *namestr, const char *attrstr, int value)
+int dict_addvalue(char const *namestr, char const *attrstr, int value)
{
size_t length;
- const DICT_ATTR *dattr;
+ DICT_ATTR const *da;
DICT_VALUE *dval;
- static const DICT_ATTR *last_attr = NULL;
+ static DICT_ATTR const *last_attr = NULL;
if (!*namestr) {
fr_strerror_printf("dict_addvalue: empty names are not permitted");
* caching the last attribute.
*/
if (last_attr && (strcasecmp(attrstr, last_attr->name) == 0)) {
- dattr = last_attr;
+ da = last_attr;
} else {
- dattr = dict_attrbyname(attrstr);
- last_attr = dattr;
+ da = dict_attrbyname(attrstr);
+ last_attr = da;
}
/*
* Remember which attribute is associated with this
* value, if possible.
*/
- if (dattr) {
- if (dattr->flags.has_value_alias) {
+ if (da) {
+ if (da->flags.has_value_alias) {
fr_strerror_printf("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr);
return -1;
}
- dval->attr = dattr->attr;
- dval->vendor = dattr->vendor;
+ dval->attr = da->attr;
+ dval->vendor = da->vendor;
/*
* Enforce valid values
*
* Don't worry about fixups...
*/
- switch (dattr->type) {
+ switch (da->type) {
case PW_TYPE_BYTE:
if (value > 255) {
fr_pool_free(dval);
default:
fr_pool_free(dval);
fr_strerror_printf("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'",
- fr_int2str(dict_attr_types, dattr->type, "?Unknown?"));
+ fr_int2str(dict_attr_types, da->type, "?Unknown?"));
return -1;
}
} else {
{
DICT_ATTR *tmp;
memcpy(&tmp, &dval, sizeof(tmp));
-
+
if (!fr_hash_table_insert(values_byname, tmp)) {
- if (dattr) {
+ if (da) {
DICT_VALUE *old;
/*
* name and value. There are lots in
* dictionary.ascend.
*/
- old = dict_valbyname(dattr->attr, dattr->vendor, namestr);
+ old = dict_valbyname(da->attr, da->vendor, namestr);
if (old && (old->value == dval->value)) {
fr_pool_free(dval);
return 0;
return 0;
}
-static int sscanf_i(const char *str, unsigned int *pvalue)
+static int sscanf_i(char const *str, unsigned int *pvalue)
{
int rcode = 0;
int base = 10;
- static const char *tab = "0123456789";
+ static char const *tab = "0123456789";
if ((str[0] == '0') &&
((str[1] == 'x') || (str[1] == 'X'))) {
}
while (*str) {
- const char *c;
+ char const *c;
if (*str == '.') break;
*
* <whew>! Are we crazy, or what?
*/
-int dict_str2oid(const char *ptr, unsigned int *pvalue, unsigned int *pvendor,
+int dict_str2oid(char const *ptr, unsigned int *pvalue, unsigned int *pvendor,
int tlv_depth)
{
- const char *p;
+ char const *p;
unsigned int value;
- const DICT_ATTR *da;
+ DICT_ATTR const *da = NULL;
if (tlv_depth > fr_attr_max_tlv) {
fr_strerror_printf("Too many sub-attributes");
if (*pvalue) {
da = dict_attrbyvalue(*pvalue, *pvendor);
if (!da) {
- fr_strerror_printf("Parent attribute is undefined.");
+ fr_strerror_printf("Parent attribute is undefined");
return -1;
}
-
+
if (!da->flags.has_tlv && !da->flags.extended) {
fr_strerror_printf("Parent attribute %s cannot have sub-attributes",
da->name);
* If we find it, re-write the parameters, and recurse.
*/
if (!*pvendor && (tlv_depth == 0) && (*pvalue == PW_VENDOR_SPECIFIC)) {
- const DICT_VENDOR *dv;
+ DICT_VENDOR const *dv;
if (!p) {
fr_strerror_printf("VSA needs to have sub-attribute");
if (*pvendor >= FR_MAX_VENDOR) {
fr_strerror_printf("Cannot handle vendor ID larger than 2^24");
-
+
return -1;
}
return -1;
}
- if (!*pvendor && (tlv_depth == 1) &&
+ if (!*pvendor && (tlv_depth == 1) && da &&
(da->flags.has_tlv || da->flags.extended)) {
/*
* Bamboo skewers under the fingernails in 5, 4, 3, 2, ...
*/
-static const DICT_ATTR *dict_parent(unsigned int attr, unsigned int vendor)
+static DICT_ATTR const *dict_parent(unsigned int attr, unsigned int vendor)
{
if (vendor < FR_MAX_VENDOR) {
return dict_attrbyvalue(attr & 0xff, vendor);
/*
* Process the ATTRIBUTE command
*/
-static int process_attribute(const char* fn, const int line,
+static int process_attribute(char const* fn, int const line,
unsigned int block_vendor,
- const DICT_ATTR *block_tlv, int tlv_depth,
+ DICT_ATTR const *block_tlv, int tlv_depth,
char **argv, int argc)
{
int oid = 0;
}
if (oid) {
- const DICT_ATTR *da;
+ DICT_ATTR const *da;
vendor = block_vendor;
char buffer[256];
strlcpy(buffer, fr_strerror(), sizeof(buffer));
-
+
fr_strerror_printf("dict_init: %s[%d]: Invalid attribute identifier: %s", fn, line, buffer);
return -1;
}
} else {
type = PW_TYPE_OCTETS;
-
+
p = strchr(argv[2] + 7, ']');
if (!p) {
fr_strerror_printf("dict_init: %s[%d]: Invalid format for octets", fn, line);
break;
case PW_TYPE_DATE:
- case PW_TYPE_IPADDR:
+ case PW_TYPE_IPV4_ADDR:
case PW_TYPE_INTEGER:
case PW_TYPE_SIGNED:
length = 4;
length = 8;
break;
- case PW_TYPE_IPV6ADDR:
+ case PW_TYPE_IPV6_ADDR:
length = 16;
break;
fr_strerror_printf("dict_init: %s[%d]: Attributes of type \"extended\" MUST be RFC attributes with value >= 241.", fn, line);
return -1;
}
- type = PW_TYPE_OCTETS;
flags.extended = 1;
break;
fr_strerror_printf("dict_init: %s[%d]: Attributes of type \"long-extended\" MUST be RFC attributes with value >= 241.", fn, line);
return -1;
}
- type = PW_TYPE_OCTETS;
flags.extended = 1;
flags.long_extended = 1;
break;
case PW_TYPE_EVS:
- type = PW_TYPE_OCTETS;
flags.extended = 1;
flags.evs = 1;
if (value != PW_VENDOR_SPECIFIC) {
break;
}
- flags.length = length;
+ flags.length = length;
} else { /* argc == 4: we have options */
char *key, *next, *last;
/* Boolean flag, means this is a
tagged attribute */
flags.has_tag = 1;
-
+
} else if (strncmp(key, "encrypt=", 8) == 0) {
/* Encryption method, defaults to 0 (none).
Currently valid is just type 2,
fn, line);
return -1;
}
-
+
} else if (strncmp(key, "array", 6) == 0) {
flags.array = 1;
-
+
switch (type) {
- case PW_TYPE_IPADDR:
+ case PW_TYPE_IPV4_ADDR:
+ case PW_TYPE_IPV6_ADDR:
case PW_TYPE_BYTE:
case PW_TYPE_SHORT:
case PW_TYPE_INTEGER:
case PW_TYPE_DATE:
+ case PW_TYPE_STRING:
break;
default:
- fr_strerror_printf( "dict_init: %s[%d] Only IP addresses can have the \"array\" flag set.",
+ fr_strerror_printf( "dict_init: %s[%d] \"%s\" type cannot have the "
+ "\"array\" flag set",
+ fn, line,
+ fr_int2str(dict_attr_types, type, "<UNKNOWN>"));
+ return -1;
+ }
+
+ } else if (strncmp(key, "concat", 6) == 0) {
+ flags.concat = 1;
+
+ if (type != PW_TYPE_OCTETS) {
+ fr_strerror_printf( "dict_init: %s[%d] Only \"octets\" type can have the \"concat\" flag set.",
fn, line);
return -1;
}
}
flags.has_tlv = 1;
}
-
+
if (block_tlv) {
/*
* TLV's can be only one octet.
}
/*
- *
+ *
*/
value <<= fr_attr_shift[tlv_depth];
value |= block_tlv->attr;
/*
* Process the VALUE command
*/
-static int process_value(const char* fn, const int line, char **argv,
+static int process_value(char const* fn, int const line, char **argv,
int argc)
{
unsigned int value;
* This allows VALUE mappings to be shared among multiple
* attributes.
*/
-static int process_value_alias(const char* fn, const int line, char **argv,
+static int process_value_alias(char const* fn, int const line, char **argv,
int argc)
{
- const DICT_ATTR *my_da, *da;
+ DICT_ATTR const *my_da, *da;
DICT_VALUE *dval;
if (argc != 2) {
/*
* Process the VENDOR command
*/
-static int process_vendor(const char* fn, const int line, char **argv,
+static int process_vendor(char const* fn, int const line, char **argv,
int argc)
{
- int value;
- int continuation = 0;
- const char *format = NULL;
+ int value;
+ bool continuation = false;
+ char const *format = NULL;
if ((argc < 2) || (argc > 3)) {
fr_strerror_printf( "dict_init: %s[%d] invalid VENDOR entry",
if (format) {
int type, length;
- const char *p;
+ char const *p;
DICT_VENDOR *dv;
if (strncasecmp(format, "format=", 7) != 0) {
fn, line, p);
return -1;
}
- continuation = 1;
+ continuation = true;
if ((value != VENDORPEC_WIMAX) ||
(type != 1) || (length != 1)) {
return argc;
}
+static int my_dict_init(char const *parent, char const *filename,
+ char const *src_file, int src_line);
+
+int dict_read(char const *dir, char const *filename)
+{
+ if (!attributes_byname) {
+ fr_strerror_printf("Must call dict_init() before dict_read()");
+ return -1;
+ }
+
+ return my_dict_init(dir, filename, NULL, 0);
+}
+
+
#define MAX_ARGV (16)
/*
* Initialize the dictionary.
*/
-static int my_dict_init(const char *dir, const char *fn,
- const char *src_file, int src_line)
+static int my_dict_init(char const *parent, char const *filename,
+ char const *src_file, int src_line)
{
FILE *fp;
- char dirtmp[256];
+ char dir[256], fn[256];
char buf[256];
char *p;
int line = 0;
struct stat statbuf;
char *argv[MAX_ARGV];
int argc;
- const DICT_ATTR *da, *block_tlv[MAX_TLV_NEST + 1];
+ DICT_ATTR const *da, *block_tlv[MAX_TLV_NEST + 1];
int which_block_tlv = 0;
block_tlv[0] = NULL;
block_tlv[2] = NULL;
block_tlv[3] = NULL;
- if (strlen(fn) >= sizeof(dirtmp) / 2 ||
- strlen(dir) >= sizeof(dirtmp) / 2) {
+ if ((strlen(parent) + 3 + strlen(filename)) > sizeof(dir)) {
fr_strerror_printf("dict_init: filename name too long");
return -1;
}
/*
- * First see if fn is relative to dir. If so, create
- * new filename. If not, remember the absolute dir.
+ * If it's an absolute dir, forget the parent dir,
+ * and remember the new one.
+ *
+ * If it's a relative dir, tack on the current filename
+ * to the parent dir. And use that.
*/
- if ((p = strrchr(fn, FR_DIR_SEP)) != NULL) {
- strcpy(dirtmp, fn);
- dirtmp[p - fn] = 0;
- dir = dirtmp;
- } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
- snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn);
- fn = dirtmp;
+ if (!FR_DIR_IS_RELATIVE(filename)) {
+ strlcpy(dir, filename, sizeof(dir));
+ p = strrchr(dir, FR_DIR_SEP);
+ if (p) {
+ p[1] = '\0';
+ } else {
+ strlcat(dir, "/", sizeof(dir));
+ }
+
+ strlcpy(fn, filename, sizeof(fn));
+ } else {
+ strlcpy(dir, parent, sizeof(dir));
+ p = strrchr(dir, FR_DIR_SEP);
+ if (p) {
+ if (p[1]) strlcat(dir, "/", sizeof(dir));
+ } else {
+ strlcat(dir, "/", sizeof(dir));
+ }
+ strlcat(dir, filename, sizeof(dir));
+ p = strrchr(dir, FR_DIR_SEP);
+ if (p) {
+ p[1] = '\0';
+ } else {
+ strlcat(dir, "/", sizeof(dir));
+ }
+
+ p = strrchr(filename, FR_DIR_SEP);
+ if (p) {
+ snprintf(fn, sizeof(fn), "%s%s", dir, p);
+ } else {
+ snprintf(fn, sizeof(fn), "%s%s", dir, filename);
+ }
+
+ }
+
+ /*
+ * Check if we've loaded this file before. If so, ignore it.
+ */
+ p = strrchr(fn, FR_DIR_SEP);
+ if (p) {
+ *p = '\0';
+ if (dict_stat_check(fn, p + 1)) {
+ *p = FR_DIR_SEP;
+ return 0;
+ }
+ *p = FR_DIR_SEP;
}
if ((fp = fopen(fn, "r")) == NULL) {
if (!src_file) {
fr_strerror_printf("dict_init: Couldn't open dictionary \"%s\": %s",
- fn, strerror(errno));
+ fn, fr_syserror(errno));
} else {
fr_strerror_printf("dict_init: %s[%d]: Couldn't open dictionary \"%s\": %s",
- src_file, src_line, fn, strerror(errno));
+ src_file, src_line, fn, fr_syserror(errno));
}
return -2;
}
}
#endif
- dict_stat_add(fn, &statbuf);
+ dict_stat_add(&statbuf);
/*
* Seed the random pool with data.
fclose(fp);
return -1;
}
-
+
p = argv[2] + 7;
da = dict_attrbyname(p);
if (!da) {
fclose(fp);
return -1;
}
-
+
/*
* Pack the encapsulating
* attribute into the upper 8
/*
* Empty callback for hash table initialization.
*/
-static int null_callback(void *ctx, void *data)
+static int null_callback(UNUSED void *ctx, UNUSED void *data)
{
- ctx = ctx; /* -Wunused */
- data = data; /* -Wunused */
-
return 0;
}
* Initialize the directory, then fix the attr member of
* all attributes.
*/
-int dict_init(const char *dir, const char *fn)
+int dict_init(char const *dir, char const *fn)
{
/*
* Check if we need to change anything. If not, don't do
* Free the dictionaries, and the stat cache.
*/
dict_free();
- stat_root_dir = strdup(dir);
- stat_root_file = strdup(fn);
/*
* Create the table of vendor by name. There MAY NOT
return -1;
if (value_fixup) {
- const DICT_ATTR *a;
+ DICT_ATTR const *a;
value_fixup_t *this, *next;
for (this = value_fixup; this != NULL; this = next) {
}
/** Free dynamically allocated (unknown attributes)
- *
+ *
* If the da was dynamically allocated it will be freed, else the function
* will return without doing anything.
*
* @param da to free.
*/
-void dict_attr_free(DICT_ATTR * const *da)
+void dict_attr_free(DICT_ATTR const **da)
{
DICT_ATTR **tmp;
-
+
+ if (!da || !*da) return;
+
/* Don't free real DAs */
if (!(*da)->flags.is_unknown) {
return;
}
-
+
memcpy(&tmp, &da, sizeof(*tmp));
free(*tmp);
-
- *tmp = NULL;
+
+ *tmp = NULL;
}
/** Copies a dictionary attr
* If the attr is known, a pointer to the da will be returned.
*
* @param da to copy.
+ * @param vp_free if true, da will be freed at the same time as the
+ * VALUE_PAIR which contains it.
* @return return a copy of the da.
*/
-const DICT_ATTR *dict_attr_copy(const DICT_ATTR *da)
+DICT_ATTR const *dict_attr_copy(DICT_ATTR const *da, int vp_free)
{
DICT_ATTR *copy;
-
+
+ if (!da) return NULL;
+
if (!da->flags.is_unknown) {
return da;
}
-
+
copy = malloc(DICT_ATTR_SIZE);
if (!copy) {
fr_strerror_printf("Out of memory");
return NULL;
}
-
+
memcpy(copy, da, DICT_ATTR_SIZE);
-
+ copy->flags.vp_free = (vp_free != 0);
+
return copy;
}
*
* @param[in] attr number.
* @param[in] vendor number.
+ * @param[in] vp_free if > 0 DICT_ATTR will be freed on VALUE_PAIR free.
* @return new dictionary attribute.
*/
-const DICT_ATTR *dict_attrunknown(unsigned int attr, unsigned int vendor)
+DICT_ATTR const *dict_attrunknown(unsigned int attr, unsigned int vendor,
+ int vp_free)
{
DICT_ATTR *da;
char *p;
int dv_type = 1;
size_t len = 0;
size_t bufsize = DICT_ATTR_MAX_NAME_LEN;
-
+
da = malloc(DICT_ATTR_SIZE);
if (!da) {
fr_strerror_printf("Out of memory");
return NULL;
}
memset(da, 0, DICT_ATTR_SIZE);
-
+
da->attr = attr;
da->vendor = vendor;
da->type = PW_TYPE_OCTETS;
- da->flags.is_unknown = TRUE;
-
+ da->flags.is_unknown = true;
+ da->flags.vp_free = (vp_free != 0);
+
+ /*
+ * Unknown attributes of the "WiMAX" vendor get marked up
+ * as being for WiMAX.
+ */
+ if (vendor == VENDORPEC_WIMAX) {
+ da->flags.wimax = 1;
+ }
+
p = da->name;
-
+
len = snprintf(p, bufsize, "Attr-");
p += len;
bufsize -= len;
dv_type = dv->type;
}
len = snprintf(p, bufsize, "26.%u.", vendor);
-
+
p += len;
bufsize -= len;
}
- p += print_attr_oid(p, bufsize , attr, dv_type);
-
+ print_attr_oid(p, bufsize , attr, dv_type);
+
return da;
}
*
* @todo should check attr/vendor against dictionary and return the real da.
*
- * @param attribute name to parse.
+ * @param[in] attribute name.
+ * @param[in] vp_free if > 0 DICT_ATTR will be freed on VALUE_PAIR free.
* @return new da or NULL on error.
*/
-const DICT_ATTR *dict_attrunknownbyname(const char *attribute)
+DICT_ATTR const *dict_attrunknownbyname(char const *attribute, int vp_free)
{
unsigned int attr, vendor = 0;
unsigned int dv_type = 1; /* The type of vendor field */
- const char *p = attribute;
+ char const *p = attribute;
char *q;
-
+
DICT_VENDOR *dv;
- const DICT_ATTR *da;
+ DICT_ATTR const *da;
/*
* Pull off vendor prefix first.
vendor = (int) strtol(p + 7, &q, 10);
if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
fr_strerror_printf("Invalid vendor value in "
- "attribute name \"%s\"",
+ "attribute name \"%s\"",
attribute);
return NULL;
}
vendor = dict_vendorbyname(buffer);
if (!vendor) {
- fr_strerror_printf("Unknown vendor name in "
- "attribute name \"%s\"",
+ fr_strerror_printf("Unknown attribute \"%s\"",
attribute);
return NULL;
}
}
p++;
}
-
+
/*
* Attr-%d
*/
if (strncasecmp(p, "Attr-", 5) != 0) {
- fr_strerror_printf("Invalid format in attribute name \"%s\"",
+ fr_strerror_printf("Unknown attribute \"%s\"",
attribute);
return NULL;
}
}
p = q;
-
+
/*
* Vendor-%d-Attr-%d
* VendorName-Attr-%d
fr_strerror_printf("Invalid OID");
return NULL;
}
-
+
/*
* Look for OIDs. Require the "Attr-26.Vendor-Id.type"
* format, and disallow "Vendor-%d-Attr-%d" and
fr_strerror_printf("Cannot parse attributes without "
"dictionaries");
return NULL;
- }
-
+ }
+
if ((attr != PW_VENDOR_SPECIFIC) &&
!(da->flags.extended || da->flags.long_extended)) {
fr_strerror_printf("Standard attributes cannot use "
if (dv_type > 3) dv_type = 3; /* hack */
}
}
-
+
/*
* Parse the next number. It could be a Vendor-Type
* of 1..2^24, or it could be a TLV.
if (*q != '.') {
goto invalid;
}
-
+
if (dv_type != 1) {
goto invalid;
}
}
}
- return dict_attrunknown(attr, vendor);
+ return dict_attrunknown(attr, vendor, vp_free);
}
/*
* Get an attribute by its numerical value.
*/
-const DICT_ATTR *dict_attrbyvalue(unsigned int attr, unsigned int vendor)
+DICT_ATTR const *dict_attrbyvalue(unsigned int attr, unsigned int vendor)
{
- DICT_ATTR dattr;
+ DICT_ATTR da;
if ((attr > 0) && (attr < 256) && !vendor) return dict_base_attrs[attr];
- dattr.attr = attr;
- dattr.vendor = vendor;
+ da.attr = attr;
+ da.vendor = vendor;
- return fr_hash_table_finddata(attributes_byvalue, &dattr);
+ return fr_hash_table_finddata(attributes_byvalue, &da);
}
*
* @return The attribute, or NULL if not found
*/
-const DICT_ATTR *dict_attrbytype(unsigned int attr, unsigned int vendor,
- PW_TYPE type)
+DICT_ATTR const *dict_attrbytype(unsigned int attr, unsigned int vendor,
+ PW_TYPE type)
{
- DICT_ATTR dattr;
+ DICT_ATTR da;
- dattr.attr = attr;
- dattr.vendor = vendor;
- dattr.type = type;
+ da.attr = attr;
+ da.vendor = vendor;
+ da.type = type;
- return fr_hash_table_finddata(attributes_combo, &dattr);
+ return fr_hash_table_finddata(attributes_combo, &da);
}
-
-/*
- * Get an attribute by it's numerical value, and the parent
+/**
+ * @brief Using a parent and attr/vendor, find a child attr/vendor
*/
-const DICT_ATTR *dict_attrbyparent(const DICT_ATTR *parent, unsigned int attr)
+int dict_attr_child(DICT_ATTR const *parent,
+ unsigned int *pattr, unsigned int *pvendor)
{
- DICT_ATTR dattr;
+ unsigned int attr, vendor;
+ DICT_ATTR da;
+
+ if (!parent || !pattr || !pvendor) return false;
- if (!parent) return NULL;
+ attr = *pattr;
+ vendor = *pvendor;
/*
- * Only TLVs can have children
+ * Only some types can have children
*/
- if (!parent->flags.has_tlv) return NULL;
+ switch (parent->type) {
+ default: return false;
+
+ case PW_TYPE_VSA:
+ case PW_TYPE_TLV:
+ case PW_TYPE_EVS:
+ case PW_TYPE_EXTENDED:
+ case PW_TYPE_LONG_EXTENDED:
+ break;
+ }
+
+ if ((vendor == 0) && (parent->vendor != 0)) return false;
/*
* Bootstrap by starting off with the parents values.
*/
- dattr.attr = parent->attr;
- dattr.vendor = parent->vendor;
+ da.attr = parent->attr;
+ da.vendor = parent->vendor;
/*
* Do various butchery to insert the "attr" value.
* EEVID 000000AA EVS with vendor VID, attr AAA
* EEVID DDCCBBAA EVS with TLVs
*/
- if (!dattr.vendor) {
- dattr.vendor = parent->attr * FR_MAX_VENDOR;
- dattr.attr = attr;
+ if (!da.vendor) {
+ da.vendor = parent->attr * FR_MAX_VENDOR;
+ da.vendor |= vendor;
+ da.attr = attr;
} else {
int i;
* Trying to nest too deep. It's an error
*/
if (parent->attr & (fr_attr_mask[MAX_TLV_NEST] << fr_attr_shift[MAX_TLV_NEST])) {
- return NULL;
+ return false;
}
for (i = MAX_TLV_NEST - 1; i >= 0; i--) {
if ((parent->attr & (fr_attr_mask[i] << fr_attr_shift[i]))) {
- dattr.attr |= (attr & fr_attr_mask[i + 1]) << fr_attr_shift[i + 1];
+ da.attr |= (attr & fr_attr_mask[i + 1]) << fr_attr_shift[i + 1];
goto find;
}
}
- return NULL;
+ return false;
}
find:
- return fr_hash_table_finddata(attributes_byvalue, &dattr);
+#if 0
+ fprintf(stderr, "LOOKING FOR %08x %08x + %08x %08x --> %08x %08x\n",
+ parent->vendor, parent->attr, attr, vendor,
+ da.vendor, da.attr);
+#endif
+
+ *pattr = da.attr;
+ *pvendor = da.vendor;
+ return true;
+}
+
+/*
+ * Get an attribute by it's numerical value, and the parent
+ */
+DICT_ATTR const *dict_attrbyparent(DICT_ATTR const *parent, unsigned int attr, unsigned int vendor)
+{
+ unsigned int my_attr, my_vendor;
+ DICT_ATTR da;
+
+ my_attr = attr;
+ my_vendor = vendor;
+
+ if (!dict_attr_child(parent, &my_attr, &my_vendor)) return NULL;
+
+ da.attr = my_attr;
+ da.vendor = my_vendor;
+
+ return fr_hash_table_finddata(attributes_byvalue, &da);
}
/*
* Get an attribute by its name.
*/
-const DICT_ATTR *dict_attrbyname(const char *name)
+DICT_ATTR const *dict_attrbyname(char const *name)
+{
+ DICT_ATTR *da;
+ uint32_t buffer[(sizeof(*da) + DICT_ATTR_MAX_NAME_LEN + 3)/4];
+
+ if (!name) return NULL;
+
+ da = (DICT_ATTR *) buffer;
+ strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1);
+
+ return fr_hash_table_finddata(attributes_byname, da);
+}
+
+/*
+ * Get an attribute by its name, where the name might have a tag
+ * or something else after it.
+ */
+DICT_ATTR const *dict_attrbytagged_name(char const *name)
{
DICT_ATTR *da;
+ char *p;
uint32_t buffer[(sizeof(*da) + DICT_ATTR_MAX_NAME_LEN + 3)/4];
if (!name) return NULL;
da = (DICT_ATTR *) buffer;
strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1);
+ /*
+ * The name might have a tag or array reference. That
+ * isn't properly part of the name, and can be ignored on
+ * lookup.
+ */
+ for (p = &da->name[0]; *p; p++) {
+ if (*p == ':') {
+ *p = '\0';
+ break;
+ }
+
+ if (*p == '[') {
+ *p = '\0';
+ break;
+ }
+ }
+
return fr_hash_table_finddata(attributes_byname, da);
}
/*
* Associate a value with an attribute and return it.
*/
-const char *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value)
+char const *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value)
{
DICT_VALUE *dv;
/*
* Get a value by its name, keyed off of an attribute.
*/
-DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, const char *name)
+DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, char const *name)
{
DICT_VALUE *my_dv, *dv;
uint32_t buffer[(sizeof(*my_dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4];
*
* This is efficient only for small numbers of vendors.
*/
-int dict_vendorbyname(const char *name)
+int dict_vendorbyname(char const *name)
{
DICT_VENDOR *dv;
- uint32_t buffer[(sizeof(*dv) + DICT_VENDOR_MAX_NAME_LEN + 3)/4];
+ size_t buffer[(sizeof(*dv) + DICT_VENDOR_MAX_NAME_LEN + sizeof(size_t) - 1) / sizeof(size_t)];
if (!name) return 0;