Support for VMPS. We can now send && receive VMPS packets
[freeradius.git] / src / main / modules.c
1 /*
2  * modules.c    Radius module support.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2003,2006  The FreeRADIUS server project
21  * Copyright 2000  Alan DeKok <aland@ox.org>
22  * Copyright 2000  Alan Curry <pacman@world.std.com>
23  */
24
25 #include <freeradius-devel/ident.h>
26 RCSID("$Id$")
27
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/modpriv.h>
30 #include <freeradius-devel/modcall.h>
31 #include <freeradius-devel/rad_assert.h>
32
33 #define VMPS_SPACE (1)
34
35 typedef struct indexed_modcallable {
36         int             space;
37         int             comp;
38         int             idx;
39         modcallable     *modulelist;
40 } indexed_modcallable;
41
42 /*
43  *      For each component, keep an ordered list of ones to call.
44  */
45 static rbtree_t *components;
46
47 static rbtree_t *module_tree = NULL;
48
49 typedef struct section_type_value_t {
50         const char      *section;
51         const char      *typename;
52         int             attr;
53 } section_type_value_t;
54
55
56 /*
57  *      Ordered by component
58  */
59 static const section_type_value_t section_type_value[RLM_COMPONENT_COUNT] = {
60         { "authenticate", "Auth-Type",       PW_AUTH_TYPE },
61         { "authorize",    "Autz-Type",       PW_AUTZ_TYPE },
62         { "preacct",      "Pre-Acct-Type",   PW_PRE_ACCT_TYPE },
63         { "accounting",   "Acct-Type",       PW_ACCT_TYPE },
64         { "session",      "Session-Type",    PW_SESSION_TYPE },
65         { "pre-proxy",    "Pre-Proxy-Type",  PW_PRE_PROXY_TYPE },
66         { "post-proxy",   "Post-Proxy-Type", PW_POST_PROXY_TYPE },
67         { "post-auth",    "Post-Auth-Type",  PW_POST_AUTH_TYPE },
68 };
69
70 static void indexed_modcallable_free(void *data)
71 {
72         indexed_modcallable *c = data;
73
74         modcallable_free(&c->modulelist);
75         free(c);
76 }
77
78 static int indexed_modcallable_cmp(const void *one, const void *two)
79 {
80         const indexed_modcallable *a = one;
81         const indexed_modcallable *b = two;
82
83         if (a->space < b->space) return -1;
84         if (a->space > b->space) return +1;
85
86         if (a->comp < b->comp) return -1;
87         if (a->comp >  b->comp) return +1;
88
89         return a->idx - b->idx;
90 }
91
92
93 /*
94  *      Free a module instance.
95  */
96 static void module_instance_free(void *data)
97 {
98         module_instance_t *this = data;
99
100         if (this->entry->module->detach)
101                 (this->entry->module->detach)(this->insthandle);
102 #ifdef HAVE_PTHREAD_H
103         if (this->mutex) {
104                 /*
105                  *      FIXME
106                  *      The mutex MIGHT be locked...
107                  *      we'll check for that later, I guess.
108                  */
109                 pthread_mutex_destroy(this->mutex);
110                 free(this->mutex);
111         }
112 #endif
113         free(this);
114 }
115
116
117 /*
118  *      Compare two module entries
119  */
120 static int module_entry_cmp(const void *one, const void *two)
121 {
122         const module_entry_t *a = one;
123         const module_entry_t *b = two;
124
125         return strcmp(a->name, b->name);
126 }
127
128 /*
129  *      Free a module entry.
130  */
131 static void module_entry_free(void *data)
132 {
133         module_entry_t *this = data;
134
135         lt_dlclose(this->handle);       /* ignore any errors */
136         free(this);
137 }
138
139
140 /*
141  *      Remove the module lists.
142  */
143 int detach_modules(void)
144 {
145         rbtree_free(components);
146         rbtree_free(module_tree);
147
148         return 0;
149 }
150
151
152 /*
153  *      Find a module on disk or in memory, and link to it.
154  */
155 static module_entry_t *linkto_module(const char *module_name,
156                                      const char *cffilename, int cflineno)
157 {
158         module_entry_t myentry;
159         module_entry_t *node;
160         lt_dlhandle handle;
161         char module_struct[256];
162         char *p;
163         const void *module;
164
165         strlcpy(myentry.name, module_name, sizeof(myentry.name));
166         node = rbtree_finddata(module_tree, &myentry);
167         if (node) return node;
168
169         /*
170          *      Keep the handle around so we can dlclose() it.
171          */
172         handle = lt_dlopenext(module_name);
173         if (handle == NULL) {
174                 radlog(L_ERR|L_CONS, "%s[%d] Failed to link to module '%s':"
175                        " %s\n", cffilename, cflineno, module_name, lt_dlerror());
176                 return NULL;
177         }
178
179         /*
180          *      Link to the module's rlm_FOO{} module structure.
181          *
182          *      The module_name variable has the version number
183          *      embedded in it, and we don't want that here.
184          */
185         strcpy(module_struct, module_name);
186         p = strrchr(module_struct, '-');
187         if (p) *p = '\0';
188
189         DEBUG3("    (Loaded %s, checking if it's valid)", module_name);
190
191         /*
192          *      libltld MAY core here, if the handle it gives us contains
193          *      garbage data.
194          */
195         module = lt_dlsym(handle, module_struct);
196         if (!module) {
197                 radlog(L_ERR|L_CONS, "%s[%d] Failed linking to "
198                                 "%s structure in %s: %s\n",
199                                 cffilename, cflineno,
200                                 module_name, cffilename, lt_dlerror());
201                 lt_dlclose(handle);
202                 return NULL;
203         }
204         /*
205          *      Before doing anything else, check if it's sane.
206          */
207         if ((*(const uint32_t *) module) != RLM_MODULE_MAGIC_NUMBER) {
208                 lt_dlclose(handle);
209                 radlog(L_ERR|L_CONS, "%s[%d] Invalid version in module '%s'",
210                        cffilename, cflineno, module_name);
211                 return NULL;
212
213         }
214
215         /* make room for the module type */
216         node = rad_malloc(sizeof(*node));
217         memset(node, 0, sizeof(*node));
218         strlcpy(node->name, module_name, sizeof(node->name));
219         node->module = module;
220         node->handle = handle;
221
222         DEBUG(" Module: Linked to module %s", module_name);
223
224         /*
225          *      Add the module as "rlm_foo-version" to the configuration
226          *      section.
227          */
228         if (!rbtree_insert(module_tree, node)) {
229                 radlog(L_ERR, "Failed to cache module %s", module_name);
230                 lt_dlclose(handle);
231                 free(node);
232                 return NULL;
233         }
234
235         return node;
236 }
237
238 /*
239  *      Find a module instance.
240  */
241 module_instance_t *find_module_instance(CONF_SECTION *modules,
242                                         const char *instname)
243 {
244         CONF_SECTION *cs;
245         const char *name1, *name2;
246         module_instance_t *node;
247         char module_name[256];
248
249         if (!modules) return NULL;
250
251         /*
252          *      Module instances are declared in the modules{} block
253          *      and referenced later by their name, which is the
254          *      name2 from the config section, or name1 if there was
255          *      no name2.
256          */
257         cs = cf_section_sub_find_name2(modules, NULL, instname);
258         if (cs == NULL) {
259                 radlog(L_ERR|L_CONS, "ERROR: Cannot find a configuration entry for module \"%s\".\n", instname);
260                 return NULL;
261         }
262
263         /*
264          *      If there's already a module instance, return it.
265          */
266         node = cf_data_find(cs, "instance");
267         if (node) return node;
268
269         name1 = cf_section_name1(cs);
270         name2 = cf_section_name2(cs);
271
272         /*
273          *      Found the configuration entry.
274          */
275         node = rad_malloc(sizeof(*node));
276         memset(node, 0, sizeof(*node));
277
278         node->insthandle = NULL;
279
280         /*
281          *      Names in the "modules" section aren't prefixed
282          *      with "rlm_", so we add it here.
283          */
284         snprintf(module_name, sizeof(module_name), "rlm_%s", name1);
285
286         node->entry = linkto_module(module_name,
287                                     mainconfig.radiusd_conf,
288                                     cf_section_lineno(cs));
289         if (!node->entry) {
290                 free(node);
291                 /* linkto_module logs any errors */
292                 return NULL;
293         }
294
295         DEBUG2(" Module: Instantiating %s", instname);
296
297         /*
298          *      Call the module's instantiation routine.
299          */
300         if ((node->entry->module->instantiate) &&
301             ((node->entry->module->instantiate)(cs, &node->insthandle) < 0)) {
302                 radlog(L_ERR|L_CONS,
303                                 "%s[%d]: %s: Module instantiation failed.\n",
304                        mainconfig.radiusd_conf, cf_section_lineno(cs),
305                        instname);
306                 free(node);
307                 return NULL;
308         }
309
310         /*
311          *      We're done.  Fill in the rest of the data structure,
312          *      and link it to the module instance list.
313          */
314         strlcpy(node->name, instname, sizeof(node->name));
315
316 #ifdef HAVE_PTHREAD_H
317         /*
318          *      If we're threaded, check if the module is thread-safe.
319          *
320          *      If it isn't, we create a mutex.
321          */
322         if ((node->entry->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) {
323                 node->mutex = (pthread_mutex_t *) rad_malloc(sizeof(pthread_mutex_t));
324                 /*
325                  *      Initialize the mutex.
326                  */
327                 pthread_mutex_init(node->mutex, NULL);
328         } else {
329                 /*
330                  *      The module is thread-safe.  Don't give it a mutex.
331                  */
332                 node->mutex = NULL;
333         }
334
335 #endif
336         cf_data_add(cs, "instance", node, module_instance_free);
337
338         return node;
339 }
340
341 static indexed_modcallable *lookup_by_index(int space, int comp, int idx)
342 {
343         indexed_modcallable myc;
344
345         myc.comp = comp;
346         myc.idx = idx;
347         myc.space = space;
348
349         return rbtree_finddata(components, &myc);
350 }
351
352 /*
353  *      Create a new sublist.
354  */
355 static indexed_modcallable *new_sublist(int space, int comp, int idx)
356 {
357         indexed_modcallable *c;
358
359         c = lookup_by_index(space, comp, idx);
360
361         /* It is an error to try to create a sublist that already
362          * exists. It would almost certainly be caused by accidental
363          * duplication in the config file.
364          *
365          * index 0 is the exception, because it is used when we want
366          * to collect _all_ listed modules under a single index by
367          * default, which is currently the case in all components
368          * except authenticate. */
369         if (c) {
370                 if (idx == 0) {
371                         return c;
372                 }
373                 return NULL;
374         }
375
376         c = rad_malloc(sizeof(*c));
377         c->modulelist = NULL;
378         c->space = space;
379         c->comp = comp;
380         c->idx = idx;
381
382         if (!rbtree_insert(components, c)) {
383                 free(c);
384                 return NULL;
385         }
386
387         return c;
388 }
389
390 static int indexed_modcall(int space, int comp, int idx, REQUEST *request)
391 {
392         int rcode;
393         indexed_modcallable *this;
394
395         this = lookup_by_index(space, comp, idx);
396         if (!this) {
397                 if (idx != 0) DEBUG2("  ERROR: Unknown value specified for %s.  Cannot perform requested action.",
398                                      section_type_value[comp].typename);
399                 request->component = section_type_value[comp].typename;
400                 rcode = modcall(comp, NULL, request); /* does default action */
401         } else {
402                 DEBUG2("  Processing the %s section of %s",
403                        (space == 0) ? section_type_value[comp].section : "vmps",
404                        mainconfig.radiusd_conf);
405                 request->component = section_type_value[comp].typename;
406                 rcode = modcall(comp, this->modulelist, request);
407         }
408         request->module = "<server-core>";
409         request->component = "<server-core>";
410         return rcode;
411 }
412
413 /*
414  *      Load a sub-module list, as found inside an Auth-Type foo {}
415  *      block
416  */
417 static int load_subcomponent_section(modcallable *parent,
418                                      CONF_SECTION *cs, int space, int comp,
419                                      const char *filename)
420 {
421         indexed_modcallable *subcomp;
422         modcallable *ml;
423         DICT_VALUE *dval;
424         const char *name2 = cf_section_name2(cs);
425
426         rad_assert(comp >= RLM_COMPONENT_AUTH);
427         rad_assert(comp <= RLM_COMPONENT_COUNT);
428
429         /*
430          *      Sanity check.
431          */
432         if (!name2) {
433                 radlog(L_ERR|L_CONS,
434                        "%s[%d]: No name specified for %s block",
435                        filename, cf_section_lineno(cs),
436                        section_type_value[comp].typename);
437                 return 1;
438         }
439
440         /*
441          *      Compile the group.
442          */
443         ml = compile_modgroup(parent, comp, cs, filename);
444         if (!ml) {
445                 return 0;
446         }
447
448         /*
449          *      We must assign a numeric index to this subcomponent.
450          *      It is generated and placed in the dictionary by
451          *      setup_modules(), when it loads the sections.  If it
452          *      isn't found, it's a serious error.
453          */
454         dval = dict_valbyname(section_type_value[comp].attr, name2);
455         if (!dval) {
456                 radlog(L_ERR|L_CONS,
457                        "%s[%d] %s %s Not previously configured",
458                        filename, cf_section_lineno(cs),
459                        section_type_value[comp].typename, name2);
460                 modcallable_free(&ml);
461                 return 0;
462         }
463
464         subcomp = new_sublist(space, comp, dval->value);
465         if (!subcomp) {
466                 radlog(L_ERR|L_CONS,
467                        "%s[%d] %s %s already configured - skipping",
468                        filename, cf_section_lineno(cs),
469                        section_type_value[comp].typename, name2);
470                 modcallable_free(&ml);
471                 return 1;
472         }
473
474         subcomp->modulelist = ml;
475         return 1;               /* OK */
476 }
477
478 static int load_component_section(modcallable *parent,
479                                   CONF_SECTION *cs, int space, int comp,
480                                   const char *filename)
481 {
482         modcallable *this;
483         CONF_ITEM *modref;
484         int idx;
485         indexed_modcallable *subcomp;
486         const char *modname;
487         const char *visiblename;
488
489         /*
490          *      Loop over the entries in the named section.
491          */
492         for (modref = cf_item_find_next(cs, NULL);
493              modref != NULL;
494              modref = cf_item_find_next(cs, modref)) {
495                 CONF_PAIR *cp = NULL;
496                 CONF_SECTION *scs = NULL;
497
498                 /*
499                  *      Look for Auth-Type foo {}, which are special
500                  *      cases of named sections, and allowable ONLY
501                  *      at the top-level.
502                  *
503                  *      i.e. They're not allowed in a "group" or "redundant"
504                  *      subsection.
505                  */
506                 if (cf_item_is_section(modref)) {
507                         const char *sec_name;
508                         scs = cf_itemtosection(modref);
509
510                         sec_name = cf_section_name1(scs);
511
512                         if (strcmp(sec_name,
513                                    section_type_value[comp].typename) == 0) {
514                                 if (!load_subcomponent_section(parent, scs,
515                                                                space, comp,
516                                                                filename)) {
517                                         return -1; /* FIXME: memleak? */
518                                 }
519                                 continue;
520                         }
521
522                         cp = NULL;
523                 } else if (cf_item_is_pair(modref)) {
524                         cp = cf_itemtopair(modref);
525                 } else {
526                         continue; /* ignore it */
527                 }
528
529                 /*
530                  *      Try to compile one entry.
531                  */
532                 this = compile_modsingle(parent, comp, modref, filename,
533                                          &modname);
534                 if (!this) {
535                         radlog(L_ERR|L_CONS,
536                                "%s[%d] Failed to parse %s section.\n",
537                                filename, cf_section_lineno(cs),
538                                cf_section_name1(cs));
539                         return -1;
540                 }
541
542                 if (comp == RLM_COMPONENT_AUTH) {
543                         DICT_VALUE *dval;
544                         const char *modrefname = NULL;
545                         int lineno = 0;
546
547                         if (cp) {
548                                 modrefname = cf_pair_attr(cp);
549                                 lineno = cf_pair_lineno(cp);
550                         } else {
551                                 modrefname = cf_section_name2(scs);
552                                 lineno = cf_section_lineno(scs);
553                                 if (!modrefname) {
554                                         radlog(L_ERR|L_CONS,
555                                                "%s[%d] Failed to parse %s sub-section.\n",
556                                                filename, lineno,
557                                                cf_section_name1(scs));
558                                         return -1;
559                                 }
560                         }
561
562                         dval = dict_valbyname(PW_AUTH_TYPE, modrefname);
563                         if (!dval) {
564                                 /*
565                                  *      It's a section, but nothing we
566                                  *      recognize.  Die!
567                                  */
568                                 radlog(L_ERR|L_CONS, "%s[%d] Unknown Auth-Type \"%s\" in %s sub-section.",
569                                        filename, lineno,
570                                        modrefname, section_type_value[comp].section);
571                                 return -1;
572                         }
573                         idx = dval->value;
574                 } else {
575                         /* See the comment in new_sublist() for explanation
576                          * of the special index 0 */
577                         idx = 0;
578                 }
579
580                 subcomp = new_sublist(space, comp, idx);
581                 if (subcomp == NULL) {
582                         radlog(L_INFO|L_CONS,
583                                         "%s %s %s already configured - skipping",
584                                         filename, section_type_value[comp].typename,
585                                         modname);
586                         modcallable_free(&this);
587                         continue;
588                 }
589
590                 /* If subcomp->modulelist is NULL, add_to_modcallable will
591                  * create it */
592                 visiblename = cf_section_name2(cs);
593                 if (visiblename == NULL)
594                         visiblename = cf_section_name1(cs);
595                 add_to_modcallable(&subcomp->modulelist, this,
596                                    comp, visiblename);
597         }
598
599         return 0;
600 }
601
602
603 /*
604  *      Parse the module config sections, and load
605  *      and call each module's init() function.
606  *
607  *      Libtool makes your life a LOT easier, especially with libltdl.
608  *      see: http://www.gnu.org/software/libtool/
609  */
610 int setup_modules(int reload)
611 {
612         int             comp;
613         CONF_SECTION    *cs, *modules;
614         int             do_component[RLM_COMPONENT_COUNT];
615         rad_listen_t    *listener;
616
617         /*
618          *      If necessary, initialize libltdl.
619          */
620         if (!reload) {
621                 /*
622                  *      Set the default list of preloaded symbols.
623                  *      This is used to initialize libltdl's list of
624                  *      preloaded modules.
625                  *
626                  *      i.e. Static modules.
627                  */
628                 LTDL_SET_PRELOADED_SYMBOLS();
629
630                 if (lt_dlinit() != 0) {
631                         radlog(L_ERR|L_CONS, "Failed to initialize libraries: %s\n",
632                                         lt_dlerror());
633                         return -1;
634                 }
635
636                 /*
637                  *      Set the search path to ONLY our library directory.
638                  *      This prevents the modules from being found from
639                  *      any location on the disk.
640                  */
641                 lt_dlsetsearchpath(radlib_dir);
642
643                 DEBUG2("radiusd: Library search path is %s",
644                        lt_dlgetsearchpath());
645
646                 /*
647                  *      Set up the internal module struct.
648                  */
649                 module_tree = rbtree_create(module_entry_cmp,
650                                             module_entry_free, 0);
651                 if (!module_tree) {
652                         radlog(L_ERR|L_CONS, "Failed to initialize modules\n");
653                         return -1;
654                 }
655         } else {
656                 rbtree_free(components);
657         }
658
659         components = rbtree_create(indexed_modcallable_cmp,
660                                    indexed_modcallable_free, 0);
661         if (!components) {
662                 radlog(L_ERR|L_CONS, "Failed to initialize components\n");
663                 return -1;
664         }
665
666         /*
667          *      Figure out which sections to load.
668          */
669         memset(do_component, 0, sizeof(do_component));
670         for (listener = mainconfig.listen;
671              listener != NULL;
672              listener = listener->next) {
673                 switch (listener->type) {
674                 case RAD_LISTEN_AUTH:
675                         do_component[RLM_COMPONENT_AUTZ] = 1;
676                         do_component[RLM_COMPONENT_AUTH] = 1;
677                         do_component[RLM_COMPONENT_POST_AUTH] = 1;
678                         do_component[RLM_COMPONENT_SESS] = 1;
679                         break;
680
681                 case RAD_LISTEN_DETAIL: /* just like acct */
682                 case RAD_LISTEN_ACCT:
683                         do_component[RLM_COMPONENT_PREACCT] = 1;
684                         do_component[RLM_COMPONENT_ACCT] = 1;
685                         break;
686
687                 case RAD_LISTEN_PROXY:
688                         do_component[RLM_COMPONENT_PRE_PROXY] = 1;
689                         do_component[RLM_COMPONENT_POST_PROXY] = 1;
690                         break;
691
692                 case RAD_LISTEN_VQP:
693                         do_component[RLM_COMPONENT_POST_AUTH] = 1;
694                         break;
695                         /*
696                          *      Ignore this.
697                          */
698                 case RAD_LISTEN_SNMP:
699                         break;
700
701                 default:
702                         rad_assert(0 == 1);
703                         break;
704                 }
705         }
706
707         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
708                 /*
709                  *      Have the debugging messages all in one place.
710                  */
711                 if (!do_component[comp]) {
712                         DEBUG2("modules: Not loading %s{} section",
713                                section_type_value[comp].section);
714                 }
715         }
716
717         /*
718          *      Create any DICT_VALUE's for the types.  See
719          *      'doc/configurable_failover' for examples of 'authtype'
720          *      used to create new Auth-Type values.  In order to
721          *      let the user create new names, we've got to look for
722          *      those names, and create DICT_VALUE's for them.
723          */
724         for (comp = RLM_COMPONENT_AUTH; comp < RLM_COMPONENT_COUNT; comp++) {
725                 int             value;
726                 const char      *name2;
727                 DICT_ATTR       *dattr;
728                 DICT_VALUE      *dval;
729                 CONF_SECTION    *sub, *next;
730                 CONF_PAIR       *cp;
731
732                 /*
733                  *      Not needed, don't load it.
734                  */
735                 if (!do_component[comp]) {
736                         continue;
737                 }
738                 cs = cf_section_find(section_type_value[comp].section);
739
740                 if (!cs) continue;
741
742                 sub = NULL;
743                 do {
744                         /*
745                          *      See if there's a sub-section by that
746                          *      name.
747                          */
748                         next = cf_subsection_find_next(cs, sub,
749                                                        section_type_value[comp].typename);
750                         sub = next;
751
752                         /*
753                          *      If so, look for it to define a new
754                          *      value.
755                          */
756                         name2 = cf_section_name2(sub);
757                         if (!name2) continue;
758
759
760                         /*
761                          *      If the value already exists, don't
762                          *      create it again.
763                          */
764                         dval = dict_valbyname(section_type_value[comp].attr,
765                                               name2);
766                         if (dval) continue;
767
768                         /*
769                          *      Find the attribute for the value.
770                          */
771                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
772                         if (!dattr) {
773                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
774                                        mainconfig.radiusd_conf,
775                                        cf_section_lineno(sub),
776                                        section_type_value[comp].typename);
777                                 continue;
778                         }
779
780                         /*
781                          *      Create a new unique value with a
782                          *      meaningless number.  You can't look at
783                          *      it from outside of this code, so it
784                          *      doesn't matter.  The only requirement
785                          *      is that it's unique.
786                          */
787                         do {
788                                 value = lrad_rand() & 0x00ffffff;
789                         } while (dict_valbyattr(dattr->attr, value));
790
791                         if (dict_addvalue(name2, dattr->name, value) < 0) {
792                                 radlog(L_ERR, "%s", librad_errstr);
793                                 return -1;
794                         }
795                 } while (sub != NULL);
796
797                 /*
798                  *      Loop over the non-sub-sections, too.
799                  */
800                 cp = NULL;
801                 do {
802                         /*
803                          *      See if there's a conf-pair by that
804                          *      name.
805                          */
806                         cp = cf_pair_find_next(cs, cp, NULL);
807                         if (!cp) break;
808
809
810                         /*
811                          *      If the value already exists, don't
812                          *      create it again.
813                          */
814                         name2 = cf_pair_attr(cp);
815                         dval = dict_valbyname(section_type_value[comp].attr,
816                                               name2);
817                         if (dval) continue;
818
819                         /*
820                          *      Find the attribute for the value.
821                          */
822                         dattr = dict_attrbyvalue(section_type_value[comp].attr);
823                         if (!dattr) {
824                                 radlog(L_ERR, "%s[%d]: No such attribute %s",
825                                        mainconfig.radiusd_conf,
826                                        cf_section_lineno(sub),
827                                        section_type_value[comp].typename);
828                                 continue;
829                         }
830
831                         /*
832                          *      Finally, create the new attribute.
833                          */
834                         do {
835                                 value = lrad_rand() & 0x00ffffff;
836                         } while (dict_valbyattr(dattr->attr, value));
837                         if (dict_addvalue(name2, dattr->name, value) < 0) {
838                                 radlog(L_ERR, "%s", librad_errstr);
839                                 return -1;
840                         }
841                 } while (cp != NULL);
842         } /* over the sections which can have redundent sub-sections */
843
844         /*
845          *      Remember where the modules were stored.
846          */
847         modules = cf_section_find("modules");
848         if (!modules) {
849                 radlog(L_ERR, "Cannot find a \"modules\" section in the configuration file!");
850                 return -1;
851         }
852
853         /*
854          *  Look for the 'instantiate' section, which tells us
855          *  the instantiation order of the modules, and also allows
856          *  us to load modules with no authorize/authenticate/etc.
857          *  sections.
858          */
859         cs = cf_section_find("instantiate");
860         if (cs != NULL) {
861                 CONF_ITEM *ci;
862                 CONF_PAIR *cp;
863                 module_instance_t *module;
864                 const char *name;
865
866                 DEBUG2(" instantiate {");
867
868                 /*
869                  *  Loop over the items in the 'instantiate' section.
870                  */
871                 for (ci=cf_item_find_next(cs, NULL);
872                      ci != NULL;
873                      ci=cf_item_find_next(cs, ci)) {
874
875                         /*
876                          *      Skip sections.  They'll be handled
877                          *      later, if they're referenced at all...
878                          */
879                         if (cf_item_is_section(ci)) {
880                                 continue;
881                         }
882
883                         cp = cf_itemtopair(ci);
884                         name = cf_pair_attr(cp);
885                         module = find_module_instance(modules, name);
886                         if (!module) {
887                                 return -1;
888                         }
889                 } /* loop over items in the subsection */
890
891                 DEBUG2(" }");
892         } /* if there's an 'instantiate' section. */
893
894         DEBUG2(" modules {");
895
896         /*
897          *      Loop over all of the known components, finding their
898          *      configuration section, and loading it.
899          */
900         for (comp = 0; comp < RLM_COMPONENT_COUNT; ++comp) {
901                 cs = cf_section_find(section_type_value[comp].section);
902                 if (cs == NULL)
903                         continue;
904
905                 if (!do_component[comp]) {
906                         continue;
907                 }
908
909                 if (cf_item_find_next(cs, NULL) == NULL) {
910                         continue; /* section is empty */
911                 }
912
913                 DEBUG2(" Module: Checking %s {...} for more modules to load",
914                        section_type_value[comp].section);
915
916                 if (load_component_section(NULL, cs, 0, comp, mainconfig.radiusd_conf) < 0) {
917                         return -1;
918                 }
919         }
920
921         /*
922          *      Load the VMPS section, if necessary.
923          */
924         for (listener = mainconfig.listen;
925              listener != NULL;
926              listener = listener->next) {
927                 if (listener->type == RAD_LISTEN_VQP) {
928                         break;
929                 }
930         }
931
932         if (listener) {
933                 cs = cf_section_find("vmps");
934                 if (!cs) {
935                         radlog(L_ERR, "Listening on vmps socket, but no vmps section");
936                         return -1;
937                 }
938
939                 if (cf_item_find_next(cs, NULL) == NULL) {
940                         radlog(L_ERR, "Listening on vmps socket, vmps section is empty");
941                         return -1;
942                 }
943
944                 DEBUG2(" Module: Checking vmps {...} for more modules to load");
945
946                 if (load_component_section(NULL, cs, VMPS_SPACE,
947                                            RLM_COMPONENT_POST_AUTH,
948                                            mainconfig.radiusd_conf) < 0) {
949                         return -1;
950                 }
951         }
952
953         DEBUG2(" }");
954
955         return 0;
956 }
957
958 /*
959  *      Call all authorization modules until one returns
960  *      somethings else than RLM_MODULE_OK
961  */
962 int module_authorize(int autz_type, REQUEST *request)
963 {
964         return indexed_modcall(0, RLM_COMPONENT_AUTZ, autz_type, request);
965 }
966
967 /*
968  *      Authenticate a user/password with various methods.
969  */
970 int module_authenticate(int auth_type, REQUEST *request)
971 {
972         return indexed_modcall(0, RLM_COMPONENT_AUTH, auth_type, request);
973 }
974
975 /*
976  *      Do pre-accounting for ALL configured sessions
977  */
978 int module_preacct(REQUEST *request)
979 {
980         return indexed_modcall(0, RLM_COMPONENT_PREACCT, 0, request);
981 }
982
983 /*
984  *      Do accounting for ALL configured sessions
985  */
986 int module_accounting(int acct_type, REQUEST *request)
987 {
988         return indexed_modcall(0, RLM_COMPONENT_ACCT, acct_type, request);
989 }
990
991 /*
992  *      See if a user is already logged in.
993  *
994  *      Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
995  */
996 int module_checksimul(int sess_type, REQUEST *request, int maxsimul)
997 {
998         int rcode;
999
1000         if(!request->username)
1001                 return 0;
1002
1003         request->simul_count = 0;
1004         request->simul_max = maxsimul;
1005         request->simul_mpp = 1;
1006
1007         rcode = indexed_modcall(0, RLM_COMPONENT_SESS, sess_type, request);
1008
1009         if (rcode != RLM_MODULE_OK) {
1010                 /* FIXME: Good spot for a *rate-limited* warning to the log */
1011                 return 0;
1012         }
1013
1014         return (request->simul_count < maxsimul) ? 0 : request->simul_mpp;
1015 }
1016
1017 /*
1018  *      Do pre-proxying for ALL configured sessions
1019  */
1020 int module_pre_proxy(int type, REQUEST *request)
1021 {
1022         return indexed_modcall(0, RLM_COMPONENT_PRE_PROXY, type, request);
1023 }
1024
1025 /*
1026  *      Do post-proxying for ALL configured sessions
1027  */
1028 int module_post_proxy(int type, REQUEST *request)
1029 {
1030         return indexed_modcall(0, RLM_COMPONENT_POST_PROXY, type, request);
1031 }
1032
1033 /*
1034  *      Do post-authentication for ALL configured sessions
1035  */
1036 int module_post_auth(int postauth_type, REQUEST *request)
1037 {
1038         return indexed_modcall(0, RLM_COMPONENT_POST_AUTH, postauth_type, request);
1039 }
1040
1041 /*
1042  *      Do VMPS
1043  */
1044 int module_vmps(REQUEST *request)
1045 {
1046         return indexed_modcall(VMPS_SPACE, RLM_COMPONENT_POST_AUTH, 0,
1047                                request);
1048 }
1049