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