added TNC_TNCC_ReportMessageTypesLong() and TNC_TNCS_ReportMessageTypesLong() messages
[strongswan.git] / src / libcharon / plugins / tnc_imv / tnc_imv.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.h"
17
18 #include <dlfcn.h>
19
20 #include <tncif_pa_subtypes.h>
21
22 #include <debug.h>
23 #include <library.h>
24 #include <threading/mutex.h>
25
26 typedef struct private_tnc_imv_t private_tnc_imv_t;
27
28 /**
29 * Private data of an imv_t object.
30 */
31 struct private_tnc_imv_t {
32
33 /**
34 * Public members of imv_t.
35 */
36 imv_t public;
37
38 /**
39 * Path of loaded IMV
40 */
41 char *path;
42
43 /**
44 * Name of loaded IMV
45 */
46 char *name;
47
48 /**
49 * Handle of loaded IMV
50 */
51 void *handle;
52
53 /**
54 * ID of loaded IMV
55 */
56 TNC_IMVID id;
57
58 /**
59 * List of message types supported by IMV - Vendor ID part
60 */
61 TNC_VendorIDList supported_vids;
62
63 /**
64 * List of message types supported by IMV - Subtype part
65 */
66 TNC_MessageSubtypeList supported_subtypes;
67
68 /**
69 * Number of supported message types
70 */
71 TNC_UInt32 type_count;
72
73 /**
74 * mutex to lock the imv_t object
75 */
76 mutex_t *mutex;
77 };
78
79 METHOD(imv_t, set_id, void,
80 private_tnc_imv_t *this, TNC_IMVID id)
81 {
82 this->id = id;
83 }
84
85 METHOD(imv_t, get_id, TNC_IMVID,
86 private_tnc_imv_t *this)
87 {
88 return this->id;
89 }
90
91 METHOD(imv_t, get_name, char*,
92 private_tnc_imv_t *this)
93 {
94 return this->name;
95 }
96
97 METHOD(imv_t, set_message_types, void,
98 private_tnc_imv_t *this, TNC_MessageTypeList supported_types,
99 TNC_UInt32 type_count)
100 {
101 char buf[BUF_LEN];
102 char *pos = buf;
103 int len = sizeof(buf);
104 int i, written;
105 size_t size;
106 TNC_VendorID vid;
107 TNC_MessageSubtype subtype;
108 enum_name_t *pa_subtype_names;
109
110 /* lock the imv_t instance */
111 this->mutex->lock(this->mutex);
112
113 /* Free existing VendorID and MessageSubtype lists */
114 free(this->supported_vids);
115 this->supported_vids = NULL;
116 free(this->supported_subtypes);
117 this->supported_subtypes = NULL;
118
119 /* Store the new MessageType list */
120 this->type_count = type_count;
121 if (type_count && supported_types)
122 {
123 size = type_count * sizeof(TNC_VendorID);
124 this->supported_vids = malloc(size);
125 size = type_count * sizeof(TNC_MessageSubtype);
126 this->supported_subtypes = malloc(size);
127
128 for (i = 0; i < type_count; i++)
129 {
130 vid = (supported_types[i] >> 8) & TNC_VENDORID_ANY;
131 subtype = supported_types[i] & TNC_SUBTYPE_ANY;
132
133 pa_subtype_names = get_pa_subtype_names(vid);
134 if (pa_subtype_names)
135 {
136 written = snprintf(pos, len," '%N/%N' 0x%06x/0x%02x",
137 pen_names, vid, pa_subtype_names, subtype,
138 vid, subtype);
139 }
140 else
141 {
142 written = snprintf(pos, len," '%N' 0x%06x/0x%02x",
143 pen_names, vid, vid, subtype);
144 }
145 if (written >= len)
146 {
147 break;
148 }
149 pos += written;
150 len -= written;
151
152 this->supported_vids[i] = vid;
153 this->supported_subtypes[i] = subtype;
154 }
155 }
156 *pos = '\0';
157 DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s",
158 this->id, type_count, (type_count == 1) ? "":"s", buf);
159
160 /* unlock the imv_t instance */
161 this->mutex->unlock(this->mutex);
162 }
163
164 METHOD(imv_t, set_message_types_long, void,
165 private_tnc_imv_t *this, TNC_VendorIDList supported_vids,
166 TNC_MessageSubtypeList supported_subtypes, TNC_UInt32 type_count)
167 {
168 char buf[BUF_LEN];
169 char *pos = buf;
170 int len = sizeof(buf);
171 int i, written;
172 size_t size;
173 TNC_VendorID vid;
174 TNC_MessageSubtype subtype;
175 enum_name_t *pa_subtype_names;
176
177 /* lock the imv_t instance */
178 this->mutex->lock(this->mutex);
179
180 /* Free existing VendorID and MessageSubtype lists */
181 free(this->supported_vids);
182 this->supported_vids = NULL;
183 free(this->supported_subtypes);
184 this->supported_subtypes = NULL;
185
186 /* Store the new MessageType list */
187 this->type_count = type_count;
188 if (type_count && supported_vids && supported_subtypes)
189 {
190 size = type_count * sizeof(TNC_VendorID);
191 this->supported_vids = malloc(size);
192 memcpy(this->supported_vids, supported_vids, size);
193 size = type_count * sizeof(TNC_MessageSubtype);
194 this->supported_subtypes = malloc(size);
195 memcpy(this->supported_subtypes, supported_subtypes, size);
196
197 for (i = 0; i < type_count; i++)
198 {
199 vid = supported_vids[i];
200 subtype = supported_subtypes[i];
201
202 pa_subtype_names = get_pa_subtype_names(vid);
203 if (pa_subtype_names)
204 {
205 written = snprintf(pos, len," '%N/%N' 0x%06x/0x%08x",
206 pen_names, vid, pa_subtype_names, subtype,
207 vid, subtype);
208 }
209 else
210 {
211 written = snprintf(pos, len," '%N' 0x%06x/0x%08x",
212 pen_names, vid, vid, subtype);
213 }
214 if (written >= len)
215 {
216 break;
217 }
218 pos += written;
219 len -= written;
220 }
221 }
222 *pos = '\0';
223 DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s",
224 this->id, type_count, (type_count == 1) ? "":"s", buf);
225
226 /* unlock the imv_t instance */
227 this->mutex->unlock(this->mutex);
228 }
229
230 METHOD(imv_t, type_supported, bool,
231 private_tnc_imv_t *this, TNC_MessageType message_type)
232 {
233 TNC_VendorID msg_vid, vid;
234 TNC_MessageSubtype msg_subtype, subtype;
235 int i;
236
237 msg_vid = (message_type >> 8) & TNC_VENDORID_ANY;
238 msg_subtype = message_type & TNC_SUBTYPE_ANY;
239
240 for (i = 0; i < this->type_count; i++)
241 {
242 vid = this->supported_vids[i];
243 subtype = this->supported_subtypes[i];
244
245 if ((vid == TNC_VENDORID_ANY && subtype == TNC_SUBTYPE_ANY) ||
246 (vid == msg_vid && (subtype == TNC_SUBTYPE_ANY ||
247 subtype == msg_subtype)))
248 {
249 return TRUE;
250 }
251 }
252 return FALSE;
253 }
254
255 METHOD(imv_t, destroy, void,
256 private_tnc_imv_t *this)
257 {
258 dlclose(this->handle);
259 this->mutex->destroy(this->mutex);
260 free(this->supported_vids);
261 free(this->supported_subtypes);
262 free(this->name);
263 free(this->path);
264 free(this);
265 }
266
267 /**
268 * Described in header.
269 */
270 imv_t* tnc_imv_create(char *name, char *path)
271 {
272 private_tnc_imv_t *this;
273
274 INIT(this,
275 .public = {
276 .set_id = _set_id,
277 .get_id = _get_id,
278 .get_name = _get_name,
279 .set_message_types = _set_message_types,
280 .set_message_types_long = _set_message_types_long,
281 .type_supported = _type_supported,
282 .destroy = _destroy,
283 },
284 .name = name,
285 .path = path,
286 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
287 );
288
289 this->handle = dlopen(path, RTLD_LAZY);
290 if (!this->handle)
291 {
292 DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror());
293 free(this);
294 return NULL;
295 }
296
297 this->public.initialize = dlsym(this->handle, "TNC_IMV_Initialize");
298 if (!this->public.initialize)
299 {
300 DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n",
301 path, dlerror());
302 dlclose(this->handle);
303 free(this);
304 return NULL;
305 }
306 this->public.notify_connection_change =
307 dlsym(this->handle, "TNC_IMV_NotifyConnectionChange");
308 this->public.solicit_recommendation =
309 dlsym(this->handle, "TNC_IMV_SolicitRecommendation");
310 if (!this->public.solicit_recommendation)
311 {
312 DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n",
313 path, dlerror());
314 dlclose(this->handle);
315 free(this);
316 return NULL;
317 }
318 this->public.receive_message =
319 dlsym(this->handle, "TNC_IMV_ReceiveMessage");
320 this->public.batch_ending =
321 dlsym(this->handle, "TNC_IMV_BatchEnding");
322 this->public.terminate =
323 dlsym(this->handle, "TNC_IMV_Terminate");
324 this->public.provide_bind_function =
325 dlsym(this->handle, "TNC_IMV_ProvideBindFunction");
326 if (!this->public.provide_bind_function)
327 {
328 DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n",
329 path, dlerror());
330 dlclose(this->handle);
331 free(this);
332 return NULL;
333 }
334
335 return &this->public;
336 }