Exemplo n.º 1
0
NTSTATUS 
DraidListenConnection(
	PDRAID_LISTEN_CONTEXT ListenContext
) {
	NTSTATUS status;
//	KIRQL	oldIrql;
	
	KeClearEvent(&ListenContext->TdiListenContext.CompletionEvent);
	
	status = LpxTdiOpenConnection(
			&ListenContext->ListenFileHandle,
			&ListenContext->ListenFileObject,
			NULL);

	if(!NT_SUCCESS(status)) 
	{
		ASSERT(FALSE);// This should not happen
		return status;
	}

	// 3. Associate address
	status = LpxTdiAssociateAddress(
			ListenContext->ListenFileObject,
			ListenContext->AddressFileHandle
			);

	if(!NT_SUCCESS(status)) 
	{
		ASSERT(FALSE);
		LpxTdiCloseConnection(ListenContext->ListenFileHandle, ListenContext->ListenFileObject);
		return status;
	}

	// 4. Start listening

	ListenContext->Flags = TDI_QUERY_ACCEPT; //???

	status = LpxTdiListenWithCompletionEvent(
					ListenContext->ListenFileObject,
					&ListenContext->TdiListenContext,
					&ListenContext->Flags
				);
	if(!NT_SUCCESS(status)) {
		ASSERT(FALSE); // May be this can be happen if multiple instances of this function is called with same address
		LpxTdiDisassociateAddress(ListenContext->ListenFileObject);
		LpxTdiCloseConnection(ListenContext->ListenFileHandle, ListenContext->ListenFileObject);
		return status;
	}
	return status;
}
Exemplo n.º 2
0
NTSTATUS 
DraidStopListenAddress(
	PDRAID_GLOBALS DraidGlobals,
	PDRAID_LISTEN_CONTEXT ListenContext
) {
	UNREFERENCED_PARAMETER(DraidGlobals);
	
	KDPrintM(DBG_LURN_INFO, ("Stop listening to address %02x:%02x:%02x:%02x:%02x:%02x\n",
		ListenContext->Addr.Node[0], ListenContext->Addr.Node[1], ListenContext->Addr.Node[2],
		ListenContext->Addr.Node[3], ListenContext->Addr.Node[4], ListenContext->Addr.Node[5]
	));
	if (ListenContext->ListenFileObject)
		LpxTdiDisconnect(ListenContext->ListenFileObject, 0);
	if (ListenContext->ListenFileObject)
		LpxTdiDisassociateAddress(ListenContext->ListenFileObject);
	if (ListenContext->ListenFileHandle && ListenContext->ListenFileObject) {
		LpxTdiCloseConnection(
			ListenContext->ListenFileHandle, 
			ListenContext->ListenFileObject
		);
	}
	if (ListenContext->AddressFileHandle && ListenContext->AddressFileObject) {
		LpxTdiCloseAddress (
			ListenContext->AddressFileHandle,
			ListenContext->AddressFileObject
		);
	}
	ExFreePoolWithTag(ListenContext, DRAID_LISTEN_CONTEXT_POOL_TAG);
	
	return STATUS_SUCCESS;
}
Exemplo n.º 3
0
//
// To clean up terminated PrimarySession is performed here
//
VOID
Primary_AcceptConnection(
	IN PPRIMARY			Primary,
	IN HANDLE			ListenFileHandle,
	IN PFILE_OBJECT		ListenFileObject,
	IN  ULONG			ListenSocketIndex,
	IN PLPX_ADDRESS		RemoteAddress
	)
{
    PLIST_ENTRY				listEntry;
	PPRIMARY_SESSION		newPrimarySession;
	KIRQL					oldIrql;



	newPrimarySession = PrimarySession_Create(
							Primary, 
							ListenFileHandle, 
							ListenFileObject,
							ListenSocketIndex,
							RemoteAddress
					);

	if(newPrimarySession == NULL)
	{	
		LpxTdiDisconnect(ListenFileObject, 0);
		LpxTdiDisassociateAddress(ListenFileObject);
		LpxTdiCloseConnection(
					ListenFileHandle, 
					ListenFileObject
					);
	}

		
	KeAcquireSpinLock(&Primary->SpinLock, &oldIrql);

	listEntry = Primary->PrimarySessionQueue[ListenSocketIndex].Flink;
	while(listEntry != &Primary->PrimarySessionQueue[ListenSocketIndex])
	{
		PPRIMARY_SESSION primarySession;
	

		primarySession = CONTAINING_RECORD (listEntry, PRIMARY_SESSION, ListEntry);			
		listEntry = listEntry->Flink;

		if(primarySession->ThreadFlags & PRIMARY_SESSION_THREAD_TERMINATED
			|| primarySession->State == SESSION_CLOSED)
	{
			KeReleaseSpinLock(&Primary->SpinLock, oldIrql);
			PrimarySession_Close(primarySession);
			KeAcquireSpinLock(&Primary->SpinLock, &oldIrql);
		}
	}

	KeReleaseSpinLock(&Primary->SpinLock, oldIrql);

	return;
}
Exemplo n.º 4
0
NTSTATUS
MakeConnectionObject(
    HANDLE			AddressFileHandle,
    PFILE_OBJECT	AddressFileObject,
	HANDLE			*ListenFileHandle,
	PFILE_OBJECT	*ListenFileObject
)
{
	HANDLE			listenFileHandle;
	PFILE_OBJECT	listenFileObject;
	NTSTATUS		ntStatus;


	UNREFERENCED_PARAMETER(AddressFileObject);

	ntStatus = LpxTdiOpenConnection(
					&listenFileHandle,
					&listenFileObject,
					NULL
					);

	if(!NT_SUCCESS(ntStatus)) 
	{
		ASSERT(LPX_BUG);

		*ListenFileHandle = NULL;
		*ListenFileObject = NULL;
		
		return ntStatus;
	}

	ntStatus = LpxTdiAssociateAddress(
					listenFileObject,
					AddressFileHandle
					);

	if(!NT_SUCCESS(ntStatus)) 
	{
		ASSERT(LPX_BUG);

		LpxTdiCloseConnection(listenFileHandle, listenFileObject);

		*ListenFileHandle = NULL;
		*ListenFileObject = NULL;
		
		return ntStatus;
	}

	*ListenFileHandle = listenFileHandle;
	*ListenFileObject = listenFileObject;

	return ntStatus;
}
Exemplo n.º 5
0
static
VOID
PrimaryAgentNICDisabled(
		PPRIMARY	Primary,
		PSOCKETLPX_ADDRESS_LIST AddressList
	) {

	LONG		idx_listen;
	LONG		idx_disabled;
	BOOLEAN		found;

	for(idx_disabled = 0; idx_disabled < AddressList->iAddressCount; idx_disabled ++ ) {

		found = FALSE;
		for(idx_listen = 0; idx_listen < MAX_SOCKETLPX_INTERFACE; idx_listen ++) {
			//
			//	find the match
			//
			if(Primary->Agent.ListenSocket[idx_listen].Active &&
				RtlCompareMemory(
					AddressList->SocketLpx[idx_disabled].LpxAddress.Node,
					Primary->Agent.ListenSocket[idx_listen].NICAddress.Node,
					ETHER_ADDR_LENGTH
					) == ETHER_ADDR_LENGTH ) {

				found = TRUE;
				break;
			}
		}

		//
		//	delete disabled one if found.
		//
		if(found) {
			PPRIMARY_LISTEN_SOCKET	listenSock = Primary->Agent.ListenSocket + idx_listen;

			listenSock->Active = FALSE;

			LpxTdiDisassociateAddress(listenSock->ListenFileObject);
			LpxTdiCloseConnection(listenSock->ListenFileHandle, listenSock->ListenFileObject);
			LpxTdiCloseAddress (listenSock->AddressFileHandle, listenSock->AddressFileObject);
			
			Primary->Agent.ActiveListenSocketCount --;

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					("PrimaryAgentNICEnabled: A NIC deleted..\n"));
		}
	}
}
Exemplo n.º 6
0
VOID
CloseListenSockets(
	IN 	PPRIMARY	Primary,
	IN  BOOLEAN		OnlyConnection
	)
{
	ULONG	i;

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("CloseListenSockets: Entered\n"));

	for(i=0; i < MAX_SOCKETLPX_INTERFACE; i++)
	{
		if(Primary->Agent.ListenSocket[i].Active != TRUE)
			continue;

		ASSERT(Primary->Agent.ListenSocket[i].AddressFileObject != NULL);
		ASSERT(Primary->Agent.ListenSocket[i].ListenFileObject != NULL);

		LpxTdiDisconnect(Primary->Agent.ListenSocket[i].ListenFileObject, 0);
		LpxTdiDisassociateAddress(Primary->Agent.ListenSocket[i].ListenFileObject);
		LpxTdiCloseConnection(
					Primary->Agent.ListenSocket[i].ListenFileHandle, 
					Primary->Agent.ListenSocket[i].ListenFileObject
					);
		
		if(OnlyConnection == FALSE)
		{
			LpxTdiCloseAddress (
				Primary->Agent.ListenSocket[i].AddressFileHandle,
				Primary->Agent.ListenSocket[i].AddressFileObject
				);

			Primary->Agent.ListenSocket[i].AddressFileObject = NULL;
			Primary->Agent.ListenSocket[i].AddressFileHandle = NULL;

			Primary->Agent.ListenSocket[i].Active = FALSE;		
			Primary->Agent.ActiveListenSocketCount --;
		}

	}

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("CloseListenSockets: Returned\n"));

	return;
}
Exemplo n.º 7
0
static
NTSTATUS
PrimaryOpenOneListenSocket(
		PPRIMARY_LISTEN_SOCKET	listenSock,
		PLPX_ADDRESS			NICAddr
	) {
	NTSTATUS	ntStatus;
	HANDLE					addressFileHandle = NULL;
	PFILE_OBJECT			addressFileObject = NULL;
	HANDLE					listenFileHandle = NULL;
	PFILE_OBJECT			listenFileObject = NULL;
	

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryOpenOneSocket: Entered\n"));

	listenSock->Active = FALSE;
	RtlCopyMemory(
			listenSock->NICAddress.Node,
			NICAddr->Node,
			ETHER_ADDR_LENGTH
		);

	//
	//	open a address.
	//
	ntStatus = LpxTdiOpenAddress(
						&addressFileHandle,
						&addressFileObject,
						NICAddr
					);

	if(!NT_SUCCESS(ntStatus)) 
	{
		ASSERT(LPX_BUG);
		return ntStatus;
	}

	listenSock->Active = TRUE;

	KeClearEvent(
			&listenSock->TdiListenContext.CompletionEvent
		);

	listenSock->AddressFileHandle = addressFileHandle;
	listenSock->AddressFileObject = addressFileObject;
		
	ntStatus = MakeConnectionObject(addressFileHandle, addressFileObject, &listenFileHandle, &listenFileObject);
	
	if(!NT_SUCCESS(ntStatus)) 
		{
			ASSERT(LPX_BUG);
			LpxTdiCloseAddress (addressFileHandle, addressFileObject);

			listenSock->Active = FALSE;
	
			return STATUS_UNSUCCESSFUL;
		}

	listenSock->ListenFileHandle = listenFileHandle;
	listenSock->ListenFileObject = listenFileObject;
		
	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				( "PrimaryOpenOneListenSocket: opened a address:'%02X:%02X:%02X:%02X:%02X:%02X 0x%04X'\n",
					NICAddr->Node[0],NICAddr->Node[1],NICAddr->Node[2],
					NICAddr->Node[3],NICAddr->Node[4],NICAddr->Node[5],
					NTOHS(NICAddr->Port)
			) );

	listenSock->Flags	= TDI_QUERY_ACCEPT;

	ntStatus = LpxTdiListenWithCompletionEvent(
					listenSock->ListenFileObject,
					&listenSock->TdiListenContext,
					&listenSock->Flags
				);

	if(!NT_SUCCESS(ntStatus)) 
	{
		ASSERT(LPX_BUG);
		LpxTdiDisassociateAddress(listenFileObject);
		LpxTdiCloseConnection(listenFileHandle, listenFileObject);
		LpxTdiCloseAddress (addressFileHandle, addressFileObject);

		listenSock->Active = FALSE;
		ntStatus = STATUS_UNSUCCESSFUL;
	}

	return ntStatus;
}
Exemplo n.º 8
0
NTSTATUS
BindListenSockets(
	IN 	PPRIMARY	Primary
	)
{
	NTSTATUS				ntStatus;
	PSOCKETLPX_ADDRESS_LIST	socketLpxAddressList;
	LONG					idx_addr;


	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("BindListenSockets: Entered\n"));

	Primary->Agent.ActiveListenSocketCount = 0;
	socketLpxAddressList = &Primary->Agent.SocketLpxAddressList;
	ntStatus = LpxTdiGetAddressList(
		socketLpxAddressList
        );

	if(!NT_SUCCESS(ntStatus)) 
	{
		//ASSERT(LPX_BUG);
		return	ntStatus;
	}
	
	if(socketLpxAddressList->iAddressCount <= 0) 
	{
		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					( "BindListenSockets: No NICs in the host.\n") );

		return STATUS_UNSUCCESSFUL;
	}
	
	if(socketLpxAddressList->iAddressCount > MAX_SOCKETLPX_INTERFACE)
		socketLpxAddressList->iAddressCount = MAX_SOCKETLPX_INTERFACE;

	for(idx_addr = 0; idx_addr < socketLpxAddressList->iAddressCount; idx_addr ++) 
	{
		LPX_ADDRESS		NICAddr;
	
		HANDLE			addressFileHandle = NULL;
		PFILE_OBJECT	addressFileObject = NULL;

		HANDLE			listenFileHandle = NULL;
		PFILE_OBJECT	listenFileObject = NULL;
		
		
		Primary->Agent.ListenSocket[idx_addr].Active = FALSE;

		if( (0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[0]) &&
			(0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[1]) &&
			(0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[2]) &&
			(0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[3]) &&
			(0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[4]) &&
			(0 == socketLpxAddressList->SocketLpx[idx_addr].LpxAddress.Node[5]) ) 
		{
			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						( "BindListenSockets: We don't use SocketLpx device.\n"));
			continue;
		}

		RtlCopyMemory(
				&Primary->Agent.ListenSocket[idx_addr].NICAddress,
				&socketLpxAddressList->SocketLpx[idx_addr].LpxAddress, 
				sizeof(LPX_ADDRESS)
			);

		RtlCopyMemory(
				&NICAddr, 
				&socketLpxAddressList->SocketLpx[idx_addr].LpxAddress, 
				sizeof(LPX_ADDRESS)
			);

		NICAddr.Port = HTONS(Primary->Agent.ListenPort);
	
		//
		//	open a address.
		//
		ntStatus = LpxTdiOpenAddress(
						&addressFileHandle,
						&addressFileObject,
						&NICAddr
						);

		if(!NT_SUCCESS(ntStatus)) 
		{
			ASSERT(LPX_BUG);
			continue;
		}

		Primary->Agent.ListenSocket[idx_addr].Active = TRUE;

		KeInitializeEvent(&Primary->Agent.ListenSocket[idx_addr].TdiListenContext.CompletionEvent, NotificationEvent, FALSE);

		Primary->Agent.ListenSocket[idx_addr].AddressFileHandle = addressFileHandle;
		Primary->Agent.ListenSocket[idx_addr].AddressFileObject = addressFileObject;
		
		Primary->Agent.ActiveListenSocketCount ++;

		ntStatus = MakeConnectionObject(addressFileHandle, addressFileObject, &listenFileHandle, &listenFileObject);
	
		if(!NT_SUCCESS(ntStatus)) 
		{
			ASSERT(LPX_BUG);
			LpxTdiCloseAddress (addressFileHandle, addressFileObject);

			Primary->Agent.ListenSocket[idx_addr].Active = FALSE;
			Primary->Agent.ActiveListenSocketCount --;
	
			continue;
		}

		Primary->Agent.ListenSocket[idx_addr].ListenFileHandle = listenFileHandle;
		Primary->Agent.ListenSocket[idx_addr].ListenFileObject = listenFileObject;

		
		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					( "BindListenSockets: opened a address:'%02X:%02X:%02X:%02X:%02X:%02X 0x%04X'\n",
						NICAddr.Node[0],NICAddr.Node[1],NICAddr.Node[2],
						NICAddr.Node[3],NICAddr.Node[4],NICAddr.Node[5],
						NTOHS(NICAddr.Port)
						) );

		Primary->Agent.ListenSocket[idx_addr].Flags	= TDI_QUERY_ACCEPT;

		ntStatus = LpxTdiListenWithCompletionEvent(
						Primary->Agent.ListenSocket[idx_addr].ListenFileObject,
						&Primary->Agent.ListenSocket[idx_addr].TdiListenContext,
						&Primary->Agent.ListenSocket[idx_addr].Flags
						);

		if(!NT_SUCCESS(ntStatus)) 
		{
			ASSERT(LPX_BUG);
			LpxTdiDisassociateAddress(listenFileObject);
			LpxTdiCloseConnection(listenFileHandle, listenFileObject);
			LpxTdiCloseAddress (addressFileHandle, addressFileObject);

			Primary->Agent.ListenSocket[idx_addr].Active = FALSE;
			Primary->Agent.ActiveListenSocketCount --;
	
			continue;
		}
	}

	return STATUS_SUCCESS;
}
Exemplo n.º 9
0
VOID
PrimaryAgentThreadProc(
	IN 	PPRIMARY	Primary
	)
{
	BOOLEAN			primaryAgentThreadExit = FALSE;
	ULONG			listenSocketIndex;
	PKWAIT_BLOCK	waitBlocks;

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: Start\n"));

	Primary->Agent.Flags |= PRIMARY_AGENT_INITIALIZING;
	
	//
	// Allocate wait block
	//
	 waitBlocks = ExAllocatePool(NonPagedPool, sizeof(KWAIT_BLOCK) * MAXIMUM_WAIT_OBJECTS);
	 if(waitBlocks == NULL) {
		 ASSERT(LFS_REQUIRED);
		 PsTerminateSystemThread(STATUS_INSUFFICIENT_RESOURCES);
	 }

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeInitializeEvent(
					&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent, 
					NotificationEvent, 
					FALSE
					);

	BindListenSockets(
		Primary
		);

	Primary->Agent.Flags |= PRIMARY_AGENT_START;
				
	KeSetEvent(&Primary->Agent.ReadyEvent, IO_DISK_INCREMENT, FALSE);


	while(primaryAgentThreadExit == FALSE)
	{
		PKEVENT				events[MAXIMUM_WAIT_OBJECTS];
		LONG				eventCnt;

		ULONG				i;

		LARGE_INTEGER		timeOut;
		NTSTATUS			ntStatus;
		PLIST_ENTRY			primaryAgentRequestEntry;


		ASSERT(MAX_SOCKETLPX_INTERFACE + 1 <= MAXIMUM_WAIT_OBJECTS);

		eventCnt = 0;
		events[eventCnt++] = &Primary->Agent.RequestEvent;

		if(!BooleanFlagOn(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN))
		{
			for(i=0; i<MAX_SOCKETLPX_INTERFACE; i++)
			{
				if(Primary->Agent.ListenSocket[i].TdiListenContext.Irp &&
					Primary->Agent.ListenSocket[i].Active)
				{
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
				else
				{
					// events[eventCnt++] = NULL; // I wanna set NULL, But It's not Work
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
			}

			ASSERT(eventCnt == MAX_SOCKETLPX_INTERFACE + 1);
		}

		timeOut.QuadPart = - 5 * HZ;
		ntStatus = KeWaitForMultipleObjects(
					eventCnt,
					events,
					WaitAny,
					Executive,
					KernelMode,
					TRUE,
					&timeOut,
					waitBlocks
				);

		if(ntStatus == STATUS_TIMEOUT) 
		{
			continue;
		}

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
			("PrimaryAgentThreadProc: NTSTATUS:%lu\n", ntStatus));
		

		if(!NT_SUCCESS(ntStatus) || ntStatus >= eventCnt)
		{
			ASSERT(LFS_UNEXPECTED);
			SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

			primaryAgentThreadExit = TRUE;

			continue;
		}

		KeClearEvent(events[ntStatus]);

		if(0 == ntStatus)
		{
			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
					("PrimaryAgentThreadProc: RequestEvent received\n"));

			while(primaryAgentRequestEntry = 
					ExInterlockedRemoveHeadList(
							&Primary->Agent.RequestQueue,
							&Primary->Agent.RequestQSpinLock
							)
				) 
			{
				PPRIMARY_AGENT_REQUEST		primaryAgentRequest;

				primaryAgentRequest = CONTAINING_RECORD(
										primaryAgentRequestEntry,
										PRIMARY_AGENT_REQUEST,
										ListEntry
										);
	
				switch(primaryAgentRequest->RequestType) 
				{

				case PRIMARY_AGENT_REQ_DISCONNECT:
				{
					CloseListenSockets(
						Primary,
						FALSE
						);
				
					break;
				}

				case PRIMARY_AGENT_REQ_SHUTDOWN:
				{
					CloseListenSockets(
						Primary,
						TRUE
						);				
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN);
					break;
				}

				case PRIMARY_AGENT_REQ_DOWN:

					primaryAgentThreadExit = TRUE;
					break;

				//
				//	added to adapt network card changes.
				//
				case PRIMARY_AGENT_REQ_NIC_DISABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_DISABLED\n"));
					PrimaryAgentNICDisabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				case PRIMARY_AGENT_REQ_NIC_ENABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_ENABLED\n"));
					PrimaryAgentNICEnabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				default:
		
					ASSERT(LFS_BUG);
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

					break;
				}

				if(primaryAgentRequest->Synchronous == TRUE)
						KeSetEvent(&primaryAgentRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
				else
					DereferencePrimaryAgentRequest(
						primaryAgentRequest
						);
			}

			continue;	
		}

		ASSERT(1 <= ntStatus && ntStatus < eventCnt); // LpxEvent 
		
		if(	1 <= ntStatus &&
			ntStatus <= MAX_SOCKETLPX_INTERFACE
			) // Connected 
		{
			NTSTATUS		tdiStatus;
			HANDLE			listenFileHandle;
			PFILE_OBJECT	listenFileObject;
			HANDLE			connFileHandle;
			PFILE_OBJECT	connFileObject;
			PPRIMARY_LISTEN_SOCKET	listenSocket;
			LPX_ADDRESS		remoteAddress;

			listenSocket = &Primary->Agent.ListenSocket[ntStatus-1];

			//
			//	retreive a connection file and remote address.
			//
			connFileHandle = listenSocket->ListenFileHandle;
			connFileObject = listenSocket->ListenFileObject;
			RtlCopyMemory(&remoteAddress, &listenSocket->TdiListenContext.RemoteAddress, sizeof(LPX_ADDRESS));

			listenSocket->TdiListenContext.Irp = NULL;
			listenSocket->ListenFileHandle = NULL;
			listenSocket->ListenFileObject = NULL;
			KeClearEvent(&listenSocket->TdiListenContext.CompletionEvent);

			if(!listenSocket->Active) 
			{
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("ListenSocket is not active. Maybe a NIC disabled.\n"));
				continue;

			} 
			else if(listenSocket->TdiListenContext.Status != STATUS_SUCCESS) 
			{
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("Listen IRP #%d failed.\n", ntStatus));
				continue;
			}

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					("PrimaryAgentThreadProc: Connect from %02X:%02X:%02X:%02X:%02X:%02X 0x%4X\n",
						listenSocket->TdiListenContext.RemoteAddress.Node[0], listenSocket->TdiListenContext.RemoteAddress.Node[1],
						listenSocket->TdiListenContext.RemoteAddress.Node[2], listenSocket->TdiListenContext.RemoteAddress.Node[3],
						listenSocket->TdiListenContext.RemoteAddress.Node[4], listenSocket->TdiListenContext.RemoteAddress.Node[5],
						NTOHS(listenSocket->TdiListenContext.RemoteAddress.Port)
						));

			//
			//	Make a new listen connection first of all to get another connection.
			//	It must be earlier than start a session that takes long time.
			//	Primary cannot accept a connection before it creates a new listen object.
			//
			tdiStatus = MakeConnectionObject(
							listenSocket->AddressFileHandle,
							listenSocket->AddressFileObject,
							&listenFileHandle,
							&listenFileObject
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
				goto start_session;
			}

			listenSocket->ListenFileHandle = listenFileHandle;
			listenSocket->ListenFileObject = listenFileObject;

			listenSocket->Flags	= TDI_QUERY_ACCEPT;
			tdiStatus = LpxTdiListenWithCompletionEvent(
							listenSocket->ListenFileObject,
							&listenSocket->TdiListenContext,
							&listenSocket->Flags
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiDisassociateAddress(listenFileObject);
				LpxTdiCloseConnection(listenFileHandle, listenFileObject);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);
				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
			}

