~ubuntu-branches/ubuntu/natty/freeradius/natty-updates

« back to all changes in this revision

Viewing changes to src/main/modcall.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Hampson
  • Date: 2006-01-15 13:34:13 UTC
  • mto: (3.1.3 dapper) (4.1.3 sid) (1.1.14 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20060115133413-zo1dslttvdoalqym
Tags: upstream-1.1.0
ImportĀ upstreamĀ versionĀ 1.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * modcall.c
3
3
 *
4
 
 * Version:     $Id: modcall.c,v 1.22.2.1 2005/02/09 18:19:00 aland Exp $
 
4
 * Version:     $Id: modcall.c,v 1.22.2.1.2.3 2005/12/15 00:44:34 aland Exp $
5
5
 *
6
6
 *   This program is free software; you can redistribute it and/or modify
7
7
 *   it under the terms of the GNU General Public License as published by
46
46
 * explanation of what they are all about, see ../../doc/README.failover */
47
47
struct modcallable {
48
48
        struct modcallable *next;
 
49
        const char *name;
49
50
        int actions[RLM_MODULE_NUMCODES];
50
 
        const char *name;
51
 
        enum { MOD_SINGLE, MOD_GROUP } type;
 
51
        enum { MOD_SINGLE, MOD_GROUP, MOD_LOAD_BALANCE, MOD_REDUNDANT_LOAD_BALANCE  } type;
52
52
};
53
53
 
 
54
#define GROUPTYPE_SIMPLE        0
 
55
#define GROUPTYPE_REDUNDANT     1
 
56
#define GROUPTYPE_APPEND        2
 
57
#define GROUPTYPE_COUNT         3
 
58
 
54
59
typedef struct {
55
60
        modcallable mc;
 
61
        int grouptype;
56
62
        modcallable *children;
57
63
} modgroup;
58
64
 
61
67
        module_instance_t *modinst;
62
68
} modsingle;
63
69
 
 
70
 
 
71
static const LRAD_NAME_NUMBER grouptype_table[] = {
 
72
        { "", GROUPTYPE_SIMPLE },
 
73
        { "redundant ", GROUPTYPE_REDUNDANT },
 
74
        { "append ", GROUPTYPE_APPEND },
 
75
        { NULL, -1 }
 
76
};
 
77
 
64
78
/* Simple conversions: modsingle and modgroup are subclasses of modcallable,
65
79
 * so we often want to go back and forth between them. */
66
80
static modsingle *mod_callabletosingle(modcallable *p)
70
84
}
71
85
static modgroup *mod_callabletogroup(modcallable *p)
72
86
{
73
 
        rad_assert(p->type==MOD_GROUP);
 
87
        rad_assert((p->type==MOD_GROUP) ||
 
88
                   (p->type==MOD_LOAD_BALANCE) ||
 
89
                   (p->type==MOD_REDUNDANT_LOAD_BALANCE));
74
90
        return (modgroup *)p;
75
91
}
76
92
static modcallable *mod_singletocallable(modsingle *p)
89
105
        modcallable *node = *head;
90
106
        modcallable **last = head;
91
107
 
 
108
        if (!c) return;
 
109
 
