6e0b4a53a2f2439785c8bf8352106c47d9b9af63
[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
23 typedef struct private_tnc_imc_t private_tnc_imc_t;
24
25 struct private_tnc_imc_t {
26
27 /**
28 * Public members of imc_t.
29 */
30 imc_t public;
31
32 /**
33 * Name of loaded IMC
34 */
35 char *name;
36
37 /**
38 * ID of loaded IMC
39 */
40 TNC_IMCID id;
41 };
42
43 METHOD(imc_t, set_id, void,
44 private_tnc_imc_t *this, TNC_IMCID id)
45 {
46 this->id = id;
47 }
48
49 METHOD(imc_t, get_id, TNC_IMCID,
50 private_tnc_imc_t *this)
51 {
52 return this->id;
53 }
54
55 METHOD(imc_t, get_name, char*,
56 private_tnc_imc_t *this)
57 {
58 return this->name;
59 }
60
61 METHOD(imc_t, destroy, void,
62 private_tnc_imc_t *this)
63 {
64 free(this->name);
65 free(this);
66 }
67
68 /**
69 * Described in header.
70 */
71 imc_t* tnc_imc_create(char* name, char *filename)
72 {
73 private_tnc_imc_t *this;
74 void *handle;
75
76 INIT(this,
77 .public = {
78 .set_id = _set_id,
79 .get_id = _get_id,
80 .get_name = _get_name,
81 .destroy = _destroy,
82 },
83 );
84
85 handle = dlopen(filename, RTLD_NOW);
86 if (handle == NULL)
87 {
88 DBG1(DBG_TNC, "IMC '%s' failed to load from '%s': %s",
89 name, filename, dlerror());
90 free(this);
91 return NULL;
92 }
93
94 /* we do not store or free dlopen() handles, leak_detective requires
95 * the modules to keep loaded until leak report */
96
97 this->public.initialize = dlsym(handle, "TNC_IMC_Initialize");
98 if (!this->public.initialize)
99 {
100 DBG1(DBG_TNC, "could not resolve TNC_IMC_Initialize in %s: %s\n",
101 filename, dlerror());
102 free(this);
103 return NULL;
104 }
105 this->public.notify_connection_change =
106 dlsym(handle, "TNC_IMC_NotifyConnectionChange");
107 this->public.begin_handshake = dlsym(handle, "TNC_IMC_BeginHandshake");
108 if (!this->public.begin_handshake)
109 {
110 DBG1(DBG_TNC, "could not resolve TNC_IMC_BeginHandshake in %s: %s\n",
111 filename, dlerror());
112 free(this);
113 return NULL;
114 }
115 this->public.receive_message =
116 dlsym(handle, "TNC_IMC_ReceiveMessage");
117 this->public.batch_ending =
118 dlsym(handle, "TNC_IMC_BatchEnding");
119 this->public.terminate =
120 dlsym(handle, "TNC_IMC_Terminate");
121 this->public.provide_bind_function =
122 dlsym(handle, "TNC_IMC_ProvideBindFunction");
123 if (!this->public.provide_bind_function)
124 {
125 DBG1(DBG_TNC, "could not resolve TNC_IMC_ProvideBindFunction in %s: %s\n",
126 filename, dlerror());
127 free(this);
128 return NULL;
129 }
130 this->name = strdup(name);
131
132 return &this->public;
133 }
134
135 /**
136 * Called by the IMC to inform a TNCC about the set of message types the IMC
137 * is able to receive
138 */
139 TNC_Result TNC_TNCC_ReportMessageTypes(TNC_IMCID imc_id,
140 TNC_MessageTypeList supported_types,
141 TNC_UInt32 type_count)
142 {
143 DBG2(DBG_TNC,"TNCC_ReportMessageTypes %u %u", imc_id, type_count);
144 return TNC_RESULT_SUCCESS;
145 }
146
147 /**
148 * Called by the IMC to ask a TNCC to retry an Integrity Check Handshake
149 */
150 TNC_Result TNC_TNCC_RequestHandshakeRetry(TNC_IMCID imc_id,
151 TNC_ConnectionID connection_id,
152 TNC_RetryReason reason)
153 {
154 DBG2(DBG_TNC,"TNCC_RequestHandshakeRetry %u %u", imc_id, connection_id);
155 return TNC_RESULT_SUCCESS;
156 }
157
158 /**
159 * Called by the IMC when an IMC-IMV message is to be sent
160 */
161 TNC_Result TNC_TNCC_SendMessage(TNC_IMCID imc_id,
162 TNC_ConnectionID connection_id,
163 TNC_BufferReference message,
164 TNC_UInt32 message_len,
165 TNC_MessageType message_type)
166 {
167 DBG2(DBG_TNC,"TNCC_SendMessage %u %u '%s' %u %0x", imc_id, connection_id,
168 message, message_len, message_type);
169
170 /*
171 -----TNCCS 2.0-----
172 tnc_tncc_connection* conn;
173
174 conn = libtnc_array_index(&connections, connectionID);
175
176 TNC_MessageSubtype message_type = messageType & TNC_SUBTYPE_ANY;
177 TNC_VendorID message_vendor_id = (messageType >> 8) & TNC_VENDORID_ANY;
178
179 chunk_t pa_message = tnc_create_pa_message(FALSE, message_vendor_id,
180 message_type, 0, 0, message, messageLength);
181
182 if(conn->current_batch.len)
183 {
184 chunk_t batch = conn->current_batch;
185 htoun32(batch.ptr + 4,batch.len + pa_message.len);
186 conn->current_batch = chunk_cat("cc", batch, pa_message);
187
188 }
189 else
190 {
191 chunk_t header = tnc_create_batch_header(TNCCS_BATCH_TYPE_CDATA, false);
192
193 htoun32(header.ptr + 4,header.len + pa_message.len);
194 conn->current_batch = chunk_cat("cc", header, pa_message);
195
196 }
197 -----TNCCS 1.1-----
198 libtnc_mutex_lock();
199 conn = libtnc_array_index(&connections, connectionID);
200 libtnc_mutex_unlock();
201 return libtnc_tncc_add_imc_imv_message(conn, message, messageLength, messageType);
202 */
203
204 return TNC_RESULT_SUCCESS;
205 }
206
207 /**
208 * Called by the IMC when it needs a function pointer
209 */
210 TNC_Result TNC_TNCC_BindFunction(TNC_IMCID id,
211 char *function_name,
212 void **function_pointer)
213 {
214 if (streq(function_name, "TNC_TNCC_ReportMessageTypes"))
215 {
216 *function_pointer = (void*)TNC_TNCC_ReportMessageTypes;
217 }
218 else if (streq(function_name, "TNC_TNCC_RequestHandshakeRetry"))
219 {
220 *function_pointer = (void*)TNC_TNCC_RequestHandshakeRetry;
221 }
222 else if (streq(function_name, "TNC_TNCC_SendMessage"))
223 {
224 *function_pointer = (void*)TNC_TNCC_SendMessage;
225 }
226 else
227 {
228 return TNC_RESULT_INVALID_PARAMETER;
229 }
230 return TNC_RESULT_SUCCESS;
231 }