use singular form
[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 <debug.h>
21 #include <library.h>
22 #include <threading/mutex.h>
23
24 typedef struct private_tnc_imv_t private_tnc_imv_t;
25
26 /**
27 * Private data of an imv_t object.
28 */
29 struct private_tnc_imv_t {
30
31 /**
32 * Public members of imv_t.
33 */
34 imv_t public;
35
36 /**
37 * Path of loaded IMV
38 */
39 char *path;
40
41 /**
42 * Name of loaded IMV
43 */
44 char *name;
45
46 /**
47 * Handle of loaded IMV
48 */
49 void *handle;
50
51 /**
52 * ID of loaded IMV
53 */
54 TNC_IMVID 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 imv_t object
68 */
69 mutex_t *mutex;
70 };
71
72 METHOD(imv_t, set_id, void,
73 private_tnc_imv_t *this, TNC_IMVID id)
74 {
75 this->id = id;
76 }
77
78 METHOD(imv_t, get_id, TNC_IMVID,
79 private_tnc_imv_t *this)
80 {
81 return this->id;
82 }
83
84 METHOD(imv_t, get_name, char*,
85 private_tnc_imv_t *this)
86 {
87 return this->name;
88 }
89
90 METHOD(imv_t, set_message_types, void,
91 private_tnc_imv_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 imv_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
112 int i;
113
114 for (i = 0; i < type_count; i++)
115 {
116 written = snprintf(pos, len, " 0x%08x", supported_types[i]);
117 if (written >= len)
118 {
119 break;
120 }
121 pos += written;
122 len -= written;
123 }
124 this->supported_types = malloc(size);
125 memcpy(this->supported_types, supported_types, size);
126 }
127 *pos = '\0';
128 DBG2(DBG_TNC, "IMV %u supports %u message type%s:%s",
129 this->id, type_count, (type_count == 1) ? "":"s", buf);
130
131 /* lock the imv_t instance */
132 this->mutex->unlock(this->mutex);
133 }
134
135 METHOD(imv_t, type_supported, bool,
136 private_tnc_imv_t *this, TNC_MessageType message_type)
137 {
138 TNC_VendorID msg_vid, vid;
139 TNC_MessageSubtype msg_subtype, subtype;
140 int i;
141
142 msg_vid = (message_type >> 8) & TNC_VENDORID_ANY;
143 msg_subtype = message_type & TNC_SUBTYPE_ANY;
144
145 for (i = 0; i < this->type_count; i++)
146 {
147 vid = (this->supported_types[i] >> 8) & TNC_VENDORID_ANY;
148 subtype = this->supported_types[i] & TNC_SUBTYPE_ANY;
149
150 if (this->supported_types[i] == message_type
151 || (subtype == TNC_SUBTYPE_ANY
152 && (msg_vid == vid || vid == TNC_VENDORID_ANY))
153 || (vid == TNC_VENDORID_ANY
154 && (msg_subtype == subtype || subtype == TNC_SUBTYPE_ANY)))
155 {
156 return TRUE;
157 }
158 }
159 return FALSE;
160 }
161
162 METHOD(imv_t, destroy, void,
163 private_tnc_imv_t *this)
164 {
165 dlclose(this->handle);
166 this->mutex->destroy(this->mutex);
167 free(this->supported_types);
168 free(this->name);
169 free(this->path);
170 free(this);
171 }
172
173 /**
174 * Described in header.
175 */
176 imv_t* tnc_imv_create(char *name, char *path)
177 {
178 private_tnc_imv_t *this;
179
180 INIT(this,
181 .public = {
182 .set_id = _set_id,
183 .get_id = _get_id,
184 .get_name = _get_name,
185 .set_message_types = _set_message_types,
186 .type_supported = _type_supported,
187 .destroy = _destroy,
188 },
189 .name = name,
190 .path = path,
191 .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
192 );
193
194 this->handle = dlopen(path, RTLD_LAZY);
195 if (!this->handle)
196 {
197 DBG1(DBG_TNC, "IMV \"%s\" failed to load: %s", name, dlerror());
198 free(this);
199 return NULL;
200 }
201
202 this->public.initialize = dlsym(this->handle, "TNC_IMV_Initialize");
203 if (!this->public.initialize)
204 {
205 DBG1(DBG_TNC, "could not resolve TNC_IMV_Initialize in %s: %s\n",
206 path, dlerror());
207 dlclose(this->handle);
208 free(this);
209 return NULL;
210 }
211 this->public.notify_connection_change =
212 dlsym(this->handle, "TNC_IMV_NotifyConnectionChange");
213 this->public.solicit_recommendation =
214 dlsym(this->handle, "TNC_IMV_SolicitRecommendation");
215 if (!this->public.solicit_recommendation)
216 {
217 DBG1(DBG_TNC, "could not resolve TNC_IMV_SolicitRecommendation in %s: %s\n",
218 path, dlerror());
219 dlclose(this->handle);
220 free(this);
221 return NULL;
222 }
223 this->public.receive_message =
224 dlsym(this->handle, "TNC_IMV_ReceiveMessage");
225 this->public.batch_ending =
226 dlsym(this->handle, "TNC_IMV_BatchEnding");
227 this->public.terminate =
228 dlsym(this->handle, "TNC_IMV_Terminate");
229 this->public.provide_bind_function =
230 dlsym(this->handle, "TNC_IMV_ProvideBindFunction");
231 if (!this->public.provide_bind_function)
232 {
233 DBG1(DBG_TNC, "could not resolve TNC_IMV_ProvideBindFunction in %s: %s\n",
234 path, dlerror());
235 dlclose(this->handle);
236 free(this);
237 return NULL;
238 }
239
240 return &this->public;
241 }