92
110
        while (node) {
93
111
                last = &node->next;
94
112
                node = node->next;
100
118
 
101
119
/* Here's where we recognize all of our keywords: first the rcodes, then the
102
120
 * actions */
103
 
static LRAD_NAME_NUMBER rcode_table[] = {
 
121
static const LRAD_NAME_NUMBER rcode_table[] = {
104
122
        { "reject",     RLM_MODULE_REJECT       },
105
123
        { "fail",       RLM_MODULE_FAIL         },
106
124
        { "ok",         RLM_MODULE_OK           },
113
131
        { NULL, 0 }
114
132
};
115
133
 
116
 
static int str2rcode(const char *s, const char *filename, int lineno)
 
134
 
 
135
/*
 
136
 *      Compile action && rcode for later use.
 
137
 */
 
138
static int compile_action(modcallable *c, const char *attr, const char *value,
 
139
                          const char *filename, int lineno)
117
140
{
118
 
        int rcode;
 
141
        int rcode, action;
119
142
 
120
 
        rcode = lrad_str2int(rcode_table, s, -1);
 
143
        rcode = lrad_str2int(rcode_table, attr, -1);
121
144
        if (rcode < 0) {
122
145
                radlog(L_ERR|L_CONS,
123
146
                       "%s[%d] Unknown module rcode '%s'.\n",
124
 
                       filename, lineno, s);
125
 
                exit(1);
 
147
                       filename, lineno, attr);
 
148
                return 0;
126
149
        }
127
150
 
128
 
        return rcode;
129
 
}
130
 
 
131
 
static int str2action(const char *s, const char *filename, int lineno)
132
 
{
133
 
        if(!strcasecmp(s, "return"))
134
 
                return MOD_ACTION_RETURN;
135
 
        else if(!strcasecmp(s, "reject"))
136
 
                return MOD_ACTION_REJECT;
137
 
        else if (strspn(s, "0123456789")==strlen(s)) {
138
 
                int rcode = atoi(s);
139
 
 
 
151
        if (!strcasecmp(value, "return"))
 
152
                action = MOD_ACTION_RETURN;
 
153
 
 
154
        else if (!strcasecmp(value, "reject"))
 
155
                action = MOD_ACTION_REJECT;
 
156
 
 
157
        else if (strspn(value, "0123456789")==strlen(value)) {
 
158
                action = atoi(value);
 
159
                
140
160
                /*
141
161
                 *      Don't allow priority zero, for future use.
142
162
                 */
143
 
                if (rcode == 0) {
144
 
                        radlog(L_ERR|L_CONS,
145
 
                               "%s[%d] Invalid action '%s'.\n",
146
 
                               filename, lineno, s);
147
 
                        exit(1);
148
 
                }
149
 
                return rcode;
 
163
                if (action == 0) return 0;
150
164
        } else {
151
165
                radlog(L_ERR|L_CONS,
152
 
                                "%s[%d] Unknown action '%s'.\n",
153
 
                                filename, lineno, s);
154
 
                exit(1);
 
166
                       "%s[%d] Unknown action '%s'.\n",
 
167
                       filename, lineno, value);
 
168
                return 0;
155
169
        }
156
 
        return -1;
 
170
 
 
171
        c->actions[rcode] = action;
 
172
 
 
173
        return 1;
157
174
}
158
175
 
159
176
#if 0
226
243
        return myresult;
227
244
}
228
245
 
 
246
 
 
247
/*
 
248
 *      Helper function for call_modgroup, and call_modredundantloadbalance
 
249
 *
 
250
 *      Returns 0 for "stop", and "1" for continue.
 
251
 */
 
252
static int call_one(int component, modcallable *p, REQUEST *request,
 
253
                    int *priority, int *result)
 
254
{
 
255
        int r;
 
256
 
 
257
#ifdef RAD_REQUEST_OPTION_STOP_NOW
 
258
        /*
 
259
         *      A module has taken too long to process the request,
 
260
         *      and we've been told to stop processing it.
 
261
         */
 
262
        if (request->options & RAD_REQUEST_OPTION_STOP_NOW) {
 
263
                *result = RLM_MODULE_FAIL;
 
264
                return 0;
 
265
        }
 
266
#endif
 
267
        
 
268
        /* Call this child by recursing into modcall */
 
269
        r = modcall(component, p, request);
 
270
        
 
271
#if 0
 
272
        DEBUG2("%s: action for %s is %s",
 
273
               comp2str[component], lrad_int2str(rcode_table, r, "??"),
 
274
               action2str(p->actions[r]));
 
275
#endif
 
276
        
 
277
        /*
 
278
         *      Find an action to go with the child's result. If it is
 
279
         *      "return", break out of the loop so the rest of the
 
280
         *      children in the list will be skipped.
 
281
         */
 
282
        if (p->actions[r] == MOD_ACTION_RETURN) {
 
283
                *result = r;
 
284
                return 0;
 
285
        }
 
286
        
 
287
        /* If "reject" break out of the loop and return reject */
 
288
        if (p->actions[r] == MOD_ACTION_REJECT) {
 
289
                *result = RLM_MODULE_REJECT;
 
290
                return 0;
 
291
        }
 
292
        
 
293
        /*
 
294
         *      Otherwise, the action is a number, the preference
 
295
         *      level of this return code. If no higher preference has
 
296
         *      been seen yet, remember this one
 
297
         . */
 
298
        if (p->actions[r] >= *priority) {
 
299
                *result = r;
 
300
                *priority = p->actions[r];
 
301
        }
 
302
        
 
303
        return 1;
 
304
}
 
305
 
 
306
 
229
307
static int call_modgroup(int component, modgroup *g, REQUEST *request,
230
 
                int default_result)
 
308
                         int default_result)
