2 * Copyright (C) 2010 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
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>.
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
16 #include "tnccs_manager.h"
18 #include <tnc/imv/imv_recommendations.h>
22 #include <utils/linked_list.h>
23 #include <threading/rwlock.h>
25 typedef struct private_tnccs_manager_t private_tnccs_manager_t
;
26 typedef struct tnccs_entry_t tnccs_entry_t
;
27 typedef struct tnccs_connection_entry_t tnccs_connection_entry_t
;
30 * TNCCS constructor entry
32 struct tnccs_entry_t
{
40 * constructor function to create instance
42 tnccs_constructor_t constructor
;
46 * TNCCS connection entry
48 struct tnccs_connection_entry_t
{
61 * TNCCS send message function
63 tnccs_send_message_t send_message
;
66 * collection of IMV recommendations
68 recommendations_t
*recs
;
72 * private data of tnccs_manager
74 struct private_tnccs_manager_t
{
79 tnccs_manager_t
public;
82 * list of TNCCS protocol entries
84 linked_list_t
*protocols
;
87 * rwlock to lock the TNCCS protocol entries
89 rwlock_t
*protocol_lock
;
92 * connection ID counter
94 TNC_ConnectionID connection_id
;
97 * list of TNCCS connection entries
99 linked_list_t
*connections
;
102 * rwlock to lock TNCCS connection entries
104 rwlock_t
*connection_lock
;
108 METHOD(tnccs_manager_t
, add_method
, void,
109 private_tnccs_manager_t
*this, tnccs_type_t type
,
110 tnccs_constructor_t constructor
)
112 tnccs_entry_t
*entry
;
114 entry
= malloc_thing(tnccs_entry_t
);
116 entry
->constructor
= constructor
;
118 this->protocol_lock
->write_lock(this->protocol_lock
);
119 this->protocols
->insert_last(this->protocols
, entry
);
120 this->protocol_lock
->unlock(this->protocol_lock
);
123 METHOD(tnccs_manager_t
, remove_method
, void,
124 private_tnccs_manager_t
*this, tnccs_constructor_t constructor
)
126 enumerator_t
*enumerator
;
127 tnccs_entry_t
*entry
;
129 this->protocol_lock
->write_lock(this->protocol_lock
);
130 enumerator
= this->protocols
->create_enumerator(this->protocols
);
131 while (enumerator
->enumerate(enumerator
, &entry
))
133 if (constructor
== entry
->constructor
)
135 this->protocols
->remove_at(this->protocols
, enumerator
);
139 enumerator
->destroy(enumerator
);
140 this->protocol_lock
->unlock(this->protocol_lock
);
143 METHOD(tnccs_manager_t
, create_instance
, tnccs_t
*,
144 private_tnccs_manager_t
*this, tnccs_type_t type
, bool is_server
)
146 enumerator_t
*enumerator
;
147 tnccs_entry_t
*entry
;
148 tnccs_t
*protocol
= NULL
;
150 this->protocol_lock
->read_lock(this->protocol_lock
);
151 enumerator
= this->protocols
->create_enumerator(this->protocols
);
152 while (enumerator
->enumerate(enumerator
, &entry
))
154 if (type
== entry
->type
)
156 protocol
= entry
->constructor(is_server
);
163 enumerator
->destroy(enumerator
);
164 this->protocol_lock
->unlock(this->protocol_lock
);
169 METHOD(tnccs_manager_t
, create_connection
, TNC_ConnectionID
,
170 private_tnccs_manager_t
*this, tnccs_t
*tnccs
,
171 tnccs_send_message_t send_message
, recommendations_t
**recs
)
173 tnccs_connection_entry_t
*entry
;
175 entry
= malloc_thing(tnccs_connection_entry_t
);
176 entry
->tnccs
= tnccs
;
177 entry
->send_message
= send_message
;
180 /* we assume a TNC Server needing recommendations from IMVs */
183 DBG1(DBG_TNC
, "no IMV manager available!");
187 entry
->recs
= charon
->imvs
->create_recommendations(charon
->imvs
);
192 /* we assume a TNC Client */
195 DBG1(DBG_TNC
, "no IMC manager available!");
201 this->connection_lock
->write_lock(this->connection_lock
);
202 entry
->id
= ++this->connection_id
;
203 this->connections
->insert_last(this->connections
, entry
);
204 this->connection_lock
->unlock(this->connection_lock
);
206 DBG1(DBG_TNC
, "assigned TNCCS Connection ID %u", entry
->id
);
210 METHOD(tnccs_manager_t
, remove_connection
, void,
211 private_tnccs_manager_t
*this, TNC_ConnectionID id
)
213 enumerator_t
*enumerator
;
214 tnccs_connection_entry_t
*entry
;
216 this->connection_lock
->write_lock(this->connection_lock
);
217 enumerator
= this->connections
->create_enumerator(this->connections
);
218 while (enumerator
->enumerate(enumerator
, &entry
))
222 this->connections
->remove_at(this->connections
, enumerator
);
225 entry
->recs
->destroy(entry
->recs
);
228 DBG1(DBG_TNC
, "removed TNCCS Connection ID %u", id
);
231 enumerator
->destroy(enumerator
);
232 this->connection_lock
->unlock(this->connection_lock
);
235 METHOD(tnccs_manager_t
, send_message
, TNC_Result
,
236 private_tnccs_manager_t
*this, TNC_ConnectionID id
,
237 TNC_BufferReference message
,
238 TNC_UInt32 message_len
,
239 TNC_MessageType message_type
)
241 enumerator_t
*enumerator
;
242 tnccs_connection_entry_t
*entry
;
243 tnccs_send_message_t send_message
= NULL
;
244 tnccs_t
*tnccs
= NULL
;
246 this->connection_lock
->read_lock(this->connection_lock
);
247 enumerator
= this->connections
->create_enumerator(this->connections
);
248 while (enumerator
->enumerate(enumerator
, &entry
))
252 tnccs
= entry
->tnccs
;
253 send_message
= entry
->send_message
;
257 enumerator
->destroy(enumerator
);
258 this->connection_lock
->unlock(this->connection_lock
);
260 if (tnccs
&& send_message
)
262 send_message(tnccs
, message
, message_len
, message_type
);
263 return TNC_RESULT_SUCCESS
;
265 return TNC_RESULT_FATAL
;
268 METHOD(tnccs_manager_t
, provide_recommendation
, TNC_Result
,
269 private_tnccs_manager_t
*this, TNC_IMVID imv_id
,
271 TNC_IMV_Action_Recommendation rec
,
272 TNC_IMV_Evaluation_Result eval
)
274 enumerator_t
*enumerator
;
275 tnccs_connection_entry_t
*entry
;
276 recommendations_t
*recs
= NULL
;
278 this->connection_lock
->read_lock(this->connection_lock
);
279 enumerator
= this->connections
->create_enumerator(this->connections
);
280 while (enumerator
->enumerate(enumerator
, &entry
))
288 enumerator
->destroy(enumerator
);
289 this->connection_lock
->unlock(this->connection_lock
);
293 recs
->provide_recommendation(recs
, imv_id
, rec
, eval
);
294 return TNC_RESULT_SUCCESS
;
296 return TNC_RESULT_FATAL
;
299 METHOD(tnccs_manager_t
, get_attribute
, TNC_Result
,
300 private_tnccs_manager_t
*this, TNC_IMVID imv_id
,
302 TNC_AttributeID attribute_id
,
303 TNC_UInt32 buffer_len
,
304 TNC_BufferReference buffer
,
305 TNC_UInt32
*out_value_len
)
307 enumerator_t
*enumerator
;
308 tnccs_connection_entry_t
*entry
;
309 recommendations_t
*recs
= NULL
;
311 if (id
== TNC_CONNECTIONID_ANY
||
312 attribute_id
!= TNC_ATTRIBUTEID_PREFERRED_LANGUAGE
)
314 return TNC_RESULT_INVALID_PARAMETER
;
317 this->connection_lock
->read_lock(this->connection_lock
);
318 enumerator
= this->connections
->create_enumerator(this->connections
);
319 while (enumerator
->enumerate(enumerator
, &entry
))
327 enumerator
->destroy(enumerator
);
328 this->connection_lock
->unlock(this->connection_lock
);
334 pref_lang
= recs
->get_preferred_language(recs
);
335 if (pref_lang
.len
== 0)
337 return TNC_RESULT_INVALID_PARAMETER
;
339 *out_value_len
= pref_lang
.len
;
340 if (buffer
&& buffer_len
<= pref_lang
.len
)
342 memcpy(buffer
, pref_lang
.ptr
, pref_lang
.len
);
344 return TNC_RESULT_SUCCESS
;
346 return TNC_RESULT_INVALID_PARAMETER
;
349 METHOD(tnccs_manager_t
, set_attribute
, TNC_Result
,
350 private_tnccs_manager_t
*this, TNC_IMVID imv_id
,
352 TNC_AttributeID attribute_id
,
353 TNC_UInt32 buffer_len
,
354 TNC_BufferReference buffer
)
356 enumerator_t
*enumerator
;
357 tnccs_connection_entry_t
*entry
;
358 recommendations_t
*recs
= NULL
;
360 if (id
== TNC_CONNECTIONID_ANY
||
361 (attribute_id
!= TNC_ATTRIBUTEID_REASON_STRING
&&
362 attribute_id
!= TNC_ATTRIBUTEID_REASON_LANGUAGE
))
364 return TNC_RESULT_INVALID_PARAMETER
;
367 this->connection_lock
->read_lock(this->connection_lock
);
368 enumerator
= this->connections
->create_enumerator(this->connections
);
369 while (enumerator
->enumerate(enumerator
, &entry
))
377 enumerator
->destroy(enumerator
);
378 this->connection_lock
->unlock(this->connection_lock
);
382 chunk_t attribute
= { buffer
, buffer_len
};
384 if (attribute_id
== TNC_ATTRIBUTEID_REASON_STRING
)
386 return recs
->set_reason_string(recs
, imv_id
, attribute
);
390 return recs
->set_reason_language(recs
, imv_id
, attribute
);
393 return TNC_RESULT_INVALID_PARAMETER
;
396 METHOD(tnccs_manager_t
, destroy
, void,
397 private_tnccs_manager_t
*this)
399 this->protocols
->destroy_function(this->protocols
, free
);
400 this->protocol_lock
->destroy(this->protocol_lock
);
401 this->connections
->destroy_function(this->connections
, free
);
402 this->connection_lock
->destroy(this->connection_lock
);
409 tnccs_manager_t
*tnccs_manager_create()
411 private_tnccs_manager_t
*this;
415 .add_method
= _add_method
,
416 .remove_method
= _remove_method
,
417 .create_instance
= _create_instance
,
418 .create_connection
= _create_connection
,
419 .remove_connection
= _remove_connection
,
420 .send_message
= _send_message
,
421 .provide_recommendation
= _provide_recommendation
,
422 .get_attribute
= _get_attribute
,
423 .set_attribute
= _set_attribute
,
426 .protocols
= linked_list_create(),
427 .connections
= linked_list_create(),
428 .protocol_lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
429 .connection_lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
432 return &this->public;