start_session:
			//
			//	start a session.
			//
			Primary_AcceptConnection(Primary, connFileHandle, connFileObject, ntStatus-1, &remoteAddress);
			
			continue;
		}
	}

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeClearEvent(&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent);

	//
	// Free wait blocks
	//

	ExFreePool(waitBlocks);

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: PsTerminateSystemThread\n"));
	
	Primary->Agent.Flags |= PRIMARY_AGENT_TERMINATED;

	PsTerminateSystemThread(STATUS_SUCCESS);
}
Exemplo n.º 10
0
VOID
PrimarySession_Close (
	IN 	PPRIMARY_SESSION	PrimarySession
	)
{
	DebugTrace2( 0, Dbg2, ("PrimarySession_Close: PrimarySession = %p\n", PrimarySession) );

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	if (FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP)) {

		ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
		return;
	}

	SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOP );

	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );
	
	if (PrimarySession->ThreadHandle == NULL) {

		ASSERT( NDASFAT_BUG );
		PrimarySession_Dereference( PrimarySession );

		return;
	}

	ASSERT( PrimarySession->ThreadObject != NULL );

	if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED)) {

		ObDereferenceObject( PrimarySession->ThreadObject );

		PrimarySession->ThreadHandle = NULL;
		PrimarySession->ThreadObject = NULL;

	
	} else {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
		NTSTATUS					ntStatus;
		LARGE_INTEGER				timeOut;
	
		
		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DISCONNECT;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		primarySessionRequest = AllocPrimarySessionRequest( FALSE );
		primarySessionRequest->RequestType = PRIMARY_SESSION_REQ_DOWN;

		QueueingPrimarySessionRequest( PrimarySession,
									   primarySessionRequest,
									   FALSE );

		timeOut.QuadPart = -NDASFAT_TIME_OUT;
		ntStatus = KeWaitForSingleObject( PrimarySession->ThreadObject,
										  Executive,
										  KernelMode,
										  FALSE,
										  &timeOut );

		if (ntStatus == STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg, ("PrimarySession_Close: thread stoped\n") );

			ObDereferenceObject( PrimarySession->ThreadObject );

			PrimarySession->ThreadHandle = NULL;
			PrimarySession->ThreadObject = NULL;
				
		} else {

			ASSERT( NDASFAT_BUG );
			return;
		}
	}

