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