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