231
309
{
232
310
        int myresult = default_result;
233
 
        int myresultpref;
 
311
        int priority = 0;       /* default result has lowest priority  */
234
312
        modcallable *p;
235
313
 
236
314
        /*
241
319
                return default_result;
242
320
        }
243
321
 
244
 
        /* Assign the lowest possible preference to the default return code */
245
 
        myresultpref = 0;
246
 
 
247
 
        /* Loop over the children */
248
 
        for(p = g->children; p; p = p->next) {
249
 
                int r = RLM_MODULE_FAIL;
250
 
 
251
 
                /* Call this child by recursing into modcall */
252
 
                r = modcall(component, p, request);
253
 
 
254
 
#if 0
255
 
                DEBUG2("%s: action for %s is %s",
256
 
                        comp2str[component], lrad_int2str(rcode_table, r, "??"),
257
 
                        action2str(p->actions[r]));
258
 
#endif
259
 
 
260
 
                /* Find an action to go with the child's result. If "return",
261
 
                 * break out of the loop so the rest of the children in the
262
 
                 * list will be skipped. */
263
 
                if(p->actions[r] == MOD_ACTION_RETURN) {
264
 
                        myresult = r;
265
 
                        break;
266
 
                }
267
 
 
268
 
                /* If "reject" break out of the loop and return reject */
269
 
                if (p->actions[r] == MOD_ACTION_REJECT) {
270
 
                        myresult = RLM_MODULE_REJECT;
271
 
                        break;
272
 
                }
273
 
 
274
 
                /* Otherwise, the action is a number, the preference level of
275
 
                 * this return code. If no higher preference has been seen
276
 
                 * yet, remember this one. */
277
 
                if(p->actions[r] >= myresultpref) {
278
 
                        myresult = r;
279
 
                        myresultpref = p->actions[r];
280
 
                }
281
 
        }
282
 
 
 
322
        /* Loop over the children */
 
323
        for (p = g->children; p; p = p->next) {
 
324
                if (!call_one(component, p, request, &priority, &myresult)) {
 
325
                        break;
 
326
                }
 
327
        }
 
328
 
 
329
        return myresult;
 
330
}
 
331
 
 
332
static int call_modloadbalance(int component, modgroup *g, REQUEST *request,
 
333
                               int default_result)
 
334
{
 
335
        int count = 1;
 
336
        modcallable *p, *child = NULL;
 
337
 
 
338
        /*
 
339
         *      Catch people who have issues.
 
340
         */
 
341
        if (!g->children) {
 
342
                DEBUG2("  WARNING! Asked to process empty load-balance group.  Returning %s.", lrad_int2str(rcode_table, default_result, "??"));
 
343
                return default_result;
 
344
        }
 
345
 
 
346
        /*
 
347
         *      Pick a random child.
 
348
         */
 
349
 
 
350
        /* Loop over the children */
 
351
        for(p = g->children; p; p = p->next) {
 
352
                if (!child) {
 
353
                        child = p;
 
354
                        count = 1;
 
355
                        continue;
 
356
                }
 
357
 
 
358
                /*
 
359
                 *      Keep track of how many load balancing servers
 
360
                 *      we've gone through.
 
361
                 */
 
362
                count++;
 
363
 
 
364
                /*
 
365
                 *      See the "camel book" for why this works.
 
366
                 *
 
367
                 *      If (rand(0..n) < 1), pick the current realm.
 
368
                 *      We add a scale factor of 65536, to avoid
 
369
                 *      floating point.
 
370
                 */
 
371
                if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) {
 
372
                        child = p;
 
373
                }
 
374
        }
 
375
        rad_assert(child != NULL);
 
376
 
 
377
        /* Call the chosen child by recursing into modcall */
 
378
        return modcall(component, child, request);
 
379
}
 
380
 
 
381
 
 
382
/*
 
383
 *      For more than 2 modules with redundancy + load balancing
 
384
 *      across all of them, layering the "redundant" and
 
385
 *      "load-balance" groups gets too complicated.  As a result, we
 
386
 *      implement a special function to do this.
 
387
 */
 
388
static int call_modredundantloadbalance(int component, modgroup *g, REQUEST *request,
 
389
                                        int default_result)
 
