bc40ba1043af5f41d7b382c49a626e4384416c37
[freeradius.git] / src / modules / rlm_eap / mem.c
1 /*
2  * mem.c  Memory allocation, deallocation stuff.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2000,2001  The FreeRADIUS server project
21  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
22  */
23 #include <stdio.h>
24 #include "rlm_eap.h"
25
26 /*
27  *      Allocate a new EAP_PACKET
28  */
29 EAP_PACKET *eap_packet_alloc(void)
30 {
31         EAP_PACKET   *rp;
32
33         rp = rad_malloc(sizeof(EAP_PACKET));
34         memset(rp, 0, sizeof(EAP_PACKET));
35         return rp;
36 }
37
38 /*
39  *      Free EAP_PACKET
40  */
41 void eap_packet_free(EAP_PACKET **eap_packet_ptr)
42 {
43         EAP_PACKET *eap_packet;
44
45         if (!eap_packet_ptr) return;
46         eap_packet = *eap_packet_ptr;
47         if (!eap_packet) return;
48
49         if (eap_packet->type.data) {
50                 /*
51                  * This is just a pointer in the packet
52                  * so we do not free it but we NULL it
53                 free(eap_packet->type.data);
54                 */
55                 eap_packet->type.data = NULL;
56         }
57
58         if (eap_packet->packet) {
59                 free(eap_packet->packet);
60                 eap_packet->packet = NULL;
61         }
62
63         free(eap_packet);
64
65         *eap_packet_ptr = NULL;
66 }
67
68 /*
69  *      Allocate a new EAP_PACKET
70  */
71 EAP_DS *eap_ds_alloc(void)
72 {
73         EAP_DS  *eap_ds;
74         
75         eap_ds = rad_malloc(sizeof(EAP_DS));
76         memset(eap_ds, 0, sizeof(EAP_DS));
77         if ((eap_ds->response = eap_packet_alloc()) == NULL) {
78                 eap_ds_free(&eap_ds);
79                 return NULL;
80         }
81         if ((eap_ds->request = eap_packet_alloc()) == NULL) {
82                 eap_ds_free(&eap_ds);
83                 return NULL;
84         }
85
86         return eap_ds;
87 }
88
89 void eap_ds_free(EAP_DS **eap_ds_p)
90 {
91         EAP_DS *eap_ds;
92
93         if (!eap_ds_p) return;
94         eap_ds = *eap_ds_p;
95         if (!eap_ds) return;
96
97         if (eap_ds->response) eap_packet_free(&(eap_ds->response));
98         if (eap_ds->request) eap_packet_free(&(eap_ds->request));
99
100         free(eap_ds);
101         *eap_ds_p = NULL;
102 }
103
104 /*
105  *      Allocate a new EAP_HANDLER
106  */
107 EAP_HANDLER *eap_handler_alloc(void)
108 {
109         EAP_HANDLER     *handler;
110         
111         if ((handler = malloc(sizeof(EAP_HANDLER))) == NULL) {
112                 radlog(L_ERR, "out of memory");
113                 return NULL;
114         }
115         handler = rad_malloc(sizeof(EAP_HANDLER));
116         return handler;
117 }
118
119 void eap_handler_free(EAP_HANDLER **handler_p)
120 {
121         EAP_HANDLER *handler;
122
123         if ((handler_p == NULL) || (*handler_p == NULL))
124                 return;
125         handler = *handler_p;
126
127         if (handler->id) {
128                 free(handler->id);
129                 handler->id = NULL;
130         }
131
132         if (handler->identity) {
133                 free(handler->identity);
134                 handler->identity = NULL;
135         }
136
137         if (handler->username) pairfree(&(handler->username));
138         if (handler->configured) pairfree(&(handler->configured));
139
140         if (handler->prev_eapds) eap_ds_free(&(handler->prev_eapds));
141         if (handler->eap_ds) eap_ds_free(&(handler->eap_ds));
142
143         if ((handler->opaque) && (handler->free_opaque))
144                 handler->free_opaque(&handler->opaque);
145         else if ((handler->opaque) && (handler->free_opaque == NULL))
146                 radlog(L_ERR, "Possible memory leak ...");
147
148         handler->opaque = NULL;
149         handler->free_opaque = NULL;
150         handler->next = NULL;
151
152         *handler_p = NULL;
153 }
154
155 void eaptype_freelist(EAP_TYPES **i)
156 {
157         EAP_TYPES       *c, *next;
158
159         c = *i;
160         while (c) {
161                 next = c->next;
162                 if(c->type->detach) (c->type->detach)(&(c->type_stuff));
163                 if (c->handle) lt_dlclose(c->handle);
164                 free(c);
165                 c = next;
166         }
167         *i = NULL;
168 }
169
170 void eaplist_free(EAP_HANDLER **list)
171 {
172         EAP_HANDLER *node, *next;
173         if (!list) return;
174         node = *list;
175
176         while (node) {
177                 next = node->next;
178                 eap_handler_free(&node);
179                 node = next;
180         }
181
182         *list = NULL;
183 }
184
185 int eaplist_add(EAP_HANDLER **list, EAP_HANDLER *node)
186 {
187         EAP_HANDLER     **last;
188
189         if (node == NULL) return 0;
190         
191         last = list;
192         while (*last) last = &((*last)->next);
193         
194         node->timestamp = time(NULL);
195         node->status = 1;
196         node->next = NULL;
197
198         *last = node;
199         return 1;
200 }
201
202 /*
203  * List should contain only recent packets with life < x seconds.
204  */
205 void eaplist_clean(EAP_HANDLER **first, time_t limit)
206 {
207         time_t  now;
208         EAP_HANDLER *node, *next;
209         EAP_HANDLER **last = first;
210
211         now = time(NULL);
212
213         for (node = *first; node; node = next) {
214                 next = node->next;
215                 if ((now - node->timestamp) > limit) {
216                         radlog(L_INFO, "rlm_eap:  list_clean deleted one item");
217                         *last = next;
218                         eap_handler_free(&node);
219                 } else  {
220                         last = &(node->next);
221                 }
222         }
223 }
224
225 /*
226  * If the present EAP-Response is a reply to the previous
227  * EAP-Request sent by us, then return the EAP_HANDLER
228  * only after releasing from the eaplist
229  * Also since we fill the eap_ds with the present EAP-Response
230  * we got to free the prev_eapds & move the eap_ds to prev_eapds
231  */
232 EAP_HANDLER *eaplist_isreply(EAP_HANDLER **first, unsigned char id[])
233 {
234         EAP_HANDLER *node, *next, *ret = NULL;
235         EAP_HANDLER **last = first;
236
237         for (node = *first; node; node = next) {
238                 next = node->next;
239                 if (memcmp(node->id, id, id[0]) == 0) {
240                         radlog(L_INFO, "rlm_eap: Request found, released from the list");
241                         /* detach the node from the list */
242                         *last = next;
243                         node->next = NULL;
244
245                         /* clean up the unwanted stuff before returning */
246                         eap_ds_free(&(node->prev_eapds));
247                         node->prev_eapds = node->eap_ds;
248                         node->eap_ds = NULL;
249
250                         ret = node;
251                         break;
252                 } else  {
253                         last = &(node->next);
254                 }
255         }
256
257         if (!ret) {
258                 radlog(L_INFO, "rlm_eap: Request not found in the list");
259         }
260         return ret;
261 }
262
263 EAP_HANDLER *eaplist_findhandler(EAP_HANDLER *list, unsigned char id[])
264 {
265         EAP_HANDLER *node;
266         node = list;
267         
268         while (node) {
269                 /*
270                  * Match is identified by the same IDs 
271                  */
272                 if (memcmp(node->id, id, id[0]) == 0) {
273                         radlog(L_INFO, "rlm_eap: EAP Handler found in the list ");
274                         return node;
275                 }
276                 node = node->next;
277         }
278         return NULL;
279 }