1 /*******************************************************************************
2 * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * - Neither the name of Intel Corp. nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 #include <cerrno>
35 #include "types.h"
36 #include "LMEConnection.h"
37 #include "LMS_if_compat.h"
38 #include "Lock.h"
39 #include "glue.h"
40
41 #ifdef _LINUX
42 #define _strnicmp strncasecmp
43 #endif
44
45 extern glue plugin;
46
47 const GUID LMEConnection::_guidCompat = {0x3d98d9b7, 0x1ce8, 0x4252, {0xb3, 0x37, 0x2e, 0xff, 0x10, 0x6e, 0xf2, 0x9f}};
48
CompatSendMessage(UINT8 connID,UINT32 len,unsigned char * buffer)49 int LMEConnection::CompatSendMessage(UINT8 connID, UINT32 len, unsigned char *buffer)
50 {
51 if (!IsInitialized()) {
52 PRINT("[Compat]State: not connected to HECI.\n");
53 return -1;
54 }
55
56 unsigned char sendBuf[1024 + sizeof(LMS_SEND_DATA_MESSAGE)];
57 LMS_SEND_DATA_MESSAGE *msg;
58
59 if (len > 1024) {
60 return -1;
61 }
62
63 msg = (LMS_SEND_DATA_MESSAGE *)sendBuf;
64 msg->MessageType = LMS_MESSAGE_TYPE_SEND_DATA;
65 msg->ConnectionId = connID;
66 msg->DataLength = htons(len);
67 memcpy(msg->Data, buffer, len);
68
69 return _sendMessage(sendBuf, sizeof(LMS_SEND_DATA_MESSAGE) + len);
70 }
71
CompatCloseConnection(int connID,int status)72 void LMEConnection::CompatCloseConnection(int connID, int status)
73 {
74 if (!IsInitialized()) {
75 PRINT("[Compat]State: not connected to HECI.\n");
76 return;
77 }
78
79 LMS_CLOSE_CONNECTION_MESSAGE msg;
80
81 msg.MessageType = LMS_MESSAGE_TYPE_CLOSE_CONNECTION;
82 msg.ConnectionId = connID;
83 msg.ClosingReason = status;
84
85 _sendMessage((unsigned char *)&msg, sizeof(msg));
86 }
87
CompatProtocolVersion()88 bool LMEConnection::CompatProtocolVersion()
89 {
90 if (!IsInitialized()) {
91 PRINT("[Compat]State: not connected to HECI.\n");
92 return false;
93 }
94
95 LMS_PROTO_VERSION_MESSAGE msg;
96
97 memset(&msg, 0, sizeof(msg));
98 msg.MessageType = LMS_MESSAGE_TYPE_PROTO_VERSION;
99 msg.ConnectionId = 0;
100 msg.Protocol = 0;
101
102 PRINT("[Compat]Sending Protocol Version to LME\n");
103 int bytesWritten = _sendMessage((unsigned char *)&msg, sizeof(msg));
104 return (bytesWritten == sizeof(msg));
105 }
106
CompatRequestIPFQDN()107 bool LMEConnection::CompatRequestIPFQDN()
108 {
109 if (!IsInitialized()) {
110 PRINT("[Compat]State: not connected to HECI.\n");
111 return false;
112 }
113
114 LMS_IP_FQDN_REQUEST_MESSAGE msg;
115
116 memset(&msg, 0, sizeof(msg));
117 msg.MessageType = LMS_MESSAGE_TYPE_IP_FQDN_REQUEST;
118 msg.ConnectionId = 0;
119
120 PRINT("[Compat]Sending IP_FQDN request to LME\n");
121 int bytesWritten = _sendMessage((unsigned char *)&msg, sizeof(msg));
122 return (bytesWritten == sizeof(msg));
123 }
124
CompatOpenConnection(in_port_t mePort,ATAddress addr,unsigned int & connID)125 bool LMEConnection::CompatOpenConnection(in_port_t mePort, ATAddress addr, unsigned int &connID)
126 {
127 if (!IsInitialized()) {
128 PRINT("[Compat]State: not connected to HECI.\n");
129 return false;
130 }
131
132 unsigned char currReqID = _reqID++;
133 bool ret = false;
134 LMS_OPEN_CONNECTION_EX_MESSAGE openConnectionExMsg;
135 LMS_OPEN_CONNECTION_MESSAGE openConnectionMsg;
136 unsigned char *msg = NULL;
137 int msgLen = 0;
138 size_t addrSize = 0;
139 const void *inAddr = addr.inAddr(addrSize);
140
141 if (protocolVer == LMS_PROCOL_VERSION_COMPAT) {
142 memset(&openConnectionExMsg, 0, sizeof(openConnectionExMsg));
143 openConnectionExMsg.MessageType = LMS_MESSAGE_TYPE_OPEN_CONNECTION_EX;
144 openConnectionExMsg.ConnectionId = 0;
145 openConnectionExMsg.Protocol = LMS_PROTOCOL_TYPE_TCP_IPV4;
146 openConnectionExMsg.Flags = 0;
147 openConnectionExMsg.OpenRequestId = currReqID;
148 memcpy(openConnectionExMsg.Host, inAddr, addrSize);
149 openConnectionExMsg.HostPort = htons(addr.inPort());
150 openConnectionExMsg.MEPort = htons(mePort);
151
152 msg = (unsigned char *)&openConnectionExMsg;
153 msgLen = sizeof(openConnectionExMsg);
154 PRINT("[Compat]OpenConnectionEx %x (%d) p=%d mp=%d\n",
155 *(int *)inAddr, addrSize, addr.inPort(), mePort);
156 }
157 else {
158 memset(&openConnectionMsg, 0, sizeof(openConnectionMsg));
159 openConnectionMsg.MessageType = LMS_MESSAGE_TYPE_OPEN_CONNECTION;
160 openConnectionMsg.ConnectionId = 0;
161 openConnectionMsg.Protocol = LMS_PROTOCOL_TYPE_TCP_IPV4;
162 openConnectionMsg.OpenRequestId = currReqID;
163 memcpy(openConnectionMsg.HostIPAddress, inAddr, addrSize);
164 openConnectionMsg.HostPort = htons(addr.inPort());
165 openConnectionMsg.MEPort = htons(mePort);
166
167 msg = (unsigned char *)&openConnectionMsg;
168 msgLen = sizeof(openConnectionMsg);
169 PRINT("[Compat]OpenConnection %x (%d) p=%d mp=%d\n",
170 *(int *)inAddr, addrSize, addr.inPort(), mePort);
171 }
172
173 // save as pending request
174 CompatConnection conn;
175 conn.event = new Event();
176 conn.status = LMS_CONNECTION_STATUS_FAILED;
177 conn.connID = 0;
178
179 _compatMapLock.acquire();
180 _compatPendingConnections[currReqID] = conn;
181 _compatMapLock.release();
182
183 int bytesWritten;
184 bytesWritten = _sendMessage(msg, msgLen);
185 if (bytesWritten != msgLen) {
186 goto out;
187 }
188
189 if (conn.event->wait(10000) == false) {
190 // no response from FW
191 goto out;
192 }
193
194 ret = true;
195
196 out:
197 {
198 Lock ml(_compatMapLock);
199
200 if (_compatPendingConnections[currReqID].status != LMS_CONNECTION_STATUS_OK) {
201 ret = false;
202 } else {
203 connID = _compatPendingConnections[currReqID].connID;
204 }
205 _compatPendingConnections.erase(currReqID);
206 }
207
208 delete conn.event;
209 conn.event = NULL;
210
211 return ret;
212 }
213
_doRXCompat()214 void LMEConnection::_doRXCompat()
215 {
216 unsigned int bytesRead;
217 int status = 1;
218
219 _threadStartedEvent.set();
220
221 unsigned char *rxBuffer = new unsigned char[_heciCompat.GetBufferSize()];
222
223 while (true) {
224 bytesRead = (unsigned int)_receiveMessage(rxBuffer, _heciCompat.GetBufferSize());
225
226 if ((int)bytesRead < 0) {
227 PRINT("[Compat]Error receiving data from HECI\n");
228 Deinit();
229 break;
230 }
231
232 if (bytesRead == 0) {
233 // ERROR
234 continue;
235 }
236
237 PRINT("[Compat]Received from LME %d bytes (msg type %02d)\n", bytesRead, rxBuffer[0]);
238
239 if (bytesRead < 2) {
240 // ERROR
241 continue;
242 }
243
244 if (plugin.preprocess(rxBuffer, bytesRead) == LMS_DROPPED) {
245 continue;
246 }
247
248 switch (rxBuffer[0]) {
249 case LMS_MESSAGE_TYPE_PROTO_VERSION_REPLY:
250 CompatRequestIPFQDN();
251 break;
252
253 case LMS_MESSAGE_TYPE_CLOSE_CONNECTION:
254 case LMS_MESSAGE_TYPE_SEND_DATA:
255 case LMS_MESSAGE_TYPE_IP_FQDN:
256 _cb(_cbParam, rxBuffer, bytesRead, &status);
257 break;
258
259 case LMS_MESSAGE_TYPE_OPEN_CONNECTION_REPLY:
260 {
261 LMS_OPEN_CONNECTION_REPLY_MESSAGE *repMsg =
262 (LMS_OPEN_CONNECTION_REPLY_MESSAGE *)rxBuffer;
263
264 Lock ml(_compatMapLock);
265
266 CompatConnMap::iterator itr;
267 itr = _compatPendingConnections.find(repMsg->OpenRequestId);
268 if (itr != _compatPendingConnections.end()) {
269 (*itr).second.connID = repMsg->ConnectionId;
270 (*itr).second.status = repMsg->Status;
271 (*itr).second.event->set();
272 PRINT("[Compat]Open connection reply %d %d =%d\n", repMsg->OpenRequestId, repMsg->ConnectionId, repMsg->Status);
273 }
274 }
275 break;
276
277 case LMS_MESSAGE_TYPE_OPEN_CONNECTION_EX:
278 {
279 // report incoming connection request
280 _cb(_cbParam, rxBuffer, bytesRead, &status);
281
282 if (IsInitialized() && (status == 1)) {
283 if (plugin.retry(rxBuffer, bytesRead) == LMS_DROPPED) {
284 continue;
285 } else {
286 _cb(_cbParam, rxBuffer, bytesRead, &status);
287 }
288 }
289
290 LMS_OPEN_CONNECTION_EX_MESSAGE *msg =
291 (LMS_OPEN_CONNECTION_EX_MESSAGE *)rxBuffer;
292
293 if ((msg->Flags & HOSTNAME_BIT) != 0) {
294 PRINT("[Compat]Got client connection request %d for host %s, port %d\n",
295 msg->ConnectionId, msg->Host, ntohs(msg->HostPort));
296 }
297 else {
298 PRINT("[Compat]Got client connection request %d for IP %s, port %d\n",
299 msg->ConnectionId, inet_ntoa(*((struct in_addr *)msg->Host)), ntohs(msg->HostPort));
300 }
301
302 LMS_OPEN_CONNECTION_REPLY_MESSAGE repMsg;
303 memset(&repMsg, 0, sizeof(repMsg));
304
305 repMsg.MessageType = LMS_MESSAGE_TYPE_OPEN_CONNECTION_REPLY;
306 repMsg.ConnectionId = msg->ConnectionId;
307 if (status == 0) {
308 repMsg.Status = LMS_CONNECTION_STATUS_OK;
309 } else {
310 repMsg.Status = LMS_CONNECTION_STATUS_FAILED;
311 }
312
313 DWORD bytesWritten;
314 bytesWritten = _sendMessage((unsigned char *)&repMsg, sizeof(repMsg));
315 if (bytesWritten != sizeof(repMsg)) {
316 PRINT("[Compat]Send Open Connection Reply failed: bytesWritten: %lu\n", bytesWritten);
317 }
318 }
319 break;
320
321 default:
322 // Uknown request. Ignore
323 break;
324 }
325
326 if (IsInitialized()) {
327 plugin.postprocess(rxBuffer, bytesRead, status);
328 }
329 }
330
331 if (rxBuffer != NULL) {
332 delete[] rxBuffer;
333 }
334 }
335
336