Was leaking memory on module unload
[freeradius.git] / src / modules / rlm_always / rlm_always.c
1 /*
2  * rlm_always.c
3  *
4  *  This program is is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License, version 2 if the
6  *  License as published by the Free Software Foundation.
7  * 
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *  
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  *
17  * Copyright 2000  The FreeRADIUS server project
18  */
19
20 #include "autoconf.h"
21 #include "libradius.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "radiusd.h"
28 #include "modules.h"
29 #include "conffile.h"
30
31 static const char rcsid[] = "$Id$";
32
33 /*
34  *      The instance data for rlm_always is the list of fake values we are
35  *      going to return.
36  */
37 typedef struct rlm_always_t {
38         char    *rcode_str;
39         int     rcode;
40         int     simulcount;
41         int     mpp;
42 } rlm_always_t;
43
44 /*
45  *      A temporary holding area for config values to be extracted
46  *      into, before they are copied into the instance data
47  */
48 static rlm_always_t config;
49
50 /*
51  *      A mapping of configuration file names to internal variables.
52  *
53  *      Note that the string is dynamically allocated, so it MUST
54  *      be freed.  When the configuration file parse re-reads the string,
55  *      it free's the old one, and strdup's the new one, placing the pointer
56  *      to the strdup'd string into 'config.string'.  This gets around
57  *      buffer over-flows.
58  */
59 static CONF_PARSER module_config[] = {
60   { "rcode",      PW_TYPE_STRING_PTR, &config.rcode_str,  "fail" },
61   { "simulcount", PW_TYPE_INTEGER,    &config.simulcount, "0" },
62   { "mpp",        PW_TYPE_BOOLEAN,    &config.mpp,        "no" },
63
64   { NULL, -1, NULL, NULL }              /* end the list */
65 };
66
67 static int str2rcode(const char *s)
68 {
69         if(!strcasecmp(s, "reject"))
70                 return RLM_MODULE_REJECT;
71         else if(!strcasecmp(s, "fail"))
72                 return RLM_MODULE_FAIL;
73         else if(!strcasecmp(s, "ok"))
74                 return RLM_MODULE_OK;
75         else if(!strcasecmp(s, "handled"))
76                 return RLM_MODULE_HANDLED;
77         else if(!strcasecmp(s, "invalid"))
78                 return RLM_MODULE_INVALID;
79         else if(!strcasecmp(s, "userlock"))
80                 return RLM_MODULE_USERLOCK;
81         else if(!strcasecmp(s, "notfound"))
82                 return RLM_MODULE_NOTFOUND;
83         else if(!strcasecmp(s, "noop"))
84                 return RLM_MODULE_NOOP;
85         else if(!strcasecmp(s, "updated"))
86                 return RLM_MODULE_UPDATED;
87         else {
88                 radlog(L_ERR|L_CONS,
89                         "rlm_always: Unknown module rcode '%s'.\n", s);
90                 return -1;
91         }
92 }
93
94 static int always_instantiate(CONF_SECTION *conf, void **instance)
95 {
96         rlm_always_t *data;
97
98         /*
99          *      If the configuration parameters can't be parsed, then
100          *      fail.
101          */
102         if (cf_section_parse(conf, module_config) < 0) {
103                 return -1;
104         }
105         
106         /*
107          *      Set up a storage area for instance data
108          */
109         data = rad_malloc(sizeof(*data));
110         
111         /*
112          *      Copy the configuration into the instance data
113          */
114         data->simulcount = config.simulcount;
115         data->mpp = config.mpp;
116         data->rcode = str2rcode(config.rcode_str);
117         if (data->rcode == -1) {
118                 free(data);
119                 return -1;
120         }
121
122         *instance = data;
123
124         return 0;
125 }
126
127 /*
128  *      Just return the rcode ... this function is autz, auth, acct, and
129  *      preacct!
130  */
131 static int always_return(void *instance, REQUEST *request)
132 {
133         /* quiet the compiler */
134         request = request;
135
136         return ((struct rlm_always_t *)instance)->rcode;
137 }
138
139 /*
140  *      checksimul fakes some other variables besides the rcode...
141  */
142 static int always_checksimul(void *instance, REQUEST *request)
143 {
144         struct rlm_always_t *inst = instance;
145
146         request->simul_count = inst->simulcount;
147
148         if (inst->mpp)
149                 request->simul_mpp = 2;
150
151         return inst->rcode;
152 }
153
154 static int always_detach(void *instance)
155 {
156         free(instance);
157         return 0;
158 }
159
160 static int always_destroy(void)
161 {
162         /* We reuse this buffer across multiple instances, instead of
163          * freeing it in instantiate() after converting it to an int.
164          * That makes it a module-global variable, so it must be freed
165          * in destroy(). */
166         free(config.rcode_str);
167         return 0;
168 }
169
170 module_t rlm_always = {
171         "always",       
172         RLM_TYPE_THREAD_SAFE,           /* type */
173         NULL,                           /* initialization */
174         always_instantiate,             /* instantiation */
175         always_return,                  /* authorization */
176         always_return,                  /* authentication */
177         always_return,                  /* preaccounting */
178         always_return,                  /* accounting */
179         always_checksimul,              /* checksimul */
180         always_detach,                  /* detach */
181         always_destroy,                 /* destroy */
182 };