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