1*617e2443SMark Logan /*******************************************************************************
2*617e2443SMark Logan * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3*617e2443SMark Logan *
4*617e2443SMark Logan * Redistribution and use in source and binary forms, with or without
5*617e2443SMark Logan * modification, are permitted provided that the following conditions are met:
6*617e2443SMark Logan *
7*617e2443SMark Logan * - Redistributions of source code must retain the above copyright notice,
8*617e2443SMark Logan * this list of conditions and the following disclaimer.
9*617e2443SMark Logan *
10*617e2443SMark Logan * - Redistributions in binary form must reproduce the above copyright notice,
11*617e2443SMark Logan * this list of conditions and the following disclaimer in the documentation
12*617e2443SMark Logan * and/or other materials provided with the distribution.
13*617e2443SMark Logan *
14*617e2443SMark Logan * - Neither the name of Intel Corp. nor the names of its
15*617e2443SMark Logan * contributors may be used to endorse or promote products derived from this
16*617e2443SMark Logan * software without specific prior written permission.
17*617e2443SMark Logan *
18*617e2443SMark Logan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19*617e2443SMark Logan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*617e2443SMark Logan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*617e2443SMark Logan * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22*617e2443SMark Logan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*617e2443SMark Logan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*617e2443SMark Logan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*617e2443SMark Logan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*617e2443SMark Logan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*617e2443SMark Logan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*617e2443SMark Logan * POSSIBILITY OF SUCH DAMAGE.
29*617e2443SMark Logan *******************************************************************************/
30*617e2443SMark Logan
31*617e2443SMark Logan #ifdef HAVE_CONFIG_H
32*617e2443SMark Logan #include "config.h"
33*617e2443SMark Logan #endif
34*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
35*617e2443SMark Logan #include <cerrno>
36*617e2443SMark Logan #include <sys/socket.h>
37*617e2443SMark Logan #include <arpa/inet.h>
38*617e2443SMark Logan #include <netinet/in.h>
39*617e2443SMark Logan #include <net/if.h>
40*617e2443SMark Logan #include <sys/ioctl.h>
41*617e2443SMark Logan #include <unistd.h>
42*617e2443SMark Logan #include <fcntl.h>
43*617e2443SMark Logan #include <netdb.h>
44*617e2443SMark Logan #include <syslog.h>
45*617e2443SMark Logan
46*617e2443SMark Logan #define _stprintf_s snprintf
47*617e2443SMark Logan #define strnicmp strncasecmp
48*617e2443SMark Logan #else
49*617e2443SMark Logan
50*617e2443SMark Logan #include <winsock2.h>
51*617e2443SMark Logan #include <iphlpapi.h>
52*617e2443SMark Logan #include <Ws2tcpip.h>
53*617e2443SMark Logan #include <tchar.h>
54*617e2443SMark Logan
55*617e2443SMark Logan #endif // __sun || _LINUX
56*617e2443SMark Logan
57*617e2443SMark Logan #include <fstream>
58*617e2443SMark Logan #include <algorithm>
59*617e2443SMark Logan #include "Protocol.h"
60*617e2443SMark Logan #include "LMS_if.h"
61*617e2443SMark Logan #include "LMS_if_compat.h"
62*617e2443SMark Logan #include "Lock.h"
63*617e2443SMark Logan #include "ATNetworkTool.h"
64*617e2443SMark Logan
65*617e2443SMark Logan const LMEProtocolVersionMessage Protocol::MIN_PROT_VERSION(1, 0);
66*617e2443SMark Logan const LMEProtocolVersionMessage Protocol::MAX_PROT_VERSION(1, 0);
67*617e2443SMark Logan
Protocol()68*617e2443SMark Logan Protocol::Protocol() :
69*617e2443SMark Logan #if DEBUGLOG
70*617e2443SMark Logan _lme(true),
71*617e2443SMark Logan #else
72*617e2443SMark Logan _lme(false),
73*617e2443SMark Logan #endif
74*617e2443SMark Logan _rxSocketBuffer(NULL),
75*617e2443SMark Logan _rxSocketBufferSize(0)
76*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
77*617e2443SMark Logan , _cfg(true)
78*617e2443SMark Logan #endif
79*617e2443SMark Logan {
80*617e2443SMark Logan _serverSignalSocket = INVALID_SOCKET;
81*617e2443SMark Logan _clientSignalSocket = INVALID_SOCKET;
82*617e2443SMark Logan _sockets_active = false;
83*617e2443SMark Logan _handshakingStatus = NOT_INITIATED;
84*617e2443SMark Logan _pfwdService = NOT_STARTED;
85*617e2443SMark Logan _AmtProtVersion.MajorVersion = 0;
86*617e2443SMark Logan _AmtProtVersion.MinorVersion = 0;
87*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
88*617e2443SMark Logan _remoteAccessEnabled = false;
89*617e2443SMark Logan #endif
90*617e2443SMark Logan memset(_AMTFQDN, 0, sizeof(_AMTFQDN));
91*617e2443SMark Logan oldProtocolMode = false;
92*617e2443SMark Logan _deinitReq = false;
93*617e2443SMark Logan _listenFailReported.clear();
94*617e2443SMark Logan }
95*617e2443SMark Logan
~Protocol()96*617e2443SMark Logan Protocol::~Protocol()
97*617e2443SMark Logan {
98*617e2443SMark Logan if (!oldProtocolMode) {
99*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_BY_APPLICATION);
100*617e2443SMark Logan }
101*617e2443SMark Logan DeinitFull();
102*617e2443SMark Logan DestroySockets();
103*617e2443SMark Logan _listenFailReported.clear();
104*617e2443SMark Logan }
105*617e2443SMark Logan
Init(EventLogCallback cb,void * param)106*617e2443SMark Logan bool Protocol::Init(EventLogCallback cb, void *param)
107*617e2443SMark Logan {
108*617e2443SMark Logan _eventLog = cb;
109*617e2443SMark Logan _eventLogParam = param;
110*617e2443SMark Logan
111*617e2443SMark Logan DeinitFull();
112*617e2443SMark Logan
113*617e2443SMark Logan {
114*617e2443SMark Logan Lock dl(_deinitLock);
115*617e2443SMark Logan _deinitReq = false;
116*617e2443SMark Logan }
117*617e2443SMark Logan
118*617e2443SMark Logan if (!_lme.Init(_LmeCallback, this)) {
119*617e2443SMark Logan return false;
120*617e2443SMark Logan }
121*617e2443SMark Logan
122*617e2443SMark Logan oldProtocolMode = (LMS_PROCOL_VERSION != _lme.protocolVer);
123*617e2443SMark Logan
124*617e2443SMark Logan {
125*617e2443SMark Logan Lock l(_versionLock);
126*617e2443SMark Logan
127*617e2443SMark Logan if (_handshakingStatus == NOT_INITIATED) {
128*617e2443SMark Logan if (oldProtocolMode) {
129*617e2443SMark Logan _lme.CompatProtocolVersion();
130*617e2443SMark Logan } else {
131*617e2443SMark Logan _lme.ProtocolVersion(MAX_PROT_VERSION);
132*617e2443SMark Logan }
133*617e2443SMark Logan _handshakingStatus = INITIATED;
134*617e2443SMark Logan }
135*617e2443SMark Logan }
136*617e2443SMark Logan
137*617e2443SMark Logan if (!oldProtocolMode) {
138*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
139*617e2443SMark Logan if (!_cfg.Init(true)) {
140*617e2443SMark Logan #else
141*617e2443SMark Logan if (!_cfg.IsAMTEnabled(false)) {
142*617e2443SMark Logan #endif
143*617e2443SMark Logan _lme.Deinit();
144*617e2443SMark Logan return false;
145*617e2443SMark Logan }
146*617e2443SMark Logan }
147*617e2443SMark Logan
148*617e2443SMark Logan long bufSize = _lme.GetHeciBufferSize() - sizeof(APF_CHANNEL_DATA_MESSAGE);
149*617e2443SMark Logan if (bufSize > 0) {
150*617e2443SMark Logan _rxSocketBuffer = new char[bufSize];
151*617e2443SMark Logan _rxSocketBufferSize = bufSize;
152*617e2443SMark Logan } else {
153*617e2443SMark Logan DeinitFull();
154*617e2443SMark Logan return false;
155*617e2443SMark Logan }
156*617e2443SMark Logan
157*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
158*617e2443SMark Logan if (!oldProtocolMode) {
159*617e2443SMark Logan _checkRemoteSupport(true);
160*617e2443SMark Logan }
161*617e2443SMark Logan #endif
162*617e2443SMark Logan return true;
163*617e2443SMark Logan }
164*617e2443SMark Logan
165*617e2443SMark Logan Channel *Protocol::_getSockOpenChannel(SOCKET s)
166*617e2443SMark Logan {
167*617e2443SMark Logan if (oldProtocolMode) {
168*617e2443SMark Logan ChannelMap::iterator it = _openChannels.begin();
169*617e2443SMark Logan for (; it != _openChannels.end(); it++) {
170*617e2443SMark Logan if (it->second->GetSocket() == s) {
171*617e2443SMark Logan return it->second;
172*617e2443SMark Logan }
173*617e2443SMark Logan }
174*617e2443SMark Logan } else {
175*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(s);
176*617e2443SMark Logan if (it != _openChannels.end()) {
177*617e2443SMark Logan return it->second;
178*617e2443SMark Logan }
179*617e2443SMark Logan }
180*617e2443SMark Logan return NULL;
181*617e2443SMark Logan }
182*617e2443SMark Logan
183*617e2443SMark Logan bool Protocol::IsDeInitialized()
184*617e2443SMark Logan {
185*617e2443SMark Logan Lock dl(_deinitLock);
186*617e2443SMark Logan return _deinitReq;
187*617e2443SMark Logan }
188*617e2443SMark Logan
189*617e2443SMark Logan
190*617e2443SMark Logan bool Protocol::IsInitialized()
191*617e2443SMark Logan {
192*617e2443SMark Logan if (IsDeInitialized()) {
193*617e2443SMark Logan return false;
194*617e2443SMark Logan }
195*617e2443SMark Logan
196*617e2443SMark Logan return _lme.IsInitialized();
197*617e2443SMark Logan }
198*617e2443SMark Logan
199*617e2443SMark Logan void Protocol::Deinit()
200*617e2443SMark Logan {
201*617e2443SMark Logan Lock dl(_deinitLock);
202*617e2443SMark Logan _deinitReq = true;
203*617e2443SMark Logan
204*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
205*617e2443SMark Logan ATNetworkTool::CloseSocket(_clientSignalSocket);
206*617e2443SMark Logan
207*617e2443SMark Logan {
208*617e2443SMark Logan Lock l(_channelsLock);
209*617e2443SMark Logan
210*617e2443SMark Logan ChannelMap::iterator it = _openChannels.begin();
211*617e2443SMark Logan
212*617e2443SMark Logan for (; it != _openChannels.end(); it++) {
213*617e2443SMark Logan ATNetworkTool::CloseSocket(it->second->GetSocket());
214*617e2443SMark Logan delete it->second;
215*617e2443SMark Logan }
216*617e2443SMark Logan
217*617e2443SMark Logan _openChannels.clear();
218*617e2443SMark Logan }
219*617e2443SMark Logan
220*617e2443SMark Logan {
221*617e2443SMark Logan Lock l(_portsLock);
222*617e2443SMark Logan PortMap::iterator it = _openPorts.begin();
223*617e2443SMark Logan
224*617e2443SMark Logan for (; it != _openPorts.end(); it++) {
225*617e2443SMark Logan if (it->second.size() > 0) {
226*617e2443SMark Logan ATNetworkTool::CloseSocket(it->second[0]->GetListeningSocket());
227*617e2443SMark Logan
228*617e2443SMark Logan PortForwardRequestList::iterator it2 = it->second.begin();
229*617e2443SMark Logan for (; it2 != it->second.end(); it2++) {
230*617e2443SMark Logan delete *it2;
231*617e2443SMark Logan }
232*617e2443SMark Logan }
233*617e2443SMark Logan }
234*617e2443SMark Logan _openPorts.clear();
235*617e2443SMark Logan }
236*617e2443SMark Logan
237*617e2443SMark Logan _lme.Deinit();
238*617e2443SMark Logan
239*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
240*617e2443SMark Logan if (!oldProtocolMode) {
241*617e2443SMark Logan _cfg.Deinit();
242*617e2443SMark Logan }
243*617e2443SMark Logan #endif
244*617e2443SMark Logan
245*617e2443SMark Logan {
246*617e2443SMark Logan Lock vl(_versionLock);
247*617e2443SMark Logan _handshakingStatus = NOT_INITIATED;
248*617e2443SMark Logan _pfwdService = NOT_STARTED;
249*617e2443SMark Logan _AmtProtVersion.MajorVersion = 0;
250*617e2443SMark Logan _AmtProtVersion.MinorVersion = 0;
251*617e2443SMark Logan }
252*617e2443SMark Logan
253*617e2443SMark Logan }
254*617e2443SMark Logan
255*617e2443SMark Logan void Protocol::DeinitFull()
256*617e2443SMark Logan {
257*617e2443SMark Logan Deinit();
258*617e2443SMark Logan
259*617e2443SMark Logan if (_rxSocketBuffer != NULL) {
260*617e2443SMark Logan delete []_rxSocketBuffer;
261*617e2443SMark Logan _rxSocketBuffer = NULL;
262*617e2443SMark Logan _rxSocketBufferSize = 0;
263*617e2443SMark Logan }
264*617e2443SMark Logan
265*617e2443SMark Logan _serverSignalSocket = INVALID_SOCKET;
266*617e2443SMark Logan _clientSignalSocket = INVALID_SOCKET;
267*617e2443SMark Logan _sockets_active = false;
268*617e2443SMark Logan
269*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
270*617e2443SMark Logan _remoteAccessEnabled = false;
271*617e2443SMark Logan #endif
272*617e2443SMark Logan memset(_AMTFQDN, 0, sizeof(_AMTFQDN));
273*617e2443SMark Logan }
274*617e2443SMark Logan
275*617e2443SMark Logan bool Protocol::_checkListen(std::string address, in_port_t port, int &socket)
276*617e2443SMark Logan {
277*617e2443SMark Logan bool exists = false;
278*617e2443SMark Logan
279*617e2443SMark Logan PortMap::iterator it = _openPorts.find(port);
280*617e2443SMark Logan if (it != _openPorts.end()) {
281*617e2443SMark Logan if (it->second.size() > 0) {
282*617e2443SMark Logan socket = it->second[0]->GetListeningSocket();
283*617e2443SMark Logan PortForwardRequestList::iterator it2 = it->second.begin();
284*617e2443SMark Logan
285*617e2443SMark Logan for (; it2 != it->second.end(); it2++) {
286*617e2443SMark Logan if (((*it2)->GetStatus() != PortForwardRequest::NOT_ACTIVE) &&
287*617e2443SMark Logan ((*it2)->GetBindedAddress().compare(address) == 0)) {
288*617e2443SMark Logan exists = true;
289*617e2443SMark Logan break;
290*617e2443SMark Logan }
291*617e2443SMark Logan }
292*617e2443SMark Logan
293*617e2443SMark Logan }
294*617e2443SMark Logan } else {
295*617e2443SMark Logan PortForwardRequestList portForwardRequestList;
296*617e2443SMark Logan _openPorts[port] = portForwardRequestList;
297*617e2443SMark Logan }
298*617e2443SMark Logan
299*617e2443SMark Logan return exists;
300*617e2443SMark Logan }
301*617e2443SMark Logan
302*617e2443SMark Logan int Protocol::_listenPort(in_port_t port, int &error)
303*617e2443SMark Logan {
304*617e2443SMark Logan return ATNetworkTool::CreateServerSocket(
305*617e2443SMark Logan port,
306*617e2443SMark Logan error,
307*617e2443SMark Logan false, true, PF_INET);
308*617e2443SMark Logan }
309*617e2443SMark Logan
310*617e2443SMark Logan bool Protocol::_localListen(in_port_t port)
311*617e2443SMark Logan {
312*617e2443SMark Logan int error;
313*617e2443SMark Logan int socket = INVALID_SOCKET;
314*617e2443SMark Logan bool exists = _checkListen("127.0.0.1", port, socket);
315*617e2443SMark Logan
316*617e2443SMark Logan int serverSocket = _listenPort(port, error);
317*617e2443SMark Logan if (serverSocket == INVALID_SOCKET) {
318*617e2443SMark Logan PRINT("[Compat]LMS Service cannot listen at port %d.\n", (int)port);
319*617e2443SMark Logan if (exists) {
320*617e2443SMark Logan //already listening
321*617e2443SMark Logan }
322*617e2443SMark Logan return false;
323*617e2443SMark Logan }
324*617e2443SMark Logan PRINT("[Compat]Listening at port %d at local interface.\n", (int)port);
325*617e2443SMark Logan
326*617e2443SMark Logan PortForwardRequest *portForwardRequest =
327*617e2443SMark Logan new PortForwardRequest("127.0.0.1", port,
328*617e2443SMark Logan serverSocket, _isLocalCallback, true);
329*617e2443SMark Logan
330*617e2443SMark Logan _openPorts[port].push_back(portForwardRequest);
331*617e2443SMark Logan portForwardRequest->SetStatus(PortForwardRequest::LISTENING);
332*617e2443SMark Logan
333*617e2443SMark Logan return true;
334*617e2443SMark Logan }
335*617e2443SMark Logan
336*617e2443SMark Logan bool Protocol::CreateSockets()
337*617e2443SMark Logan {
338*617e2443SMark Logan int error;
339*617e2443SMark Logan _sockets_active = false;
340*617e2443SMark Logan
341*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
342*617e2443SMark Logan _serverSignalSocket = ATNetworkTool::CreateServerSocket((in_port_t)0, error, true);
343*617e2443SMark Logan if (_serverSignalSocket == INVALID_SOCKET) {
344*617e2443SMark Logan return false;
345*617e2443SMark Logan }
346*617e2443SMark Logan
347*617e2443SMark Logan ATNetworkTool::CloseSocket(_clientSignalSocket);
348*617e2443SMark Logan _clientSignalSocket = ATNetworkTool::ConnectToSocket(_serverSignalSocket, error);
349*617e2443SMark Logan if (_clientSignalSocket == INVALID_SOCKET) {
350*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
351*617e2443SMark Logan _serverSignalSocket = INVALID_SOCKET;
352*617e2443SMark Logan return false;
353*617e2443SMark Logan }
354*617e2443SMark Logan
355*617e2443SMark Logan struct sockaddr_storage addr;
356*617e2443SMark Logan socklen_t addrLen = sizeof(addr);
357*617e2443SMark Logan SOCKET s_new = accept(_serverSignalSocket, (struct sockaddr *)&addr, &addrLen);
358*617e2443SMark Logan if (s_new == INVALID_SOCKET) {
359*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
360*617e2443SMark Logan ATNetworkTool::CloseSocket(_clientSignalSocket);
361*617e2443SMark Logan _serverSignalSocket = INVALID_SOCKET;
362*617e2443SMark Logan _clientSignalSocket = INVALID_SOCKET;
363*617e2443SMark Logan return false;
364*617e2443SMark Logan }
365*617e2443SMark Logan
366*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
367*617e2443SMark Logan _serverSignalSocket = s_new;
368*617e2443SMark Logan
369*617e2443SMark Logan if (oldProtocolMode) {
370*617e2443SMark Logan if (!_localListen(16992)) {
371*617e2443SMark Logan return false;
372*617e2443SMark Logan }
373*617e2443SMark Logan if (!_localListen(16993)) {
374*617e2443SMark Logan return false;
375*617e2443SMark Logan }
376*617e2443SMark Logan }
377*617e2443SMark Logan
378*617e2443SMark Logan _sockets_active = true;
379*617e2443SMark Logan return true;
380*617e2443SMark Logan }
381*617e2443SMark Logan
382*617e2443SMark Logan void Protocol::DestroySockets()
383*617e2443SMark Logan {
384*617e2443SMark Logan _sockets_active = false;
385*617e2443SMark Logan
386*617e2443SMark Logan if (_serverSignalSocket != INVALID_SOCKET) {
387*617e2443SMark Logan ATNetworkTool::CloseSocket(_serverSignalSocket);
388*617e2443SMark Logan _serverSignalSocket = INVALID_SOCKET;
389*617e2443SMark Logan }
390*617e2443SMark Logan }
391*617e2443SMark Logan
392*617e2443SMark Logan bool Protocol::_acceptConnection(SOCKET s, unsigned int port)
393*617e2443SMark Logan {
394*617e2443SMark Logan ATAddress addr;
395*617e2443SMark Logan int error = 0;
396*617e2443SMark Logan char buf[NI_MAXHOST];
397*617e2443SMark Logan
398*617e2443SMark Logan if (!IsInitialized()) {
399*617e2443SMark Logan return false;
400*617e2443SMark Logan }
401*617e2443SMark Logan
402*617e2443SMark Logan SOCKET s_new = ATNetworkTool::Accept(s, addr, error);
403*617e2443SMark Logan if (s_new == INVALID_SOCKET) {
404*617e2443SMark Logan #if DEBUGLOG
405*617e2443SMark Logan char *msg = _getErrMsg(error);
406*617e2443SMark Logan PRINT("Error accepting new connection (%d): %s\n", error, msg);
407*617e2443SMark Logan #endif
408*617e2443SMark Logan return false;
409*617e2443SMark Logan }
410*617e2443SMark Logan
411*617e2443SMark Logan const char *addrStr = addr.inNtoP(buf, NI_MAXHOST);
412*617e2443SMark Logan if (addrStr == NULL) {
413*617e2443SMark Logan PRINT("Error: ntop failed for new connection\n");
414*617e2443SMark Logan ATNetworkTool::CloseSocket(s_new);
415*617e2443SMark Logan return false;
416*617e2443SMark Logan }
417*617e2443SMark Logan
418*617e2443SMark Logan PortForwardRequest *portForwardRequest = NULL;
419*617e2443SMark Logan
420*617e2443SMark Logan //_portsLock is already aquired by the calling function: Select().
421*617e2443SMark Logan PortMap::iterator it = _openPorts.find(port);
422*617e2443SMark Logan if (it != _openPorts.end()) {
423*617e2443SMark Logan PortForwardRequestList::iterator it2 = it->second.begin();
424*617e2443SMark Logan
425*617e2443SMark Logan for (; it2 != it->second.end(); it2++) {
426*617e2443SMark Logan if (((*it2)->GetStatus() == PortForwardRequest::LISTENING) &&
427*617e2443SMark Logan (1 == (*it2)->IsConnectionPermitted(this, s_new))) {
428*617e2443SMark Logan portForwardRequest = *it2;
429*617e2443SMark Logan break;
430*617e2443SMark Logan }
431*617e2443SMark Logan }
432*617e2443SMark Logan
433*617e2443SMark Logan }
434*617e2443SMark Logan
435*617e2443SMark Logan if (portForwardRequest == NULL) {
436*617e2443SMark Logan PRINT("Error: new connection is denied (addr %s)\n", addrStr);
437*617e2443SMark Logan ATNetworkTool::CloseSocket(s_new);
438*617e2443SMark Logan return false;
439*617e2443SMark Logan }
440*617e2443SMark Logan
441*617e2443SMark Logan if (oldProtocolMode) {
442*617e2443SMark Logan unsigned int connId;
443*617e2443SMark Logan bool oret = _lme.CompatOpenConnection(port, addr, connId);
444*617e2443SMark Logan if (!oret) {
445*617e2443SMark Logan PRINT("[Compat]Error: failed to open new LME MEI connection\n");
446*617e2443SMark Logan ATNetworkTool::CloseSocket(s_new);
447*617e2443SMark Logan return false;
448*617e2443SMark Logan }
449*617e2443SMark Logan PRINT("[Compat]Send open connection to LME. Sender %d.\n", (int)s_new);
450*617e2443SMark Logan
451*617e2443SMark Logan Channel *c = new Channel(portForwardRequest, s_new);
452*617e2443SMark Logan c->SetStatus(Channel::OPEN);
453*617e2443SMark Logan c->SetRecipientChannel(connId);
454*617e2443SMark Logan c->AddBytesTxWindow(1024);
455*617e2443SMark Logan
456*617e2443SMark Logan Lock l(_channelsLock);
457*617e2443SMark Logan _openChannels[connId] = c;
458*617e2443SMark Logan c->GetPortForwardRequest()->IncreaseChannelCount();
459*617e2443SMark Logan } else {
460*617e2443SMark Logan Channel *c = new Channel(portForwardRequest, s_new);
461*617e2443SMark Logan c->SetStatus(Channel::NOT_OPENED);
462*617e2443SMark Logan
463*617e2443SMark Logan Lock l(_channelsLock);
464*617e2443SMark Logan _openChannels[s_new] = c;
465*617e2443SMark Logan c->GetPortForwardRequest()->IncreaseChannelCount();
466*617e2443SMark Logan
467*617e2443SMark Logan _lme.ChannelOpenForwardedRequest((UINT32)s_new,
468*617e2443SMark Logan port,
469*617e2443SMark Logan ((portForwardRequest->IsLocal()) ? "127.0.0.1" : addrStr),
470*617e2443SMark Logan addr.inPort());
471*617e2443SMark Logan PRINT("Send channel open request to LME. Sender %d.\n", (int)s_new);
472*617e2443SMark Logan }
473*617e2443SMark Logan
474*617e2443SMark Logan return true;
475*617e2443SMark Logan }
476*617e2443SMark Logan
477*617e2443SMark Logan int Protocol::Select()
478*617e2443SMark Logan {
479*617e2443SMark Logan fd_set rset;
480*617e2443SMark Logan struct timeval tv;
481*617e2443SMark Logan int res;
482*617e2443SMark Logan int fdCount = 0;
483*617e2443SMark Logan int fdMin = -1;
484*617e2443SMark Logan
485*617e2443SMark Logan tv.tv_sec = 1;
486*617e2443SMark Logan tv.tv_usec = 0;
487*617e2443SMark Logan
488*617e2443SMark Logan FD_ZERO(&rset);
489*617e2443SMark Logan
490*617e2443SMark Logan FD_SET(_serverSignalSocket, &rset);
491*617e2443SMark Logan if ((int)_serverSignalSocket > fdCount) {
492*617e2443SMark Logan fdCount = (int)_serverSignalSocket;
493*617e2443SMark Logan }
494*617e2443SMark Logan
495*617e2443SMark Logan {
496*617e2443SMark Logan Lock l(_portsLock);
497*617e2443SMark Logan PortMap::iterator it = _openPorts.begin();
498*617e2443SMark Logan
499*617e2443SMark Logan for (; it != _openPorts.end(); it++) {
500*617e2443SMark Logan if (it->second.size() > 0) {
501*617e2443SMark Logan SOCKET serverSocket = it->second[0]->GetListeningSocket();
502*617e2443SMark Logan FD_SET(serverSocket, &rset);
503*617e2443SMark Logan if ((int)serverSocket > fdCount) {
504*617e2443SMark Logan fdCount = (int)serverSocket;
505*617e2443SMark Logan }
506*617e2443SMark Logan }
507*617e2443SMark Logan }
508*617e2443SMark Logan }
509*617e2443SMark Logan
510*617e2443SMark Logan {
511*617e2443SMark Logan Lock l(_channelsLock);
512*617e2443SMark Logan
513*617e2443SMark Logan ChannelMap::iterator it = _openChannels.begin();
514*617e2443SMark Logan
515*617e2443SMark Logan for (; it != _openChannels.end(); it++) {
516*617e2443SMark Logan if ((it->second->GetStatus() == Channel::OPEN) &&
517*617e2443SMark Logan (it->second->GetTxWindow() > 0)) {
518*617e2443SMark Logan SOCKET socket = it->second->GetSocket();
519*617e2443SMark Logan FD_SET(socket, &rset);
520*617e2443SMark Logan if ((int)socket > fdCount) {
521*617e2443SMark Logan fdCount = (int)socket;
522*617e2443SMark Logan }
523*617e2443SMark Logan if ((fdMin == -1) || ((int)socket < fdMin)) {
524*617e2443SMark Logan fdMin = (int)socket;
525*617e2443SMark Logan }
526*617e2443SMark Logan }
527*617e2443SMark Logan }
528*617e2443SMark Logan }
529*617e2443SMark Logan
530*617e2443SMark Logan fdCount++;
531*617e2443SMark Logan res = select(fdCount, &rset, NULL, NULL, &tv);
532*617e2443SMark Logan if (res == -1) {
533*617e2443SMark Logan #if DEBUGLOG
534*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
535*617e2443SMark Logan int err = errno;
536*617e2443SMark Logan #else
537*617e2443SMark Logan int err = GetLastError();
538*617e2443SMark Logan #endif // __sun || _LINUX
539*617e2443SMark Logan
540*617e2443SMark Logan char *msg = _getErrMsg(err);
541*617e2443SMark Logan PRINT("Select error (%d): %s\n", err, msg);
542*617e2443SMark Logan #endif
543*617e2443SMark Logan return -1;
544*617e2443SMark Logan }
545*617e2443SMark Logan
546*617e2443SMark Logan if (res == 0) {
547*617e2443SMark Logan return 0;
548*617e2443SMark Logan }
549*617e2443SMark Logan
550*617e2443SMark Logan if (!IsInitialized()) {
551*617e2443SMark Logan return 0;
552*617e2443SMark Logan }
553*617e2443SMark Logan
554*617e2443SMark Logan if (FD_ISSET(_serverSignalSocket, &rset)) { // Received a 'signal'
555*617e2443SMark Logan char c = 0;
556*617e2443SMark Logan res = recv(_serverSignalSocket, &c, 1, 0);
557*617e2443SMark Logan FD_CLR(_serverSignalSocket, &rset);
558*617e2443SMark Logan res--;
559*617e2443SMark Logan }
560*617e2443SMark Logan
561*617e2443SMark Logan {
562*617e2443SMark Logan Lock l(_portsLock);
563*617e2443SMark Logan PortMap::iterator it = _openPorts.begin();
564*617e2443SMark Logan
565*617e2443SMark Logan for (; it != _openPorts.end(); it++) {
566*617e2443SMark Logan if (it->second.size() > 0) {
567*617e2443SMark Logan SOCKET serverSocket = it->second[0]->GetListeningSocket();
568*617e2443SMark Logan if (FD_ISSET(serverSocket, &rset)) {
569*617e2443SMark Logan // connection request
570*617e2443SMark Logan PRINT("Connection requested on port %d\n", it->first);
571*617e2443SMark Logan _acceptConnection(serverSocket, it->first);
572*617e2443SMark Logan FD_CLR(serverSocket, &rset);
573*617e2443SMark Logan res--;
574*617e2443SMark Logan }
575*617e2443SMark Logan }
576*617e2443SMark Logan }
577*617e2443SMark Logan }
578*617e2443SMark Logan
579*617e2443SMark Logan int i;
580*617e2443SMark Logan for (i = fdMin/*0*/; (res > 0) && (i < fdCount); i++) {
581*617e2443SMark Logan if (FD_ISSET(i, &rset)) {
582*617e2443SMark Logan _rxFromSocket(i);
583*617e2443SMark Logan res--;
584*617e2443SMark Logan }
585*617e2443SMark Logan }
586*617e2443SMark Logan
587*617e2443SMark Logan return 1;
588*617e2443SMark Logan }
589*617e2443SMark Logan
590*617e2443SMark Logan int Protocol::_rxFromSocket(SOCKET s)
591*617e2443SMark Logan {
592*617e2443SMark Logan Channel *c = NULL;
593*617e2443SMark Logan
594*617e2443SMark Logan if (!IsInitialized()) {
595*617e2443SMark Logan return 0;
596*617e2443SMark Logan }
597*617e2443SMark Logan
598*617e2443SMark Logan {
599*617e2443SMark Logan Lock l(_channelsLock);
600*617e2443SMark Logan
601*617e2443SMark Logan Channel *cx = _getSockOpenChannel(s);
602*617e2443SMark Logan
603*617e2443SMark Logan if (cx == NULL) {
604*617e2443SMark Logan // Data received from a socket that is not in the map.
605*617e2443SMark Logan // Since we only select on our sockets, this means it was
606*617e2443SMark Logan // in the map, but was removed, probably because we received
607*617e2443SMark Logan // an End Connection message from the HECI.
608*617e2443SMark Logan return 0;
609*617e2443SMark Logan }
610*617e2443SMark Logan
611*617e2443SMark Logan c = new Channel(*cx);
612*617e2443SMark Logan }
613*617e2443SMark Logan
614*617e2443SMark Logan int res = 0;
615*617e2443SMark Logan
616*617e2443SMark Logan int len = std::min(c->GetTxWindow(), _rxSocketBufferSize);
617*617e2443SMark Logan res = recv(s, _rxSocketBuffer, len, 0);
618*617e2443SMark Logan if (res > 0) {
619*617e2443SMark Logan // send data to LME
620*617e2443SMark Logan PRINT("Received %d bytes from socket %d. Sending to LME\n", res, (int)s);
621*617e2443SMark Logan if (oldProtocolMode) {
622*617e2443SMark Logan _lme.CompatSendMessage((UINT8)c->GetRecipientChannel(), res, (unsigned char *)_rxSocketBuffer);
623*617e2443SMark Logan } else {
624*617e2443SMark Logan _lme.ChannelData(c->GetRecipientChannel(), res, (unsigned char *)_rxSocketBuffer);
625*617e2443SMark Logan }
626*617e2443SMark Logan goto out;
627*617e2443SMark Logan } else if (res == 0) {
628*617e2443SMark Logan // connection closed
629*617e2443SMark Logan PRINT("Received 0 bytes from socket %d.\n", (int)s);
630*617e2443SMark Logan goto out;
631*617e2443SMark Logan } else {
632*617e2443SMark Logan #if DEBUGLOG
633*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
634*617e2443SMark Logan int err = errno;
635*617e2443SMark Logan #else
636*617e2443SMark Logan int err = GetLastError();
637*617e2443SMark Logan #endif // __sun || _LINUX
638*617e2443SMark Logan
639*617e2443SMark Logan char *msg = _getErrMsg(err);
640*617e2443SMark Logan PRINT("Receive error on socket %d (%d): %s\n", (int)s, err, msg);
641*617e2443SMark Logan #endif
642*617e2443SMark Logan #ifdef __sun
643*617e2443SMark Logan ATNetworkTool::CloseSocket(s);
644*617e2443SMark Logan #endif
645*617e2443SMark Logan goto out;
646*617e2443SMark Logan }
647*617e2443SMark Logan
648*617e2443SMark Logan out:
649*617e2443SMark Logan {
650*617e2443SMark Logan Lock l(_channelsLock);
651*617e2443SMark Logan
652*617e2443SMark Logan Channel *cx = _getSockOpenChannel(s);
653*617e2443SMark Logan
654*617e2443SMark Logan if (cx == NULL) {
655*617e2443SMark Logan // Data received from a socket that is not in the map.
656*617e2443SMark Logan // Since we only select on our sockets, this means it was
657*617e2443SMark Logan // in the map, but was removed, probably because we received
658*617e2443SMark Logan // an End Connection message from the HECI.
659*617e2443SMark Logan delete c;
660*617e2443SMark Logan return 0;
661*617e2443SMark Logan }
662*617e2443SMark Logan if (res > 0) {
663*617e2443SMark Logan if (!oldProtocolMode) {
664*617e2443SMark Logan cx->AddBytesTxWindow(-res);
665*617e2443SMark Logan }
666*617e2443SMark Logan }
667*617e2443SMark Logan else {
668*617e2443SMark Logan cx->SetStatus(Channel::WAITING_CLOSE);
669*617e2443SMark Logan if (oldProtocolMode) {
670*617e2443SMark Logan if (res == 0) {
671*617e2443SMark Logan _closeMChannel(cx);
672*617e2443SMark Logan
673*617e2443SMark Logan ChannelMap::iterator it = _openChannels.begin();
674*617e2443SMark Logan for (; it != _openChannels.end(); it++) {
675*617e2443SMark Logan if (it->second == cx) {
676*617e2443SMark Logan break;
677*617e2443SMark Logan }
678*617e2443SMark Logan }
679*617e2443SMark Logan if (it != _openChannels.end()) {
680*617e2443SMark Logan _openChannels.erase(it);
681*617e2443SMark Logan }
682*617e2443SMark Logan }
683*617e2443SMark Logan _lme.CompatCloseConnection(c->GetRecipientChannel(),
684*617e2443SMark Logan ((res == 0) ? LMS_CLOSE_STATUS_CLIENT :
685*617e2443SMark Logan LMS_CLOSE_STATUS_SOCKET));
686*617e2443SMark Logan } else {
687*617e2443SMark Logan _lme.ChannelClose(c->GetRecipientChannel());
688*617e2443SMark Logan }
689*617e2443SMark Logan }
690*617e2443SMark Logan }
691*617e2443SMark Logan delete c;
692*617e2443SMark Logan
693*617e2443SMark Logan return 0;
694*617e2443SMark Logan }
695*617e2443SMark Logan
696*617e2443SMark Logan void Protocol::_signalSelect()
697*617e2443SMark Logan {
698*617e2443SMark Logan int senderr = 0;
699*617e2443SMark Logan
700*617e2443SMark Logan _send(_clientSignalSocket, "s", 1, senderr); //Enforce a new execution of Select()
701*617e2443SMark Logan }
702*617e2443SMark Logan
703*617e2443SMark Logan void Protocol::_closePortForwardRequest(PortForwardRequest *p)
704*617e2443SMark Logan {
705*617e2443SMark Logan PortMap::iterator it = _openPorts.find(p->GetPort());
706*617e2443SMark Logan if (it == _openPorts.end()) {
707*617e2443SMark Logan return;
708*617e2443SMark Logan }
709*617e2443SMark Logan
710*617e2443SMark Logan bool found = false;
711*617e2443SMark Logan PortForwardRequestList::iterator it2 = it->second.begin();
712*617e2443SMark Logan for (; it2 != it->second.end(); it2++) {
713*617e2443SMark Logan if ((*it2) == p) {
714*617e2443SMark Logan found = true;
715*617e2443SMark Logan break;
716*617e2443SMark Logan }
717*617e2443SMark Logan }
718*617e2443SMark Logan
719*617e2443SMark Logan if ((*it2)->GetStatus() == PortForwardRequest::NOT_ACTIVE) {
720*617e2443SMark Logan
721*617e2443SMark Logan SOCKET serverSocket = (*it2)->GetListeningSocket();
722*617e2443SMark Logan delete (*it2);
723*617e2443SMark Logan it->second.erase(it2);
724*617e2443SMark Logan
725*617e2443SMark Logan if (it->second.size() == 0) {
726*617e2443SMark Logan int res = ATNetworkTool::CloseSocket(serverSocket);
727*617e2443SMark Logan if (res != 0) {
728*617e2443SMark Logan int err;
729*617e2443SMark Logan
730*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
731*617e2443SMark Logan err = errno;
732*617e2443SMark Logan #else
733*617e2443SMark Logan err = WSAGetLastError()
734*617e2443SMark Logan #endif
735*617e2443SMark Logan PRINT("Error %d in closing server socket at port %d.\n", err, p->GetPort());
736*617e2443SMark Logan }
737*617e2443SMark Logan _openPorts.erase(it);
738*617e2443SMark Logan }
739*617e2443SMark Logan }
740*617e2443SMark Logan }
741*617e2443SMark Logan
742*617e2443SMark Logan bool Protocol::_checkProtocolFlow(LMEMessage *message)
743*617e2443SMark Logan {
744*617e2443SMark Logan switch (message->MessageType) {
745*617e2443SMark Logan case APF_SERVICE_REQUEST:
746*617e2443SMark Logan case APF_USERAUTH_REQUEST:
747*617e2443SMark Logan {
748*617e2443SMark Logan Lock l(_versionLock);
749*617e2443SMark Logan if (_handshakingStatus != AGREED) {
750*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
751*617e2443SMark Logan Deinit();
752*617e2443SMark Logan return false;
753*617e2443SMark Logan }
754*617e2443SMark Logan return true;
755*617e2443SMark Logan }
756*617e2443SMark Logan break;
757*617e2443SMark Logan
758*617e2443SMark Logan case APF_GLOBAL_REQUEST:
759*617e2443SMark Logan case APF_CHANNEL_OPEN:
760*617e2443SMark Logan case APF_CHANNEL_OPEN_CONFIRMATION:
761*617e2443SMark Logan case APF_CHANNEL_OPEN_FAILURE:
762*617e2443SMark Logan case APF_CHANNEL_CLOSE:
763*617e2443SMark Logan case APF_CHANNEL_DATA:
764*617e2443SMark Logan case APF_CHANNEL_WINDOW_ADJUST:
765*617e2443SMark Logan {
766*617e2443SMark Logan Lock l(_versionLock);
767*617e2443SMark Logan if ((_handshakingStatus != AGREED) || (_pfwdService != STARTED)) {
768*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
769*617e2443SMark Logan Deinit();
770*617e2443SMark Logan return false;
771*617e2443SMark Logan }
772*617e2443SMark Logan return true;
773*617e2443SMark Logan }
774*617e2443SMark Logan break;
775*617e2443SMark Logan
776*617e2443SMark Logan case APF_DISCONNECT:
777*617e2443SMark Logan case APF_PROTOCOLVERSION:
778*617e2443SMark Logan return true;
779*617e2443SMark Logan break;
780*617e2443SMark Logan
781*617e2443SMark Logan default:
782*617e2443SMark Logan {
783*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
784*617e2443SMark Logan Deinit();
785*617e2443SMark Logan return false;
786*617e2443SMark Logan }
787*617e2443SMark Logan break;
788*617e2443SMark Logan }
789*617e2443SMark Logan
790*617e2443SMark Logan return false;
791*617e2443SMark Logan }
792*617e2443SMark Logan
793*617e2443SMark Logan unsigned int Protocol::_getMinMessageLen(LMEMessage *message)
794*617e2443SMark Logan {
795*617e2443SMark Logan switch (message->MessageType) {
796*617e2443SMark Logan case APF_SERVICE_REQUEST:
797*617e2443SMark Logan return sizeof(LMEServiceRequestMessage);
798*617e2443SMark Logan break;
799*617e2443SMark Logan case APF_USERAUTH_REQUEST:
800*617e2443SMark Logan return sizeof(LMEUserAuthRequestMessage);
801*617e2443SMark Logan break;
802*617e2443SMark Logan case APF_GLOBAL_REQUEST:
803*617e2443SMark Logan return sizeof(LMEGlobalRequestMessage);
804*617e2443SMark Logan break;
805*617e2443SMark Logan case APF_CHANNEL_OPEN:
806*617e2443SMark Logan return sizeof(LMEChannelOpenRequestMessage);
807*617e2443SMark Logan break;
808*617e2443SMark Logan case APF_CHANNEL_OPEN_CONFIRMATION:
809*617e2443SMark Logan return sizeof(LMEChannelOpenReplaySuccessMessage);
810*617e2443SMark Logan break;
811*617e2443SMark Logan case APF_CHANNEL_OPEN_FAILURE:
812*617e2443SMark Logan return sizeof(LMEChannelOpenReplayFailureMessage);
813*617e2443SMark Logan break;
814*617e2443SMark Logan case APF_CHANNEL_CLOSE:
815*617e2443SMark Logan return sizeof(LMEChannelCloseMessage);
816*617e2443SMark Logan break;
817*617e2443SMark Logan case APF_CHANNEL_DATA:
818*617e2443SMark Logan return sizeof(LMEChannelDataMessage);
819*617e2443SMark Logan break;
820*617e2443SMark Logan case APF_CHANNEL_WINDOW_ADJUST:
821*617e2443SMark Logan return sizeof(LMEChannelWindowAdjustMessage);
822*617e2443SMark Logan break;
823*617e2443SMark Logan case APF_DISCONNECT:
824*617e2443SMark Logan return sizeof(LMEDisconnectMessage);
825*617e2443SMark Logan break;
826*617e2443SMark Logan case APF_PROTOCOLVERSION:
827*617e2443SMark Logan return sizeof(LMEProtocolVersionMessage);
828*617e2443SMark Logan break;
829*617e2443SMark Logan default:
830*617e2443SMark Logan return 0;
831*617e2443SMark Logan }
832*617e2443SMark Logan
833*617e2443SMark Logan return 0;
834*617e2443SMark Logan }
835*617e2443SMark Logan
836*617e2443SMark Logan bool Protocol::_checkMessageAndProtocol(LMEMessage *message, unsigned int len)
837*617e2443SMark Logan {
838*617e2443SMark Logan if (len < sizeof(LMEMessage)) {
839*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
840*617e2443SMark Logan Deinit();
841*617e2443SMark Logan return false;
842*617e2443SMark Logan }
843*617e2443SMark Logan
844*617e2443SMark Logan if (!_checkProtocolFlow(message)) {
845*617e2443SMark Logan return false;
846*617e2443SMark Logan }
847*617e2443SMark Logan if (len < _getMinMessageLen(message)) {
848*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
849*617e2443SMark Logan Deinit();
850*617e2443SMark Logan return false;
851*617e2443SMark Logan }
852*617e2443SMark Logan return true;
853*617e2443SMark Logan }
854*617e2443SMark Logan
855*617e2443SMark Logan void Protocol::_LmeCallback(void *param, void *buffer, unsigned int len, int *status)
856*617e2443SMark Logan {
857*617e2443SMark Logan Protocol *prot = (Protocol *)param;
858*617e2443SMark Logan
859*617e2443SMark Logan if (prot->oldProtocolMode) {
860*617e2443SMark Logan prot->_LmeReceiveCompat((char *)buffer, len, status);
861*617e2443SMark Logan } else {
862*617e2443SMark Logan prot->_LmeReceive(buffer, len, status);
863*617e2443SMark Logan }
864*617e2443SMark Logan }
865*617e2443SMark Logan
866*617e2443SMark Logan void Protocol::_LmeReceive(void *buffer, unsigned int len, int *status)
867*617e2443SMark Logan {
868*617e2443SMark Logan LMEMessage *message = (LMEMessage *)buffer;
869*617e2443SMark Logan *status = 0;
870*617e2443SMark Logan
871*617e2443SMark Logan if (!_checkMessageAndProtocol(message, len)) {
872*617e2443SMark Logan return;
873*617e2443SMark Logan }
874*617e2443SMark Logan
875*617e2443SMark Logan switch (message->MessageType) {
876*617e2443SMark Logan case APF_DISCONNECT:
877*617e2443SMark Logan {
878*617e2443SMark Logan PRINT("LME requested to disconnect with reason code 0x%08x\n",
879*617e2443SMark Logan ((LMEDisconnectMessage *)message)->ReasonCode);
880*617e2443SMark Logan Deinit();
881*617e2443SMark Logan return;
882*617e2443SMark Logan }
883*617e2443SMark Logan break;
884*617e2443SMark Logan
885*617e2443SMark Logan case APF_SERVICE_REQUEST:
886*617e2443SMark Logan {
887*617e2443SMark Logan LMEServiceRequestMessage *sRMsg =
888*617e2443SMark Logan (LMEServiceRequestMessage *)message;
889*617e2443SMark Logan
890*617e2443SMark Logan if ((sRMsg->ServiceName.compare(APF_SERVICE_AUTH) == 0) ||
891*617e2443SMark Logan (sRMsg->ServiceName.compare(APF_SERVICE_PFWD) == 0)) {
892*617e2443SMark Logan
893*617e2443SMark Logan _lme.ServiceAccept(sRMsg->ServiceName);
894*617e2443SMark Logan PRINT("Accepting service: %s\n",
895*617e2443SMark Logan sRMsg->ServiceName.c_str());
896*617e2443SMark Logan if (sRMsg->ServiceName.compare(APF_SERVICE_PFWD) == 0) {
897*617e2443SMark Logan Lock l(_versionLock);
898*617e2443SMark Logan _pfwdService = STARTED;
899*617e2443SMark Logan }
900*617e2443SMark Logan } else {
901*617e2443SMark Logan PRINT("Requesting to disconnect from LME with reason code 0x%08x\n",
902*617e2443SMark Logan APF_DISCONNECT_SERVICE_NOT_AVAILABLE);
903*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_SERVICE_NOT_AVAILABLE);
904*617e2443SMark Logan Deinit();
905*617e2443SMark Logan return;
906*617e2443SMark Logan }
907*617e2443SMark Logan }
908*617e2443SMark Logan break;
909*617e2443SMark Logan
910*617e2443SMark Logan case APF_USERAUTH_REQUEST:
911*617e2443SMark Logan {
912*617e2443SMark Logan PRINT("Sending Userauth success message\n");
913*617e2443SMark Logan _lme.UserAuthSuccess();
914*617e2443SMark Logan }
915*617e2443SMark Logan break;
916*617e2443SMark Logan
917*617e2443SMark Logan case APF_PROTOCOLVERSION:
918*617e2443SMark Logan _apfProtocolVersion((LMEProtocolVersionMessage *)message);
919*617e2443SMark Logan break;
920*617e2443SMark Logan
921*617e2443SMark Logan case APF_GLOBAL_REQUEST:
922*617e2443SMark Logan _apfGlobalRequest((LMEGlobalRequestMessage *)message, len, status);
923*617e2443SMark Logan break;
924*617e2443SMark Logan
925*617e2443SMark Logan case APF_CHANNEL_OPEN:
926*617e2443SMark Logan _apfChannelOpen((LMEChannelOpenRequestMessage *)message, status);
927*617e2443SMark Logan break;
928*617e2443SMark Logan
929*617e2443SMark Logan case APF_CHANNEL_OPEN_CONFIRMATION:
930*617e2443SMark Logan {
931*617e2443SMark Logan LMEChannelOpenReplaySuccessMessage *chOpenSuccMsg =
932*617e2443SMark Logan (LMEChannelOpenReplaySuccessMessage *)message;
933*617e2443SMark Logan
934*617e2443SMark Logan Lock l(_channelsLock);
935*617e2443SMark Logan
936*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(chOpenSuccMsg->RecipientChannel);
937*617e2443SMark Logan if (it != _openChannels.end()) {
938*617e2443SMark Logan it->second->SetStatus(Channel::OPEN);
939*617e2443SMark Logan it->second->SetRecipientChannel(chOpenSuccMsg->SenderChannel);
940*617e2443SMark Logan it->second->AddBytesTxWindow(chOpenSuccMsg->InitialWindow);
941*617e2443SMark Logan }
942*617e2443SMark Logan
943*617e2443SMark Logan _signalSelect();
944*617e2443SMark Logan }
945*617e2443SMark Logan break;
946*617e2443SMark Logan
947*617e2443SMark Logan case APF_CHANNEL_OPEN_FAILURE:
948*617e2443SMark Logan {
949*617e2443SMark Logan PortForwardRequest *clPFwdReq =
950*617e2443SMark Logan _apfChannelOFail((LMEChannelOpenReplayFailureMessage *)message);
951*617e2443SMark Logan if (clPFwdReq != NULL) {
952*617e2443SMark Logan Lock l(_portsLock);
953*617e2443SMark Logan _closePortForwardRequest(clPFwdReq);
954*617e2443SMark Logan }
955*617e2443SMark Logan }
956*617e2443SMark Logan break;
957*617e2443SMark Logan
958*617e2443SMark Logan case APF_CHANNEL_CLOSE:
959*617e2443SMark Logan {
960*617e2443SMark Logan PortForwardRequest *clPFwdReq =
961*617e2443SMark Logan _apfChannelClose((LMEChannelCloseMessage *)message);
962*617e2443SMark Logan if (clPFwdReq != NULL) {
963*617e2443SMark Logan Lock l(_portsLock);
964*617e2443SMark Logan _closePortForwardRequest(clPFwdReq);
965*617e2443SMark Logan }
966*617e2443SMark Logan }
967*617e2443SMark Logan break;
968*617e2443SMark Logan
969*617e2443SMark Logan case APF_CHANNEL_DATA:
970*617e2443SMark Logan {
971*617e2443SMark Logan PortForwardRequest *clPFwdReq =
972*617e2443SMark Logan _apfChannelData((LMEChannelDataMessage *)message, status);
973*617e2443SMark Logan if (clPFwdReq != NULL) {
974*617e2443SMark Logan Lock l(_portsLock);
975*617e2443SMark Logan _closePortForwardRequest(clPFwdReq);
976*617e2443SMark Logan }
977*617e2443SMark Logan }
978*617e2443SMark Logan break;
979*617e2443SMark Logan
980*617e2443SMark Logan case APF_CHANNEL_WINDOW_ADJUST:
981*617e2443SMark Logan {
982*617e2443SMark Logan LMEChannelWindowAdjustMessage *channelWindowMessage = (LMEChannelWindowAdjustMessage *)message;
983*617e2443SMark Logan
984*617e2443SMark Logan Lock l(_channelsLock);
985*617e2443SMark Logan
986*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(channelWindowMessage->RecipientChannel);
987*617e2443SMark Logan if (it != _openChannels.end()) {
988*617e2443SMark Logan it->second->AddBytesTxWindow(channelWindowMessage->BytesToAdd);
989*617e2443SMark Logan _signalSelect();
990*617e2443SMark Logan }
991*617e2443SMark Logan }
992*617e2443SMark Logan break;
993*617e2443SMark Logan
994*617e2443SMark Logan default:
995*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
996*617e2443SMark Logan Deinit();
997*617e2443SMark Logan break;
998*617e2443SMark Logan }
999*617e2443SMark Logan }
1000*617e2443SMark Logan
1001*617e2443SMark Logan unsigned int Protocol::_getMinGlobalMsgLen(LMEGlobalRequestMessage *globalMessage)
1002*617e2443SMark Logan {
1003*617e2443SMark Logan switch (globalMessage->RequestType) {
1004*617e2443SMark Logan case LMEGlobalRequestMessage::TCP_FORWARD_REQUEST:
1005*617e2443SMark Logan return sizeof(LMETcpForwardRequestMessage);
1006*617e2443SMark Logan break;
1007*617e2443SMark Logan case LMEGlobalRequestMessage::TCP_FORWARD_CANCEL_REQUEST:
1008*617e2443SMark Logan return sizeof(LMETcpForwardCancelRequestMessage);
1009*617e2443SMark Logan break;
1010*617e2443SMark Logan case LMEGlobalRequestMessage::UDP_SEND_TO:
1011*617e2443SMark Logan return sizeof(LMEUdpSendToMessage);
1012*617e2443SMark Logan break;
1013*617e2443SMark Logan default:
1014*617e2443SMark Logan return 0;
1015*617e2443SMark Logan }
1016*617e2443SMark Logan return 0;
1017*617e2443SMark Logan }
1018*617e2443SMark Logan
1019*617e2443SMark Logan void Protocol::_apfGlobalRequest(LMEGlobalRequestMessage *globalMessage,
1020*617e2443SMark Logan unsigned int len, int *status)
1021*617e2443SMark Logan {
1022*617e2443SMark Logan PRINT("Global Request type 0x%02x\n", globalMessage->RequestType);
1023*617e2443SMark Logan
1024*617e2443SMark Logan if (len < _getMinGlobalMsgLen(globalMessage)) {
1025*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
1026*617e2443SMark Logan Deinit();
1027*617e2443SMark Logan return;
1028*617e2443SMark Logan }
1029*617e2443SMark Logan
1030*617e2443SMark Logan switch (globalMessage->RequestType) {
1031*617e2443SMark Logan case LMEGlobalRequestMessage::TCP_FORWARD_REQUEST:
1032*617e2443SMark Logan _apfTcpForwardRequest((LMETcpForwardRequestMessage *)globalMessage, status);
1033*617e2443SMark Logan break;
1034*617e2443SMark Logan
1035*617e2443SMark Logan case LMEGlobalRequestMessage::TCP_FORWARD_CANCEL_REQUEST:
1036*617e2443SMark Logan _apfTcpForwardCancel((LMETcpForwardCancelRequestMessage *)globalMessage);
1037*617e2443SMark Logan break;
1038*617e2443SMark Logan
1039*617e2443SMark Logan case LMEGlobalRequestMessage::UDP_SEND_TO:
1040*617e2443SMark Logan _aptSendUdp((LMEUdpSendToMessage *)globalMessage, status);
1041*617e2443SMark Logan break;
1042*617e2443SMark Logan
1043*617e2443SMark Logan default:
1044*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
1045*617e2443SMark Logan Deinit();
1046*617e2443SMark Logan break;
1047*617e2443SMark Logan }
1048*617e2443SMark Logan }
1049*617e2443SMark Logan
1050*617e2443SMark Logan void Protocol::_apfTcpForwardRequest(LMETcpForwardRequestMessage *tcpFwdReqMsg, int *status)
1051*617e2443SMark Logan {
1052*617e2443SMark Logan IsConnectionPermittedCallback cb = NULL;
1053*617e2443SMark Logan bool failure = false;
1054*617e2443SMark Logan
1055*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
1056*617e2443SMark Logan if (tcpFwdReqMsg->Address.compare("0.0.0.0") == 0) {
1057*617e2443SMark Logan cb = _isRemoteCallback;
1058*617e2443SMark Logan }
1059*617e2443SMark Logan else
1060*617e2443SMark Logan #endif
1061*617e2443SMark Logan {
1062*617e2443SMark Logan cb = _isLocalCallback;
1063*617e2443SMark Logan }
1064*617e2443SMark Logan
1065*617e2443SMark Logan {
1066*617e2443SMark Logan Lock l(_portsLock);
1067*617e2443SMark Logan SOCKET serverSocket = INVALID_SOCKET;
1068*617e2443SMark Logan listenPortSet::iterator lpi;
1069*617e2443SMark Logan
1070*617e2443SMark Logan if (_checkListen(tcpFwdReqMsg->Address, tcpFwdReqMsg->Port, serverSocket)) {
1071*617e2443SMark Logan *status = 1;
1072*617e2443SMark Logan // Log in Event Log
1073*617e2443SMark Logan TCHAR message[1024];
1074*617e2443SMark Logan _stprintf_s(message, 1024,
1075*617e2443SMark Logan TEXT("LMS Service already accepted a request at %s:%d\n"),
1076*617e2443SMark Logan tcpFwdReqMsg->Address.c_str(),
1077*617e2443SMark Logan tcpFwdReqMsg->Port);
1078*617e2443SMark Logan _eventLog(_eventLogParam, message, EVENTLOG_ERROR_TYPE);
1079*617e2443SMark Logan PRINT(message);
1080*617e2443SMark Logan // Send Failure replay to LME
1081*617e2443SMark Logan _lme.TcpForwardReplyFailure();
1082*617e2443SMark Logan return;
1083*617e2443SMark Logan }
1084*617e2443SMark Logan
1085*617e2443SMark Logan lpi = _listenFailReported.find(tcpFwdReqMsg->Port);
1086*617e2443SMark Logan
1087*617e2443SMark Logan if (serverSocket == INVALID_SOCKET) {
1088*617e2443SMark Logan int error;
1089*617e2443SMark Logan serverSocket = _listenPort(tcpFwdReqMsg->Port, error);
1090*617e2443SMark Logan if (serverSocket == INVALID_SOCKET) {
1091*617e2443SMark Logan *status = 1;
1092*617e2443SMark Logan // Log in Event Log
1093*617e2443SMark Logan TCHAR message[1024];
1094*617e2443SMark Logan _stprintf_s(message, 1024,
1095*617e2443SMark Logan TEXT("LMS Service cannot listen at port %d.\n"),
1096*617e2443SMark Logan tcpFwdReqMsg->Port);
1097*617e2443SMark Logan if (lpi == _listenFailReported.end()) {
1098*617e2443SMark Logan _eventLog(_eventLogParam, message, EVENTLOG_ERROR_TYPE);
1099*617e2443SMark Logan _listenFailReported.insert(tcpFwdReqMsg->Port);
1100*617e2443SMark Logan }
1101*617e2443SMark Logan PRINT(message);
1102*617e2443SMark Logan // Send Failure replay to LME
1103*617e2443SMark Logan _lme.TcpForwardReplyFailure();
1104*617e2443SMark Logan failure = true;
1105*617e2443SMark Logan }
1106*617e2443SMark Logan }
1107*617e2443SMark Logan
1108*617e2443SMark Logan if (failure != true) {
1109*617e2443SMark Logan PRINT("Listening at port %d at %s interface.\n",
1110*617e2443SMark Logan tcpFwdReqMsg->Port,
1111*617e2443SMark Logan ((cb == _isLocalCallback) ? "local" : "remote"));
1112*617e2443SMark Logan
1113*617e2443SMark Logan PortForwardRequest *portForwardRequest =
1114*617e2443SMark Logan new PortForwardRequest(tcpFwdReqMsg->Address,
1115*617e2443SMark Logan tcpFwdReqMsg->Port,
1116*617e2443SMark Logan serverSocket, cb, (cb == _isLocalCallback));
1117*617e2443SMark Logan
1118*617e2443SMark Logan _openPorts[tcpFwdReqMsg->Port].push_back(portForwardRequest);
1119*617e2443SMark Logan
1120*617e2443SMark Logan // Send Success replay to LME
1121*617e2443SMark Logan _lme.TcpForwardReplySuccess(tcpFwdReqMsg->Port);
1122*617e2443SMark Logan
1123*617e2443SMark Logan portForwardRequest->SetStatus(
1124*617e2443SMark Logan (cb == _isLocalCallback) ?
1125*617e2443SMark Logan PortForwardRequest::LISTENING :
1126*617e2443SMark Logan PortForwardRequest::PENDING_REQUEST);
1127*617e2443SMark Logan if (lpi != _listenFailReported.end()) {
1128*617e2443SMark Logan _listenFailReported.erase(lpi);
1129*617e2443SMark Logan }
1130*617e2443SMark Logan
1131*617e2443SMark Logan _signalSelect();
1132*617e2443SMark Logan }
1133*617e2443SMark Logan }
1134*617e2443SMark Logan
1135*617e2443SMark Logan if (failure == true) {
1136*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_ERROR);
1137*617e2443SMark Logan Deinit();
1138*617e2443SMark Logan return;
1139*617e2443SMark Logan }
1140*617e2443SMark Logan
1141*617e2443SMark Logan if (cb == _isLocalCallback) {
1142*617e2443SMark Logan if (_listenFailReported.empty()) {
1143*617e2443SMark Logan _updateIPFQDN(tcpFwdReqMsg->Address.c_str());
1144*617e2443SMark Logan }
1145*617e2443SMark Logan }
1146*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
1147*617e2443SMark Logan else {
1148*617e2443SMark Logan _checkRemoteSupport(true);
1149*617e2443SMark Logan }
1150*617e2443SMark Logan #endif
1151*617e2443SMark Logan }
1152*617e2443SMark Logan
1153*617e2443SMark Logan void Protocol::_apfTcpForwardCancel(LMETcpForwardCancelRequestMessage *tcpFwdCnclMsg)
1154*617e2443SMark Logan {
1155*617e2443SMark Logan bool found = false;
1156*617e2443SMark Logan Lock l(_portsLock);
1157*617e2443SMark Logan
1158*617e2443SMark Logan PortMap::iterator it = _openPorts.find(tcpFwdCnclMsg->Port);
1159*617e2443SMark Logan if (it == _openPorts.end()) {
1160*617e2443SMark Logan PRINT("Previous request on address %s and port %d doesn't exist.\n",
1161*617e2443SMark Logan tcpFwdCnclMsg->Address.c_str(), tcpFwdCnclMsg->Port);
1162*617e2443SMark Logan _lme.TcpForwardCancelReplyFailure();
1163*617e2443SMark Logan return;
1164*617e2443SMark Logan }
1165*617e2443SMark Logan
1166*617e2443SMark Logan PortForwardRequestList::iterator it2 = it->second.begin();
1167*617e2443SMark Logan for (; it2 != it->second.end(); it2++) {
1168*617e2443SMark Logan if (((*it2)->GetBindedAddress().compare(tcpFwdCnclMsg->Address) == 0) &&
1169*617e2443SMark Logan //((*it2)->GetPort() == tcpFwdCnclMsg->Port)) {
1170*617e2443SMark Logan ((*it2)->GetStatus() != PortForwardRequest::NOT_ACTIVE)) {
1171*617e2443SMark Logan found = true;
1172*617e2443SMark Logan break;
1173*617e2443SMark Logan }
1174*617e2443SMark Logan }
1175*617e2443SMark Logan
1176*617e2443SMark Logan if (found) {
1177*617e2443SMark Logan (*it2)->SetStatus(PortForwardRequest::NOT_ACTIVE);
1178*617e2443SMark Logan if ((*it2)->GetChannelCount() == 0) {
1179*617e2443SMark Logan _closePortForwardRequest(*it2);
1180*617e2443SMark Logan }
1181*617e2443SMark Logan _lme.TcpForwardCancelReplySuccess();
1182*617e2443SMark Logan } else {
1183*617e2443SMark Logan PRINT("Previous request on address %s and port %d doesn't exist.\n",
1184*617e2443SMark Logan tcpFwdCnclMsg->Address.c_str(), tcpFwdCnclMsg->Port);
1185*617e2443SMark Logan _lme.TcpForwardCancelReplyFailure();
1186*617e2443SMark Logan }
1187*617e2443SMark Logan }
1188*617e2443SMark Logan
1189*617e2443SMark Logan void Protocol::_aptSendUdp(LMEUdpSendToMessage *udpSendToMessage, int *status)
1190*617e2443SMark Logan {
1191*617e2443SMark Logan int error = 0;
1192*617e2443SMark Logan
1193*617e2443SMark Logan SOCKET s = ATNetworkTool::Connect(udpSendToMessage->Address.c_str(),
1194*617e2443SMark Logan udpSendToMessage->Port, error,
1195*617e2443SMark Logan PF_INET, SOCK_DGRAM);
1196*617e2443SMark Logan if (s == INVALID_SOCKET) {
1197*617e2443SMark Logan *status = 1;
1198*617e2443SMark Logan PRINT("Unable to send UDP data.\n");
1199*617e2443SMark Logan return;
1200*617e2443SMark Logan }
1201*617e2443SMark Logan
1202*617e2443SMark Logan int count = _send(s, (char *)udpSendToMessage->Data, udpSendToMessage->DataLength, error);
1203*617e2443SMark Logan PRINT("Sent UDP data: %d bytes of %d.\n", count, udpSendToMessage->DataLength);
1204*617e2443SMark Logan
1205*617e2443SMark Logan ATNetworkTool::CloseSocket(s);
1206*617e2443SMark Logan }
1207*617e2443SMark Logan
1208*617e2443SMark Logan void Protocol::_apfProtocolVersion(LMEProtocolVersionMessage *verMsg)
1209*617e2443SMark Logan {
1210*617e2443SMark Logan Lock l(_versionLock);
1211*617e2443SMark Logan
1212*617e2443SMark Logan switch (_handshakingStatus) {
1213*617e2443SMark Logan case AGREED:
1214*617e2443SMark Logan case NOT_INITIATED:
1215*617e2443SMark Logan _lme.ProtocolVersion(MAX_PROT_VERSION);
1216*617e2443SMark Logan case INITIATED:
1217*617e2443SMark Logan if (*verMsg < MIN_PROT_VERSION) {
1218*617e2443SMark Logan PRINT("Version %d.%d is not supported.\n",
1219*617e2443SMark Logan verMsg->MajorVersion, verMsg->MinorVersion);
1220*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED);
1221*617e2443SMark Logan Deinit();
1222*617e2443SMark Logan return;
1223*617e2443SMark Logan }
1224*617e2443SMark Logan if (*verMsg > MAX_PROT_VERSION) {
1225*617e2443SMark Logan _AmtProtVersion = MAX_PROT_VERSION;
1226*617e2443SMark Logan } else {
1227*617e2443SMark Logan _AmtProtVersion = (*verMsg);
1228*617e2443SMark Logan }
1229*617e2443SMark Logan _handshakingStatus = AGREED;
1230*617e2443SMark Logan break;
1231*617e2443SMark Logan
1232*617e2443SMark Logan default:
1233*617e2443SMark Logan _lme.Disconnect(APF_DISCONNECT_BY_APPLICATION);
1234*617e2443SMark Logan Deinit();
1235*617e2443SMark Logan break;
1236*617e2443SMark Logan }
1237*617e2443SMark Logan }
1238*617e2443SMark Logan
1239*617e2443SMark Logan void Protocol::_apfChannelOpen(LMEChannelOpenRequestMessage *chOpenMsg, int *status)
1240*617e2443SMark Logan {
1241*617e2443SMark Logan int error = 0;
1242*617e2443SMark Logan
1243*617e2443SMark Logan PRINT("Got channel request from AMT. "
1244*617e2443SMark Logan " Recipient channel %d for address %s, port %d.\n",
1245*617e2443SMark Logan chOpenMsg->SenderChannel,
1246*617e2443SMark Logan chOpenMsg->Address.c_str(), chOpenMsg->Port);
1247*617e2443SMark Logan
1248*617e2443SMark Logan SOCKET s = ATNetworkTool::Connect(chOpenMsg->Address.c_str(),
1249*617e2443SMark Logan chOpenMsg->Port, error, PF_INET);
1250*617e2443SMark Logan if (s == INVALID_SOCKET) {
1251*617e2443SMark Logan *status = 1;
1252*617e2443SMark Logan PRINT("Unable to open direct channel to address %s.\n",
1253*617e2443SMark Logan chOpenMsg->Address.c_str());
1254*617e2443SMark Logan return;
1255*617e2443SMark Logan }
1256*617e2443SMark Logan
1257*617e2443SMark Logan ATNetworkTool::SetNonBlocking(s);
1258*617e2443SMark Logan
1259*617e2443SMark Logan Channel *c = new Channel(NULL, s);
1260*617e2443SMark Logan c->AddBytesTxWindow(chOpenMsg->InitialWindow);
1261*617e2443SMark Logan c->SetRecipientChannel(chOpenMsg->SenderChannel);
1262*617e2443SMark Logan c->SetStatus(Channel::OPEN);
1263*617e2443SMark Logan
1264*617e2443SMark Logan {
1265*617e2443SMark Logan Lock l(_channelsLock);
1266*617e2443SMark Logan _openChannels[c->GetSenderChannel()] = c;
1267*617e2443SMark Logan _lme.ChannelOpenReplaySuccess(c->GetRecipientChannel(), c->GetSenderChannel());
1268*617e2443SMark Logan }
1269*617e2443SMark Logan
1270*617e2443SMark Logan _signalSelect();
1271*617e2443SMark Logan }
1272*617e2443SMark Logan
1273*617e2443SMark Logan PortForwardRequest *Protocol::_closeMChannel(Channel *c)
1274*617e2443SMark Logan {
1275*617e2443SMark Logan PortForwardRequest *clPFwdReq = NULL;
1276*617e2443SMark Logan
1277*617e2443SMark Logan ATNetworkTool::CloseSocket(c->GetSocket());
1278*617e2443SMark Logan PortForwardRequest *p = c->GetPortForwardRequest();
1279*617e2443SMark Logan if ((p != NULL) && (p->DecreaseChannelCount() == 0)) {
1280*617e2443SMark Logan clPFwdReq = p;
1281*617e2443SMark Logan }
1282*617e2443SMark Logan delete c;
1283*617e2443SMark Logan
1284*617e2443SMark Logan return clPFwdReq;
1285*617e2443SMark Logan }
1286*617e2443SMark Logan
1287*617e2443SMark Logan PortForwardRequest *Protocol::_apfChannelOFail(LMEChannelOpenReplayFailureMessage *chFailMsg)
1288*617e2443SMark Logan {
1289*617e2443SMark Logan PortForwardRequest *clPFwdReq = NULL;
1290*617e2443SMark Logan
1291*617e2443SMark Logan Lock l(_channelsLock);
1292*617e2443SMark Logan
1293*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(chFailMsg->RecipientChannel);
1294*617e2443SMark Logan if (it != _openChannels.end()) {
1295*617e2443SMark Logan clPFwdReq = _closeMChannel(it->second);
1296*617e2443SMark Logan _openChannels.erase(it);
1297*617e2443SMark Logan PRINT("Channel open request was refused. Reason code: 0x%02x reason.\n",
1298*617e2443SMark Logan chFailMsg->ReasonCode);
1299*617e2443SMark Logan }
1300*617e2443SMark Logan
1301*617e2443SMark Logan return clPFwdReq;
1302*617e2443SMark Logan }
1303*617e2443SMark Logan
1304*617e2443SMark Logan PortForwardRequest *Protocol::_apfChannelClose(LMEChannelCloseMessage *chClMsg)
1305*617e2443SMark Logan {
1306*617e2443SMark Logan PortForwardRequest *clPFwdReq = NULL;
1307*617e2443SMark Logan
1308*617e2443SMark Logan Lock l(_channelsLock);
1309*617e2443SMark Logan
1310*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(chClMsg->RecipientChannel);
1311*617e2443SMark Logan if (it != _openChannels.end()) {
1312*617e2443SMark Logan Channel *c = it->second;
1313*617e2443SMark Logan switch(c->GetStatus()) {
1314*617e2443SMark Logan case Channel::OPEN:
1315*617e2443SMark Logan c->SetStatus(Channel::CLOSED);
1316*617e2443SMark Logan _lme.ChannelClose(c->GetRecipientChannel());
1317*617e2443SMark Logan PRINT("Channel %d was closed by AMT.\n", c->GetSenderChannel());
1318*617e2443SMark Logan break;
1319*617e2443SMark Logan
1320*617e2443SMark Logan case Channel::WAITING_CLOSE:
1321*617e2443SMark Logan PRINT("Received reply by AMT on closing channel %d.\n", c->GetSenderChannel());
1322*617e2443SMark Logan break;
1323*617e2443SMark Logan
1324*617e2443SMark Logan case Channel::CLOSED:
1325*617e2443SMark Logan case Channel::NOT_OPENED:
1326*617e2443SMark Logan break;
1327*617e2443SMark Logan }
1328*617e2443SMark Logan
1329*617e2443SMark Logan clPFwdReq = _closeMChannel(c);
1330*617e2443SMark Logan _openChannels.erase(it);
1331*617e2443SMark Logan }
1332*617e2443SMark Logan
1333*617e2443SMark Logan return clPFwdReq;
1334*617e2443SMark Logan }
1335*617e2443SMark Logan
1336*617e2443SMark Logan PortForwardRequest *Protocol::_apfChannelData(LMEChannelDataMessage *chDMsg, int *status)
1337*617e2443SMark Logan {
1338*617e2443SMark Logan PortForwardRequest *clPFwdReq = NULL;
1339*617e2443SMark Logan
1340*617e2443SMark Logan do {
1341*617e2443SMark Logan Lock l(_channelsLock);
1342*617e2443SMark Logan
1343*617e2443SMark Logan ChannelMap::iterator it = _openChannels.find(chDMsg->RecipientChannel);
1344*617e2443SMark Logan if (it == _openChannels.end()) {
1345*617e2443SMark Logan break;
1346*617e2443SMark Logan }
1347*617e2443SMark Logan
1348*617e2443SMark Logan if ((it->second->GetStatus() != Channel::OPEN) &&
1349*617e2443SMark Logan (it->second->GetStatus() != Channel::WAITING_CLOSE)) {
1350*617e2443SMark Logan break;
1351*617e2443SMark Logan }
1352*617e2443SMark Logan
1353*617e2443SMark Logan if (it->second->GetRxWindow() < chDMsg->DataLength) {
1354*617e2443SMark Logan break;
1355*617e2443SMark Logan }
1356*617e2443SMark Logan
1357*617e2443SMark Logan int senderr = 0;
1358*617e2443SMark Logan int count = _send(it->second->GetSocket(), (char *)chDMsg->Data,
1359*617e2443SMark Logan chDMsg->DataLength, senderr);
1360*617e2443SMark Logan PRINT("Sent %d bytes of %d from AMT to channel %d with socket %d.\n",
1361*617e2443SMark Logan count, chDMsg->DataLength, chDMsg->RecipientChannel,
1362*617e2443SMark Logan it->second->GetSocket());
1363*617e2443SMark Logan
1364*617e2443SMark Logan if ((count == -1) && (senderr == EPIPE)) {
1365*617e2443SMark Logan *status = 1;
1366*617e2443SMark Logan clPFwdReq = _closeMChannel(it->second);
1367*617e2443SMark Logan _openChannels.erase(it);
1368*617e2443SMark Logan PRINT("Channel send data request was refused. Broken pipe.\n");
1369*617e2443SMark Logan break;
1370*617e2443SMark Logan }
1371*617e2443SMark Logan //it->second->AddBytesRxWindow(-count);
1372*617e2443SMark Logan //if (it->second->GetRxWindow() < Channel::LMS_WINDOW_SIZE / 2) {
1373*617e2443SMark Logan _lme.ChannelWindowAdjust(it->second->GetRecipientChannel(), chDMsg->DataLength);
1374*617e2443SMark Logan //Channel::LMS_WINDOW_SIZE - it->second->GetRxWindow());
1375*617e2443SMark Logan //}
1376*617e2443SMark Logan } while (0);
1377*617e2443SMark Logan
1378*617e2443SMark Logan return clPFwdReq;
1379*617e2443SMark Logan }
1380*617e2443SMark Logan
1381*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
1382*617e2443SMark Logan
1383*617e2443SMark Logan bool Protocol::_compareDNSSuffix(std::string AMTDNSSuffix, std::string suffix)
1384*617e2443SMark Logan {
1385*617e2443SMark Logan if (AMTDNSSuffix.size() > suffix.size()) {
1386*617e2443SMark Logan return false;
1387*617e2443SMark Logan }
1388*617e2443SMark Logan
1389*617e2443SMark Logan if ((AMTDNSSuffix.size() < suffix.size()) &&
1390*617e2443SMark Logan (suffix[suffix.size()-AMTDNSSuffix.size()-1] != '.')) {
1391*617e2443SMark Logan return false;
1392*617e2443SMark Logan }
1393*617e2443SMark Logan
1394*617e2443SMark Logan if (strnicmp(suffix.c_str() + suffix.size()-AMTDNSSuffix.size(),
1395*617e2443SMark Logan AMTDNSSuffix.c_str(),
1396*617e2443SMark Logan AMTDNSSuffix.size()) == 0) {
1397*617e2443SMark Logan return true;
1398*617e2443SMark Logan }
1399*617e2443SMark Logan
1400*617e2443SMark Logan return false;
1401*617e2443SMark Logan }
1402*617e2443SMark Logan
1403*617e2443SMark Logan bool Protocol::_checkRemoteSupport(bool requestDnsFromAmt)
1404*617e2443SMark Logan {
1405*617e2443SMark Logan if (requestDnsFromAmt) {
1406*617e2443SMark Logan std::list<std::string> amtDnsSuffixes;
1407*617e2443SMark Logan
1408*617e2443SMark Logan AMT_STATUS status = _cfg.RequestEntDNSSuffixList(amtDnsSuffixes);
1409*617e2443SMark Logan
1410*617e2443SMark Logan if (status != AMT_STATUS_SUCCESS) {
1411*617e2443SMark Logan PRINT("Remote access is disabled - AMT is not configured [%x]\n", status);
1412*617e2443SMark Logan return false;
1413*617e2443SMark Logan }
1414*617e2443SMark Logan
1415*617e2443SMark Logan _AMTDNSLock.acquire();
1416*617e2443SMark Logan _AMTDNSSuffixes.clear();
1417*617e2443SMark Logan _AMTDNSSuffixes.assign(amtDnsSuffixes.begin(), amtDnsSuffixes.end());
1418*617e2443SMark Logan _AMTDNSLock.release();
1419*617e2443SMark Logan
1420*617e2443SMark Logan amtDnsSuffixes.clear();
1421*617e2443SMark Logan }
1422*617e2443SMark Logan
1423*617e2443SMark Logan ATDomainMap domains;
1424*617e2443SMark Logan int error = 0;
1425*617e2443SMark Logan ATNetworkTool::GetLocalNetDomains(domains, error, PF_INET);
1426*617e2443SMark Logan _updateEnterpriseAccessStatus(domains);
1427*617e2443SMark Logan
1428*617e2443SMark Logan return true;
1429*617e2443SMark Logan }
1430*617e2443SMark Logan
1431*617e2443SMark Logan void Protocol::_updateEnterpriseAccessStatus(const ATDomainMap &localDNSSuffixes)
1432*617e2443SMark Logan {
1433*617e2443SMark Logan _AMTDNSLock.acquire();
1434*617e2443SMark Logan
1435*617e2443SMark Logan std::list<std::string>::iterator remIt;
1436*617e2443SMark Logan std::list<std::string>::iterator startIt = _AMTDNSSuffixes.begin();
1437*617e2443SMark Logan std::list<std::string>::iterator endIt = _AMTDNSSuffixes.end();
1438*617e2443SMark Logan ATDomainMap::const_iterator locIt;
1439*617e2443SMark Logan
1440*617e2443SMark Logan bool access = false;
1441*617e2443SMark Logan ATAddress localIp;
1442*617e2443SMark Logan
1443*617e2443SMark Logan for (locIt = localDNSSuffixes.begin(); locIt != localDNSSuffixes.end(); locIt++) {
1444*617e2443SMark Logan remIt = find_if(startIt, endIt, bind2nd(ptr_fun(_compareDNSSuffix), locIt->second));
1445*617e2443SMark Logan if (remIt != _AMTDNSSuffixes.end()) {
1446*617e2443SMark Logan access = true;
1447*617e2443SMark Logan localIp = locIt->first;
1448*617e2443SMark Logan break;
1449*617e2443SMark Logan }
1450*617e2443SMark Logan }
1451*617e2443SMark Logan
1452*617e2443SMark Logan _AMTDNSLock.release();
1453*617e2443SMark Logan
1454*617e2443SMark Logan bool sendEntAccessMessage = true;
1455*617e2443SMark Logan if (access) {
1456*617e2443SMark Logan Lock l(_portsLock);
1457*617e2443SMark Logan for (PortMap::iterator it = _openPorts.begin(); it != _openPorts.end(); it++) {
1458*617e2443SMark Logan for (PortForwardRequestList::iterator it2 = it->second.begin();
1459*617e2443SMark Logan it2 != it->second.end(); it2++) {
1460*617e2443SMark Logan
1461*617e2443SMark Logan if ((*it2)->GetStatus() == PortForwardRequest::PENDING_REQUEST) {
1462*617e2443SMark Logan (*it2)->SetStatus(PortForwardRequest::LISTENING);
1463*617e2443SMark Logan sendEntAccessMessage = false;
1464*617e2443SMark Logan break; // Assuming that there is a such request one per port
1465*617e2443SMark Logan }
1466*617e2443SMark Logan }
1467*617e2443SMark Logan }
1468*617e2443SMark Logan
1469*617e2443SMark Logan _signalSelect();
1470*617e2443SMark Logan }
1471*617e2443SMark Logan
1472*617e2443SMark Logan if (sendEntAccessMessage == false) {
1473*617e2443SMark Logan return;
1474*617e2443SMark Logan }
1475*617e2443SMark Logan
1476*617e2443SMark Logan AMT_STATUS status = _cfg.SendEnterpriseAccess(access, localIp);
1477*617e2443SMark Logan
1478*617e2443SMark Logan Lock l(_remoteAccessLock);
1479*617e2443SMark Logan _remoteAccessEnabled = (status == AMT_STATUS_SUCCESS);
1480*617e2443SMark Logan switch (status) {
1481*617e2443SMark Logan case AMT_STATUS_SUCCESS:
1482*617e2443SMark Logan PRINT("Remote access is allowed.\n");
1483*617e2443SMark Logan break;
1484*617e2443SMark Logan case AMT_STATUS_REMOTE_ACCESS_NOT_GRANTED:
1485*617e2443SMark Logan PRINT("Remote access is denied because AMT is directly connected "
1486*617e2443SMark Logan "to enterprise network.\n");
1487*617e2443SMark Logan break;
1488*617e2443SMark Logan case AMT_STATUS_REMOTE_ACCESS_HOST_VPN_IS_DISABLED:
1489*617e2443SMark Logan PRINT("Remote access is disabled.\n");
1490*617e2443SMark Logan break;
1491*617e2443SMark Logan default:
1492*617e2443SMark Logan PRINT("Remote access is disabled.\n");
1493*617e2443SMark Logan break;
1494*617e2443SMark Logan }
1495*617e2443SMark Logan
1496*617e2443SMark Logan //if (_remoteAccessEnabled) {
1497*617e2443SMark Logan // Lock l(_portsLock);
1498*617e2443SMark Logan // for (PortMap::iterator it = _openPorts.begin(); it != _openPorts.end(); it++) {
1499*617e2443SMark Logan // for (PortForwardRequestList::iterator it2 = it->second.begin();
1500*617e2443SMark Logan // it2 != it->second.end(); it2++) {
1501*617e2443SMark Logan
1502*617e2443SMark Logan // if ((*it2)->GetStatus() == PortForwardRequest::PENDING_REQUEST) {
1503*617e2443SMark Logan // (*it2)->SetStatus(PortForwardRequest::LISTENING);
1504*617e2443SMark Logan // break; // Assuming that there is a such request one per port
1505*617e2443SMark Logan // }
1506*617e2443SMark Logan // }
1507*617e2443SMark Logan // }
1508*617e2443SMark Logan
1509*617e2443SMark Logan // _signalSelect();
1510*617e2443SMark Logan //}
1511*617e2443SMark Logan
1512*617e2443SMark Logan }
1513*617e2443SMark Logan
1514*617e2443SMark Logan #endif
1515*617e2443SMark Logan
1516*617e2443SMark Logan int Protocol::_isLocalCallback(void *const param, SOCKET s)
1517*617e2443SMark Logan {
1518*617e2443SMark Logan int error = 0;
1519*617e2443SMark Logan
1520*617e2443SMark Logan return ((1 == ATNetworkTool::IsSockPeerLocal(s, error, PF_INET)) ? 1 : -1);
1521*617e2443SMark Logan }
1522*617e2443SMark Logan
1523*617e2443SMark Logan #ifdef _REMOTE_SUPPORT
1524*617e2443SMark Logan
1525*617e2443SMark Logan int Protocol::_isRemoteCallback(void *const param, SOCKET s)
1526*617e2443SMark Logan {
1527*617e2443SMark Logan Protocol *prot = (Protocol *)param;
1528*617e2443SMark Logan
1529*617e2443SMark Logan return prot->_isRemote(s);
1530*617e2443SMark Logan }
1531*617e2443SMark Logan
1532*617e2443SMark Logan int Protocol::_isRemote(SOCKET s) const
1533*617e2443SMark Logan {
1534*617e2443SMark Logan int result = 0;
1535*617e2443SMark Logan int error = 0;
1536*617e2443SMark Logan int ret;
1537*617e2443SMark Logan std::string dnsSuffix;
1538*617e2443SMark Logan
1539*617e2443SMark Logan ret = ATNetworkTool::GetSockDomain(s, dnsSuffix, error);
1540*617e2443SMark Logan if (ret != 1) {
1541*617e2443SMark Logan return ret;
1542*617e2443SMark Logan }
1543*617e2443SMark Logan
1544*617e2443SMark Logan Lock l(_remoteAccessLock);
1545*617e2443SMark Logan
1546*617e2443SMark Logan if (_remoteAccessEnabled) {
1547*617e2443SMark Logan
1548*617e2443SMark Logan _AMTDNSLock.acquire();
1549*617e2443SMark Logan
1550*617e2443SMark Logan std::list<std::string>::const_iterator it = _AMTDNSSuffixes.begin();
1551*617e2443SMark Logan for (; it != _AMTDNSSuffixes.end(); it++) {
1552*617e2443SMark Logan if (_compareDNSSuffix(*it, dnsSuffix)) {
1553*617e2443SMark Logan result = 1;
1554*617e2443SMark Logan break;
1555*617e2443SMark Logan }
1556*617e2443SMark Logan }
1557*617e2443SMark Logan
1558*617e2443SMark Logan _AMTDNSLock.release();
1559*617e2443SMark Logan }
1560*617e2443SMark Logan
1561*617e2443SMark Logan return result;
1562*617e2443SMark Logan }
1563*617e2443SMark Logan #endif
1564*617e2443SMark Logan
1565*617e2443SMark Logan int Protocol::_updateIPFQDN(const char *fqdn)
1566*617e2443SMark Logan {
1567*617e2443SMark Logan if (strcmp(fqdn, _AMTFQDN) != 0) {
1568*617e2443SMark Logan char localName[FQDN_MAX_SIZE] = "\0";
1569*617e2443SMark Logan int res = gethostname(localName, sizeof(localName));
1570*617e2443SMark Logan
1571*617e2443SMark Logan // If AMT FQDN is equal to local FQDN than we don't do anything
1572*617e2443SMark Logan if ((res == -1) || (strcmp(fqdn, localName) != 0)) {
1573*617e2443SMark Logan if (_handleFQDNChange(fqdn) < 0) {
1574*617e2443SMark Logan ERROR("Error: failed to update FQDN info\n");
1575*617e2443SMark Logan return -1;
1576*617e2443SMark Logan }
1577*617e2443SMark Logan } else {
1578*617e2443SMark Logan if (_handleFQDNChange("") < 0) {
1579*617e2443SMark Logan ERROR("Error: failed to update FQDN info\n");
1580*617e2443SMark Logan return -1;
1581*617e2443SMark Logan }
1582*617e2443SMark Logan }
1583*617e2443SMark Logan }
1584*617e2443SMark Logan
1585*617e2443SMark Logan memcpy(_AMTFQDN, fqdn, sizeof(_AMTFQDN));
1586*617e2443SMark Logan
1587*617e2443SMark Logan PRINT("Got FQDN: %s\n", _AMTFQDN);
1588*617e2443SMark Logan
1589*617e2443SMark Logan return 0;
1590*617e2443SMark Logan }
1591*617e2443SMark Logan
1592*617e2443SMark Logan
1593*617e2443SMark Logan char *Protocol::_getErrMsg(DWORD err)
1594*617e2443SMark Logan {
1595*617e2443SMark Logan static char buffer[1024];
1596*617e2443SMark Logan
1597*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
1598*617e2443SMark Logan strerror_r(err, buffer, sizeof(buffer) - 1);
1599*617e2443SMark Logan #else
1600*617e2443SMark Logan FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
1601*617e2443SMark Logan NULL,
1602*617e2443SMark Logan err,
1603*617e2443SMark Logan 0,
1604*617e2443SMark Logan buffer,
1605*617e2443SMark Logan sizeof(buffer) - 1,
1606*617e2443SMark Logan 0);
1607*617e2443SMark Logan #endif // __sun || _LINUX
1608*617e2443SMark Logan
1609*617e2443SMark Logan return buffer;
1610*617e2443SMark Logan }
1611*617e2443SMark Logan
1612*617e2443SMark Logan
1613*617e2443SMark Logan int Protocol::_handleFQDNChange(const char *fqdn)
1614*617e2443SMark Logan {
1615*617e2443SMark Logan const char *hostFile = "hosts";
1616*617e2443SMark Logan const char *tmpFile = "hosts-lms.tmp";
1617*617e2443SMark Logan bool hasFqdn = false;
1618*617e2443SMark Logan #define LMS_MAX_FILENAME_LEN 1024
1619*617e2443SMark Logan char inFileName[LMS_MAX_FILENAME_LEN] = "";
1620*617e2443SMark Logan char oldFqdn[FQDN_MAX_SIZE + 1];
1621*617e2443SMark Logan char outFileName[LMS_MAX_FILENAME_LEN] = "";
1622*617e2443SMark Logan char host[FQDN_MAX_SIZE + 1];
1623*617e2443SMark Logan #define LMS_MAX_LINE_LEN 1023
1624*617e2443SMark Logan char line[LMS_MAX_LINE_LEN + 1];
1625*617e2443SMark Logan #define LMS_LINE_SIG_FIRST_WORDS "# LMS GENERATED "
1626*617e2443SMark Logan #define LMS_LINE_SIG_LAST_WORD "LINE"
1627*617e2443SMark Logan #define LMS_LINE_SIG_LAST_WORD_LEN 4
1628*617e2443SMark Logan #define LMS_LINE_SIG LMS_LINE_SIG_FIRST_WORDS LMS_LINE_SIG_LAST_WORD
1629*617e2443SMark Logan #define lmsstr(s) lmsname(s)
1630*617e2443SMark Logan #define lmsname(s) #s
1631*617e2443SMark Logan #define LMS_LINE_FORMAT "127.0.0.1 %s %s " LMS_LINE_SIG
1632*617e2443SMark Logan #define LMS_LINE_SCAN_FORMAT "127.0.0.1 %" lmsstr(FQDN_MAX_SIZE) "s %" lmsstr(FQDN_MAX_SIZE) "s " LMS_LINE_SIG_FIRST_WORDS "%" lmsstr(LMS_LINE_SIG_LAST_WORD_LEN) "c"
1633*617e2443SMark Logan char tmpsige[LMS_LINE_SIG_LAST_WORD_LEN];
1634*617e2443SMark Logan
1635*617e2443SMark Logan #if defined(__sun) || defined(_LINUX)
1636*617e2443SMark Logan
1637*617e2443SMark Logan const char *dir = "/etc/";
1638*617e2443SMark Logan
1639*617e2443SMark Logan #else
1640*617e2443SMark Logan
1641*617e2443SMark Logan char *sysDrive;
1642*617e2443SMark Logan const char *dir = "\\system32\\drivers\\etc\\";
1643*617e2443SMark Logan
1644*617e2443SMark Logan sysDrive = getenv("SystemRoot");
1645*617e2443SMark Logan if (NULL == sysDrive) {
1646*617e2443SMark Logan return -1;
1647*617e2443SMark Logan }
1648*617e2443SMark Logan
1649*617e2443SMark Logan // sanity check before string copying
1650*617e2443SMark Logan if (LMS_MAX_FILENAME_LEN < (strnlen(sysDrive, LMS_MAX_FILENAME_LEN)
1651*617e2443SMark Logan + strnlen(dir, LMS_MAX_FILENAME_LEN)
1652*617e2443SMark Logan + strnlen(hostFile, LMS_MAX_FILENAME_LEN) + 1)) {
1653*617e2443SMark Logan return -1;
1654*617e2443SMark Logan }
1655*617e2443SMark Logan // sanity check before string copying
1656*617e2443SMark Logan if (LMS_MAX_FILENAME_LEN < (strnlen(sysDrive, LMS_MAX_FILENAME_LEN)
1657*617e2443SMark Logan + strnlen(dir, LMS_MAX_FILENAME_LEN)
1658*617e2443SMark Logan + strnlen(tmpFile, LMS_MAX_FILENAME_LEN) + 1)) {
1659*617e2443SMark Logan return -1;
1660*617e2443SMark Logan }
1661*617e2443SMark Logan
1662*617e2443SMark Logan strncpy(inFileName, sysDrive, LMS_MAX_FILENAME_LEN - 1);
1663*617e2443SMark Logan strncpy(outFileName, sysDrive, LMS_MAX_FILENAME_LEN - 1);
1664*617e2443SMark Logan
1665*617e2443SMark Logan #endif // __sun || _LINUX
1666*617e2443SMark Logan
1667*617e2443SMark Logan strncat(inFileName, dir, LMS_MAX_FILENAME_LEN - 1);
1668*617e2443SMark Logan strncat(outFileName, dir, LMS_MAX_FILENAME_LEN - 1);
1669*617e2443SMark Logan strncat(inFileName, hostFile, LMS_MAX_FILENAME_LEN - 1);
1670*617e2443SMark Logan strncat(outFileName, tmpFile, LMS_MAX_FILENAME_LEN - 1);
1671*617e2443SMark Logan
1672*617e2443SMark Logan FILE *ifp = fopen(inFileName, "r");
1673*617e2443SMark Logan if (NULL == ifp) {
1674*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't open hosts file"), EVENTLOG_ERROR_TYPE);
1675*617e2443SMark Logan return -1;
1676*617e2443SMark Logan }
1677*617e2443SMark Logan
1678*617e2443SMark Logan FILE *ofp = fopen(outFileName, "w");
1679*617e2443SMark Logan if (NULL == ofp) {
1680*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't create temporary hosts file"), EVENTLOG_ERROR_TYPE);
1681*617e2443SMark Logan fclose(ifp);
1682*617e2443SMark Logan return -1;
1683*617e2443SMark Logan }
1684*617e2443SMark Logan
1685*617e2443SMark Logan // First create a copy of the hosts file, without lines that were
1686*617e2443SMark Logan // previously added by the LMS.
1687*617e2443SMark Logan // Go over each line and copy it to the tmp file.
1688*617e2443SMark Logan while (fgets(line, sizeof(line), ifp)) {
1689*617e2443SMark Logan // don't copy the line if it was generated by the LMS
1690*617e2443SMark Logan memset(oldFqdn, 0, sizeof(oldFqdn));
1691*617e2443SMark Logan memset(tmpsige, 0, sizeof(tmpsige));
1692*617e2443SMark Logan if (0 == (
1693*617e2443SMark Logan (3 == sscanf(line, LMS_LINE_SCAN_FORMAT, oldFqdn, host, tmpsige))
1694*617e2443SMark Logan ? strncmp(tmpsige, LMS_LINE_SIG_LAST_WORD, LMS_LINE_SIG_LAST_WORD_LEN)
1695*617e2443SMark Logan : (-2))
1696*617e2443SMark Logan ) {
1697*617e2443SMark Logan if (0 == strncmp((char *)fqdn, oldFqdn, FQDN_MAX_SIZE)) {
1698*617e2443SMark Logan // copy the old LMS line too, since it's up to date
1699*617e2443SMark Logan fprintf(ofp, "%s", line);
1700*617e2443SMark Logan hasFqdn = true;
1701*617e2443SMark Logan }
1702*617e2443SMark Logan continue;
1703*617e2443SMark Logan }
1704*617e2443SMark Logan
1705*617e2443SMark Logan fprintf(ofp, "%s", line);
1706*617e2443SMark Logan
1707*617e2443SMark Logan while ((LMS_MAX_LINE_LEN == strnlen(line, LMS_MAX_LINE_LEN))
1708*617e2443SMark Logan && ('\n' != line[LMS_MAX_LINE_LEN - 1])
1709*617e2443SMark Logan && (fgets(line, sizeof(line), ifp))) {
1710*617e2443SMark Logan fprintf(ofp, "%s", line);
1711*617e2443SMark Logan }
1712*617e2443SMark Logan }
1713*617e2443SMark Logan
1714*617e2443SMark Logan if (hasFqdn) {
1715*617e2443SMark Logan fclose(ofp);
1716*617e2443SMark Logan fclose(ifp);
1717*617e2443SMark Logan unlink(outFileName);
1718*617e2443SMark Logan return 0;
1719*617e2443SMark Logan }
1720*617e2443SMark Logan
1721*617e2443SMark Logan // If the original hosts file does not end with a new line character,
1722*617e2443SMark Logan // add a new line at the end of the new file before adding our line.
1723*617e2443SMark Logan fseek(ifp, -1, SEEK_END);
1724*617e2443SMark Logan char lastChar = fgetc(ifp);
1725*617e2443SMark Logan if ('\n' != lastChar) {
1726*617e2443SMark Logan fprintf(ofp, "\n");
1727*617e2443SMark Logan }
1728*617e2443SMark Logan
1729*617e2443SMark Logan memset(host, 0, FQDN_MAX_SIZE + 1);
1730*617e2443SMark Logan strncpy(host, fqdn, FQDN_MAX_SIZE);
1731*617e2443SMark Logan char *lmsdot = strchr(host, '.');
1732*617e2443SMark Logan if (NULL != lmsdot) {
1733*617e2443SMark Logan lmsdot[0] = '\0';
1734*617e2443SMark Logan }
1735*617e2443SMark Logan
1736*617e2443SMark Logan if ((fqdn != NULL) && (fqdn[0] != 0)) {
1737*617e2443SMark Logan // Add the specified FQDN to the end of the tmp file
1738*617e2443SMark Logan fprintf(ofp, LMS_LINE_FORMAT "\n", fqdn, host);
1739*617e2443SMark Logan }
1740*617e2443SMark Logan
1741*617e2443SMark Logan fclose(ofp);
1742*617e2443SMark Logan fclose(ifp);
1743*617e2443SMark Logan
1744*617e2443SMark Logan if (0 != std::rename(outFileName, inFileName)) {
1745*617e2443SMark Logan std::string tmp2FileName = std::string(inFileName) + ".~tmp";
1746*617e2443SMark Logan std::ifstream mfile(inFileName, std::ios_base::in);
1747*617e2443SMark Logan if (!mfile.is_open()) {
1748*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [1]"), EVENTLOG_ERROR_TYPE);
1749*617e2443SMark Logan return -1;
1750*617e2443SMark Logan }
1751*617e2443SMark Logan std::ofstream wfile(tmp2FileName.c_str(), std::ios_base::out | std::ios_base::trunc);
1752*617e2443SMark Logan if (!wfile.is_open()) {
1753*617e2443SMark Logan mfile.close();
1754*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [2]"), EVENTLOG_ERROR_TYPE);
1755*617e2443SMark Logan return -1;
1756*617e2443SMark Logan }
1757*617e2443SMark Logan wfile << mfile.rdbuf();
1758*617e2443SMark Logan if (wfile.bad()) {
1759*617e2443SMark Logan mfile.close();
1760*617e2443SMark Logan wfile.close();
1761*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [3]"), EVENTLOG_ERROR_TYPE);
1762*617e2443SMark Logan return -1;
1763*617e2443SMark Logan }
1764*617e2443SMark Logan mfile.close();
1765*617e2443SMark Logan wfile.close();
1766*617e2443SMark Logan std::ifstream sfile(outFileName, std::ios_base::in);
1767*617e2443SMark Logan if (!sfile.is_open()) {
1768*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [4]"), EVENTLOG_ERROR_TYPE);
1769*617e2443SMark Logan return -1;
1770*617e2443SMark Logan }
1771*617e2443SMark Logan std::ofstream dfile(inFileName, std::ios_base::out | std::ios_base::trunc);
1772*617e2443SMark Logan if (!dfile.is_open()) {
1773*617e2443SMark Logan sfile.close();
1774*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [5]"), EVENTLOG_ERROR_TYPE);
1775*617e2443SMark Logan return -1;
1776*617e2443SMark Logan }
1777*617e2443SMark Logan dfile << sfile.rdbuf();
1778*617e2443SMark Logan if (dfile.bad()) {
1779*617e2443SMark Logan sfile.close();
1780*617e2443SMark Logan dfile.close();
1781*617e2443SMark Logan unlink(inFileName);
1782*617e2443SMark Logan if (0 != std::rename(outFileName, inFileName)) {
1783*617e2443SMark Logan std::rename(tmp2FileName.c_str(), inFileName);
1784*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("Error: Can't update hosts file [6]"), EVENTLOG_ERROR_TYPE);
1785*617e2443SMark Logan return -1;
1786*617e2443SMark Logan }
1787*617e2443SMark Logan }
1788*617e2443SMark Logan sfile.close();
1789*617e2443SMark Logan dfile.close();
1790*617e2443SMark Logan }
1791*617e2443SMark Logan
1792*617e2443SMark Logan _eventLog(_eventLogParam, TEXT("hosts file updated"), EVENTLOG_INFORMATION_TYPE);
1793*617e2443SMark Logan
1794*617e2443SMark Logan return 0;
1795*617e2443SMark Logan }
1796*617e2443SMark Logan
1797*617e2443SMark Logan ssize_t Protocol::_send(int s, const void *buf, size_t len, int &senderr)
1798*617e2443SMark Logan {
1799*617e2443SMark Logan ssize_t result;
1800*617e2443SMark Logan
1801*617e2443SMark Logan #if defined(_LINUX)
1802*617e2443SMark Logan if (-1 == (result = send(s, buf, len, MSG_NOSIGNAL))) {
1803*617e2443SMark Logan senderr = errno;
1804*617e2443SMark Logan }
1805*617e2443SMark Logan #elif defined(__sun)
1806*617e2443SMark Logan if (-1 == (result = send(s, buf, len, 0))) {
1807*617e2443SMark Logan senderr = errno;
1808*617e2443SMark Logan }
1809*617e2443SMark Logan #else
1810*617e2443SMark Logan result = send(s, buf, len);
1811*617e2443SMark Logan #endif // _LINUX
1812*617e2443SMark Logan
1813*617e2443SMark Logan return result;
1814*617e2443SMark Logan }
1815*617e2443SMark Logan
1816