390
{
 
391
        int count = 1;
 
392
        int myresult = default_result;
 
393
        int priority = 0;       /* default result has lowest priority  */
 
394
        modcallable *p, *child = NULL;
 
395
 
 
396
        /*
 
397
         *      Catch people who have issues.
 
398
         */
 
399
        if (!g->children) {
 
400
                DEBUG2("  WARNING! Asked to process empty redundant-load-balance group.  Returning %s.", lrad_int2str(rcode_table, default_result, "??"));
 
401
                return default_result;
 
402
        }
 
403
 
 
404
        /*
 
405
         *      Pick a random child.
 
406
         */
 
407
 
 
408
        /* Loop over the children */
 
409
        for(p = g->children; p; p = p->next) {
 
410
                if (!child) {
 
411
                        child = p;
 
412
                        count = 1;
 
413
                        continue;
 
414
                }
 
415
 
 
416
                /*
 
417
                 *      Keep track of how many load balancing servers
 
418
                 *      we've gone through.
 
419
                 */
 
420
                count++;
 
421
 
 
422
                /*
 
423
                 *      See the "camel book" for why this works.
 
424
                 *
 
425
                 *      If (rand(0..n) < 1), pick the current realm.
 
426
                 *      We add a scale factor of 65536, to avoid
 
427
                 *      floating point.
 
428
                 */
 
429
                if ((count * (lrad_rand() & 0xffff)) < (uint32_t) 0x10000) {
 
430
                        child = p;
 
431
                }
 
432
        }
 
433
        rad_assert(child != NULL);
 
434
 
 
435
        /*
 
436
         *      Call the chosen child, with fail-over to the next one
 
437
         *      if it is down.
 
438
         */
 
439
        p = child;
 
440
        do {
 
441
                /*
 
442
                 *      Call the chosen entry.  If we're done, then
 
443
                 *      stop.
 
444
                 */
 
445
                if (!call_one(component, p, request, &priority, &myresult)) {
 
446
                        break;
 
447
                }
 
448
                
 
449
                /*
 
450
                 *      Go to the next one, and wrap around to the beginning if
 
451
                 *      we reach the end.
 
452
                 */
 
453
                p = p->next;
 
454
                if (!p) p = g->children;
 
455
        } while (p != child);
 
456
 
 
457
        /*
 
458
         *      And return whatever was decided.
 
459
         */
283
460
        return myresult;
284
461
}
285
462
 
326
503
                return myresult;
327
504
        }
328
505
 
329
 
        if(c->type==MOD_GROUP) {
330
 
                modgroup *g = mod_callabletogroup(c);
331
 
 
332
 
                DEBUG2("modcall: entering group %s for request %d",
333
 
                       c->name, request->number);
334
 
 
335
 
                myresult = call_modgroup(component, g, request, myresult);
336
 
 
337
 
                DEBUG2("modcall: group %s returns %s for request %d",
338
 
                        c->name,
339
 
                       lrad_int2str(rcode_table, myresult, "??"),
340
 
                       request->number);
341
 
        } else {
342
 
                modsingle *sp = mod_callabletosingle(c);
343
 
 
344
 
                myresult = call_modsingle(component, sp, request, myresult);
345
 
 
346
 
                DEBUG2("  modcall[%s]: module \"%s\" returns %s for request %d",
347
 
                       comp2str[component], c->name,
348
 
                       lrad_int2str(rcode_table, myresult, "??"),
349
 
                       request->number);
 
506
        switch (c->type) {
 
507
        case MOD_LOAD_BALANCE:
 
508
                {
 
509
                        modgroup *g = mod_callabletogroup(c);
 
510
                        
 
511
                        DEBUG2("modcall: entering load-balance group %s for request %d",
 
512
                               c->name, request->number);
 
513
                        
 
514
                        myresult = call_modloadbalance(component, g, request,
 
515
                                                       myresult);
 
516
                        
 
517
                        DEBUG2("modcall: load-balance group %s returns %s for request %d",
 
518
                               c->name,
 
519
                               lrad_int2str(rcode_table, myresult, "??"),
 
520
                               request->number);
 
521
                }
 
522
                break;
 
523
                
 
524
        case MOD_REDUNDANT_LOAD_BALANCE:
 
525
                {
 
526
                        modgroup *g = mod_callabletogroup(c);
 
527
                        
 
528
                        DEBUG2("modcall: entering redundant-load-balance group %s for request %d",
 
529
                               c->name, request->number);
 
530
                        
 
531
                        myresult = call_modredundantloadbalance(component, g, request,
 
532
                                                                myresult);
 
533
                        
 
534
                        DEBUG2("modcall: redundant-load-balance group %s returns %s for request %d",
 
535
                               c->name,
 
536
                               lrad_int2str(rcode_table, myresult, "??"),
 
537
                               request->number);
 
538
                }
 
539
                break;
 
540
                
 
541
        case MOD_GROUP:
 
542
                {
 
543
                        modgroup *g = mod_callabletogroup(c);
 
544
                        
 
545
                        DEBUG2("modcall: entering group %s%s for request %d",
 
546
                               lrad_int2str(grouptype_table, g->grouptype, ""),
 
547
                               c->name, request->number);
 
548
                        
 
549
                        myresult = call_modgroup(component, g, request,
 
550
                                                 myresult);
 
551
                        
 
552
                        DEBUG2("modcall: leaving group %s%s (returns %s) for request %d",
 
553
                               lrad_int2str(grouptype_table, g->grouptype, ""),
 
554
                               c->name,
 
555
                               lrad_int2str(rcode_table, myresult, "??"),
 
556
                               request->number);
 
557
                }
 
558
                break;
 
559
                
 
560
        case MOD_SINGLE:
 
561
                {
 
562
                        modsingle *sp = mod_callabletosingle(c);
 
563
                        
 
564
                        myresult = call_modsingle(component, sp, request,
 
565
                                                  myresult);
 
566
                        
 
567
                        DEBUG2("  modcall[%s]: module \"%s\" returns %s for request %d",
 
568
                               comp2str[component], c->name,
 
569
                               lrad_int2str(rcode_table, myresult, "??"),
 
570
                               request->number);
 
571
                }
 
572
                break;
 
573
 
 
574
        default:
 
575
                radlog(L_ERR, "Internal error processing module entry");
 
576
                break;
350
577
        }
351
578
 
352
579
        return myresult;
393
620
}
394
621
#endif
395
622
 
