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 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 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 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 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 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 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