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