#if 0
    interval.QuadPart = (5 * DELAY_ONE_SECOND);      //delay 5 seconds
    KeDelayExecutionThread( KernelMode, FALSE, &interval );
#endif

	if (PrimarySession->ConnectionFileHandle) {

		LpxTdiDisassociateAddress( PrimarySession->ConnectionFileObject );
		LpxTdiCloseConnection( PrimarySession->ConnectionFileHandle, PrimarySession->ConnectionFileObject );
	}

	PrimarySession->ConnectionFileHandle = NULL;
	PrimarySession->ConnectionFileObject = NULL;

	PrimarySession_Dereference( PrimarySession );

	return;
}
Exemplo n.º 11
0
//
// Wait for registration message and forward proper arbiter.
//
VOID
DraidReceptionThreadProc(
	IN PVOID Param
) {
	PDRAID_REMOTE_CLIENT_CONNECTION Connection = Param;
	LARGE_INTEGER Timeout;
	NTSTATUS status;
	DRIX_REGISTER RegMsg;
	DRIX_HEADER Reply = {0};
	PDRAID_ARBITER_INFO Arbiter;
	KIRQL	oldIrql;
	PLIST_ENTRY listEntry;
	BOOLEAN Disconnect = TRUE;
	BOOLEAN MatchFound;
	ULONG		result;
	
	Connection->TdiReceiveContext.Irp = NULL;
	KeInitializeEvent(&Connection->TdiReceiveContext.CompletionEvent, NotificationEvent, FALSE) ;
	
	// Wait for network event or short timeout
	status = LpxTdiRecvWithCompletionEvent(
					Connection->ConnectionFileObject,
					&Connection->TdiReceiveContext,
					(PUCHAR)&RegMsg,
					sizeof(DRIX_REGISTER),
					0,
					NULL,
					NULL
					);
	if(!NT_SUCCESS(status)) {
		KDPrintM(DBG_LURN_INFO, ("LpxTdiRecvWithCompletionEvent returned %d.\n", status));
		goto out;
	}

	Timeout.QuadPart =  - HZ * 5;
	
	status = KeWaitForSingleObject(
		&Connection->TdiReceiveContext.CompletionEvent,
		Executive, KernelMode, 	FALSE, &Timeout);
	
	if (status == STATUS_SUCCESS) {
		UCHAR ResultCode;
		
		//
		// Data received. Check validity and forward channel to arbiter.
		//
		if (Connection->TdiReceiveContext.Result != sizeof(DRIX_REGISTER)) {
			KDPrintM(DBG_LURN_INFO, ("Registration packet size is not %d.\n", sizeof(DRIX_REGISTER)));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		if (NTOHL(RegMsg.Header.Signature) != DRIX_SIGNATURE) {
			KDPrintM(DBG_LURN_INFO, ("DRIX signature mismatch\n"));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}
		
		if (RegMsg.Header.Command != DRIX_CMD_REGISTER) {
			KDPrintM(DBG_LURN_INFO, ("Inappropriate command %x sent.\n", RegMsg.Header.Command));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		if (RegMsg.Header.ReplyFlag) {
			KDPrintM(DBG_LURN_INFO, ("Reply flag should be cleared\n"));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}
		if (NTOHS(RegMsg.Header.Length) !=  sizeof(DRIX_REGISTER)) {
			KDPrintM(DBG_LURN_INFO, ("Invalid packet length %d\n", NTOHS(RegMsg.Header.Length)));
			status = STATUS_UNSUCCESSFUL;
			goto out;
		}

		ACQUIRE_SPIN_LOCK(&g_DraidGlobals->ArbiterListSpinlock, &oldIrql);
		MatchFound = FALSE;
		for (listEntry = g_DraidGlobals->ArbiterList.Flink;
			listEntry != &g_DraidGlobals->ArbiterList;
			listEntry = listEntry->Flink) 
		{
			Arbiter = CONTAINING_RECORD (listEntry, DRAID_ARBITER_INFO, AllArbiterList);
			if (RtlCompareMemory(&Arbiter->Rmd.RaidSetId, &RegMsg.RaidSetId, sizeof(GUID)) == sizeof(GUID) &&
				RtlCompareMemory(&Arbiter->Rmd.ConfigSetId, &RegMsg.ConfigSetId, sizeof(GUID)) == sizeof(GUID)
			) {
				if (Arbiter->Status != DRAID_ARBITER_STATUS_TERMINATING) {
					MatchFound = TRUE;
				} else {
					KDPrintM(DBG_LURN_INFO, ("Arbiter is terminating. Reject reception\n"));	
					MatchFound = FALSE;
				}
				break;
			}
		}
		RELEASE_SPIN_LOCK(&g_DraidGlobals->ArbiterListSpinlock, oldIrql);

		if (MatchFound) {
			ResultCode = DRIX_RESULT_SUCCESS;
		} else {
			ResultCode = DRIX_RESULT_RAID_SET_NOT_FOUND;
		}
//reply:
		//
		// Send reply
		//
		Reply.Signature = 	NTOHL(DRIX_SIGNATURE);
		Reply.Command = DRIX_CMD_REGISTER;
		Reply.Length = NTOHS((UINT16)sizeof(DRIX_HEADER));
		Reply.ReplyFlag = 1;
		Reply.Sequence = RegMsg.Header.Sequence;
		Reply.Result = ResultCode;

		Timeout.QuadPart =  HZ * 5;

		KDPrintM(DBG_LURN_INFO, ("DRAID Sending registration reply(result=%x) to remote client\n", ResultCode));
		status = LpxTdiSend(
					Connection->ConnectionFileObject, (PUCHAR)&Reply, sizeof(DRIX_HEADER), 
					0, &Timeout,	NULL, &result	);
		KDPrintM(DBG_LURN_INFO, ("LpxTdiSend status=%x, result=%x.\n", status, result));
		if (status !=STATUS_SUCCESS) {
			Disconnect = TRUE;
			goto out;
		}
		if (MatchFound) {
			status = DraidArbiterAcceptClient(Arbiter, RegMsg.ConnType, Connection);
			if (status == STATUS_SUCCESS) {
				Disconnect = FALSE;
			} else {
				KDPrintM(DBG_LURN_INFO, ("Failed to accept client %x.\n", status));
			}
		}
	} else if (status == STATUS_TIMEOUT) {
		KDPrintM(DBG_LURN_INFO, ("Timeout before registration.\n"));
	}
	
out:
	if (Disconnect) {
		KDPrintM(DBG_LURN_INFO, ("Closing connection to client.\n"));			
		// Close connection.
		LpxTdiDisassociateAddress(Connection->ConnectionFileObject);
		LpxTdiCloseConnection(
					Connection->ConnectionFileHandle, 
					Connection->ConnectionFileObject
					);
		Connection->ConnectionFileHandle = NULL;
		Connection->ConnectionFileObject = NULL;

		ExFreePoolWithTag(Connection, DRAID_REMOTE_CLIENT_CHANNEL_POOL_TAG);
	} else {
		// Arbiter thread will close connection and free channel
	}
	
	KDPrintM(DBG_LURN_INFO, ("Exiting reception thread.\n"));
	// Decrease counter
	InterlockedDecrement(&g_DraidGlobals->ReceptionThreadCount);
}