f664e142a7c75d5689cf44ce50f60f993036c192
[strongswan.git] / src / libimcv / plugins / imv_test / imv_test_state.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include "imv_test_state.h"
16
17 #include <utils/lexparser.h>
18 #include <utils/linked_list.h>
19 #include <debug.h>
20
21 typedef struct private_imv_test_state_t private_imv_test_state_t;
22
23 /**
24 * Private data of an imv_test_state_t object.
25 */
26 struct private_imv_test_state_t {
27
28 /**
29 * Public members of imv_test_state_t
30 */
31 imv_test_state_t public;
32
33 /**
34 * TNCCS connection ID
35 */
36 TNC_ConnectionID connection_id;
37
38 /**
39 * TNCCS connection state
40 */
41 TNC_ConnectionState state;
42
43 /**
44 * Does the TNCCS connection support long message types?
45 */
46 bool has_long;
47
48 /**
49 * Does the TNCCS connection support exclusive delivery?
50 */
51 bool has_excl;
52
53 /**
54 * Maximum PA-TNC message size for this TNCCS connection
55 */
56 u_int32_t max_msg_len;
57
58 /**
59 * IMV action recommendation
60 */
61 TNC_IMV_Action_Recommendation rec;
62
63 /**
64 * IMV evaluation result
65 */
66 TNC_IMV_Evaluation_Result eval;
67
68 /**
69 * List of IMCs
70 */
71 linked_list_t *imcs;
72
73 };
74
75 typedef struct imc_entry_t imc_entry_t;
76
77 /**
78 * Define an internal IMC entry
79 */
80 struct imc_entry_t {
81 TNC_UInt32 imc_id;
82 int rounds;
83 };
84
85 typedef struct entry_t entry_t;
86
87 /**
88 * Define an internal reason string entry
89 */
90 struct entry_t {
91 char *lang;
92 char *string;
93 };
94
95 /**
96 * Table of multi-lingual reason string entries
97 */
98 static entry_t reasons[] = {
99 { "en", "IMC Test was not configured with \"command = allow\"" },
100 { "de", "IMC Test wurde nicht mit \"command = allow\" konfiguriert" },
101 { "fr", "IMC Test n'etait pas configuré avec \"command = allow\"" },
102 { "pl", "IMC Test nie zostało skonfigurowany z \"command = allow\"" }
103 };
104
105 METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
106 private_imv_test_state_t *this)
107 {
108 return this->connection_id;
109 }
110
111 METHOD(imv_state_t, has_long, bool,
112 private_imv_test_state_t *this)
113 {
114 return this->has_long;
115 }
116
117 METHOD(imv_state_t, has_excl, bool,
118 private_imv_test_state_t *this)
119 {
120 return this->has_excl;
121 }
122
123 METHOD(imv_state_t, set_flags, void,
124 private_imv_test_state_t *this, bool has_long, bool has_excl)
125 {
126 this->has_long = has_long;
127 this->has_excl = has_excl;
128 }
129
130 METHOD(imv_state_t, set_max_msg_len, void,
131 private_imv_test_state_t *this, u_int32_t max_msg_len)
132 {
133 this->max_msg_len = max_msg_len;
134 }
135
136 METHOD(imv_state_t, get_max_msg_len, u_int32_t,
137 private_imv_test_state_t *this)
138 {
139 return this->max_msg_len;
140 }
141
142 METHOD(imv_state_t, change_state, void,
143 private_imv_test_state_t *this, TNC_ConnectionState new_state)
144 {
145 this->state = new_state;
146 }
147
148 METHOD(imv_state_t, get_recommendation, void,
149 private_imv_test_state_t *this, TNC_IMV_Action_Recommendation *rec,
150 TNC_IMV_Evaluation_Result *eval)
151 {
152 *rec = this->rec;
153 *eval = this->eval;
154 }
155
156 METHOD(imv_state_t, set_recommendation, void,
157 private_imv_test_state_t *this, TNC_IMV_Action_Recommendation rec,
158 TNC_IMV_Evaluation_Result eval)
159 {
160 this->rec = rec;
161 this->eval = eval;
162 }
163
164 METHOD(imv_state_t, get_reason_string, bool,
165 private_imv_test_state_t *this, chunk_t preferred_language,
166 chunk_t *reason_string, chunk_t *reason_language)
167 {
168 chunk_t pref_lang, lang;
169 u_char *pos;
170 int i;
171
172 while (eat_whitespace(&preferred_language))
173 {
174 if (!extract_token(&pref_lang, ',', &preferred_language))
175 {
176 /* last entry in a comma-separated list or single entry */
177 pref_lang = preferred_language;
178 }
179
180 /* eat trailing whitespace */
181 pos = pref_lang.ptr + pref_lang.len - 1;
182 while (pref_lang.len && *pos-- == ' ')
183 {
184 pref_lang.len--;
185 }
186
187 for (i = 0 ; i < countof(reasons); i++)
188 {
189 lang = chunk_create(reasons[i].lang, strlen(reasons[i].lang));
190 if (chunk_equals(lang, pref_lang))
191 {
192 *reason_language = lang;
193 *reason_string = chunk_create(reasons[i].string,
194 strlen(reasons[i].string));
195 return TRUE;
196 }
197 }
198 }
199
200 /* no preferred language match found - use the default language */
201 *reason_string = chunk_create(reasons[0].string,
202 strlen(reasons[0].string));
203 *reason_language = chunk_create(reasons[0].lang,
204 strlen(reasons[0].lang));
205 return TRUE;
206 }
207
208 METHOD(imv_state_t, destroy, void,
209 private_imv_test_state_t *this)
210 {
211 this->imcs->destroy_function(this->imcs, free);
212 free(this);
213 }
214
215 METHOD(imv_test_state_t, add_imc, void,
216 private_imv_test_state_t *this, TNC_UInt32 imc_id, int rounds)
217 {
218 enumerator_t *enumerator;
219 imc_entry_t *imc_entry;
220 bool found = FALSE;
221
222 enumerator = this->imcs->create_enumerator(this->imcs);
223 while (enumerator->enumerate(enumerator, &imc_entry))
224 {
225 if (imc_entry->imc_id == imc_id)
226 {
227 found = TRUE;
228 break;
229 }
230 }
231 enumerator->destroy(enumerator);
232
233 if (!found)
234 {
235 imc_entry = malloc_thing(imc_entry_t);
236 imc_entry->imc_id = imc_id;
237 imc_entry->rounds = rounds;
238 this->imcs->insert_last(this->imcs, imc_entry);
239 }
240 }
241
242 METHOD(imv_test_state_t, set_rounds, void,
243 private_imv_test_state_t *this, int rounds)
244 {
245 enumerator_t *enumerator;
246 imc_entry_t *imc_entry;
247
248 enumerator = this->imcs->create_enumerator(this->imcs);
249 while (enumerator->enumerate(enumerator, &imc_entry))
250 {
251 imc_entry->rounds = rounds;
252 }
253 enumerator->destroy(enumerator);
254 }
255
256 METHOD(imv_test_state_t, another_round, bool,
257 private_imv_test_state_t *this, TNC_UInt32 imc_id)
258 {
259 enumerator_t *enumerator;
260 imc_entry_t *imc_entry;
261 bool not_finished = FALSE;
262
263 enumerator = this->imcs->create_enumerator(this->imcs);
264 while (enumerator->enumerate(enumerator, &imc_entry))
265 {
266 if (imc_entry->rounds > 0)
267 {
268 not_finished = TRUE;
269 }
270 if (imc_entry->imc_id == imc_id)
271 {
272 imc_entry->rounds--;
273 }
274 }
275 enumerator->destroy(enumerator);
276
277 return not_finished;
278 }
279
280 /**
281 * Described in header.
282 */
283 imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id)
284 {
285 private_imv_test_state_t *this;
286
287 INIT(this,
288 .public = {
289 .interface = {
290 .get_connection_id = _get_connection_id,
291 .has_long = _has_long,
292 .has_excl = _has_excl,
293 .set_flags = _set_flags,
294 .set_max_msg_len = _set_max_msg_len,
295 .get_max_msg_len = _get_max_msg_len,
296 .change_state = _change_state,
297 .get_recommendation = _get_recommendation,
298 .set_recommendation = _set_recommendation,
299 .get_reason_string = _get_reason_string,
300 .destroy = _destroy,
301 },
302 .add_imc = _add_imc,
303 .set_rounds = _set_rounds,
304 .another_round = _another_round,
305 },
306 .state = TNC_CONNECTION_STATE_CREATE,
307 .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
308 .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
309 .connection_id = connection_id,
310 .imcs = linked_list_create(),
311 );
312
313 return &this->public.interface;
314 }
315
316