d46b1f3ccaf89a65ae9c39d76379e7a6cda9e64a
[strongswan.git] / src / libcharon / plugins / tnc_imv / tnc_imv_manager.c
1 /*
2 * Copyright (C) 2006 Mike McCauley
3 * Copyright (C) 2010 Andreas Steffen, 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
18 #include <tnc/imv/imv_manager.h>
19 #include <tnc/tncifimv.h>
20
21 #include <debug.h>
22 #include <library.h>
23 #include <utils/linked_list.h>
24
25 typedef struct private_tnc_imv_manager_t private_tnc_imv_manager_t;
26
27 /**
28 * Private data of an imv_manager_t object.
29 */
30 struct private_tnc_imv_manager_t {
31
32 /**
33 * Public members of imv_manager_t.
34 */
35 imv_manager_t public;
36
37 /**
38 * Linked list of IMVs
39 */
40 linked_list_t *imvs;
41
42 /**
43 * Next IMV ID to be assigned
44 */
45 TNC_IMVID next_imv_id;
46 };
47
48 METHOD(imv_manager_t, add, bool,
49 private_tnc_imv_manager_t *this, imv_t *imv)
50 {
51 TNC_Version version;
52
53 /* Initialize the IMV module */
54 imv->set_id(imv, this->next_imv_id);
55 if (imv->initialize(imv->get_id(imv), TNC_IFIMV_VERSION_1,
56 TNC_IFIMV_VERSION_1, &version) != TNC_RESULT_SUCCESS)
57 {
58 DBG1(DBG_TNC, "could not initialize IMV '%s'",
59 imv->get_name(imv));
60 return FALSE;
61 }
62 this->imvs->insert_last(this->imvs, imv);
63 this->next_imv_id++;
64
65 if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction)
66 != TNC_RESULT_SUCCESS)
67 {
68 DBG1(DBG_TNC, "could not provide bind function for IMV '%s'",
69 imv->get_name(imv));
70 this->imvs->remove_last(this->imvs, (void**)&imv);
71 return FALSE;
72 }
73
74 return TRUE;
75 }
76
77 METHOD(imv_manager_t, remove_, imv_t*,
78 private_tnc_imv_manager_t *this, TNC_IMVID id)
79 {
80 enumerator_t *enumerator;
81 imv_t *imv;
82
83 enumerator = this->imvs->create_enumerator(this->imvs);
84 while (enumerator->enumerate(enumerator, &imv))
85 {
86 if (id == imv->get_id(imv))
87 {
88 this->imvs->remove_at(this->imvs, enumerator);
89 return imv;
90 }
91 }
92 enumerator->destroy(enumerator);
93 return NULL;
94 }
95
96 METHOD(imv_manager_t, get_count, int,
97 private_tnc_imv_manager_t *this)
98 {
99 return this->imvs->get_count(this->imvs);
100 }
101
102 METHOD(imv_manager_t, notify_connection_change, void,
103 private_tnc_imv_manager_t *this, TNC_ConnectionID id,
104 TNC_ConnectionState state)
105 {
106 enumerator_t *enumerator;
107 imv_t *imv;
108
109 enumerator = this->imvs->create_enumerator(this->imvs);
110 while (enumerator->enumerate(enumerator, &imv))
111 {
112 if (imv->notify_connection_change)
113 {
114 imv->notify_connection_change(imv->get_id(imv), id, state);
115 }
116 }
117 enumerator->destroy(enumerator);
118 }
119
120 METHOD(imv_manager_t, set_message_types, TNC_Result,
121 private_tnc_imv_manager_t *this, TNC_IMVID id,
122 TNC_MessageTypeList supported_types,
123 TNC_UInt32 type_count)
124 {
125 enumerator_t *enumerator;
126 imv_t *imv;
127 TNC_Result result = TNC_RESULT_FATAL;
128
129 enumerator = this->imvs->create_enumerator(this->imvs);
130 while (enumerator->enumerate(enumerator, &imv))
131 {
132 if (id == imv->get_id(imv))
133 {
134 imv->set_message_types(imv, supported_types, type_count);
135 result = TNC_RESULT_SUCCESS;
136 break;
137 }
138 }
139 enumerator->destroy(enumerator);
140 return result;
141 }
142
143 METHOD(imv_manager_t, receive_message, void,
144 private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
145 TNC_BufferReference message,
146 TNC_UInt32 message_len,
147 TNC_MessageType message_type)
148 {
149 enumerator_t *enumerator;
150 imv_t *imv;
151
152 enumerator = this->imvs->create_enumerator(this->imvs);
153 while (enumerator->enumerate(enumerator, &imv))
154 {
155 if (imv->receive_message && imv->type_supported(imv, message_type))
156 {
157 imv->receive_message(imv->get_id(imv), connection_id,
158 message, message_len, message_type);
159 }
160 }
161 enumerator->destroy(enumerator);
162 }
163
164 METHOD(imv_manager_t, destroy, void,
165 private_tnc_imv_manager_t *this)
166 {
167 imv_t *imv;
168
169 while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
170 {
171 if (imv->terminate &&
172 imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
173 {
174 DBG1(DBG_TNC, "IMV '%s' not terminated successfully",
175 imv->get_name(imv));
176 }
177 imv->destroy(imv);
178 }
179 this->imvs->destroy(this->imvs);
180 free(this);
181 }
182
183 /**
184 * Described in header.
185 */
186 imv_manager_t* tnc_imv_manager_create(void)
187 {
188 private_tnc_imv_manager_t *this;
189
190 INIT(this,
191 .public = {
192 .add = _add,
193 .remove = _remove_, /* avoid name conflict with stdio.h */
194 .get_count = _get_count,
195 .notify_connection_change = _notify_connection_change,
196 .set_message_types = _set_message_types,
197 .receive_message = _receive_message,
198 .destroy = _destroy,
199 },
200 .imvs = linked_list_create(),
201 .next_imv_id = 1,
202 );
203
204 return &this->public;
205 }