396
 
#define GROUPTYPE_SIMPLEGROUP 0
397
 
#define GROUPTYPE_REDUNDANT 1
398
 
#define GROUPTYPE_APPEND 2
399
 
#define GROUPTYPE_COUNT 3
400
 
 
401
623
/* These are the default actions. For each component, the group{} block
402
624
 * behaves like the code from the old module_*() function. redundant{} and
403
625
 * append{} are based on my guesses of what they will be used for. --Pac. */
404
 
static int
 
626
static const int
405
627
defaultactions[RLM_COMPONENT_COUNT][GROUPTYPE_COUNT][RLM_MODULE_NUMCODES] =
406
628
{
407
629
        /* authenticate */
718
940
        }
719
941
};
720
942
 
721
 
/* Bail out if the module in question does not supply the wanted component */
722
 
static void sanity_check(int component, module_instance_t *inst,
723
 
                         const char *filename)
724
 
{
725
 
        if (!inst->entry->module->methods[component]) {
726
 
                radlog(L_ERR|L_CONS,
727
 
                                "%s: \"%s\" modules aren't allowed in '%s' sections -- they have no such method.",
728
 
                                filename, inst->entry->module->name,
729
 
                                component_names[component]);
730
 
                exit(1);
731
 
        }
732
 
}
733
 
 
734
 
/* Parse a CONF_SECTION containing only result=action pairs */
735
 
static void override_actions(modcallable *c, CONF_SECTION *cs,
736
 
                const char *filename)
737
 
{
738
 
        CONF_ITEM *ci;
739
 
        CONF_PAIR *cp;
740
 
        const char *attr, *value;
741
 
        int lineno, rcode, action;
742
 
 
743
 
        for(ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) {
744
 
                if(cf_item_is_section(ci)) {
745
 
                        radlog(L_ERR|L_CONS,
746
 
                                        "%s[%d] Subsection of module instance call "
747
 
                                        "not allowed\n", filename,
748
 
                                        cf_section_lineno(cf_itemtosection(ci)));
749
 
                        exit(1);
750
 
                }
751
 
                cp = cf_itemtopair(ci);
752
 
                attr = cf_pair_attr(cp);
753
 
                value = cf_pair_value(cp);
754
 
                lineno = cf_pair_lineno(cp);
755
 
                rcode = str2rcode(attr, filename, lineno);
756
 
                action = str2action(value, filename, lineno);
757
 
                c->actions[rcode] = action;
758
 
        }
759
 
}
760
943
 
761
944
static modcallable *do_compile_modsingle(int component, CONF_ITEM *ci,
762
 
                const char *filename, int grouptype,
763
 
                const char **modname)
 
945
                                         const char *filename, int grouptype,
 
946
                                         const char **modname)
