84d4509fd33a013400b7dcccf94f14eec4ffb466
[strongswan.git] / src / libcharon / tnc / tnccs / tnccs_manager.c
1 /*
2 * Copyright (C) 2010 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "tnccs_manager.h"
17
18 #include <debug.h>
19 #include <utils/linked_list.h>
20 #include <threading/rwlock.h>
21
22 typedef struct private_tnccs_manager_t private_tnccs_manager_t;
23 typedef struct tnccs_entry_t tnccs_entry_t;
24 typedef struct tnccs_connection_entry_t tnccs_connection_entry_t;
25
26 /**
27 * TNCCS constructor entry
28 */
29 struct tnccs_entry_t {
30
31 /**
32 * TNCCS protocol type
33 */
34 tnccs_type_t type;
35
36 /**
37 * constructor function to create instance
38 */
39 tnccs_constructor_t constructor;
40 };
41
42 /**
43 * TNCCS connection entry
44 */
45 struct tnccs_connection_entry_t {
46
47 /**
48 * TNCCS connection ID
49 */
50 TNC_ConnectionID id;
51
52 /**
53 * TNCCS instance
54 */
55 tnccs_t *tnccs;
56
57 /** TNCCS send message function
58 *
59 */
60 tnccs_send_message_t send_message;
61
62 /** TNCS provide recommendation function
63 *
64 */
65 tnccs_provide_recommendation_t provide_recommendation;
66 };
67
68 /**
69 * private data of tnccs_manager
70 */
71 struct private_tnccs_manager_t {
72
73 /**
74 * public functions
75 */
76 tnccs_manager_t public;
77
78 /**
79 * list of TNCCS protocol entries
80 */
81 linked_list_t *protocols;
82
83 /**
84 * connection ID counter
85 */
86 TNC_ConnectionID connection_id;
87
88 /**
89 * list of TNCCS connection entries
90 */
91 linked_list_t *connections;
92
93 /**
94 * rwlock to lock TNCCS protocol and connection entries
95 */
96 rwlock_t *lock;
97
98 };
99
100 METHOD(tnccs_manager_t, add_method, void,
101 private_tnccs_manager_t *this, tnccs_type_t type,
102 tnccs_constructor_t constructor)
103 {
104 tnccs_entry_t *entry = malloc_thing(tnccs_entry_t);
105
106 entry->type = type;
107 entry->constructor = constructor;
108
109 this->lock->write_lock(this->lock);
110 this->protocols->insert_last(this->protocols, entry);
111 this->lock->unlock(this->lock);
112 }
113
114 METHOD(tnccs_manager_t, remove_method, void,
115 private_tnccs_manager_t *this, tnccs_constructor_t constructor)
116 {
117 enumerator_t *enumerator;
118 tnccs_entry_t *entry;
119
120 this->lock->write_lock(this->lock);
121 enumerator = this->protocols->create_enumerator(this->protocols);
122 while (enumerator->enumerate(enumerator, &entry))
123 {
124 if (constructor == entry->constructor)
125 {
126 this->protocols->remove_at(this->protocols, enumerator);
127 free(entry);
128 }
129 }
130 enumerator->destroy(enumerator);
131 this->lock->unlock(this->lock);
132 }
133
134 METHOD(tnccs_manager_t, create_instance, tnccs_t*,
135 private_tnccs_manager_t *this, tnccs_type_t type, bool is_server)
136 {
137 enumerator_t *enumerator;
138 tnccs_entry_t *entry;
139 tnccs_t *protocol = NULL;
140
141 this->lock->read_lock(this->lock);
142 enumerator = this->protocols->create_enumerator(this->protocols);
143 while (enumerator->enumerate(enumerator, &entry))
144 {
145 if (type == entry->type)
146 {
147 protocol = entry->constructor(is_server);
148 if (protocol)
149 {
150 break;
151 }
152 }
153 }
154 enumerator->destroy(enumerator);
155 this->lock->unlock(this->lock);
156 return protocol;
157 }
158
159 METHOD(tnccs_manager_t, create_connection, TNC_ConnectionID,
160 private_tnccs_manager_t *this, tnccs_t *tnccs,
161 tnccs_send_message_t send_message,
162 tnccs_provide_recommendation_t provide_recommendation)
163 {
164 tnccs_connection_entry_t *entry = malloc_thing(tnccs_connection_entry_t);
165
166 entry->id = ++this->connection_id;
167 entry->tnccs = tnccs;
168 entry->send_message = send_message;
169 entry->provide_recommendation = provide_recommendation;
170
171 this->lock->write_lock(this->lock);
172 this->connections->insert_last(this->connections, entry);
173 this->lock->unlock(this->lock);
174
175 DBG1(DBG_TNC, "assigned TNCCS Connection ID %u", entry->id);
176 return entry->id;
177 }
178
179 METHOD(tnccs_manager_t, remove_connection, void,
180 private_tnccs_manager_t *this, TNC_ConnectionID id)
181 {
182 enumerator_t *enumerator;
183 tnccs_connection_entry_t *entry;
184
185 this->lock->write_lock(this->lock);
186 enumerator = this->connections->create_enumerator(this->connections);
187 while (enumerator->enumerate(enumerator, &entry))
188 {
189 if (id == entry->id)
190 {
191 this->connections->remove_at(this->connections, enumerator);
192 free(entry);
193 DBG1(DBG_TNC, "removed TNCCS Connection ID %u", id);
194 }
195 }
196 enumerator->destroy(enumerator);
197 this->lock->unlock(this->lock);
198 }
199
200 METHOD(tnccs_manager_t, send_message, TNC_Result,
201 private_tnccs_manager_t *this, TNC_ConnectionID id,
202 TNC_BufferReference message,
203 TNC_UInt32 message_len,
204 TNC_MessageType message_type)
205 {
206 enumerator_t *enumerator;
207 tnccs_connection_entry_t *entry;
208 tnccs_send_message_t send_message = NULL;
209 tnccs_t *tnccs = NULL;
210
211 this->lock->write_lock(this->lock);
212 enumerator = this->connections->create_enumerator(this->connections);
213 while (enumerator->enumerate(enumerator, &entry))
214 {
215 if (id == entry->id)
216 {
217 tnccs = entry->tnccs;
218 send_message = entry->send_message;
219 break;
220 }
221 }
222 enumerator->destroy(enumerator);
223 this->lock->unlock(this->lock);
224
225 if (tnccs && send_message)
226 {
227 send_message(tnccs, message, message_len, message_type);
228 return TNC_RESULT_SUCCESS;
229 }
230 return TNC_RESULT_FATAL;
231 }
232
233 METHOD(tnccs_manager_t, provide_recommendation, TNC_Result,
234 private_tnccs_manager_t *this, TNC_IMVID imv_id,
235 TNC_ConnectionID id,
236 TNC_IMV_Action_Recommendation recommendation,
237 TNC_IMV_Evaluation_Result evaluation)
238 {
239 enumerator_t *enumerator;
240 tnccs_connection_entry_t *entry;
241 tnccs_provide_recommendation_t provide_recommendation = NULL;
242 tnccs_t *tnccs = NULL;
243
244 this->lock->write_lock(this->lock);
245 enumerator = this->connections->create_enumerator(this->connections);
246 while (enumerator->enumerate(enumerator, &entry))
247 {
248 if (id == entry->id)
249 {
250 tnccs = entry->tnccs;
251 provide_recommendation = entry->provide_recommendation;
252 break;
253 }
254 }
255 enumerator->destroy(enumerator);
256 this->lock->unlock(this->lock);
257
258 if (tnccs && provide_recommendation)
259 {
260 provide_recommendation(tnccs, imv_id, recommendation, evaluation);
261 return TNC_RESULT_SUCCESS;
262 }
263 return TNC_RESULT_FATAL;
264 }
265
266 METHOD(tnccs_manager_t, destroy, void,
267 private_tnccs_manager_t *this)
268 {
269 this->protocols->destroy_function(this->protocols, free);
270 this->connections->destroy_function(this->connections, free);
271 this->lock->destroy(this->lock);
272 free(this);
273 }
274
275 /*
276 * See header
277 */
278 tnccs_manager_t *tnccs_manager_create()
279 {
280 private_tnccs_manager_t *this;
281
282 INIT(this,
283 .public = {
284 .add_method = _add_method,
285 .remove_method = _remove_method,
286 .create_instance = _create_instance,
287 .create_connection = _create_connection,
288 .remove_connection = _remove_connection,
289 .send_message = _send_message,
290 .provide_recommendation = _provide_recommendation,
291 .destroy = _destroy,
292 },
293 .protocols = linked_list_create(),
294 .connections = linked_list_create(),
295 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
296 );
297
298 return &this->public;
299 }
300