use singular form
[strongswan.git] / src / libcharon / plugins / tnc_imc / tnc_imc.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.h"
17
18 #include <dlfcn.h>
19
20 #include <debug.h>
21 #include <library.h>
22 #include <threading/mutex.h>
23
24 typedef struct private_tnc_imc_t private_tnc_imc_t;
25
26 /**
27 * Private data of an imc_t object.
28 */
29 struct private_tnc_imc_t {
30
31 /**
32 * Public members of imc_t.
33 */
34 imc_t public;
35
36 /**
37 * Path of loaded IMC
38 */
39 char *path;
40
41 /**
42 * Name of loaded IMC
43 */
44 char *name;
45
46 /**
47 * Handle of loaded IMC
48 */
49 void *handle;
50
51 /**
52 * ID of loaded IMC
53 */
54 TNC_IMCID id;
55
56 /**
57 * List of message types supported by IMC
58 */
59 TNC_MessageTypeList supported_types;
60
61 /**
62 * Number of supported message types
63 */
64 TNC_UInt32 type_count;
65
66 /**
67 * mutex to lock the imc_t object
68 */
69 mutex_t *mutex;
70 };
71
72 METHOD(imc_t, set_id, void,
73 private_tnc_imc_t *this, TNC_IMCID id)
74 {
75 this->id = id;
76 }
77
78 METHOD(imc_t, get_id, TNC_IMCID,
79 private_tnc_imc_t *this)
80 {
81 return this->id;
82 }
83
84 METHOD(imc_t, get_name, char*,
85 private_tnc_imc_t *this)
86 {
87 return this->name;
88 }
89
90 METHOD(imc_t, set_message_types, void,
91 private_tnc_imc_t *this, TNC_MessageTypeList supported_types,
92 TNC_UInt32 type_count)
93 {
94 char buf[512];
95 char *pos = buf;
96 int len = sizeof(buf);
97 int written;
98
99 /* lock the imc_t instance */
100 this->mutex->lock(this->mutex);
101
102 /* Free an existing MessageType list */
103 free(this->supported_types);
104 this->supported_types = NULL;
105
106 /* Store the new MessageType list */
107 this->type_count = type_count;
108 if (type_count && supported_types)
109 {
110 size_t size = type_count * sizeof(TNC_MessageType);
111 int i;
112
113 for (i = 0; i < type_count; i++)
114 {
115 written = snprintf(pos, len, " 0x%08x", supported_types[i]);
116 if (written >= len)
117 {
118 break;
119 }
120 pos += written;
121 len -= written;
122 }
123 this->supported_types = malloc(size);
124 memcpy(this->supported_types, supported_types, size);
125 }
126 *pos = '\0';
127 DBG2(DBG_TNC, "IMC %u supports %u message type%s:%s",
128 this->id, type_count, (type_count == 1) ? "":"s", buf);
129
130 /* lock the imc_t instance */
131 this->mutex->unlock(this->mutex);
132 }
133
134 METHOD(imc_t, type_supported, bool,
135 private_tnc_imc_t *this, TNC_MessageType message_type)
136 {
137 TNC_VendorID msg_vid, vid;
138 TNC_MessageSubtype msg_subtype, subtype;
139 int i;
140
141 msg_vid = (message_type >> 8) & TNC_VENDORID_ANY;
142 msg_subtype = message_type & TNC_SUBTYPE_ANY;
143
144 for (i = 0; i < this->type_count; i++)
145 {
146 vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY;
147 subtype = this->supported_types[i] & TNC_SUBTYPE_ANY;
148
149 if (this->supported_types[i] == message_type
150 || (subtype == TNC_SUBTYPE_ANY
151 && (msg_vid == vid || vid == TNC_VENDORID_ANY))
152 || (vid == TNC_VENDORID_ANY
153 && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY)))
154 {
155 return TRUE;
156 }
157 }
158 return FALSE;
159 }
160
161 METHOD(imc_t, destroy, void,
162 private_tnc_imc_t *this)
163 {
164 dlclose(this->handle);
165 this->mutex->destroy(this->mutex);
166 free(this->supported_types);
167 free(this->name);
168 free(this->path);
169 free(this);
170 }
171
172 /**
173 * Described in header.
174 */
175 imc_t* tnc_imc_create(char *name, char *path)
176 {
177 private_tnc_imc_t *this;
178
179 INIT(this,
180 .public = {
181 .set_id = _set_id,
182 .get_id = _get_id,
183 .get_name = _get_name,
184 .set_message_types = _set_message_types,
185 .type_supported = _type_supported,
186 .destroy = _destroy,
187 },
188 .name = name,
189 .path = path,
190 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
191 );
192
193 this->handle = dlopen(path, RTLD_LAZY);
194 if (!this->handle)
195 {
196 DBG1(DBG_TNC, "IMC \"%s\" failed to load: %s", name, dlerror());
197 free(this);
198 return NULL;
199 }
200
201 this->public.initialize = dlsym(this->handle, "TNC_IMC_Initialize");
202 if (!this->public.initialize)
203 {
204 DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
205 path, dlerror());
206 dlclose(this->handle);
207 free(this);
208 return NULL;
209 }
210 this->public.notify_connection_change =
211 dlsym(this->handle, "TNC_IMC_NotifyConnectionChange");
212 this->public.begin_handshake = dlsym(this->handle, "TNC_IMC_BeginHandshake");
213 if (!this->public.begin_handshake)
214 {
215 DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
216 path, dlerror());
217 dlclose(this->handle);
218 free(this);
219 return NULL;
220 }
221 this->public.receive_message =
222 dlsym(this->handle, "TNC_IMC_ReceiveMessage");
223 this->public.batch_ending =
224 dlsym(this->handle, "TNC_IMC_BatchEnding");
225 this->public.terminate =
226 dlsym(this->handle, "TNC_IMC_Terminate");
227 this->public.provide_bind_function =
228 dlsym(this->handle, "TNC_IMC_ProvideBindFunction");
229 if (!this->public.provide_bind_function)
230 {
231 DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
232 path, dlerror());
233 dlclose(this->handle);
234 free(this);
235 return NULL;
236 }
237
238 return &this->public;
239 }