cf_data_add() sends us a static string. cf_data_add_internal()
[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
38 #ifdef HAVE_SYS_STAT_H
39 #include <sys/stat.h>
40 #endif
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         CONF_ITEM_TYPE type;
57 };
58 struct conf_pair {
59         CONF_ITEM item;
60         char *attr;
61         char *value;
62         LRAD_TOKEN operator;
63 };
64 struct conf_part {
65         CONF_ITEM item;
66         const char *name1;
67         const char *name2;
68         struct conf_item *children;
69         struct conf_item *tail; /* for speed */
70         CONF_SECTION    *template;
71         rbtree_t        *pair_tree; /* and a partridge.. */
72         rbtree_t        *section_tree; /* no jokes here */
73         rbtree_t        *name2_tree; /* for sections of the same name2 */
74         rbtree_t        *data_tree;
75         void            *base;
76         const CONF_PARSER *variables;
77 };
78
79
80 /*
81  *      Internal data that is associated with a configuration section,
82  *      so that we don't have to track it separately.
83  */
84 struct conf_data {
85         CONF_ITEM  item;
86         const char *name;
87         int        flag;
88         void       *data;       /* user data */
89         void       (*free)(void *); /* free user data function */
90 };
91
92
93 static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
94                                 void *data, void (*data_free)(void *),
95                                 int flag);
96 static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
97                                    int flag);
98
99 /*
100  *      Isolate the scary casts in these tiny provably-safe functions
101  */
102 CONF_PAIR *cf_itemtopair(CONF_ITEM *ci)
103 {
104         if (ci == NULL)
105                 return NULL;
106         rad_assert(ci->type == CONF_ITEM_PAIR);
107         return (CONF_PAIR *)ci;
108 }
109 CONF_SECTION *cf_itemtosection(CONF_ITEM *ci)
110 {
111         if (ci == NULL)
112                 return NULL;
113         rad_assert(ci->type == CONF_ITEM_SECTION);
114         return (CONF_SECTION *)ci;
115 }
116 CONF_ITEM *cf_pairtoitem(CONF_PAIR *cp)
117 {
118         if (cp == NULL)
119                 return NULL;
120         return (CONF_ITEM *)cp;
121 }
122 CONF_ITEM *cf_sectiontoitem(CONF_SECTION *cs)
123 {
124         if (cs == NULL)
125                 return NULL;
126         return (CONF_ITEM *)cs;
127 }
128
129 static CONF_DATA *cf_itemtodata(CONF_ITEM *ci)
130 {
131         if (ci == NULL)
132                 return NULL;
133         rad_assert(ci->type == CONF_ITEM_DATA);
134         return (CONF_DATA *)ci;
135 }
136 static CONF_ITEM *cf_datatoitem(CONF_DATA *cd)
137 {
138         if (cd == NULL)
139                 return NULL;
140         return (CONF_ITEM *)cd;
141 }
142
143 /*
144  *      Create a new CONF_PAIR
145  */
146 static CONF_PAIR *cf_pair_alloc(const char *attr, const char *value,
147                                 LRAD_TOKEN operator, CONF_SECTION *parent)
148 {
149         CONF_PAIR *cp;
150
151         cp = rad_malloc(sizeof(*cp));
152         memset(cp, 0, sizeof(*cp));
153         cp->item.type = CONF_ITEM_PAIR;
154         cp->item.parent = parent;
155         cp->attr = strdup(attr);
156         cp->value = strdup(value);
157         cp->operator = operator;
158
159         return cp;
160 }
161
162 /*
163  *      Free a CONF_PAIR
164  */
165 void cf_pair_free(CONF_PAIR **cp)
166 {
167         if (!cp || !*cp) return;
168
169         if ((*cp)->attr)
170                 free((*cp)->attr);
171         if ((*cp)->value)
172                 free((*cp)->value);
173
174 #ifndef NDEBUG
175         memset(*cp, 0, sizeof(*cp));
176 #endif
177         free(*cp);
178
179         *cp = NULL;
180 }
181
182
183 static void cf_data_free(CONF_DATA **cd)
184 {
185         if (!cd || !*cd) return;
186
187         if ((*cd)->flag != 0) free((*cd)->name);
188         if (!(*cd)->free) {
189                 free((*cd)->data);
190         } else {
191                 ((*cd)->free)((*cd)->data);
192         }
193 #ifndef NDEBUG
194         memset(*cd, 0, sizeof(*cd));
195 #endif
196         free(*cd);
197         *cd = NULL;
198 }
199
200 /*
201  *      rbtree callback function
202  */
203 static int pair_cmp(const void *a, const void *b)
204 {
205         const CONF_PAIR *one = a;
206         const CONF_PAIR *two = b;
207
208         return strcmp(one->attr, two->attr);
209 }
210
211
212 /*
213  *      rbtree callback function
214  */
215 static int section_cmp(const void *a, const void *b)
216 {
217         const CONF_SECTION *one = a;
218         const CONF_SECTION *two = b;
219
220         return strcmp(one->name1, two->name1);
221 }
222
223
224 /*
225  *      rbtree callback function
226  */
227 static int name2_cmp(const void *a, const void *b)
228 {
229         const CONF_SECTION *one = a;
230         const CONF_SECTION *two = b;
231
232         rad_assert(strcmp(one->name1, two->name1) == 0);
233
234         if (!one->name2 && !two->name2) return 0;
235         if (!one->name2) return -1;
236         if (!two->name2) return +1;
237
238         return strcmp(one->name2, two->name2);
239 }
240
241
242 /*
243  *      rbtree callback function
244  */
245 static int data_cmp(const void *a, const void *b)
246 {
247         int rcode;
248
249         const CONF_DATA *one = a;
250         const CONF_DATA *two = b;
251
252         rcode = one->flag - two->flag;
253         if (rcode != 0) return rcode;
254
255         return strcmp(one->name, two->name);
256 }
257
258
259 /*
260  *      Free strings we've parsed into data structures.
261  */
262 static void cf_section_parse_free(void *base, const CONF_PARSER *variables)
263 {
264         int i;
265
266         /*
267          *      Don't automatically free the strings if we're being
268          *      called from a module.  This is also for clients.c,
269          *      where client_free() expects to be able to free the
270          *      client structure.  If we moved everything to key off
271          *      of the config files, we might solve some problems...
272          */
273         if (!variables) return;
274
275         /*
276          *      Free up dynamically allocated string pointers.
277          */
278         for (i = 0; variables[i].name != NULL; i++) {
279                 char **p;
280
281                 if ((variables[i].type != PW_TYPE_STRING_PTR) &&
282                     (variables[i].type != PW_TYPE_FILENAME)) {
283                         continue;
284                 }
285
286                 /*
287                  *      No base struct offset, data must be the pointer.
288                  *      If data doesn't exist, ignore the entry, there
289                  *      must be something wrong.
290                  */
291                 if (!base) {
292                         if (!variables[i].data) {
293                                 continue;
294                         }
295
296                         p = (char **) variables[i].data;;
297
298                 } else if (variables[i].data) {
299                         p = (char **) variables[i].data;;
300
301                 } else {
302                         p = (char **) (((char *)base) + variables[i].offset);
303                 }
304
305                 free(*p);
306                 *p = NULL;
307         }
308 }
309
310
311 /*
312  *      Free a CONF_SECTION
313  */
314 void cf_section_free(CONF_SECTION **cs)
315 {
316         CONF_ITEM       *ci, *next;
317
318         if (!cs || !*cs) return;
319
320         if ((*cs)->variables) {
321                 cf_section_parse_free((*cs)->base, (*cs)->variables);
322         }
323
324         for (ci = (*cs)->children; ci; ci = next) {
325                 next = ci->next;
326
327                 switch (ci->type) {
328                 case CONF_ITEM_PAIR: {
329                                 CONF_PAIR *pair = cf_itemtopair(ci);
330                                 cf_pair_free(&pair);
331                         }
332                         break;
333
334                 case CONF_ITEM_SECTION: {
335                                 
336                                 CONF_SECTION *section = cf_itemtosection(ci);
337                                 cf_section_free(&section);
338                         }
339                         break;
340
341                 case CONF_ITEM_DATA: {
342                                 CONF_DATA *data = cf_itemtodata(ci);
343                                 cf_data_free(&data);
344                         }
345                         break;
346
347                 default:        /* should really be an error. */
348                         break;
349                 }
350         }
351
352         if ((*cs)->name1)
353                 free((*cs)->name1);
354         if ((*cs)->name2)
355                 free((*cs)->name2);
356         if ((*cs)->pair_tree)
357                 rbtree_free((*cs)->pair_tree);
358         if ((*cs)->section_tree)
359                 rbtree_free((*cs)->section_tree);
360         if ((*cs)->name2_tree)
361                 rbtree_free((*cs)->name2_tree);
362         if ((*cs)->data_tree)
363                 rbtree_free((*cs)->data_tree);
364
365         /*
366          * And free the section
367          */
368 #ifndef NDEBUG
369         memset(*cs, 0, sizeof(*cs));
370 #endif
371         free(*cs);
372
373         *cs = NULL;
374 }
375
376
377 /*
378  *      Allocate a CONF_SECTION
379  */
380 static CONF_SECTION *cf_section_alloc(const char *name1, const char *name2,
381                                       CONF_SECTION *parent)
382 {
383         CONF_SECTION    *cs;
384
385         if (!name1) return NULL;
386
387         cs = rad_malloc(sizeof(*cs));
388         memset(cs, 0, sizeof(*cs));
389         cs->item.type = CONF_ITEM_SECTION;
390         cs->item.parent = parent;
391         cs->name1 = strdup(name1);
392         if (!cs->name1) {
393                 cf_section_free(&cs);
394                 return NULL;
395         }
396         
397         if (name2 && *name2) {
398                 cs->name2 = strdup(name2);
399                 if (!cs->name2) {
400                         cf_section_free(&cs);
401                         return NULL;
402                 }
403         }
404         cs->pair_tree = rbtree_create(pair_cmp, NULL, 0);
405         if (!cs->pair_tree) {
406                 cf_section_free(&cs);
407                 return NULL;
408         }
409
410         /*
411          *      Don't create a data tree, it may not be needed.
412          */
413
414         /*
415          *      Don't create the section tree here, it may not
416          *      be needed.
417          */
418         return cs;
419 }
420
421
422 /*
423  *      Add an item to a configuration section.
424  */
425 static void cf_item_add(CONF_SECTION *cs, CONF_ITEM *ci)
426 {
427         if (!cs->children) {
428                 rad_assert(cs->tail == NULL);
429                 cs->children = ci;
430         } else {
431                 rad_assert(cs->tail != NULL);
432                 cs->tail->next = ci;
433         }
434
435         /*
436          *      Update the trees (and tail) for each item added.
437          */
438         for (/* nothing */; ci != NULL; ci = ci->next) {
439                 cs->tail = ci;
440
441                 /*
442                  *      For fast lookups, pair's and sections get
443                  *      added to rbtree's.
444                  */
445                 switch (ci->type) {
446                         case CONF_ITEM_PAIR:
447                                 rbtree_insert(cs->pair_tree, ci);
448                                 break;
449                                 
450                         case CONF_ITEM_SECTION: {
451                                 const CONF_SECTION *cs_new = cf_itemtosection(ci);
452                                 
453                                 if (!cs->section_tree) {
454                                         cs->section_tree = rbtree_create(section_cmp, NULL, 0);
455                                         /* ignore any errors */
456                                 }
457                                 
458                                 if (cs->section_tree) {
459                                         rbtree_insert(cs->section_tree, cs_new);                                }
460                                 
461                                 /*
462                                  *      Two names: find the named instance.
463                                  */
464                                 if (cs_new->name2) {
465                                         CONF_SECTION *old_cs;
466                                         
467                                         /*
468                                          *      Find the FIRST
469                                          *      CONF_SECTION having
470                                          *      the given name1, and
471                                          *      create a new tree
472                                          *      under it.
473                                          */
474                                         old_cs = rbtree_finddata(cs->section_tree, cs_new);
475                                         if (!old_cs) return; /* this is a bad error! */
476                                         
477                                         if (!old_cs->name2_tree) {
478                                                 old_cs->name2_tree = rbtree_create(name2_cmp,
479                                                                                    NULL, 0);
480                                         }
481                                         if (old_cs->name2_tree) {
482                                                 rbtree_insert(old_cs->name2_tree, cs_new);
483                                         }
484                                 } /* had a name2 */
485                                 break;
486                         } /* was a section */
487
488                         case CONF_ITEM_DATA:
489                                 if (!cs->data_tree) {
490                                         cs->data_tree = rbtree_create(data_cmp, NULL, 0);
491                                 }
492                                 if (cs->data_tree) {
493                                         rbtree_insert(cs->data_tree, ci);
494                                 }
495                                 break;
496
497                         default: /* FIXME: assert & error! */
498                                 break;
499
500                 } /* switch over conf types */
501         } /* loop over ci */
502 }
503
504 /*
505  *      Expand the variables in an input string.
506  */
507 static const char *cf_expand_variables(const char *cf, int *lineno,
508                                        const CONF_SECTION *outercs,
509                                        char *output, const char *input)
510 {
511         char *p;
512         const char *end, *ptr;
513         char name[8192];
514         const CONF_SECTION *parentcs;
515
516         /*
517          *      Find the master parent conf section.
518          *      We can't use mainconfig.config, because we're in the
519          *      process of re-building it, and it isn't set up yet...
520          */
521         for (parentcs = outercs;
522              parentcs->item.parent != NULL;
523              parentcs = parentcs->item.parent) {
524                 /* do nothing */
525         }
526
527         p = output;
528         ptr = input;
529         while (*ptr) {
530                 /*
531                  *      Ignore anything other than "${"
532                  */
533                 if ((*ptr == '$') && (ptr[1] == '{')) {
534                         int up;
535                         CONF_PAIR *cp;
536                         const CONF_SECTION *cs;
537
538                         /*
539                          *      FIXME: Add support for ${foo:-bar},
540                          *      like in xlat.c
541                          */
542
543                         /*
544                          *      Look for trailing '}', and log a
545                          *      warning for anything that doesn't match,
546                          *      and exit with a fatal error.
547                          */
548                         end = strchr(ptr, '}');
549                         if (end == NULL) {
550                                 *p = '\0';
551                                 radlog(L_INFO, "%s[%d]: Variable expansion missing }",
552                                        cf, *lineno);
553                                 return NULL;
554                         }
555
556                         ptr += 2;
557
558                         cp = NULL;
559                         up = 0;
560
561                         /*
562                          *      ${.foo} means "foo from the current section"
563                          */
564                         if (*ptr == '.') {
565                                 up = 1;
566                                 cs = outercs;
567                                 ptr++;
568
569                                 /*
570                                  *      ${..foo} means "foo from the section
571                                  *      enclosing this section" (etc.)
572                                  */
573                                 while (*ptr == '.') {
574                                         if (cs->item.parent)
575                                                 cs = cs->item.parent;
576                                         ptr++;
577                                 }
578
579                         } else {
580                                 const char *q;
581                                 /*
582                                  *      ${foo} is local, with
583                                  *      main as lower priority
584                                  */
585                                 cs = outercs;
586
587                                 /*
588                                  *      ${foo.bar.baz} is always rooted
589                                  *      from the top.
590                                  */
591                                 for (q = ptr; *q && q != end; q++) {
592                                         if (*q == '.') {
593                                                 cs = parentcs;
594                                                 up = 1;
595                                                 break;
596                                         }
597                                 }
598                         }
599
600                         while (cp == NULL) {
601                                 char *q;
602                                 /*
603                                  *      Find the next section.
604                                  */
605                                 for (q = name;
606                                      (*ptr != 0) && (*ptr != '.') &&
607                                              (ptr != end);
608                                      q++, ptr++) {
609                                         *q = *ptr;
610                                 }
611                                 *q = '\0';
612
613                                 /*
614                                  *      The character is a '.', find a
615                                  *      section (as the user has given
616                                  *      us a subsection to find)
617                                  */
618                                 if (*ptr == '.') {
619                                         CONF_SECTION *next;
620
621                                         ptr++;  /* skip the period */
622
623                                         /*
624                                          *      Find the sub-section.
625                                          */
626                                         next = cf_section_sub_find(cs, name);
627                                         if (next == NULL) {
628                                                 radlog(L_ERR, "config: No such section %s in variable %s", name, input);
629                                                 return NULL;
630                                         }
631                                         cs = next;
632
633                                 } else { /* no period, must be a conf-part */
634                                         /*
635                                          *      Find in the current referenced
636                                          *      section.
637                                          */
638                                         cp = cf_pair_find(cs, name);
639                                         if (cp == NULL) {
640                                                 /*
641                                                  *      It it was NOT ${..foo}
642                                                  *      then look in the
643                                                  *      top-level config items.
644                                                  */
645                                                 if (!up) cp = cf_pair_find(parentcs, name);
646                                         }
647                                         if (cp == NULL) {
648                                                 radlog(L_ERR, "config: No such configuration item %s in section %s when expanding string \"%s\"", name,
649                                                        cf_section_name1(cs),
650                                                        input);
651                                                 return NULL;
652                                         }
653                                 }
654                         } /* until cp is non-NULL */
655
656                         /*
657                          *  Substitute the value of the variable.
658                          */
659                         strcpy(p, cp->value);
660                         p += strlen(p);
661                         ptr = end + 1;
662
663                 } else if (memcmp(ptr, "$ENV{", 5) == 0) {
664                         char *env;
665
666                         ptr += 5;
667
668                         /*
669                          *      Look for trailing '}', and log a
670                          *      warning for anything that doesn't match,
671                          *      and exit with a fatal error.
672                          */
673                         end = strchr(ptr, '}');
674                         if (end == NULL) {
675                                 *p = '\0';
676                                 radlog(L_INFO, "%s[%d]: Environment variable expansion missing }",
677                                        cf, *lineno);
678                                 return NULL;
679                         }
680
681                         memcpy(name, ptr, end - ptr);
682                         name[end - ptr] = '\0';
683
684                         /*
685                          *      Get the environment variable.
686                          *      If none exists, then make it an empty string.
687                          */
688                         env = getenv(name);
689                         if (env == NULL) {
690                                 *name = '\0';
691                                 env = name;
692                         }
693
694                         strcpy(p, env);
695                         p += strlen(p);
696                         ptr = end + 1;
697
698                 } else {
699                         /*
700                          *      Copy it over verbatim.
701                          */
702                         *(p++) = *(ptr++);
703                 }
704         } /* loop over all of the input string. */
705
706         *p = '\0';
707
708         return output;
709 }
710
711
712 /*
713  *      Parses an item (not a CONF_ITEM) into the specified format,
714  *      with a default value.
715  *
716  *      Returns -1 on error, 0 for correctly parsed, and 1 if the
717  *      default value was used.  Note that the default value will be
718  *      used ONLY if the CONF_PAIR is NULL.
719  */
720 int cf_item_parse(CONF_SECTION *cs, const char *name,
721                   int type, void *data, const char *dflt)
722 {
723         int rcode = 0;
724         char **q;
725         const char *value;
726         lrad_ipaddr_t ipaddr;
727         const CONF_PAIR *cp;
728         char ipbuf[128];
729
730         cp = cf_pair_find(cs, name);
731         if (cp) {
732                 value = cp->value;
733
734         } else if (!dflt) {
735                 return 1;       /* nothing to parse, return default value */
736
737         } else {
738                 rcode = 1;
739                 value = dflt;
740         }
741
742         switch (type) {
743         case PW_TYPE_BOOLEAN:
744                 /*
745                  *      Allow yes/no and on/off
746                  */
747                 if ((strcasecmp(value, "yes") == 0) ||
748                     (strcasecmp(value, "on") == 0)) {
749                         *(int *)data = 1;
750                 } else if ((strcasecmp(value, "no") == 0) ||
751                            (strcasecmp(value, "off") == 0)) {
752                         *(int *)data = 0;
753                 } else {
754                         *(int *)data = 0;
755                         radlog(L_ERR, "Bad value \"%s\" for boolean variable %s", value, name);
756                         return -1;
757                 }
758                 if (cs->name2) {
759                         DEBUG2(" %s %s: %s = %s", cs->name1, cs->name2, name, value);
760                 } else {
761                         DEBUG2(" %s: %s = %s", cs->name1, name, value);
762                 }
763                 break;
764                 
765         case PW_TYPE_INTEGER:
766                 *(int *)data = strtol(value, 0, 0);
767                 if (cs->name2) {
768                         DEBUG2(" %s %s: %s = %d",
769                                cs->name1, cs->name2, name,
770                                *(int *)data);
771                 } else {
772                         DEBUG2(" %s: %s = %d",
773                                cs->name1, name,
774                                *(int *)data);
775                 }
776                 break;
777                 
778         case PW_TYPE_STRING_PTR:
779                 q = (char **) data;
780                 if (*q != NULL) {
781                         free(*q);
782                 }
783                 
784                 /*
785                  *      Expand variables which haven't already been
786                  *      expanded automagically when the configuration
787                  *      file was read.
788                  */
789                 if (value == dflt) {
790                         char buffer[8192];
791
792                         int lineno = cs->item.lineno;
793
794                         /*
795                          *      FIXME: sizeof(buffer)?
796                          */
797                         value = cf_expand_variables("?",
798                                                     &lineno,
799                                                     cs, buffer, value);
800                         if (!value) return -1;
801                 }
802                 
803                 if (cs->name2) {
804                         DEBUG2(" %s %s: %s = \"%s\"",
805                                cs->name1, cs->name2, name,
806                                value ? value : "(null)");
807                 } else {
808                         DEBUG2(" %s: %s = \"%s\"",
809                                cs->name1, name,
810                                value ? value : "(null)");
811                 }
812                 *q = value ? strdup(value) : NULL;
813                 break;
814                 
815                 /*
816                  *      This is the same as PW_TYPE_STRING_PTR,
817                  *      except that we also "stat" the file, and
818                  *      cache the result.
819                  */
820         case PW_TYPE_FILENAME:
821                 q = (char **) data;
822                 if (*q != NULL) {
823                         free(*q);
824                 }
825                 
826                 /*
827                  *      Expand variables which haven't already been
828                  *      expanded automagically when the configuration
829                  *      file was read.
830                  */
831                 if (value == dflt) {
832                         char buffer[8192];
833
834                         int lineno = cs->item.lineno;
835
836                         /*
837                          *      FIXME: sizeof(buffer)?
838                          */
839                         value = cf_expand_variables("?",
840                                                     &lineno,
841                                                     cs, buffer, value);
842                         if (!value) return -1;
843                 }
844                 
845                 if (cs->name2) {
846                         DEBUG2(" %s %s: %s = \"%s\"",
847                                cs->name1, cs->name2, name,
848                                value ? value : "(null)");
849                 } else {
850                         DEBUG2(" %s: %s = \"%s\"",
851                                cs->name1, name,
852                                value ? value : "(null)");
853                 }
854                 *q = value ? strdup(value) : NULL;
855
856                 /*
857                  *      And now we "stat" the file.
858                  */
859                 if (*q) {
860                         struct stat buf;
861
862                         if (stat(*q, &buf) == 0) {
863                                 time_t *mtime;
864
865                                 mtime = rad_malloc(sizeof(*mtime));
866                                 *mtime = buf.st_mtime;
867                                 /* FIXME: error? */
868                                 cf_data_add_internal(cs, *q, mtime, free,
869                                                      PW_TYPE_FILENAME);
870                         }
871                 }
872                 break;
873
874         case PW_TYPE_IPADDR:
875                 /*
876                  *      Allow '*' as any address
877                  */
878                 if (strcmp(value, "*") == 0) {
879                         *(uint32_t *) data = htonl(INADDR_ANY);
880                         DEBUG2(" %s: %s = *", cs->name1, name);
881                         break;
882                 }
883                 if (ip_hton(value, AF_INET, &ipaddr) < 0) {
884                         radlog(L_ERR, "Can't find IP address for host %s", value);
885                         return -1;
886                 }
887                 if (cs->name2) {
888                         DEBUG2(" %s %s: %s = %s IP address [%s]",
889                                cs->name1, cs->name2, name, value,
890                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
891                 } else {
892                         DEBUG2(" %s: %s = %s IP address [%s]",
893                                cs->name1, name, value,
894                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
895                 }
896                 *(uint32_t *) data = ipaddr.ipaddr.ip4addr.s_addr;
897                 break;
898                 
899         case PW_TYPE_IPV6ADDR:
900                 if (ip_hton(value, AF_INET6, &ipaddr) < 0) {
901                         radlog(L_ERR, "Can't find IPv6 address for host %s", value);
902                         return -1;
903                 }
904                 if (cs->name2) {
905                         DEBUG2(" %s %s: %s = %s IPv6 address [%s]",
906                                cs->name1, cs->name2, name, value,
907                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
908                 } else {
909                         DEBUG2(" %s: %s = %s IPv6 address [%s]",
910                                cs->name1, name, value,
911                                ip_ntoh(&ipaddr, ipbuf, sizeof(ipbuf)));
912                 }
913                 memcpy(data, &ipaddr.ipaddr.ip6addr,
914                        sizeof(ipaddr.ipaddr.ip6addr));
915                 break;
916                 
917         default:
918                 radlog(L_ERR, "type %d not supported yet", type);
919                 return -1;
920                 break;
921         } /* switch over variable type */
922         
923         return rcode;
924 }
925
926 /*
927  *      Parse a configuration section into user-supplied variables.
928  */
929 int cf_section_parse(CONF_SECTION *cs, void *base,
930                      const CONF_PARSER *variables)
931 {
932         int i;
933         void *data;
934
935         /*
936          *      Handle the known configuration parameters.
937          */
938         for (i = 0; variables[i].name != NULL; i++) {
939                 /*
940                  *      Handle subsections specially
941                  */
942                 if (variables[i].type == PW_TYPE_SUBSECTION) {
943                         const CONF_SECTION *subcs;
944                         subcs = cf_section_sub_find(cs, variables[i].name);
945                         
946                         /*
947                          *      If the configuration section is NOT there,
948                          *      then ignore it.
949                          *
950                          *      FIXME! This is probably wrong... we should
951                          *      probably set the items to their default values.
952                          */
953                         if (!subcs) continue;
954
955                         if (!variables[i].dflt) {
956                                 DEBUG2("Internal sanity check 1 failed in cf_section_parse");
957                                 cf_section_parse_free(base, variables);
958                                 return -1;
959                         }
960                         
961                         if (cf_section_parse(subcs, base,
962                                              (const CONF_PARSER *) variables[i].dflt) < 0) {
963                                 cf_section_parse_free(base, variables);
964                                 return -1;
965                         }
966                         continue;
967                 } /* else it's a CONF_PAIR */
968                 
969                 if (variables[i].data) {
970                         data = variables[i].data; /* prefer this. */
971                 } else if (base) {
972                         data = ((char *)base) + variables[i].offset;
973                 } else {
974                         DEBUG2("Internal sanity check 2 failed in cf_section_parse");
975                         cf_section_parse_free(base, variables);
976                         return -1;
977                 }
978
979                 /*
980                  *      Parse the pair we found, or a default value.
981                  */
982                 if (cf_item_parse(cs, variables[i].name, variables[i].type,
983                                   data, variables[i].dflt) < 0) {
984                         cf_section_parse_free(base, variables);
985                         return -1;
986                 }
987         } /* for all variables in the configuration section */
988
989         cs->base = base;
990         cs->variables = variables;
991
992         return 0;
993 }
994
995
996 /*
997  *      Read a part of the config file.
998  */
999 static int cf_section_read(const char *file, int *lineno, FILE *fp,
1000                            CONF_SECTION *current)
1001
1002 {
1003         CONF_SECTION *this, *css;
1004         CONF_PAIR *cpn;
1005         char *ptr;
1006         const char *value;
1007         char buf[8192];
1008         char buf1[8192];
1009         char buf2[8192];
1010         char buf3[8192];
1011         int t1, t2, t3;
1012         char *cbuf = buf;
1013         int len;
1014
1015         this = current;         /* add items here */
1016
1017         /*
1018          *      Read, checking for line continuations ('\\' at EOL)
1019          */
1020         for (;;) {
1021                 int eof;
1022
1023                 /*
1024                  *      Get data, and remember if we are at EOF.
1025                  */
1026                 eof = (fgets(cbuf, sizeof(buf) - (cbuf - buf), fp) == NULL);
1027                 (*lineno)++;
1028
1029                 len = strlen(cbuf);
1030
1031                 /*
1032                  *      We've filled the buffer, and there isn't
1033                  *      a CR in it.  Die!
1034                  */
1035                 if ((len == (sizeof(buf) - 1)) &&
1036                     (cbuf[len - 1] != '\n')) {
1037                         radlog(L_ERR, "%s[%d]: Line too long",
1038                                file, *lineno);
1039                         return -1;
1040                 }
1041
1042                 /*
1043                  *  Check for continuations.
1044                  */
1045                 if (cbuf[len - 1] == '\n') len--;
1046
1047                 /*
1048                  *      Last character is '\\'.  Over-write it,
1049                  *      and read another line.
1050                  */
1051                 if ((len > 0) && (cbuf[len - 1] == '\\')) {
1052                         cbuf[len - 1] = '\0';
1053                         cbuf += len - 1;
1054                         continue;
1055                 }
1056
1057                 /*
1058                  *  We're at EOF, and haven't read anything.  Stop.
1059                  */
1060                 if (eof && (cbuf == buf)) {
1061                         break;
1062                 }
1063
1064                 ptr = cbuf = buf;
1065                 t1 = gettoken(&ptr, buf1, sizeof(buf1));
1066
1067                if ((*buf1 == '#') || (*buf1 == '\0')) {
1068                        continue;
1069                }
1070
1071                 /*
1072                  *      The caller eats "name1 name2 {", and calls us
1073                  *      for the data inside of the section.  So if we
1074                  *      receive a closing brace, then it must mean the
1075                  *      end of the section.
1076                  */
1077                if (t1 == T_RCBRACE) {
1078                        if (this == current) {
1079                                radlog(L_ERR, "%s[%d]: Too many closing braces",
1080                                       file, *lineno);
1081                                return -1;
1082                                
1083                        }
1084                        this = this->item.parent;
1085                        continue;
1086                 }
1087
1088                 /*
1089                  *      Allow for $INCLUDE files
1090                  *
1091                  *      This *SHOULD* work for any level include.
1092                  *      I really really really hate this file.  -cparker
1093                  */
1094                 if (strcasecmp(buf1, "$INCLUDE") == 0) {
1095                         t2 = getword(&ptr, buf2, sizeof(buf2));
1096
1097                         value = cf_expand_variables(file, lineno, this, buf, buf2);
1098                         if (!value) return -1;
1099
1100 #ifdef HAVE_DIRENT_H
1101                         /*
1102                          *      $INCLUDE foo/
1103                          *
1104                          *      Include ALL non-"dot" files in the directory.
1105                          *      careful!
1106                          */
1107                         if (value[strlen(value) - 1] == '/') {
1108                                 DIR             *dir;
1109                                 struct dirent   *dp;
1110                                 struct stat stat_buf;
1111
1112                                 DEBUG2( "Config:   including files in directory: %s", value );
1113                                 dir = opendir(value);
1114                                 if (!dir) {
1115                                         radlog(L_ERR, "%s[%d]: Error reading directory %s: %s",
1116                                                file, *lineno, value,
1117                                                strerror(errno));
1118                                         return -1;
1119                                 }
1120
1121                                 /*
1122                                  *      Read the directory, ignoring "." files.
1123                                  */
1124                                 while ((dp = readdir(dir)) != NULL) {
1125                                         const char *p;
1126
1127                                         if (dp->d_name[0] == '.') continue;
1128
1129                                         /*
1130                                          *      Check for valid characters
1131                                          */
1132                                         for (p = dp->d_name; *p != '\0'; p++) {
1133                                                 if (isalpha((int)*p) ||
1134                                                     isdigit((int)*p) ||
1135                                                     (*p == '_') ||
1136                                                     (*p == '.')) continue;
1137                                                 break;
1138                                         }
1139                                         if (*p != '\0') continue;
1140
1141                                         snprintf(buf2, sizeof(buf2), "%s%s",
1142                                                  value, dp->d_name);
1143                                         if ((stat(buf2, &stat_buf) != 0) ||
1144                                             S_ISDIR(stat_buf.st_mode)) continue;
1145                                         /*
1146                                          *      Read the file into the current
1147                                          *      configuration sectoin.
1148                                          */
1149                                         if (cf_file_include(buf2, this) < 0) {
1150                                                 closedir(dir);
1151                                                 return -1;
1152                                         }
1153                                 }
1154                                 closedir(dir);
1155                         }  else
1156 #endif
1157                         { /* it was a normal file */
1158                                 if (cf_file_include(value, this) < 0) {
1159                                         return -1;
1160                                 }
1161                         }
1162                         continue;
1163                 } /* we were in an include */
1164
1165                 /*
1166                  *      No '=': must be a section or sub-section.
1167                  */
1168                 if (strchr(ptr, '=') == NULL) {
1169                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
1170                         t3 = gettoken(&ptr, buf3, sizeof(buf3));
1171                 } else {
1172                         t2 = gettoken(&ptr, buf2, sizeof(buf2));
1173                         t3 = getword(&ptr, buf3, sizeof(buf3));
1174                 }
1175
1176                 /*
1177                  * Perhaps a subsection.
1178                  */
1179                 if (t2 == T_LCBRACE || t3 == T_LCBRACE) {
1180                         css = cf_section_alloc(buf1,
1181                                                t2 == T_LCBRACE ? NULL : buf2,
1182                                                this);
1183                         if (!css) {
1184                                 radlog(L_ERR, "%s[%d]: Failed allocating memory for section",
1185                                                 file, *lineno);
1186                         }
1187                         cf_item_add(this, cf_sectiontoitem(css));
1188                         css->item.lineno = *lineno;
1189
1190                         /*
1191                          *      The current section is now the child section.
1192                          */
1193                         this = css;
1194                         continue;
1195                 }
1196
1197                 /*
1198                  *      Ignore semi-colons.
1199                  */
1200                 if (*buf2 == ';')
1201                         *buf2 = '\0';
1202
1203                 /*
1204                  *      Must be a normal attr = value line.
1205                  */
1206                 if (buf1[0] != 0 && buf2[0] == 0 && buf3[0] == 0) {
1207                         t2 = T_OP_EQ;
1208                 } else if (buf1[0] == 0 || buf2[0] == 0 ||
1209                            (t2 < T_EQSTART || t2 > T_EQEND)) {
1210                         radlog(L_ERR, "%s[%d]: Line is not in 'attribute = value' format",
1211                                         file, *lineno);
1212                         return -1;
1213                 }
1214
1215                 /*
1216                  *      Ensure that the user can't add CONF_PAIRs
1217                  *      with 'internal' names;
1218                  */
1219                 if (buf1[0] == '_') {
1220                         radlog(L_ERR, "%s[%d]: Illegal configuration pair name \"%s\"",
1221                                         file, *lineno, buf1);
1222                         return -1;
1223                 }
1224
1225                 /*
1226                  *      Handle variable substitution via ${foo}
1227                  */
1228                 value = cf_expand_variables(file, lineno, this, buf, buf3);
1229                 if (!value) return -1;
1230
1231
1232                 /*
1233                  *      Add this CONF_PAIR to our CONF_SECTION
1234                  */
1235                 cpn = cf_pair_alloc(buf1, value, t2, this);
1236                 cpn->item.lineno = *lineno;
1237                 cf_item_add(this, cf_pairtoitem(cpn));
1238         }
1239
1240         /*
1241          *      See if EOF was unexpected ..
1242          */
1243         if (feof(fp) && (this != current)) {
1244                 radlog(L_ERR, "%s[%d]: EOF reached without closing brace for section %s starting at line %d",
1245                        file, *lineno,
1246                        cf_section_name1(this), cf_section_lineno(this));
1247                 return -1;
1248         }
1249
1250         return 0;
1251 }
1252
1253 /*
1254  *      Include one config file in another.
1255  */
1256 int cf_file_include(const char *file, CONF_SECTION *cs)
1257 {
1258         FILE            *fp;
1259         int             lineno = 0;
1260         struct stat     statbuf;
1261         time_t          *mtime;
1262
1263         DEBUG2( "Config:   including file: %s", file);
1264
1265         if (stat(file, &statbuf) == 0) {
1266 #ifdef S_IWOTH
1267                 if ((statbuf.st_mode & S_IWOTH) != 0) {
1268                         radlog(L_ERR|L_CONS, "Configuration file %s is globally writable.  Refusing to start due to insecure configuration.",
1269                                file);
1270                         return -1;
1271                 }
1272 #endif
1273
1274 #ifdef S_IROTH
1275                 if (0 && (statbuf.st_mode & S_IROTH) != 0) {
1276                         radlog(L_ERR|L_CONS, "Configuration file %s is globally readable.  Refusing to start due to insecure configuration.",
1277                                file);
1278                         return -1;
1279                 }
1280 #endif
1281         }
1282
1283         fp = fopen(file, "r");
1284         if (!fp) {
1285                 radlog(L_ERR|L_CONS, "Unable to open file \"%s\": %s",
1286                        file, strerror(errno));
1287                 return -1;
1288         }
1289
1290         /*
1291          *      Read the section.  It's OK to have EOF without a
1292          *      matching close brace.
1293          */
1294         if (cf_section_read(file, &lineno, fp, cs) < 0) {
1295                 fclose(fp);
1296                 return -1;
1297         }
1298
1299         /*
1300          *      Add the filename to the section
1301          */
1302         mtime = rad_malloc(sizeof(*mtime));
1303         *mtime = statbuf.st_mtime;
1304         /* FIXME: error? */
1305         cf_data_add_internal(cs, file, mtime, free,
1306                              PW_TYPE_FILENAME);
1307
1308         fclose(fp);
1309         return 0;
1310 }
1311
1312 /*
1313  *      Bootstrap a config file.
1314  */
1315 CONF_SECTION *cf_file_read(const char *file)
1316 {
1317         CONF_SECTION *cs;
1318
1319         cs = cf_section_alloc("main", NULL, NULL);
1320         if (!cs) return NULL;
1321
1322         if (cf_file_include(file, cs) < 0) {
1323                 cf_section_free(&cs);
1324                 return NULL;
1325         }
1326
1327         return cs;
1328 }
1329
1330 /*
1331  * Return a CONF_PAIR within a CONF_SECTION.
1332  */
1333 CONF_PAIR *cf_pair_find(const CONF_SECTION *cs, const char *name)
1334 {
1335         CONF_ITEM       *ci;
1336         CONF_PAIR       *cp = NULL;
1337
1338         if (!cs) cs = mainconfig.config;
1339
1340         /*
1341          *      Find the name in the tree, for speed.
1342          */
1343         if (name) {
1344                 CONF_PAIR mycp;
1345
1346                 mycp.attr = name;
1347                 cp = rbtree_finddata(cs->pair_tree, &mycp);
1348         } else {
1349                 /*
1350                  *      Else find the first one that matches
1351                  */
1352                 for (ci = cs->children; ci; ci = ci->next) {
1353                         if (ci->type == CONF_ITEM_PAIR) {
1354                                 return cf_itemtopair(ci);
1355                         }
1356                 }
1357         }
1358
1359         if (cp || !cs->template) return cp;
1360
1361         return cf_pair_find(cs->template, name);
1362 }
1363
1364 /*
1365  * Return the attr of a CONF_PAIR
1366  */
1367
1368 char *cf_pair_attr(CONF_PAIR *pair)
1369 {
1370         return (pair ? pair->attr : NULL);
1371 }
1372
1373 /*
1374  * Return the value of a CONF_PAIR
1375  */
1376
1377 char *cf_pair_value(CONF_PAIR *pair)
1378 {
1379         return (pair ? pair->value : NULL);
1380 }
1381
1382 /*
1383  * Return the first label of a CONF_SECTION
1384  */
1385
1386 const char *cf_section_name1(const CONF_SECTION *cs)
1387 {
1388         return (cs ? cs->name1 : NULL);
1389 }
1390
1391 /*
1392  * Return the second label of a CONF_SECTION
1393  */
1394
1395 const char *cf_section_name2(const CONF_SECTION *cs)
1396 {
1397         return (cs ? cs->name2 : NULL);
1398 }
1399
1400 /*
1401  * Find a value in a CONF_SECTION
1402  */
1403 char *cf_section_value_find(const CONF_SECTION *cs, const char *attr)
1404 {
1405         CONF_PAIR       *cp;
1406
1407         cp = cf_pair_find(cs, attr);
1408
1409         return (cp ? cp->value : NULL);
1410 }
1411
1412 /*
1413  * Return the next pair after a CONF_PAIR
1414  * with a certain name (char *attr) If the requested
1415  * attr is NULL, any attr matches.
1416  */
1417
1418 CONF_PAIR *cf_pair_find_next(const CONF_SECTION *cs,
1419                              const CONF_PAIR *pair, const char *attr)
1420 {
1421         CONF_ITEM       *ci;
1422
1423         /*
1424          * If pair is NULL this must be a first time run
1425          * Find the pair with correct name
1426          */
1427
1428         if (pair == NULL){
1429                 return cf_pair_find(cs, attr);
1430         }
1431
1432         ci = cf_pairtoitem(pair)->next;
1433
1434         for (; ci; ci = ci->next) {
1435                 if (ci->type != CONF_ITEM_PAIR)
1436                         continue;
1437                 if (attr == NULL || strcmp(cf_itemtopair(ci)->attr, attr) == 0)
1438                         break;
1439         }
1440
1441         return cf_itemtopair(ci);
1442 }
1443
1444 /*
1445  * Find a CONF_SECTION, or return the root if name is NULL
1446  */
1447
1448 CONF_SECTION *cf_section_find(const char *name)
1449 {
1450         if (name)
1451                 return cf_section_sub_find(mainconfig.config, name);
1452         else
1453                 return mainconfig.config;
1454 }
1455
1456 /*
1457  * Find a sub-section in a section
1458  */
1459
1460 CONF_SECTION *cf_section_sub_find(const CONF_SECTION *cs, const char *name)
1461 {
1462         CONF_ITEM *ci;
1463
1464         /*
1465          *      Do the fast lookup if possible.
1466          */
1467         if (name && cs->section_tree) {
1468                 CONF_SECTION mycs;
1469
1470                 mycs.name1 = name;
1471                 mycs.name2 = NULL;
1472                 return rbtree_finddata(cs->section_tree, &mycs);
1473         }
1474
1475         for (ci = cs->children; ci; ci = ci->next) {
1476                 if (ci->type != CONF_ITEM_SECTION)
1477                         continue;
1478                 if (strcmp(cf_itemtosection(ci)->name1, name) == 0)
1479                         break;
1480         }
1481
1482         return cf_itemtosection(ci);
1483
1484 }
1485
1486
1487 /*
1488  *      Find a CONF_SECTION with both names.
1489  */
1490 CONF_SECTION *cf_section_sub_find_name2(const CONF_SECTION *cs,
1491                                         const char *name1, const char *name2)
1492 {
1493         CONF_ITEM    *ci;
1494
1495         if (!name2) return cf_section_sub_find(cs, name1);
1496
1497         if (!cs) cs = mainconfig.config;
1498
1499         if (name1 && (cs->section_tree)) {
1500                 CONF_SECTION mycs, *master_cs;
1501                 
1502                 mycs.name1 = name1;
1503                 mycs.name2 = name2;
1504                 
1505                 master_cs = rbtree_finddata(cs->section_tree, &mycs);
1506                 if (master_cs) {
1507                         return rbtree_finddata(master_cs->name2_tree, &mycs);
1508                 }
1509         }
1510
1511         /*
1512          *      Else do it the old-fashioned way.
1513          */
1514         for (ci = cs->children; ci; ci = ci->next) {
1515                 CONF_SECTION *subcs;
1516
1517                 if (ci->type != CONF_ITEM_SECTION)
1518                         continue;
1519
1520                 subcs = cf_itemtosection(ci);
1521                 if (!name1) {
1522                         if (!subcs->name2) {
1523                                 if (strcmp(subcs->name1, name2) == 0) break;
1524                         } else {
1525                                 if (strcmp(subcs->name2, name2) == 0) break;
1526                         }
1527                         continue; /* don't do the string comparisons below */
1528                 }
1529
1530                 if ((strcmp(subcs->name1, name1) == 0) &&
1531                     (subcs->name2 != NULL) &&
1532                     (strcmp(subcs->name2, name2) == 0))
1533                         break;
1534         }
1535
1536         return cf_itemtosection(ci);
1537 }
1538
1539 /*
1540  * Return the next subsection after a CONF_SECTION
1541  * with a certain name1 (char *name1). If the requested
1542  * name1 is NULL, any name1 matches.
1543  */
1544
1545 CONF_SECTION *cf_subsection_find_next(CONF_SECTION *section,
1546                                       CONF_SECTION *subsection,
1547                                       const char *name1)
1548 {
1549         CONF_ITEM       *ci;
1550
1551         /*
1552          * If subsection is NULL this must be a first time run
1553          * Find the subsection with correct name
1554          */
1555
1556         if (subsection == NULL){
1557                 ci = section->children;
1558         } else {
1559                 ci = cf_sectiontoitem(subsection)->next;
1560         }
1561
1562         for (; ci; ci = ci->next) {
1563                 if (ci->type != CONF_ITEM_SECTION)
1564                         continue;
1565                 if ((name1 == NULL) ||
1566                     (strcmp(cf_itemtosection(ci)->name1, name1) == 0))
1567                         break;
1568         }
1569
1570         return cf_itemtosection(ci);
1571 }
1572
1573 /*
1574  * Return the next item after a CONF_ITEM.
1575  */
1576
1577 CONF_ITEM *cf_item_find_next(CONF_SECTION *section, CONF_ITEM *item)
1578 {
1579         /*
1580          * If item is NULL this must be a first time run
1581          * Return the first item
1582          */
1583
1584         if (item == NULL) {
1585                 return section->children;
1586         } else {
1587                 return item->next;
1588         }
1589 }
1590
1591 int cf_section_lineno(CONF_SECTION *section)
1592 {
1593         return cf_sectiontoitem(section)->lineno;
1594 }
1595
1596 int cf_pair_lineno(CONF_PAIR *pair)
1597 {
1598         return cf_pairtoitem(pair)->lineno;
1599 }
1600
1601 int cf_item_is_section(CONF_ITEM *item)
1602 {
1603         return item->type == CONF_ITEM_SECTION;
1604 }
1605 int cf_item_is_pair(CONF_ITEM *item)
1606 {
1607         return item->type == CONF_ITEM_PAIR;
1608 }
1609
1610
1611 static CONF_DATA *cf_data_alloc(CONF_SECTION *parent, const char *name,
1612                                 void *data, void (*data_free)(void *))
1613 {
1614         CONF_DATA *cd;
1615
1616         cd = rad_malloc(sizeof(*cd));
1617         memset(cd, 0, sizeof(*cd));
1618
1619         cd->item.type = CONF_ITEM_DATA;
1620         cd->item.parent = parent;
1621         cd->name = strdup(name);
1622         cd->data = data;
1623         cd->free = data_free;
1624
1625         return cd;
1626 }
1627
1628
1629 static void *cf_data_find_internal(CONF_SECTION *cs, const char *name,
1630                                    int flag)
1631 {
1632         if (!cs || !name) return NULL;
1633         
1634         /*
1635          *      Find the name in the tree, for speed.
1636          */
1637         if (cs->data_tree) {
1638                 CONF_DATA mycd, *cd;
1639
1640                 mycd.name = name;
1641                 mycd.flag = flag;
1642                 cd = rbtree_finddata(cs->data_tree, &mycd);
1643                 if (cd) return cd->data;
1644         }
1645
1646         return NULL;
1647 }
1648
1649 /*
1650  *      Find data from a particular section.
1651  */
1652 void *cf_data_find(CONF_SECTION *cs, const char *name)
1653 {
1654         return cf_data_find_internal(cs, name, 0);
1655 }
1656
1657
1658 /*
1659  *      Add named data to a configuration section.
1660  */
1661 static int cf_data_add_internal(CONF_SECTION *cs, const char *name,
1662                                 void *data, void (*data_free)(void *),
1663                                 int flag)
1664 {
1665         CONF_DATA *cd;
1666
1667         if (!cs || !name) return -1;
1668
1669         /*
1670          *      Already exists.  Can't add it.
1671          */
1672         if (cf_data_find_internal(cs, name, flag) != NULL) return -1;
1673
1674         cd = cf_data_alloc(cs, name, data, data_free);
1675         if (!cd) return -1;
1676         cd->flag = flag;
1677
1678         cf_item_add(cs, cf_datatoitem(cd));
1679
1680         return 0;
1681 }
1682
1683 /*
1684  *      Add named data to a configuration section.
1685  */
1686 int cf_data_add(CONF_SECTION *cs, const char *name,
1687                 void *data, void (*data_free)(void *))
1688 {
1689         return cf_data_add_internal(cs, name, data, data_free, 0);
1690 }
1691
1692
1693 /*
1694  *      Copy CONF_DATA from src to dst
1695  */
1696 static void cf_section_copy_data(CONF_SECTION *s, CONF_SECTION *d)
1697 {
1698         
1699         CONF_ITEM *cd, *next, **last;
1700
1701         /*
1702          *      Don't check if s->data_tree is NULL.  It's child
1703          *      sections may have data, even if this section doesn't.
1704          */
1705
1706         rad_assert(d->data_tree == NULL);
1707         d->data_tree = s->data_tree;
1708         s->data_tree = NULL;
1709         
1710         /*
1711          *      Walk through src, moving CONF_ITEM_DATA
1712          *      to dst, by hand.
1713          */
1714         last = &(s->children);
1715         for (cd = s->children; cd != NULL; cd = next) {
1716                 next = cd->next;
1717                 
1718                 /*
1719                  *      Recursively copy data from child sections.
1720                  */
1721                 if (cd->type == CONF_ITEM_SECTION) {
1722                         CONF_SECTION *s1, *d1;
1723                         
1724                         s1 = cf_itemtosection(cd);
1725                         d1 = cf_section_sub_find_name2(d, s1->name1, s1->name2);
1726                         if (d1) {
1727                                 cf_section_copy_data(s1, d1);
1728                         }
1729                         last = &(cd->next);
1730                         continue;
1731                 }
1732
1733                 /*
1734                  *      Not conf data, remember last ptr.
1735                  */
1736                 if (cd->type != CONF_ITEM_DATA) {
1737                         last = &(cd->next);
1738                         continue;
1739                 }
1740                 
1741                 /*
1742                  *      Remove it from the src list
1743                  */
1744                 *last = cd->next;
1745                 cd->next = NULL;
1746                 
1747                 /*
1748                  *      Add it to the dst list
1749                  */
1750                 if (!d->children) {
1751                         rad_assert(d->tail == NULL);
1752                         d->children = cd;
1753                 } else {
1754                         rad_assert(d->tail != NULL);
1755                         d->tail->next = cd;
1756                 }
1757                 d->tail = cd;
1758         }
1759 }
1760
1761 /*
1762  *      For a CONF_DATA element, stat the filename, if necessary.
1763  */
1764 static int filename_stat(void *context, void *data)
1765 {
1766         struct stat buf;
1767         CONF_DATA *cd = data;
1768
1769         context = context;      /* -Wunused */
1770
1771         if (cd->flag != PW_TYPE_FILENAME) return 0;
1772
1773         if (stat(cd->name, &buf) < 0) return -1;
1774
1775         if (buf.st_mtime != *(time_t *) cd->data) return -1;
1776
1777         return 0;
1778 }
1779
1780
1781 /*
1782  *      Compare two CONF_SECTIONS.  The items MUST be in the same
1783  *      order.
1784  */
1785 static int cf_section_cmp(CONF_SECTION *a, CONF_SECTION *b)
1786 {
1787         CONF_ITEM *ca = a->children;
1788         CONF_ITEM *cb = b->children;
1789
1790         while (1) {
1791                 CONF_PAIR *pa, *pb;
1792
1793                 /*
1794                  *      Done.  Stop.
1795                  */
1796                 if (!ca && !cb) break;
1797
1798                 /*
1799                  *      Skip CONF_DATA.
1800                  */
1801                 if (ca && ca->type == CONF_ITEM_DATA) {
1802                         ca = ca->next;
1803                         continue;
1804                 }
1805                 if (cb && cb->type == CONF_ITEM_DATA) {
1806                         cb = cb->next;
1807                         continue;
1808                 }
1809
1810                 /*
1811                  *      One is smaller than the other.  Exit.
1812                  */
1813                 if (!ca || !cb) return 0;
1814
1815                 if (ca->type != cb->type) return 0;
1816
1817                 /*
1818                  *      Deal with subsections.
1819                  */
1820                 if (ca->type == CONF_ITEM_SECTION) {
1821                         CONF_SECTION *sa = cf_itemtosection(ca);
1822                         CONF_SECTION *sb = cf_itemtosection(cb);
1823
1824                         if (!cf_section_cmp(sa, sb)) return 0;
1825                         goto next;
1826                 }
1827
1828                 rad_assert(ca->type == CONF_ITEM_PAIR);
1829
1830                 pa = cf_itemtopair(ca);
1831                 pb = cf_itemtopair(cb);
1832
1833                 /*
1834                  *      Different attr and/or value, Exit.
1835                  */
1836                 if ((strcmp(pa->attr, pb->attr) != 0) ||
1837                     (strcmp(pa->value, pb->value) != 0)) return 0;
1838                 
1839
1840                 /*
1841                  *      And go to the next element.
1842                  */
1843         next:
1844                 ca = ca->next;
1845                 cb = cb->next;
1846         }
1847
1848         /*
1849          *      Walk over the CONF_DATA, stat'ing PW_TYPE_FILENAME.
1850          */
1851         if (a->data_tree &&
1852             (rbtree_walk(a->data_tree, InOrder, filename_stat, NULL) != 0)) {
1853                 return 0;
1854         }
1855
1856         /*
1857          *      They must be the same, say so.
1858          */
1859         return 1;
1860 }
1861
1862
1863 /*
1864  *      Migrate CONF_DATA from one section to another.
1865  */
1866 int cf_section_migrate(CONF_SECTION *dst, CONF_SECTION *src)
1867 {
1868         CONF_ITEM *ci;
1869         CONF_SECTION *s, *d;
1870
1871         for (ci = src->children; ci != NULL; ci = ci->next) {
1872                 if (ci->type != CONF_ITEM_SECTION)
1873                         continue;
1874
1875                 s = cf_itemtosection(ci);
1876                 d = cf_section_sub_find_name2(dst, s->name1, s->name2);
1877
1878                 if (!d) continue; /* not in new one, don't migrate it */
1879
1880                 /*
1881                  *      A section of the same name is in BOTH src & dst,
1882                  *      compare the CONF_PAIR's.  If they're all the same,
1883                  *      then copy the CONF_DATA from one to the other.
1884                  */
1885                 if (cf_section_cmp(s, d)) {
1886                         cf_section_copy_data(s, d);
1887                 }
1888         }
1889
1890         return 1;               /* rcode means anything? */
1891 }
1892
1893 int cf_section_template(CONF_SECTION *cs, CONF_SECTION *template)
1894 {
1895         if (!cs || !template || cs->template || template->template) return -1;
1896
1897         cs->template = template;
1898
1899         return 0;
1900 }
1901
1902 #if 0
1903 /*
1904  * JMG dump_config tries to dump the config structure in a readable format
1905  *
1906 */
1907
1908 static int dump_config_section(CONF_SECTION *cs, int indent)
1909 {
1910         CONF_SECTION    *scs;
1911         CONF_PAIR       *cp;
1912         CONF_ITEM       *ci;
1913
1914         /* The DEBUG macro doesn't let me
1915          *   for(i=0;i<indent;++i) debugputchar('\t');
1916          * so I had to get creative. --Pac. */
1917
1918         for (ci = cs->children; ci; ci = ci->next) {
1919                 switch (ci->type) {
1920                 case CONF_ITEM_PAIR:
1921                         cp=cf_itemtopair(ci);
1922                         DEBUG("%.*s%s = %s",
1923                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1924                                 cp->attr, cp->value);
1925                         break;
1926
1927                 case CONF_ITEM_SECTION:
1928                         scs=cf_itemtosection(ci);
1929                         DEBUG("%.*s%s %s%s{",
1930                                 indent, "\t\t\t\t\t\t\t\t\t\t\t",
1931                                 scs->name1,
1932                                 scs->name2 ? scs->name2 : "",
1933                                 scs->name2 ?  " " : "");
1934                         dump_config_section(scs, indent+1);
1935                         DEBUG("%.*s}",
1936                                 indent, "\t\t\t\t\t\t\t\t\t\t\t");
1937                         break;
1938
1939                 default:        /* FIXME: Do more! */
1940                         break;
1941                 }
1942         }
1943
1944         return 0;
1945 }
1946
1947 int dump_config(void)
1948 {
1949         return dump_config_section(mainconfig.config, 0);
1950 }
1951 #endif