2 * Copyright (C) 2006 Mike McCauley
3 * Copyright (C) 2010-2011 Andreas Steffen,
4 * HSR Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 #include <tncif_pa_subtypes.h>
23 #include <utils/debug.h>
26 #include <collections/linked_list.h>
27 #include <threading/mutex.h>
29 typedef struct private_tnc_imc_t private_tnc_imc_t
;
32 * Private data of an imc_t object.
34 struct private_tnc_imc_t
{
37 * Public members of imc_t.
47 * Handle of loaded IMC
57 * list of additional IMC IDs
59 linked_list_t
*additional_ids
;
62 * List of message types supported by IMC - Vendor ID part
64 TNC_VendorIDList supported_vids
;
67 * List of message types supported by IMC - Subtype part
69 TNC_MessageSubtypeList supported_subtypes
;
72 * Number of supported message types
74 TNC_UInt32 type_count
;
77 * mutex to lock the imc_t object
82 METHOD(imc_t
, set_id
, void,
83 private_tnc_imc_t
*this, TNC_IMCID id
)
88 METHOD(imc_t
, get_id
, TNC_IMCID
,
89 private_tnc_imc_t
*this)
94 METHOD(imc_t
, add_id
, void,
95 private_tnc_imc_t
*this, TNC_IMCID id
)
99 /* store the scalar value in the pointer */
101 this->additional_ids
->insert_last(this->additional_ids
, pointer
);
104 METHOD(imc_t
, has_id
, bool,
105 private_tnc_imc_t
*this, TNC_IMCID id
)
107 enumerator_t
*enumerator
;
108 TNC_IMCID additional_id
;
112 /* check primary IMC ID */
118 /* return if there are no additional IMC IDs */
119 if (this->additional_ids
->get_count(this->additional_ids
) == 0)
124 /* check additional IMC IDs */
125 enumerator
= this->additional_ids
->create_enumerator(this->additional_ids
);
126 while (enumerator
->enumerate(enumerator
, &pointer
))
128 /* interpret pointer as scalar value */
129 additional_id
= (TNC_UInt32
)pointer
;
131 if (id
== additional_id
)
137 enumerator
->destroy(enumerator
);
142 METHOD(imc_t
, get_name
, char*,
143 private_tnc_imc_t
*this)
148 METHOD(imc_t
, set_message_types
, void,
149 private_tnc_imc_t
*this, TNC_MessageTypeList supported_types
,
150 TNC_UInt32 type_count
)
154 int len
= sizeof(buf
);
158 TNC_MessageSubtype subtype
;
159 enum_name_t
*pa_subtype_names
;
161 /* lock the imc_t instance */
162 this->mutex
->lock(this->mutex
);
164 /* Free existing VendorID and MessageSubtype lists */
165 free(this->supported_vids
);
166 this->supported_vids
= NULL
;
167 free(this->supported_subtypes
);
168 this->supported_subtypes
= NULL
;
170 /* Store the new MessageType list */
171 this->type_count
= type_count
;
172 if (type_count
&& supported_types
)
174 size
= type_count
* sizeof(TNC_VendorID
);
175 this->supported_vids
= malloc(size
);
176 size
= type_count
* sizeof(TNC_MessageSubtype
);
177 this->supported_subtypes
= malloc(size
);
179 for (i
= 0; i
< type_count
; i
++)
181 vid
= (supported_types
[i
] >> 8) & TNC_VENDORID_ANY
;
182 subtype
= supported_types
[i
] & TNC_SUBTYPE_ANY
;
184 pa_subtype_names
= get_pa_subtype_names(vid
);
185 if (pa_subtype_names
)
187 written
= snprintf(pos
, len
," '%N/%N' 0x%06x/0x%02x",
188 pen_names
, vid
, pa_subtype_names
, subtype
,
193 written
= snprintf(pos
, len
," '%N' 0x%06x/0x%02x",
194 pen_names
, vid
, vid
, subtype
);
203 this->supported_vids
[i
] = vid
;
204 this->supported_subtypes
[i
] = subtype
;
208 DBG2(DBG_TNC
, "IMC %u supports %u message type%s:%s",
209 this->id
, type_count
, (type_count
== 1) ?
"":"s", buf
);
211 /* unlock the imc_t instance */
212 this->mutex
->unlock(this->mutex
);
215 METHOD(imc_t
, set_message_types_long
, void,
216 private_tnc_imc_t
*this, TNC_VendorIDList supported_vids
,
217 TNC_MessageSubtypeList supported_subtypes
, TNC_UInt32 type_count
)
221 int len
= sizeof(buf
);
225 TNC_MessageSubtype subtype
;
226 enum_name_t
*pa_subtype_names
;
228 /* lock the imc_t instance */
229 this->mutex
->lock(this->mutex
);
231 /* Free existing VendorID and MessageSubtype lists */
232 free(this->supported_vids
);
233 this->supported_vids
= NULL
;
234 free(this->supported_subtypes
);
235 this->supported_subtypes
= NULL
;
237 /* Store the new MessageType list */
238 this->type_count
= type_count
;
239 if (type_count
&& supported_vids
&& supported_subtypes
)
241 size
= type_count
* sizeof(TNC_VendorID
);
242 this->supported_vids
= malloc(size
);
243 memcpy(this->supported_vids
, supported_vids
, size
);
244 size
= type_count
* sizeof(TNC_MessageSubtype
);
245 this->supported_subtypes
= malloc(size
);
246 memcpy(this->supported_subtypes
, supported_subtypes
, size
);
248 for (i
= 0; i
< type_count
; i
++)
250 vid
= supported_vids
[i
];
251 subtype
= supported_subtypes
[i
];
253 pa_subtype_names
= get_pa_subtype_names(vid
);
254 if (pa_subtype_names
)
256 written
= snprintf(pos
, len
," '%N/%N' 0x%06x/0x%08x",
257 pen_names
, vid
, pa_subtype_names
, subtype
,
262 written
= snprintf(pos
, len
," '%N' 0x%06x/0x%08x",
263 pen_names
, vid
, vid
, subtype
);
274 DBG2(DBG_TNC
, "IMC %u supports %u message type%s:%s",
275 this->id
, type_count
, (type_count
== 1) ?
"":"s", buf
);
277 /* unlock the imc_t instance */
278 this->mutex
->unlock(this->mutex
);
281 METHOD(imc_t
, type_supported
, bool,
282 private_tnc_imc_t
*this, TNC_VendorID msg_vid
, TNC_MessageSubtype msg_subtype
)
285 TNC_MessageSubtype subtype
;
288 for (i
= 0; i
< this->type_count
; i
++)
290 vid
= this->supported_vids
[i
];
291 subtype
= this->supported_subtypes
[i
];
293 if ((vid
== TNC_VENDORID_ANY
&& subtype
== TNC_SUBTYPE_ANY
) ||
294 (vid
== msg_vid
&& (subtype
== TNC_SUBTYPE_ANY
||
295 subtype
== msg_subtype
)))
303 METHOD(imc_t
, destroy
, void,
304 private_tnc_imc_t
*this)
306 if (this->handle
&& lib
->settings
->get_bool(lib
->settings
,
307 "%s.plugins.tnc-imc.dlclose", TRUE
, charon
->name
))
309 dlclose(this->handle
);
311 this->mutex
->destroy(this->mutex
);
312 this->additional_ids
->destroy(this->additional_ids
);
313 free(this->supported_vids
);
314 free(this->supported_subtypes
);
320 * Generic constructor
322 static private_tnc_imc_t
* tnc_imc_create_empty(char *name
)
324 private_tnc_imc_t
*this;
332 .get_name
= _get_name
,
333 .set_message_types
= _set_message_types
,
334 .set_message_types_long
= _set_message_types_long
,
335 .type_supported
= _type_supported
,
338 .name
= strdup(name
),
339 .additional_ids
= linked_list_create(),
340 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
349 imc_t
* tnc_imc_create(char *name
, char *path
)
351 private_tnc_imc_t
*this;
353 this = tnc_imc_create_empty(name
);
355 this->handle
= dlopen(path
, RTLD_LAZY
);
358 DBG1(DBG_TNC
, "IMC \"%s\" failed to load: %s", name
, dlerror());
363 this->public.initialize
= dlsym(this->handle
, "TNC_IMC_Initialize");
364 if (!this->public.initialize
)
366 DBG1(DBG_TNC
, "could not resolve TNC_IMC_Initialize in %s: %s\n",
371 this->public.notify_connection_change
=
372 dlsym(this->handle
, "TNC_IMC_NotifyConnectionChange");
373 this->public.begin_handshake
= dlsym(this->handle
, "TNC_IMC_BeginHandshake");
374 if (!this->public.begin_handshake
)
376 DBG1(DBG_TNC
, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
381 this->public.receive_message
=
382 dlsym(this->handle
, "TNC_IMC_ReceiveMessage");
383 this->public.receive_message_long
=
384 dlsym(this->handle
, "TNC_IMC_ReceiveMessageLong");
385 this->public.batch_ending
=
386 dlsym(this->handle
, "TNC_IMC_BatchEnding");
387 this->public.terminate
=
388 dlsym(this->handle
, "TNC_IMC_Terminate");
389 this->public.provide_bind_function
=
390 dlsym(this->handle
, "TNC_IMC_ProvideBindFunction");
391 if (!this->public.provide_bind_function
)
393 DBG1(DBG_TNC
, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
399 return &this->public;
405 imc_t
* tnc_imc_create_from_functions(char *name
,
406 TNC_IMC_InitializePointer initialize
,
407 TNC_IMC_NotifyConnectionChangePointer notify_connection_change
,
408 TNC_IMC_BeginHandshakePointer begin_handshake
,
409 TNC_IMC_ReceiveMessagePointer receive_message
,
410 TNC_IMC_ReceiveMessageLongPointer receive_message_long
,
411 TNC_IMC_BatchEndingPointer batch_ending
,
412 TNC_IMC_TerminatePointer terminate
,
413 TNC_IMC_ProvideBindFunctionPointer provide_bind_function
)
415 private_tnc_imc_t
*this;
417 this = tnc_imc_create_empty(name
);
419 this->public.initialize
= initialize
;
420 this->public.notify_connection_change
= notify_connection_change
;
421 this->public.begin_handshake
= begin_handshake
;
422 this->public.receive_message
= receive_message
;
423 this->public.receive_message_long
= receive_message_long
;
424 this->public.batch_ending
= batch_ending
;
425 this->public.terminate
= terminate
;
426 this->public.provide_bind_function
= provide_bind_function
;
428 return &this->public;