How to get source IP address in TDI filter driver?

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

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
      Keymaster

        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
          Keymaster

            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.