6c144148bbefa66bf6383629cc1b3cd3ea1416f4
[freeradius.git] / src / lib / dict.c
1 /*
2  * dict.c       Routines to read the dictionary file.
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006  The FreeRADIUS server project
21  */
22
23 #include        <freeradius-devel/ident.h>
24 RCSID("$Id$")
25
26 #include        <freeradius-devel/libradius.h>
27
28 #include        <ctype.h>
29
30 #ifdef HAVE_MALLOC_H
31 #include        <malloc.h>
32 #endif
33
34 #ifdef HAVE_SYS_STAT_H
35 #include        <sys/stat.h>
36 #endif
37
38 #define DICT_VALUE_MAX_NAME_LEN (128)
39 #define DICT_VENDOR_MAX_NAME_LEN (128)
40 #define DICT_ATTR_MAX_NAME_LEN (128)
41
42 static fr_hash_table_t *vendors_byname = NULL;
43 static fr_hash_table_t *vendors_byvalue = NULL;
44
45 static fr_hash_table_t *attributes_byname = NULL;
46 static fr_hash_table_t *attributes_byvalue = NULL;
47
48 static fr_hash_table_t *values_byvalue = NULL;
49 static fr_hash_table_t *values_byname = NULL;
50
51 static DICT_ATTR *dict_base_attrs[256];
52
53 /*
54  *      For faster HUP's, we cache the stat information for
55  *      files we've $INCLUDEd
56  */
57 typedef struct dict_stat_t {
58         struct dict_stat_t *next;
59         char               *name;
60         time_t             mtime;
61 } dict_stat_t;
62
63 static char *stat_root_dir = NULL;
64 static char *stat_root_file = NULL;
65
66 static dict_stat_t *stat_head = NULL;
67 static dict_stat_t *stat_tail = NULL;
68
69 typedef struct value_fixup_t {
70         char            attrstr[DICT_ATTR_MAX_NAME_LEN];
71         DICT_VALUE      *dval;
72         struct value_fixup_t *next;
73 } value_fixup_t;
74
75
76 /*
77  *      So VALUEs in the dictionary can have forward references.
78  */
79 static value_fixup_t *value_fixup = NULL;
80
81 static const FR_NAME_NUMBER type_table[] = {
82         { "integer",    PW_TYPE_INTEGER },
83         { "string",     PW_TYPE_STRING },
84         { "ipaddr",     PW_TYPE_IPADDR },
85         { "date",       PW_TYPE_DATE },
86         { "abinary",    PW_TYPE_ABINARY },
87         { "octets",     PW_TYPE_OCTETS },
88         { "ifid",       PW_TYPE_IFID },
89         { "ipv6addr",   PW_TYPE_IPV6ADDR },
90         { "ipv6prefix", PW_TYPE_IPV6PREFIX },
91         { "byte",       PW_TYPE_BYTE },
92         { "short",      PW_TYPE_SHORT },
93         { "ether",      PW_TYPE_ETHERNET },
94         { "combo-ip",   PW_TYPE_COMBO_IP },
95         { "tlv",        PW_TYPE_TLV },
96         { "signed",     PW_TYPE_SIGNED },
97         { NULL, 0 }
98 };
99
100
101 /*
102  *      WiMAX craziness.
103  */
104 #define MAX_TLV_NEST (4)
105 /*
106  *      Bit packing:
107  *      8 bits of base VSA
108  *      8 bits for nested TLV 1
109  *      8 bits for nested TLV 2
110  *      5 bits for nested TLV 3
111  *      3 bits for nested TLV 4
112  */
113 const int fr_wimax_max_tlv = MAX_TLV_NEST;
114 const int fr_wimax_shift[MAX_TLV_NEST + 1] = {
115   0, 8, 16, 24, 29
116 };
117
118 const int fr_wimax_mask[MAX_TLV_NEST + 1] = {
119   0, 0xff, 0xff, 0x1f, 0x07
120 };
121
122
123 /*
124  *      Create the hash of the name.
125  *
126  *      We copy the hash function here because it's substantially faster.
127  */
128 #define FNV_MAGIC_INIT (0x811c9dc5)
129 #define FNV_MAGIC_PRIME (0x01000193)
130
131 static uint32_t dict_hashname(const char *name)
132 {
133         uint32_t hash = FNV_MAGIC_INIT;
134         const char *p;
135
136         for (p = name; *p != '\0'; p++) {
137                 int c = *(const unsigned char *) p;
138                 if (isalpha(c)) c = tolower(c);
139
140                 hash *= FNV_MAGIC_PRIME;
141                 hash ^= (uint32_t ) (c & 0xff);
142         }
143
144         return hash;
145 }
146
147
148 /*
149  *      Hash callback functions.
150  */
151 static uint32_t dict_attr_name_hash(const void *data)
152 {
153         return dict_hashname(((const DICT_ATTR *)data)->name);
154 }
155
156 static int dict_attr_name_cmp(const void *one, const void *two)
157 {
158         const DICT_ATTR *a = one;
159         const DICT_ATTR *b = two;
160
161         return strcasecmp(a->name, b->name);
162 }
163
164 static uint32_t dict_attr_value_hash(const void *data)
165 {
166         uint32_t hash;
167         const DICT_ATTR *attr = data;
168
169         hash = fr_hash(&attr->vendor, sizeof(attr->vendor));
170         return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);
171 }
172
173 static int dict_attr_value_cmp(const void *one, const void *two)
174 {
175         const DICT_ATTR *a = one;
176         const DICT_ATTR *b = two;
177
178         if (a->vendor < b->vendor) return -1;
179         if (a->vendor > b->vendor) return +1;
180
181         return a->attr - b->attr;
182 }
183
184 static uint32_t dict_vendor_name_hash(const void *data)
185 {
186         return dict_hashname(((const DICT_VENDOR *)data)->name);
187 }
188
189 static int dict_vendor_name_cmp(const void *one, const void *two)
190 {
191         const DICT_VENDOR *a = one;
192         const DICT_VENDOR *b = two;
193
194         return strcasecmp(a->name, b->name);
195 }
196
197 static uint32_t dict_vendor_value_hash(const void *data)
198 {
199         return fr_hash(&(((const DICT_VENDOR *)data)->vendorpec),
200                          sizeof(((const DICT_VENDOR *)data)->vendorpec));
201 }
202
203 static int dict_vendor_value_cmp(const void *one, const void *two)
204 {
205         const DICT_VENDOR *a = one;
206         const DICT_VENDOR *b = two;
207
208         return a->vendorpec - b->vendorpec;
209 }
210
211 static uint32_t dict_value_name_hash(const void *data)
212 {
213         uint32_t hash;
214         const DICT_VALUE *dval = data;
215
216         hash = dict_hashname(dval->name);
217         hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
218         return fr_hash_update(&dval->attr, sizeof(dval->attr), hash);
219 }
220
221 static int dict_value_name_cmp(const void *one, const void *two)
222 {
223         int rcode;
224         const DICT_VALUE *a = one;
225         const DICT_VALUE *b = two;
226
227         rcode = a->attr - b->attr;
228         if (rcode != 0) return rcode;
229
230         rcode = a->vendor - b->vendor;
231         if (rcode != 0) return rcode;
232
233         return strcasecmp(a->name, b->name);
234 }
235
236 static uint32_t dict_value_value_hash(const void *data)
237 {
238         uint32_t hash;
239         const DICT_VALUE *dval = data;
240
241         hash = fr_hash(&dval->attr, sizeof(dval->attr));
242         hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
243         return fr_hash_update(&dval->value, sizeof(dval->value), hash);
244 }
245
246 static int dict_value_value_cmp(const void *one, const void *two)
247 {
248         int rcode;
249         const DICT_VALUE *a = one;
250         const DICT_VALUE *b = two;
251
252         if (a->vendor < b->vendor) return -1;
253         if (a->vendor > b->vendor) return +1;
254
255         rcode = a->attr - b->attr;
256         if (rcode != 0) return rcode;
257
258         return a->value - b->value;
259 }
260
261
262 /*
263  *      Free the list of stat buffers
264  */
265 static void dict_stat_free(void)
266 {
267         dict_stat_t *this, *next;
268
269         free(stat_root_dir);
270         stat_root_dir = NULL;
271         free(stat_root_file);
272         stat_root_file = NULL;
273
274         if (!stat_head) {
275                 stat_tail = NULL;
276                 return;
277         }
278
279         for (this = stat_head; this != NULL; this = next) {
280                 next = this->next;
281                 free(this->name);
282                 free(this);
283         }
284
285         stat_head = stat_tail = NULL;
286 }
287
288
289 /*
290  *      Add an entry to the list of stat buffers.
291  */
292 static void dict_stat_add(const char *name, const struct stat *stat_buf)
293 {
294         dict_stat_t *this;
295
296         this = malloc(sizeof(*this));
297         if (!this) return;
298         memset(this, 0, sizeof(*this));
299
300         this->name = strdup(name);
301         this->mtime = stat_buf->st_mtime;
302
303         if (!stat_head) {
304                 stat_head = stat_tail = this;
305         } else {
306                 stat_tail->next = this;
307                 stat_tail = this;
308         }
309 }
310
311
312 /*
313  *      See if any dictionaries have changed.  If not, don't
314  *      do anything.
315  */
316 static int dict_stat_check(const char *root_dir, const char *root_file)
317 {
318         struct stat buf;
319         dict_stat_t *this;
320
321         if (!stat_root_dir) return 0;
322         if (!stat_root_file) return 0;
323
324         if (strcmp(root_dir, stat_root_dir) != 0) return 0;
325         if (strcmp(root_file, stat_root_file) != 0) return 0;
326
327         if (!stat_head) return 0; /* changed, reload */
328
329         for (this = stat_head; this != NULL; this = this->next) {
330                 if (stat(this->name, &buf) < 0) return 0;
331
332                 if (buf.st_mtime != this->mtime) return 0;
333         }
334
335         return 1;
336 }
337
338 typedef struct fr_pool_t {
339         void    *page_end;
340         void    *free_ptr;
341         struct fr_pool_t *page_free;
342         struct fr_pool_t *page_next;
343 } fr_pool_t;
344
345 #define FR_POOL_SIZE (32768)
346 #define FR_ALLOC_ALIGN (8)
347
348 static fr_pool_t *dict_pool = NULL;
349
350 static fr_pool_t *fr_pool_create(void)
351 {
352         fr_pool_t *fp = malloc(FR_POOL_SIZE);
353
354         if (!fp) return NULL;
355
356         memset(fp, 0, FR_POOL_SIZE);
357
358         fp->page_end = ((uint8_t *) fp) + FR_POOL_SIZE;
359         fp->free_ptr = ((uint8_t *) fp) + sizeof(*fp);
360         fp->page_free = fp;
361         fp->page_next = NULL;
362         return fp;
363 }
364
365 static void fr_pool_delete(fr_pool_t **pfp)
366 {
367         fr_pool_t *fp, *next;
368
369         if (!pfp || !*pfp) return;
370
371         for (fp = *pfp; fp != NULL; fp = next) {
372                 next = fp->page_next;
373                 free(fp);
374         }
375 }
376
377
378 static void *fr_pool_alloc(size_t size)
379 {
380         void *ptr;
381
382         if (size == 0) return NULL;
383
384         if (size > 256) return NULL; /* shouldn't happen */
385
386         if (!dict_pool) {
387                 dict_pool = fr_pool_create();
388                 if (!dict_pool) return NULL;
389         }
390
391         if ((size & (FR_ALLOC_ALIGN - 1)) != 0) {
392                 size += FR_ALLOC_ALIGN - (size & (FR_ALLOC_ALIGN - 1));
393         }
394
395         if ((((uint8_t *) dict_pool->page_free->free_ptr) + size) > (uint8_t *) dict_pool->page_free->page_end) {
396                 dict_pool->page_free->page_next = fr_pool_create();
397                 if (!dict_pool->page_free->page_next) return NULL;
398                 dict_pool->page_free = dict_pool->page_free->page_next;
399         }
400
401         ptr = dict_pool->page_free->free_ptr;
402         dict_pool->page_free->free_ptr = ((uint8_t *) dict_pool->page_free->free_ptr) + size;
403
404         return ptr;
405 }
406
407
408 static void fr_pool_free(UNUSED void *ptr)
409 {
410         /*
411          *      Place-holder for later code.
412          */
413 }
414
415 /*
416  *      Free the dictionary_attributes and dictionary_values lists.
417  */
418 void dict_free(void)
419 {
420         /*
421          *      Free the tables
422          */
423         fr_hash_table_free(vendors_byname);
424         fr_hash_table_free(vendors_byvalue);
425         vendors_byname = NULL;
426         vendors_byvalue = NULL;
427
428         fr_hash_table_free(attributes_byname);
429         fr_hash_table_free(attributes_byvalue);
430         attributes_byname = NULL;
431         attributes_byvalue = NULL;
432
433         fr_hash_table_free(values_byname);
434         fr_hash_table_free(values_byvalue);
435         values_byname = NULL;
436         values_byvalue = NULL;
437
438         memset(dict_base_attrs, 0, sizeof(dict_base_attrs));
439
440         fr_pool_delete(&dict_pool);
441
442         dict_stat_free();
443 }
444
445
446 /*
447  *      Add vendor to the list.
448  */
449 int dict_addvendor(const char *name, int value)
450 {
451         size_t length;
452         DICT_VENDOR *dv;
453
454         if (value > FR_MAX_VENDOR) {
455                 fr_strerror_printf("dict_addvendor: Cannot handle vendor ID larger than 2^24");
456                 return -1;
457         }
458
459         if ((length = strlen(name)) >= DICT_VENDOR_MAX_NAME_LEN) {
460                 fr_strerror_printf("dict_addvendor: vendor name too long");
461                 return -1;
462         }
463
464         if ((dv = fr_pool_alloc(sizeof(*dv) + length)) == NULL) {
465                 fr_strerror_printf("dict_addvendor: out of memory");
466                 return -1;
467         }
468
469         strcpy(dv->name, name);
470         dv->vendorpec  = value;
471         dv->type = dv->length = 1; /* defaults */
472
473         if (!fr_hash_table_insert(vendors_byname, dv)) {
474                 DICT_VENDOR *old_dv;
475
476                 old_dv = fr_hash_table_finddata(vendors_byname, dv);
477                 if (!old_dv) {
478                         fr_strerror_printf("dict_addvendor: Failed inserting vendor name %s", name);
479                         return -1;
480                 }
481                 if (old_dv->vendorpec != dv->vendorpec) {
482                         fr_strerror_printf("dict_addvendor: Duplicate vendor name %s", name);
483                         return -1;
484                 }
485
486                 /*
487                  *      Already inserted.  Discard the duplicate entry.
488                  */
489                 fr_pool_free(dv);
490                 return 0;
491         }
492
493         /*
494          *      Insert the SAME pointer (not free'd when this table is
495          *      deleted), into another table.
496          *
497          *      We want this behaviour because we want OLD names for
498          *      the attributes to be read from the configuration
499          *      files, but when we're printing them, (and looking up
500          *      by value) we want to use the NEW name.
501          */
502         if (!fr_hash_table_replace(vendors_byvalue, dv)) {
503                 fr_strerror_printf("dict_addvendor: Failed inserting vendor %s",
504                            name);
505                 return -1;
506         }
507
508         return 0;
509 }
510
511 /*
512  *      Add an attribute to the dictionary.
513  */
514 int dict_addattr(const char *name, int attr, int vendor, int type,
515                  ATTR_FLAGS flags)
516 {
517         size_t namelen;
518         static int      max_attr = 0;
519         DICT_ATTR       *da;
520
521         namelen = strlen(name);
522         if (namelen >= DICT_ATTR_MAX_NAME_LEN) {
523                 fr_strerror_printf("dict_addattr: attribute name too long");
524                 return -1;
525         }
526
527         /*
528          *      If the attr is '-1', that means use a pre-existing
529          *      one (if it already exists).  If one does NOT already exist,
530          *      then create a new attribute, with a non-conflicting value,
531          *      and use that.
532          */
533         if (attr == -1) {
534                 if (dict_attrbyname(name)) {
535                         return 0; /* exists, don't add it again */
536                 }
537
538                 attr = ++max_attr;
539
540         } else if (vendor == 0) {
541                 /*
542                  *  Update 'max_attr'
543                  */
544                 if (attr > max_attr) {
545                         max_attr = attr;
546                 }
547         }
548
549         if (attr < 0) {
550                 fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (less than zero)");
551                 return -1;
552         }
553
554         if (vendor) {
555                 DICT_VENDOR *dv;
556                 static DICT_VENDOR *last_vendor = NULL;
557
558                 if (flags.has_tlv && (flags.encrypt != FLAG_ENCRYPT_NONE)) {
559                         fr_strerror_printf("TLV's cannot be encrypted");
560                         return -1;
561                 }
562
563                 if (flags.is_tlv && flags.has_tag) {
564                         fr_strerror_printf("Sub-TLV's cannot have a tag");
565                         return -1;
566                 }
567
568                 if (flags.has_tlv && flags.has_tag) {
569                         fr_strerror_printf("TLV's cannot have a tag");
570                         return -1;
571                 }
572
573                 /*
574                  *      Most ATTRIBUTEs are bunched together by
575                  *      VENDOR.  We can save a lot of lookups on
576                  *      dictionary initialization by caching the last
577                  *      vendor.
578                  */
579                 if (last_vendor && (vendor == last_vendor->vendorpec)) {
580                         dv = last_vendor;
581                 } else {
582                         dv = dict_vendorbyvalue(vendor);
583                         last_vendor = dv;
584                 }
585
586                 /*
587                  *      If the vendor isn't defined, die.
588                  */
589                 if (!dv) {
590                         fr_strerror_printf("dict_addattr: Unknown vendor %d",
591                                            vendor);
592                         return -1;
593                 }
594
595                 /*
596                  *      FIXME: Switch over dv->type, and limit things
597                  *      properly.
598                  */
599                 if ((dv->type == 1) && (attr >= 256) && !flags.is_tlv) {
600                         fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 255).");
601                         return -1;
602                 } /* else 256..65535 are allowed */
603         }
604
605         /*
606          *      Create a new attribute for the list
607          */
608         if ((da = fr_pool_alloc(sizeof(*da) + namelen)) == NULL) {
609                 fr_strerror_printf("dict_addattr: out of memory");
610                 return -1;
611         }
612
613         memcpy(da->name, name, namelen);
614         da->name[namelen] = '\0';
615         da->attr = attr;
616         da->vendor = vendor;
617         da->type = type;
618         da->flags = flags;
619         da->vendor = vendor;
620
621         /*
622          *      Insert the attribute, only if it's not a duplicate.
623          */
624         if (!fr_hash_table_insert(attributes_byname, da)) {
625                 DICT_ATTR       *a;
626
627                 /*
628                  *      If the attribute has identical number, then
629                  *      ignore the duplicate.
630                  */
631                 a = fr_hash_table_finddata(attributes_byname, da);
632                 if (a && (strcasecmp(a->name, da->name) == 0)) {
633                         if (a->attr != da->attr) {
634                                 fr_strerror_printf("dict_addattr: Duplicate attribute name %s", name);
635                                 fr_pool_free(da);
636                                 return -1;
637                         }
638
639                         /*
640                          *      Same name, same vendor, same attr,
641                          *      maybe the flags and/or type is
642                          *      different.  Let the new value
643                          *      over-ride the old one.
644                          */
645                 }
646
647
648                 fr_hash_table_delete(attributes_byvalue, a);
649
650                 if (!fr_hash_table_replace(attributes_byname, da)) {
651                         fr_strerror_printf("dict_addattr: Internal error storing attribute %s", name);
652                         fr_pool_free(da);
653                         return -1;
654                 }
655         }
656
657         /*
658          *      Insert the SAME pointer (not free'd when this entry is
659          *      deleted), into another table.
660          *
661          *      We want this behaviour because we want OLD names for
662          *      the attributes to be read from the configuration
663          *      files, but when we're printing them, (and looking up
664          *      by value) we want to use the NEW name.
665          */
666         if (!fr_hash_table_replace(attributes_byvalue, da)) {
667                 fr_strerror_printf("dict_addattr: Failed inserting attribute name %s", name);
668                 return -1;
669         }
670
671         if (!vendor && (attr > 0) && (attr < 256)) {
672                  dict_base_attrs[attr] = da;
673         }
674
675         return 0;
676 }
677
678
679 /*
680  *      Add a value for an attribute to the dictionary.
681  */
682 int dict_addvalue(const char *namestr, const char *attrstr, int value)
683 {
684         size_t          length;
685         DICT_ATTR       *dattr;
686         DICT_VALUE      *dval;
687
688         static DICT_ATTR *last_attr = NULL;
689
690         if (!*namestr) {
691                 fr_strerror_printf("dict_addvalue: empty names are not permitted");
692                 return -1;
693         }
694
695         if ((length = strlen(namestr)) >= DICT_VALUE_MAX_NAME_LEN) {
696                 fr_strerror_printf("dict_addvalue: value name too long");
697                 return -1;
698         }
699
700         if ((dval = fr_pool_alloc(sizeof(*dval) + length)) == NULL) {
701                 fr_strerror_printf("dict_addvalue: out of memory");
702                 return -1;
703         }
704         memset(dval, 0, sizeof(*dval));
705
706         strcpy(dval->name, namestr);
707         dval->value = value;
708
709         /*
710          *      Most VALUEs are bunched together by ATTRIBUTE.  We can
711          *      save a lot of lookups on dictionary initialization by
712          *      caching the last attribute.
713          */
714         if (last_attr && (strcasecmp(attrstr, last_attr->name) == 0)) {
715                 dattr = last_attr;
716         } else {
717                 dattr = dict_attrbyname(attrstr);
718                 last_attr = dattr;
719         }
720
721         /*
722          *      Remember which attribute is associated with this
723          *      value, if possible.
724          */
725         if (dattr) {
726                 if (dattr->flags.has_value_alias) {
727                         fr_strerror_printf("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr);
728                         return -1;
729                 }
730
731                 dval->attr = dattr->attr;
732                 dval->vendor = dattr->vendor;
733
734                 /*
735                  *      Enforce valid values
736                  *
737                  *      Don't worry about fixups...
738                  */
739                 switch (dattr->type) {
740                         case PW_TYPE_BYTE:
741                                 if (value > 255) {
742                                         fr_pool_free(dval);
743                                         fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255");
744                                         return -1;
745                                 }
746                                 break;
747                         case PW_TYPE_SHORT:
748                                 if (value > 65535) {
749                                         fr_pool_free(dval);
750                                         fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535");
751                                         return -1;
752                                 }
753                                 break;
754
755                                 /*
756                                  *      Allow octets for now, because
757                                  *      of dictionary.cablelabs
758                                  */
759                         case PW_TYPE_OCTETS:
760
761                         case PW_TYPE_INTEGER:
762                                 break;
763
764                         default:
765                                 fr_pool_free(dval);
766                                 fr_strerror_printf("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'",
767                                            fr_int2str(type_table, dattr->type, "?Unknown?"));
768                                 return -1;
769                 }
770
771                 dattr->flags.has_value = 1;
772         } else {
773                 value_fixup_t *fixup;
774
775                 fixup = (value_fixup_t *) malloc(sizeof(*fixup));
776                 if (!fixup) {
777                         fr_pool_free(dval);
778                         fr_strerror_printf("dict_addvalue: out of memory");
779                         return -1;
780                 }
781                 memset(fixup, 0, sizeof(*fixup));
782
783                 strlcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr));
784                 fixup->dval = dval;
785
786                 /*
787                  *      Insert to the head of the list.
788                  */
789                 fixup->next = value_fixup;
790                 value_fixup = fixup;
791
792                 return 0;
793         }
794
795         /*
796          *      Add the value into the dictionary.
797          */
798         if (!fr_hash_table_insert(values_byname, dval)) {
799                 if (dattr) {
800                         DICT_VALUE *old;
801
802                         /*
803                          *      Suppress duplicates with the same
804                          *      name and value.  There are lots in
805                          *      dictionary.ascend.
806                          */
807                         old = dict_valbyname(dattr->attr, dattr->vendor, namestr);
808                         if (old && (old->value == dval->value)) {
809                                 fr_pool_free(dval);
810                                 return 0;
811                         }
812                 }
813
814                 fr_pool_free(dval);
815                 fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr);
816                 return -1;
817         }
818
819         /*
820          *      There are multiple VALUE's, keyed by attribute, so we
821          *      take care of that here.
822          */
823         if (!fr_hash_table_replace(values_byvalue, dval)) {
824                 fr_strerror_printf("dict_addvalue: Failed inserting value %s",
825                            namestr);
826                 return -1;
827         }
828
829         return 0;
830 }
831
832 static int sscanf_i(const char *str, int *pvalue)
833 {
834         int rcode = 0;
835         int base = 10;
836         const char *tab = "0123456789";
837
838         if ((str[0] == '0') &&
839             ((str[1] == 'x') || (str[1] == 'X'))) {
840                 tab = "0123456789abcdef";
841                 base = 16;
842
843                 str += 2;
844         }
845
846         while (*str) {
847                 const char *c;
848
849                 c = memchr(tab, tolower((int) *str), base);
850                 if (!c) return 0;
851
852                 rcode *= base;
853                 rcode += (c - tab);
854                 str++;
855         }
856
857         *pvalue = rcode;
858         return 1;
859 }
860
861
862 /*
863  *      Process the ATTRIBUTE command
864  */
865 static int process_attribute(const char* fn, const int line,
866                              const int block_vendor, DICT_ATTR *block_tlv,
867                              int tlv_depth, char **argv, int argc)
868 {
869         int             vendor = 0;
870         int             value;
871         int             type;
872         int             length = 0;
873         ATTR_FLAGS      flags;
874
875         if ((argc < 3) || (argc > 4)) {
876                 fr_strerror_printf("dict_init: %s[%d]: invalid ATTRIBUTE line",
877                         fn, line);
878                 return -1;
879         }
880
881         /*
882          *      Validate all entries
883          */
884         if (!sscanf_i(argv[1], &value)) {
885                 fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line);
886                 return -1;
887         }
888
889         if (strncmp(argv[2], "octets[", 7) != 0) {
890                 /*
891                  *      find the type of the attribute.
892                  */
893                 type = fr_str2int(type_table, argv[2], -1);
894                 if (type < 0) {
895                         fr_strerror_printf("dict_init: %s[%d]: invalid type \"%s\"",
896                                            fn, line, argv[2]);
897                         return -1;
898                 }
899         } else {
900                 char *p;
901                 type = PW_TYPE_OCTETS;
902                 
903                 p = strchr(argv[2] + 7, ']');
904                 if (!p) {
905                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for octets", fn, line);
906                         return -1;
907                 }
908
909                 *p = 0;
910
911                 if (!sscanf_i(argv[1], &length)) {
912                         fr_strerror_printf("dict_init: %s[%d]: invalid length", fn, line);
913                         return -1;
914                 }
915
916                 if ((length == 0) || (length > 253)) {
917                         fr_strerror_printf("dict_init: %s[%d]: invalid length", fn, line);
918                         return -1;
919                 }
920         }
921
922         /*
923          *      Only look up the vendor if the string
924          *      is non-empty.
925          */
926         memset(&flags, 0, sizeof(flags));
927         if (argc < 4) {
928                 /*
929                  *      Force "length" for data types of fixed length;
930                  */
931                 switch (type) {
932                 case PW_TYPE_BYTE:
933                         length = 1;
934                         break;
935
936                 case PW_TYPE_SHORT:
937                         length = 2;
938                         break;
939
940                 case PW_TYPE_DATE:
941                 case PW_TYPE_IPADDR:
942                 case PW_TYPE_INTEGER:
943                 case PW_TYPE_SIGNED:
944                         length = 4;
945                         break;
946
947                 case PW_TYPE_ETHERNET:
948                         length = 6;
949                         break;
950
951                 case PW_TYPE_IFID:
952                         length = 8;
953                         break;
954
955                 case PW_TYPE_IPV6ADDR:
956                         length = 16;
957                         break;
958
959                 default:
960                         break;
961                 }
962
963                 flags.length = length;
964
965         } else {                /* argc == 4: we have options */
966                 char *key, *next, *last;
967
968                 if (length != 0) {
969                         fr_strerror_printf("dict_init: %s[%d]: length cannot be used with options", fn, line);
970                         return -1;
971                 }
972
973                 key = argv[3];
974                 do {
975                         next = strchr(key, ',');
976                         if (next) *(next++) = '\0';
977
978                         if (strcmp(key, "has_tag") == 0 ||
979                             strcmp(key, "has_tag=1") == 0) {
980                                 /* Boolean flag, means this is a
981                                    tagged attribute */
982                                 flags.has_tag = 1;
983                                 
984                         } else if (strncmp(key, "encrypt=", 8) == 0) {
985                                 /* Encryption method, defaults to 0 (none).
986                                    Currently valid is just type 2,
987                                    Tunnel-Password style, which can only
988                                    be applied to strings. */
989                                 flags.encrypt = strtol(key + 8, &last, 0);
990                                 if (*last) {
991                                         fr_strerror_printf( "dict_init: %s[%d] invalid option %s",
992                                                     fn, line, key);
993                                         return -1;
994                                 }
995                                 
996                         } else if (strncmp(key, "array", 8) == 0) {
997                                 flags.array = 1;
998                                 
999                                 switch (type) {
1000                                         case PW_TYPE_IPADDR:
1001                                         case PW_TYPE_BYTE:
1002                                         case PW_TYPE_SHORT:
1003                                         case PW_TYPE_INTEGER:
1004                                         case PW_TYPE_DATE:
1005                                                 break;
1006
1007                                         default:
1008                                                 fr_strerror_printf( "dict_init: %s[%d] Only IP addresses can have the \"array\" flag set.",
1009                                                             fn, line);
1010                                                 return -1;
1011                                 }
1012
1013                                 /*
1014                                  *      The only thing is the vendor name,
1015                                  *      and it's a known name: allow it.
1016                                  */
1017                         } else if ((key == argv[3]) && !next && !block_vendor &&
1018                                    ((vendor = dict_vendorbyname(key)) !=0)) {
1019                                 break;
1020
1021                         } else {
1022                                 fr_strerror_printf( "dict_init: %s[%d]: unknown option \"%s\"",
1023                                             fn, line, key);
1024                                 return -1;
1025                         }
1026
1027                         key = next;
1028                         if (key && !*key) break;
1029                 } while (key);
1030         }
1031
1032         if (block_vendor) vendor = block_vendor;
1033
1034         /*
1035          *      Special checks for tags, they make our life much more
1036          *      difficult.
1037          */
1038         if (flags.has_tag) {
1039                 /*
1040                  *      Only string, octets, and integer can be tagged.
1041                  */
1042                 switch (type) {
1043                 case PW_TYPE_STRING:
1044                 case PW_TYPE_INTEGER:
1045                         break;
1046
1047                 default:
1048                         fr_strerror_printf("dict_init: %s[%d]: Attributes of type %s cannot be tagged.",
1049                                    fn, line,
1050                                    fr_int2str(type_table, type, "?Unknown?"));
1051                         return -1;
1052                 }
1053         }
1054
1055         if (type == PW_TYPE_TLV) {
1056                 flags.has_tlv = 1;
1057         }
1058
1059         if (block_tlv) {
1060                 /*
1061                  *      TLV's can be only one octet.
1062                  */
1063           if ((value <= 0) || ((value & ~fr_wimax_mask[tlv_depth]) != 0)) {
1064                         fr_strerror_printf( "dict_init: %s[%d]: sub-tlv has invalid attribute number",
1065                                     fn, line);
1066                         return -1;
1067                 }
1068
1069                 /*
1070                  *      
1071                  */
1072                 value <<= fr_wimax_shift[tlv_depth];
1073                 value |= block_tlv->attr;
1074                 flags.is_tlv = 1;
1075         }
1076
1077
1078         /*
1079          *      Add it in.
1080          */
1081         if (dict_addattr(argv[0], value, vendor, type, flags) < 0) {
1082                 char buffer[256];
1083
1084                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1085
1086                 fr_strerror_printf("dict_init: %s[%d]: %s",
1087                                    fn, line, buffer);
1088                 return -1;
1089         }
1090
1091         return 0;
1092 }
1093
1094
1095 /*
1096  *      Process the VALUE command
1097  */
1098 static int process_value(const char* fn, const int line, char **argv,
1099                          int argc)
1100 {
1101         int     value;
1102
1103         if (argc != 3) {
1104                 fr_strerror_printf("dict_init: %s[%d]: invalid VALUE line",
1105                         fn, line);
1106                 return -1;
1107         }
1108         /*
1109          *      For Compatibility, skip "Server-Config"
1110          */
1111         if (strcasecmp(argv[0], "Server-Config") == 0)
1112                 return 0;
1113
1114         /*
1115          *      Validate all entries
1116          */
1117         if (!sscanf_i(argv[2], &value)) {
1118                 fr_strerror_printf("dict_init: %s[%d]: invalid value",
1119                         fn, line);
1120                 return -1;
1121         }
1122
1123         if (dict_addvalue(argv[1], argv[0], value) < 0) {
1124                 char buffer[256];
1125
1126                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1127
1128                 fr_strerror_printf("dict_init: %s[%d]: %s",
1129                                    fn, line, buffer);
1130                 return -1;
1131         }
1132
1133         return 0;
1134 }
1135
1136
1137 /*
1138  *      Process the VALUE-ALIAS command
1139  *
1140  *      This allows VALUE mappings to be shared among multiple
1141  *      attributes.
1142  */
1143 static int process_value_alias(const char* fn, const int line, char **argv,
1144                                int argc)
1145 {
1146         DICT_ATTR *my_da, *da;
1147         DICT_VALUE *dval;
1148
1149         if (argc != 2) {
1150                 fr_strerror_printf("dict_init: %s[%d]: invalid VALUE-ALIAS line",
1151                         fn, line);
1152                 return -1;
1153         }
1154
1155         my_da = dict_attrbyname(argv[0]);
1156         if (!my_da) {
1157                 fr_strerror_printf("dict_init: %s[%d]: ATTRIBUTE \"%s\" does not exist",
1158                            fn, line, argv[1]);
1159                 return -1;
1160         }
1161
1162         if (my_da->flags.has_value) {
1163                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE",
1164                            fn, line, argv[0]);
1165                 return -1;
1166         }
1167
1168         if (my_da->flags.has_value_alias) {
1169                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE-ALIAS",
1170                            fn, line, argv[0]);
1171                 return -1;
1172         }
1173
1174         da = dict_attrbyname(argv[1]);
1175         if (!da) {
1176                 fr_strerror_printf("dict_init: %s[%d]: Cannot find ATTRIBUTE \"%s\" for alias",
1177                            fn, line, argv[1]);
1178                 return -1;
1179         }
1180
1181         if (!da->flags.has_value) {
1182                 fr_strerror_printf("dict_init: %s[%d]: VALUE-ALIAS cannot refer to ATTRIBUTE %s: It has no values",
1183                            fn, line, argv[1]);
1184                 return -1;
1185         }
1186
1187         if (da->flags.has_value_alias) {
1188                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" which itself has a VALUE-ALIAS",
1189                            fn, line, argv[1]);
1190                 return -1;
1191         }
1192
1193         if (my_da->type != da->type) {
1194                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS between attributes of differing type",
1195                            fn, line);
1196                 return -1;
1197         }
1198
1199         if ((dval = fr_pool_alloc(sizeof(*dval))) == NULL) {
1200                 fr_strerror_printf("dict_addvalue: out of memory");
1201                 return -1;
1202         }
1203
1204         dval->name[0] = '\0';   /* empty name */
1205         dval->attr = my_da->attr;
1206         dval->vendor = my_da->vendor;
1207         dval->value = da->attr;
1208
1209         if (!fr_hash_table_insert(values_byname, dval)) {
1210                 fr_strerror_printf("dict_init: %s[%d]: Error create alias",
1211                            fn, line);
1212                 fr_pool_free(dval);
1213                 return -1;
1214         }
1215
1216         return 0;
1217 }
1218
1219
1220 /*
1221  *      Process the VENDOR command
1222  */
1223 static int process_vendor(const char* fn, const int line, char **argv,
1224                           int argc)
1225 {
1226         int     value;
1227         int     continuation = 0;
1228         const   char *format = NULL;
1229
1230         if ((argc < 2) || (argc > 3)) {
1231                 fr_strerror_printf( "dict_init: %s[%d] invalid VENDOR entry",
1232                             fn, line);
1233                 return -1;
1234         }
1235
1236         /*
1237          *       Validate all entries
1238          */
1239         if (!isdigit((int) argv[1][0])) {
1240                 fr_strerror_printf("dict_init: %s[%d]: invalid value",
1241                         fn, line);
1242                 return -1;
1243         }
1244         value = atoi(argv[1]);
1245
1246         /* Create a new VENDOR entry for the list */
1247         if (dict_addvendor(argv[0], value) < 0) {
1248                 char buffer[256];
1249
1250                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1251
1252                 fr_strerror_printf("dict_init: %s[%d]: %s",
1253                            fn, line, buffer);
1254                 return -1;
1255         }
1256
1257         /*
1258          *      Look for a format statement
1259          */
1260         if (argc == 3) {
1261                 format = argv[2];
1262
1263         } else if (value == VENDORPEC_USR) { /* catch dictionary screw-ups */
1264                 format = "format=4,0";
1265
1266         } else if (value == VENDORPEC_LUCENT) {
1267                 format = "format=2,1";
1268
1269         } else if (value == VENDORPEC_STARENT) {
1270                 format = "format=2,2";
1271
1272         } /* else no fixups to do */
1273
1274         if (format) {
1275                 int type, length;
1276                 const char *p;
1277                 DICT_VENDOR *dv;
1278
1279                 if (strncasecmp(format, "format=", 7) != 0) {
1280                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected \"format=\", got \"%s\"",
1281                                    fn, line, format);
1282                         return -1;
1283                 }
1284
1285                 p = format + 7;
1286                 if ((strlen(p) < 3) ||
1287                     !isdigit((int) p[0]) ||
1288                     (p[1] != ',') ||
1289                     !isdigit((int) p[2]) ||
1290                     (p[3] && (p[3] != ','))) {
1291                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected text like \"1,1\", got \"%s\"",
1292                                    fn, line, p);
1293                         return -1;
1294                 }
1295
1296                 type = (int) (p[0] - '0');
1297                 length = (int) (p[2] - '0');
1298
1299                 if (p[3] == ',') {
1300                         if ((p[4] != 'c') ||
1301                             (p[5] != '\0')) {
1302                                 fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected text like \"1,1\", got \"%s\"",
1303                                            fn, line, p);
1304                                 return -1;
1305                         }
1306                         continuation = 1;
1307
1308                         if ((value != VENDORPEC_WIMAX) ||
1309                             (type != 1) || (length != 1)) {
1310                                 fr_strerror_printf("dict_init: %s[%d]: Only WiMAX VSAs can have continuations",
1311                                            fn, line);
1312                                 return -1;
1313                         }
1314                 }
1315
1316                 dv = dict_vendorbyvalue(value);
1317                 if (!dv) {
1318                         fr_strerror_printf("dict_init: %s[%d]: Failed adding format for VENDOR",
1319                                    fn, line);
1320                         return -1;
1321                 }
1322
1323                 if ((type != 1) && (type != 2) && (type != 4)) {
1324                         fr_strerror_printf("dict_init: %s[%d]: invalid type value %d for VENDOR",
1325                                    fn, line, type);
1326                         return -1;
1327                 }
1328
1329                 if ((length != 0) && (length != 1) && (length != 2)) {
1330                         fr_strerror_printf("dict_init: %s[%d]: invalid length value %d for VENDOR",
1331                                    fn, line, length);
1332                         return -1;
1333                 }
1334
1335                 dv->type = type;
1336                 dv->length = length;
1337                 dv->flags = continuation;
1338         }
1339
1340         return 0;
1341 }
1342
1343 /*
1344  *      String split routine.  Splits an input string IN PLACE
1345  *      into pieces, based on spaces.
1346  */
1347 static int str2argv(char *str, char **argv, int max_argc)
1348 {
1349         int argc = 0;
1350
1351         while (*str) {
1352                 if (argc >= max_argc) break;
1353
1354                 /*
1355                  *      Chop out comments early.
1356                  */
1357                 if (*str == '#') {
1358                         *str = '\0';
1359                         break;
1360                 }
1361
1362                 while ((*str == ' ') ||
1363                        (*str == '\t') ||
1364                        (*str == '\r') ||
1365                        (*str == '\n')) *(str++) = '\0';
1366
1367                 if (!*str) break;
1368
1369                 argv[argc] = str;
1370                 argc++;
1371
1372                 while (*str &&
1373                        (*str != ' ') &&
1374                        (*str != '\t') &&
1375                        (*str != '\r') &&
1376                        (*str != '\n')) str++;
1377         }
1378
1379         return argc;
1380 }
1381
1382 #define MAX_ARGV (16)
1383
1384 /*
1385  *      Initialize the dictionary.
1386  */
1387 static int my_dict_init(const char *dir, const char *fn,
1388                         const char *src_file, int src_line)
1389 {
1390         FILE    *fp;
1391         char    dirtmp[256];
1392         char    buf[256];
1393         char    *p;
1394         int     line = 0;
1395         int     vendor;
1396         int     block_vendor;
1397         struct stat statbuf;
1398         char    *argv[MAX_ARGV];
1399         int     argc;
1400         DICT_ATTR *da, *block_tlv[MAX_TLV_NEST + 1];
1401         int     which_block_tlv = 0;
1402
1403         block_tlv[0] = NULL;
1404         block_tlv[1] = NULL;
1405         block_tlv[2] = NULL;
1406
1407         if (strlen(fn) >= sizeof(dirtmp) / 2 ||
1408             strlen(dir) >= sizeof(dirtmp) / 2) {
1409                 fr_strerror_printf("dict_init: filename name too long");
1410                 return -1;
1411         }
1412
1413         /*
1414          *      First see if fn is relative to dir. If so, create
1415          *      new filename. If not, remember the absolute dir.
1416          */
1417         if ((p = strrchr(fn, FR_DIR_SEP)) != NULL) {
1418                 strcpy(dirtmp, fn);
1419                 dirtmp[p - fn] = 0;
1420                 dir = dirtmp;
1421         } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
1422                 snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn);
1423                 fn = dirtmp;
1424         }
1425
1426         if ((fp = fopen(fn, "r")) == NULL) {
1427                 if (!src_file) {
1428                         fr_strerror_printf("dict_init: Couldn't open dictionary \"%s\": %s",
1429                                    fn, strerror(errno));
1430                 } else {
1431                         fr_strerror_printf("dict_init: %s[%d]: Couldn't open dictionary \"%s\": %s",
1432                                    src_file, src_line, fn, strerror(errno));
1433                 }
1434                 return -1;
1435         }
1436
1437         stat(fn, &statbuf); /* fopen() guarantees this will succeed */
1438         if (!S_ISREG(statbuf.st_mode)) {
1439                 fclose(fp);
1440                 fr_strerror_printf("dict_init: Dictionary \"%s\" is not a regular file",
1441                            fn);
1442                 return -1;
1443         }
1444
1445         /*
1446          *      Globally writable dictionaries means that users can control
1447          *      the server configuration with little difficulty.
1448          */
1449 #ifdef S_IWOTH
1450         if ((statbuf.st_mode & S_IWOTH) != 0) {
1451                 fclose(fp);
1452                 fr_strerror_printf("dict_init: Dictionary \"%s\" is globally writable.  Refusing to start due to insecure configuration.",
1453                            fn);
1454                 return -1;
1455         }
1456 #endif
1457
1458         dict_stat_add(fn, &statbuf);
1459
1460         /*
1461          *      Seed the random pool with data.
1462          */
1463         fr_rand_seed(&statbuf, sizeof(statbuf));
1464
1465         block_vendor = 0;
1466
1467         while (fgets(buf, sizeof(buf), fp) != NULL) {
1468                 line++;
1469                 if (buf[0] == '#' || buf[0] == 0 ||
1470                     buf[0] == '\n' || buf[0] == '\r')
1471                         continue;
1472
1473                 /*
1474                  *  Comment characters should NOT be appearing anywhere but
1475                  *  as start of a comment;
1476                  */
1477                 p = strchr(buf, '#');
1478                 if (p) *p = '\0';
1479
1480                 argc = str2argv(buf, argv, MAX_ARGV);
1481                 if (argc == 0) continue;
1482
1483                 if (argc == 1) {
1484                         fr_strerror_printf( "dict_init: %s[%d] invalid entry",
1485                                     fn, line);
1486                         fclose(fp);
1487                         return -1;
1488                 }
1489
1490                 /*
1491                  *      Process VALUE lines.
1492                  */
1493                 if (strcasecmp(argv[0], "VALUE") == 0) {
1494                         if (process_value(fn, line,
1495                                           argv + 1, argc - 1) == -1) {
1496                                 fclose(fp);
1497                                 return -1;
1498                         }
1499                         continue;
1500                 }
1501
1502                 /*
1503                  *      Perhaps this is an attribute.
1504                  */
1505                 if (strcasecmp(argv[0], "ATTRIBUTE") == 0) {
1506                         if (process_attribute(fn, line, block_vendor,
1507                                               block_tlv[which_block_tlv],
1508                                               which_block_tlv,
1509                                               argv + 1, argc - 1) == -1) {
1510                                 fclose(fp);
1511                                 return -1;
1512                         }
1513                         continue;
1514                 }
1515
1516                 /*
1517                  *      See if we need to import another dictionary.
1518                  */
1519                 if (strcasecmp(argv[0], "$INCLUDE") == 0) {
1520                         if (my_dict_init(dir, argv[1], fn, line) < 0) {
1521                                 fclose(fp);
1522                                 return -1;
1523                         }
1524                         continue;
1525                 } /* $INCLUDE */
1526
1527                 if (strcasecmp(argv[0], "VALUE-ALIAS") == 0) {
1528                         if (process_value_alias(fn, line,
1529                                                 argv + 1, argc - 1) == -1) {
1530                                 fclose(fp);
1531                                 return -1;
1532                         }
1533                         continue;
1534                 }
1535
1536                 /*
1537                  *      Process VENDOR lines.
1538                  */
1539                 if (strcasecmp(argv[0], "VENDOR") == 0) {
1540                         if (process_vendor(fn, line,
1541                                            argv + 1, argc - 1) == -1) {
1542                                 fclose(fp);
1543                                 return -1;
1544                         }
1545                         continue;
1546                 }
1547
1548                 if (strcasecmp(argv[0], "BEGIN-TLV") == 0) {
1549                         if (argc != 2) {
1550                                 fr_strerror_printf(
1551                                 "dict_init: %s[%d] invalid BEGIN-TLV entry",
1552                                         fn, line);
1553                                 fclose(fp);
1554                                 return -1;
1555                         }
1556
1557                         da = dict_attrbyname(argv[1]);
1558                         if (!da) {
1559                                 fr_strerror_printf(
1560                                         "dict_init: %s[%d]: unknown attribute %s",
1561                                         fn, line, argv[1]);
1562                                 fclose(fp);
1563                                 return -1;
1564                         }
1565
1566                         if (da->type != PW_TYPE_TLV) {
1567                                 fr_strerror_printf(
1568                                         "dict_init: %s[%d]: attribute %s is not of type tlv",
1569                                         fn, line, argv[1]);
1570                                 fclose(fp);
1571                                 return -1;
1572                         }
1573
1574                         if (which_block_tlv >= MAX_TLV_NEST) {
1575                                 fr_strerror_printf(
1576                                         "dict_init: %s[%d]: TLVs are nested too deep",
1577                                         fn, line);
1578                                 fclose(fp);
1579                                 return -1;
1580                         }
1581
1582
1583                         block_tlv[++which_block_tlv] = da;
1584                         continue;
1585                 } /* BEGIN-TLV */
1586
1587                 if (strcasecmp(argv[0], "END-TLV") == 0) {
1588                         if (argc != 2) {
1589                                 fr_strerror_printf(
1590                                 "dict_init: %s[%d] invalid END-TLV entry",
1591                                         fn, line);
1592                                 fclose(fp);
1593                                 return -1;
1594                         }
1595
1596                         da = dict_attrbyname(argv[1]);
1597                         if (!da) {
1598                                 fr_strerror_printf(
1599                                         "dict_init: %s[%d]: unknown attribute %s",
1600                                         fn, line, argv[1]);
1601                                 fclose(fp);
1602                                 return -1;
1603                         }
1604
1605                         if (da != block_tlv[which_block_tlv]) {
1606                                 fr_strerror_printf(
1607                                         "dict_init: %s[%d]: END-TLV %s does not match any previous BEGIN-TLV",
1608                                         fn, line, argv[1]);
1609                                 fclose(fp);
1610                                 return -1;
1611                         }
1612                         block_tlv[which_block_tlv--] = NULL;
1613                         continue;
1614                 } /* END-VENDOR */
1615
1616                 if (strcasecmp(argv[0], "BEGIN-VENDOR") == 0) {
1617                         if (argc != 2) {
1618                                 fr_strerror_printf(
1619                                 "dict_init: %s[%d] invalid BEGIN-VENDOR entry",
1620                                         fn, line);
1621                                 fclose(fp);
1622                                 return -1;
1623                         }
1624
1625                         vendor = dict_vendorbyname(argv[1]);
1626                         if (!vendor) {
1627                                 fr_strerror_printf(
1628                                         "dict_init: %s[%d]: unknown vendor %s",
1629                                         fn, line, argv[1]);
1630                                 fclose(fp);
1631                                 return -1;
1632                         }
1633                         block_vendor = vendor;
1634                         continue;
1635                 } /* BEGIN-VENDOR */
1636
1637                 if (strcasecmp(argv[0], "END-VENDOR") == 0) {
1638                         if (argc != 2) {
1639                                 fr_strerror_printf(
1640                                 "dict_init: %s[%d] invalid END-VENDOR entry",
1641                                         fn, line);
1642                                 fclose(fp);
1643                                 return -1;
1644                         }
1645
1646                         vendor = dict_vendorbyname(argv[1]);
1647                         if (!vendor) {
1648                                 fr_strerror_printf(
1649                                         "dict_init: %s[%d]: unknown vendor %s",
1650                                         fn, line, argv[1]);
1651                                 fclose(fp);
1652                                 return -1;
1653                         }
1654
1655                         if (vendor != block_vendor) {
1656                                 fr_strerror_printf(
1657                                         "dict_init: %s[%d]: END-VENDOR %s does not match any previous BEGIN-VENDOR",
1658                                         fn, line, argv[1]);
1659                                 fclose(fp);
1660                                 return -1;
1661                         }
1662                         block_vendor = 0;
1663                         continue;
1664                 } /* END-VENDOR */
1665
1666                 /*
1667                  *      Any other string: We don't recognize it.
1668                  */
1669                 fr_strerror_printf("dict_init: %s[%d] invalid keyword \"%s\"",
1670                            fn, line, argv[0]);
1671                 fclose(fp);
1672                 return -1;
1673         }
1674         fclose(fp);
1675         return 0;
1676 }
1677
1678
1679 /*
1680  *      Empty callback for hash table initialization.
1681  */
1682 static int null_callback(void *ctx, void *data)
1683 {
1684         ctx = ctx;              /* -Wunused */
1685         data = data;            /* -Wunused */
1686
1687         return 0;
1688 }
1689
1690
1691 /*
1692  *      Initialize the directory, then fix the attr member of
1693  *      all attributes.
1694  */
1695 int dict_init(const char *dir, const char *fn)
1696 {
1697         /*
1698          *      Check if we need to change anything.  If not, don't do
1699          *      anything.
1700          */
1701         if (dict_stat_check(dir, fn)) {
1702                 return 0;
1703         }
1704
1705         /*
1706          *      Free the dictionaries, and the stat cache.
1707          */
1708         dict_free();
1709         stat_root_dir = strdup(dir);
1710         stat_root_file = strdup(fn);
1711
1712         /*
1713          *      Create the table of vendor by name.   There MAY NOT
1714          *      be multiple vendors of the same name.
1715          *
1716          *      Each vendor is malloc'd, so the free function is free.
1717          */
1718         vendors_byname = fr_hash_table_create(dict_vendor_name_hash,
1719                                                 dict_vendor_name_cmp,
1720                                                 fr_pool_free);
1721         if (!vendors_byname) {
1722                 return -1;
1723         }
1724
1725         /*
1726          *      Create the table of vendors by value.  There MAY
1727          *      be vendors of the same value.  If there are, we
1728          *      pick the latest one.
1729          */
1730         vendors_byvalue = fr_hash_table_create(dict_vendor_value_hash,
1731                                                  dict_vendor_value_cmp,
1732                                                  fr_pool_free);
1733         if (!vendors_byvalue) {
1734                 return -1;
1735         }
1736
1737         /*
1738          *      Create the table of attributes by name.   There MAY NOT
1739          *      be multiple attributes of the same name.
1740          *
1741          *      Each attribute is malloc'd, so the free function is free.
1742          */
1743         attributes_byname = fr_hash_table_create(dict_attr_name_hash,
1744                                                    dict_attr_name_cmp,
1745                                                    fr_pool_free);
1746         if (!attributes_byname) {
1747                 return -1;
1748         }
1749
1750         /*
1751          *      Create the table of attributes by value.  There MAY
1752          *      be attributes of the same value.  If there are, we
1753          *      pick the latest one.
1754          */
1755         attributes_byvalue = fr_hash_table_create(dict_attr_value_hash,
1756                                                     dict_attr_value_cmp,
1757                                                     fr_pool_free);
1758         if (!attributes_byvalue) {
1759                 return -1;
1760         }
1761
1762         values_byname = fr_hash_table_create(dict_value_name_hash,
1763                                                dict_value_name_cmp,
1764                                                fr_pool_free);
1765         if (!values_byname) {
1766                 return -1;
1767         }
1768
1769         values_byvalue = fr_hash_table_create(dict_value_value_hash,
1770                                                 dict_value_value_cmp,
1771                                                 fr_pool_free);
1772         if (!values_byvalue) {
1773                 return -1;
1774         }
1775
1776         value_fixup = NULL;     /* just to be safe. */
1777
1778         if (my_dict_init(dir, fn, NULL, 0) < 0)
1779                 return -1;
1780
1781         if (value_fixup) {
1782                 DICT_ATTR *a;
1783                 value_fixup_t *this, *next;
1784
1785                 for (this = value_fixup; this != NULL; this = next) {
1786                         next = this->next;
1787
1788                         a = dict_attrbyname(this->attrstr);
1789                         if (!a) {
1790                                 fr_strerror_printf(
1791                                         "dict_init: No ATTRIBUTE \"%s\" defined for VALUE \"%s\"",
1792                                         this->attrstr, this->dval->name);
1793                                 return -1; /* leak, but they should die... */
1794                         }
1795
1796                         this->dval->attr = a->attr;
1797
1798                         /*
1799                          *      Add the value into the dictionary.
1800                          */
1801                         if (!fr_hash_table_replace(values_byname,
1802                                                      this->dval)) {
1803                                 fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", this->dval->name, a->name);
1804                                 return -1;
1805                         }
1806
1807                         /*
1808                          *      Allow them to use the old name, but
1809                          *      prefer the new name when printing
1810                          *      values.
1811                          */
1812                         if (!fr_hash_table_finddata(values_byvalue, this->dval)) {
1813                                 fr_hash_table_replace(values_byvalue,
1814                                                         this->dval);
1815                         }
1816                         free(this);
1817
1818                         /*
1819                          *      Just so we don't lose track of things.
1820                          */
1821                         value_fixup = next;
1822                 }
1823         }
1824
1825         /*
1826          *      Walk over all of the hash tables to ensure they're
1827          *      initialized.  We do this because the threads may perform
1828          *      lookups, and we don't want multi-threaded re-ordering
1829          *      of the table entries.  That would be bad.
1830          */
1831         fr_hash_table_walk(vendors_byname, null_callback, NULL);
1832         fr_hash_table_walk(vendors_byvalue, null_callback, NULL);
1833
1834         fr_hash_table_walk(attributes_byname, null_callback, NULL);
1835         fr_hash_table_walk(attributes_byvalue, null_callback, NULL);
1836
1837         fr_hash_table_walk(values_byvalue, null_callback, NULL);
1838         fr_hash_table_walk(values_byname, null_callback, NULL);
1839
1840         return 0;
1841 }
1842
1843 /*
1844  *      Get an attribute by its numerical value.
1845  */
1846 DICT_ATTR *dict_attrbyvalue(unsigned int attr, unsigned int vendor)
1847 {
1848         DICT_ATTR dattr;
1849
1850         if ((attr > 0) && (attr < 256) && !vendor) return dict_base_attrs[attr];
1851
1852         dattr.attr = attr;
1853         dattr.vendor = vendor;
1854
1855         return fr_hash_table_finddata(attributes_byvalue, &dattr);
1856 }
1857
1858 /*
1859  *      Get an attribute by its name.
1860  */
1861 DICT_ATTR *dict_attrbyname(const char *name)
1862 {
1863         DICT_ATTR *da;
1864         uint32_t buffer[(sizeof(*da) + DICT_ATTR_MAX_NAME_LEN + 3)/4];
1865
1866         if (!name) return NULL;
1867
1868         da = (DICT_ATTR *) buffer;
1869         strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1);
1870
1871         return fr_hash_table_finddata(attributes_byname, da);
1872 }
1873
1874 /*
1875  *      Associate a value with an attribute and return it.
1876  */
1877 DICT_VALUE *dict_valbyattr(unsigned int attr, unsigned int vendor, int value)
1878 {
1879         DICT_VALUE dval, *dv;
1880
1881         /*
1882          *      First, look up aliases.
1883          */
1884         dval.attr = attr;
1885         dval.vendor = vendor;
1886         dval.name[0] = '\0';
1887
1888         /*
1889          *      Look up the attribute alias target, and use
1890          *      the correct attribute number if found.
1891          */
1892         dv = fr_hash_table_finddata(values_byname, &dval);
1893         if (dv) dval.attr = dv->value;
1894
1895         dval.value = value;
1896
1897         return fr_hash_table_finddata(values_byvalue, &dval);
1898 }
1899
1900 /*
1901  *      Get a value by its name, keyed off of an attribute.
1902  */
1903 DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, const char *name)
1904 {
1905         DICT_VALUE *my_dv, *dv;
1906         uint32_t buffer[(sizeof(*my_dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4];
1907
1908         if (!name) return NULL;
1909
1910         my_dv = (DICT_VALUE *) buffer;
1911         my_dv->attr = attr;
1912         my_dv->vendor = vendor;
1913         my_dv->name[0] = '\0';
1914
1915         /*
1916          *      Look up the attribute alias target, and use
1917          *      the correct attribute number if found.
1918          */
1919         dv = fr_hash_table_finddata(values_byname, my_dv);
1920         if (dv) my_dv->attr = dv->value;
1921
1922         strlcpy(my_dv->name, name, DICT_VALUE_MAX_NAME_LEN + 1);
1923
1924         return fr_hash_table_finddata(values_byname, my_dv);
1925 }
1926
1927 /*
1928  *      Get the vendor PEC based on the vendor name
1929  *
1930  *      This is efficient only for small numbers of vendors.
1931  */
1932 int dict_vendorbyname(const char *name)
1933 {
1934         DICT_VENDOR *dv;
1935         uint32_t buffer[(sizeof(*dv) + DICT_VENDOR_MAX_NAME_LEN + 3)/4];
1936
1937         if (!name) return 0;
1938
1939         dv = (DICT_VENDOR *) buffer;
1940         strlcpy(dv->name, name, DICT_VENDOR_MAX_NAME_LEN + 1);
1941
1942         dv = fr_hash_table_finddata(vendors_byname, dv);
1943         if (!dv) return 0;
1944
1945         return dv->vendorpec;
1946 }
1947
1948 /*
1949  *      Return the vendor struct based on the PEC.
1950  */
1951 DICT_VENDOR *dict_vendorbyvalue(int vendorpec)
1952 {
1953         DICT_VENDOR dv;
1954
1955         dv.vendorpec = vendorpec;
1956
1957         return fr_hash_table_finddata(vendors_byvalue, &dv);
1958 }