在DDK---->Network Devices and Protocols--->Reference--->NdisObject----->General Object---->General Operational Characteristics中提供了一些OIDs that are used to get or set the general operational characteristics of miniport drivers and their NICs.注意到OID_GEN_NETWORK_LAYER_ADDRESSES.
 

OID_GEN_NETWORK_LAYER_ADDRESSES

The OID_GEN_NETWORK_LAYER_ADDRESSES OID notifies underlying miniport driver and other layered drivers about the list of network-layer addresses that are associated with bound instances. A bound instance is the binding between the calling transport and a driver set up by a call to NdisOpenAdapter. Transports use TRANSPORT_ADDRESS and TA_ADDRESS structures to notify underlying miniport drivers and other layered drivers about the list of network-layer addresses. Miniport drivers and other layered drivers use compatible NETWORK_ADDRESS_LIST and NETWORK_ADDRESS structures, defined as follows, to set the list of network-layer addresses on a bound interface.
也就是说协议栈会向他所绑定的NIC Miniport通知自己的网络地址信息。那么在passthru miniport端的SetInformationHandle就会被触发,可以在PtRequestComplete中得到网卡的IP地址。
typedef struct _NETWORK_ADDRESS_LIST {
  LONG  AddressCount; 
  USHORT  AddressType; 
  NETWORK_ADDRESS  Address[1]; 
} NETWORK_ADDRESS_LIST, *PNETWORK_ADDRESS_LIST;
The members of this structure contain the following information:
AddressCount
Specifies the number of network-layer addresses listed in the array in the Address member.
AddressType
Specifies the protocol type that sends this OID. This member is only valid if the AddressCount member is set to zero. The AddressCount member is set to zero to notify a miniport driver or other layered driver to clear the list of network-layer addresses on a bound interface. The protocol can be one of the following values:
NDIS_PROTOCOL_ID_DEFAULT
Default protocol
NDIS_PROTOCOL_ID_TCP_IP
TCP/IP protocol
NDIS_PROTOCOL_ID_IPX
Netware IPX protocol
NDIS_PROTOCOL_ID_NBF
NetBIOS protocol
Address
Array of network-layer addresses of type NETWORK_ADDRESS. The AddressCount member specifies the number of elements in this array.
typedef struct _NETWORK_ADDRESS {
  USHORT  AddressLength; 
  USHORT  AddressType; 
  UCHAR   Address[1]; 
} NETWORK_ADDRESS, *PNETWORK_ADDRESS;
The members of this structure contain the following information:
AddressLength
Specifies the size, in bytes, of this network-layer address. The Address member contains the array of bytes that specify this address.
AddressType
Specifies the protocol type that sends this OID and this network-layer address. This member is only valid if the AddressCount member in the NETWORK_ADDRESS_LIST structure is set to a nonzero value. The AddressCount member in NETWORK_ADDRESS_LIST is set to a nonzero value to notify a miniport driver or other layered driver to change the list of network-layer addresses on a bound interface. Protocol types are defined in the preceding list.
Address
Array of bytes that specify this network-layer address. The AddressLength member specifies the number of bytes in this array.
The transport can call the NdisRequest function and can pass an NDIS_REQUEST structure that is filled with the OID_GEN_NETWORK_LAYER_ADDRESSES code. This call notifies a bound instance of a change in the addresses that are associated with that instance. In this call, the transport also passes the bound instance in the NdisBindingHandle parameter. The bound instance is the binding set up between the transport and the underlying miniport driver or other layered driver. For this call, the transport should fill the InformationBuffer member of NDIS_REQUEST with a pointer to a TRANSPORT_ADDRESS structure. TRANSPORT_ADDRESS corresponds to a NETWORK_ADDRESS_LIST structure and should contain the list of network-layer addresses.
Suppose a transport passes addresses through an intermediate driver down to an underlying miniport driver. If the intermediate driver also requires the addresses, it should take note of them before passing them on to the underlying miniport driver. An underlying miniport driver, especially a legacy driver, can return a status value of NDIS_STATUS_NOT_SUPPORTED or NDIS_STATUS_SUCCESS. The underlying miniport driver propagates the status of the operation back up towards the transport. If the intermediate driver must continue receiving address notifications, and if it is necessary, the intermediate driver should change the status to NDIS_STATUS_SUCCESS.Otherwise, the transport might interpret NDIS_STATUS_NOT_SUPPORTED as an indication that the underlying miniport driver does not require that the transport issue additional address updates. If NDIS_STATUS_SUCCESS is returned, transports are obligated to continue notifying underlying drivers of any change in associated addresses, including addition and deletion of addresses.
A protocol can set the AddressCount member of TRANSPORT_ADDRESS to zero to notify a miniport driver or other layered driver to clear the list of network-layer addresses on a bound interface. If AddressCount is set to zero,the AddressType member in NETWORK_ADDRESS_LIST is valid and the AddressType members in NETWORK_ADDRESS structures are not valid. On the other hand, a protocol can set AddressCount to a nonzero value to notify a miniport driver or other layered driver to change the list of network-layer addresses on a bound interface. In this case, the AddressType member in NETWORK_ADDRESS_LIST is not valid and the AddressType members in NETWORK_ADDRESS structures are valid.
 
 
 
