03-15-2010 08:32 AM
Good day. I'm trying to write a kernel mode code that uses the TDI interface to accept incoming TCP-connections. And this I can not. Schematic code shown below. Attempt to connect via telnet for the first time succeeds - Irp->IoStatus.Status == STATUS_SUCCESS, but when I try to send / receive data through that connection, I get STATUS_INVALID_DEVICE_STATE (0xC0000184). At this time Process Explorer shows listening socket and the established connection on the same port. Subsequent attempts to connect get Irp->IoStatus.Status == STATUS_CONNECTION_INVALID (0xC000023A). I can not understand why. Maybe I do not understand the mechanism? I would be grateful for the help.
/* Listen-socket has two lists - the list of sockets that are waiting to connect - backlog, as I understand it,
** and the list of sockets that are already connected. Access to lists regulates the Queued-SpinLock -
** in order to operate on the list was possible on IRQL <= DISPATCH_LEVEL.
** KernelSocketAccept(__in PKERNEL_SOCKET Socket, __out PKERNEL_SOCKET * AcceptedConnectionSocket) interface function
** waits for SocketConnectedEvent and when connected socket(sockets) appears in the ConnectedSockets list, takes connected
** socket from this list and returns pointer on it in output parameter.
*/
typedef struct _TDI_ACCEPT_IRP_CONTEXT{
PKERNEL_SOCKET ListeningSocket;
PKERNEL_SOCKET AcceptSocket;
TDI_CONNECTION_INFORMATION RequestConnectionInformation;
TA_IP_ADDRESS RequestRemoteAddressIPv4;
TA_IP6_ADDRESS RequestRemoteAddressIPv6;
} TDI_ACCEPT_IRP_CONTEXT, *PTDI_ACCEPT_IRP_CONTEXT;
IO_COMPLETION_ROUTINE TDIAcceptIRPCompletionRoutine;
static NTSTATUS TDIAcceptIRPCompletionRoutine(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Context){
PTDI_ACCEPT_IRP_CONTEXT TDIAcceptIRPContext = (PTDI_ACCEPT_IRP_CONTEXT)Context;
if(TDIAcceptIRPContext){
if(TDIAcceptIRPContext->ListeningSocket && TDIAcceptIRPContext->AcceptSocket){
if(Irp->IoStatus.Status == STATUS_SUCCESS){
TDIAcceptIRPContext->AcceptSocket->Connected = true;
AppendSocketToSocketList(&TDIAcceptIRPContext->ListeningSocket->ConnectedSockets, TDIAcceptIRPContext->AcceptSocket);
KeSetEvent(&TDIAcceptIRPContext->ListeningSocket->SocketConnectedEvent, IO_NO_INCREMENT, FALSE);
}
}
ExFreeToNPagedLookasideList(&KernelSocketsModule.DataBufferLookAsideList, TDIAcceptIRPContext);
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
03-15-2010 08:36 AM
static NTSTATUS TDIClientEventIncomingConnection(IN PVOID TdiEventContext,
IN LONG RemoteAddressLength,
IN PVOID RemoteAddress,
IN LONG UserDataLength,
IN PVOID UserData,
IN LONG OptionsLength,
IN PVOID Options,
OUT CONNECTION_CONTEXT * ConnectionContext,
OUT PIRP * AcceptIrp){
NTSTATUS ThisFunctionResult = STATUS_CONNECTION_REFUSED;
*ConnectionContext = NULL;
*AcceptIrp = NULL;
PKERNEL_SOCKET Socket = (PKERNEL_SOCKET)TdiEventContext;
if(RemoteAddress){
if(RemoteAddressLength >= sizeof(TA_IP_ADDRESS)){
if(((PTA_IP_ADDRESS)RemoteAddress)->Address[0].AddressType == TDI_ADDRESS_TYPE_IP){
PIRP AcceptConnectionIRP = IoAllocateIrp(Socket->TransportDeviceObject->StackSize + 1, FALSE);
if(AcceptConnectionIRP){
PTDI_ACCEPT_IRP_CONTEXT TDIAcceptIRPContext = (PTDI_ACCEPT_IRP_CONTEXT)ExAllocateFromNPagedLookasideList(&KernelSocketsModule.DataBufferLookAsideList);
if(TDIAcceptIRPContext){
local_memset(TDIAcceptIRPContext, 0x00, sizeof(TDI_ACCEPT_IRP_CONTEXT));
TDIAcceptIRPContext->RequestRemoteAddressIPv4.TAAddressCount = 1;
TDIAcceptIRPContext->RequestRemoteAddressIPv4.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
TDIAcceptIRPContext->RequestRemoteAddressIPv4.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
TDIAcceptIRPContext->RequestRemoteAddressIPv4.Address[0].Address[0].in_addr = ((PTA_IP_ADDRESS)RemoteAddress)->Address[0].Address[0].in_addr;
TDIAcceptIRPContext->RequestRemoteAddressIPv4.Address[0].Address[0].sin_port = ((PTA_IP_ADDRESS)RemoteAddress)->Address[0].Address[0].sin_port;
TDIAcceptIRPContext->RequestConnectionInformation.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
TDIAcceptIRPContext->RequestConnectionInformation.RemoteAddress = &TDIAcceptIRPContext->RequestRemoteAddressIPv4;
03-15-2010 08:37 AM
if(SocketFromTheWaitingList){
TDIAcceptIRPContext->ListeningSocket = Socket;
TDIAcceptIRPContext->AcceptSocket = SocketFromTheWaitingList;
TdiBuildAccept(AcceptConnectionIRP, Socket->TransportDeviceObject, SocketFromTheWaitingList->TransportDeviceFile.Object, TDIAcceptIRPCompletionRoutine, TDIAcceptIRPContext, &TDIAcceptIRPContext->RequestConnectionInformation, NULL);
IoSetNextIrpStackLocation(AcceptConnectionIRP);
*ConnectionContext = (CONNECTION_CONTEXT)Socket;
*AcceptIrp = AcceptConnectionIRP;
ThisFunctionResult = STATUS_MORE_PROCESSING_REQUIRED;
}
}
}
}
}
}
return ThisFunctionResult;
}
//Module interface function
NTSTATUS KernelSocketListen(__in PKERNEL_SOCKET Socket){
/* Creation of a number of sockets for use in ClientEventConnect - backlog.
** Creation consists of opening the connection to the transport driver - ZwCreateFile()
** and subsequent TDI_ASSOCIATE_ADDRESS.
** Puts these sockets in the list, access to which regulates the Queued-SpinLock -
** in order to operate on the list was possible on IRQL <= DISPATCH_LEVEL.
** This list is tied to the current listening socket - for which this function is called.
** All these actions are fully successful.
*/
/* Then form the IRP - TDI_SET_EVENT_HANDLER with EventType == TDI_EVENT_CONNECT and
** call IoCallDriver(). As PFILE_OBJECT FileObj gives the address file object of this listen socket.
** Returns STATUS_SUCCESS.
*/
/* It seems that in this function everything is working properly */
return ThisFunctionResult;
}
//-------------------------------------------------------------------------------------