2 * dict.c Routines to read the dictionary file.
8 static const char rcsid[] = "$Id$";
14 #include <sys/types.h>
23 #include "libradius.h"
26 static DICT_ATTR *dictionary_attributes;
27 static DICT_VALUE *dictionary_values;
28 static DICT_VENDOR *dictionary_vendors;
30 static int vendorno = 1;
31 static char *dtypes[] = {
41 #ifdef WITH_DICT_NOCASE
42 #define DICT_STRCMP strcasecmp
44 #define DICT_STRCMP strcmp
48 * Free the dictionary_attributes and dictionary_values lists.
50 static void dict_free(void)
52 DICT_ATTR *dattr, *anext;
53 DICT_VALUE *dval, *vnext;
54 DICT_VENDOR *dvend, *enext;
56 for (dattr = dictionary_attributes; dattr; dattr = anext) {
60 for (dval = dictionary_values; dval; dval = vnext) {
64 for (dvend = dictionary_vendors; dvend; dvend = enext) {
68 dictionary_attributes = NULL;
69 dictionary_values = NULL;
70 dictionary_vendors = NULL;
75 * Add vendor to the list.
77 int dict_addvendor(char *name, int value)
81 if (strlen(name) > (sizeof(vval->vendorname) -1)) {
82 librad_log("dict_addvendor: vendor name too long");
86 if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) == NULL) {
87 librad_log("dict_addvendor: out of memory");
90 strcpy(vval->vendorname, name);
91 vval->vendorpec = value;
92 vval->vendorcode = vendorno++;
94 /* Insert at front. */
95 vval->next = dictionary_vendors;
96 dictionary_vendors = vval;
101 int dict_addattr(char *name, int vendor, int type, int value)
105 if (strlen(name) > (sizeof(attr->name) -1)) {
106 librad_log("dict_addattr: attribute name too long");
111 * Create a new attribute for the list
113 if ((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) == NULL) {
114 librad_log("dict_addattr: out of memory");
117 strcpy(attr->name, name);
121 attr->attr |= (vendor << 16);
125 * Add to the front of the list, so that
126 * values at the end of the file override
127 * those in the begin.
129 attr->next = dictionary_attributes;
130 dictionary_attributes = attr;
135 int dict_addvalue(char *namestr, char *attrstr, int value)
139 if (strlen(namestr) > (sizeof(dval->name) -1)) {
140 librad_log("dict_addvalue: value name too long");
144 if (strlen(attrstr) > (sizeof(dval->attrname) -1)) {
145 librad_log("dict_addvalue: attribute name too long");
149 if ((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) == NULL) {
150 librad_log("dict_addvalue: out of memory");
154 strcpy(dval->name, namestr);
155 strcpy(dval->attrname, attrstr);
156 dval->attr = 0; /* ??? */
159 /* Insert at front. */
160 dval->next = dictionary_values;
161 dictionary_values = dval;
167 * Initialize the dictionary.
169 static int my_dict_init(char *dir, char *fn)
188 int vendor_usr_seen = 0;
193 * First see if fn is relative to dir. If so, create
194 * new filename. If not, remember the absolute dir.
196 if ((p = strrchr(fn, '/')) != NULL) {
200 } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
201 sprintf(dirtmp, "%s/%s", dir, fn);
205 if ((fp = fopen(fn, "r")) == NULL) {
206 librad_log("dict_init: Couldn't open dictionary: %s", fn);
210 while (fgets(buf, sizeof(buf), fp) != NULL) {
213 if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n')
216 keyword = strtok(buf, " \t\n");
217 data = strtok(NULL, "\n");
218 if (data == NULL || data[0] == 0) {
219 librad_log("dict_init: %s[%d]: invalid entry",
225 * See if we need to import another dictionary.
227 if (strcasecmp(keyword, "$INCLUDE") == 0) {
228 if (my_dict_init(dir, data) < 0)
234 * Perhaps this is an attribute.
237 if (strcmp(keyword, "ATTRIBUTE") == 0)
241 if (strcmp(keyword, "ATTRIB_NMC") == 0)
242 is_attrib = is_nmc = 1;
248 if(sscanf(data, "%s%s%s%s", namestr,
249 valstr, typestr, vendorstr) < 3) {
251 "dict_init: %s[%d]: invalid attribute",
258 * Convert ATTRIB_NMC into our format.
259 * We might need to add USR to the list of
262 if (is_nmc && vendorstr[0] == 0) {
263 if (!vendor_usr_seen) {
264 if (dict_addvendor("USR", VENDORPEC_USR) < 0)
265 librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr);
269 strcpy(vendorstr, "USR");
273 * Validate all entries
275 if (!isdigit(*valstr)) {
276 librad_log("dict_init: %s[%d]: invalid value",
280 if (valstr[0] != '0')
281 value = atoi(valstr);
283 sscanf(valstr, "%i", &value);
288 for (type = 0; dtypes[type]; type++) {
289 if (strcmp(typestr, dtypes[type]) == 0)
292 if (dtypes[type] == NULL) {
293 librad_log("dict_init: %s[%d]: invalid type",
298 vendor = dict_vendorname(vendorstr);
299 if (vendorstr[0] && !vendor) {
301 "dict_init: %s[%d]: unknown vendor %s",
302 fn, line, vendorstr);
306 if (dict_addattr(namestr, vendor, type, value) < 0) {
307 librad_log("dict_init: %s[%d]: %s",
308 fn, line, librad_errstr);
315 * Process VALUE lines.
317 if (strcmp(keyword, "VALUE") == 0) {
319 if (sscanf(data, "%s%s%s", attrstr,
320 namestr, valstr) != 3) {
321 librad_log("dict_init: %s[%d]: invalid value",
326 * For Compatibility, skip "Server-Config"
328 if (strcmp(attrstr, "Server-Config") == 0)
332 * Validate all entries
334 if (!isdigit(*valstr)) {
335 librad_log("dict_init: %s[%d]: invalid value",
339 if (valstr[0] != '0')
340 value = atoi(valstr);
342 sscanf(valstr, "%i", &value);
344 if (dict_addvalue(namestr, attrstr, value) < 0) {
345 librad_log("dict_init: %s[%d]: %s",
346 fn, line, librad_errstr);
352 * Process VENDOR lines.
354 if (strcmp(keyword, "VENDOR") == 0) {
356 if (sscanf(data, "%s%s", attrstr, valstr) != 2) {
358 "dict_init: %s[%d] invalid vendor entry",
364 * Validate all entries
366 if (!isdigit(*valstr)) {
367 librad_log("dict_init: %s[%d]: invalid value",
371 value = atoi(valstr);
373 /* Create a new VENDOR entry for the list */
374 if (dict_addvendor(attrstr, value) < 0) {
375 librad_log("dict_init: %s[%d]: %s",
376 fn, line, librad_errstr);
380 if (value == VENDORPEC_USR)
390 * Initialize the directory, then fix the attr member of
393 int dict_init(char *dir, char *fn)
400 if (my_dict_init(dir, fn) < 0)
403 for (dval = dictionary_values; dval; dval = dval->next) {
406 if ((attr = dict_attrbyname(dval->attrname)) == NULL) {
407 librad_log("dict_init: VALUE %s for unknown ATTRIBUTE %s",
408 dval->name, dval->attrname);
411 dval->attr = attr->attr;
418 * Get an attribute by its numerical value.
420 DICT_ATTR * dict_attrbyvalue(int val)
424 for (a = dictionary_attributes; a; a = a->next) {
433 * Get an attribute by its name.
435 DICT_ATTR * dict_attrbyname(char *name)
439 for (a = dictionary_attributes; a; a = a->next) {
440 if (DICT_STRCMP(a->name, name) == 0)
448 * Associate a value with an attribute and return it.
450 DICT_VALUE * dict_valbyattr(int attr, int val)
454 for (v = dictionary_values; v; v = v->next) {
455 if (v->attr == attr && v->value == val)
463 * Get a value by its name.
465 DICT_VALUE * dict_valbyname(char *name)
469 for (v = dictionary_values; v; v = v->next) {
470 if (DICT_STRCMP(v->name, name) == 0)
478 * Get the PEC (Private Enterprise Code) of the vendor
479 * based on its internal number.
481 int dict_vendorpec(int code)
485 for (v = dictionary_vendors; v; v = v->next)
486 if (v->vendorcode == code)
489 return v ? v->vendorpec : 0;
493 * Get the internal code of the vendor based on its PEC.
495 int dict_vendorcode(int pec)
499 for (v = dictionary_vendors; v; v = v->next)
500 if (v->vendorpec == pec)
502 return v ? v->vendorcode : 0;
506 * Get the vendor code based on the vendor name
508 int dict_vendorname(char *name)
513 * Find the vendor, if any.
515 for (v = dictionary_vendors; v; v = v->next) {
516 if (strcmp(name, v->vendorname) == 0) {
517 return v->vendorcode;