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