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 int dict_addvendor(char *name, int value)
76 if (strlen(name) > (sizeof(vval->vendorname) -1)) {
77 librad_log("dict_addvendor: vendor name too long");
81 if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) == NULL) {
82 librad_log("dict_addvendor: out of memory");
85 strcpy(vval->vendorname, name);
86 vval->vendorpec = value;
87 vval->vendorcode = vendorno++;
89 /* Insert at front. */
90 vval->next = dictionary_vendors;
91 dictionary_vendors = vval;
96 int dict_addattr(char *name, int vendor, int type, int value)
100 if (strlen(name) > (sizeof(attr->name) -1)) {
101 librad_log("dict_addattr: attribute name too long");
106 * Create a new attribute for the list
108 if ((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) == NULL) {
109 librad_log("dict_addattr: out of memory");
112 strcpy(attr->name, name);
116 attr->attr |= (vendor << 16);
120 * Add to the front of the list, so that
121 * values at the end of the file override
122 * those in the begin.
124 attr->next = dictionary_attributes;
125 dictionary_attributes = attr;
130 int dict_addvalue(char *namestr, char *attrstr, int value)
134 if (strlen(namestr) > (sizeof(dval->name) -1)) {
135 librad_log("dict_addvalue: value name too long");
139 if (strlen(attrstr) > (sizeof(dval->attrname) -1)) {
140 librad_log("dict_addvalue: attribute name too long");
144 if ((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) == NULL) {
145 librad_log("dict_addvalue: out of memory");
149 strcpy(dval->name, namestr);
150 strcpy(dval->attrname, attrstr);
151 dval->attr = 0; /* ??? */
154 /* Insert at front. */
155 dval->next = dictionary_values;
156 dictionary_values = dval;
162 * Initialize the dictionary.
164 static int my_dict_init(char *dir, char *fn)
183 int vendor_usr_seen = 0;
188 * First see if fn is relative to dir. If so, create
189 * new filename. If not, remember the absolute dir.
191 if ((p = strrchr(fn, '/')) != NULL) {
195 } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
196 sprintf(dirtmp, "%s/%s", dir, fn);
200 if ((fp = fopen(fn, "r")) == NULL) {
201 librad_log("dict_init: Couldn't open dictionary: %s", fn);
205 while (fgets(buf, sizeof(buf), fp) != NULL) {
208 if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n')
211 keyword = strtok(buf, " \t\n");
212 data = strtok(NULL, "\n");
213 if (data == NULL || data[0] == 0) {
214 librad_log("dict_init: %s[%d]: invalid entry",
220 * See if we need to import another dictionary.
222 if (strcasecmp(keyword, "$INCLUDE") == 0) {
223 if (my_dict_init(dir, data) < 0)
229 * Perhaps this is an attribute.
232 if (strcmp(keyword, "ATTRIBUTE") == 0)
236 if (strcmp(keyword, "ATTRIB_NMC") == 0)
237 is_attrib = is_nmc = 1;
243 if(sscanf(data, "%s%s%s%s", namestr,
244 valstr, typestr, vendorstr) < 3) {
246 "dict_init: %s[%d]: invalid attribute",
253 * Convert ATTRIB_NMC into our format.
254 * We might need to add USR to the list of
257 if (is_nmc && vendorstr[0] == 0) {
258 if (!vendor_usr_seen) {
259 if (dict_addvendor("USR", VENDORPEC_USR) < 0)
260 librad_log("dict_init: %s[%d]: %s", fn, line, librad_errstr);
264 strcpy(vendorstr, "USR");
268 * Validate all entries
270 if (!isdigit(*valstr)) {
271 librad_log("dict_init: %s[%d]: invalid value",
275 if (valstr[0] != '0')
276 value = atoi(valstr);
278 sscanf(valstr, "%i", &value);
283 for (type = 0; dtypes[type]; type++) {
284 if (strcmp(typestr, dtypes[type]) == 0)
287 if (dtypes[type] == NULL) {
288 librad_log("dict_init: %s[%d]: invalid type",
293 vendor = dict_vendorname(vendorstr);
294 if (vendorstr[0] && !vendor) {
296 "dict_init: %s[%d]: unknown vendor %s",
297 fn, line, vendorstr);
301 if (dict_addattr(namestr, vendor, type, value) < 0) {
302 librad_log("dict_init: %s[%d]: %s",
303 fn, line, librad_errstr);
310 * Process VALUE lines.
312 if (strcmp(keyword, "VALUE") == 0) {
314 if (sscanf(data, "%s%s%s", attrstr,
315 namestr, valstr) != 3) {
316 librad_log("dict_init: %s[%d]: invalid value",
321 * For Compatibility, skip "Server-Config"
323 if (strcmp(attrstr, "Server-Config") == 0)
327 * Validate all entries
329 if (!isdigit(*valstr)) {
330 librad_log("dict_init: %s[%d]: invalid value",
334 if (valstr[0] != '0')
335 value = atoi(valstr);
337 sscanf(valstr, "%i", &value);
339 if (dict_addvalue(namestr, attrstr, value) < 0) {
340 librad_log("dict_init: %s[%d]: %s",
341 fn, line, librad_errstr);
347 * Process VENDOR lines.
349 if (strcmp(keyword, "VENDOR") == 0) {
351 if (sscanf(data, "%s%s", attrstr, valstr) != 2) {
353 "dict_init: %s[%d] invalid vendor entry",
359 * Validate all entries
361 if (!isdigit(*valstr)) {
362 librad_log("dict_init: %s[%d]: invalid value",
366 value = atoi(valstr);
368 /* Create a new VENDOR entry for the list */
369 if (dict_addvendor(attrstr, value) < 0) {
370 librad_log("dict_init: %s[%d]: %s",
371 fn, line, librad_errstr);
375 if (value == VENDORPEC_USR)
385 * Initialize the directory, then fix the attr member of
388 int dict_init(char *dir, char *fn)
395 if (my_dict_init(dir, fn) < 0)
398 for (dval = dictionary_values; dval; dval = dval->next) {
401 if ((attr = dict_attrbyname(dval->attrname)) == NULL) {
402 librad_log("dict_init: VALUE %s for unknown ATTRIBUTE %s",
403 dval->name, dval->attrname);
406 dval->attr = attr->attr;
413 * Get an attribute by its numerical value.
415 DICT_ATTR * dict_attrbyvalue(int val)
419 for (a = dictionary_attributes; a; a = a->next) {
428 * Get an attribute by its name.
430 DICT_ATTR * dict_attrbyname(char *name)
434 for (a = dictionary_attributes; a; a = a->next) {
435 if (DICT_STRCMP(a->name, name) == 0)
443 * Associate a value with an attribute and return it.
445 DICT_VALUE * dict_valbyattr(int attr, int val)
449 for (v = dictionary_values; v; v = v->next) {
450 if (v->attr == attr && v->value == val)
458 * Get a value by its name.
460 DICT_VALUE * dict_valbyname(char *name)
464 for (v = dictionary_values; v; v = v->next) {
465 if (DICT_STRCMP(v->name, name) == 0)
473 * Get the PEC (Private Enterprise Code) of the vendor
474 * based on its internal number.
476 int dict_vendorpec(int code)
480 for (v = dictionary_vendors; v; v = v->next)
481 if (v->vendorcode == code)
484 return v ? v->vendorpec : 0;
488 * Get the internal code of the vendor based on its PEC.
490 int dict_vendorcode(int pec)
494 for (v = dictionary_vendors; v; v = v->next)
495 if (v->vendorpec == pec)
497 return v ? v->vendorcode : 0;
501 * Get the vendor code based on the vendor name
503 int dict_vendorname(char *name)
508 * Find the vendor, if any.
510 for (v = dictionary_vendors; v; v = v->next) {
511 if (strcmp(name, v->vendorname) == 0) {
512 return v->vendorcode;