2 * dict.c Routines to read the dictionary file.
4 * Version: @(#)dict.c 2.30 25-Jul-1999 miquels@cistron.nl
12 #include <sys/types.h>
21 #include "libradius.h"
23 static DICT_ATTR *dictionary_attributes;
24 static DICT_VALUE *dictionary_values;
25 static DICT_VENDOR *dictionary_vendors;
27 static int vendorno = 1;
28 static char *dtypes[] = {
36 #ifdef WITH_DICT_NOCASE
37 #define DICT_STRCMP strcasecmp
39 #define DICT_STRCMP strcmp
43 * Free the dictionary_attributes and dictionary_values lists.
45 static void dict_free(void)
47 DICT_ATTR *dattr, *anext;
48 DICT_VALUE *dval, *vnext;
49 DICT_VENDOR *dvend, *enext;
51 for (dattr = dictionary_attributes; dattr; dattr = anext) {
55 for (dval = dictionary_values; dval; dval = vnext) {
59 for (dvend = dictionary_vendors; dvend; dvend = enext) {
63 dictionary_attributes = NULL;
64 dictionary_values = NULL;
65 dictionary_vendors = NULL;
70 * Add vendor to the list.
72 static int addvendor(char *name, int value)
76 if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) == NULL) {
77 librad_log("dict_init: out of memory");
80 strcpy(vval->vendorname, name);
81 vval->vendorpec = value;
82 vval->vendorcode = vendorno++;
84 /* Insert at front. */
85 vval->next = dictionary_vendors;
86 dictionary_vendors = vval;
92 * Initialize the dictionary.
94 static int my_dict_init(char *dir, char *fn)
116 int vendor_usr_seen = 0;
121 * First see if fn is relative to dir. If so, create
122 * new filename. If not, remember the absolute dir.
124 if ((p = strrchr(fn, '/')) != NULL) {
128 } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
129 sprintf(dirtmp, "%s/%s", dir, fn);
133 if ((fp = fopen(fn, "r")) == NULL) {
134 librad_log("dict_init: Couldn't open dictionary: %s", fn);
138 while (fgets(buf, sizeof(buf), fp) != NULL) {
141 if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n')
144 keyword = strtok(buf, " \t\n");
145 data = strtok(NULL, "\n");
146 if (data == NULL || data[0] == 0) {
147 librad_log("dict_init: %s[%d]: invalid entry",
153 * See if we need to import another dictionary.
155 if (strcasecmp(keyword, "$INCLUDE") == 0) {
156 if (my_dict_init(dir, data) < 0)
162 * Perhaps this is an attribute.
165 if (strcmp(keyword, "ATTRIBUTE") == 0)
169 if (strcmp(keyword, "ATTRIB_NMC") == 0)
170 is_attrib = is_nmc = 1;
176 if(sscanf(data, "%s%s%s%s", namestr,
177 valstr, typestr, vendorstr) < 3) {
179 "dict_init: %s[%d]: invalid attribute",
186 * Convert ATTRIB_NMC into our format.
187 * We might need to add USR to the list of
190 if (is_nmc && vendorstr[0] == 0) {
191 if (!vendor_usr_seen) {
192 if (addvendor("USR", VENDORPEC_USR) < 0)
196 strcpy(vendorstr, "USR");
200 * Validate all entries
202 if (strlen(namestr) > 31) {
204 "dict_init: %s[%d]: invalid name length",
209 if (!isdigit(*valstr)) {
210 librad_log("dict_init: %s[%d]: invalid value",
214 if (valstr[0] != '0')
215 value = atoi(valstr);
217 sscanf(valstr, "%i", &value);
222 for (type = 0; dtypes[type]; type++) {
223 if (strcmp(typestr, dtypes[type]) == 0)
226 if (dtypes[type] == NULL) {
227 librad_log("dict_init: %s[%d]: invalid type",
233 * Find the vendor, if any.
235 for (v = dictionary_vendors; v; v = v->next) {
236 if (strcmp(vendorstr, v->vendorname) == 0)
237 vendor = v->vendorcode;
239 if (vendorstr[0] && !vendor) {
241 "dict_init: %s[%d]: unknown vendor %s",
242 fn, line, vendorstr);
247 * Create a new attribute for the list
249 if ((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) ==
251 librad_log("dict_init: out of memory");
254 strcpy(attr->name, namestr);
258 attr->attr |= (vendor << 16);
261 * Add to the front of the list, so that
262 * values at the end of the file override
263 * those in the begin.
265 attr->next = dictionary_attributes;
266 dictionary_attributes = attr;
271 * Process VALUE lines.
273 if (strcmp(keyword, "VALUE") == 0) {
275 if (sscanf(data, "%s%s%s", attrstr,
276 namestr, valstr) != 3) {
277 librad_log("dict_init: %s[%d]: invalid value",
282 * For Compatibility, skip "Server-Config"
284 if (strcmp(attrstr, "Server-Config") == 0)
288 * Validate all entries
290 if (strlen(attrstr) > 31) {
292 "dict_init: %s[%d]: invalid attribute length",
297 if (strlen(namestr) > 31) {
299 "dict_init: %s[%d]: invalid name length",
304 if (!isdigit(*valstr)) {
305 librad_log("dict_init: %s[%d]: invalid value",
309 if (valstr[0] != '0')
310 value = atoi(valstr);
312 sscanf(valstr, "%i", &value);
314 if ((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) ==
316 librad_log("dict_init: out of memory");
320 strcpy(dval->name, namestr);
321 strcpy(dval->attrname, attrstr);
325 /* Insert at front. */
326 dval->next = dictionary_values;
327 dictionary_values = dval;
331 * Process VENDOR lines.
333 if (strcmp(keyword, "VENDOR") == 0) {
335 if (sscanf(data, "%s%s", attrstr, valstr) != 2) {
337 "dict_init: %s[%d] invalid vendor entry",
343 * Validate all entries
345 if (strlen(attrstr) > 31) {
347 "dict_init: %s[%d]: invalid attribute length",
352 if (!isdigit(*valstr)) {
353 librad_log("dict_init: %s[%d]: invalid value",
357 value = atoi(valstr);
359 /* Create a new VENDOR entry for the list */
360 if (addvendor(attrstr, value) < 0)
363 if (value == VENDORPEC_USR)
373 * Initialize the directory, then fix the attr member of
376 int dict_init(char *dir, char *fn)
383 if (my_dict_init(dir, fn) < 0)
386 for (dval = dictionary_values; dval; dval = dval->next) {
389 if ((attr = dict_attrbyname(dval->attrname)) == NULL) {
390 librad_log("dict_init: VALUE %s for unknown ATTRIBUTE %s",
391 dval->name, dval->attrname);
394 dval->attr = attr->attr;
401 * Get an attribute by its numerical value.
403 DICT_ATTR * dict_attrbyvalue(int val)
407 for (a = dictionary_attributes; a; a = a->next) {
416 * Get an attribute by its name.
418 DICT_ATTR * dict_attrbyname(char *name)
422 for (a = dictionary_attributes; a; a = a->next) {
423 if (DICT_STRCMP(a->name, name) == 0)
431 * Associate a value with an attribute and return it.
433 DICT_VALUE * dict_valbyattr(int attr, int val)
437 for (v = dictionary_values; v; v = v->next) {
438 if (v->attr == attr && v->value == val)
446 * Get a value by its name.
448 DICT_VALUE * dict_valbyname(char *name)
452 for (v = dictionary_values; v; v = v->next) {
453 if (DICT_STRCMP(v->name, name) == 0)
461 * Get the PEC (Private Enterprise Code) of the vendor
462 * based on its internal number.
464 int dict_vendorpec(int code)
468 for (v = dictionary_vendors; v; v = v->next)
469 if (v->vendorcode == code)
472 return v ? v->vendorpec : 0;
476 * Get the internal code of the vendor based on its PEC.
478 int dict_vendorcode(int pec)
482 for (v = dictionary_vendors; v; v = v->next)
483 if (v->vendorpec == pec)
485 return v ? v->vendorcode : 0;