764
947
{
765
948
        int lineno;
766
949
        const char *modrefname;
770
953
 
771
954
        if (cf_item_is_section(ci)) {
772
955
                CONF_SECTION *cs = cf_itemtosection(ci);
 
956
                const char *name2 = cf_section_name2(cs);
773
957
 
774
958
                lineno = cf_section_lineno(cs);
775
959
                modrefname = cf_section_name1(cs);
 
960
                if (!name2) name2 = "_UnNamedGroup";
776
961
 
777
 
                /* group{}, redundant{}, or append{} may appear where a
778
 
                 * single module instance was expected - in that case, we
779
 
                 * hand it off to compile_modgroup */
 
962
                /*
 
963
                 *      group{}, redundant{}, or append{} may appear
 
964
                 *      where a single module instance was expected.
 
965
                 *      In that case, we hand it off to
 
966
                 *      compile_modgroup
 
967
                 */
780
968
                if (strcmp(modrefname, "group") == 0) {
781
 
                        *modname = "UnnamedGroup";
 
969
                        *modname = name2;
782
970
                        return do_compile_modgroup(component, cs, filename,
783
 
                                        GROUPTYPE_SIMPLEGROUP, grouptype);
 
971
                                        GROUPTYPE_SIMPLE, grouptype);
784
972
                } else if (strcmp(modrefname, "redundant") == 0) {
785
 
                        *modname = "UnnamedGroup";
 
973
                        *modname = name2;
786
974
                        return do_compile_modgroup(component, cs, filename,
787
975
                                        GROUPTYPE_REDUNDANT, grouptype);
788
976
                } else if (strcmp(modrefname, "append") == 0) {
789
 
                        *modname = "UnnamedGroup";
 
977
                        *modname = name2;
790
978
                        return do_compile_modgroup(component, cs, filename,
791
979
                                        GROUPTYPE_APPEND, grouptype);
 
980
                } else if (strcmp(modrefname, "load-balance") == 0) {
 
981
                        *modname = name2;
 
982
                        csingle= do_compile_modgroup(component, cs, filename,
 
983
                                        GROUPTYPE_SIMPLE, grouptype);
 
984
                        if (!csingle) return NULL;
 
985
                        csingle->type = MOD_LOAD_BALANCE;
 
986
                        return csingle;
 
987
                } else if (strcmp(modrefname, "redundant-load-balance") == 0) {
 
988
                        *modname = name2;
 
989
                        csingle= do_compile_modgroup(component, cs, filename,
 
990
                                        GROUPTYPE_REDUNDANT, grouptype);
 
991
                        if (!csingle) return NULL;
 
992
                        csingle->type = MOD_REDUNDANT_LOAD_BALANCE;
 
993
                        return csingle;
792
994
                }
793
995
        } else {
794
996
                CONF_PAIR *cp = cf_itemtopair(ci);
796
998
                modrefname = cf_pair_attr(cp);
797
999
        }
798
1000
 
 
1001
        /*
 
1002
         *      FIXME: See if the module is a virtual one.  If so,
 
1003
         *      return that, rather than doing anything here.
 
1004
         */
 
1005
        this = find_module_instance(modrefname);
 
1006
        if (!this) {
 
1007
                *modname = NULL;
 
1008
                radlog(L_ERR|L_CONS, "%s[%d] Unknown module \"%s\".", filename,
 
1009
                       lineno, modrefname);
 
1010
                return NULL;
 
1011
        }
 
1012
 
 
1013
        /*
 
1014
         *      We know it's all OK, allocate the structures, and fill
 
1015
         *      them in.
 
1016
         */
799
1017
        single = rad_malloc(sizeof(*single));
800
1018
        csingle = mod_singletocallable(single);
801
1019
        csingle->next = NULL;
802
 
        memcpy(csingle->actions,
803
 
                        defaultactions[component][grouptype],
804
 
                        sizeof csingle->actions);
 
1020
        memcpy(csingle->actions, defaultactions[component][grouptype],
 
1021
               sizeof csingle->actions);
805
1022
        rad_assert(modrefname != NULL);
806
1023
        csingle->name = modrefname;
807
1024
        csingle->type = MOD_SINGLE;
808
1025
 
 
1026
        /*
 
1027
         *      Singles can override the actions, virtual modules cannot.
 
1028
         *
 
1029
         *      FIXME: We may want to re-visit how to do this...
 
1030
         *      maybe a csingle as a ref?
 
1031
         */
809
1032
        if (cf_item_is_section(ci)) {
810
 
                /* override default actions with what's in the CONF_SECTION */
811
 
                override_actions(csingle, cf_itemtosection(ci), filename);
812
 
        }
813
 
 
814
 
        this = find_module_instance(modrefname);
815
 
        if (this == NULL) {
816
 
                exit(1); /* FIXME */
817
 
        }
818
 
 
819
 
        sanity_check(component, this, filename);
 
1033
                CONF_SECTION *cs = cf_itemtosection(ci);
 
1034
                CONF_PAIR *cp;
 
1035
                const char *attr, *value;
 
