xref: /titanic_41/usr/src/cmd/lms/Protocol.cpp (revision 617e2443dfc17fe44fd44c0675d6aad2ffc9df42)
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