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; }
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; }
// // 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; }
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; }
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")); } } }
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; }
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; }
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; }
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); }
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; }
// // 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); }