00060bbce5772dee0392c2138cb4917a98bb1316
[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, "IMV \"%s\" failed to initialize", imv->get_name(imv));
59 return FALSE;
60 }
61 this->imvs->insert_last(this->imvs, imv);
62 this->next_imv_id++;
63
64 if (imv->provide_bind_function(imv->get_id(imv), TNC_TNCS_BindFunction)
65 != TNC_RESULT_SUCCESS)
66 {
67 DBG1(DBG_TNC, "IMV \"%s\" could failed to obtain bind function",
68 imv->get_name(imv));
69 this->imvs->remove_last(this->imvs, (void**)&imv);
70 return FALSE;
71 }
72
73 return TRUE;
74 }
75
76 METHOD(imv_manager_t, remove_, imv_t*,
77 private_tnc_imv_manager_t *this, TNC_IMVID id)
78 {
79 enumerator_t *enumerator;
80 imv_t *imv;
81
82 enumerator = this->imvs->create_enumerator(this->imvs);
83 while (enumerator->enumerate(enumerator, &imv))
84 {
85 if (id == imv->get_id(imv))
86 {
87 this->imvs->remove_at(this->imvs, enumerator);
88 return imv;
89 }
90 }
91 enumerator->destroy(enumerator);
92 return NULL;
93 }
94
95 METHOD(imv_manager_t, get_count, int,
96 private_tnc_imv_manager_t *this)
97 {
98 return this->imvs->get_count(this->imvs);
99 }
100
101 METHOD(imv_manager_t, notify_connection_change, void,
102 private_tnc_imv_manager_t *this, TNC_ConnectionID id,
103 TNC_ConnectionState state)
104 {
105 enumerator_t *enumerator;
106 imv_t *imv;
107
108 enumerator = this->imvs->create_enumerator(this->imvs);
109 while (enumerator->enumerate(enumerator, &imv))
110 {
111 if (imv->notify_connection_change)
112 {
113 imv->notify_connection_change(imv->get_id(imv), id, state);
114 }
115 }
116 enumerator->destroy(enumerator);
117 }
118
119 METHOD(imv_manager_t, set_message_types, TNC_Result,
120 private_tnc_imv_manager_t *this, TNC_IMVID id,
121 TNC_MessageTypeList supported_types,
122 TNC_UInt32 type_count)
123 {
124 enumerator_t *enumerator;
125 imv_t *imv;
126 TNC_Result result = TNC_RESULT_FATAL;
127
128 enumerator = this->imvs->create_enumerator(this->imvs);
129 while (enumerator->enumerate(enumerator, &imv))
130 {
131 if (id == imv->get_id(imv))
132 {
133 imv->set_message_types(imv, supported_types, type_count);
134 result = TNC_RESULT_SUCCESS;
135 break;
136 }
137 }
138 enumerator->destroy(enumerator);
139 return result;
140 }
141
142 METHOD(imv_manager_t, solicit_recommendation, void,
143 private_tnc_imv_manager_t *this, TNC_ConnectionID id)
144 {
145 enumerator_t *enumerator;
146 imv_t *imv;
147
148 enumerator = this->imvs->create_enumerator(this->imvs);
149 while (enumerator->enumerate(enumerator, &imv))
150 {
151 imv->solicit_recommendation(imv->get_id(imv), id);
152 }
153 enumerator->destroy(enumerator);
154 }
155
156 METHOD(imv_manager_t, receive_message, void,
157 private_tnc_imv_manager_t *this, TNC_ConnectionID connection_id,
158 TNC_BufferReference message,
159 TNC_UInt32 message_len,
160 TNC_MessageType message_type)
161 {
162 enumerator_t *enumerator;
163 imv_t *imv;
164
165 enumerator = this->imvs->create_enumerator(this->imvs);
166 while (enumerator->enumerate(enumerator, &imv))
167 {
168 if (imv->receive_message && imv->type_supported(imv, message_type))
169 {
170 imv->receive_message(imv->get_id(imv), connection_id,
171 message, message_len, message_type);
172 }
173 }
174 enumerator->destroy(enumerator);
175 }
176
177 METHOD(imv_manager_t, batch_ending, void,
178 private_tnc_imv_manager_t *this, TNC_ConnectionID id)
179 {
180 enumerator_t *enumerator;
181 imv_t *imv;
182
183 enumerator = this->imvs->create_enumerator(this->imvs);
184 while (enumerator->enumerate(enumerator, &imv))
185 {
186 if (imv->batch_ending)
187 {
188 imv->batch_ending(imv->get_id(imv), id);
189 }
190 }
191 enumerator->destroy(enumerator);
192 }
193
194 METHOD(imv_manager_t, destroy, void,
195 private_tnc_imv_manager_t *this)
196 {
197 imv_t *imv;
198
199 while (this->imvs->remove_last(this->imvs, (void**)&imv) == SUCCESS)
200 {
201 if (imv->terminate &&
202 imv->terminate(imv->get_id(imv)) != TNC_RESULT_SUCCESS)
203 {
204 DBG1(DBG_TNC, "IMV \"%s\" not terminated successfully",
205 imv->get_name(imv));
206 }
207 imv->destroy(imv);
208 }
209 this->imvs->destroy(this->imvs);
210 free(this);
211 }
212
213 /**
214 * Described in header.
215 */
216 imv_manager_t* tnc_imv_manager_create(void)
217 {
218 private_tnc_imv_manager_t *this;
219
220 INIT(this,
221 .public = {
222 .add = _add,
223 .remove = _remove_, /* avoid name conflict with stdio.h */
224 .get_count = _get_count,
225 .notify_connection_change = _notify_connection_change,
226 .set_message_types = _set_message_types,
227 .solicit_recommendation = _solicit_recommendation,
228 .receive_message = _receive_message,
229 .batch_ending = _batch_ending,
230 .destroy = _destroy,
231 },
232 .imvs = linked_list_create(),
233 .next_imv_id = 1,
234 );
235
236 return &this->public;
237 }