Added a method to enumerate registered EAP methods
[strongswan.git] / src / libcharon / sa / eap / eap_manager.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "eap_manager.h"
18
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
21
22 typedef struct private_eap_manager_t private_eap_manager_t;
23 typedef struct eap_entry_t eap_entry_t;
24
25 /**
26 * EAP constructor entry
27 */
28 struct eap_entry_t {
29
30 /**
31 * EAP method type, vendor specific if vendor is set
32 */
33 eap_type_t type;
34
35 /**
36 * vendor ID, 0 for default EAP methods
37 */
38 u_int32_t vendor;
39
40 /**
41 * Role of the method returned by the constructor, EAP_SERVER or EAP_PEER
42 */
43 eap_role_t role;
44
45 /**
46 * constructor function to create instance
47 */
48 eap_constructor_t constructor;
49 };
50
51 /**
52 * private data of eap_manager
53 */
54 struct private_eap_manager_t {
55
56 /**
57 * public functions
58 */
59 eap_manager_t public;
60
61 /**
62 * list of eap_entry_t's
63 */
64 linked_list_t *methods;
65
66 /**
67 * rwlock to lock methods
68 */
69 rwlock_t *lock;
70 };
71
72 METHOD(eap_manager_t, add_method, void,
73 private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
74 eap_role_t role, eap_constructor_t constructor)
75 {
76 eap_entry_t *entry = malloc_thing(eap_entry_t);
77
78 entry->type = type;
79 entry->vendor = vendor;
80 entry->role = role;
81 entry->constructor = constructor;
82
83 this->lock->write_lock(this->lock);
84 this->methods->insert_last(this->methods, entry);
85 this->lock->unlock(this->lock);
86 }
87
88 METHOD(eap_manager_t, remove_method, void,
89 private_eap_manager_t *this, eap_constructor_t constructor)
90 {
91 enumerator_t *enumerator;
92 eap_entry_t *entry;
93
94 this->lock->write_lock(this->lock);
95 enumerator = this->methods->create_enumerator(this->methods);
96 while (enumerator->enumerate(enumerator, &entry))
97 {
98 if (constructor == entry->constructor)
99 {
100 this->methods->remove_at(this->methods, enumerator);
101 free(entry);
102 }
103 }
104 enumerator->destroy(enumerator);
105 this->lock->unlock(this->lock);
106 }
107
108 /**
109 * filter the registered methods
110 */
111 static bool filter_methods(uintptr_t role, eap_entry_t **entry,
112 eap_type_t *type, void *in, u_int32_t *vendor)
113 {
114 if ((*entry)->role != (eap_role_t)role)
115 {
116 return FALSE;
117 }
118 if (type)
119 {
120 *type = (*entry)->type;
121 }
122 if (vendor)
123 {
124 *vendor = (*entry)->vendor;
125 }
126 return TRUE;
127 }
128
129 METHOD(eap_manager_t, create_enumerator, enumerator_t*,
130 private_eap_manager_t *this, eap_role_t role)
131 {
132 this->lock->read_lock(this->lock);
133 return enumerator_create_cleaner(
134 enumerator_create_filter(
135 this->methods->create_enumerator(this->methods),
136 (void*)filter_methods, (void*)(uintptr_t)role, NULL),
137 (void*)this->lock->unlock, this->lock);
138 }
139
140 METHOD(eap_manager_t, create_instance, eap_method_t*,
141 private_eap_manager_t *this, eap_type_t type, u_int32_t vendor,
142 eap_role_t role, identification_t *server, identification_t *peer)
143 {
144 enumerator_t *enumerator;
145 eap_entry_t *entry;
146 eap_method_t *method = NULL;
147
148 this->lock->read_lock(this->lock);
149 enumerator = this->methods->create_enumerator(this->methods);
150 while (enumerator->enumerate(enumerator, &entry))
151 {
152 if (type == entry->type && vendor == entry->vendor &&
153 role == entry->role)
154 {
155 method = entry->constructor(server, peer);
156 if (method)
157 {
158 break;
159 }
160 }
161 }
162 enumerator->destroy(enumerator);
163 this->lock->unlock(this->lock);
164 return method;
165 }
166
167 METHOD(eap_manager_t, destroy, void,
168 private_eap_manager_t *this)
169 {
170 this->methods->destroy_function(this->methods, free);
171 this->lock->destroy(this->lock);
172 free(this);
173 }
174
175 /*
176 * See header
177 */
178 eap_manager_t *eap_manager_create()
179 {
180 private_eap_manager_t *this;
181
182 INIT(this,
183 .public = {
184 .add_method = _add_method,
185 .remove_method = _remove_method,
186 .create_enumerator = _create_enumerator,
187 .create_instance = _create_instance,
188 .destroy = _destroy,
189 },
190 .methods = linked_list_create(),
191 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
192 );
193
194 return &this->public;
195 }