How to get source IP address in TDI filter driver?

Home Forums Discussions General Discussion How to get source IP address in TDI filter driver?

This topic contains 4 replies, has 2 voices, and was last updated by  kokos 10 years ago.

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #5150

    kokos
    Participant

    Hello gurus.

    I am writing a TDI filter driver which is using IoAttachDevice to attach to
    protocol devices. In my filter driver, I handle TDI_CONNECT and
    TDI_SEND_DATAGRAM and do some logics.

    The problem is, I need to get the source IP address and source port which is
    initiating a connection. I can easially get the remote IP and port by
    accessing PIO_STACK_LOCATION->Parameters field. But how can I get the source
    IP and port?

    I did a massive googling regarding this problem. And I found only solution
    regarding source port. The solution is posted by Jeff Runaway:
    http://groups.google.com/group/microsoft.public.development.device.drivers/browse_thread/thread/6ecb94f4b27b480e/d612e6caa47e8376?lnk=gst&q=TDI_QUERY_INFORMATION

    However, his code only retrievies the source port, not the IP address. How
    to solve the problem with source IP? Thanks.

    #6491

    Vadim Smirnov
    Moderator

    TDI_QUERY_INFORMATION allows getting both IP address and port. Refer the structures below in the DDK docs or MSDN.


    typedef struct _TA_ADDRESS {
    USHORT AddressLength;
    USHORT AddressType;
    UCHAR Address[1];
    } TA_ADDRESS, *PTA_ADDRESS;

    typedef struct _TA_ADDRESS_IP {
    LONG TAAddressCount;
    struct _AddrIp {
    USHORT AddressLength;
    USHORT AddressType;
    TDI_ADDRESS_IP Address[1];
    } Address [1];
    } TA_IP_ADDRESS, *PTA_IP_ADDRESS;

    typedef struct _TDI_ADDRESS_IP {
    USHORT sin_port;
    ULONG in_addr;
    UCHAR sin_zero[8];
    } TDI_ADDRESS_IP, *PTDI_ADDRESS_IP;
    #6492

    kokos
    Participant

    Hello, thank you for reply.

    Unfortunatly, TDI_QUERY_INFORMATION does not obtain the actual source IP address in 100 % of cases. I tried to obtain it using TDI_QUERY_INFORMATION and TDI_QUERY_ADDRESS_INFO but in 99 % of cases I get zero for source IP (you can take a look at the code I am using at the end of this message).

    I also tried get the adapter info (TDI_QUERY_ADAPTER_STATUS) when I handle TDI_CONNECT and once I succeed I will be able to get the adapter address, but the TDI_QUERY_ADAPTER_STATUS is not implemented – IoCallDriver returns me STATUS_NOT_IMPLEMENTED.

    When all my attempts failed, I downloaded the open source TDI firewall – tdi_fw to check how it detects the local IP address, and I noticed, that in major cases it detects the source IP as 0 (this can easially be seen in the logs).

    OK then, I did again some googling, and found an interesting reply of DDK MVP: http://tech.groups.yahoo.com/group/discussion-pcausa/message/1516
    Maybe, his reply explains why I always get the 0.0.0.0 – because the application specifies INADDR_ANY as a source address and TDI subsystem just gives me a hint that I can treat the source address, as any address of the currently running adapters. But I need to obtain the real source IP address

    The code I am using to obtain the source IP (source port is correctly obtained):



    USHORT GetPortFromAddressInfo(PDEVICE_OBJECT pDeviceObject, PFILE_OBJECT
    pAddressObject)
    {
    NTSTATUS status ;
    PIRP pIrp = NULL ;
    PMDL pMDL = NULL ;
    TDI_ADDRESS_INFO *pAddrInfo = NULL ;
    TDI_ADDRESS_IP TDI_IP ;
    USHORT usPort ;
    IO_STATUS_BLOCK IoStatusBlock ;

    pIrp = TdiBuildInternalDeviceControlIrp (TDI_QUERY_INFORMATION,
    pDeviceObject,
    pAddressObject,
    NULL,
    &IoStatusBlock
    );
    if(!pIrp)
    {
    DebugPrint("pIrp not allocated") ;
    return 0 ;
    }

    if(!pAddrInfo) //not yet allocated
    pAddrInfo = (TDI_ADDRESS_INFO*)ExAllocatePool(NonPagedPool , 2048) ;

    if(!pAddrInfo) //not allocated
    {
    return 0 ;
    }

    {
    pMDL = IoAllocateMdl(
    pAddrInfo,
    2048,
    FALSE,
    TRUE,
    pIrp
    );
    }
    if(!pMDL)
    {
    DebugPrint("MDL not allocated") ;
    goto CLEANUP ;
    }

    //__try
    {
    MmProbeAndLockPages(pMDL, KernelMode, IoWriteAccess) ;

    }
    //__except(EXCEPTION_EXECUTE_HANDLER){
    //DebugPrint("MDL not locked") ;
    //bSuccess = 0 ;
    //}

    TdiBuildQueryInformation (
    pIrp,
    pDeviceObject,
    pAddressObject,
    NULL, //QUERY_COMPLETION_ROUTINE,
    NULL,
    TDI_QUERY_ADDRESS_INFO,
    pMDL );

    status = IoCallDriver(pDeviceObject, pIrp);

    if( status == STATUS_SUCCESS )
    { in_addr *p_inetAddr ;
    //DebugPrint("Connection State [%u]", pAddrInfo->ActivityCount) ;
    TRANSPORT_ADDRESS *pTAddress = &pAddrInfo->Address ;
    TA_ADDRESS *pTA = &pTAddress->Address[0] ;
    RtlCopyMemory(&TDI_IP, (TDI_ADDRESS_IP*)pTA->Address,
    TDI_ADDRESS_LENGTH_IP) ;
    p_inetAddr = (in_addr*)&TDI_IP.in_addr ;
    }
    else
    {
    DebugPrint("Connection State - CallDriver failed") ;
    }
    usPort = TDI_IP.sin_port ;
    CLEANUP:
    if(pAddrInfo)
    ExFreePool(pAddrInfo) ;
    return usPort ;

    }
    #6493

    Vadim Smirnov
    Moderator

    Once the connection is established you can query the IP it was done from, but NOT before.

    #6494

    kokos
    Participant

    Yes. I was trying to get the source IP before I pass the IRP processing down to the stack. So at that moment, the source IP was not formed.

    So, now if I am obtaining the source IP after I pass IRP to next handler in the stack (via IoCallDriver) I get the correct value. But … This works only on XP and 2k. On Vista I continue to obtain the 0, however the port is correctly obtained.

    What to do with Vista? 😥

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.