1036
 
 
1037
                for (ci=cf_item_find_next(cs, NULL);
 
1038
                     ci != NULL;
 
1039
                     ci=cf_item_find_next(cs, ci)) {
 
1040
 
 
1041
                        if (cf_item_is_section(ci)) {
 
1042
                                radlog(L_ERR|L_CONS,
 
1043
                                       "%s[%d] Subsection of module instance call "
 
1044
                                       "not allowed\n", filename,
 
1045
                                       cf_section_lineno(cf_itemtosection(ci)));
 
1046
                                modcallable_free(&csingle);
 
1047
                                return NULL;
 
1048
                        }
 
1049
 
 
1050
                        cp = cf_itemtopair(ci);
 
1051
                        attr = cf_pair_attr(cp);
 
1052
                        value = cf_pair_value(cp);
 
1053
                        lineno = cf_pair_lineno(cp);
 
1054
 
 
1055
                        if (!compile_action(csingle, attr, value, filename,
 
1056
                                            lineno)) {
 
1057
                                modcallable_free(&csingle);
 
1058
                                return NULL;
 
1059
                        }
 
1060
                }
 
1061
        }
 
1062
 
 
1063
        /*
 
1064
         *      Bail out if the module in question does not supply the
 
1065
         *      wanted component
 
1066
         */
 
1067
        if (!this->entry->module->methods[component]) {
 
1068
                radlog(L_ERR|L_CONS,
 
1069
                       "%s: \"%s\" modules aren't allowed in '%s' sections -- they have no such method.",
 
1070
                       filename, this->entry->module->name,
 
1071
                       component_names[component]);
 
1072
                modcallable_free(&csingle);
 
1073
                return NULL;
 
1074
        }
820
1075
 
821
1076
        single->modinst = this;
822
1077
        *modname = this->entry->module->name;
824
1079
}
825
1080
 
826
1081
modcallable *compile_modsingle(int component, CONF_ITEM *ci,
827
 
                const char *filename, const char **modname)
 
1082
                               const char *filename, const char **modname)
828
1083
{
829
1084
        modcallable *ret = do_compile_modsingle(component, ci, filename,
830
 
                GROUPTYPE_SIMPLEGROUP,
831
 
                modname);
 
1085
                                                GROUPTYPE_SIMPLE,
 
1086
                                                modname);
832
1087
        dump_tree(component, ret);
833
1088
        return ret;
834
1089
}
835
1090
 
836
1091
static modcallable *do_compile_modgroup(int component, CONF_SECTION *cs,
837
 
                const char *filename, int grouptype,
838
 
                int parentgrouptype)
 
1092
                                        const char *filename, int grouptype,
 
1093
                                        int parentgrouptype)
839
1094
{
840
1095
        modgroup *g;
841
1096
        modcallable *c;
842
1097
        CONF_ITEM *ci;
843
1098
 
844
1099
        g = rad_malloc(sizeof *g);
 
1100
        g->grouptype = grouptype;
845
1101
 
846
1102
        c = mod_grouptocallable(g);
847
1103
        c->next = NULL;
848
1104
        memcpy(c->actions, defaultactions[component][parentgrouptype],
849
 
                sizeof c->actions);
850
 
        c->name = cf_section_name1(cs);
851
 
        rad_assert(c->name != NULL);
 
1105
               sizeof(c->actions));
 
1106
 
 
1107
        /*
 
1108
         *      Remember the name for printing, etc.
 
1109
         *
 
1110
         *      FIXME: We may also want to put the names into a
 
1111
         *      rbtree, so that groups can reference each other...
 
1112
         */
 
1113
        c->name = cf_section_name2(cs);
 
1114
        if (!c->name) c->name = "";
852
1115
        c->type = MOD_GROUP;
853
1116
        g->children = NULL;
854
1117
 