在F:\WINDDK\2600\src\network\ndis\e100bex\mp_req.c中提供了一个获得网卡ip地址组中第一个地址的函数MPSetNetworkAddress()
 
NDIS_STATUS
MPSetNetworkAddress(
    IN PMP_ADAPTER  pAdapter,
    IN PVOID        InformationBuffer,
    IN ULONG        InformationBufferLength,
    IN PULONG       BytesRead,
    IN PULONG       BytesNeeded
    )
/*++
Routine Description:
    Called when the protocol above us wants to let us know about
    the network address(es) assigned to this interface.
    . We pick the first IP address given to us.
Arguments:
    pAdapter                   - Pointer to the ELAN
    InformationBuffer       - Holds the data to be set.
    InformationBufferLength - The length of InformationBuffer.
    BytesRead               - If the call is successful, returns the number
                              of bytes read from InformationBuffer.
    BytesNeeded             - If there is not enough data in InformationBuffer
                              to satisfy the OID, returns the amount of storage
                              needed.
Return Value:
--*/
{
    NETWORK_ADDRESS_LIST UNALIGNED *  pAddrList = NULL;
    NETWORK_ADDRESS UNALIGNED *       pAddr = NULL;
    NETWORK_ADDRESS_IP UNALIGNED *    pIpAddr= NULL;
    ULONG                             Size;
    NDIS_STATUS                       Status;
    //
    //  Initialize.
    //
    *BytesRead = 0;
    Status = NDIS_STATUS_SUCCESS;
    pAddrList = (NETWORK_ADDRESS_LIST UNALIGNED *)InformationBuffer;
    do
    {
        *BytesNeeded = sizeof(*pAddrList) -
                        FIELD_OFFSET(NETWORK_ADDRESS_LIST, Address) +
                        sizeof(NETWORK_ADDRESS) -
                        FIELD_OFFSET(NETWORK_ADDRESS, Address);
        if (InformationBufferLength < *BytesNeeded)
        {
            Status = NDIS_STATUS_INVALID_LENGTH;
            break;
        }
        if (pAddrList->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
        {
            // Not interesting.
            break;
        }
        if (pAddrList->AddressCount <= 0)
        {
            Status = NDIS_STATUS_INVALID_DATA;
            break;
        }
        pAddr = (NETWORK_ADDRESS UNALIGNED *)&pAddrList->Address[0];
        if ((pAddr->AddressLength > InformationBufferLength - *BytesNeeded) ||
            (pAddr->AddressLength == 0))
        {
            Status = NDIS_STATUS_INVALID_LENGTH;
            break;
        }
        if (pAddr->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
        {
            // Not interesting.
            break;
        }
        if (pAddr->AddressLength < sizeof(NETWORK_ADDRESS_IP))
        {
            Status = NDIS_STATUS_INVALID_LENGTH;
            break;
        }
       
        pIpAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
        Size = sizeof(pIpAddr->in_addr);
        //
        //  Copy the network address in.
        //
        NdisMoveMemory(&pAdapter->PoMgmt.IPAddress.u32 , &pIpAddr->in_addr, sizeof(pIpAddr->in_addr));
        Status = NDIS_STATUS_SUCCESS;
       
        *BytesRead = InformationBufferLength;
    } while (FALSE);
    return Status;
}
 
 
在passthru的PtRequestComplete()中做如下修改就可以得到主机的IP地址:
VOID
PtRequestComplete(
 IN  NDIS_HANDLE   ProtocolBindingContext,
 IN  PNDIS_REQUEST  NdisRequest,
 IN  NDIS_STATUS   Status
 )
/*++
Routine Description:
 Completion handler for the previously posted request. All OIDS
    are completed by and sent to the same miniport that they were requested for.
 If Oid == OID_PNP_QUERY_POWER then the data structure needs to returned with all entries =
 NdisDeviceStateUnspecified
Arguments:
 ProtocolBindingContext Pointer to the adapter structure
 NdisRequest    The posted request
 Status     Completion status
Return Value:
 None
--*/
{
 PADAPT  pAdapt =(PADAPT)ProtocolBindingContext;
 NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
 PNETWORK_ADDRESS_LIST UNALIGNED pAddrList = NULL;
 PNETWORK_ADDRESS UNALIGNED   pAddr = NULL;
 PNETWORK_ADDRESS_IP UNALIGNED  pIpAddr= NULL;
 ULONG Size = 0;
 //
 // Since our request is not outstanding anymore
 //
 ASSERT(pAdapt->OutstandingRequests == TRUE);
 pAdapt->OutstandingRequests = FALSE;
 //
 // Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
 //
 switch (NdisRequest->RequestType)
 {
   case NdisRequestQueryInformation:
  //
  // We never pass OID_PNP_QUERY_POWER down.
  //
  ASSERT(Oid != OID_PNP_QUERY_POWER);
  if ((Oid == OID_PNP_CAPABILITIES) && (Status == NDIS_STATUS_SUCCESS))
  {
   MPQueryPNPCapabilities(pAdapt, &Status);
  }
  *pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
  *pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
  
  if ((Oid == OID_GEN_MAC_OPTIONS) && (Status == NDIS_STATUS_SUCCESS))
  {
   //
   // Remove the no-loopback bit from mac-options. In essence we are
   // telling NDIS that we can handle loopback. We don't, but the
   // interface below us does. If we do not do this, then loopback
   // processing happens both below us and above us. This is wasteful
   // at best and if Netmon is running, it will see multiple copies
   // of loopback packets when sniffing above us.
   //
   // Only the lowest miniport is a stack of layered miniports should
   // ever report this bit set to NDIS.
   //
   *(PULONG)NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer &= ~NDIS_MAC_OPTION_NO_LOOPBACK;
  }
  NdisMQueryInformationComplete(pAdapt->MiniportHandle,
           Status);
  break;
   case NdisRequestSetInformation:
  ASSERT( Oid != OID_PNP_SET_POWER);

  // 获得本机IP地址
  while(Oid == OID_GEN_NETWORK_LAYER_ADDRESSES)
  {
   KdPrint(("=>OID_GEN_NETWORK_LAYER_ADDRESSES\n"));
   pAddrList = (PNETWORK_ADDRESS_LIST)NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
   if (pAddrList->AddressCount <= 0)
   {
    break;
   }
   pAddr = (PNETWORK_ADDRESS)&pAddrList->Address[0];
   if (pAddr->AddressType != NDIS_PROTOCOL_ID_TCP_IP)
   {
    break;
   }
   pIpAddr = (NETWORK_ADDRESS_IP UNALIGNED *)&pAddr->Address[0];
   LOCAL_IP = RtlUlongByteSwap(pIpAddr->in_addr);
   KdPrint(("####OID_GEN_NETWORK_LAYER_ADDRESSES = %.8X\n",LOCAL_IP));
    break;
  };

  *pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
  *pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
  NdisMSetInformationComplete(pAdapt->MiniportHandle,
         Status);
  break;
   default:
  ASSERT(0);
  break;
 }
 
}

0

收藏

hello_world

117篇文章,149W+人气,0粉丝

Ctrl+Enter 发布

发布

取消