better implementation of dict_parent
[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 RCSID("$Id$")
23
24 #include        <freeradius-devel/libradius.h>
25
26 #ifdef WITH_DHCP
27 #include        <freeradius-devel/dhcp.h>
28 #endif
29
30 #include        <ctype.h>
31
32 #ifdef HAVE_MALLOC_H
33 #include        <malloc.h>
34 #endif
35
36 #ifdef HAVE_SYS_STAT_H
37 #include        <sys/stat.h>
38 #endif
39
40 static fr_hash_table_t *vendors_byname = NULL;
41 static fr_hash_table_t *vendors_byvalue = NULL;
42
43 static fr_hash_table_t *attributes_byname = NULL;
44 static fr_hash_table_t *attributes_byvalue = NULL;
45
46 static fr_hash_table_t *attributes_combo = 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         struct stat stat_buf;
60 } dict_stat_t;
61
62 static dict_stat_t *stat_head = NULL;
63 static dict_stat_t *stat_tail = NULL;
64
65 typedef struct value_fixup_t {
66         char            attrstr[DICT_ATTR_MAX_NAME_LEN];
67         DICT_VALUE      *dval;
68         struct value_fixup_t *next;
69 } value_fixup_t;
70
71
72 /*
73  *      So VALUEs in the dictionary can have forward references.
74  */
75 static value_fixup_t *value_fixup = NULL;
76
77 const FR_NAME_NUMBER dict_attr_types[] = {
78         { "integer",    PW_TYPE_INTEGER },
79         { "string",     PW_TYPE_STRING },
80         { "ipaddr",     PW_TYPE_IPV4_ADDR },
81         { "date",       PW_TYPE_DATE },
82         { "abinary",    PW_TYPE_ABINARY },
83         { "octets",     PW_TYPE_OCTETS },
84         { "ifid",       PW_TYPE_IFID },
85         { "ipv6addr",   PW_TYPE_IPV6_ADDR },
86         { "ipv6prefix", PW_TYPE_IPV6_PREFIX },
87         { "byte",       PW_TYPE_BYTE },
88         { "short",      PW_TYPE_SHORT },
89         { "ether",      PW_TYPE_ETHERNET },
90         { "combo-ip",   PW_TYPE_COMBO_IP_ADDR },
91         { "tlv",        PW_TYPE_TLV },
92         { "signed",     PW_TYPE_SIGNED },
93         { "extended",   PW_TYPE_EXTENDED },
94         { "long-extended",      PW_TYPE_LONG_EXTENDED },
95         { "evs",        PW_TYPE_EVS },
96         { "uint8",      PW_TYPE_BYTE },
97         { "uint16",     PW_TYPE_SHORT },
98         { "uint32",     PW_TYPE_INTEGER },
99         { "int32",      PW_TYPE_SIGNED },
100         { "integer64",  PW_TYPE_INTEGER64 },
101         { "uint64",     PW_TYPE_INTEGER64 },
102         { "ipv4prefix", PW_TYPE_IPV4_PREFIX },
103         { "cidr",       PW_TYPE_IPV4_PREFIX },
104         { "vsa",        PW_TYPE_VSA },
105         { NULL, 0 }
106 };
107
108 /*
109  *      Map data types to min / max data sizes.
110  */
111 const size_t dict_attr_sizes[PW_TYPE_MAX][2] = {
112         [PW_TYPE_INVALID]       = {~0, 0},
113         [PW_TYPE_STRING]        = {0, ~0},
114         [PW_TYPE_INTEGER]       = {4, 4 },
115         [PW_TYPE_IPV4_ADDR]     = {4, 4},
116         [PW_TYPE_DATE]          = {4, 4},
117         [PW_TYPE_ABINARY]       = {32, ~0},
118         [PW_TYPE_OCTETS]        = {0, ~0},
119         [PW_TYPE_IFID]          = {8, 8},
120         [PW_TYPE_IPV6_ADDR]     = {16, 16},
121         [PW_TYPE_IPV6_PREFIX]   = {2, 18},
122         [PW_TYPE_BYTE]          = {1, 1},
123         [PW_TYPE_SHORT]         = {2, 2},
124         [PW_TYPE_ETHERNET]      = {6, 6},
125         [PW_TYPE_SIGNED]        = {4, 4},
126         [PW_TYPE_COMBO_IP_ADDR] = {4, 16},
127         [PW_TYPE_TLV]           = {2, ~0},
128         [PW_TYPE_EXTENDED]      = {2, ~0},
129         [PW_TYPE_LONG_EXTENDED] = {3, ~0},
130         [PW_TYPE_EVS]           = {6, ~0},
131         [PW_TYPE_INTEGER64]     = {8, 8},
132         [PW_TYPE_IPV4_PREFIX]   = {6, 6},
133         [PW_TYPE_VSA]           = {4, ~0}
134 };
135
136 /*
137  *      For packing multiple TLV numbers into one 32-bit integer.  The
138  *      first 3 bytes are just the 8-bit number.  The next two are
139  *      more limited.  We only allow 31 attributes nested 3 layers
140  *      deep, and only 7 nested 4 layers deep.  This should be
141  *      sufficient for most purposes.
142  *
143  *      For TLVs and extended attributes, we packet the base attribute
144  *      number into the upper 8 bits of the "vendor" field.
145  *
146  *      e.g.    OID             attribute       vendor
147  *              241.1           1               (241 << 24)
148  *              241.26.9.1      1               (241 << 24) | (9)
149  *              241.1.2         1 | (2 << 8)    (241 << 24)
150  */
151 #define MAX_TLV_NEST (4)
152 /*
153  *      Bit packing:
154  *      8 bits of base attribute
155  *      8 bits for nested TLV 1
156  *      8 bits for nested TLV 2
157  *      5 bits for nested TLV 3
158  *      3 bits for nested TLV 4
159  */
160 int const fr_attr_max_tlv = MAX_TLV_NEST;
161 int const fr_attr_shift[MAX_TLV_NEST + 1] = { 0, 8, 16, 24, 29 };
162
163 int const fr_attr_mask[MAX_TLV_NEST + 1] = { 0xff, 0xff, 0xff, 0x1f, 0x07 };
164
165 /*
166  *      attr & fr_attr_parent_mask[i] == Nth parent of attr
167  */
168 static unsigned int const fr_attr_parent_mask[MAX_TLV_NEST + 1] = { 0, 0x000000ff, 0x0000ffff, 0x00ffffff, 0x1fffffff };
169
170 /*
171  *      Create the hash of the name.
172  *
173  *      We copy the hash function here because it's substantially faster.
174  */
175 #define FNV_MAGIC_INIT (0x811c9dc5)
176 #define FNV_MAGIC_PRIME (0x01000193)
177
178 static uint32_t dict_hashname(char const *name)
179 {
180         uint32_t hash = FNV_MAGIC_INIT;
181         char const *p;
182
183         for (p = name; *p != '\0'; p++) {
184                 int c = *(unsigned char const *) p;
185                 if (isalpha(c)) c = tolower(c);
186
187                 hash *= FNV_MAGIC_PRIME;
188                 hash ^= (uint32_t ) (c & 0xff);
189         }
190
191         return hash;
192 }
193
194
195 /*
196  *      Hash callback functions.
197  */
198 static uint32_t dict_attr_name_hash(void const *data)
199 {
200         return dict_hashname(((DICT_ATTR const *)data)->name);
201 }
202
203 static int dict_attr_name_cmp(void const *one, void const *two)
204 {
205         DICT_ATTR const *a = one;
206         DICT_ATTR const *b = two;
207
208         return strcasecmp(a->name, b->name);
209 }
210
211 static uint32_t dict_attr_value_hash(void const *data)
212 {
213         uint32_t hash;
214         DICT_ATTR const *attr = data;
215
216         hash = fr_hash(&attr->vendor, sizeof(attr->vendor));
217         return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);
218 }
219
220 static int dict_attr_value_cmp(void const *one, void const *two)
221 {
222         DICT_ATTR const *a = one;
223         DICT_ATTR const *b = two;
224
225         if (a->vendor < b->vendor) return -1;
226         if (a->vendor > b->vendor) return +1;
227
228         return a->attr - b->attr;
229 }
230
231 static uint32_t dict_attr_combo_hash(void const *data)
232 {
233         uint32_t hash;
234         DICT_ATTR const *attr = data;
235
236         hash = fr_hash(&attr->vendor, sizeof(attr->vendor));
237         hash = fr_hash_update(&attr->type, sizeof(attr->type), hash);
238         return fr_hash_update(&attr->attr, sizeof(attr->attr), hash);
239 }
240
241 static int dict_attr_combo_cmp(void const *one, void const *two)
242 {
243         DICT_ATTR const *a = one;
244         DICT_ATTR const *b = two;
245
246         if (a->type < b->type) return -1;
247         if (a->type > b->type) return +1;
248
249         if (a->vendor < b->vendor) return -1;
250         if (a->vendor > b->vendor) return +1;
251
252         return a->attr - b->attr;
253 }
254
255 static uint32_t dict_vendor_name_hash(void const *data)
256 {
257         return dict_hashname(((DICT_VENDOR const *)data)->name);
258 }
259
260 static int dict_vendor_name_cmp(void const *one, void const *two)
261 {
262         DICT_VENDOR const *a = one;
263         DICT_VENDOR const *b = two;
264
265         return strcasecmp(a->name, b->name);
266 }
267
268 static uint32_t dict_vendor_value_hash(void const *data)
269 {
270         return fr_hash(&(((DICT_VENDOR const *)data)->vendorpec),
271                          sizeof(((DICT_VENDOR const *)data)->vendorpec));
272 }
273
274 static int dict_vendor_value_cmp(void const *one, void const *two)
275 {
276         DICT_VENDOR const *a = one;
277         DICT_VENDOR const *b = two;
278
279         return a->vendorpec - b->vendorpec;
280 }
281
282 static uint32_t dict_value_name_hash(void const *data)
283 {
284         uint32_t hash;
285         DICT_VALUE const *dval = data;
286
287         hash = dict_hashname(dval->name);
288         hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
289         return fr_hash_update(&dval->attr, sizeof(dval->attr), hash);
290 }
291
292 static int dict_value_name_cmp(void const *one, void const *two)
293 {
294         int rcode;
295         DICT_VALUE const *a = one;
296         DICT_VALUE const *b = two;
297
298         rcode = a->attr - b->attr;
299         if (rcode != 0) return rcode;
300
301         rcode = a->vendor - b->vendor;
302         if (rcode != 0) return rcode;
303
304         return strcasecmp(a->name, b->name);
305 }
306
307 static uint32_t dict_value_value_hash(void const *data)
308 {
309         uint32_t hash;
310         DICT_VALUE const *dval = data;
311
312         hash = fr_hash(&dval->attr, sizeof(dval->attr));
313         hash = fr_hash_update(&dval->vendor, sizeof(dval->vendor), hash);
314         return fr_hash_update(&dval->value, sizeof(dval->value), hash);
315 }
316
317 static int dict_value_value_cmp(void const *one, void const *two)
318 {
319         int rcode;
320         DICT_VALUE const *a = one;
321         DICT_VALUE const *b = two;
322
323         if (a->vendor < b->vendor) return -1;
324         if (a->vendor > b->vendor) return +1;
325
326         rcode = a->attr - b->attr;
327         if (rcode != 0) return rcode;
328
329         return a->value - b->value;
330 }
331
332
333 /*
334  *      Free the list of stat buffers
335  */
336 static void dict_stat_free(void)
337 {
338         dict_stat_t *this, *next;
339
340         if (!stat_head) {
341                 stat_tail = NULL;
342                 return;
343         }
344
345         for (this = stat_head; this != NULL; this = next) {
346                 next = this->next;
347                 free(this);
348         }
349
350         stat_head = stat_tail = NULL;
351 }
352
353
354 /*
355  *      Add an entry to the list of stat buffers.
356  */
357 static void dict_stat_add(struct stat const *stat_buf)
358 {
359         dict_stat_t *this;
360
361         this = malloc(sizeof(*this));
362         if (!this) return;
363         memset(this, 0, sizeof(*this));
364
365         memcpy(&(this->stat_buf), stat_buf, sizeof(this->stat_buf));
366
367         if (!stat_head) {
368                 stat_head = stat_tail = this;
369         } else {
370                 stat_tail->next = this;
371                 stat_tail = this;
372         }
373 }
374
375
376 /*
377  *      See if any dictionaries have changed.  If not, don't
378  *      do anything.
379  */
380 static int dict_stat_check(char const *dir, char const *file)
381 {
382         struct stat stat_buf;
383         dict_stat_t *this;
384         char buffer[2048];
385
386         /*
387          *      Nothing cached, all files are new.
388          */
389         if (!stat_head) return 0;
390
391         /*
392          *      Stat the file.
393          */
394         snprintf(buffer, sizeof(buffer), "%s/%s", dir, file);
395         if (stat(buffer, &stat_buf) < 0) return 0;
396
397         /*
398          *      Find the cache entry.
399          *      FIXME: use a hash table.
400          *      FIXME: check dependencies, via children.
401          *             if A loads B and B changes, we probably want
402          *             to reload B at the minimum.
403          */
404         for (this = stat_head; this != NULL; this = this->next) {
405                 if (this->stat_buf.st_dev != stat_buf.st_dev) continue;
406                 if (this->stat_buf.st_ino != stat_buf.st_ino) continue;
407
408                 /*
409                  *      The file has changed.  Re-read it.
410                  */
411                 if (this->stat_buf.st_mtime < stat_buf.st_mtime) return 0;
412
413                 /*
414                  *      The file is the same.  Ignore it.
415                  */
416                 return 1;
417         }
418
419         /*
420          *      Not in the cache.
421          */
422         return 0;
423 }
424
425 typedef struct fr_pool_t {
426         void    *page_end;
427         void    *free_ptr;
428         struct fr_pool_t *page_free;
429         struct fr_pool_t *page_next;
430 } fr_pool_t;
431
432 #define FR_POOL_SIZE (32768)
433 #define FR_ALLOC_ALIGN (8)
434
435 static fr_pool_t *dict_pool = NULL;
436
437 static fr_pool_t *fr_pool_create(void)
438 {
439         fr_pool_t *fp = malloc(FR_POOL_SIZE);
440
441         if (!fp) return NULL;
442
443         memset(fp, 0, FR_POOL_SIZE);
444
445         fp->page_end = ((uint8_t *) fp) + FR_POOL_SIZE;
446         fp->free_ptr = ((uint8_t *) fp) + sizeof(*fp);
447         fp->page_free = fp;
448         fp->page_next = NULL;
449         return fp;
450 }
451
452 static void fr_pool_delete(fr_pool_t **pfp)
453 {
454         fr_pool_t *fp, *next;
455
456         if (!pfp || !*pfp) return;
457
458         for (fp = *pfp; fp != NULL; fp = next) {
459                 next = fp->page_next;
460                 fp->page_next = NULL;
461                 free(fp);
462         }
463         *pfp = NULL;
464 }
465
466
467 static void *fr_pool_alloc(size_t size)
468 {
469         void *ptr;
470
471         if (size == 0) return NULL;
472
473         if (size > 256) return NULL; /* shouldn't happen */
474
475         if (!dict_pool) {
476                 dict_pool = fr_pool_create();
477                 if (!dict_pool) return NULL;
478         }
479
480         if ((size & (FR_ALLOC_ALIGN - 1)) != 0) {
481                 size += FR_ALLOC_ALIGN - (size & (FR_ALLOC_ALIGN - 1));
482         }
483
484         if ((((uint8_t *) dict_pool->page_free->free_ptr) + size) > (uint8_t *) dict_pool->page_free->page_end) {
485                 dict_pool->page_free->page_next = fr_pool_create();
486                 if (!dict_pool->page_free->page_next) return NULL;
487                 dict_pool->page_free = dict_pool->page_free->page_next;
488         }
489
490         ptr = dict_pool->page_free->free_ptr;
491         dict_pool->page_free->free_ptr = ((uint8_t *) dict_pool->page_free->free_ptr) + size;
492
493         return ptr;
494 }
495
496
497 static void fr_pool_free(UNUSED void *ptr)
498 {
499         /*
500          *      Place-holder for later code.
501          */
502 }
503
504 /*
505  *      Free the dictionary_attributes and dictionary_values lists.
506  */
507 void dict_free(void)
508 {
509         /*
510          *      Free the tables
511          */
512         fr_hash_table_free(vendors_byname);
513         fr_hash_table_free(vendors_byvalue);
514         vendors_byname = NULL;
515         vendors_byvalue = NULL;
516
517         fr_hash_table_free(attributes_byname);
518         fr_hash_table_free(attributes_byvalue);
519         fr_hash_table_free(attributes_combo);
520         attributes_byname = NULL;
521         attributes_byvalue = NULL;
522         attributes_combo = NULL;
523
524         fr_hash_table_free(values_byname);
525         fr_hash_table_free(values_byvalue);
526         values_byname = NULL;
527         values_byvalue = NULL;
528
529         memset(dict_base_attrs, 0, sizeof(dict_base_attrs));
530
531         fr_pool_delete(&dict_pool);
532
533         dict_stat_free();
534 }
535
536 /*
537  *      Add vendor to the list.
538  */
539 int dict_addvendor(char const *name, unsigned int value)
540 {
541         size_t length;
542         DICT_VENDOR *dv;
543
544         if (value >= FR_MAX_VENDOR) {
545                 fr_strerror_printf("dict_addvendor: Cannot handle vendor ID larger than 2^24");
546                 return -1;
547         }
548
549         if ((length = strlen(name)) >= DICT_VENDOR_MAX_NAME_LEN) {
550                 fr_strerror_printf("dict_addvendor: vendor name too long");
551                 return -1;
552         }
553
554         if ((dv = fr_pool_alloc(sizeof(*dv) + length)) == NULL) {
555                 fr_strerror_printf("dict_addvendor: out of memory");
556                 return -1;
557         }
558
559         strcpy(dv->name, name);
560         dv->vendorpec  = value;
561         dv->type = dv->length = 1; /* defaults */
562
563         if (!fr_hash_table_insert(vendors_byname, dv)) {
564                 DICT_VENDOR *old_dv;
565
566                 old_dv = fr_hash_table_finddata(vendors_byname, dv);
567                 if (!old_dv) {
568                         fr_strerror_printf("dict_addvendor: Failed inserting vendor name %s", name);
569                         return -1;
570                 }
571                 if (old_dv->vendorpec != dv->vendorpec) {
572                         fr_strerror_printf("dict_addvendor: Duplicate vendor name %s", name);
573                         return -1;
574                 }
575
576                 /*
577                  *      Already inserted.  Discard the duplicate entry.
578                  */
579                 fr_pool_free(dv);
580                 return 0;
581         }
582
583         /*
584          *      Insert the SAME pointer (not free'd when this table is
585          *      deleted), into another table.
586          *
587          *      We want this behaviour because we want OLD names for
588          *      the attributes to be read from the configuration
589          *      files, but when we're printing them, (and looking up
590          *      by value) we want to use the NEW name.
591          */
592         if (!fr_hash_table_replace(vendors_byvalue, dv)) {
593                 fr_strerror_printf("dict_addvendor: Failed inserting vendor %s",
594                            name);
595                 return -1;
596         }
597
598         return 0;
599 }
600
601 const int dict_attr_allowed_chars[256] = {
602 /* 0x   0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
603 /* 0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
604 /* 1 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
605 /* 2 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
606 /* 3 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
607 /* 4 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
608 /* 5 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
609 /* 6 */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
610 /* 7 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
611 /* 8 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
612 /* 9 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
613 /* a */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
614 /* b */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
615 /* c */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
616 /* d */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
617 /* e */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
618 /* f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
619 };
620
621 /*
622  *      [a-zA-Z0-9_-:.]+
623  */
624 int dict_valid_name(char const *name)
625 {
626         uint8_t const *p;
627
628         for (p = (uint8_t const *) name; *p != '\0'; p++) {
629                 if (!dict_attr_allowed_chars[*p]) {
630                         char buff[5];
631
632                         fr_prints(buff, sizeof(buff), (char const *)p, 1, '\'');
633                         fr_strerror_printf("Invalid character '%s' in attribute", buff);
634
635                         return -(p - (uint8_t const *)name);
636                 }
637         }
638
639         return 0;
640 }
641
642 /** Add an attribute to the dictionary
643  *
644  * @return 0 on success -1 on failure.
645  */
646 int dict_addattr(char const *name, int attr, unsigned int vendor, PW_TYPE type,
647                  ATTR_FLAGS flags)
648 {
649         size_t namelen;
650         static int      max_attr = 0;
651         DICT_ATTR const *da;
652         DICT_ATTR *n;
653
654         namelen = strlen(name);
655         if (namelen >= DICT_ATTR_MAX_NAME_LEN) {
656                 fr_strerror_printf("dict_addattr: attribute name too long");
657                 return -1;
658         }
659
660         if (dict_valid_name(name) < 0) return -1;
661
662         if (flags.has_tag &&
663             !((type == PW_TYPE_INTEGER) || (type == PW_TYPE_STRING))) {
664                 fr_strerror_printf("dict_addattr: Only 'integer' and 'string' attributes can have tags");
665                 return -1;
666         }
667
668         /*
669          *      Disallow attributes of type zero.
670          */
671         if (!attr && !vendor) {
672                 fr_strerror_printf("dict_addattr: Attribute 0 is invalid and cannot be used");
673                 return -1;
674         }
675
676         /*
677          *      If the attr is '-1', that means use a pre-existing
678          *      one (if it already exists).  If one does NOT already exist,
679          *      then create a new attribute, with a non-conflicting value,
680          *      and use that.
681          */
682         if (attr == -1) {
683                 if (dict_attrbyname(name)) {
684                         return 0; /* exists, don't add it again */
685                 }
686
687                 attr = ++max_attr;
688
689         } else if (vendor == 0) {
690                 /*
691                  *  Update 'max_attr'
692                  */
693                 if (attr > max_attr) {
694                         max_attr = attr;
695                 }
696         }
697
698         /*
699          *      Additional checks for extended attributes.
700          */
701         if (flags.extended || flags.long_extended || flags.evs) {
702                 if (vendor && (vendor < FR_MAX_VENDOR)) {
703                         fr_strerror_printf("dict_addattr: VSAs cannot use the \"extended\" or \"evs\" attribute formats");
704                         return -1;
705                 }
706                 if (flags.has_tag
707 #ifdef WITH_DHCP
708                     || flags.array
709 #endif
710                     || (flags.encrypt != FLAG_ENCRYPT_NONE)) {
711                         fr_strerror_printf("dict_addattr: The \"extended\" attributes MUST NOT have any flags set");
712                         return -1;
713                 }
714         }
715
716         if (flags.evs) {
717                 if (!(flags.extended || flags.long_extended)) {
718                         fr_strerror_printf("dict_addattr: Attributes of type \"evs\" MUST have a parent of type \"extended\"");
719                         return -1;
720                 }
721
722                 /* VSAs cannot be of format EVS */
723                 if ((vendor & (FR_MAX_VENDOR - 1)) != 0) {
724                         fr_strerror_printf("dict_addattr: Attribute of type \"evs\" fails internal sanity check");
725                         return -1;
726                 }
727         }
728
729         /*
730          *      Do various sanity checks.
731          */
732         if (attr < 0) {
733                 fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (less than zero)");
734                 return -1;
735         }
736
737         if (flags.has_tlv && flags.length) {
738                 fr_strerror_printf("TLVs cannot have a fixed length");
739                 return -1;
740         }
741
742         if (vendor && flags.concat) {
743                 fr_strerror_printf("VSAs cannot have the \"concat\" flag set");
744                 return -1;
745         }
746
747         if (flags.concat && (type != PW_TYPE_OCTETS)) {
748                 fr_strerror_printf("The \"concat\" flag can only be set for attributes of type \"octets\"");
749                 return -1;
750         }
751
752         if (flags.concat && (flags.has_tag || flags.array || flags.is_tlv || flags.has_tlv ||
753                              flags.length || flags.evs || flags.extended || flags.long_extended ||
754                              (flags.encrypt != FLAG_ENCRYPT_NONE))) {
755                 fr_strerror_printf("The \"concat\" flag cannot be used with any other flag");
756                 return -1;
757         }
758
759         if (flags.length && (type != PW_TYPE_OCTETS)) {
760                 fr_strerror_printf("The \"length\" flag can only be set for attributes of type \"octets\"");
761                 return -1;
762         }
763
764         if (flags.length && (flags.has_tag || flags.array || flags.is_tlv || flags.has_tlv ||
765                              flags.concat || flags.evs || flags.extended || flags.long_extended ||
766                              (flags.encrypt > FLAG_ENCRYPT_USER_PASSWORD))) {
767                 fr_strerror_printf("The \"length\" flag cannot be used with any other flag");
768                 return -1;
769         }
770
771         /*
772          *      Force "length" for data types of fixed length;
773          */
774         switch (type) {
775         case PW_TYPE_BYTE:
776                 flags.length = 1;
777                 break;
778
779         case PW_TYPE_SHORT:
780                 flags.length = 2;
781                 break;
782
783         case PW_TYPE_DATE:
784         case PW_TYPE_IPV4_ADDR:
785         case PW_TYPE_INTEGER:
786         case PW_TYPE_SIGNED:
787                 flags.length = 4;
788                 break;
789
790         case PW_TYPE_INTEGER64:
791                 flags.length = 8;
792                 break;
793
794         case PW_TYPE_ETHERNET:
795                 flags.length = 6;
796                 break;
797
798         case PW_TYPE_IFID:
799                 flags.length = 8;
800                 break;
801
802         case PW_TYPE_IPV6_ADDR:
803                 flags.length = 16;
804                 break;
805
806         case PW_TYPE_EXTENDED:
807                 if ((vendor != 0) || (attr < 241)) {
808                         fr_strerror_printf("Attributes of type \"extended\" MUST be "
809                                            "RFC attributes with value >= 241.");
810                         return -1;
811                 }
812
813                 flags.length = 0;
814                 flags.extended = 1;
815                 break;
816
817         case PW_TYPE_LONG_EXTENDED:
818                 if ((vendor != 0) || (attr < 241)) {
819                         fr_strerror_printf("Attributes of type \"long-extended\" MUST "
820                                            "be RFC attributes with value >= 241.");
821                         return -1;
822                 }
823
824                 flags.length = 0;
825                 flags.extended = 1;
826                 flags.long_extended = 1;
827                 break;
828
829         case PW_TYPE_EVS:
830                 if (attr != PW_VENDOR_SPECIFIC) {
831                         fr_strerror_printf("Attributes of type \"evs\" MUST have "
832                                            "attribute code 26.");
833                         return -1;
834                 }
835
836                 flags.length = 0;
837                 flags.extended = 1;
838                 flags.evs = 1;
839                 break;
840
841         case PW_TYPE_STRING:
842         case PW_TYPE_OCTETS:
843         case PW_TYPE_TLV:
844                 flags.is_pointer = true;
845                 break;
846
847         default:
848                 break;
849         }
850
851         /*
852          *      Stupid hacks for MS-CHAP-MPPE-Keys.  The User-Password
853          *      encryption method has no provisions for encoding the
854          *      length of the data.  For User-Password, the data is
855          *      (presumably) all printable non-zero data.  For
856          *      MS-CHAP-MPPE-Keys, the data is binary crap.  So... we
857          *      MUST specify a length in the dictionary.
858          */
859         if ((flags.encrypt == FLAG_ENCRYPT_USER_PASSWORD) && (type != PW_TYPE_STRING)) {
860                 if (type != PW_TYPE_OCTETS) {
861                         fr_strerror_printf("The \"encrypt=1\" flag cannot be used with non-string data types");
862                         return -1;
863                 }
864
865                 if (flags.length == 0) {
866                         fr_strerror_printf("The \"encrypt=1\" flag MUST be used with an explicit length for 'octets' data types");
867                         return -1;
868                 }
869         }
870
871         if ((vendor & (FR_MAX_VENDOR -1)) != 0) {
872                 DICT_VENDOR *dv;
873                 static DICT_VENDOR *last_vendor = NULL;
874
875                 if (flags.has_tlv && (flags.encrypt != FLAG_ENCRYPT_NONE)) {
876                         fr_strerror_printf("TLV's cannot be encrypted");
877                         return -1;
878                 }
879
880                 if (flags.is_tlv && flags.has_tag) {
881                         fr_strerror_printf("Sub-TLV's cannot have a tag");
882                         return -1;
883                 }
884
885                 if (flags.has_tlv && flags.has_tag) {
886                         fr_strerror_printf("TLV's cannot have a tag");
887                         return -1;
888                 }
889
890                 /*
891                  *      Most ATTRIBUTEs are bunched together by
892                  *      VENDOR.  We can save a lot of lookups on
893                  *      dictionary initialization by caching the last
894                  *      vendor.
895                  */
896                 if (last_vendor &&
897                     ((vendor & (FR_MAX_VENDOR - 1)) == last_vendor->vendorpec)) {
898                         dv = last_vendor;
899                 } else {
900                         /*
901                          *      Ignore the high byte (sigh)
902                          */
903                         dv = dict_vendorbyvalue(vendor & (FR_MAX_VENDOR - 1));
904                         last_vendor = dv;
905                 }
906
907                 /*
908                  *      If the vendor isn't defined, die.
909                  */
910                 if (!dv) {
911                         fr_strerror_printf("dict_addattr: Unknown vendor %u",
912                                            vendor & (FR_MAX_VENDOR - 1));
913                         return -1;
914                 }
915
916                 if (!attr && dv->type != 1) {
917                         fr_strerror_printf("dict_addattr: Attribute %s cannot have value zero",
918                                            name);
919                         return -1;
920                 }
921
922                 /*
923                  *      FIXME: Switch over dv->type, and limit things
924                  *      properly.
925                  */
926                 if ((dv->type == 1) && (attr >= 256) && !flags.is_tlv) {
927                         fr_strerror_printf("dict_addattr: ATTRIBUTE has invalid number (larger than 255)");
928                         return -1;
929                 } /* else 256..65535 are allowed */
930
931                 /*
932                  *      If the attribute is in the standard space, AND
933                  *      has a sub-type (e.g. 241.1 or 255.3), then its
934                  *      number is placed into the upper 8 bits of the
935                  *      vendor field.
936                  *
937                  *      This also happens for the new VSAs.
938                  *
939                  *      If we find it, then set the various flags
940                  *      based on what we see.
941                  */
942                 if (vendor >= FR_MAX_VENDOR) {
943                         unsigned int parent;
944
945                         parent = (vendor / FR_MAX_VENDOR) & 0xff;
946
947                         da = dict_attrbyvalue(parent, 0);
948                         if (!da) {
949                                 fr_strerror_printf("dict_addattr: ATTRIBUTE refers to unknown parent attribute %u.", parent);
950                                 return -1;
951                         }
952
953                         /*
954                          *      These flags are inherited from the
955                          *      parent.
956                          */
957                         flags.extended = da->flags.extended;
958                         flags.long_extended = da->flags.long_extended;
959
960                         /*
961                          *      Non-extended attributes can't have VSAs.
962                          */
963                         if (!flags.extended &&
964                             ((vendor & (FR_MAX_VENDOR - 1)) != 0)) {
965                                 fr_strerror_printf("dict_addattr: ATTRIBUTE cannot be a VSA");
966                                 return -1;
967                         }
968
969                         if ((vendor & (FR_MAX_VENDOR - 1)) != 0) {
970                                 flags.evs = 1;
971                         }
972                 }
973
974                 /*
975                  *      <sigh> Alvarion, being *again* a horribly
976                  *      broken vendor, has re-used the WiMAX format in
977                  *      their proprietary vendor space.  This re-use
978                  *      means that there are *multiple* conflicting
979                  *      Alvarion dictionaries.
980                  */
981                 flags.wimax = dv->flags;
982         }
983
984         /*
985          *      Create a new attribute for the list
986          */
987         if ((n = fr_pool_alloc(sizeof(*n) + namelen)) == NULL) {
988         oom:
989                 fr_strerror_printf("dict_addattr: out of memory");
990                 return -1;
991         }
992
993         memcpy(n->name, name, namelen);
994         n->name[namelen] = '\0';
995         n->attr = attr;
996         n->vendor = vendor;
997         n->type = type;
998         n->flags = flags;
999
1000         /*
1001          *      Insert the attribute, only if it's not a duplicate.
1002          */
1003         if (!fr_hash_table_insert(attributes_byname, n)) {
1004                 DICT_ATTR       *a;
1005
1006                 /*
1007                  *      If the attribute has identical number, then
1008                  *      ignore the duplicate.
1009                  */
1010                 a = fr_hash_table_finddata(attributes_byname, n);
1011                 if (a && (strcasecmp(a->name, n->name) == 0)) {
1012                         if (a->attr != n->attr) {
1013                                 fr_strerror_printf("dict_addattr: Duplicate attribute name %s", name);
1014                                 fr_pool_free(n);
1015                                 return -1;
1016                         }
1017
1018                         /*
1019                          *      Same name, same vendor, same attr,
1020                          *      maybe the flags and/or type is
1021                          *      different.  Let the new value
1022                          *      over-ride the old one.
1023                          */
1024                 }
1025
1026
1027                 fr_hash_table_delete(attributes_byvalue, a);
1028
1029                 if (!fr_hash_table_replace(attributes_byname, n)) {
1030                         fr_strerror_printf("dict_addattr: Internal error storing attribute %s", name);
1031                         fr_pool_free(n);
1032                         return -1;
1033                 }
1034         }
1035
1036         /*
1037          *      Insert the SAME pointer (not free'd when this entry is
1038          *      deleted), into another table.
1039          *
1040          *      We want this behaviour because we want OLD names for
1041          *      the attributes to be read from the configuration
1042          *      files, but when we're printing them, (and looking up
1043          *      by value) we want to use the NEW name.
1044          */
1045         if (!fr_hash_table_replace(attributes_byvalue, n)) {
1046                 fr_strerror_printf("dict_addattr: Failed inserting attribute name %s", name);
1047                 return -1;
1048         }
1049
1050         /*
1051          *      Hacks for combo-IP
1052          */
1053         if (n->type == PW_TYPE_COMBO_IP_ADDR) {
1054                 DICT_ATTR *v4, *v6;
1055
1056                 v4 = fr_pool_alloc(sizeof(*v4) + namelen);
1057                 if (!v4) goto oom;
1058
1059                 v6 = fr_pool_alloc(sizeof(*v6) + namelen);
1060                 if (!v6) goto oom;
1061
1062                 memcpy(v4, n, sizeof(*v4) + namelen);
1063                 v4->type = PW_TYPE_IPV4_ADDR;
1064
1065                 memcpy(v6, n, sizeof(*v6) + namelen);
1066                 v6->type = PW_TYPE_IPV6_ADDR;
1067                 if (!fr_hash_table_replace(attributes_combo, v4)) {
1068                         fr_strerror_printf("dict_addattr: Failed inserting attribute name %s - IPv4", name);
1069                         return -1;
1070                 }
1071
1072                 if (!fr_hash_table_replace(attributes_combo, v6)) {
1073                         fr_strerror_printf("dict_addattr: Failed inserting attribute name %s - IPv6", name);
1074                         return -1;
1075                 }
1076         }
1077
1078         if (!vendor && (attr > 0) && (attr < 256)) {
1079                  dict_base_attrs[attr] = n;
1080         }
1081
1082         return 0;
1083 }
1084
1085
1086 /*
1087  *      Add a value for an attribute to the dictionary.
1088  */
1089 int dict_addvalue(char const *namestr, char const *attrstr, int value)
1090 {
1091         size_t          length;
1092         DICT_ATTR const *da;
1093         DICT_VALUE      *dval;
1094
1095         static DICT_ATTR const *last_attr = NULL;
1096
1097         if (!*namestr) {
1098                 fr_strerror_printf("dict_addvalue: empty names are not permitted");
1099                 return -1;
1100         }
1101
1102         if ((length = strlen(namestr)) >= DICT_VALUE_MAX_NAME_LEN) {
1103                 fr_strerror_printf("dict_addvalue: value name too long");
1104                 return -1;
1105         }
1106
1107         if ((dval = fr_pool_alloc(sizeof(*dval) + length)) == NULL) {
1108                 fr_strerror_printf("dict_addvalue: out of memory");
1109                 return -1;
1110         }
1111         memset(dval, 0, sizeof(*dval));
1112
1113         strcpy(dval->name, namestr);
1114         dval->value = value;
1115
1116         /*
1117          *      Most VALUEs are bunched together by ATTRIBUTE.  We can
1118          *      save a lot of lookups on dictionary initialization by
1119          *      caching the last attribute.
1120          */
1121         if (last_attr && (strcasecmp(attrstr, last_attr->name) == 0)) {
1122                 da = last_attr;
1123         } else {
1124                 da = dict_attrbyname(attrstr);
1125                 last_attr = da;
1126         }
1127
1128         /*
1129          *      Remember which attribute is associated with this
1130          *      value, if possible.
1131          */
1132         if (da) {
1133                 if (da->flags.has_value_alias) {
1134                         fr_strerror_printf("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr);
1135                         return -1;
1136                 }
1137
1138                 dval->attr = da->attr;
1139                 dval->vendor = da->vendor;
1140
1141                 /*
1142                  *      Enforce valid values
1143                  *
1144                  *      Don't worry about fixups...
1145                  */
1146                 switch (da->type) {
1147                 case PW_TYPE_BYTE:
1148                         if (value > 255) {
1149                                 fr_pool_free(dval);
1150                                 fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255");
1151                                 return -1;
1152                         }
1153                         break;
1154                 case PW_TYPE_SHORT:
1155                         if (value > 65535) {
1156                                 fr_pool_free(dval);
1157                                 fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535");
1158                                 return -1;
1159                         }
1160                         break;
1161
1162                         /*
1163                          *      Allow octets for now, because
1164                          *      of dictionary.cablelabs
1165                          */
1166                 case PW_TYPE_OCTETS:
1167
1168                 case PW_TYPE_INTEGER:
1169                         break;
1170
1171                 case PW_TYPE_INTEGER64:
1172                 default:
1173                         fr_pool_free(dval);
1174                         fr_strerror_printf("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'",
1175                                    fr_int2str(dict_attr_types, da->type, "?Unknown?"));
1176                         return -1;
1177                 }
1178         } else {
1179                 value_fixup_t *fixup;
1180
1181                 fixup = (value_fixup_t *) malloc(sizeof(*fixup));
1182                 if (!fixup) {
1183                         fr_pool_free(dval);
1184                         fr_strerror_printf("dict_addvalue: out of memory");
1185                         return -1;
1186                 }
1187                 memset(fixup, 0, sizeof(*fixup));
1188
1189                 strlcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr));
1190                 fixup->dval = dval;
1191
1192                 /*
1193                  *      Insert to the head of the list.
1194                  */
1195                 fixup->next = value_fixup;
1196                 value_fixup = fixup;
1197
1198                 return 0;
1199         }
1200
1201         /*
1202          *      Add the value into the dictionary.
1203          */
1204         {
1205                 DICT_ATTR *tmp;
1206                 memcpy(&tmp, &dval, sizeof(tmp));
1207
1208                 if (!fr_hash_table_insert(values_byname, tmp)) {
1209                         if (da) {
1210                                 DICT_VALUE *old;
1211
1212                                 /*
1213                                  *      Suppress duplicates with the same
1214                                  *      name and value.  There are lots in
1215                                  *      dictionary.ascend.
1216                                  */
1217                                 old = dict_valbyname(da->attr, da->vendor, namestr);
1218                                 if (old && (old->value == dval->value)) {
1219                                         fr_pool_free(dval);
1220                                         return 0;
1221                                 }
1222                         }
1223
1224                         fr_pool_free(dval);
1225                         fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr);
1226                         return -1;
1227                 }
1228         }
1229
1230         /*
1231          *      There are multiple VALUE's, keyed by attribute, so we
1232          *      take care of that here.
1233          */
1234         if (!fr_hash_table_replace(values_byvalue, dval)) {
1235                 fr_strerror_printf("dict_addvalue: Failed inserting value %s",
1236                            namestr);
1237                 return -1;
1238         }
1239
1240         return 0;
1241 }
1242
1243 static int sscanf_i(char const *str, unsigned int *pvalue)
1244 {
1245         int rcode = 0;
1246         int base = 10;
1247         static char const *tab = "0123456789";
1248
1249         if ((str[0] == '0') &&
1250             ((str[1] == 'x') || (str[1] == 'X'))) {
1251                 tab = "0123456789abcdef";
1252                 base = 16;
1253
1254                 str += 2;
1255         }
1256
1257         while (*str) {
1258                 char const *c;
1259
1260                 if (*str == '.') break;
1261
1262                 c = memchr(tab, tolower((int) *str), base);
1263                 if (!c) return 0;
1264
1265                 rcode *= base;
1266                 rcode += (c - tab);
1267                 str++;
1268         }
1269
1270         *pvalue = rcode;
1271         return 1;
1272 }
1273
1274
1275 /*
1276  *      Get the OID based on various pieces of information.
1277  *
1278  *      Remember, the packing format is weird.
1279  *
1280  *      00VID   000000AA        normal VSA for vendor VID
1281  *      00VID   AABBCCDD        normal VSAs with TLVs
1282  *      EE000   000000AA        extended attr (241.1)
1283  *      EE000   AABBCCDD        extended attr with TLVs
1284  *      EEVID   000000AA        EVS with vendor VID, attr AAA
1285  *      EEVID   AABBCCDD        EVS with TLVs
1286  *
1287  *      <whew>!  Are we crazy, or what?
1288  */
1289 int dict_str2oid(char const *ptr, unsigned int *pvalue, unsigned int *pvendor,
1290                  int tlv_depth)
1291 {
1292         char const *p;
1293         unsigned int value;
1294         DICT_ATTR const *da = NULL;
1295
1296         if (tlv_depth > fr_attr_max_tlv) {
1297                 fr_strerror_printf("Too many sub-attributes");
1298                 return -1;
1299         }
1300
1301         /*
1302          *      If *pvalue is set, check if the attribute exists.
1303          *      Otherwise, check that the vendor exists.
1304          */
1305         if (*pvalue) {
1306                 da = dict_attrbyvalue(*pvalue, *pvendor);
1307                 if (!da) {
1308                         fr_strerror_printf("Parent attribute is undefined");
1309                         return -1;
1310                 }
1311
1312                 if (!da->flags.has_tlv && !da->flags.extended) {
1313                         fr_strerror_printf("Parent attribute %s cannot have sub-attributes",
1314                                            da->name);
1315                         return -1;
1316                 }
1317
1318         } else if ((*pvendor & (FR_MAX_VENDOR - 1)) != 0) {
1319                 if (!dict_vendorbyvalue(*pvendor & (FR_MAX_VENDOR - 1))) {
1320                         fr_strerror_printf("Unknown vendor %u",
1321                                            *pvendor & (FR_MAX_VENDOR - 1));
1322                         return -1;
1323                 }
1324         }
1325
1326         p = strchr(ptr, '.');
1327
1328         /*
1329          *      Look for 26.VID.x.y
1330          *
1331          *      If we find it, re-write the parameters, and recurse.
1332          */
1333         if (!*pvendor && (tlv_depth == 0) && (*pvalue == PW_VENDOR_SPECIFIC)) {
1334                 DICT_VENDOR const *dv;
1335
1336                 if (!p) {
1337                         fr_strerror_printf("VSA needs to have sub-attribute");
1338                         return -1;
1339                 }
1340
1341                 if (!sscanf_i(ptr, pvendor)) {
1342                         fr_strerror_printf("Invalid number in attribute");
1343                         return -1;
1344                 }
1345
1346                 if (*pvendor >= FR_MAX_VENDOR) {
1347                         fr_strerror_printf("Cannot handle vendor ID larger than 2^24");
1348
1349                         return -1;
1350                 }
1351
1352                 dv = dict_vendorbyvalue(*pvendor & (FR_MAX_VENDOR - 1));
1353                 if (!dv) {
1354                         fr_strerror_printf("Unknown vendor \"%u\" ",
1355                                            *pvendor  & (FR_MAX_VENDOR - 1));
1356                         return -1;
1357                 }
1358
1359                 /*
1360                  *      Start off with (attr=0, vendor=VID), and
1361                  *      recurse.  This causes the various checks above
1362                  *      to be done.
1363                  */
1364                 *pvalue = 0;
1365                 return dict_str2oid(p + 1, pvalue, pvendor, 0);
1366         }
1367
1368         if (!sscanf_i(ptr, &value)) {
1369                 fr_strerror_printf("Invalid number in attribute");
1370                 return -1;
1371         }
1372
1373         if (!*pvendor && (tlv_depth == 1) && da &&
1374             (da->flags.has_tlv || da->flags.extended)) {
1375
1376
1377                 *pvendor = *pvalue * FR_MAX_VENDOR;
1378                 *pvalue = value;
1379
1380                 if (!p) return 0;
1381                 return dict_str2oid(p + 1, pvalue, pvendor, 1);
1382         }
1383
1384         /*
1385          *      And pack the data according to the scheme described in
1386          *      the comments at the start of this function.
1387          */
1388         if (*pvalue) {
1389                 *pvalue |= (value & fr_attr_mask[tlv_depth]) << fr_attr_shift[tlv_depth];
1390         } else {
1391                 *pvalue = value;
1392         }
1393
1394         if (p) {
1395                 return dict_str2oid(p + 1, pvalue, pvendor, tlv_depth + 1);
1396         }
1397
1398         return tlv_depth;
1399 }
1400
1401 /*
1402  *      Bamboo skewers under the fingernails in 5, 4, 3, 2, ...
1403  */
1404 static DICT_ATTR const *dict_parent(unsigned int attr, unsigned int vendor)
1405 {
1406         int i;
1407         unsigned int base_vendor;
1408
1409         /*
1410          *      RFC attributes can't be of type "tlv".
1411          */
1412         if (!vendor) return NULL;
1413
1414         base_vendor = vendor & (FR_MAX_VENDOR - 1);
1415
1416         /*
1417          *      It's a real vendor.
1418          */
1419         if (base_vendor != 0) {
1420                 DICT_VENDOR const *dv;
1421
1422                 dv = dict_vendorbyvalue(base_vendor);
1423                 if (!dv) return NULL;
1424
1425                 /*
1426                  *      Only standard format attributes can be of type "tlv",
1427                  *      Except for DHCP.  <sigh>
1428                  */
1429                 if ((vendor != 54) && ((dv->type != 1) || (dv->length != 1))) return NULL;
1430
1431                 for (i = MAX_TLV_NEST; i > 0; i--) {
1432                         unsigned int parent;
1433
1434                         parent = attr & fr_attr_parent_mask[i];
1435
1436                         if (parent != attr) return dict_attrbyvalue(parent, vendor); /* not base_vendor */
1437                 }
1438
1439                 /*
1440                  *      It was a top-level VSA.  There's no parent.
1441                  *      We COULD return the appropriate enclosing VSA
1442                  *      (26, or 241.26, etc.) but that's not what we
1443                  *      want.
1444                  */
1445                 return NULL;
1446         }
1447
1448         /*
1449          *      It's an extended attribute.  Return the base Extended-Attr-X
1450          */
1451         if (attr < 256) return dict_attrbyvalue((vendor / FR_MAX_VENDOR) & 0xff, 0);
1452
1453
1454         /*
1455          *      Figure out which attribute it is.
1456          */
1457         for (i = MAX_TLV_NEST; i > 0; i--) {
1458                 unsigned int parent;
1459
1460                 parent = attr & fr_attr_parent_mask[i];
1461                 if (parent != attr) return dict_attrbyvalue(parent, vendor); /* not base_vendor */
1462         }
1463
1464         return NULL;
1465 }
1466
1467
1468 /*
1469  *      Process the ATTRIBUTE command
1470  */
1471 static int process_attribute(char const* fn, int const line,
1472                              unsigned int block_vendor,
1473                              DICT_ATTR const *block_tlv, int tlv_depth,
1474                              char **argv, int argc)
1475 {
1476         int             oid = 0;
1477         unsigned int    vendor = 0;
1478         unsigned int    value;
1479         int             type;
1480         unsigned int    length;
1481         ATTR_FLAGS      flags;
1482         char            *p;
1483
1484         if ((argc < 3) || (argc > 4)) {
1485                 fr_strerror_printf("dict_init: %s[%d]: invalid ATTRIBUTE line",
1486                         fn, line);
1487                 return -1;
1488         }
1489
1490         /*
1491          *      Dictionaries need to have real names, not shitty ones.
1492          */
1493         if (strncmp(argv[1], "Attr-", 5) == 0) {
1494                 fr_strerror_printf("dict_init: %s[%d]: Invalid attribute name",
1495                                    fn, line);
1496                 return -1;
1497         }
1498
1499         memset(&flags, 0, sizeof(flags));
1500
1501         /*
1502          *      Look for OIDs before doing anything else.
1503          */
1504         p = strchr(argv[1], '.');
1505         if (p) oid = 1;
1506
1507         /*
1508          *      Validate all entries
1509          */
1510         if (!sscanf_i(argv[1], &value)) {
1511                 fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line);
1512                 return -1;
1513         }
1514
1515         if (oid) {
1516                 DICT_ATTR const *da;
1517
1518                 vendor = block_vendor;
1519
1520                 /*
1521                  *      Parse the rest of the OID.
1522                  */
1523                 if (dict_str2oid(p + 1, &value, &vendor, tlv_depth + 1) < 0) {
1524                         char buffer[256];
1525
1526                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
1527
1528                         fr_strerror_printf("dict_init: %s[%d]: Invalid attribute identifier: %s", fn, line, buffer);
1529                         return -1;
1530                 }
1531                 block_vendor = vendor;
1532
1533                 /*
1534                  *      Set the flags based on the parents flags.
1535                  */
1536                 da = dict_parent(value, vendor);
1537                 if (!da) {
1538                         fr_strerror_printf("dict_init: %s[%d]: Parent attribute is undefined.", fn, line);
1539                         return -1;
1540                 }
1541
1542                 flags.extended = da->flags.extended;
1543                 flags.long_extended = da->flags.long_extended;
1544                 flags.evs = da->flags.evs;
1545                 if (da->flags.has_tlv) flags.is_tlv = 1;
1546         }
1547
1548         if (strncmp(argv[2], "octets[", 7) != 0) {
1549                 /*
1550                  *      find the type of the attribute.
1551                  */
1552                 type = fr_str2int(dict_attr_types, argv[2], -1);
1553                 if (type < 0) {
1554                         fr_strerror_printf("dict_init: %s[%d]: invalid type \"%s\"",
1555                                            fn, line, argv[2]);
1556                         return -1;
1557                 }
1558
1559         } else {
1560                 type = PW_TYPE_OCTETS;
1561
1562                 p = strchr(argv[2] + 7, ']');
1563                 if (!p) {
1564                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for octets", fn, line);
1565                         return -1;
1566                 }
1567
1568                 *p = 0;
1569
1570                 if (!sscanf_i(argv[1], &length)) {
1571                         fr_strerror_printf("dict_init: %s[%d]: invalid length", fn, line);
1572                         return -1;
1573                 }
1574
1575                 if ((length == 0) || (length > 253)) {
1576                         fr_strerror_printf("dict_init: %s[%d]: invalid length", fn, line);
1577                         return -1;
1578                 }
1579
1580                 flags.length = length;
1581         }
1582
1583         /*
1584          *      Parse options.
1585          */
1586         if (argc >= 4) {
1587                 char *key, *next, *last;
1588
1589                 /*
1590                  *      Keep it real.
1591                  */
1592                 if (flags.extended) {
1593                         fr_strerror_printf("dict_init: %s[%d]: Extended attributes cannot use flags", fn, line);
1594                         return -1;
1595                 }
1596
1597                 key = argv[3];
1598                 do {
1599                         next = strchr(key, ',');
1600                         if (next) *(next++) = '\0';
1601
1602                         /*
1603                          *      Boolean flag, means this is a tagged
1604                          *      attribute.
1605                          */
1606                         if ((strcmp(key, "has_tag") == 0) || (strcmp(key, "has_tag=1") == 0)) {
1607                                 flags.has_tag = 1;
1608
1609                         /*
1610                          *      Encryption method, defaults to 0 (none).
1611                          *      Currently valid is just type 2,
1612                          *      Tunnel-Password style, which can only
1613                          *      be applied to strings.
1614                          */
1615                         } else if (strncmp(key, "encrypt=", 8) == 0) {
1616                                 flags.encrypt = strtol(key + 8, &last, 0);
1617                                 if (*last) {
1618                                         fr_strerror_printf("dict_init: %s[%d] invalid option %s",
1619                                                            fn, line, key);
1620                                         return -1;
1621                                 }
1622
1623                                 if ((flags.encrypt == FLAG_ENCRYPT_ASCEND_SECRET) &&
1624                                     (type != PW_TYPE_STRING)) {
1625                                         fr_strerror_printf("dict_init: %s[%d] Only \"string\" types can have the "
1626                                                            "\"encrypt=3\" flag set", fn, line);
1627                                         return -1;
1628                                 }
1629
1630                         } else if (strncmp(key, "array", 6) == 0) {
1631                                 flags.array = 1;
1632
1633                                 switch (type) {
1634                                 case PW_TYPE_IPV4_ADDR:
1635                                 case PW_TYPE_IPV6_ADDR:
1636                                 case PW_TYPE_BYTE:
1637                                 case PW_TYPE_SHORT:
1638                                 case PW_TYPE_INTEGER:
1639                                 case PW_TYPE_DATE:
1640                                 case PW_TYPE_STRING:
1641                                         break;
1642
1643                                 default:
1644                                         fr_strerror_printf("dict_init: %s[%d] \"%s\" type cannot have the "
1645                                                            "\"array\" flag set",
1646                                                            fn, line,
1647                                                            fr_int2str(dict_attr_types, type, "<UNKNOWN>"));
1648                                         return -1;
1649                                 }
1650
1651                         } else if (strncmp(key, "concat", 7) == 0) {
1652                                 flags.concat = 1;
1653
1654                                 if (type != PW_TYPE_OCTETS) {
1655                                         fr_strerror_printf("dict_init: %s[%d] Only \"octets\" type can have the "
1656                                                            "\"concat\" flag set", fn, line);
1657                                         return -1;
1658                                 }
1659
1660                         } else if (strncmp(key, "virtual", 8) == 0) {
1661                                 flags.virtual = 1;
1662
1663                                 if (vendor != 0) {
1664                                         fr_strerror_printf("dict_init: %s[%d] VSAs cannot have the \"virtual\" "
1665                                                            "flag set", fn, line);
1666                                         return -1;
1667                                 }
1668
1669                                 if (value < 256) {
1670                                         fr_strerror_printf("dict_init: %s[%d] Standard attributes cannot "
1671                                                            "have the \"virtual\" flag set", fn, line);
1672                                         return -1;
1673                                 }
1674
1675                         /*
1676                          *      The only thing is the vendor name,
1677                          *      and it's a known name: allow it.
1678                          */
1679                         } else if ((key == argv[3]) && !next) {
1680                                 if (oid) {
1681                                         fr_strerror_printf("dict_init: %s[%d] New-style attributes cannot use "
1682                                                            "a vendor flag", fn, line);
1683                                         return -1;
1684                                 }
1685
1686                                 if (block_vendor) {
1687                                         fr_strerror_printf("dict_init: %s[%d] Vendor flag inside of \"BEGIN-VENDOR\" "
1688                                                            "is not allowed", fn, line);
1689                                         return -1;
1690                                 }
1691
1692                                 vendor = dict_vendorbyname(key);
1693                                 if (!vendor) goto unknown;
1694                                 break;
1695
1696                         } else {
1697                         unknown:
1698                                 fr_strerror_printf("dict_init: %s[%d]: unknown option \"%s\"", fn, line, key);
1699                                 return -1;
1700                         }
1701
1702                         key = next;
1703                         if (key && !*key) break;
1704                 } while (key);
1705         }
1706
1707         if (block_vendor) vendor = block_vendor;
1708
1709         /*
1710          *      Special checks for tags, they make our life much more
1711          *      difficult.
1712          */
1713         if (flags.has_tag) {
1714                 /*
1715                  *      Only string, octets, and integer can be tagged.
1716                  */
1717                 switch (type) {
1718                 case PW_TYPE_STRING:
1719                 case PW_TYPE_INTEGER:
1720                         break;
1721
1722                 default:
1723                         fr_strerror_printf("dict_init: %s[%d]: Attributes of type %s cannot be tagged.",
1724                                    fn, line,
1725                                    fr_int2str(dict_attr_types, type, "?Unknown?"));
1726                         return -1;
1727                 }
1728         }
1729
1730         if (type == PW_TYPE_TLV) {
1731                 if (vendor && (vendor < FR_MAX_VENDOR)
1732 #ifdef WITH_DHCP
1733                     && (vendor != DHCP_MAGIC_VENDOR)
1734 #endif
1735                         ) {
1736                         DICT_VENDOR *dv;
1737
1738                         dv = dict_vendorbyvalue(vendor);
1739                         if (!dv || (dv->type != 1) || (dv->length != 1)) {
1740                                 fr_strerror_printf("dict_init: %s[%d]: Type \"tlv\" can only be for \"format=1,1\".",
1741                                                    fn, line);
1742                                 return -1;
1743                         }
1744
1745                 }
1746                 flags.has_tlv = 1;
1747         }
1748
1749         if (block_tlv) {
1750                 /*
1751                  *      TLV's can be only one octet.
1752                  */
1753                 if ((value == 0) || ((value & ~fr_attr_mask[tlv_depth]) != 0)) {
1754                         fr_strerror_printf( "dict_init: %s[%d]: sub-tlv has invalid attribute number",
1755                                             fn, line);
1756                         return -1;
1757                 }
1758
1759                 /*
1760                  *      Shift the value left.
1761                  */
1762                 value <<= fr_attr_shift[tlv_depth];
1763                 value |= block_tlv->attr;
1764                 flags.is_tlv = 1;
1765         }
1766
1767 #ifdef WITH_DICTIONARY_WARNINGS
1768         /*
1769          *      Hack to help us discover which vendors have illegal
1770          *      attributes.
1771          */
1772         if (!vendor && (value < 256) &&
1773             !strstr(fn, "rfc") && !strstr(fn, "illegal")) {
1774                 fprintf(stderr, "WARNING: Illegal Attribute %s in %s\n",
1775                         argv[0], fn);
1776         }
1777 #endif
1778
1779         /*
1780          *      Add it in.
1781          */
1782         if (dict_addattr(argv[0], value, vendor, type, flags) < 0) {
1783                 char buffer[256];
1784
1785                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1786
1787                 fr_strerror_printf("dict_init: %s[%d]: %s",
1788                                    fn, line, buffer);
1789                 return -1;
1790         }
1791
1792         return 0;
1793 }
1794
1795
1796 /*
1797  *      Process the VALUE command
1798  */
1799 static int process_value(char const* fn, int const line, char **argv,
1800                          int argc)
1801 {
1802         unsigned int    value;
1803
1804         if (argc != 3) {
1805                 fr_strerror_printf("dict_init: %s[%d]: invalid VALUE line",
1806                         fn, line);
1807                 return -1;
1808         }
1809         /*
1810          *      For Compatibility, skip "Server-Config"
1811          */
1812         if (strcasecmp(argv[0], "Server-Config") == 0)
1813                 return 0;
1814
1815         /*
1816          *      Validate all entries
1817          */
1818         if (!sscanf_i(argv[2], &value)) {
1819                 fr_strerror_printf("dict_init: %s[%d]: invalid value",
1820                         fn, line);
1821                 return -1;
1822         }
1823
1824         if (dict_addvalue(argv[1], argv[0], value) < 0) {
1825                 char buffer[256];
1826
1827                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1828
1829                 fr_strerror_printf("dict_init: %s[%d]: %s",
1830                                    fn, line, buffer);
1831                 return -1;
1832         }
1833
1834         return 0;
1835 }
1836
1837
1838 /*
1839  *      Process the VALUE-ALIAS command
1840  *
1841  *      This allows VALUE mappings to be shared among multiple
1842  *      attributes.
1843  */
1844 static int process_value_alias(char const* fn, int const line, char **argv,
1845                                int argc)
1846 {
1847         DICT_ATTR const *my_da, *da;
1848         DICT_VALUE *dval;
1849
1850         if (argc != 2) {
1851                 fr_strerror_printf("dict_init: %s[%d]: invalid VALUE-ALIAS line",
1852                         fn, line);
1853                 return -1;
1854         }
1855
1856         my_da = dict_attrbyname(argv[0]);
1857         if (!my_da) {
1858                 fr_strerror_printf("dict_init: %s[%d]: ATTRIBUTE \"%s\" does not exist",
1859                            fn, line, argv[1]);
1860                 return -1;
1861         }
1862
1863         if (my_da->flags.has_value_alias) {
1864                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" with pre-existing VALUE-ALIAS",
1865                            fn, line, argv[0]);
1866                 return -1;
1867         }
1868
1869         da = dict_attrbyname(argv[1]);
1870         if (!da) {
1871                 fr_strerror_printf("dict_init: %s[%d]: Cannot find ATTRIBUTE \"%s\" for alias",
1872                            fn, line, argv[1]);
1873                 return -1;
1874         }
1875
1876         if (da->flags.has_value_alias) {
1877                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS to ATTRIBUTE \"%s\" which itself has a VALUE-ALIAS",
1878                            fn, line, argv[1]);
1879                 return -1;
1880         }
1881
1882         if (my_da->type != da->type) {
1883                 fr_strerror_printf("dict_init: %s[%d]: Cannot add VALUE-ALIAS between attributes of differing type",
1884                            fn, line);
1885                 return -1;
1886         }
1887
1888         if ((dval = fr_pool_alloc(sizeof(*dval))) == NULL) {
1889                 fr_strerror_printf("dict_addvalue: out of memory");
1890                 return -1;
1891         }
1892
1893         dval->name[0] = '\0';   /* empty name */
1894         dval->attr = my_da->attr;
1895         dval->vendor = my_da->vendor;
1896         dval->value = da->attr;
1897
1898         if (!fr_hash_table_insert(values_byname, dval)) {
1899                 fr_strerror_printf("dict_init: %s[%d]: Error create alias",
1900                            fn, line);
1901                 fr_pool_free(dval);
1902                 return -1;
1903         }
1904
1905         return 0;
1906 }
1907
1908
1909 static int parse_format(char const *fn, int line, char const *format, int *pvalue, int *ptype, int *plength, bool *pcontinuation)
1910 {
1911         char const *p;
1912         int type, length;
1913         bool continuation = false;
1914
1915         if (strncasecmp(format, "format=", 7) != 0) {
1916                 fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected \"format=\", got \"%s\"",
1917                                    fn, line, format);
1918                 return -1;
1919         }
1920
1921         p = format + 7;
1922         if ((strlen(p) < 3) ||
1923             !isdigit((int) p[0]) ||
1924             (p[1] != ',') ||
1925             !isdigit((int) p[2]) ||
1926             (p[3] && (p[3] != ','))) {
1927                 fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected text like \"1,1\", got \"%s\"",
1928                                    fn, line, p);
1929                 return -1;
1930         }
1931
1932         type = (int) (p[0] - '0');
1933         length = (int) (p[2] - '0');
1934
1935         if ((type != 1) && (type != 2) && (type != 4)) {
1936                 fr_strerror_printf("dict_init: %s[%d]: invalid type value %d for VENDOR",
1937                                    fn, line, type);
1938                 return -1;
1939         }
1940
1941         if ((length != 0) && (length != 1) && (length != 2)) {
1942                 fr_strerror_printf("dict_init: %s[%d]: invalid length value %d for VENDOR",
1943                                    fn, line, length);
1944                 return -1;
1945         }
1946
1947         if (p[3] == ',') {
1948                 if (!p[4]) {
1949                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected text like \"1,1\", got \"%s\"",
1950                                            fn, line, p);
1951                         return -1;
1952                 }
1953
1954                 if ((p[4] != 'c') ||
1955                     (p[5] != '\0')) {
1956                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR.  Expected text like \"1,1\", got \"%s\"",
1957                                            fn, line, p);
1958                         return -1;
1959                 }
1960                 continuation = true;
1961
1962                 if ((*pvalue != VENDORPEC_WIMAX) ||
1963                     (type != 1) || (length != 1)) {
1964                         fr_strerror_printf("dict_init: %s[%d]: Only WiMAX VSAs can have continuations",
1965                                            fn, line);
1966                         return -1;
1967                 }
1968         }
1969
1970         *ptype = type;
1971         *plength = length;
1972         *pcontinuation = continuation;
1973         return 0;
1974 }
1975
1976
1977 /*
1978  *      Process the VENDOR command
1979  */
1980 static int process_vendor(char const* fn, int const line, char **argv,
1981                           int argc)
1982 {
1983         int             value;
1984         int             type, length;
1985         bool            continuation = false;
1986         DICT_VENDOR     *dv;
1987
1988         if ((argc < 2) || (argc > 3)) {
1989                 fr_strerror_printf( "dict_init: %s[%d] invalid VENDOR entry",
1990                             fn, line);
1991                 return -1;
1992         }
1993
1994         /*
1995          *       Validate all entries
1996          */
1997         if (!isdigit((int) argv[1][0])) {
1998                 fr_strerror_printf("dict_init: %s[%d]: invalid value",
1999                         fn, line);
2000                 return -1;
2001         }
2002         value = atoi(argv[1]);
2003
2004         /* Create a new VENDOR entry for the list */
2005         if (dict_addvendor(argv[0], value) < 0) {
2006                 char buffer[256];
2007
2008                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
2009
2010                 fr_strerror_printf("dict_init: %s[%d]: %s",
2011                            fn, line, buffer);
2012                 return -1;
2013         }
2014
2015         /*
2016          *      Look for a format statement.  Allow it to over-ride the hard-coded formats below.
2017          */
2018         if (argc == 3) {
2019                 if (parse_format(fn, line, argv[2], &value, &type, &length, &continuation) < 0) {
2020                         return -1;
2021                 }
2022
2023         } else if (value == VENDORPEC_USR) { /* catch dictionary screw-ups */
2024                 type = 4;
2025                 length = 0;
2026
2027         } else if (value == VENDORPEC_LUCENT) {
2028                 type = 2;
2029                 length = 1;
2030
2031         } else if (value == VENDORPEC_STARENT) {
2032                 type = 2;
2033                 length = 2;
2034
2035         } else {
2036                 type = length = 1;
2037         }
2038
2039         dv = dict_vendorbyvalue(value);
2040         if (!dv) {
2041                 fr_strerror_printf("dict_init: %s[%d]: Failed adding format for VENDOR",
2042                                    fn, line);
2043                 return -1;
2044         }
2045
2046         dv->type = type;
2047         dv->length = length;
2048         dv->flags = continuation;
2049
2050         return 0;
2051 }
2052
2053 /*
2054  *      String split routine.  Splits an input string IN PLACE
2055  *      into pieces, based on spaces.
2056  */
2057 int str2argv(char *str, char **argv, int max_argc)
2058 {
2059         int argc = 0;
2060
2061         while (*str) {
2062                 if (argc >= max_argc) break;
2063
2064                 /*
2065                  *      Chop out comments early.
2066                  */
2067                 if (*str == '#') {
2068                         *str = '\0';
2069                         break;
2070                 }
2071
2072                 while ((*str == ' ') ||
2073                        (*str == '\t') ||
2074                        (*str == '\r') ||
2075                        (*str == '\n')) *(str++) = '\0';
2076
2077                 if (!*str) break;
2078
2079                 argv[argc] = str;
2080                 argc++;
2081
2082                 while (*str &&
2083                        (*str != ' ') &&
2084                        (*str != '\t') &&
2085                        (*str != '\r') &&
2086                        (*str != '\n')) str++;
2087         }
2088
2089         return argc;
2090 }
2091
2092 static int my_dict_init(char const *parent, char const *filename,
2093                         char const *src_file, int src_line);
2094
2095 int dict_read(char const *dir, char const *filename)
2096 {
2097         if (!attributes_byname) {
2098                 fr_strerror_printf("Must call dict_init() before dict_read()");
2099                 return -1;
2100         }
2101
2102         return my_dict_init(dir, filename, NULL, 0);
2103 }
2104
2105
2106 #define MAX_ARGV (16)
2107
2108 /*
2109  *      Initialize the dictionary.
2110  */
2111 static int my_dict_init(char const *parent, char const *filename,
2112                         char const *src_file, int src_line)
2113 {
2114         FILE    *fp;
2115         char    dir[256], fn[256];
2116         char    buf[256];
2117         char    *p;
2118         int     line = 0;
2119         unsigned int    vendor;
2120         unsigned int    block_vendor;
2121         struct stat statbuf;
2122         char    *argv[MAX_ARGV];
2123         int     argc;
2124         DICT_ATTR const *da, *block_tlv[MAX_TLV_NEST + 1];
2125         int     which_block_tlv = 0;
2126
2127         block_tlv[0] = NULL;
2128         block_tlv[1] = NULL;
2129         block_tlv[2] = NULL;
2130         block_tlv[3] = NULL;
2131
2132         if ((strlen(parent) + 3 + strlen(filename)) > sizeof(dir)) {
2133                 fr_strerror_printf("dict_init: filename name too long");
2134                 return -1;
2135         }
2136
2137         /*
2138          *      If it's an absolute dir, forget the parent dir,
2139          *      and remember the new one.
2140          *
2141          *      If it's a relative dir, tack on the current filename
2142          *      to the parent dir.  And use that.
2143          */
2144         if (!FR_DIR_IS_RELATIVE(filename)) {
2145                 strlcpy(dir, filename, sizeof(dir));
2146                 p = strrchr(dir, FR_DIR_SEP);
2147                 if (p) {
2148                         p[1] = '\0';
2149                 } else {
2150                         strlcat(dir, "/", sizeof(dir));
2151                 }
2152
2153                 strlcpy(fn, filename, sizeof(fn));
2154         } else {
2155                 strlcpy(dir, parent, sizeof(dir));
2156                 p = strrchr(dir, FR_DIR_SEP);
2157                 if (p) {
2158                         if (p[1]) strlcat(dir, "/", sizeof(dir));
2159                 } else {
2160                         strlcat(dir, "/", sizeof(dir));
2161                 }
2162                 strlcat(dir, filename, sizeof(dir));
2163                 p = strrchr(dir, FR_DIR_SEP);
2164                 if (p) {
2165                         p[1] = '\0';
2166                 } else {
2167                         strlcat(dir, "/", sizeof(dir));
2168                 }
2169
2170                 p = strrchr(filename, FR_DIR_SEP);
2171                 if (p) {
2172                         snprintf(fn, sizeof(fn), "%s%s", dir, p);
2173                 } else {
2174                         snprintf(fn, sizeof(fn), "%s%s", dir, filename);
2175                 }
2176
2177         }
2178
2179         /*
2180          *      Check if we've loaded this file before.  If so, ignore it.
2181          */
2182         p = strrchr(fn, FR_DIR_SEP);
2183         if (p) {
2184                 *p = '\0';
2185                 if (dict_stat_check(fn, p + 1)) {
2186                         *p = FR_DIR_SEP;
2187                         return 0;
2188                 }
2189                 *p = FR_DIR_SEP;
2190         }
2191
2192         if ((fp = fopen(fn, "r")) == NULL) {
2193                 if (!src_file) {
2194                         fr_strerror_printf("dict_init: Couldn't open dictionary \"%s\": %s",
2195                                    fn, fr_syserror(errno));
2196                 } else {
2197                         fr_strerror_printf("dict_init: %s[%d]: Couldn't open dictionary \"%s\": %s",
2198                                    src_file, src_line, fn, fr_syserror(errno));
2199                 }
2200                 return -2;
2201         }
2202
2203         stat(fn, &statbuf); /* fopen() guarantees this will succeed */
2204         if (!S_ISREG(statbuf.st_mode)) {
2205                 fclose(fp);
2206                 fr_strerror_printf("dict_init: Dictionary \"%s\" is not a regular file",
2207                            fn);
2208                 return -1;
2209         }
2210
2211         /*
2212          *      Globally writable dictionaries means that users can control
2213          *      the server configuration with little difficulty.
2214          */
2215 #ifdef S_IWOTH
2216         if ((statbuf.st_mode & S_IWOTH) != 0) {
2217                 fclose(fp);
2218                 fr_strerror_printf("dict_init: Dictionary \"%s\" is globally writable.  Refusing to start due to insecure configuration.",
2219                            fn);
2220                 return -1;
2221         }
2222 #endif
2223
2224         dict_stat_add(&statbuf);
2225
2226         /*
2227          *      Seed the random pool with data.
2228          */
2229         fr_rand_seed(&statbuf, sizeof(statbuf));
2230
2231         block_vendor = 0;
2232
2233         while (fgets(buf, sizeof(buf), fp) != NULL) {
2234                 line++;
2235                 if (buf[0] == '#' || buf[0] == 0 ||
2236                     buf[0] == '\n' || buf[0] == '\r')
2237                         continue;
2238
2239                 /*
2240                  *  Comment characters should NOT be appearing anywhere but
2241                  *  as start of a comment;
2242                  */
2243                 p = strchr(buf, '#');
2244                 if (p) *p = '\0';
2245
2246                 argc = str2argv(buf, argv, MAX_ARGV);
2247                 if (argc == 0) continue;
2248
2249                 if (argc == 1) {
2250                         fr_strerror_printf( "dict_init: %s[%d] invalid entry",
2251                                     fn, line);
2252                         fclose(fp);
2253                         return -1;
2254                 }
2255
2256                 /*
2257                  *      Process VALUE lines.
2258                  */
2259                 if (strcasecmp(argv[0], "VALUE") == 0) {
2260                         if (process_value(fn, line,
2261                                           argv + 1, argc - 1) == -1) {
2262                                 fclose(fp);
2263                                 return -1;
2264                         }
2265                         continue;
2266                 }
2267
2268                 /*
2269                  *      Perhaps this is an attribute.
2270                  */
2271                 if (strcasecmp(argv[0], "ATTRIBUTE") == 0) {
2272                         if (process_attribute(fn, line, block_vendor,
2273                                               block_tlv[which_block_tlv],
2274                                               which_block_tlv,
2275                                               argv + 1, argc - 1) == -1) {
2276                                 fclose(fp);
2277                                 return -1;
2278                         }
2279                         continue;
2280                 }
2281
2282                 /*
2283                  *      See if we need to import another dictionary.
2284                  */
2285                 if (strcasecmp(argv[0], "$INCLUDE") == 0) {
2286                         if (my_dict_init(dir, argv[1], fn, line) < 0) {
2287                                 fclose(fp);
2288                                 return -1;
2289                         }
2290                         continue;
2291                 } /* $INCLUDE */
2292
2293                 /*
2294                  *      Optionally include a dictionary
2295                  */
2296                 if (strcasecmp(argv[0], "$INCLUDE-") == 0) {
2297                         int rcode = my_dict_init(dir, argv[1], fn, line);
2298
2299                         if (rcode == -2) continue;
2300
2301                         if (rcode < 0) {
2302                                 fclose(fp);
2303                                 return -1;
2304                         }
2305                         continue;
2306                 } /* $INCLUDE- */
2307
2308                 if (strcasecmp(argv[0], "VALUE-ALIAS") == 0) {
2309                         if (process_value_alias(fn, line,
2310                                                 argv + 1, argc - 1) == -1) {
2311                                 fclose(fp);
2312                                 return -1;
2313                         }
2314                         continue;
2315                 }
2316
2317                 /*
2318                  *      Process VENDOR lines.
2319                  */
2320                 if (strcasecmp(argv[0], "VENDOR") == 0) {
2321                         if (process_vendor(fn, line,
2322                                            argv + 1, argc - 1) == -1) {
2323                                 fclose(fp);
2324                                 return -1;
2325                         }
2326                         continue;
2327                 }
2328
2329                 if (strcasecmp(argv[0], "BEGIN-TLV") == 0) {
2330                         if (argc != 2) {
2331                                 fr_strerror_printf(
2332                                 "dict_init: %s[%d] invalid BEGIN-TLV entry",
2333                                         fn, line);
2334                                 fclose(fp);
2335                                 return -1;
2336                         }
2337
2338                         da = dict_attrbyname(argv[1]);
2339                         if (!da) {
2340                                 fr_strerror_printf(
2341                                         "dict_init: %s[%d]: unknown attribute %s",
2342                                         fn, line, argv[1]);
2343                                 fclose(fp);
2344                                 return -1;
2345                         }
2346
2347                         if (da->type != PW_TYPE_TLV) {
2348                                 fr_strerror_printf(
2349                                         "dict_init: %s[%d]: attribute %s is not of type tlv",
2350                                         fn, line, argv[1]);
2351                                 fclose(fp);
2352                                 return -1;
2353                         }
2354
2355                         if (which_block_tlv >= MAX_TLV_NEST) {
2356                                 fr_strerror_printf(
2357                                         "dict_init: %s[%d]: TLVs are nested too deep",
2358                                         fn, line);
2359                                 fclose(fp);
2360                                 return -1;
2361                         }
2362
2363
2364                         block_tlv[++which_block_tlv] = da;
2365                         continue;
2366                 } /* BEGIN-TLV */
2367
2368                 if (strcasecmp(argv[0], "END-TLV") == 0) {
2369                         if (argc != 2) {
2370                                 fr_strerror_printf(
2371                                 "dict_init: %s[%d] invalid END-TLV entry",
2372                                         fn, line);
2373                                 fclose(fp);
2374                                 return -1;
2375                         }
2376
2377                         da = dict_attrbyname(argv[1]);
2378                         if (!da) {
2379                                 fr_strerror_printf(
2380                                         "dict_init: %s[%d]: unknown attribute %s",
2381                                         fn, line, argv[1]);
2382                                 fclose(fp);
2383                                 return -1;
2384                         }
2385
2386                         if (da != block_tlv[which_block_tlv]) {
2387                                 fr_strerror_printf(
2388                                         "dict_init: %s[%d]: END-TLV %s does not match any previous BEGIN-TLV",
2389                                         fn, line, argv[1]);
2390                                 fclose(fp);
2391                                 return -1;
2392                         }
2393                         block_tlv[which_block_tlv--] = NULL;
2394                         continue;
2395                 } /* END-VENDOR */
2396
2397                 if (strcasecmp(argv[0], "BEGIN-VENDOR") == 0) {
2398                         if (argc < 2) {
2399                                 fr_strerror_printf(
2400                                 "dict_init: %s[%d] invalid BEGIN-VENDOR entry",
2401                                         fn, line);
2402                                 fclose(fp);
2403                                 return -1;
2404                         }
2405
2406                         vendor = dict_vendorbyname(argv[1]);
2407                         if (!vendor) {
2408                                 fr_strerror_printf(
2409                                         "dict_init: %s[%d]: unknown vendor %s",
2410                                         fn, line, argv[1]);
2411                                 fclose(fp);
2412                                 return -1;
2413                         }
2414
2415                         block_vendor = vendor;
2416
2417                         /*
2418                          *      Check for extended attr VSAs
2419                          *
2420                          *      BEGIN-VENDOR foo format=Foo-Encapsulation-Attr
2421                          */
2422                         if (argc > 2) {
2423                                 if (strncmp(argv[2], "format=", 7) != 0) {
2424                                         fr_strerror_printf(
2425                                                 "dict_init: %s[%d]: Invalid format %s",
2426                                                 fn, line, argv[2]);
2427                                         fclose(fp);
2428                                         return -1;
2429                                 }
2430
2431                                 p = argv[2] + 7;
2432                                 da = dict_attrbyname(p);
2433                                 if (!da) {
2434                                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for BEGIN-VENDOR: unknown attribute \"%s\"",
2435                                                            fn, line, p);
2436                                         fclose(fp);
2437                                         return -1;
2438                                 }
2439
2440                                 if (!da->flags.evs) {
2441                                         fr_strerror_printf("dict_init: %s[%d]: Invalid format for BEGIN-VENDOR.  Attribute \"%s\" is not of \"evs\" data type",
2442                                                            fn, line, p);
2443                                         fclose(fp);
2444                                         return -1;
2445                                 }
2446
2447                                 /*
2448                                  *      Pack the encapsulating
2449                                  *      attribute into the upper 8
2450                                  *      bits of the vendor ID
2451                                  */
2452                                 block_vendor |= da->vendor;
2453                         }
2454
2455                         continue;
2456                 } /* BEGIN-VENDOR */
2457
2458                 if (strcasecmp(argv[0], "END-VENDOR") == 0) {
2459                         if (argc != 2) {
2460                                 fr_strerror_printf(
2461                                 "dict_init: %s[%d] invalid END-VENDOR entry",
2462                                         fn, line);
2463                                 fclose(fp);
2464                                 return -1;
2465                         }
2466
2467                         vendor = dict_vendorbyname(argv[1]);
2468                         if (!vendor) {
2469                                 fr_strerror_printf(
2470                                         "dict_init: %s[%d]: unknown vendor %s",
2471                                         fn, line, argv[1]);
2472                                 fclose(fp);
2473                                 return -1;
2474                         }
2475
2476                         if (vendor != (block_vendor & (FR_MAX_VENDOR - 1))) {
2477                                 fr_strerror_printf(
2478                                         "dict_init: %s[%d]: END-VENDOR %s does not match any previous BEGIN-VENDOR",
2479                                         fn, line, argv[1]);
2480                                 fclose(fp);
2481                                 return -1;
2482                         }
2483                         block_vendor = 0;
2484                         continue;
2485                 } /* END-VENDOR */
2486
2487                 /*
2488                  *      Any other string: We don't recognize it.
2489                  */
2490                 fr_strerror_printf("dict_init: %s[%d] invalid keyword \"%s\"",
2491                            fn, line, argv[0]);
2492                 fclose(fp);
2493                 return -1;
2494         }
2495         fclose(fp);
2496         return 0;
2497 }
2498
2499
2500 /*
2501  *      Empty callback for hash table initialization.
2502  */
2503 static int null_callback(UNUSED void *ctx, UNUSED void *data)
2504 {
2505         return 0;
2506 }
2507
2508
2509 /*
2510  *      Initialize the directory, then fix the attr member of
2511  *      all attributes.
2512  */
2513 int dict_init(char const *dir, char const *fn)
2514 {
2515         /*
2516          *      Check if we need to change anything.  If not, don't do
2517          *      anything.
2518          */
2519         if (dict_stat_check(dir, fn)) {
2520                 return 0;
2521         }
2522
2523         /*
2524          *      Free the dictionaries, and the stat cache.
2525          */
2526         dict_free();
2527
2528         /*
2529          *      Create the table of vendor by name.   There MAY NOT
2530          *      be multiple vendors of the same name.
2531          *
2532          *      Each vendor is malloc'd, so the free function is free.
2533          */
2534         vendors_byname = fr_hash_table_create(dict_vendor_name_hash,
2535                                                 dict_vendor_name_cmp,
2536                                                 fr_pool_free);
2537         if (!vendors_byname) {
2538                 return -1;
2539         }
2540
2541         /*
2542          *      Create the table of vendors by value.  There MAY
2543          *      be vendors of the same value.  If there are, we
2544          *      pick the latest one.
2545          */
2546         vendors_byvalue = fr_hash_table_create(dict_vendor_value_hash,
2547                                                  dict_vendor_value_cmp,
2548                                                  fr_pool_free);
2549         if (!vendors_byvalue) {
2550                 return -1;
2551         }
2552
2553         /*
2554          *      Create the table of attributes by name.   There MAY NOT
2555          *      be multiple attributes of the same name.
2556          *
2557          *      Each attribute is malloc'd, so the free function is free.
2558          */
2559         attributes_byname = fr_hash_table_create(dict_attr_name_hash,
2560                                                    dict_attr_name_cmp,
2561                                                    fr_pool_free);
2562         if (!attributes_byname) {
2563                 return -1;
2564         }
2565
2566         /*
2567          *      Create the table of attributes by value.  There MAY
2568          *      be attributes of the same value.  If there are, we
2569          *      pick the latest one.
2570          */
2571         attributes_byvalue = fr_hash_table_create(dict_attr_value_hash,
2572                                                     dict_attr_value_cmp,
2573                                                     fr_pool_free);
2574         if (!attributes_byvalue) {
2575                 return -1;
2576         }
2577
2578         /*
2579          *      Horrible hacks for combo-IP.
2580          */
2581         attributes_combo = fr_hash_table_create(dict_attr_combo_hash,
2582                                                 dict_attr_combo_cmp,
2583                                                 fr_pool_free);
2584         if (!attributes_combo) {
2585                 return -1;
2586         }
2587
2588         values_byname = fr_hash_table_create(dict_value_name_hash,
2589                                                dict_value_name_cmp,
2590                                                fr_pool_free);
2591         if (!values_byname) {
2592                 return -1;
2593         }
2594
2595         values_byvalue = fr_hash_table_create(dict_value_value_hash,
2596                                                 dict_value_value_cmp,
2597                                                 fr_pool_free);
2598         if (!values_byvalue) {
2599                 return -1;
2600         }
2601
2602         value_fixup = NULL;     /* just to be safe. */
2603
2604         if (my_dict_init(dir, fn, NULL, 0) < 0)
2605                 return -1;
2606
2607         if (value_fixup) {
2608                 DICT_ATTR const *a;
2609                 value_fixup_t *this, *next;
2610
2611                 for (this = value_fixup; this != NULL; this = next) {
2612                         next = this->next;
2613
2614                         a = dict_attrbyname(this->attrstr);
2615                         if (!a) {
2616                                 fr_strerror_printf(
2617                                         "dict_init: No ATTRIBUTE \"%s\" defined for VALUE \"%s\"",
2618                                         this->attrstr, this->dval->name);
2619                                 return -1; /* leak, but they should die... */
2620                         }
2621
2622                         this->dval->attr = a->attr;
2623
2624                         /*
2625                          *      Add the value into the dictionary.
2626                          */
2627                         if (!fr_hash_table_replace(values_byname,
2628                                                      this->dval)) {
2629                                 fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", this->dval->name, a->name);
2630                                 return -1;
2631                         }
2632
2633                         /*
2634                          *      Allow them to use the old name, but
2635                          *      prefer the new name when printing
2636                          *      values.
2637                          */
2638                         if (!fr_hash_table_finddata(values_byvalue, this->dval)) {
2639                                 fr_hash_table_replace(values_byvalue,
2640                                                         this->dval);
2641                         }
2642                         free(this);
2643
2644                         /*
2645                          *      Just so we don't lose track of things.
2646                          */
2647                         value_fixup = next;
2648                 }
2649         }
2650
2651         /*
2652          *      Walk over all of the hash tables to ensure they're
2653          *      initialized.  We do this because the threads may perform
2654          *      lookups, and we don't want multi-threaded re-ordering
2655          *      of the table entries.  That would be bad.
2656          */
2657         fr_hash_table_walk(vendors_byname, null_callback, NULL);
2658         fr_hash_table_walk(vendors_byvalue, null_callback, NULL);
2659
2660         fr_hash_table_walk(attributes_byname, null_callback, NULL);
2661         fr_hash_table_walk(attributes_byvalue, null_callback, NULL);
2662
2663         fr_hash_table_walk(values_byvalue, null_callback, NULL);
2664         fr_hash_table_walk(values_byname, null_callback, NULL);
2665
2666         return 0;
2667 }
2668
2669 static size_t print_attr_oid(char *buffer, size_t size, unsigned int attr,
2670                              int dv_type)
2671 {
2672         int nest;
2673         size_t outlen;
2674         size_t len;
2675
2676         switch (dv_type) {
2677         default:
2678         case 1:
2679                 len = snprintf(buffer, size, "%u", attr & 0xff);
2680                 break;
2681
2682         case 4:
2683                 return snprintf(buffer, size, "%u", attr);
2684
2685         case 2:
2686                 return snprintf(buffer, size, "%u", attr & 0xffff);
2687
2688         }
2689
2690         if ((attr >> 8) == 0) return len;
2691
2692         outlen = len;
2693         buffer += len;
2694         size -= len;
2695
2696         for (nest = 1; nest <= fr_attr_max_tlv; nest++) {
2697                 if (((attr >> fr_attr_shift[nest]) & fr_attr_mask[nest]) == 0) break;
2698
2699                 len = snprintf(buffer, size, ".%u",
2700                                (attr >> fr_attr_shift[nest]) & fr_attr_mask[nest]);
2701
2702                 outlen = len;
2703                 buffer += len;
2704                 size -= len;
2705         }
2706
2707         return outlen;
2708 }
2709
2710 /** Free dynamically allocated (unknown attributes)
2711  *
2712  * If the da was dynamically allocated it will be freed, else the function
2713  * will return without doing anything.
2714  *
2715  * @param da to free.
2716  */
2717 void dict_attr_free(DICT_ATTR const **da)
2718 {
2719         DICT_ATTR **tmp;
2720
2721         if (!da || !*da) return;
2722
2723         /* Don't free real DAs */
2724         if (!(*da)->flags.is_unknown) {
2725                 return;
2726         }
2727
2728         memcpy(&tmp, &da, sizeof(*tmp));
2729         talloc_free(*tmp);
2730
2731         *tmp = NULL;
2732 }
2733
2734
2735 /** Initialises a dictionary attr for unknown attributes
2736  *
2737  * Initialises a dict attr for an unknown attribute/vendor/type without adding
2738  * it to dictionary pools/hashes.
2739  *
2740  * @param[in,out] da struct to initialise, must be at least DICT_ATTR_SIZE bytes.
2741  * @param[in] attr number.
2742  * @param[in] vendor number.
2743  * @return 0 on success.
2744  */
2745 int dict_unknown_from_fields(DICT_ATTR *da, unsigned int attr, unsigned int vendor)
2746 {
2747         char *p;
2748         int dv_type = 1;
2749         size_t len = 0;
2750         size_t bufsize = DICT_ATTR_MAX_NAME_LEN;
2751
2752         memset(da, 0, DICT_ATTR_SIZE);
2753
2754         da->attr = attr;
2755         da->vendor = vendor;
2756         da->type = PW_TYPE_OCTETS;
2757         da->flags.is_unknown = true;
2758         da->flags.is_pointer = true;
2759
2760         /*
2761          *      Unknown attributes of the "WiMAX" vendor get marked up
2762          *      as being for WiMAX.
2763          */
2764         if (vendor == VENDORPEC_WIMAX) {
2765                 da->flags.wimax = 1;
2766         }
2767
2768         p = da->name;
2769
2770         len = snprintf(p, bufsize, "Attr-");
2771         p += len;
2772         bufsize -= len;
2773
2774         if (vendor > FR_MAX_VENDOR) {
2775                 len = snprintf(p, bufsize, "%u.", vendor / FR_MAX_VENDOR);
2776                 p += len;
2777                 bufsize -= len;
2778                 vendor &= (FR_MAX_VENDOR) - 1;
2779         }
2780
2781         if (vendor) {
2782                 DICT_VENDOR *dv;
2783
2784                 /*
2785                  *      dv_type is the length of the vendor's type field
2786                  *      RFC 2865 never defined a mandatory length, so
2787                  *      different vendors have different length type fields.
2788                  */
2789                 dv = dict_vendorbyvalue(vendor);
2790                 if (dv) {
2791                         dv_type = dv->type;
2792                 }
2793                 len = snprintf(p, bufsize, "26.%u.", vendor);
2794
2795                 p += len;
2796                 bufsize -= len;
2797         }
2798
2799         print_attr_oid(p, bufsize , attr, dv_type);
2800
2801         return 0;
2802 }
2803
2804 /** Allocs a dictionary attr for unknown attributes
2805  *
2806  * Allocs a dict attr for an unknown attribute/vendor/type without adding
2807  * it to dictionary pools/hashes.
2808  *
2809  * @param[in] ctx to allocate DA in.
2810  * @param[in] attr number.
2811  * @param[in] vendor number.
2812  * @return 0 on success.
2813  */
2814 DICT_ATTR const *dict_unknown_afrom_fields(TALLOC_CTX *ctx, unsigned int attr, unsigned int vendor)
2815 {
2816         uint8_t *p;
2817         DICT_ATTR *da;
2818
2819         p = talloc_zero_array(ctx, uint8_t, DICT_ATTR_SIZE);
2820         if (!p) {
2821                 fr_strerror_printf("Out of memory");
2822                 return NULL;
2823         }
2824         da = (DICT_ATTR *) p;
2825         talloc_set_type(da, DICT_ATTR);
2826
2827         if (dict_unknown_from_fields(da, attr, vendor) < 0) {
2828                 talloc_free(p);
2829                 return NULL;
2830         }
2831
2832         return da;
2833 }
2834
2835 /** Create a DICT_ATTR from an ASCII attribute and value
2836  *
2837  * Where the attribute name is in the form:
2838  *  - Attr-%d
2839  *  - Attr-%d.%d.%d...
2840  *  - Vendor-%d-Attr-%d
2841  *  - VendorName-Attr-%d
2842  *
2843  * @param[in] da to initialise.
2844  * @param[in] name of attribute.
2845  * @return 0 on success -1 on failure.
2846  */
2847 int dict_unknown_from_str(DICT_ATTR *da, char const *name)
2848 {
2849         unsigned int    attr, vendor = 0;
2850         unsigned int    dv_type = 1;    /* The type of vendor field */
2851
2852         char const      *p = name;
2853         char            *q;
2854
2855         DICT_VENDOR     *dv;
2856         DICT_ATTR const *found;
2857
2858         if (dict_valid_name(name) < 0) return -1;
2859
2860         /*
2861          *      Pull off vendor prefix first.
2862          */
2863         if (strncasecmp(p, "Attr-", 5) != 0) {
2864                 if (strncasecmp(p, "Vendor-", 7) == 0) {
2865                         vendor = (int) strtol(p + 7, &q, 10);
2866                         if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
2867                                 fr_strerror_printf("Invalid vendor value in attribute name \"%s\"", name);
2868
2869                                 return -1;
2870                         }
2871
2872                         p = q;
2873
2874                 /* must be vendor name */
2875                 } else {
2876                         char buffer[256];
2877
2878                         q = strchr(p, '-');
2879
2880                         if (!q) {
2881                                 fr_strerror_printf("Invalid vendor name in attribute name \"%s\"", name);
2882                                 return -1;
2883                         }
2884
2885                         if ((size_t) (q - p) >= sizeof(buffer)) {
2886                                 fr_strerror_printf("Vendor name too long in attribute name \"%s\"", name);
2887
2888                                 return -1;
2889                         }
2890
2891                         memcpy(buffer, p, (q - p));
2892                         buffer[q - p] = '\0';
2893
2894                         vendor = dict_vendorbyname(buffer);
2895                         if (!vendor) {
2896                                 fr_strerror_printf("Unknown name \"%s\"", name);
2897
2898                                 return -1;
2899                         }
2900
2901                         p = q;
2902                 }
2903
2904                 if (*p != '-') {
2905                         fr_strerror_printf("Invalid text following vendor definition in attribute name \"%s\"", name);
2906
2907                         return -1;
2908                 }
2909                 p++;
2910         }
2911
2912         /*
2913          *      Attr-%d
2914          */
2915         if (strncasecmp(p, "Attr-", 5) != 0) {
2916                 fr_strerror_printf("Unknown attribute \"%s\"", name);
2917
2918                 return -1;
2919         }
2920
2921         attr = strtol(p + 5, &q, 10);
2922
2923         /*
2924          *      Invalid name.
2925          */
2926         if (attr == 0) {
2927                 fr_strerror_printf("Invalid value in attribute name \"%s\"", name);
2928
2929                 return -1;
2930         }
2931
2932         p = q;
2933
2934         /*
2935          *      Vendor-%d-Attr-%d
2936          *      VendorName-Attr-%d
2937          *      Attr-%d
2938          *      Attr-%d.
2939          *
2940          *      Anything else is invalid.
2941          */
2942         if (((vendor != 0) && (*p != '\0')) ||
2943             ((vendor == 0) && *p && (*p != '.'))) {
2944         invalid:
2945                 fr_strerror_printf("Invalid OID");
2946                 return -1;
2947         }
2948
2949         /*
2950          *      Look for OIDs.  Require the "Attr-26.Vendor-Id.type"
2951          *      format, and disallow "Vendor-%d-Attr-%d" and
2952          *      "VendorName-Attr-%d"
2953          *
2954          *      This section parses the Vendor-Id portion of
2955          *      Attr-%d.%d.  where the first number is 26, *or* an
2956          *      extended name of the "evs" foundta type.
2957          */
2958         if (*p == '.') {
2959                 found = dict_attrbyvalue(attr, 0);
2960                 if (!found) {
2961                         fr_strerror_printf("Cannot parse names without dictionaries");
2962
2963                         return -1;
2964                 }
2965
2966                 if ((attr != PW_VENDOR_SPECIFIC) &&
2967                     !(found->flags.extended || found->flags.long_extended)) {
2968                         fr_strerror_printf("Standard attributes cannot use OIDs");
2969
2970                         return -1;
2971                 }
2972
2973                 if ((attr == PW_VENDOR_SPECIFIC) || found->flags.evs) {
2974                         vendor = strtol(p + 1, &q, 10);
2975                         if ((vendor == 0) || (vendor > FR_MAX_VENDOR)) {
2976                                 fr_strerror_printf("Invalid vendor");
2977
2978                                 return -1;
2979                         }
2980
2981                         if (*q != '.') goto invalid;
2982
2983                         p = q;
2984
2985                         if (found->flags.evs) vendor |= attr * FR_MAX_VENDOR;
2986                         attr = 0;
2987                 } /* else the second number is a TLV number */
2988         }
2989
2990         /*
2991          *      Get the expected maximum size of the name.
2992          */
2993         if (vendor) {
2994                 dv = dict_vendorbyvalue(vendor & (FR_MAX_VENDOR - 1));
2995                 if (dv) {
2996                         dv_type = dv->type;
2997                         if (dv_type > 3) dv_type = 3; /* hack */
2998                 }
2999         }
3000
3001         /*
3002          *      Parse the next number.  It could be a Vendor-Type
3003          *      of 1..2^24, or it could be a TLV.
3004          */
3005         if (*p == '.') {
3006                 attr = strtol(p + 1, &q, 10);
3007                 if (attr == 0) {
3008                         fr_strerror_printf("Invalid name number");
3009                         return -1;
3010                 }
3011
3012                 if (*q) {
3013                         if (*q != '.') {
3014                                 goto invalid;
3015                         }
3016
3017                         if (dv_type != 1) {
3018                                 goto invalid;
3019                         }
3020                 }
3021
3022                 p = q;
3023         }
3024
3025         /*
3026          *      Enforce a maximum value on the attribute number.
3027          */
3028         if ((vendor > 0) && (attr >= (unsigned) (1 << (dv_type << 3)))) goto invalid;
3029
3030         if (*p == '.') {
3031                 if (dict_str2oid(p + 1, &attr, &vendor, 1) < 0) {
3032                         return -1;
3033                 }
3034         }
3035
3036         /*
3037          *      If the caller doesn't provide a DICT_ATTR
3038          *      we can't call dict_unknown_from_fields.
3039          */
3040         if (!da) {
3041                 fr_strerror_printf("Unknown attributes disallowed");
3042                 return -1;
3043         }
3044
3045         return dict_unknown_from_fields(da, attr, vendor);
3046 }
3047
3048 /** Create a DICT_ATTR from an ASCII attribute and value
3049  *
3050  * Where the attribute name is in the form:
3051  *  - Attr-%d
3052  *  - Attr-%d.%d.%d...
3053  *  - Vendor-%d-Attr-%d
3054  *  - VendorName-Attr-%d
3055  *
3056  * @param[in] ctx to alloc new attribute in.
3057  * @param[in] name of attribute.
3058  * @return 0 on success -1 on failure.
3059  */
3060 DICT_ATTR const *dict_unknown_afrom_str(TALLOC_CTX *ctx, char const *name)
3061 {
3062         uint8_t *p;
3063         DICT_ATTR *da;
3064
3065         p = talloc_zero_array(ctx, uint8_t, DICT_ATTR_SIZE);
3066         if (!p) {
3067                 fr_strerror_printf("Out of memory");
3068                 return NULL;
3069         }
3070         da = (DICT_ATTR *) p;
3071         talloc_set_type(da, DICT_ATTR);
3072
3073         if (dict_unknown_from_str(da, name) < 0) {
3074                 talloc_free(p);
3075                 return NULL;
3076         }
3077
3078         return da;
3079 }
3080
3081 /** Create a dictionary attribute by name embedded in another string
3082  *
3083  * Find the first invalid attribute name char in the string pointed
3084  * to by name.
3085  *
3086  * Copy the characters between the start of the name string and the first
3087  * none dict_attr_allowed_char to a buffer and initialise da as an
3088  * unknown attribute.
3089  *
3090  * @param[out] da to initialise.
3091  * @param[in,out] name string start.
3092  * @return 0 on success or -1 on error;
3093  */
3094 int dict_unknown_from_substr(DICT_ATTR *da, char const **name)
3095 {
3096         char const *p;
3097         size_t len;
3098         char buffer[DICT_ATTR_MAX_NAME_LEN + 1];
3099
3100         if (!name || !*name) return -1;
3101
3102         /*
3103          *      Advance p until we get something that's not part of
3104          *      the dictionary attribute name.
3105          */
3106         for (p = *name; dict_attr_allowed_chars[(int) *p] || (*p == '.' ) || (*p == '-'); p++);
3107
3108         len = p - *name;
3109         if (len > DICT_ATTR_MAX_NAME_LEN) {
3110                 fr_strerror_printf("Attribute name too long");
3111
3112                 return -1;
3113         }
3114         if (len == 0) {
3115                 fr_strerror_printf("Invalid attribute name");
3116                 return -1;
3117         }
3118         strlcpy(buffer, *name, len + 1);
3119
3120         if (dict_unknown_from_str(da, buffer) < 0) return -1;
3121
3122         *name = p;
3123
3124         return 0;
3125 }
3126
3127 /*
3128  *      Get an attribute by its numerical value.
3129  */
3130 DICT_ATTR const *dict_attrbyvalue(unsigned int attr, unsigned int vendor)
3131 {
3132         DICT_ATTR da;
3133
3134         if ((attr > 0) && (attr < 256) && !vendor) return dict_base_attrs[attr];
3135
3136         da.attr = attr;
3137         da.vendor = vendor;
3138
3139         return fr_hash_table_finddata(attributes_byvalue, &da);
3140 }
3141
3142
3143 /** Get an attribute by its numerical value and data type
3144  *
3145  * Used only for COMBO_IP
3146  *
3147  * @return The attribute, or NULL if not found
3148  */
3149 DICT_ATTR const *dict_attrbytype(unsigned int attr, unsigned int vendor,
3150                                  PW_TYPE type)
3151 {
3152         DICT_ATTR da;
3153
3154         da.attr = attr;
3155         da.vendor = vendor;
3156         da.type = type;
3157
3158         return fr_hash_table_finddata(attributes_combo, &da);
3159 }
3160
3161 /** Using a parent and attr/vendor, find a child attr/vendor
3162  *
3163  */
3164 int dict_attr_child(DICT_ATTR const *parent,
3165                     unsigned int *pattr, unsigned int *pvendor)
3166 {
3167         unsigned int attr, vendor;
3168         DICT_ATTR da;
3169
3170         if (!parent || !pattr || !pvendor) return false;
3171
3172         attr = *pattr;
3173         vendor = *pvendor;
3174
3175         /*
3176          *      Only some types can have children
3177          */
3178         switch (parent->type) {
3179         default: return false;
3180
3181         case PW_TYPE_VSA:
3182         case PW_TYPE_TLV:
3183         case PW_TYPE_EVS:
3184         case PW_TYPE_EXTENDED:
3185         case PW_TYPE_LONG_EXTENDED:
3186           break;
3187         }
3188
3189         if ((vendor == 0) && (parent->vendor != 0)) return false;
3190
3191         /*
3192          *      Bootstrap by starting off with the parents values.
3193          */
3194         da.attr = parent->attr;
3195         da.vendor = parent->vendor;
3196
3197         /*
3198          *      Do various butchery to insert the "attr" value.
3199          *
3200          *      00VID   000000AA        normal VSA for vendor VID
3201          *      00VID   DDCCBBAA        normal VSAs with TLVs
3202          *      EE000   000000AA        extended attr (241.1)
3203          *      EE000   DDCCBBAA        extended attr with TLVs
3204          *      EEVID   000000AA        EVS with vendor VID, attr AAA
3205          *      EEVID   DDCCBBAA        EVS with TLVs
3206          */
3207         if (!da.vendor) {
3208                 da.vendor = parent->attr * FR_MAX_VENDOR;
3209                 da.vendor |= vendor;
3210                 da.attr = attr;
3211
3212         } else {
3213                 int i;
3214
3215                 /*
3216                  *      Trying to nest too deep.  It's an error
3217                  */
3218                 if (parent->attr & (fr_attr_mask[MAX_TLV_NEST] << fr_attr_shift[MAX_TLV_NEST])) {
3219                         return false;
3220                 }
3221
3222                 for (i = MAX_TLV_NEST - 1; i >= 0; i--) {
3223                         if ((parent->attr & (fr_attr_mask[i] << fr_attr_shift[i]))) {
3224                                 da.attr |= (attr & fr_attr_mask[i + 1]) << fr_attr_shift[i + 1];
3225                                 goto find;
3226                         }
3227                 }
3228
3229                 return false;
3230         }
3231
3232 find:
3233 #if 0
3234         fprintf(stderr, "LOOKING FOR %08x %08x + %08x %08x --> %08x %08x\n",
3235                 parent->vendor, parent->attr, attr, vendor,
3236                 da.vendor, da.attr);
3237 #endif
3238
3239         *pattr = da.attr;
3240         *pvendor = da.vendor;
3241         return true;
3242 }
3243
3244 /*
3245  *      Get an attribute by it's numerical value, and the parent
3246  */
3247 DICT_ATTR const *dict_attrbyparent(DICT_ATTR const *parent, unsigned int attr, unsigned int vendor)
3248 {
3249         unsigned int my_attr, my_vendor;
3250         DICT_ATTR da;
3251
3252         my_attr = attr;
3253         my_vendor = vendor;
3254
3255         if (!dict_attr_child(parent, &my_attr, &my_vendor)) return NULL;
3256
3257         da.attr = my_attr;
3258         da.vendor = my_vendor;
3259
3260         return fr_hash_table_finddata(attributes_byvalue, &da);
3261 }
3262
3263
3264 /*
3265  *      Get an attribute by its name.
3266  */
3267 DICT_ATTR const *dict_attrbyname(char const *name)
3268 {
3269         DICT_ATTR *da;
3270         uint32_t buffer[(sizeof(*da) + DICT_ATTR_MAX_NAME_LEN + 3)/4];
3271
3272         if (!name) return NULL;
3273
3274         da = (DICT_ATTR *) buffer;
3275         strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1);
3276
3277         return fr_hash_table_finddata(attributes_byname, da);
3278 }
3279
3280 /** Look up a dictionary attribute by name embedded in another string
3281  *
3282  * Find the first invalid attribute name char in the string pointed
3283  * to by name.
3284  *
3285  * Copy the characters between the start of the name string and the first
3286  * none dict_attr_allowed_char to a buffer and perform a dictionary lookup
3287  * using that value.
3288  *
3289  * If the attribute exists, advance the pointer pointed to by name
3290  * to the first none dict_attr_allowed_char char, and return the DA.
3291  *
3292  * If the attribute does not exist, don't advance the pointer and return
3293  * NULL.
3294  *
3295  * @param[in,out] name string start.
3296  * @return NULL if no attributes matching the name could be found, else
3297  */
3298 DICT_ATTR const *dict_attrbyname_substr(char const **name)
3299 {
3300         DICT_ATTR *find;
3301         DICT_ATTR const *da;
3302         char const *p;
3303         size_t len;
3304         uint32_t buffer[(sizeof(*find) + DICT_ATTR_MAX_NAME_LEN + 3)/4];
3305
3306         if (!name || !*name) return NULL;
3307
3308         find = (DICT_ATTR *) buffer;
3309
3310         /*
3311          *      Advance p until we get something that's not part of
3312          *      the dictionary attribute name.
3313          */
3314         for (p = *name; dict_attr_allowed_chars[(int) *p]; p++);
3315
3316         len = p - *name;
3317         if (len > DICT_ATTR_MAX_NAME_LEN) {
3318                 fr_strerror_printf("Attribute name too long");
3319
3320                 return NULL;
3321         }
3322         strlcpy(find->name, *name, len + 1);
3323
3324         da = fr_hash_table_finddata(attributes_byname, find);
3325         if (!da) {
3326                 fr_strerror_printf("Unknown attribute \"%s\"", find->name);
3327                 return NULL;
3328         }
3329         *name = p;
3330
3331         return da;
3332 }
3333
3334 /*
3335  *      Associate a value with an attribute and return it.
3336  */
3337 DICT_VALUE *dict_valbyattr(unsigned int attr, unsigned int vendor, int value)
3338 {
3339         DICT_VALUE dval, *dv;
3340
3341         /*
3342          *      First, look up aliases.
3343          */
3344         dval.attr = attr;
3345         dval.vendor = vendor;
3346         dval.name[0] = '\0';
3347
3348         /*
3349          *      Look up the attribute alias target, and use
3350          *      the correct attribute number if found.
3351          */
3352         dv = fr_hash_table_finddata(values_byname, &dval);
3353         if (dv) dval.attr = dv->value;
3354
3355         dval.value = value;
3356
3357         return fr_hash_table_finddata(values_byvalue, &dval);
3358 }
3359
3360 /*
3361  *      Associate a value with an attribute and return it.
3362  */
3363 char const *dict_valnamebyattr(unsigned int attr, unsigned int vendor, int value)
3364 {
3365         DICT_VALUE *dv;
3366
3367         dv = dict_valbyattr(attr, vendor, value);
3368         if (!dv) return "";
3369
3370         return dv->name;
3371 }
3372
3373 /*
3374  *      Get a value by its name, keyed off of an attribute.
3375  */
3376 DICT_VALUE *dict_valbyname(unsigned int attr, unsigned int vendor, char const *name)
3377 {
3378         DICT_VALUE *my_dv, *dv;
3379         uint32_t buffer[(sizeof(*my_dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4];
3380
3381         if (!name) return NULL;
3382
3383         my_dv = (DICT_VALUE *) buffer;
3384         my_dv->attr = attr;
3385         my_dv->vendor = vendor;
3386         my_dv->name[0] = '\0';
3387
3388         /*
3389          *      Look up the attribute alias target, and use
3390          *      the correct attribute number if found.
3391          */
3392         dv = fr_hash_table_finddata(values_byname, my_dv);
3393         if (dv) my_dv->attr = dv->value;
3394
3395         strlcpy(my_dv->name, name, DICT_VALUE_MAX_NAME_LEN + 1);
3396
3397         return fr_hash_table_finddata(values_byname, my_dv);
3398 }
3399
3400 /*
3401  *      Get the vendor PEC based on the vendor name
3402  *
3403  *      This is efficient only for small numbers of vendors.
3404  */
3405 int dict_vendorbyname(char const *name)
3406 {
3407         DICT_VENDOR *dv;
3408         size_t buffer[(sizeof(*dv) + DICT_VENDOR_MAX_NAME_LEN + sizeof(size_t) - 1) / sizeof(size_t)];
3409
3410         if (!name) return 0;
3411
3412         dv = (DICT_VENDOR *) buffer;
3413         strlcpy(dv->name, name, DICT_VENDOR_MAX_NAME_LEN + 1);
3414
3415         dv = fr_hash_table_finddata(vendors_byname, dv);
3416         if (!dv) return 0;
3417
3418         return dv->vendorpec;
3419 }
3420
3421 /*
3422  *      Return the vendor struct based on the PEC.
3423  */
3424 DICT_VENDOR *dict_vendorbyvalue(int vendorpec)
3425 {
3426         DICT_VENDOR dv;
3427
3428         dv.vendorpec = vendorpec;
3429
3430         return fr_hash_table_finddata(vendors_byvalue, &dv);
3431 }
3432
3433 /** Converts an unknown to a known by adding it to the internal dictionaries.
3434  *
3435  * Does not free old DICT_ATTR, that is left up to the caller.
3436  *
3437  * @param old unknown attribute to add.
3438  * @return existing DICT_ATTR if old was found in a dictionary, else the new entry in the dictionary
3439  *         representing old.
3440  */
3441 DICT_ATTR const *dict_unknown_add(DICT_ATTR const *old)
3442 {
3443         DICT_ATTR const *da, *parent;
3444         ATTR_FLAGS flags;
3445
3446         if (!old) return NULL;
3447
3448         if (!old->flags.is_unknown) return old;
3449
3450         da = dict_attrbyvalue(old->attr, old->vendor);
3451         if (da) return da;
3452
3453         memcpy(&flags, &old->flags, sizeof(flags));
3454         flags.is_unknown = false;
3455
3456         parent = dict_parent(old->attr, old->vendor);
3457         if (parent) {
3458                 if (parent->flags.has_tlv) flags.is_tlv = true;
3459                 flags.evs = parent->flags.evs;
3460                 flags.extended = parent->flags.extended;
3461                 flags.long_extended = parent->flags.long_extended;
3462         }
3463
3464         if (dict_addattr(old->name, old->attr, old->vendor, old->type, flags) < 0) {
3465                 return NULL;
3466         }
3467
3468         da = dict_attrbyvalue(old->attr, old->vendor);
3469         return da;
3470 }