1 /* This file is part of GNU Radius.
2 Copyright (C) 2000,2001,2002,2003,2004,2005,
3 2006,2007,2008 Free Software Foundation, Inc.
4
5 Written by Sergey Poznyakoff
6
7 GNU Radius is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Radius is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public
18 License along with GNU Radius; if not, write to the Free
19 Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301 USA. */
21
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <pwd.h>
30 #include <ctype.h>
31
32 #include <radlib.h>
33
34 #ifndef DICT_INDEX_SIZE
35 # define DICT_INDEX_SIZE 2048
36 #endif
37
38 enum dict_symbol_type {
39 dict_symbol_uninitialized,
40 dict_symbol_attribute,
41 dict_symbol_alias
42 };
43
44 typedef struct dict_symbol DICT_SYMBOL;
45 struct dict_symbol {
46 DICT_SYMBOL *next; /* Link to the next attribute */
47 char *name;
48 enum dict_symbol_type type; /* Type of the entry */
49 union {
50 grad_dict_attr_t attr;
51 grad_dict_attr_t *alias;
52 } v;
53 };
54
55 static grad_symtab_t *dict_attr_tab;
56 static grad_dict_attr_t *dict_attr_index[DICT_INDEX_SIZE];
57 static grad_list_t /* of grad_dict_value_t */ *dictionary_values;
58 static grad_list_t /* of grad_dict_vendor_t */ *dictionary_vendors;
59 static int vendorno;
60
61
62 static grad_dict_attr_t *
dict_symbol_ptr(DICT_SYMBOL * sym)63 dict_symbol_ptr(DICT_SYMBOL *sym)
64 {
65 switch (sym->type) {
66 case dict_symbol_uninitialized:
67 grad_insist_fail("uninitialized dictionary symbol found!");
68 break;
69
70 case dict_symbol_attribute:
71 return &sym->v.attr;
72
73 case dict_symbol_alias:
74 return sym->v.alias;
75 }
76 }
77
78 static grad_dict_attr_t *
dict_attr_lookup(const char * ident)79 dict_attr_lookup(const char *ident)
80 {
81 DICT_SYMBOL *sym = grad_sym_lookup(dict_attr_tab, ident);
82 if (sym)
83 return dict_symbol_ptr(sym);
84
85 return NULL;
86 }
87
88 /* ************************************************************************ */
89
90 static int
free_vendor(void * ptr,void * closure ARG_UNUSED)91 free_vendor(void *ptr, void *closure ARG_UNUSED)
92 {
93 grad_dict_vendor_t *vp = ptr;
94 if (vp->vendorname)
95 grad_free(vp->vendorname);
96 grad_free(vp);
97 return 0;
98 }
99
100 static int
free_value(void * ptr,void * closure ARG_UNUSED)101 free_value(void *ptr, void *closure ARG_UNUSED)
102 {
103 grad_dict_value_t *vp = ptr;
104 grad_free(vp->name);
105 grad_free(vp);
106 return 0;
107 }
108
109 void
dict_free()110 dict_free()
111 {
112 grad_symtab_free(&dict_attr_tab);
113 memset(dict_attr_index, 0, sizeof dict_attr_index);
114
115 grad_list_destroy(&dictionary_values, free_value, NULL);
116 grad_list_destroy(&dictionary_vendors, free_vendor, NULL);
117 }
118
119 static int
nfields(int fc,int minf,int maxf,grad_locus_t * loc)120 nfields(int fc, int minf, int maxf, grad_locus_t *loc)
121 {
122 if (fc < minf) {
123 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("too few fields"));
124 return -1;
125 } else if (maxf != -1 && fc > maxf) {
126 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("too many fields"));
127 return -1;
128 }
129 return 0;
130 }
131
132 /*
133 * Add vendor to the list.
134 */
135 static int
addvendor(char * name,int value)136 addvendor(char *name, int value)
137 {
138 grad_dict_vendor_t *vval;
139
140 vval = grad_emalloc(sizeof(grad_dict_vendor_t));
141
142 vval->vendorname = grad_estrdup(name);
143 vval->vendorpec = value;
144 vval->vendorcode = vendorno++;
145 if (!dictionary_vendors)
146 dictionary_vendors = grad_list_create();
147 grad_list_prepend(dictionary_vendors, vval);
148
149 return 0;
150 }
151
152 /* **************************************************************************
153 Parser table for built-in abinary attributes
154 */
155
156 typedef struct attr_parser_tab ATTR_PARSER_TAB;
157 struct attr_parser_tab {
158 ATTR_PARSER_TAB *next;
159 int attr;
160 grad_attr_parser_fp fun;
161 };
162 static ATTR_PARSER_TAB *attr_parser_tab;
163
164 static grad_attr_parser_fp
dict_find_parser(int attr)165 dict_find_parser(int attr)
166 {
167 ATTR_PARSER_TAB *ep;
168 for (ep = attr_parser_tab; ep; ep = ep->next)
169 if (ep->attr == attr)
170 return ep->fun;
171 return NULL;
172 }
173
174 void
dict_register_parser(int attr,grad_attr_parser_fp fun)175 dict_register_parser(int attr, grad_attr_parser_fp fun)
176 {
177 ATTR_PARSER_TAB *e = grad_emalloc(sizeof(*e));
178 e->attr = attr;
179 e->fun = fun;
180 e->next = attr_parser_tab;
181 attr_parser_tab = e;
182 }
183
184 static void
parser_tab_init()185 parser_tab_init()
186 {
187 if (!attr_parser_tab) {
188 /* Register ascend filters */
189 dict_register_parser(242, grad_ascend_parse_filter);
190 dict_register_parser(243, grad_ascend_parse_filter);
191 }
192 }
193
194 static void
parser_tab_free()195 parser_tab_free()
196 {
197 ATTR_PARSER_TAB *ep = attr_parser_tab;
198
199 while (ep) {
200 ATTR_PARSER_TAB *next = ep->next;
201 grad_free(ep);
202 ep = next;
203 }
204 attr_parser_tab = NULL;
205 }
206
207 /* **************************************************************************
208 * Parser
209 */
210 static int parse_dict(char *name);
211
212 #define KEYWORD fv[0]
213 #define ATTR_NAME fv[1]
214 #define ATTR_VALUE fv[2]
215 #define ATTR_TYPE fv[3]
216 #define ATTR_VENDOR fv[4]
217 #define ATTR_FLAGS ((fc == 6) ? fv[5] : fv[4])
218 #define HAS_VENDOR(c,p) ((c>=5) && strcmp(p[4],"-") && p[4][0] != '[')
219 #define HAS_FLAGS(c,p) ((c==6) || (c==5 && p[4][0] == '['))
220 #define VALUE_ATTR fv[1]
221 #define VALUE_NAME fv[2]
222 #define VALUE_NUM fv[3]
223 #define VENDOR_NAME fv[1]
224 #define VENDOR_VALUE fv[2]
225
226 static grad_keyword_t type_kw[] = {
227 { "string", GRAD_TYPE_STRING },
228 { "integer", GRAD_TYPE_INTEGER },
229 { "ipaddr", GRAD_TYPE_IPADDR },
230 { "date", GRAD_TYPE_DATE }
231 };
232
233 struct parse_data {
234 int vendor;
235 grad_locus_t begin_locus;
236 int errcnt;
237 };
238
239 /*ARGSUSED*/
240 static int
_dict_include(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)241 _dict_include(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
242 {
243 if (nfields(fc, 2, 2, loc))
244 return 0;
245 parse_dict(fv[1]);
246 return 0;
247 }
248
249 static int
parse_flags(char ** ptr,int * flags,grad_locus_t * loc)250 parse_flags(char **ptr, int *flags, grad_locus_t *loc)
251 {
252 int i;
253 char *p;
254
255 for (p = *ptr+1, i = 0; i < GRAD_CF_MAX; i++) {
256 if (*p == 0) {
257 grad_log_loc(GRAD_LOG_ERR, loc, _("missing ]"), *p);
258 return 1;
259 }
260 switch (*p++) {
261 case 'C':
262 case 'L':
263 *flags |= GRAD_AF_LHS(i);
264 break;
265 case '-':
266 *flags &= ~GRAD_AF_LHS(i);
267 break;
268 case ']':
269 p--;
270 goto stop;
271 default:
272 grad_log_loc(GRAD_LOG_ERR, loc,
273 _("invalid syntax flag %c"),
274 p[-1]);
275 return 1;
276 }
277 switch (*p++) {
278 case 'R':
279 *flags |= GRAD_AF_RHS(i);
280 break;
281 case '-':
282 *flags &= ~GRAD_AF_RHS(i);
283 break;
284 default:
285 grad_log_loc(GRAD_LOG_ERR, loc,
286 _("invalid syntax flag %c"),
287 p[-1]);
288 return 1;
289 }
290 }
291 stop:
292 for (; i < GRAD_CF_MAX; i++)
293 *flags |= GRAD_AF_LHS(i)|GRAD_AF_RHS(i);
294 *ptr = p;
295 return 0;
296 }
297
298 static int
parse_attr_properties(grad_locus_t * loc,char * str,int * flags,int * prop)299 parse_attr_properties(grad_locus_t *loc, char *str, int *flags, int *prop)
300 {
301 int errcnt = 0;
302 char *p;
303
304 for (p = str; *p; p++) {
305 switch (*p) {
306 case 'C':
307 case 'L':
308 *flags |= GRAD_AF_LHS(GRAD_CF_USERS)
309 |GRAD_AF_LHS(GRAD_CF_HINTS)
310 |GRAD_AF_LHS(GRAD_CF_HUNTGROUPS);
311 break;
312 case 'R':
313 *flags |= GRAD_AF_RHS(GRAD_CF_USERS)
314 |GRAD_AF_RHS(GRAD_CF_HINTS)
315 |GRAD_AF_RHS(GRAD_CF_HUNTGROUPS);
316 break;
317 case '[':
318 if (parse_flags(&p, flags, loc)) {
319 while (*++p);
320 --p;
321 errcnt++;
322 }
323 break;
324 case '=':
325 GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_REPLACE);
326 break;
327 case '+':
328 GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_APPEND);
329 break;
330 case 'N':
331 GRAD_SET_ADDITIVITY(*prop, GRAD_AP_ADD_NONE);
332 break;
333 case 'P':
334 *prop |= GRAD_AP_PROPAGATE;
335 break;
336 case 'l':
337 *flags &= ~GRAD_AP_INTERNAL;
338 break;
339 case '1':
340 case '2':
341 case '3':
342 case '4':
343 case '5':
344 case '6':
345 case '7':
346 case '8':
347 case '9':
348 *prop |= GRAD_AP_USER_FLAG(*p-'0');
349 break;
350 case 'b':
351 *prop |= GRAD_AP_BINARY_STRING;
352 break;
353 case 'E':
354 *prop |= GRAD_AP_ENCRYPT_RFC2138;
355 break;
356 case 'T':
357 *prop |= GRAD_AP_ENCRYPT_RFC2868;
358 break;
359 case 'c':
360 /* Retained for compatibility */
361 break;
362 default:
363 grad_log_loc(GRAD_LOG_ERR, loc,
364 _("invalid flag %c"),
365 *p);
366 errcnt++;
367 break;
368 }
369 }
370 return errcnt;
371 }
372
373 static void
set_default_attr_properties(int value,int * flags,int * prop)374 set_default_attr_properties(int value, int *flags, int *prop)
375 {
376 *flags = GRAD_AF_DEFAULT_FLAGS;
377 *prop = GRAD_AP_DEFAULT_ADD;
378
379 if (GRAD_VENDOR_CODE(value) == 0) {
380 if (value > 255)
381 *flags |= GRAD_AP_INTERNAL;
382 /* FIXME: A temporary hack until all users update
383 their dictionaries */
384 else if (value == DA_USER_PASSWORD
385 || value == DA_USER_PASSWORD)
386 *prop |= GRAD_AP_ENCRYPT_RFC2138;
387 }
388 }
389
390 static int
_dict_attribute(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)391 _dict_attribute(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
392 {
393 DICT_SYMBOL *sym;
394 grad_dict_attr_t *attr;
395 int type;
396 int vendor = 0;
397 unsigned value;
398 char *p;
399 grad_attr_parser_fp fp = NULL;
400 int flags;
401 int prop;
402
403 if (nfields(fc, 4, 6, loc))
404 return 0;
405
406 GRAD_DEBUG7(100,
407 "%s:%lu: ATTR_NAME=%s ATTR_VALUE=%s ATTR_TYPE=%s ATTR_VENDOR=%s ATTR_FLAGS=%s",
408 loc->file, loc->line,
409 ATTR_NAME,ATTR_VALUE,ATTR_TYPE,
410 HAS_VENDOR(fc, fv) ? ATTR_VENDOR : pd->vendor ? "BLOCK" : "N/A",
411 HAS_FLAGS(fc,fv) ? ATTR_FLAGS : "N/A");
412
413 /*
414 * Validate all entries
415 */
416
417 value = strtol(ATTR_VALUE, &p, 0);
418 if (*p) {
419 grad_log_loc(GRAD_LOG_ERR, loc,
420 _("value not a number (near %s)"),
421 p);
422 pd->errcnt++;
423 return 0;
424 }
425
426 if (strcmp(ATTR_TYPE, "abinary") == 0) {
427 type = GRAD_TYPE_STRING;
428 fp = dict_find_parser(value);
429 if (!fp) {
430 grad_log_loc(GRAD_LOG_WARN, loc,
431 _("no parser registered for this attribute"));
432 return 0;
433 }
434 } else
435 type = grad_xlat_keyword(type_kw, ATTR_TYPE, GRAD_TYPE_INVALID);
436
437 if (type == GRAD_TYPE_INVALID) {
438 grad_log_loc(GRAD_LOG_ERR, loc,
439 "%s",
440 _("invalid type"));
441 pd->errcnt++;
442 return 0;
443 }
444
445 if (HAS_VENDOR(fc, fv)) {
446 if ((vendor = grad_vendor_name_to_id(ATTR_VENDOR)) == 0) {
447 grad_log_loc(GRAD_LOG_ERR, loc, _("unknown vendor"));
448 pd->errcnt++;
449 return 0;
450 }
451 } else if (pd->vendor)
452 vendor = pd->vendor;
453
454 value |= (vendor << 16);
455
456 set_default_attr_properties(value, &flags, &prop);
457
458 if (HAS_FLAGS(fc,fv)) {
459 int rc = parse_attr_properties(loc, ATTR_FLAGS, &flags, &prop);
460 if (rc) {
461 pd->errcnt++;
462 return 0;
463 }
464 }
465
466 sym = grad_sym_lookup_or_install(dict_attr_tab, ATTR_NAME, 1);
467 switch (sym->type) {
468 case dict_symbol_uninitialized:
469 sym->type = dict_symbol_attribute;
470 attr = &sym->v.attr;
471 break;
472
473 case dict_symbol_attribute:
474 grad_log_loc(GRAD_LOG_WARN, loc,
475 _("Redefining attribute %s"),
476 ATTR_NAME);
477 attr = &sym->v.attr;
478 break;
479
480 case dict_symbol_alias:
481 grad_log_loc(GRAD_LOG_WARN, loc,
482 _("Redefining alias %s"),
483 ATTR_NAME);
484 attr = sym->v.alias;
485 }
486
487 attr->name = sym->name;
488 attr->value = value;
489 attr->type = type;
490 attr->prop = flags | prop;
491 attr->parser = fp;
492 if (attr->value >= 0 && attr->value < DICT_INDEX_SIZE)
493 dict_attr_index[attr->value] = attr;
494
495 return 0;
496 }
497
498 /* Syntax:
499 ALIAS oldname newname */
500 static int
_dict_alias(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)501 _dict_alias(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
502 {
503 DICT_SYMBOL *sym;
504 grad_dict_attr_t *attr;
505
506 if (nfields(fc, 3, 3, loc))
507 return 0;
508
509 attr = dict_attr_lookup(fv[1]);
510 if (!attr) {
511 grad_log_loc(GRAD_LOG_ERR, loc,
512 _("Attribute %s is not defined"),
513 fv[1]);
514 return 0;
515 }
516
517 sym = grad_sym_lookup_or_install(dict_attr_tab, fv[2], 1);
518 if (sym->type != dict_symbol_uninitialized) {
519 grad_log_loc(GRAD_LOG_ERR, loc,
520 _("Symbol %s already declared"),
521 fv[2]);
522 /*FIXME: location of the previous declaration*/
523 /* Not a fatal error: do not increase error count */
524 return 0;
525 }
526 sym->type = dict_symbol_alias;
527 sym->v.alias = attr;
528 return 0;
529 }
530
531 /* Syntax:
532
533 PROPERTY Attribute Flags */
534 static int
_dict_property(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)535 _dict_property(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
536 {
537 grad_dict_attr_t *attr;
538 int i;
539 int flags;
540 int prop;
541
542 if (nfields(fc, 3, -1, loc))
543 return 0;
544
545 attr = dict_attr_lookup(fv[1]);
546 if (!attr) {
547 grad_log_loc(GRAD_LOG_ERR, loc,
548 _("Attribute %s is not defined"),
549 fv[1]);
550 return 0;
551 }
552
553 for (i = 2; i < fc; i++) {
554 switch (fv[i][0]) {
555 case '+':
556 flags = prop = 0;
557 if (parse_attr_properties(loc, fv[i]+1,
558 &flags, &prop)) {
559 pd->errcnt++;
560 break;
561 }
562 attr->prop |= flags | prop;
563 break;
564
565 case '-':
566 flags = prop = 0;
567 if (parse_attr_properties(loc, fv[i]+1,
568 &flags, &prop)) {
569 pd->errcnt++;
570 break;
571 }
572 attr->prop &= ~(flags | prop);
573 break;
574
575 default:
576 if (i > 2) {
577 grad_log_loc(GRAD_LOG_ERR, loc,
578 _("PROPERTY syntax error"));
579 pd->errcnt++;
580 } else {
581 set_default_attr_properties(attr->value,
582 &flags, &prop);
583 if (parse_attr_properties(loc, fv[i],
584 &flags, &prop) == 0)
585 attr->prop = flags | prop;
586 else
587 pd->errcnt++;
588 break;
589 }
590 }
591 }
592 return 0;
593 }
594
595 static int
_dict_value(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)596 _dict_value(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
597 {
598 grad_dict_value_t *dval;
599 grad_dict_attr_t *attr;
600 char *p;
601 int value;
602
603 if (nfields(fc, 4, 4, loc))
604 return 0;
605
606 value = strtol(VALUE_NUM, &p, 0);
607 if (*p) {
608 grad_log_loc(GRAD_LOG_ERR, loc,
609 _("value not a number (near %s)"),
610 p);
611 pd->errcnt++;
612 return 0;
613 }
614
615 attr = dict_attr_lookup(VALUE_ATTR);
616 if (!attr) {
617 grad_log_loc(GRAD_LOG_ERR, loc,
618 _("Attribute %s is not defined"),
619 VALUE_ATTR);
620 pd->errcnt++;
621 return 0;
622 }
623
624 attr->prop |= GRAD_AP_TRANSLATE;
625
626 /* Create a new VALUE entry for the list */
627 dval = grad_emalloc(sizeof(grad_dict_value_t));
628
629 dval->name = grad_estrdup(VALUE_NAME);
630 dval->attr = attr;
631 dval->value = value;
632
633 /* Append */
634 if (!dictionary_values)
635 dictionary_values = grad_list_create();
636 grad_list_append(dictionary_values, dval);
637
638 return 0;
639 }
640
641 static int
_dict_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)642 _dict_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
643 {
644 int value;
645 char *p;
646
647 if (nfields(fc, 3, 3, loc))
648 return 1;
649
650 value = strtol(VENDOR_VALUE, &p, 0);
651 if (*p) {
652 grad_log_loc(GRAD_LOG_ERR, loc,
653 _("value not a number (near %s)"),
654 p);
655 pd->errcnt++;
656 return 1;
657 }
658
659 if (addvendor(VENDOR_NAME, value) < 0) {
660 pd->errcnt++;
661 return 1;
662 }
663
664 return 0;
665
666 }
667
668 static void
_dict_begin(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)669 _dict_begin(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
670 {
671 if (pd->vendor) {
672 grad_log_loc(GRAD_LOG_ERR, loc, _("blocks cannot be nested"));
673 grad_log_loc(GRAD_LOG_ERR, &pd->begin_locus,
674 _("block opened here"));
675 pd->errcnt++;
676 return;
677 }
678
679 if (nfields(fc, 3, 4, loc)) {
680 pd->errcnt++;
681 return;
682 }
683
684 if (strcmp (fv[1], "VENDOR")) {
685 grad_log_loc(GRAD_LOG_ERR, loc,
686 _("block syntax: expected `VENDOR' but found `%s'"),
687 fv[1]);
688 pd->errcnt++;
689 return;
690 }
691
692 if (fc == 4 && _dict_vendor(pd, fc-1, fv+1, loc))
693 return;
694
695 if ((pd->vendor = grad_vendor_name_to_id(fv[2])) == 0) {
696 grad_log_loc(GRAD_LOG_ERR, loc, _("unknown vendor"));
697 pd->errcnt++;
698 return;
699 }
700 pd->begin_locus = *loc;
701 GRAD_DEBUG4(1, "%s:%lu: BEGIN VENDOR %s (%d)",
702 loc->file, loc->line, fv[2], pd->vendor);
703 }
704
705 static void
_dict_end(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)706 _dict_end(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
707 {
708 if (!pd->vendor) {
709 grad_log_loc(GRAD_LOG_ERR, loc, _("unexpected END"));
710 pd->errcnt++;
711 }
712 GRAD_DEBUG1(1, "END VENDOR %d", pd->vendor);
713 pd->vendor = 0;
714 }
715
716 static void
_dict_begin_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)717 _dict_begin_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
718 {
719 char *args[4];
720
721 if (nfields(fc, 2, 2, loc)) {
722 pd->errcnt++;
723 return;
724 }
725
726 args[0] = "BEGIN";
727 args[1] = "VENDOR";
728 args[2] = fv[1];
729 args[3] = NULL;
730 _dict_begin(pd, 3, args, loc);
731 }
732
733 static void
_dict_end_vendor(struct parse_data * pd,int fc,char ** fv,grad_locus_t * loc)734 _dict_end_vendor(struct parse_data *pd, int fc, char **fv, grad_locus_t *loc)
735 {
736 _dict_end(pd, fc, fv, loc);
737 }
738
739 enum {
740 KW_INCLUDE,
741 KW_ATTRIBUTE,
742 KW_ALIAS,
743 KW_VALUE,
744 KW_VENDOR,
745 KW_PROPERTY,
746 KW_BEGIN,
747 KW_BEGIN_VENDOR,
748 KW_END_VENDOR,
749 KW_END
750 };
751
752 static grad_keyword_t dict_kw[] = {
753 { "$INCLUDE", KW_INCLUDE },
754 { "ATTRIBUTE", KW_ATTRIBUTE },
755 { "ALIAS", KW_ALIAS },
756 { "VALUE", KW_VALUE },
757 { "VENDOR", KW_VENDOR },
758 { "PROPERTY", KW_PROPERTY },
759 { "BEGIN", KW_BEGIN },
760 { "END", KW_END },
761 { "BEGIN-VENDOR", KW_BEGIN_VENDOR },
762 { "END-VENDOR", KW_END_VENDOR },
763 { NULL, 0 }
764 };
765
766 static int
parse_dict_entry(void * closure,int fc,char ** fv,grad_locus_t * loc)767 parse_dict_entry(void *closure, int fc, char **fv, grad_locus_t *loc)
768 {
769 struct parse_data *pd = closure;
770 switch (grad_xlat_keyword(dict_kw, KEYWORD, -1)) {
771 case KW_INCLUDE:
772 _dict_include(pd, fc, fv, loc);
773 break;
774
775 case KW_ATTRIBUTE:
776 _dict_attribute(pd, fc, fv, loc);
777 break;
778
779 case KW_ALIAS:
780 _dict_alias(pd, fc, fv, loc);
781 break;
782
783 case KW_VALUE:
784 _dict_value(pd, fc, fv, loc);
785 break;
786
787 case KW_VENDOR:
788 _dict_vendor(pd, fc, fv, loc);
789 break;
790
791 case KW_PROPERTY:
792 _dict_property(pd, fc, fv, loc);
793 break;
794
795 case KW_BEGIN:
796 _dict_begin(pd, fc, fv, loc);
797 break;
798
799 case KW_END:
800 _dict_end(pd, fc, fv, loc);
801 break;
802
803 case KW_BEGIN_VENDOR:
804 _dict_begin_vendor(pd, fc, fv, loc);
805 break;
806
807 case KW_END_VENDOR:
808 _dict_end_vendor(pd, fc, fv, loc);
809 break;
810
811 default:
812 grad_log_loc(GRAD_LOG_ERR, loc, "%s", _("unknown keyword"));
813 break;
814 }
815 return 0;
816 }
817
818 static int
parse_dict(char * name)819 parse_dict(char *name)
820 {
821 char *path;
822 int rc;
823 struct parse_data pd;
824
825 pd.errcnt = 0;
826 pd.vendor = 0;
827
828 if (name[0] == '/')
829 path = grad_estrdup(name);
830 else
831 path = grad_mkfilename(grad_config_dir, name);
832 GRAD_DEBUG1(1,"parsing %s", path);
833 rc = grad_read_raddb_file(path, 1, NULL, parse_dict_entry, &pd);
834 if (pd.vendor) {
835 grad_log_loc(GRAD_LOG_ERR, &pd.begin_locus, _("BEGIN without END"));
836 pd.vendor = 0;
837 pd.errcnt++;
838 }
839 if (pd.errcnt)
840 grad_log(GRAD_LOG_NOTICE,
841 dngettext(PACKAGE,
842 "%s: %d error", "%s: %d errors",
843 pd.errcnt), path, pd.errcnt);
844 grad_free(path);
845 return rc;
846 }
847
848 int
grad_dict_init()849 grad_dict_init()
850 {
851 parser_tab_free();
852 dict_free();
853
854 parser_tab_init();
855 dict_attr_tab = grad_symtab_create(sizeof(DICT_SYMBOL), NULL);
856 vendorno = 1;
857 return parse_dict(RADIUS_DICTIONARY);
858 }
859
860 void
grad_dict_free()861 grad_dict_free()
862 {
863 parser_tab_free();
864 dict_free();
865 }
866
867 /* **************************************************************************
868 * Lookup functions
869 */
870
871 /*
872 * Return the full attribute structure based on the
873 * attribute id number.
874 */
875
876 struct attr_value {
877 unsigned value;
878 grad_dict_attr_t *da;
879 };
880
881 static int
attrval_cmp(void * data,grad_symbol_t * s)882 attrval_cmp(void *data, grad_symbol_t *s)
883 {
884 struct attr_value *av = data;
885 DICT_SYMBOL *sym = (DICT_SYMBOL *) s;
886
887 if (sym->type == dict_symbol_attribute
888 && sym->v.attr.value == av->value) {
889 av->da = &sym->v.attr;
890 return 1;
891 }
892 return 0;
893 }
894
895 grad_dict_attr_t *
grad_attr_number_to_dict(int attribute)896 grad_attr_number_to_dict(int attribute)
897 {
898 struct attr_value av;
899 if (attribute >= 0 && attribute < DICT_INDEX_SIZE)
900 return dict_attr_index[attribute];
901 av.value = attribute;
902 av.da = NULL;
903 grad_symtab_iterate(dict_attr_tab, attrval_cmp, &av);
904 return av.da;
905 }
906
907 /*
908 * Return the full attribute structure based on the attribute name.
909 */
910
911 grad_dict_attr_t *
grad_attr_name_to_dict(const char * attrname)912 grad_attr_name_to_dict(const char *attrname)
913 {
914 return dict_attr_lookup(attrname);
915 }
916
917 /*
918 * Return the full value structure based on the value name.
919 */
920 struct val_lookup {
921 const char *name;
922 char *attrname;
923 int number;
924 };
925
926 static int
valname_cmp(const void * item,const void * data)927 valname_cmp(const void *item, const void *data)
928 {
929 const grad_dict_value_t *v = item;
930 const struct val_lookup *d = data;
931 if (d->number == v->attr->value && strcmp(v->name, d->name) == 0)
932 return 0;
933 return 1;
934 }
935
936 grad_dict_value_t *
grad_value_name_to_value(const char * valname,int attr)937 grad_value_name_to_value(const char *valname, int attr)
938 {
939 struct val_lookup data;
940 data.name = valname;
941 data.number = attr;
942 return grad_list_locate(dictionary_values, &data, valname_cmp);
943 }
944
945 /*
946 * Return the full value structure based on the actual value and
947 * the associated attribute name.
948 */
949 static int
valnum_cmp(const void * item,const void * data)950 valnum_cmp(const void *item, const void *data)
951 {
952 const grad_dict_value_t *v = item;
953 const struct val_lookup *d = data;
954
955 if (strcmp(d->attrname, v->attr->name) == 0 && d->number == v->value)
956 return 0;
957 return 1;
958 }
959
960 grad_dict_value_t *
grad_value_lookup(grad_uint32_t value,char * attrname)961 grad_value_lookup(grad_uint32_t value, char *attrname)
962 {
963 struct val_lookup data;
964 data.number = value;
965 data.attrname = attrname;
966 return grad_list_locate(dictionary_values, &data, valnum_cmp);
967 }
968
969 /*
970 * Get the PEC (Private Enterprise Code) of the vendor
971 * based on it's internal number.
972 */
973 static int
code_cmp(const void * item,const void * data)974 code_cmp(const void *item, const void *data)
975 {
976 const grad_dict_vendor_t *v = item;
977 const int *code = data;
978
979 return v->vendorcode != *code;
980 }
981
982 int
grad_vendor_id_to_pec(int code)983 grad_vendor_id_to_pec(int code)
984 {
985 grad_dict_vendor_t *vp;
986
987 vp = grad_list_locate(dictionary_vendors, &code, code_cmp);
988 return vp ? vp->vendorpec : 0;
989 }
990
991 /*
992 * Get the internal code of the vendor based on its PEC.
993 */
994 static int
pec_cmp(const void * item,const void * data)995 pec_cmp(const void *item, const void *data)
996 {
997 const grad_dict_vendor_t *v = item;
998 const int *pec = data;
999
1000 return v->vendorpec != *pec;
1001 }
1002
1003 int
grad_vendor_pec_to_id(int pec)1004 grad_vendor_pec_to_id(int pec)
1005 {
1006 grad_dict_vendor_t *vp;
1007
1008 vp = grad_list_locate(dictionary_vendors, &pec, pec_cmp);
1009 return vp ? vp->vendorcode : 0;
1010 }
1011
1012 char *
grad_vendor_pec_to_name(int pec)1013 grad_vendor_pec_to_name(int pec)
1014 {
1015 grad_dict_vendor_t *vp;
1016
1017 vp = grad_list_locate(dictionary_vendors, &pec, pec_cmp);
1018 return vp ? vp->vendorname : NULL;
1019 }
1020
1021
1022 /*
1023 * Get the internal code of the vendor based on its name.
1024 */
1025 static int
vendor_cmp(const void * item,const void * data)1026 vendor_cmp(const void *item, const void *data)
1027 {
1028 const grad_dict_vendor_t *v = item;
1029 const char *s = data;
1030
1031 return strcmp(v->vendorname, s);
1032 }
1033
1034 int
grad_vendor_name_to_id(char * name)1035 grad_vendor_name_to_id(char *name)
1036 {
1037 grad_dict_vendor_t *vp;
1038
1039 vp = grad_list_locate(dictionary_vendors, name, vendor_cmp);
1040 return vp ? vp->vendorcode : 0;
1041 }
1042
1043 struct dict_iterator {
1044 dict_iterator_fp fp;
1045 void *closure;
1046 };
1047
1048 int
dict_iter_helper(void * data,grad_symbol_t * symbol)1049 dict_iter_helper(void *data, grad_symbol_t *symbol)
1050 {
1051 struct dict_iterator *p = data;
1052 DICT_SYMBOL *dsym = (DICT_SYMBOL *) symbol;
1053 grad_dict_attr_t *attr;
1054
1055 return p->fp(p->closure, dsym->name, dict_symbol_ptr(dsym));
1056 }
1057
1058 void
grad_dictionary_iterate(dict_iterator_fp fp,void * closure)1059 grad_dictionary_iterate(dict_iterator_fp fp, void *closure)
1060 {
1061 static struct dict_iterator d;
1062 d.fp = fp;
1063 d.closure = closure;
1064 grad_symtab_iterate(dict_attr_tab, dict_iter_helper, &d);
1065 }
1066
1067 struct dict_value_iterator {
1068 dict_value_iterator_fp fp;
1069 void *closure;
1070 };
1071
1072 static int
dict_value_iter_helper(void * item,void * data)1073 dict_value_iter_helper(void *item, void *data)
1074 {
1075 struct dict_value_iterator *p = data;
1076 return p->fp(p->closure, item);
1077 }
1078
1079 void
grad_dictionary_value_iterate(dict_value_iterator_fp fp,void * closure)1080 grad_dictionary_value_iterate(dict_value_iterator_fp fp, void *closure)
1081 {
1082 static struct dict_value_iterator d;
1083 d.fp = fp;
1084 d.closure = closure;
1085 grad_list_iterate(dictionary_values, dict_value_iter_helper, &d);
1086 }
1087
1088
1089