855
 
        for (ci=cf_item_find_next(cs, NULL); ci != NULL; ci=cf_item_find_next(cs, ci)) {
 
1118
        for (ci=cf_item_find_next(cs, NULL);
 
1119
             ci != NULL;
 
1120
             ci=cf_item_find_next(cs, ci)) {
 
1121
 
856
1122
                if(cf_item_is_section(ci)) {
857
 
                        const char *junk;
 
1123
                        const char *junk = NULL;
858
1124
                        modcallable *single;
 
1125
                        int lineno;
 
1126
                        CONF_SECTION *subcs = cf_itemtosection(ci);
 
1127
 
 
1128
                        lineno = cf_section_lineno(subcs);
 
1129
 
859
1130
                        single = do_compile_modsingle(component, ci, filename,
860
 
                                        grouptype, &junk);
 
1131
                                                      grouptype, &junk);
 
1132
                        if (!single) {
 
1133
                                radlog(L_ERR|L_CONS,
 
1134
                                       "%s[%d] Failed to parse \"%s\" subsection.\n",
 
1135
                                       filename, lineno,
 
1136
                                       cf_section_name1(subcs));
 
1137
                                modcallable_free(&c);
 
1138
                                return NULL;
 
1139
                        }
861
1140
                        add_child(g, single);
 
1141
 
862
1142
                } else {
863
1143
                        const char *attr, *value;
864
1144
                        CONF_PAIR *cp = cf_itemtopair(ci);
868
1148
                        value = cf_pair_value(cp);
869
1149
                        lineno = cf_pair_lineno(cp);
870
1150
 
871
 
                        /* A CONF_PAIR is either a module instance with no
872
 
                         * actions specified... */
873
 
                        if(value[0]==0) {
 
1151
                        /*
 
1152
                         *      A CONF_PAIR is either a module
 
1153
                         *      instance with no actions
 
1154
                         *      specified ...
 
1155
                         */
 
1156
                        if (value[0] == 0) {
874
1157
                                modcallable *single;
875
 
                                const char *junk;
 
1158
                                const char *junk = NULL;
876
1159
 
877
1160
                                single = do_compile_modsingle(component,
878
1161
                                                cf_pairtoitem(cp), filename,
879
1162
                                                grouptype, &junk);
 
1163
                                if (!single) {
 
1164
                                        radlog(L_ERR|L_CONS,
 
1165
                                               "%s[%d] Failed to parse \"%s\" entry.\n",
 
1166
                                               filename, lineno, attr);
 
1167
                                        modcallable_free(&c);
 
1168
                                        return NULL;
 
1169
                                }
880
1170
                                add_child(g, single);
881
 
                        } else {
882
 
                                /* ...or an action to be applied to this
883
 
                                 * group. */
884
 
                                int rcode, action;
885
 
                                rcode = str2rcode(attr, filename, lineno);
886
 
                                action = str2action(value, filename, lineno);
887
1171
 
888
 
                                c->actions[rcode] = action;
889
 
                        }
 
1172
                                /*
 
1173
                                 *      Or a module instance with action.
 
1174
                                 */
 
1175
                        } else if (!compile_action(c, attr, value, filename,
 
1176
                                                   lineno)) {
 
1177
                                modcallable_free(&c);
 
1178
                                return NULL;
 
1179
                        } /* else it worked */
890
1180
                }
891
1181
        }
 
1182
 
 
1183
        /*
 
1184
         *      FIXME: If there are no children, return NULL?
 
1185
         */
892
1186
        return mod_grouptocallable(g);
893
1187
}
894
1188
 
896
1190
                const char *filename)
897
1191
{
898
1192
        modcallable *ret = do_compile_modgroup(component, cs, filename,
899
 
                        GROUPTYPE_SIMPLEGROUP,
900
 
                        GROUPTYPE_SIMPLEGROUP);
 
1193
                                               GROUPTYPE_SIMPLE,
 
1194
                                               GROUPTYPE_SIMPLE);
901
1195
        dump_tree(component, ret);
902
1196
        return ret;
903
1197
}
904
1198
 
905
1199
void add_to_modcallable(modcallable **parent, modcallable *this,
906
 
                int component, char *name)
 
1200
                        int component, char *name)
907
1201
{
908
1202
        modgroup *g;
 
1203
        
 
1204
        rad_assert(this != NULL);
909
1205
 
910
1206
        if (*parent == NULL) {
911
1207
                modcallable *c;
912
1208
 
913
1209
                g = rad_malloc(sizeof *g);
 
1210
                g->grouptype = GROUPTYPE_SIMPLE;
914
1211
                c = mod_grouptocallable(g);
915
1212
                c->next = NULL;
916
1213
                memcpy(c->actions,
917
 
                                defaultactions[component][GROUPTYPE_SIMPLEGROUP],
918
 
                                sizeof c->actions);
 
1214
                       defaultactions[component][GROUPTYPE_SIMPLE],
 
1215
                       sizeof(c->actions));
919
1216
                rad_assert(name != NULL);
920
1217
                c->name = name;
921
1218
                c->type = MOD_GROUP;
934
1231
        modcallable *c, *loop, *next;
935
1232
        c = *pc;
936
1233
        if(c->type==MOD_GROUP) {
937
 
                for(loop=mod_callabletogroup(c)->children ; loop ; loop=next) {
 
1234
                for(loop = mod_callabletogroup(c)->children;
 
1235
                    loop ;
 
1236
                    loop = next) {
938
1237
                        next = loop->next;
939
1238
                        modcallable_free(&loop);
940
1239
                }