Annotation of embedaddon/strongswan/src/libtnccs/plugins/tnc_imv/tnc_imv_manager.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2010-2013 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 "tnc_imv_manager.h"
17: #include "tnc_imv.h"
18: #include "tnc_imv_recommendations.h"
19:
20: #include <tncifimv.h>
21:
22: #include <sys/types.h>
23: #include <sys/stat.h>
24: #include <unistd.h>
25: #include <errno.h>
26: #include <fcntl.h>
27:
28: #include <utils/debug.h>
29: #include <threading/rwlock.h>
30: #include <threading/mutex.h>
31: #include <collections/linked_list.h>
32:
33: typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t;
34:
35: /**
36: * Private data of an imv_manager_t object.
37: */
38: struct private_tnc_imv_manager_t {
39:
40: /**
41: * Public members of imv_manager_t.
42: */
43: imv_manager_t public;
44:
45: /**
46: * Linked list of IMVs
47: */
48: linked_list_t *imvs;
49:
50: /**
51: * Lock for IMV list
52: */
53: rwlock_t *lock;
54:
55: /**
56: * Next IMV ID to be assigned
57: */
58: TNC_IMVID next_imv_id;
59:
60: /**
61: * Mutex to access next IMV ID
62: */
63: mutex_t *id_mutex;
64:
65: /**
66: * Policy defining how to derive final recommendation from individual ones
67: */
68: recommendation_policy_t policy;
69: };
70:
71: METHOD(imv_manager_t, add, bool,
72: private_tnc_imv_manager_t *this, imv_t *imv)
73: {
74: TNC_Version version;
75: TNC_IMVID imv_id;
76:
77: this->id_mutex->lock(this->id_mutex);
78: imv_id = this->next_imv_id++;
79: this->id_mutex->unlock(this->id_mutex);
80:
81: imv->set_id(imv, imv_id);
82: if (imv->initialize(imv_id, TNC_IFIMV_VERSION_1,
83: TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
84: {
85: DBG1(DBG_TNC, "IMV \"%s\" failed to initialize", imv->get_name(imv));
86: return FALSE;
87: }
88: this->lock->write_lock(this->lock);
89: this->imvs->insert_last(this->imvs, imv);
90: this->lock->unlock(this->lock);
91:
92: if (imv->provide_bind_function(imv->get_id(imv),
93: TNC_TNCS_BindFunction) != TNC_RESULT_SUCCESS)
94: {
95: if (imv->terminate)
96: {
97: imv->terminate(imv->get_id(imv));
98: }
99: DBG1(DBG_TNC, "IMV \"%s\" failed to obtain bind function",
100: imv->get_name(imv));
101: this->lock->write_lock(this->lock);
102: this->imvs->remove_last(this->imvs, (void**)&imv);
103: this->lock->unlock(this->lock);
104: return FALSE;
105: }
106: return TRUE;
107: }
108:
109: METHOD(imv_manager_t, remove_, imv_t*,
110: private_tnc_imv_manager_t *this, TNC_IMVID id)
111: {
112: enumerator_t *enumerator;
113: imv_t *imv, *removed_imv = NULL;
114:
115: this->lock->write_lock(this->lock);
116: enumerator = this->imvs->create_enumerator(this->imvs);
117: while (enumerator->enumerate(enumerator, &imv))
118: {
119: if (id == imv->get_id(imv))
120: {
121: this->imvs->remove_at(this->imvs, enumerator);
122: removed_imv = imv;
123: break;
124: }
125: }
126: enumerator->destroy(enumerator);
127: this->lock->unlock(this->lock);
128:
129: return removed_imv;
130: }
131:
132: METHOD(imv_manager_t, load, bool,
133: private_tnc_imv_manager_t *this, char *name, char *path)
134: {
135: imv_t *imv;
136:
137: imv = tnc_imv_create(name, path);
138: if (!imv)
139: {
140: return FALSE;
141: }
142: if (!add(this, imv))
143: {
144: imv->destroy(imv);
145: return FALSE;
146: }
147: DBG1(DBG_TNC, "IMV %u \"%s\" loaded from '%s'", imv->get_id(imv), name, path);
148: return TRUE;
149: }
150:
151: METHOD(imv_manager_t, load_from_functions, bool,
152: private_tnc_imv_manager_t *this, char *name,
153: TNC_IMV_InitializePointer initialize,
154: TNC_IMV_NotifyConnectionChangePointer notify_connection_change,
155: TNC_IMV_ReceiveMessagePointer receive_message,
156: TNC_IMV_ReceiveMessageLongPointer receive_message_long,
157: TNC_IMV_SolicitRecommendationPointer solicit_recommendation,
158: TNC_IMV_BatchEndingPointer batch_ending,
159: TNC_IMV_TerminatePointer terminate,
160: TNC_IMV_ProvideBindFunctionPointer provide_bind_function)
161: {
162: imv_t *imv;
163:
164: imv = tnc_imv_create_from_functions(name,
165: initialize,notify_connection_change,
166: receive_message, receive_message_long,
167: solicit_recommendation, batch_ending,
168: terminate, provide_bind_function);
169: if (!imv)
170: {
171: return FALSE;
172: }
173: if (!add(this, imv))
174: {
175: imv->destroy(imv);
176: return FALSE;
177: }
178: DBG1(DBG_TNC, "IMV %u \"%s\" loaded", imv->get_id(imv), name);
179: return TRUE;
180: }
181:
182: METHOD(imv_manager_t, is_registered, bool,
183: private_tnc_imv_manager_t *this, TNC_IMVID id)
184: {
185: enumerator_t *enumerator;
186: imv_t *imv;
187: bool found = FALSE;
188:
189: this->lock->read_lock(this->lock);
190: enumerator = this->imvs->create_enumerator(this->imvs);
191: while (enumerator->enumerate(enumerator, &imv))
192: {
193: if (imv->has_id(imv, id))
194: {
195: found = TRUE;
196: break;
197: }
198: }
199: enumerator->destroy(enumerator);
200: this->lock->unlock(this->lock);
201:
202: return found;
203: }
204:
205: METHOD(imv_manager_t, reserve_id, bool,
206: private_tnc_imv_manager_t *this, TNC_IMVID id, TNC_UInt32 *new_id)
207: {
208: enumerator_t *enumerator;
209: imv_t *imv;
210: bool found = FALSE;
211:
212: this->lock->read_lock(this->lock);
213: enumerator = this->imvs->create_enumerator(this->imvs);
214: while (enumerator->enumerate(enumerator, &imv))
215: {
216: if (id == imv->get_id(imv))
217: {
218: found = TRUE;
219: this->id_mutex->lock(this->id_mutex);
220: *new_id = this->next_imv_id++;
221: this->id_mutex->unlock(this->id_mutex);
222: imv->add_id(imv, *new_id);
223: DBG2(DBG_TNC, "additional ID %u reserved for IMV with primary ID %u",
224: *new_id, id);
225: break;
226: }
227: }
228: enumerator->destroy(enumerator);
229: this->lock->unlock(this->lock);
230:
231: return found;
232: }
233:
234: METHOD(imv_manager_t, get_recommendation_policy, recommendation_policy_t,
235: private_tnc_imv_manager_t *this)
236: {
237: return this->policy;
238: }
239:
240: METHOD(imv_manager_t, create_recommendations, recommendations_t*,
241: private_tnc_imv_manager_t *this)
242: {
243: return tnc_imv_recommendations_create(this->imvs);
244: }
245:
246:
247: METHOD(imv_manager_t, notify_connection_change, void,
248: private_tnc_imv_manager_t *this, TNC_ConnectionID id,
249: TNC_ConnectionState state)
250: {
251: enumerator_t *enumerator;
252: imv_t *imv;
253:
254: this->lock->read_lock(this->lock);
255: enumerator = this->imvs->create_enumerator(this->imvs);
256: while (enumerator->enumerate(enumerator, &imv))
257: {
258: if (imv->notify_connection_change)
259: {
260: imv->notify_connection_change(imv->get_id(imv), id, state);
261: }
262: }
263: enumerator->destroy(enumerator);
264: this->lock->unlock(this->lock);
265: }
266:
267: METHOD(imv_manager_t, set_message_types, TNC_Result,
268: private_tnc_imv_manager_t *this, TNC_IMVID id,
269: TNC_MessageTypeList supported_types,
270: TNC_UInt32 type_count)
271: {
272: enumerator_t *enumerator;
273: imv_t *imv;
274: TNC_Result result = TNC_RESULT_FATAL;
275:
276: this->lock->read_lock(this->lock);
277: enumerator = this->imvs->create_enumerator(this->imvs);
278: while (enumerator->enumerate(enumerator, &imv))
279: {
280: if (id == imv->get_id(imv))
281: {
282: imv->set_message_types(imv, supported_types, type_count);
283: result = TNC_RESULT_SUCCESS;
284: break;
285: }
286: }
287: enumerator->destroy(enumerator);
288: this->lock->unlock(this->lock);
289: return result;
290: }
291:
292: METHOD(imv_manager_t, set_message_types_long, TNC_Result,
293: private_tnc_imv_manager_t *this, TNC_IMVID id,
294: TNC_VendorIDList supported_vids,
295: TNC_MessageSubtypeList supported_subtypes,
296: TNC_UInt32 type_count)
297: {
298: enumerator_t *enumerator;
299: imv_t *imv;
300: TNC_Result result = TNC_RESULT_FATAL;
301:
302: this->lock->read_lock(this->lock);
303: enumerator = this->imvs->create_enumerator(this->imvs);
304: while (enumerator->enumerate(enumerator, &imv))
305: {
306: if (id == imv->get_id(imv))
307: {
308: imv->set_message_types_long(imv, supported_vids, supported_subtypes,
309: type_count);
310: result = TNC_RESULT_SUCCESS;
311: break;
312: }
313: }
314: enumerator->destroy(enumerator);
315: this->lock->unlock(this->lock);
316: return result;
317: }
318:
319: METHOD(imv_manager_t, solicit_recommendation, void,
320: private_tnc_imv_manager_t *this, TNC_ConnectionID id)
321: {
322: enumerator_t *enumerator;
323: imv_t *imv;
324:
325: this->lock->read_lock(this->lock);
326: enumerator = this->imvs->create_enumerator(this->imvs);
327: while (enumerator->enumerate(enumerator, &imv))
328: {
329: imv->solicit_recommendation(imv->get_id(imv), id);
330: }
331: enumerator->destroy(enumerator);
332: this->lock->unlock(this->lock);
333: }
334:
335: METHOD(imv_manager_t, receive_message, void,
336: private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
337: bool excl,
338: TNC_BufferReference msg,
339: TNC_UInt32 msg_len,
340: TNC_VendorID msg_vid,
341: TNC_MessageSubtype msg_subtype,
342: TNC_UInt32 src_imc_id,
343: TNC_UInt32 dst_imv_id)
344: {
345: bool type_supported = FALSE;
346: TNC_MessageType msg_type;
347: TNC_UInt32 msg_flags;
348: enumerator_t *enumerator;
349: imv_t *imv;
350:
351: msg_type = (msg_vid << 8) | msg_subtype;
352:
353: this->lock->read_lock(this->lock);
354: enumerator = this->imvs->create_enumerator(this->imvs);
355: while (enumerator->enumerate(enumerator, &imv))
356: {
357: if (imv->type_supported(imv, msg_vid, msg_subtype) &&
358: (!excl || (excl && imv->has_id(imv, dst_imv_id))))
359: {
360: if (imv->receive_message_long && src_imc_id)
361: {
362: type_supported = TRUE;
363: msg_flags = excl ? TNC_MESSAGE_FLAGS_EXCLUSIVE : 0;
364: imv->receive_message_long(imv->get_id(imv), connection_id,
365: msg_flags, msg, msg_len, msg_vid, msg_subtype,
366: src_imc_id, dst_imv_id);
367:
368: }
369: else if (imv->receive_message && msg_vid <= TNC_VENDORID_ANY &&
370: msg_subtype <= TNC_SUBTYPE_ANY)
371: {
372: type_supported = TRUE;
373: msg_type = (msg_vid << 8) | msg_subtype;
374: imv->receive_message(imv->get_id(imv), connection_id,
375: msg, msg_len, msg_type);
376: }
377: }
378: }
379: enumerator->destroy(enumerator);
380: this->lock->unlock(this->lock);
381:
382: if (!type_supported)
383: {
384: DBG2(DBG_TNC, "message type 0x%06x/0x%08x not supported by any IMV",
385: msg_vid, msg_subtype);
386: }
387: }
388:
389: METHOD(imv_manager_t, batch_ending, void,
390: private_tnc_imv_manager_t *this, TNC_ConnectionID id)
391: {
392: enumerator_t *enumerator;
393: imv_t *imv;
394:
395: this->lock->read_lock(this->lock);
396: enumerator = this->imvs->create_enumerator(this->imvs);
397: while (enumerator->enumerate(enumerator, &imv))
398: {
399: if (imv->batch_ending)
400: {
401: imv->batch_ending(imv->get_id(imv), id);
402: }
403: }
404: enumerator->destroy(enumerator);
405: this->lock->unlock(this->lock);
406: }
407:
408: METHOD(imv_manager_t, destroy, void,
409: private_tnc_imv_manager_t *this)
410: {
411: imv_t *imv;
412:
413: while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
414: {
415: if (imv->terminate &&
416: imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
417: {
418: DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
419: imv->get_name(imv));
420: }
421: imv->destroy(imv);
422: }
423: this->imvs->destroy(this->imvs);
424: this->lock->destroy(this->lock);
425: this->id_mutex->destroy(this->id_mutex);
426: free(this);
427: }
428:
429: /**
430: * Described in header.
431: */
432: imv_manager_t* tnc_imv_manager_create(void)
433: {
434: private_tnc_imv_manager_t *this;
435: char *polname;
436:
437: INIT(this,
438: .public = {
439: .add = _add,
440: .remove = _remove_, /* avoid name conflict with stdio.h */
441: .load = _load,
442: .load_from_functions = _load_from_functions,
443: .is_registered = _is_registered,
444: .reserve_id = _reserve_id,
445: .get_recommendation_policy = _get_recommendation_policy,
446: .create_recommendations = _create_recommendations,
447: .notify_connection_change = _notify_connection_change,
448: .set_message_types = _set_message_types,
449: .set_message_types_long = _set_message_types_long,
450: .solicit_recommendation = _solicit_recommendation,
451: .receive_message = _receive_message,
452: .batch_ending = _batch_ending,
453: .destroy = _destroy,
454: },
455: .imvs = linked_list_create(),
456: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
457: .id_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
458: .next_imv_id = 1,
459: );
460:
461: polname = lib->settings->get_str(lib->settings,
462: "%s.plugins.tnc-imv.recommendation_policy", "default", lib->ns);
463: if (!enum_from_name(recommendation_policy_names, polname, &this->policy))
464: {
465: this->policy = RECOMMENDATION_POLICY_DEFAULT;
466: }
467: DBG1(DBG_TNC, "TNC recommendation policy is '%N'",
468: recommendation_policy_names, this->policy);
469:
470: return &this->public;
471: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>