New API's to update CONF_PAIRs, and get CONF_PARSERS
[freeradius.git] / src / main / conffile.c
1 /*
2  * conffile.c   Read the radiusd.conf file.
3  *
4  *              Yep I should learn to use lex & yacc, or at least
5  *              write a decent parser. I know how to do that, really :)
6  *              miquels@cistron.nl
7  *
8  * Version:     $Id$
9  *
10  *   This program is free software; you can redistribute it and/or modify
11  *   it under the terms of the GNU General Public License as published by
12  *   the Free Software Foundation; either version 2 of the License, or
13  *   (at your option) any later version.
14  *
15  *   This program is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with this program; if not, write to the Free Software
22  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  *
24  * Copyright 2000,2006  The FreeRADIUS server project
25  * Copyright 2000  Miquel van Smoorenburg <miquels@cistron.nl>
26  * Copyright 2000  Alan DeKok <aland@ox.org>
27  */
28
29 #include <freeradius-devel/ident.h>
30 RCSID("$Id$")
31
32 #include <freeradius-devel/radiusd.h>
33 #include <freeradius-devel/rad_assert.h>
34
35 #ifdef HAVE_DIRENT_H
36 #include <dirent.h>
37 #endif
38
39 #ifdef HAVE_SYS_STAT_H
40 #include <sys/stat.h>
41 #endif
42
43 #include <ctype.h>
44
45 typedef enum conf_type {
46         CONF_ITEM_INVALID = 0,
47         CONF_ITEM_PAIR,
48         CONF_ITEM_SECTION,
49         CONF_ITEM_DATA
50 } CONF_ITEM_TYPE;
51
52 struct conf_item {
53         struct conf_item *next;
54         struct conf_part *parent;
55         int lineno;
56         const char *filename;
57         CONF_ITEM_TYPE type;
58 };
59 struct conf_pair {
60         CONF_ITEM item;
61         const char *attr;
62         const char *value;
63         FR_TOKEN operator;
64         FR_TOKEN value_type;
65 };
66 struct conf_part {
67         CONF_ITEM item;
68         const char *name1;
69         const char *name2;
70         struct conf_item *children;
71         struct conf_item *tail; /* for speed */
72         CONF_SECTION    *template;
73         rbtree_t        *pair_tree; /* and a partridge.. */
74         rbtree_t        *section_tree; /* no jokes here */
75         rbtree_t        *name2_tree; /* for sections of the same name2 */
76         rbtree_t        *data_tree;
77         void            *base;
78         int depth;
79         const CONF_PARSER *variables;
80 };
81
82
83 /*
84  *      Internal data that is associated with a configuration section,
85  *      so that we don't have to track it separately.
86  */
87 struct conf_data {
88         CONF_ITEM  item;
89         const char *name;
90         int        flag;
91         void       *data;       /* user data */
92         void       (*free)(void *); /* free user data function */
93 };
94
95
96 static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
97                                 void *data, void (*data_free)(void *),
98                                 int flag);
99 static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
100                                    int flag);
101
102 int cf_log_config = 1;
103 int cf_log_modules = 1;
104
105 /*
106  *      Isolate the scary casts in these tiny provably-safe functions
107  */
108 CONF_PAIR *cf_itemtopair(CONF_ITEM *ci)
109 {
110         if (ci == NULL)
111                 return NULL;
112         rad_assert(ci->type == CONF_ITEM_PAIR);
113         return (CONF_PAIR *)ci;
114 }
115 CONF_SECTION *cf_itemtosection(CONF_ITEM *ci)
116 {
117         if (ci == NULL)
118                 return NULL;
119         rad_assert(ci->type == CONF_ITEM_SECTION);
120         return (CONF_SECTION *)ci;
121 }
122 CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp)
123 {
124         if (cp == NULL)
125                 return NULL;
126         return (CONF_ITEM *)cp;
127 }
128 CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs)
129 {
130         if (cs == NULL)
131                 return NULL;
132         return (CONF_ITEM *)cs;
133 }
134
135 static CONF_DATA *cf_itemtodata(CONF_ITEM *ci)
136 {
137         if (ci == NULL)
138                 return NULL;
139         rad_assert(ci->type == CONF_ITEM_DATA);
140         return (CONF_DATA *)ci;
141 }
142 static CONF_ITEM *cf_datatoitem(CONF_DATA *cd)
143 {
144         if (cd == NULL)
145                 return NULL;
146         return (CONF_ITEM *)cd;
147 }
148
149 /*
150  *      Create a new CONF_PAIR
151  */
152 static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,
153                                 FR_TOKEN operator, FR_TOKEN value_type,
154                                 CONF_SECTION *parent)
155 {
156         char *p;
157         size_t attr_len, value_len = 0;
158         CONF_PAIR *cp;
159
160         if (!attr) return NULL;
161         attr_len = strlen(attr) + 1;
162         if (value) value_len = strlen(value) + 1;
163
164         p = rad_malloc(sizeof(*cp) + attr_len + value_len);
165
166         cp = (CONF_PAIR *) p;
167         memset(cp, 0, sizeof(*cp));
168         cp->item.type = CONF_ITEM_PAIR;
169         cp->item.parent = parent;
170
171         p += sizeof(*cp);
172         memcpy(p, attr, attr_len);
173         cp->attr = p;
174
175         if (value) {
176                 p += attr_len;
177                 memcpy(p, value, value_len);
178                 cp->value = p;
179         }
180         cp->value_type = value_type;
181         cp->operator = operator;
182
183         return cp;
184 }
185
186 /*
187  *      Free a CONF_PAIR
188  */
189 void cf_pair_free(CONF_PAIR **cp)
190 {
191         if (!cp || !*cp) return;
192
193         /*
194          *      attr && value are allocated contiguous with cp.
195          */
196
197 #ifndef NDEBUG
198         memset(*cp, 0, sizeof(*cp));
199 #endif
200         free(*cp);
201
202         *cp = NULL;
203 }
204
205
206 static void cf_data_free(CONF_DATA **cd)
207 {
208         if (!cd || !*cd) return;
209
210         /* name is allocated contiguous with cd */
211         if (!(*cd)->free) {
212                 free((*cd)->data);
213         } else {
214                 ((*cd)->free)((*cd)->data);
215         }
216 #ifndef NDEBUG
217         memset(*cd, 0, sizeof(*cd));
218 #endif
219         free(*cd);
220         *cd = NULL;
221 }
222
223 /*
224  *      rbtree callback function
225  */
226 static int pair_cmp(const void *a, const void *b)
227 {
228         const CONF_PAIR *one = a;
229         const CONF_PAIR *two = b;
230
231         return strcmp(one->attr, two->attr);
232 }
233
234
235 /*
236  *      rbtree callback function
237  */
238 static int section_cmp(const void *a, const void *b)
239 {
240         const CONF_SECTION *one = a;
241         const CONF_SECTION *two = b;
242
243         return strcmp(one->name1, two->name1);
244 }
245
246
247 /*
248  *      rbtree callback function
249  */
250 static int name2_cmp(const void *a, const void *b)
251 {
252         const CONF_SECTION *one = a;
253         const CONF_SECTION *two = b;
254
255         rad_assert(strcmp(one->name1, two->name1) == 0);
256
257         if (!one->name2 && !two->name2) return 0;
258         if (!one->name2) return -1;
259         if (!two->name2) return +1;
260
261         return strcmp(one->name2, two->name2);
262 }
263
264
265 /*
266  *      rbtree callback function
267  */
268 static int data_cmp(const void *a, const void *b)
269 {
270         int rcode;
271
272         const CONF_DATA *one = a;
273         const CONF_DATA *two = b;
274
275         rcode = one->flag - two->flag;
276         if (rcode != 0) return rcode;
277
278         return strcmp(one->name, two->name);
279 }
280
281
282 /*
283  *      Free strings we've parsed into data structures.
284  */
285 void cf_section_parse_free(CONF_SECTION *cs, void *base)
286 {
287         int i;
288         const CONF_PARSER *variables = cs->variables;
289
290         /*
291          *      Don't automatically free the strings if we're being
292          *      called from a module.  This is also for clients.c,
293          *      where client_free() expects to be able to free the
294          *      client structure.  If we moved everything to key off
295          *      of the config files, we might solve some problems...
296          */
297         if (!variables) return;
298
299         /*
300          *      Free up dynamically allocated string pointers.
301          */
302         for (i = 0; variables[i].name != NULL; i++) {
303                 char **p;
304
305                 if ((variables[i].type != PW_TYPE_STRING_PTR) &&
306                     (variables[i].type != PW_TYPE_FILENAME)) {
307                         continue;
308                 }
309
310                 /*
311                  *      No base struct offset, data must be the pointer.
312                  *      If data doesn't exist, ignore the entry, there
313                  *      must be something wrong.
314                  */
315                 if (!base) {
316                         if (!variables[i].data) {
317                                 continue;
318                         }
319
320                         p = (char **) variables[i].data;;
321
322                 } else if (variables[i].data) {
323                         p = (char **) variables[i].data;;
324
325                 } else {
326                         p = (char **) (((char *)base) + variables[i].offset);
327                 }
328
329                 free(*p);
330                 *p = NULL;
331         }
332 }
333
334
335 /*
336  *      Free a CONF_SECTION
337  */
338 void cf_section_free(CONF_SECTION **cs)
339 {
340         CONF_ITEM       *ci, *next;
341
342         if (!cs || !*cs) return;
343
344         cf_section_parse_free(*cs, (*cs)->base);
345
346         for (ci = (*cs)->children; ci; ci = next) {
347                 next = ci->next;
348
349                 switch (ci->type) {
350                 case CONF_ITEM_PAIR: {
351                                 CONF_PAIR *pair = cf_itemtopair(ci);
352                                 cf_pair_free(&pair);
353                         }
354                         break;
355
356                 case CONF_ITEM_SECTION: {
357                                 CONF_SECTION *section = cf_itemtosection(ci);
358                                 cf_section_free(&section);
359                         }
360                         break;
361
362                 case CONF_ITEM_DATA: {
363                                 CONF_DATA *data = cf_itemtodata(ci);
364                                 cf_data_free(&data);
365                         }
366                         break;
367
368                 default:        /* should really be an error. */
369                         break;
370                 }
371         }
372
373         /*
374          *      Name1 and name2 are allocated contiguous with
375          *      cs.
376          */
377         if ((*cs)->pair_tree)
378                 rbtree_free((*cs)->pair_tree);
379         if ((*cs)->section_tree)
380                 rbtree_free((*cs)->section_tree);
381         if ((*cs)->name2_tree)
382                 rbtree_free((*cs)->name2_tree);
383         if ((*cs)->data_tree)
384                 rbtree_free((*cs)->data_tree);
385
386         /*
387          * And free the section
388          */
389 #ifndef NDEBUG
390         memset(*cs, 0, sizeof(*cs));
391 #endif
392         free(*cs);
393
394         *cs = NULL;
395 }
396
397
398 /*
399  *      Allocate a CONF_SECTION
400  */
401 static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
402                                       CONF_SECTION *parent)
403 {
404         size_t name1_len, name2_len = 0;
405         char *p;
406         CONF_SECTION    *cs;
407
408         if (!name1) return NULL;
409
410         name1_len = strlen(name1) + 1;
411         if (name2) name2_len = strlen(name2) + 1;
412
413         p = rad_malloc(sizeof(*cs) + name1_len + name2_len);
414
415         cs = (CONF_SECTION *) p;
416         memset(cs, 0, sizeof(*cs));
417         cs->item.type = CONF_ITEM_SECTION;
418         cs->item.parent = parent;
419
420         p += sizeof(*cs);
421         memcpy(p, name1, name1_len);
422         cs->name1 = p;
423
424         if (name2 && *name2) {
425                 p += name1_len;
426                 memcpy(p, name2, name2_len);
427                 cs->name2 = p;
428         }
429
430         cs->pair_tree = rbtree_create(pair_cmp, NULL, 0);
431         if (!cs->pair_tree) {
432                 cf_section_free(&cs);
433                 return NULL;
434         }
435
436         /*
437          *      Don't create a data tree, it may not be needed.
438          */
439
440         /*
441          *      Don't create the section tree here, it may not
442          *      be needed.
443          */
444
445         if (parent) cs->depth = parent->depth + 1;
446
447         return cs;
448 }
449
450 /*
451  *      Replace pair in a given section with a new pair,
452  *      of the given value.
453  */
454 int cf_pair_replace(CONF_SECTION *cs, CONF_PAIR *cp, const char *value)
455 {
456         CONF_PAIR *newp;
457         CONF_ITEM *ci, *cn, **last;
458
459         newp = cf_pair_alloc(cp->attr, value, cp->operator, cp->value_type,
460                              cs);
461         if (!newp) return -1;
462
463         ci = cf_pairtoitem(cp);
464         cn = cf_pairtoitem(newp);
465
466         /*
467          *      Find the old one from the linked list, and replace it
468          *      with the new one.
469          */
470         for (last = &cs->children; (*last) != NULL; last = &(*last)->next) {
471                 if (*last == ci) {
472                         cn->next = (*last)->next;
473                         *last = cn;
474                         ci->next = NULL;
475                         break;
476                 }
477         }
478
479         rbtree_deletebydata(cs->pair_tree, ci);
480
481         rbtree_insert(cs->pair_tree, cn);
482
483         return 0;
484 }
485
486
487 /*
488  *      Add an item to a configuration section.
489  */
490 static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci)
491 {
492         if (!cs->children) {
493                 rad_assert(cs->tail == NULL);
494                 cs->children = ci;
495         } else {
496                 rad_assert(cs->tail != NULL);
497                 cs->tail->next = ci;
498         }
499
500         /*
501          *      Update the trees (and tail) for each item added.
502          */
503         for (/* nothing */; ci != NULL; ci = ci->next) {
504                 cs->tail = ci;
505
506                 /*
507                  *      For fast lookups, pair's and sections get
508                  *      added to rbtree's.
509                  */
510                 switch (ci->type) {
511                         case CONF_ITEM_PAIR:
512                                 rbtree_insert(cs->pair_tree, ci);
513                                 break;
514
515                         case CONF_ITEM_SECTION: {
516                                 CONF_SECTION *cs_new = cf_itemtosection(ci);
517
518                                 if (!cs->section_tree) {
519                                         cs->section_tree = rbtree_create(section_cmp, NULL, 0);
520                                         /* ignore any errors */
521                                 }
522
523                                 if (cs->section_tree) {
524                                         rbtree_insert(cs->section_tree, cs_new);                                }
525
526                                 /*
527                                  *      Two names: find the named instance.
528                                  */
529                                 {
530                                         CONF_SECTION *old_cs;
531
532                                         /*
533                                          *      Find the FIRST
534                                          *      CONF_SECTION having
535                                          *      the given name1, and
536                                          *      create a new tree
537                                          *      under it.
538                                          */
539                                         old_cs = rbtree_finddata(cs->section_tree, cs_new);
540                                         if (!old_cs) return; /* this is a bad error! */
541
542                                         if (!old_cs->name2_tree) {
543                                                 old_cs->name2_tree = rbtree_create(name2_cmp,
544                                                                                    NULL, 0);
545                                         }
546                                         if (old_cs->name2_tree) {
547                                                 rbtree_insert(old_cs->name2_tree, cs_new);
548                                         }
549                                 } /* had a name2 */
550                                 break;
551                         } /* was a section */
552
553                         case CONF_ITEM_DATA:
554                                 if (!cs->data_tree) {
555                                         cs->data_tree = rbtree_create(data_cmp, NULL, 0);
556                                 }
557                                 if (cs->data_tree) {
558                                         rbtree_insert(cs->data_tree, ci);
559                                 }
560                                 break;
561
562                         default: /* FIXME: assert & error! */
563                                 break;
564
565                 } /* switch over conf types */
566         } /* loop over ci */
567 }
568
569
570 CONF_ITEM *cf_reference_item(const CONF_SECTION *parentcs,
571                              CONF_SECTION *outercs,
572                              const char *ptr)
573 {
574         CONF_PAIR *cp;
575         CONF_SECTION *next;
576         const CONF_SECTION *cs = outercs;
577         char name[8192];
578         char *p;
579
580         strlcpy(name, ptr, sizeof(name));
581         p = name;
582
583         /*
584          *      ".foo" means "foo from the current section"
585          */
586         if (*p == '.') {
587                 p++;
588                 
589                 /*
590                  *      ..foo means "foo from the section
591                  *      enclosing this section" (etc.)
592                  */
593                 while (*p == '.') {
594                         if (cs->item.parent)
595                                 cs = cs->item.parent;
596                         p++;
597                 }
598
599                 /*
600                  *      "foo.bar.baz" means "from the root"
601                  */
602         } else if (strchr(p, '.') != NULL) {
603                 if (!parentcs) goto no_such_item;
604
605                 cs = parentcs;
606         }
607
608         while (*p) {
609                 char *q, *r;
610
611                 r = strchr(p, '[');
612                 q = strchr(p, '.');
613                 if (!r && !q) break;
614
615                 if (r && q > r) q = NULL;
616                 if (q && q < r) r = NULL;
617
618                 /*
619                  *      Split off name2.
620                  */
621                 if (r) {
622                         q = strchr(r + 1, ']');
623                         if (!q) return NULL; /* parse error */
624
625                         /*
626                          *      Points to foo[bar]xx: parse error,
627                          *      it should be foo[bar] or foo[bar].baz
628                          */
629                         if (q[1] && q[1] != '.') goto no_such_item;
630
631                         *r = '\0';
632                         *q = '\0';
633                         next = cf_section_sub_find_name2(cs, p, r + 1);
634                         *r = '[';
635                         *q = ']';
636
637                         /*
638                          *      Points to a named instance of a section.
639                          */
640                         if (!q[1]) {
641                                 if (!next) goto no_such_item;
642                                 return cf_sectiontoitem(next);
643                         }
644
645                         q++;    /* ensure we skip the ']' and '.' */
646
647                 } else {
648                         *q = '\0';
649                         next = cf_section_sub_find(cs, p);
650                         *q = '.';
651                 }
652
653                 if (!next) break; /* it MAY be a pair in this section! */
654
655                 cs = next;
656                 p = q + 1;
657         }
658
659         if (!*p) goto no_such_item;
660
661  retry:
662         /*
663          *      Find it in the current referenced
664          *      section.
665          */
666         cp = cf_pair_find(cs, p);
667         if (cp) return cf_pairtoitem(cp);
668
669         next = cf_section_sub_find(cs, p);
670         if (next) return cf_sectiontoitem(next);
671         
672         /*
673          *      "foo" is "in the current section, OR in main".
674          */
675         if ((p == name) && (parentcs != NULL) && (cs != parentcs)) {
676                 cs = parentcs;
677                 goto retry;
678         }
679
680 no_such_item:
681         DEBUG2("WARNING: No such configuration item %s", ptr);
682         return NULL;
683 }
684
685
686 CONF_SECTION *cf_top_section(CONF_SECTION *cs)
687 {
688         while (cs->item.parent != NULL) {
689                 cs = cs->item.parent;
690         }
691
692         return cs;
693 }
694
695
696 /*
697  *      Expand the variables in an input string.
698  */
699 static const char *cf_expand_variables(const char *cf, int *lineno,
700                                        CONF_SECTION *outercs,
701                                        char *output, const char *input)
702 {
703         char *p;
704         const char *end, *ptr;
705         const CONF_SECTION *parentcs;
706         char name[8192];
707
708         /*
709          *      Find the master parent conf section.
710          *      We can't use mainconfig.config, because we're in the
711          *      process of re-building it, and it isn't set up yet...
712          */
713         parentcs = cf_top_section(outercs);
714
715         p = output;
716         ptr = input;
717         while (*ptr) {
718                 /*
719                  *      Ignore anything other than "${"
720                  */
721                 if ((*ptr == '$') && (ptr[1] == '{')) {
722                         CONF_ITEM *ci;
723                         CONF_PAIR *cp;
724
725                         /*
726                          *      FIXME: Add support for ${foo:-bar},
727                          *      like in xlat.c
728                          */
729
730                         /*
731                          *      Look for trailing '}', and log a
732                          *      warning for anything that doesn't match,
733                          *      and exit with a fatal error.
734                          */
735                         end = strchr(ptr, '}');
736                         if (end == NULL) {
737                                 *p = '\0';
738                                 radlog(L_INFO, "%s[%d]: Variable expansion missing }",
739                                        cf, *lineno);
740                                 return NULL;
741                         }
742
743                         ptr += 2;
744
745                         /*
746                          *      Can't really happen because input lines are
747                          *      capped at 8k, which is sizeof(name)
748                          */
749                         if ((size_t) (end - ptr) >= sizeof(name)) {
750                                 radlog(L_ERR, "%s[%d]: Reference string is too large",
751                                        cf, *lineno);
752                                 return NULL;
753                         }
754
755                         memcpy(name, ptr, end - ptr);
756                         name[end - ptr] = '\0';
757
758                         ci = cf_reference_item(parentcs, outercs, name);
759                         if (!ci || (ci->type != CONF_ITEM_PAIR)) {
760                                 radlog(L_ERR, "%s[%d]: Reference \"%s\" not found",
761                                        cf, *lineno, input);
762                                 return NULL;
763                         }
764
765                         /*
766                          *  Substitute the value of the variable.
767                          */
768                         cp = cf_itemtopair(ci);
769                         if (!cp->value) {
770                                 radlog(L_ERR, "%s[%d]: Reference \"%s\" has no value",
771                                        cf, *lineno, input);
772                                 return NULL;
773                         }
774                         strcpy(p, cp->value);
775                         p += strlen(p);
776                         ptr = end + 1;
777
778                 } else if (memcmp(ptr, "$ENV{", 5) == 0) {
779                         char *env;
780
781                         ptr += 5;
782
783                         /*
784                          *      Look for trailing '}', and log a
785                          *      warning for anything that doesn't match,
786                          *      and exit with a fatal error.
787                          */
788                         end = strchr(ptr, '}');
789                         if (end == NULL) {
790                                 *p = '\0';
791                                 radlog(L_INFO, "%s[%d]: Environment variable expansion missing }",
792                                        cf, *lineno);
793                                 return NULL;
794                         }
795
796                         /*
797                          *      Can't really happen because input lines are
798                          *      capped at 8k, which is sizeof(name)
799                          */
800                         if ((size_t) (end - ptr) >= sizeof(name)) {
801                                 radlog(L_ERR, "%s[%d]: Environment variable name is too large",
802                                        cf, *lineno);
803                                 return NULL;
804                         }
805
806                         memcpy(name, ptr, end - ptr);
807                         name[end - ptr] = '\0';
808
809                         /*
810                          *      Get the environment variable.
811                          *      If none exists, then make it an empty string.
812                          */
813                         env = getenv(name);
814                         if (env == NULL) {
815                                 *name = '\0';
816                                 env = name;
817                         }
818
819                         strcpy(p, env);
820                         p += strlen(p);
821                         ptr = end + 1;
822
823                 } else {
824                         /*
825                          *      Copy it over verbatim.
826                          */
827                         *(p++) = *(ptr++);
828                 }
829         } /* loop over all of the input string. */
830
831         *p = '\0';
832
833         return output;
834 }
835
836
837 /*
838  *      Parses an item (not a CONF_ITEM) into the specified format,
839  *      with a default value.
840  *
841  *      Returns -1 on error, 0 for correctly parsed, and 1 if the
842  *      default value was used.  Note that the default value will be
843  *      used ONLY if the CONF_PAIR is NULL.
844  */
845 int cf_item_parse(CONF_SECTION *cs, const char *name,
846                   int type, void *data, const char *dflt)
847 {
848         int rcode = 0;
849         char **q;
850         const char *value;
851         fr_ipaddr_t ipaddr;
852         const CONF_PAIR *cp = NULL;
853         char ipbuf[128];
854
855         if (cs) cp = cf_pair_find(cs, name);
856         if (cp) {
857                 value = cp->value;
858
859         } else if (!dflt) {
860                 return 1;       /* nothing to parse, return default value */
861
862         } else {
863                 rcode = 1;
864                 value = dflt;
865         }
866
867         if (!value) {
868                 return 0;
869         }
870
871         switch (type) {
872         case PW_TYPE_BOOLEAN:
873                 /*
874                  *      Allow yes/no and on/off
875                  */
876                 if ((strcasecmp(value, "yes") == 0) ||
877                     (strcasecmp(value, "on") == 0)) {
878                         *(int *)data = 1;
879                 } else if ((strcasecmp(value, "no") == 0) ||
880                            (strcasecmp(value, "off") == 0)) {
881                         *(int *)data = 0;
882                 } else {
883                         *(int *)data = 0;
884                         radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, name);
885                         return -1;
886                 }
887                 cf_log_info(cs, "\t%s = %s", name, value);
888                 break;
889
890         case PW_TYPE_INTEGER:
891                 *(int *)data = strtol(value, 0, 0);
892                 cf_log_info(cs, "\t%s = %d", name, *(int *)data);
893                 break;
894
895         case PW_TYPE_STRING_PTR:
896                 q = (char **) data;
897                 if (*q != NULL) {
898                         free(*q);
899                 }
900
901                 /*
902                  *      Expand variables which haven't already been
903                  *      expanded automagically when the configuration
904                  *      file was read.
905                  */
906                 if (value == dflt) {
907                         char buffer[8192];
908
909                         int lineno = cs->item.lineno;
910
911                         /*
912                          *      FIXME: sizeof(buffer)?
913                          */
914                         value = cf_expand_variables("?",
915                                                     &lineno,
916                                                     cs, buffer, value);
917                         if (!value) return -1;
918                 }
919
920                 cf_log_info(cs, "\t%s = \"%s\"", name, value ? value : "(null)");
921                 *q = value ? strdup(value) : NULL;
922                 break;
923
924                 /*
925                  *      This is the same as PW_TYPE_STRING_PTR,
926                  *      except that we also "stat" the file, and
927                  *      cache the result.
928                  */
929         case PW_TYPE_FILENAME:
930                 q = (char **) data;
931                 if (*q != NULL) {
932                         free(*q);
933                 }
934
935                 /*
936                  *      Expand variables which haven't already been
937                  *      expanded automagically when the configuration
938                  *      file was read.
939                  */
940                 if (value == dflt) {
941                         char buffer[8192];
942
943                         int lineno = cs->item.lineno;
944
945                         /*
946                          *      FIXME: sizeof(buffer)?
947                          */
948                         value = cf_expand_variables("?",
949                                                     &lineno,
950                                                     cs, buffer, value);
951                         if (!value) return -1;
952                 }
953
954                 cf_log_info(cs, "\t%s = \"%s\"", name, value ? value : "(null)");
955                 *q = value ? strdup(value) : NULL;
956
957                 /*
958                  *      And now we "stat" the file.
959                  *
960                  *      FIXME: This appears to leak memory on exit,
961                  *      and we don't use this information.  So it's
962                  *      commented out for now.
963                  */
964                 if (0 && *q) {
965                         struct stat buf;
966
967                         if (stat(*q, &buf) == 0) {
968                                 time_t *mtime;
969
970                                 mtime = rad_malloc(sizeof(*mtime));
971                                 *mtime = buf.st_mtime;
972                                 /* FIXME: error? */
973                                 cf_data_add_internal(cs, *q, mtime, free,
974                                                      PW_TYPE_FILENAME);
975                         }
976                 }
977                 break;
978
979         case PW_TYPE_IPADDR:
980                 /*
981                  *      Allow '*' as any address
982                  */
983                 if (strcmp(value, "*") == 0) {
984                         *(uint32_t *) data = htonl(INADDR_ANY);
985                         cf_log_info(cs, "\t%s = *", name);
986                         break;
987                 }
988                 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
989                         radlog(L_ERR, "Can't find IP address for host %s", value);
990                         return -1;
991                 }
992                 
993                 if (strspn(value, "0123456789.") == strlen(value)) {
994                         cf_log_info(cs, "\t%s = %s", name, value);
995                 } else {
996                         cf_log_info(cs, "\t%s = %s IP address [%s]", name, value,
997                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
998                 }
999                 *(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;
1000                 break;
1001
1002         case PW_TYPE_IPV6ADDR:
1003                 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
1004                         radlog(L_ERR, "Can't find IPv6 address for host %s", value);
1005                         return -1;
1006                 }
1007                 cf_log_info(cs, "\t%s = %s IPv6 address [%s]", name, value,
1008                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
1009                 memcpy(data, &ipaddr.ipaddr.ip6addr,
1010                        sizeof(ipaddr.ipaddr.ip6addr));
1011                 break;
1012
1013         default:
1014                 radlog(L_ERR, "type %d not supported yet", type);
1015                 return -1;
1016                 break;
1017         } /* switch over variable type */
1018
1019         return rcode;
1020 }
1021
1022 static const char *parse_spaces = "                                                                                                                                                                                                                                                                ";
1023
1024 /*
1025  *      Parse a configuration section into user-supplied variables.
1026  */
1027 int cf_section_parse(CONF_SECTION *cs, void *base,
1028                      const CONF_PARSER *variables)
1029 {
1030         int i;
1031         void *data;
1032
1033         cs->variables = variables; /* this doesn't hurt anything */
1034
1035         if (!cs->name2) {
1036                 cf_log_info(cs, "%.*s%s {", cs->depth, parse_spaces,
1037                        cs->name1);
1038         } else {
1039                 cf_log_info(cs, "%.*s%s %s {", cs->depth, parse_spaces,
1040                        cs->name1, cs->name2);
1041         }
1042
1043         /*
1044          *      Handle the known configuration parameters.
1045          */
1046         for (i = 0; variables[i].name != NULL; i++) {
1047                 /*
1048                  *      Handle subsections specially
1049                  */
1050                 if (variables[i].type == PW_TYPE_SUBSECTION) {
1051                         CONF_SECTION *subcs;
1052                         subcs = cf_section_sub_find(cs, variables[i].name);
1053
1054                         /*
1055                          *      If the configuration section is NOT there,
1056                          *      then ignore it.
1057                          *
1058                          *      FIXME! This is probably wrong... we should
1059                          *      probably set the items to their default values.
1060                          */
1061                         if (!subcs) continue;
1062
1063                         if (!variables[i].dflt) {
1064                                 DEBUG2("Internal sanity check 1 failed in cf_section_parse");
1065                                 goto error;
1066                         }
1067
1068                         if (cf_section_parse(subcs, base,
1069                                              (const CONF_PARSER *) variables[i].dflt) < 0) {
1070                                 goto error;
1071                         }
1072                         continue;
1073                 } /* else it's a CONF_PAIR */
1074
1075                 if (variables[i].data) {
1076                         data = variables[i].data; /* prefer this. */
1077                 } else if (base) {
1078                         data = ((char *)base) + variables[i].offset;
1079                 } else {
1080                         DEBUG2("Internal sanity check 2 failed in cf_section_parse");
1081                         goto error;
1082                 }
1083
1084                 /*
1085                  *      Parse the pair we found, or a default value.
1086                  */
1087                 if (cf_item_parse(cs, variables[i].name, variables[i].type,
1088                                   data, variables[i].dflt) < 0) {
1089                         goto error;
1090                 }
1091         } /* for all variables in the configuration section */
1092
1093         cf_log_info(cs, "%.*s}", cs->depth, parse_spaces);
1094
1095         cs->base = base;
1096
1097         return 0;
1098
1099  error:
1100         cf_log_info(cs, "%.*s}", cs->depth, parse_spaces);
1101         cf_section_parse_free(cs, base);
1102         return -1;
1103 }
1104
1105
1106 /*
1107  *      Sanity check the "if" or "elsif", presuming that the first '('
1108  *      has already been eaten.
1109  *
1110  *      We're not really parsing it here, just checking if it's mostly
1111  *      well-formed.
1112  */
1113 static int condition_looks_ok(const char **ptr)
1114 {
1115         int num_braces = 1;
1116         int quote = 0;
1117         const char *p = *ptr;
1118
1119         while (*p) {
1120                 if (quote) {
1121                         if (*p == quote) {
1122                                 p++;
1123                                 quote = 0;
1124                                 continue;
1125                         }
1126
1127                         if (*p == '\\') {
1128                                 if (!p[1]) {
1129                                         return 0; /* no trailing slash */
1130                                 }
1131                                 p += 2;
1132                                 continue;
1133                         }
1134                         p++;
1135                         continue;
1136                 }
1137
1138                 switch (*p) {
1139                 case '\\':
1140                         if (!p[1]) {
1141                                 return 0; /* no trailing slash */
1142                         }
1143                         p += 2;
1144                         continue;
1145
1146                 case '(':
1147                         num_braces++;
1148                         p++;
1149                         continue;
1150
1151                 case ')':
1152                         if (num_braces == 1) {
1153                                 const char *q = p + 1;
1154
1155                                 /*
1156                                  *      Validate that there isn't much
1157                                  *      else after the closing brace.
1158                                  */
1159                                 while ((*q == ' ') || (*q == '\t')) q++;
1160
1161                                 /*
1162                                  *      Parse error.
1163                                  */
1164                                 if (*q != '{') {
1165                                         return 0;
1166                                 }
1167
1168                                 *ptr = p + 1; /* include the trailing ')' */
1169                                 return 1;
1170                         }
1171                         num_braces--;
1172                         p++;
1173                         continue;
1174
1175                 case '"':
1176                 case '\'':
1177                 case '/':
1178                 case '`':
1179                         quote = *p;
1180                         /* FALL-THROUGH */
1181
1182                 default:
1183                         p++;
1184                         break;
1185                 }
1186         }
1187
1188         return 0;
1189 }
1190
1191
1192 static const char *cf_local_file(CONF_SECTION *cs, const char *local,
1193                                  char *buffer, size_t bufsize)
1194 {
1195         size_t dirsize;
1196         const char *p;
1197         CONF_SECTION *parentcs = cf_top_section(cs);
1198
1199         p = strrchr(parentcs->item.filename, FR_DIR_SEP);
1200         if (!p) return local;
1201
1202         dirsize = (p - parentcs->item.filename) + 1;
1203
1204         if ((dirsize + strlen(local)) >= bufsize) {
1205                 return NULL;
1206         }
1207
1208         memcpy(buffer, parentcs->item.filename, dirsize);
1209         strlcpy(buffer + dirsize, local, bufsize - dirsize);
1210
1211         return buffer;
1212 }
1213
1214
1215 /*
1216  *      Read a part of the config file.
1217  */
1218 static int cf_section_read(const char *filename, int *lineno, FILE *fp,
1219                            CONF_SECTION *current)
1220
1221 {
1222         CONF_SECTION *this, *css;
1223         CONF_PAIR *cpn;
1224         const char *ptr;
1225         const char *value;
1226         char buf[8192];
1227         char buf1[8192];
1228         char buf2[8192];
1229         char buf3[8192];
1230         int t1, t2, t3;
1231         char *cbuf = buf;
1232         size_t len;
1233
1234         this = current;         /* add items here */
1235
1236         /*
1237          *      Read, checking for line continuations ('\\' at EOL)
1238          */
1239         for (;;) {
1240                 int eof;
1241
1242                 /*
1243                  *      Get data, and remember if we are at EOF.
1244                  */
1245                 eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);
1246                 (*lineno)++;
1247
1248                 /*
1249                  *      We read the entire 8k worth of data: complain.
1250                  *      Note that we don't care if the last character
1251                  *      is \n: it's still forbidden.  This means that
1252                  *      the maximum allowed length of text is 8k-1, which
1253                  *      should be plenty.
1254                  */
1255                 len = strlen(cbuf);
1256                 if ((cbuf + len + 1) >= (buf + sizeof(buf))) {
1257                         radlog(L_ERR, "%s[%d]: Line too long",
1258                                filename, *lineno);
1259                         return -1;
1260                 }
1261
1262                 /*
1263                  *      Not doing continuations: check for edge
1264                  *      conditions.
1265                  */
1266                 if (cbuf == buf) {
1267                         if (eof) break;
1268                         
1269                         ptr = buf;
1270                         while (*ptr && isspace((int) *ptr)) ptr++;
1271
1272                         if (!*ptr || (*ptr == '#')) continue;
1273
1274                 } else if (eof || (len == 0)) {
1275                         radlog(L_ERR, "%s[%d]: Continuation at EOF is illegal",
1276                                filename, *lineno);
1277                         return -1;
1278                 }
1279
1280                 /*
1281                  *      See if there's a continuation.
1282                  */
1283                 while ((len > 0) &&
1284                        ((cbuf[len - 1] == '\n') || (cbuf[len - 1] == '\r'))) {
1285                         len--;
1286                         cbuf[len] = '\0';
1287                 }
1288
1289                 if ((len > 0) && (cbuf[len - 1] == '\\')) {
1290                         cbuf[len - 1] = '\0';
1291                         cbuf += len - 1;
1292                         continue;
1293                 }
1294
1295                 ptr = cbuf = buf;
1296
1297                 /*
1298                  *      The parser is getting to be evil.
1299                  */
1300                 while ((*ptr == ' ') || (*ptr == '\t')) ptr++;
1301
1302                 if (((ptr[0] == '%') && (ptr[1] == '{')) ||
1303                     (ptr[0] == '`')) {
1304                         int hack;
1305
1306                         if (ptr[0] == '%') {
1307                                 hack = rad_copy_variable(buf1, ptr);
1308                         } else {
1309                                 hack = rad_copy_string(buf1, ptr);
1310                         }
1311                         if (hack < 0) {
1312                                 radlog(L_ERR, "%s[%d]: Invalid expansion: %s",
1313                                        filename, *lineno, ptr);
1314                                 return -1;
1315                         }
1316
1317                         t1 = T_BARE_WORD;
1318                         ptr += hack;
1319
1320                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
1321                         switch (t2) {
1322                         case T_EOL:
1323                         case T_HASH:
1324                                 goto do_bare_word;
1325                                 
1326                         default:
1327                                 radlog(L_ERR, "%s[%d]: Invalid expansion: %s",
1328                                        filename, *lineno, ptr);
1329                                 return -1;
1330                         }
1331                 } else {
1332                         t1 = gettoken(&ptr, buf1, sizeof(buf1));
1333                 }
1334
1335                 /*
1336                  *      The caller eats "name1 name2 {", and calls us
1337                  *      for the data inside of the section.  So if we
1338                  *      receive a closing brace, then it must mean the
1339                  *      end of the section.
1340                  */
1341                if (t1 == T_RCBRACE) {
1342                        if (this == current) {
1343                                radlog(L_ERR, "%s[%d]: Too many closing braces",
1344                                       filename, *lineno);
1345                                return -1;
1346
1347                        }
1348                        this = this->item.parent;
1349                        continue;
1350                 }
1351
1352                 /*
1353                  *      Allow for $INCLUDE files
1354                  *
1355                  *      This *SHOULD* work for any level include.
1356                  *      I really really really hate this file.  -cparker
1357                  */
1358                if ((strcasecmp(buf1, "$INCLUDE") == 0) ||
1359                    (strcasecmp(buf1, "$-INCLUDE") == 0)) {
1360                        int relative = 1;
1361
1362                         t2 = getword(&ptr, buf2, sizeof(buf2));
1363
1364                         if (buf2[0] == '$') relative = 0;
1365
1366                         value = cf_expand_variables(filename, lineno, this, buf, buf2);
1367                         if (!value) return -1;
1368
1369                         if (!FR_DIR_IS_RELATIVE(value)) relative = 0;
1370
1371                         if (relative) {
1372                                 value = cf_local_file(current, value, buf3,
1373                                                       sizeof(buf3));
1374                                 if (!value) {
1375                                         radlog(L_ERR, "%s[%d]: Directories too deep.",
1376                                                filename, *lineno);
1377                                         return -1;
1378                                 }
1379                         }
1380
1381
1382 #ifdef HAVE_DIRENT_H
1383                         /*
1384                          *      $INCLUDE foo/
1385                          *
1386                          *      Include ALL non-"dot" files in the directory.
1387                          *      careful!
1388                          */
1389                         if (value[strlen(value) - 1] == '/') {
1390                                 DIR             *dir;
1391                                 struct dirent   *dp;
1392                                 struct stat stat_buf;
1393
1394                                 DEBUG2("including files in directory %s", value );
1395                                 dir = opendir(value);
1396                                 if (!dir) {
1397                                         radlog(L_ERR, "%s[%d]: Error reading directory %s: %s",
1398                                                filename, *lineno, value,
1399                                                strerror(errno));
1400                                         return -1;
1401                                 }
1402
1403                                 /*
1404                                  *      Read the directory, ignoring "." files.
1405                                  */
1406                                 while ((dp = readdir(dir)) != NULL) {
1407                                         const char *p;
1408
1409                                         if (dp->d_name[0] == '.') continue;
1410
1411                                         /*
1412                                          *      Check for valid characters
1413                                          */
1414                                         for (p = dp->d_name; *p != '\0'; p++) {
1415                                                 if (isalpha((int)*p) ||
1416                                                     isdigit((int)*p) ||
1417                                                     (*p == '-') ||
1418                                                     (*p == '_') ||
1419                                                     (*p == '.')) continue;
1420                                                 break;
1421                                         }
1422                                         if (*p != '\0') continue;
1423
1424                                         snprintf(buf2, sizeof(buf2), "%s%s",
1425                                                  value, dp->d_name);
1426                                         if ((stat(buf2, &stat_buf) != 0) ||
1427                                             S_ISDIR(stat_buf.st_mode)) continue;
1428                                         /*
1429                                          *      Read the file into the current
1430                                          *      configuration sectoin.
1431                                          */
1432                                         if (cf_file_include(buf2, this) < 0) {
1433                                                 closedir(dir);
1434                                                 return -1;
1435                                         }
1436                                 }
1437                                 closedir(dir);
1438                         }  else
1439 #endif
1440                         { /* it was a normal file */
1441                                 if (buf1[1] == '-') {
1442                                         struct stat statbuf;
1443
1444                                         if (stat(value, &statbuf) < 0) {
1445                                                 DEBUG("WARNING: Not including file %s: %s", value, strerror(errno));
1446                                                 continue;
1447                                         }
1448                                 }
1449
1450                                 if (cf_file_include(value, this) < 0) {
1451                                         return -1;
1452                                 }
1453                         }
1454                         continue;
1455                 } /* we were in an include */
1456
1457                if (strcasecmp(buf1, "$template") == 0) {
1458                        CONF_ITEM *ci;
1459                        CONF_SECTION *parentcs;
1460                        t2 = getword(&ptr, buf2, sizeof(buf2));
1461
1462                        parentcs = cf_top_section(current);
1463
1464                        ci = cf_reference_item(parentcs, this, buf2);
1465                        if (!ci || (ci->type != CONF_ITEM_SECTION)) {
1466                                 radlog(L_ERR, "%s[%d]: Reference \"%s\" not found",
1467                                        filename, *lineno, buf2);
1468                                 return -1;
1469                        }
1470                        
1471                        if (this->template) {
1472                                 radlog(L_ERR, "%s[%d]: Section already has a template",
1473                                        filename, *lineno);
1474                                 return -1;
1475                        }
1476
1477                        this->template = cf_itemtosection(ci);
1478                        continue;
1479                }
1480
1481                 /*
1482                  *      Ensure that the user can't add CONF_PAIRs
1483                  *      with 'internal' names;
1484                  */
1485                 if (buf1[0] == '_') {
1486                         radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
1487                                         filename, *lineno, buf1);
1488                         return -1;
1489                 }
1490
1491                 /*
1492                  *      Grab the next token.
1493                  */
1494                 t2 = gettoken(&ptr, buf2, sizeof(buf2));
1495                 switch (t2) {
1496                 case T_EOL:
1497                 case T_HASH:
1498                 do_bare_word:
1499                         t2 = T_OP_EQ;
1500                         value = NULL;
1501                         goto do_set;
1502
1503                 case T_OP_ADD:
1504                 case T_OP_CMP_EQ:
1505                 case T_OP_SUB:
1506                 case T_OP_LE:
1507                 case T_OP_GE:
1508                         if (!this || (strcmp(this->name1, "update") != 0)) {
1509                                 radlog(L_ERR, "%s[%d]: Invalid operator in assignment",
1510                                        filename, *lineno);
1511                                 return -1;
1512                         }
1513
1514                 case T_OP_EQ:
1515                 case T_OP_SET:
1516                 do_set:
1517                         t3 = getstring(&ptr, buf3, sizeof(buf3));
1518
1519                         /*
1520                          *      Handle variable substitution via ${foo}
1521                          */
1522                         if ((t3 == T_BARE_WORD) ||
1523                             (t3 == T_DOUBLE_QUOTED_STRING)) {
1524                                 value = cf_expand_variables(filename, lineno, this,
1525                                                             buf, buf3);
1526                                 if (!value) return -1;
1527                         } else if ((t3 == T_EOL) ||
1528                                    (t3 == T_HASH)) {
1529                                 value = NULL;
1530                         } else {
1531                                 value = buf3;
1532                         }
1533                         
1534                         /*
1535                          *      Add this CONF_PAIR to our CONF_SECTION
1536                          */
1537                         cpn = cf_pair_alloc(buf1, value, t2, t3, this);
1538                         cpn->item.filename = filename;
1539                         cpn->item.lineno = *lineno;
1540                         cf_item_add(this, cf_pairtoitem(cpn));
1541                         continue;
1542
1543                         /*
1544                          *      This horrible code is here to support
1545                          *      if/then/else failover in the
1546                          *      authorize, etc. sections.  It makes no
1547                          *      sense anywhere else.
1548                          */
1549                 case T_LBRACE:
1550                         if ((strcmp(buf1, "if") == 0) ||
1551                             (strcmp(buf1, "elsif") == 0)) {
1552                                 const char *end = ptr;
1553                                 CONF_SECTION *server;
1554
1555                                 if (!condition_looks_ok(&end)) {
1556                                         radlog(L_ERR, "%s[%d]: Parse error in condition at: %s",
1557                                                filename, *lineno, ptr);
1558                                         return -1;
1559                                 }
1560
1561                                 if ((size_t) (end - ptr) >= (sizeof(buf2) - 1)) {
1562                                         radlog(L_ERR, "%s[%d]: Statement too complicated after \"%s\"",
1563                                                filename, *lineno, buf1);
1564                                         return -1;
1565                                 }
1566
1567                                 /*
1568                                  *      More sanity checking.  This is
1569                                  *      getting to be a horrible hack.
1570                                  */
1571                                 server = this;
1572                                 while (server) {
1573                                         if (strcmp(server->name1, "server") == 0) break;
1574                                         server = server->item.parent;
1575                                 }
1576                                 
1577                                 if (0 && !server) {
1578                                         radlog(L_ERR, "%s[%d]: Processing directives such as \"%s\" cannot be used here.",
1579                                                filename, *lineno, buf1);
1580                                         return -1;
1581                                 }
1582
1583                                 buf2[0] = '(';
1584                                 memcpy(buf2 + 1, ptr, end - ptr);
1585                                 buf2[end - ptr + 1] = '\0';
1586                                 ptr = end + 1;
1587                                 t2 = T_BARE_WORD;
1588                                 goto section_alloc;
1589
1590                         } else {
1591                                 radlog(L_ERR, "%s[%d]: Parse error after \"%s\"",
1592                                        filename, *lineno, buf1);
1593                                 return -1;
1594                         }
1595
1596                         /* FALL-THROUGH */
1597
1598                         /*
1599                          *      No '=', must be a section or sub-section.
1600                          */
1601                 case T_BARE_WORD:
1602                 case T_DOUBLE_QUOTED_STRING:
1603                 case T_SINGLE_QUOTED_STRING:
1604                         t3 = gettoken(&ptr, buf3, sizeof(buf3));
1605                         if (t3 != T_LCBRACE) {
1606                                 radlog(L_ERR, "%s[%d]: Expecting section start brace '{' after \"%s %s\"",
1607                                        filename, *lineno, buf1, buf2);
1608                                 return -1;
1609                         }
1610
1611                 case T_LCBRACE:
1612                 section_alloc:
1613                         css = cf_section_alloc(buf1,
1614                                                t2 == T_LCBRACE ? NULL : buf2,
1615                                                this);
1616                         if (!css) {
1617                                 radlog(L_ERR, "%s[%d]: Failed allocating memory for section",
1618                                                 filename, *lineno);
1619                                 return -1;
1620                         }
1621                         cf_item_add(this, cf_sectiontoitem(css));
1622                         css->item.filename = filename;
1623                         css->item.lineno = *lineno;
1624
1625                         /*
1626                          *      The current section is now the child section.
1627                          */
1628                         this = css;
1629                         continue;
1630
1631                 default:
1632                         radlog(L_ERR, "%s[%d]: Parse error after \"%s\"",
1633                                filename, *lineno, buf1);
1634                         return -1;
1635                 }
1636         }
1637
1638         /*
1639          *      See if EOF was unexpected ..
1640          */
1641         if (feof(fp) && (this != current)) {
1642                 radlog(L_ERR, "%s[%d]: EOF reached without closing brace for section %s starting at line %d",
1643                        filename, *lineno,
1644                        cf_section_name1(this), cf_section_lineno(this));
1645                 return -1;
1646         }
1647
1648         return 0;
1649 }
1650
1651 /*
1652  *      Include one config file in another.
1653  */
1654 int cf_file_include(const char *filename, CONF_SECTION *cs)
1655 {
1656         FILE            *fp;
1657         int             lineno = 0;
1658         struct stat     statbuf;
1659         time_t          *mtime;
1660         CONF_DATA       *cd;
1661
1662         DEBUG2( "including configuration file %s", filename);
1663
1664         if (stat(filename, &statbuf) == 0) {
1665 #ifdef S_IWOTH
1666                 if ((statbuf.st_mode & S_IWOTH) != 0) {
1667                         radlog(L_ERR|L_CONS, "Configuration file %s is globally writable.  Refusing to start due to insecure configuration.",
1668                                filename);
1669                         return -1;
1670                 }
1671 #endif
1672
1673 #ifdef S_IROTH
1674                 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
1675                         radlog(L_ERR|L_CONS, "Configuration file %s is globally readable.  Refusing to start due to insecure configuration.",
1676                                filename);
1677                         return -1;
1678                 }
1679 #endif
1680         }
1681
1682         fp = fopen(filename, "r");
1683         if (!fp) {
1684                 radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s",
1685                        filename, strerror(errno));
1686                 return -1;
1687         }
1688
1689         /*
1690          *      Add the filename to the section
1691          */
1692         mtime = rad_malloc(sizeof(*mtime));
1693         *mtime = statbuf.st_mtime;
1694
1695         if (cf_data_add_internal(cs, filename, mtime, free,
1696                                  PW_TYPE_FILENAME) < 0) {
1697                 fclose(fp);
1698                 radlog(L_ERR|L_CONS, "Internal error open file \"%s\"",
1699                        filename);
1700                 return -1;
1701         }
1702
1703         cd = cf_data_find_internal(cs, filename, PW_TYPE_FILENAME);
1704         if (!cd) {
1705                 fclose(fp);
1706                 radlog(L_ERR|L_CONS, "Internal error open file \"%s\"",
1707                        filename);
1708                 return -1;
1709         }
1710
1711         if (!cs->item.filename) cs->item.filename = filename;
1712
1713         /*
1714          *      Read the section.  It's OK to have EOF without a
1715          *      matching close brace.
1716          */
1717         if (cf_section_read(cd->name, &lineno, fp, cs) < 0) {
1718                 fclose(fp);
1719                 return -1;
1720         }
1721
1722         fclose(fp);
1723         return 0;
1724 }
1725
1726 /*
1727  *      Bootstrap a config file.
1728  */
1729 CONF_SECTION *cf_file_read(const char *filename)
1730 {
1731         char *p;
1732         CONF_PAIR *cp;
1733         CONF_SECTION *cs;
1734
1735         cs = cf_section_alloc("main", NULL, NULL);
1736         if (!cs) return NULL;
1737
1738         cp = cf_pair_alloc("confdir", filename, T_OP_SET, T_BARE_WORD, cs);
1739         if (!cp) return NULL;
1740
1741         p = strrchr(cp->value, FR_DIR_SEP);
1742         if (p) *p = '\0';
1743
1744         cp->item.filename = "internal";
1745         cp->item.lineno = 0;
1746         cf_item_add(cs, cf_pairtoitem(cp));
1747
1748         if (cf_file_include(filename, cs) < 0) {
1749                 cf_section_free(&cs);
1750                 return NULL;
1751         }
1752
1753         return cs;
1754 }
1755
1756 /*
1757  * Return a CONF_PAIR within a CONF_SECTION.
1758  */
1759 CONF_PAIR *cf_pair_find(const CONF_SECTION *cs, const char *name)
1760 {
1761         CONF_ITEM       *ci;
1762         CONF_PAIR       *cp = NULL;
1763
1764         if (!cs) return NULL;
1765
1766         /*
1767          *      Find the name in the tree, for speed.
1768          */
1769         if (name) {
1770                 CONF_PAIR mycp;
1771
1772                 mycp.attr = name;
1773                 cp = rbtree_finddata(cs->pair_tree, &mycp);
1774         } else {
1775                 /*
1776                  *      Else find the first one that matches
1777                  */
1778                 for (ci = cs->children; ci; ci = ci->next) {
1779                         if (ci->type == CONF_ITEM_PAIR) {
1780                                 return cf_itemtopair(ci);
1781                         }
1782                 }
1783         }
1784
1785         if (cp || !cs->template) return cp;
1786
1787         return cf_pair_find(cs->template, name);
1788 }
1789
1790 /*
1791  * Return the attr of a CONF_PAIR
1792  */
1793
1794 const char *cf_pair_attr(CONF_PAIR *pair)
1795 {
1796         return (pair ? pair->attr : NULL);
1797 }
1798
1799 /*
1800  * Return the value of a CONF_PAIR
1801  */
1802
1803 const char *cf_pair_value(CONF_PAIR *pair)
1804 {
1805         return (pair ? pair->value : NULL);
1806 }
1807
1808 /*
1809  *      Copied here for error reporting.
1810  */
1811 extern void fr_strerror_printf(const char *, ...);
1812
1813 /*
1814  * Turn a CONF_PAIR into a VALUE_PAIR
1815  * For now, ignore the "value_type" field...
1816  */
1817 VALUE_PAIR *cf_pairtovp(CONF_PAIR *pair)
1818 {
1819         VALUE_PAIR *vp;
1820
1821         if (!pair) {
1822                 fr_strerror_printf("Internal error");
1823                 return NULL;
1824         }
1825
1826         if (!pair->value) {
1827                 fr_strerror_printf("No value given for attribute %s", pair->attr);
1828                 return NULL;
1829         }
1830
1831         /*
1832          *      pairmake handles tags.  pairalloc() doesn't.
1833          */
1834         vp = pairmake(pair->attr, NULL, pair->operator);
1835         if (!vp) {
1836                 return NULL;
1837         }
1838
1839         if (pair->value_type == T_BARE_WORD) {
1840                 if ((vp->type == PW_TYPE_STRING) && 
1841                     (pair->value[0] == '0') && (pair->value[1] == 'x')) {
1842                         vp->type = PW_TYPE_OCTETS;
1843                 }
1844                 if (!pairparsevalue(vp, pair->value)) {
1845                         pairfree(&vp);
1846                         return NULL;
1847                 }
1848                 vp->flags.do_xlat = 0;
1849           
1850         } else if (pair->value_type == T_SINGLE_QUOTED_STRING) {
1851                 if (!pairparsevalue(vp, pair->value)) {
1852                         pairfree(&vp);
1853                         return NULL;
1854                 }
1855                 vp->flags.do_xlat = 0;
1856         } else {
1857                 vp->flags.do_xlat = 1;
1858         }
1859
1860         return vp;
1861 }
1862
1863 /*
1864  * Return the first label of a CONF_SECTION
1865  */
1866
1867 const char *cf_section_name1(const CONF_SECTION *cs)
1868 {
1869         return (cs ? cs->name1 : NULL);
1870 }
1871
1872 /*
1873  * Return the second label of a CONF_SECTION
1874  */
1875
1876 const char *cf_section_name2(const CONF_SECTION *cs)
1877 {
1878         return (cs ? cs->name2 : NULL);
1879 }
1880
1881 /*
1882  * Find a value in a CONF_SECTION
1883  */
1884 const char *cf_section_value_find(const CONF_SECTION *cs, const char *attr)
1885 {
1886         CONF_PAIR       *cp;
1887
1888         cp = cf_pair_find(cs, attr);
1889
1890         return (cp ? cp->value : NULL);
1891 }
1892
1893 /*
1894  * Return the next pair after a CONF_PAIR
1895  * with a certain name (char *attr) If the requested
1896  * attr is NULL, any attr matches.
1897  */
1898
1899 CONF_PAIR *cf_pair_find_next(const CONF_SECTION *cs,
1900                              CONF_PAIR *pair, const char *attr)
1901 {
1902         CONF_ITEM       *ci;
1903
1904         /*
1905          * If pair is NULL this must be a first time run
1906          * Find the pair with correct name
1907          */
1908
1909         if (pair == NULL){
1910                 return cf_pair_find(cs, attr);
1911         }
1912
1913         ci = cf_pairtoitem(pair)->next;
1914
1915         for (; ci; ci = ci->next) {
1916                 if (ci->type != CONF_ITEM_PAIR)
1917                         continue;
1918                 if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0)
1919                         break;
1920         }
1921
1922         return cf_itemtopair(ci);
1923 }
1924
1925 /*
1926  * Find a CONF_SECTION, or return the root if name is NULL
1927  */
1928
1929 CONF_SECTION *cf_section_find(const char *name)
1930 {
1931         if (name)
1932                 return cf_section_sub_find(mainconfig.config, name);
1933         else
1934                 return mainconfig.config;
1935 }
1936
1937 /*
1938  * Find a sub-section in a section
1939  */
1940
1941 CONF_SECTION *cf_section_sub_find(const CONF_SECTION *cs, const char *name)
1942 {
1943         CONF_ITEM *ci;
1944
1945         /*
1946          *      Do the fast lookup if possible.
1947          */
1948         if (name && cs->section_tree) {
1949                 CONF_SECTION mycs;
1950
1951                 mycs.name1 = name;
1952                 mycs.name2 = NULL;
1953                 return rbtree_finddata(cs->section_tree, &mycs);
1954         }
1955
1956         for (ci = cs->children; ci; ci = ci->next) {
1957                 if (ci->type != CONF_ITEM_SECTION)
1958                         continue;
1959                 if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
1960                         break;
1961         }
1962
1963         return cf_itemtosection(ci);
1964
1965 }
1966
1967
1968 /*
1969  *      Find a CONF_SECTION with both names.
1970  */
1971 CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs,
1972                                         const char *name1, const char *name2)
1973 {
1974         CONF_ITEM    *ci;
1975
1976         if (!cs) cs = mainconfig.config;
1977
1978         if (name1 && (cs->section_tree)) {
1979                 CONF_SECTION mycs, *master_cs;
1980
1981                 mycs.name1 = name1;
1982                 mycs.name2 = name2;
1983
1984                 master_cs = rbtree_finddata(cs->section_tree, &mycs);
1985                 if (master_cs) {
1986                         return rbtree_finddata(master_cs->name2_tree, &mycs);
1987                 }
1988         }
1989
1990         /*
1991          *      Else do it the old-fashioned way.
1992          */
1993         for (ci = cs->children; ci; ci = ci->next) {
1994                 CONF_SECTION *subcs;
1995
1996                 if (ci->type != CONF_ITEM_SECTION)
1997                         continue;
1998
1999                 subcs = cf_itemtosection(ci);
2000                 if (!name1) {
2001                         if (!subcs->name2) {
2002                                 if (strcmp(subcs->name1, name2) == 0) break;
2003                         } else {
2004                                 if (strcmp(subcs->name2, name2) == 0) break;
2005                         }
2006                         continue; /* don't do the string comparisons below */
2007                 }
2008
2009                 if ((strcmp(subcs->name1, name1) == 0) &&
2010                     (subcs->name2 != NULL) &&
2011                     (strcmp(subcs->name2, name2) == 0))
2012                         break;
2013         }
2014
2015         return cf_itemtosection(ci);
2016 }
2017
2018 /*
2019  * Return the next subsection after a CONF_SECTION
2020  * with a certain name1 (char *name1). If the requested
2021  * name1 is NULL, any name1 matches.
2022  */
2023
2024 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
2025                                       CONF_SECTION *subsection,
2026                                       const char *name1)
2027 {
2028         CONF_ITEM       *ci;
2029
2030         /*
2031          * If subsection is NULL this must be a first time run
2032          * Find the subsection with correct name
2033          */
2034
2035         if (subsection == NULL){
2036                 ci = section->children;
2037         } else {
2038                 ci = cf_sectiontoitem(subsection)->next;
2039         }
2040
2041         for (; ci; ci = ci->next) {
2042                 if (ci->type != CONF_ITEM_SECTION)
2043                         continue;
2044                 if ((name1 == NULL) ||
2045                     (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
2046                         break;
2047         }
2048
2049         return cf_itemtosection(ci);
2050 }
2051
2052
2053 /*
2054  * Return the next section after a CONF_SECTION
2055  * with a certain name1 (char *name1). If the requested
2056  * name1 is NULL, any name1 matches.
2057  */
2058
2059 CONF_SECTION *cf_section_find_next(CONF_SECTION *section,
2060                                    CONF_SECTION *subsection,
2061                                    const char *name1)
2062 {
2063         if (!section->item.parent) return NULL;
2064
2065         return cf_subsection_find_next(section->item.parent, subsection, name1);
2066 }
2067
2068 /*
2069  * Return the next item after a CONF_ITEM.
2070  */
2071
2072 CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item)
2073 {
2074         /*
2075          * If item is NULL this must be a first time run
2076          * Return the first item
2077          */
2078
2079         if (item == NULL) {
2080                 return section->children;
2081         } else {
2082                 return item->next;
2083         }
2084 }
2085
2086 int cf_section_lineno(CONF_SECTION *section)
2087 {
2088         return cf_sectiontoitem(section)->lineno;
2089 }
2090
2091 const char *cf_pair_filename(CONF_PAIR *pair)
2092 {
2093         return cf_pairtoitem(pair)->filename;
2094 }
2095
2096 const char *cf_section_filename(CONF_SECTION *section)
2097 {
2098         return cf_sectiontoitem(section)->filename;
2099 }
2100
2101 int cf_pair_lineno(CONF_PAIR *pair)
2102 {
2103         return cf_pairtoitem(pair)->lineno;
2104 }
2105
2106 int cf_item_is_section(CONF_ITEM *item)
2107 {
2108         return item->type == CONF_ITEM_SECTION;
2109 }
2110 int cf_item_is_pair(CONF_ITEM *item)
2111 {
2112         return item->type == CONF_ITEM_PAIR;
2113 }
2114
2115
2116 static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, const char *name,
2117                                 void *data, void (*data_free)(void *))
2118 {
2119         char *p;
2120         size_t name_len;
2121         CONF_DATA *cd;
2122
2123         name_len = strlen(name) + 1;
2124
2125         p = rad_malloc(sizeof(*cd) + name_len);
2126         cd = (CONF_DATA *) p;
2127         memset(cd, 0, sizeof(*cd));
2128
2129         cd->item.type = CONF_ITEM_DATA;
2130         cd->item.parent = parent;
2131         cd->data = data;
2132         cd->free = data_free;
2133
2134         p += sizeof(*cd);
2135         memcpy(p, name, name_len);
2136         cd->name = p;
2137         return cd;
2138 }
2139
2140
2141 static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
2142                                    int flag)
2143 {
2144         if (!cs || !name) return NULL;
2145
2146         /*
2147          *      Find the name in the tree, for speed.
2148          */
2149         if (cs->data_tree) {
2150                 CONF_DATA mycd;
2151
2152                 mycd.name = name;
2153                 mycd.flag = flag;
2154                 return rbtree_finddata(cs->data_tree, &mycd);
2155         }
2156
2157         return NULL;
2158 }
2159
2160 /*
2161  *      Find data from a particular section.
2162  */
2163 void *cf_data_find(CONF_SECTION *cs, const char *name)
2164 {
2165         CONF_DATA *cd = cf_data_find_internal(cs, name, 0);
2166
2167         if (cd) return cd->data;
2168         return NULL;
2169 }
2170
2171
2172 /*
2173  *      Add named data to a configuration section.
2174  */
2175 static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
2176                                 void *data, void (*data_free)(void *),
2177                                 int flag)
2178 {
2179         CONF_DATA *cd;
2180
2181         if (!cs || !name) return -1;
2182
2183         /*
2184          *      Already exists.  Can't add it.
2185          */
2186         if (cf_data_find_internal(cs, name, flag) != NULL) return -1;
2187
2188         cd = cf_data_alloc(cs, name, data, data_free);
2189         if (!cd) return -1;
2190         cd->flag = flag;
2191
2192         cf_item_add(cs, cf_datatoitem(cd));
2193
2194         return 0;
2195 }
2196
2197 /*
2198  *      Add named data to a configuration section.
2199  */
2200 int cf_data_add(CONF_SECTION *cs, const char *name,
2201                 void *data, void (*data_free)(void *))
2202 {
2203         return cf_data_add_internal(cs, name, data, data_free, 0);
2204 }
2205
2206 #if 0
2207 /*
2208  *      Copy CONF_DATA from src to dst
2209  */
2210 static void cf_section_copy_data(CONF_SECTION *s, CONF_SECTION *d)
2211 {
2212
2213         CONF_ITEM *cd, *next, **last;
2214
2215         /*
2216          *      Don't check if s->data_tree is NULL.  It's child
2217          *      sections may have data, even if this section doesn't.
2218          */
2219
2220         rad_assert(d->data_tree == NULL);
2221         d->data_tree = s->data_tree;
2222         s->data_tree = NULL;
2223
2224         /*
2225          *      Walk through src, moving CONF_ITEM_DATA
2226          *      to dst, by hand.
2227          */
2228         last = &(s->children);
2229         for (cd = s->children; cd != NULL; cd = next) {
2230                 next = cd->next;
2231
2232                 /*
2233                  *      Recursively copy data from child sections.
2234                  */
2235                 if (cd->type == CONF_ITEM_SECTION) {
2236                         CONF_SECTION *s1, *d1;
2237
2238                         s1 = cf_itemtosection(cd);
2239                         d1 = cf_section_sub_find_name2(d, s1->name1, s1->name2);
2240                         if (d1) {
2241                                 cf_section_copy_data(s1, d1);
2242                         }
2243                         last = &(cd->next);
2244                         continue;
2245                 }
2246
2247                 /*
2248                  *      Not conf data, remember last ptr.
2249                  */
2250                 if (cd->type != CONF_ITEM_DATA) {
2251                         last = &(cd->next);
2252                         continue;
2253                 }
2254
2255                 /*
2256                  *      Remove it from the src list
2257                  */
2258                 *last = cd->next;
2259                 cd->next = NULL;
2260
2261                 /*
2262                  *      Add it to the dst list
2263                  */
2264                 if (!d->children) {
2265                         rad_assert(d->tail == NULL);
2266                         d->children = cd;
2267                 } else {
2268                         rad_assert(d->tail != NULL);
2269                         d->tail->next = cd;
2270                 }
2271                 d->tail = cd;
2272         }
2273 }
2274
2275 /*
2276  *      For a CONF_DATA element, stat the filename, if necessary.
2277  */
2278 static int filename_stat(void *context, void *data)
2279 {
2280         struct stat buf;
2281         CONF_DATA *cd = data;
2282
2283         context = context;      /* -Wunused */
2284
2285         if (cd->flag != PW_TYPE_FILENAME) return 0;
2286
2287         if (stat(cd->name, &buf) < 0) return -1;
2288
2289         if (buf.st_mtime != *(time_t *) cd->data) return -1;
2290
2291         return 0;
2292 }
2293
2294
2295 /*
2296  *      Compare two CONF_SECTIONS.  The items MUST be in the same
2297  *      order.
2298  */
2299 static int cf_section_cmp(CONF_SECTION *a, CONF_SECTION *b)
2300 {
2301         CONF_ITEM *ca = a->children;
2302         CONF_ITEM *cb = b->children;
2303
2304         while (1) {
2305                 CONF_PAIR *pa, *pb;
2306
2307                 /*
2308                  *      Done.  Stop.
2309                  */
2310                 if (!ca && !cb) break;
2311
2312                 /*
2313                  *      Skip CONF_DATA.
2314                  */
2315                 if (ca && ca->type == CONF_ITEM_DATA) {
2316                         ca = ca->next;
2317                         continue;
2318                 }
2319                 if (cb && cb->type == CONF_ITEM_DATA) {
2320                         cb = cb->next;
2321                         continue;
2322                 }
2323
2324                 /*
2325                  *      One is smaller than the other.  Exit.
2326                  */
2327                 if (!ca || !cb) return 0;
2328
2329                 if (ca->type != cb->type) return 0;
2330
2331                 /*
2332                  *      Deal with subsections.
2333                  */
2334                 if (ca->type == CONF_ITEM_SECTION) {
2335                         CONF_SECTION *sa = cf_itemtosection(ca);
2336                         CONF_SECTION *sb = cf_itemtosection(cb);
2337
2338                         if (!cf_section_cmp(sa, sb)) return 0;
2339                         goto next;
2340                 }
2341
2342                 rad_assert(ca->type == CONF_ITEM_PAIR);
2343
2344                 pa = cf_itemtopair(ca);
2345                 pb = cf_itemtopair(cb);
2346
2347                 /*
2348                  *      Different attr and/or value, Exit.
2349                  */
2350                 if ((strcmp(pa->attr, pb->attr) != 0) ||
2351                     (strcmp(pa->value, pb->value) != 0)) return 0;
2352
2353
2354                 /*
2355                  *      And go to the next element.
2356                  */
2357         next:
2358                 ca = ca->next;
2359                 cb = cb->next;
2360         }
2361
2362         /*
2363          *      Walk over the CONF_DATA, stat'ing PW_TYPE_FILENAME.
2364          */
2365         if (a->data_tree &&
2366             (rbtree_walk(a->data_tree, InOrder, filename_stat, NULL) != 0)) {
2367                 return 0;
2368         }
2369
2370         /*
2371          *      They must be the same, say so.
2372          */
2373         return 1;
2374 }
2375
2376
2377 /*
2378  *      Migrate CONF_DATA from one section to another.
2379  */
2380 int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src)
2381 {
2382         CONF_ITEM *ci;
2383         CONF_SECTION *s, *d;
2384
2385         for (ci = src->children; ci != NULL; ci = ci->next) {
2386                 if (ci->type != CONF_ITEM_SECTION)
2387                         continue;
2388
2389                 s = cf_itemtosection(ci);
2390                 d = cf_section_sub_find_name2(dst, s->name1, s->name2);
2391
2392                 if (!d) continue; /* not in new one, don't migrate it */
2393
2394                 /*
2395                  *      A section of the same name is in BOTH src & dst,
2396                  *      compare the CONF_PAIR's.  If they're all the same,
2397                  *      then copy the CONF_DATA from one to the other.
2398                  */
2399                 if (cf_section_cmp(s, d)) {
2400                         cf_section_copy_data(s, d);
2401                 }
2402         }
2403
2404         return 1;               /* rcode means anything? */
2405 }
2406 #endif
2407
2408 int cf_section_template(CONF_SECTION *cs, CONF_SECTION *template)
2409 {
2410         if (!cs || !template || cs->template || template->template) return -1;
2411
2412         cs->template = template;
2413
2414         return 0;
2415 }
2416
2417
2418 /*
2419  *      This is here to make the rest of the code easier to read.  It
2420  *      ties conffile.c to log.c, but it means we don't have to
2421  *      pollute every other function with the knowledge of the
2422  *      configuration internals.
2423  */
2424 void cf_log_err(CONF_ITEM *ci, const char *fmt, ...)
2425 {
2426         va_list ap;
2427         char buffer[256];
2428
2429         va_start(ap, fmt);
2430         vsnprintf(buffer, sizeof(buffer), fmt, ap);
2431         va_end(ap);
2432
2433         radlog(L_ERR, "%s[%d]: %s", ci->filename, ci->lineno, buffer);
2434 }
2435
2436
2437 void cf_log_info(CONF_SECTION *cs, const char *fmt, ...)
2438 {
2439         va_list ap;
2440
2441         va_start(ap, fmt);
2442         if (debug_flag > 1 && cf_log_config && cs) vradlog(L_DBG, fmt, ap);
2443         va_end(ap);
2444 }
2445
2446 /*
2447  *      Wrapper to simplify the code.
2448  */
2449 void cf_log_module(CONF_SECTION *cs, const char *fmt, ...)
2450 {
2451         va_list ap;
2452         char buffer[256];
2453
2454         va_start(ap, fmt);
2455         if (debug_flag > 1 && cf_log_modules && cs) {
2456                 vsnprintf(buffer, sizeof(buffer), fmt, ap);
2457
2458                 radlog(L_DBG, " Module: %s", buffer);
2459         }
2460         va_end(ap);
2461 }
2462
2463 const CONF_PARSER *cf_section_parse_table(CONF_SECTION *cs)
2464 {
2465         if (!cs) return NULL;
2466
2467         return cs->variables;
2468 }
2469
2470 #if 0
2471 /*
2472  * JMG dump_config tries to dump the config structure in a readable format
2473  *
2474 */
2475
2476 static int dump_config_section(CONF_SECTION *cs, int indent)
2477 {
2478         CONF_SECTION    *scs;
2479         CONF_PAIR       *cp;
2480         CONF_ITEM       *ci;
2481
2482         /* The DEBUG macro doesn't let me
2483          *   for(i=0;i<indent;++i) debugputchar('\t');
2484          * so I had to get creative. --Pac. */
2485
2486         for (ci = cs->children; ci; ci = ci->next) {
2487                 switch (ci->type) {
2488                 case CONF_ITEM_PAIR:
2489                         cp=cf_itemtopair(ci);
2490                         DEBUG("%.*s%s = %s",
2491                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
2492                                 cp->attr, cp->value);
2493                         break;
2494
2495                 case CONF_ITEM_SECTION:
2496                         scs=cf_itemtosection(ci);
2497                         DEBUG("%.*s%s %s%s{",
2498                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
2499                                 scs->name1,
2500                                 scs->name2 ? scs->name2 : "",
2501                                 scs->name2 ?  " " : "");
2502                         dump_config_section(scs, indent+1);
2503                         DEBUG("%.*s}",
2504                                 indent, "\t\t\t\t\t\t\t\t\t\t\t");
2505                         break;
2506
2507                 default:        /* FIXME: Do more! */
2508                         break;
2509                 }
2510         }
2511
2512         return 0;
2513 }
2514
2515 int dump_config(CONF_SECTION *cs)
2516 {
2517         return dump_config_section(cs, 0);
2518 }
2519 #endif