Пример #1
0
static
void
InternalErrorEventHandler(void *arg, const err_t err)
{
    PCONNECTION_ENDPOINT Connection = arg;
    KIRQL OldIrql;

    /* Make sure the socket didn't get closed */
    if (!arg) return;

    /* Check if data is left to be read */
    LockObject(Connection, &OldIrql);
    if (IsListEmpty(&Connection->PacketQueue))
    {
        UnlockObject(Connection, OldIrql);

        /* Deliver the error now */
        TCPFinEventHandler(arg, err);
    }
    else
    {
        UnlockObject(Connection, OldIrql);

        /* Defer the error delivery until all data is gone */
        Connection->ReceiveShutdown = TRUE;
        Connection->ReceiveShutdownStatus = TCPTranslateError(err);

        TCPRecvEventHandler(arg);
    }
}
Пример #2
0
NTSTATUS TCPSendData
( PCONNECTION_ENDPOINT Connection,
  PCHAR BufferData,
  ULONG SendLength,
  PULONG BytesSent,
  ULONG Flags,
  PTCP_COMPLETION_ROUTINE Complete,
  PVOID Context )
{
    NTSTATUS Status;
    PTDI_BUCKET Bucket;
    KIRQL OldIrql;

    LockObject(Connection, &OldIrql);

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Called for %d bytes (on socket %x)\n",
                           SendLength, Connection->SocketContext));

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection = %x\n", Connection));
    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Connection->SocketContext = %x\n",
                           Connection->SocketContext));

    Status = TCPTranslateError(LibTCPSend(Connection,
                                          BufferData,
                                          SendLength,
                                          BytesSent,
                                          FALSE));
    
    TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Send: %x, %d\n", Status, SendLength));

    /* Keep this request around ... there was no data yet */
    if (Status == STATUS_PENDING)
    {
        /* Freed in TCPSocketState */
        Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
        if (!Bucket)
        {
            UnlockObject(Connection, OldIrql);
            TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Failed to allocate bucket\n"));
            return STATUS_NO_MEMORY;
        }
        
        Bucket->Request.RequestNotifyObject = Complete;
        Bucket->Request.RequestContext = Context;
        
        InsertTailList( &Connection->SendRequest, &Bucket->Entry );
        TI_DbgPrint(DEBUG_TCP,("[IP, TCPSendData] Queued write irp\n"));
    }

    UnlockObject(Connection, OldIrql);

    TI_DbgPrint(DEBUG_TCP, ("[IP, TCPSendData] Leaving. Status = %x\n", Status));

    return Status;
}
Пример #3
0
NTSTATUS TCPGetSockAddress
( PCONNECTION_ENDPOINT Connection,
  PTRANSPORT_ADDRESS Address,
  BOOLEAN GetRemote )
{
    PTA_IP_ADDRESS AddressIP = (PTA_IP_ADDRESS)Address;
    struct ip_addr ipaddr;
    NTSTATUS Status;
    KIRQL OldIrql;
    
    AddressIP->TAAddressCount = 1;
    AddressIP->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    AddressIP->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;

    LockObject(Connection, &OldIrql);

    if (GetRemote)
    {
        Status = TCPTranslateError(LibTCPGetPeerName(Connection->SocketContext,
                                    &ipaddr,
                                    &AddressIP->Address[0].Address[0].sin_port));
    }
    else
    {
        Status = TCPTranslateError(LibTCPGetHostName(Connection->SocketContext,
                                    &ipaddr,
                                    &AddressIP->Address[0].Address[0].sin_port));
    }

    UnlockObject(Connection, OldIrql);
    
    AddressIP->Address[0].Address[0].in_addr = ipaddr.addr;
    
    RtlZeroMemory(&AddressIP->Address[0].Address[0].sin_zero,
                  sizeof(AddressIP->Address[0].Address[0].sin_zero));

    return Status;
}
Пример #4
0
VOID NTAPI
DisconnectTimeoutDpc(PKDPC Dpc,
                     PVOID DeferredContext,
                     PVOID SystemArgument1,
                     PVOID SystemArgument2)
{
    PCONNECTION_ENDPOINT Connection = (PCONNECTION_ENDPOINT)DeferredContext;
    PLIST_ENTRY Entry;
    PTDI_BUCKET Bucket;

    LockObjectAtDpcLevel(Connection);

    /* We timed out waiting for pending sends so force it to shutdown */
    TCPTranslateError(LibTCPShutdown(Connection, 0, 1));

    while (!IsListEmpty(&Connection->SendRequest))
    {
        Entry = RemoveHeadList(&Connection->SendRequest);
        
        Bucket = CONTAINING_RECORD(Entry, TDI_BUCKET, Entry);
        
        Bucket->Information = 0;
        Bucket->Status = STATUS_FILE_CLOSED;
        
        CompleteBucket(Connection, Bucket, FALSE);
    }
    
    while (!IsListEmpty(&Connection->ShutdownRequest))
    {
        Entry = RemoveHeadList( &Connection->ShutdownRequest );
        
        Bucket = CONTAINING_RECORD( Entry, TDI_BUCKET, Entry );
        
        Bucket->Status = STATUS_TIMEOUT;
        Bucket->Information = 0;
        
        CompleteBucket(Connection, Bucket, FALSE);
    }
    
    UnlockObjectFromDpcLevel(Connection);
    
    DereferenceObject(Connection);
}
Пример #5
0
static
void
InternalErrorEventHandler(void *arg, const err_t err)
{
    PCONNECTION_ENDPOINT Connection = arg;

    /* Make sure the socket didn't get closed */
    if (!arg || Connection->SocketContext == NULL) return;

    /* The PCB is dead now */
    Connection->SocketContext = NULL;

    /* Give them one shot to receive the remaining data */
    Connection->ReceiveShutdown = TRUE;
    Connection->ReceiveShutdownStatus = TCPTranslateError(err);
    TCPRecvEventHandler(Connection);

    /* Terminate the connection */
    TCPFinEventHandler(Connection, err);
}
Пример #6
0
NTSTATUS TCPDisconnect
( PCONNECTION_ENDPOINT Connection,
  UINT Flags,
  PLARGE_INTEGER Timeout,
  PTDI_CONNECTION_INFORMATION ConnInfo,
  PTDI_CONNECTION_INFORMATION ReturnInfo,
  PTCP_COMPLETION_ROUTINE Complete,
  PVOID Context )
{
    NTSTATUS Status = STATUS_INVALID_PARAMETER;
    PTDI_BUCKET Bucket;
    KIRQL OldIrql;
    LARGE_INTEGER ActualTimeout;

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Called\n"));

    LockObject(Connection, &OldIrql);

    if (Connection->SocketContext)
    {
        if (Flags & TDI_DISCONNECT_RELEASE)
        {
            if (IsListEmpty(&Connection->SendRequest))
            {
                Status = TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
            }
            else if (Timeout && Timeout->QuadPart == 0)
            {
                FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
                TCPTranslateError(LibTCPShutdown(Connection, 0, 1));
                Status = STATUS_TIMEOUT;
            }
            else 
            {
                /* Use the timeout specified or 1 second if none was specified */
                if (Timeout)
                {
                    ActualTimeout = *Timeout;
                }
                else
                {
                    ActualTimeout.QuadPart = -1000000;
                }

                /* We couldn't complete the request now because we need to wait for outstanding I/O */
                Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
                if (!Bucket)
                {
                    UnlockObject(Connection, OldIrql);
                    return STATUS_NO_MEMORY;
                }

                Bucket->Request.RequestNotifyObject = (PVOID)Complete;
                Bucket->Request.RequestContext = Context;

                InsertTailList(&Connection->ShutdownRequest, &Bucket->Entry);

                ReferenceObject(Connection);
                if (KeCancelTimer(&Connection->DisconnectTimer))
                {
                    DereferenceObject(Connection);
                }
                KeSetTimer(&Connection->DisconnectTimer, ActualTimeout, &Connection->DisconnectDpc);

                Status = STATUS_PENDING;
            }
        }

        if ((Flags & TDI_DISCONNECT_ABORT) || !Flags)
        {
            FlushReceiveQueue(Connection, STATUS_FILE_CLOSED, FALSE);
            FlushSendQueue(Connection, STATUS_FILE_CLOSED, FALSE);
            FlushShutdownQueue(Connection, STATUS_FILE_CLOSED, FALSE);
            Status = TCPTranslateError(LibTCPShutdown(Connection, 1, 1));
        }
    }
    else
    {
        /* We already got closed by the other side so just return success */
        Status = STATUS_SUCCESS;
    }

    UnlockObject(Connection, OldIrql);

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPDisconnect] Leaving. Status = 0x%x\n", Status));

    return Status;
}
Пример #7
0
NTSTATUS TCPConnect
( PCONNECTION_ENDPOINT Connection,
  PTDI_CONNECTION_INFORMATION ConnInfo,
  PTDI_CONNECTION_INFORMATION ReturnInfo,
  PTCP_COMPLETION_ROUTINE Complete,
  PVOID Context )
{
    NTSTATUS Status;
    struct ip_addr bindaddr, connaddr;
    IP_ADDRESS RemoteAddress;
    USHORT RemotePort;
    TA_IP_ADDRESS LocalAddress;
    PTDI_BUCKET Bucket;
    PNEIGHBOR_CACHE_ENTRY NCE;
    KIRQL OldIrql;

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Called\n"));

    Status = AddrBuildAddress
        ((PTRANSPORT_ADDRESS)ConnInfo->RemoteAddress,
         &RemoteAddress,
         &RemotePort);

    if (!NT_SUCCESS(Status))
    {
        TI_DbgPrint(DEBUG_TCP, ("Could not AddrBuildAddress in TCPConnect\n"));
        return Status;
    }

    /* Freed in TCPSocketState */
    TI_DbgPrint(DEBUG_TCP,
                ("Connecting to address %x:%x\n",
                 RemoteAddress.Address.IPv4Address,
                 RemotePort));

    LockObject(Connection, &OldIrql);

    if (!Connection->AddressFile)
    {
        UnlockObject(Connection, OldIrql);
        return STATUS_INVALID_PARAMETER;
    }

    if (AddrIsUnspecified(&Connection->AddressFile->Address))
    {
        if (!(NCE = RouteGetRouteToDestination(&RemoteAddress)))
        {
            UnlockObject(Connection, OldIrql);
            return STATUS_NETWORK_UNREACHABLE;
        }

        bindaddr.addr = NCE->Interface->Unicast.Address.IPv4Address;
    }
    else
    {
        bindaddr.addr = Connection->AddressFile->Address.Address.IPv4Address;
    }

    Status = TCPTranslateError(LibTCPBind(Connection,
                                          &bindaddr,
                                          Connection->AddressFile->Port));
    
    if (NT_SUCCESS(Status))
    {
        /* Check if we had an unspecified port */
        if (!Connection->AddressFile->Port)
        {
            /* We did, so we need to copy back the port */
            Status = TCPGetSockAddress(Connection, (PTRANSPORT_ADDRESS)&LocalAddress, FALSE);
            if (NT_SUCCESS(Status))
            {
                /* Allocate the port in the port bitmap */
                Connection->AddressFile->Port = TCPAllocatePort(LocalAddress.Address[0].Address[0].sin_port);
                    
                /* This should never fail */
                ASSERT(Connection->AddressFile->Port != 0xFFFF);
            }
        }

        if (NT_SUCCESS(Status))
        {
            connaddr.addr = RemoteAddress.Address.IPv4Address;

            Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList);
            if (!Bucket)
            {
                UnlockObject(Connection, OldIrql);
                return STATUS_NO_MEMORY;
            }
            
            Bucket->Request.RequestNotifyObject = (PVOID)Complete;
            Bucket->Request.RequestContext = Context;
			
            InsertTailList( &Connection->ConnectRequest, &Bucket->Entry );
        
            Status = TCPTranslateError(LibTCPConnect(Connection,
                                                     &connaddr,
                                                     RemotePort));
        }
    }

    UnlockObject(Connection, OldIrql);

    TI_DbgPrint(DEBUG_TCP,("[IP, TCPConnect] Leaving. Status = 0x%x\n", Status));

    return Status;
}