Esempio n. 1
0
VOID tapReadPermanentAddress(__in PTAP_ADAPTER_CONTEXT Adapter,
                             __in NDIS_HANDLE ConfigurationHandle, __out MACADDR PermanentAddress) {
  NDIS_STATUS status;
  NDIS_CONFIGURATION_PARAMETER *configParameter;
  NDIS_STRING macKey = NDIS_STRING_CONST("MAC");
  ANSI_STRING macString;
  BOOLEAN macFromRegistry = FALSE;

  // Read MAC parameter from registry.
  NdisReadConfiguration(&status, &configParameter, ConfigurationHandle, &macKey,
                        NdisParameterString);

  if (status == NDIS_STATUS_SUCCESS) {
    if ((configParameter->ParameterType == NdisParameterString) &&
        (configParameter->ParameterData.StringData.Length >= 12)) {
      if (RtlUnicodeStringToAnsiString(&macString, &configParameter->ParameterData.StringData,
                                       TRUE) == STATUS_SUCCESS) {
        macFromRegistry = ParseMAC(PermanentAddress, macString.Buffer);
        RtlFreeAnsiString(&macString);
      }
    }
  }

  if (!macFromRegistry) {
    //
    // There is no (valid) address stashed in the registry parameter.
    //
    // Make up a dummy mac address based on the ANSI representation of the
    // NetCfgInstanceId GUID.
    //
    GenerateRandomMac(PermanentAddress, MINIPORT_INSTANCE_ID(Adapter));
  }
}
Esempio n. 2
0
VOID tapWaitForReceiveNblInFlightCountZeroEvent(__in PTAP_ADAPTER_CONTEXT Adapter) {
  LONG nblCount;

  //
  // Wait until higher-level protocol has returned all NBLs
  // to the driver.
  //

  // Add one NBL "bias" to insure allow event to be reset safely.
  nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
  ASSERT(nblCount > 0);
  NdisResetEvent(&Adapter->ReceiveNblInFlightCountZeroEvent);

  //
  // Now remove the bias and wait for the ReceiveNblInFlightCountZeroEvent
  // if the count returned is not zero.
  //
  nblCount = NdisInterlockedDecrement(&Adapter->ReceiveNblInFlightCount);
  ASSERT(nblCount >= 0);

  if (nblCount) {
    LARGE_INTEGER startTime, currentTime;

    NdisGetSystemUpTimeEx(&startTime);

    for (;;) {
      BOOLEAN waitResult =
          NdisWaitEvent(&Adapter->ReceiveNblInFlightCountZeroEvent, TAP_WAIT_POLL_LOOP_TIMEOUT);

      NdisGetSystemUpTimeEx(&currentTime);

      if (waitResult) {
        break;
      }

      DEBUGP(("[%s] Waiting for %d in-flight receive NBLs to be returned.\n",
              MINIPORT_INSTANCE_ID(Adapter), Adapter->ReceiveNblInFlightCount));
    }

    DEBUGP(("[%s] Waited %d ms for all in-flight NBLs to be returned.\n",
            MINIPORT_INSTANCE_ID(Adapter), (currentTime.LowPart - startTime.LowPart)));
  }
}
Esempio n. 3
0
VOID
IndicateReceivePacket(
    __in PTAP_ADAPTER_CONTEXT  Adapter,
    __in PUCHAR packetData,
    __in const unsigned int packetLength
    )
{
    PUCHAR  injectBuffer;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas inject path
    // the code below will simply ignore inject packets passed to the driver while
    // the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the inject packet - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(Adapter) != NDIS_STATUS_SUCCESS)
    {
        DEBUGP (("[%s] Lying send in IndicateReceivePacket while adapter paused\n",
            MINIPORT_INSTANCE_ID (Adapter)));

        return;
    }

    // Allocate flat buffer for packet data.
    injectBuffer = (PUCHAR )NdisAllocateMemoryWithTagPriority(
                        Adapter->MiniportAdapterHandle,
                        packetLength,
                        TAP_RX_INJECT_BUFFER_TAG,
                        NormalPoolPriority
                        );

    if( injectBuffer)
    {
        PMDL    mdl;

        // Copy packet data to flat buffer.
        NdisMoveMemory (injectBuffer, packetData, packetLength);

        // Allocate MDL for flat buffer.
        mdl = NdisAllocateMdl(
                Adapter->MiniportAdapterHandle,
                injectBuffer,
                packetLength
                );

        if( mdl )
        {
            PNET_BUFFER_LIST    netBufferList;

            mdl->Next = NULL;   // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                                Adapter->ReceiveNblPool,
                                0,                  // ContextSize
                                0,                  // ContextBackFill
                                mdl,                // MDL chain
                                0,
                                packetLength
                                );

            if(netBufferList != NULL)
            {
                ULONG       receiveFlags = 0;
                LONG        nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                if(KeGetCurrentIrql() == DISPATCH_LEVEL)
                {
                    receiveFlags |= NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
                }

                // Set flag indicating that this is an injected packet
                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED);

                netBufferList->MiniportReserved[0] = NULL;
                netBufferList->MiniportReserved[1] = NULL;

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                netBufferList->SourceHandle = Adapter->MiniportAdapterHandle;

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    Adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    receiveFlags
                    );

                return;
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateNetBufferAndNetBufferList failed in IndicateReceivePacket\n",
                    MINIPORT_INSTANCE_ID (Adapter)));
                NOTE_ERROR ();

                NdisFreeMdl(mdl);
                NdisFreeMemory(injectBuffer,0,0);
            }
        }
        else
        {
            DEBUGP (("[%s] NdisAllocateMdl failed in IndicateReceivePacket\n",
                MINIPORT_INSTANCE_ID (Adapter)));
            NOTE_ERROR ();

            NdisFreeMemory(injectBuffer,0,0);
        }
    }
    else
    {
        DEBUGP (("[%s] NdisAllocateMemoryWithTagPriority failed in IndicateReceivePacket\n",
            MINIPORT_INSTANCE_ID (Adapter)));
        NOTE_ERROR ();
    }
}
Esempio n. 4
0
// IRP_MJ_WRITE callback.
NTSTATUS
TapDeviceWrite(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )
{
    NTSTATUS                ntStatus = STATUS_SUCCESS;// Assume success
    PIO_STACK_LOCATION      irpSp;// Pointer to current stack location
    PTAP_ADAPTER_CONTEXT    adapter = NULL;
    ULONG                   dataLength;

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    // Fetch adapter context for this device.
    // --------------------------------------
    // Adapter pointer was stashed in FsContext when handle was opened.
    //
    adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;

    ASSERT(adapter);

    //
    // Sanity checks on state variables
    //
    if (!tapAdapterReadAndWriteReady(adapter))
    {
        //DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
        //    MINIPORT_INSTANCE_ID (adapter)));
        //NOTE_ERROR();

        Irp->IoStatus.Status = ntStatus = STATUS_CANCELLED;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    // Save IRP-accessible copy of buffer length
    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    if (Irp->MdlAddress == NULL)
    {
        DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    //
    // Try to get a virtual address for the MDL.
    //
    NdisQueryMdl(
        Irp->MdlAddress,
        &Irp->AssociatedIrp.SystemBuffer,
        &dataLength,
        NormalPagePriority
        );

    if (Irp->AssociatedIrp.SystemBuffer == NULL)
    {
        DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    ASSERT(dataLength == irpSp->Parameters.Write.Length);

    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas receive path
    // the code below will perform a "lying send" for write IRPs passed to the
    // driver while the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the user-mode write - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS)
    {
        if (!adapter->m_tun && ((irpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
        {
            PNET_BUFFER_LIST    netBufferList;

            DUMP_PACKET ("IRP_MJ_WRITE ETH",
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                FALSE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif
            (Irp->MdlAddress)->Next = NULL; // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                adapter->ReceiveNblPool,
                0,                  // ContextSize
                0,                  // ContextBackFill
                Irp->MdlAddress,    // MDL chain
                0,
                dataLength
                );

            if(netBufferList != NULL)
            {
                LONG    nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                // Stash IRP pointer in NBL MiniportReserved[0] field.
                netBufferList->MiniportReserved[0] = Irp;
                netBufferList->MiniportReserved[1] = NULL;

                // BUGBUG!!! Setup for IRP cancel!!!

                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    0       // ReceiveFlags
                    );

                ntStatus = STATUS_PENDING;
            }
            else
            {
                DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else if (adapter->m_tun && ((irpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
        {
            PETH_HEADER         p_UserToTap = &adapter->m_UserToTap;
            PMDL                mdl;    // Head of MDL chain.

            // For IPv6, need to use Ethernet header with IPv6 proto
            if ( IPH_GET_VER( ((IPHDR*) Irp->AssociatedIrp.SystemBuffer)->version_len) == 6 )
            {
                p_UserToTap = &adapter->m_UserToTap_IPv6;
            }

            DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
                p_UserToTap,
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                TRUE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif

            //
            // Allocate MDL for Ethernet header
            // --------------------------------
            // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
            // contains the only the Ethernet payload. Prepend the user-mode provided
            // payload with the Ethernet header pointed to by p_UserToTap.
            //
            mdl = NdisAllocateMdl(
                adapter->MiniportAdapterHandle,
                p_UserToTap,
                sizeof(ETH_HEADER)
                );

            if(mdl != NULL)
            {
                PNET_BUFFER_LIST    netBufferList;

                // Chain user's Ethernet payload behind Ethernet header.
                mdl->Next = Irp->MdlAddress;
                (Irp->MdlAddress)->Next = NULL; // No next MDL

                // Allocate the NBL and NB. Link MDL chain to NB.
                netBufferList = NdisAllocateNetBufferAndNetBufferList(
                    adapter->ReceiveNblPool,
                    0,          // ContextSize
                    0,          // ContextBackFill
                    mdl,        // MDL chain
                    0,
                    sizeof(ETH_HEADER) + dataLength
                    );

                if(netBufferList != NULL)
                {
                    LONG        nblCount;

                    NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                    // This IRP is pended.
                    IoMarkIrpPending(Irp);

                    // This IRP cannot be cancelled while in-flight.
                    IoSetCancelRoutine(Irp,NULL);

                    // Stash IRP pointer in NBL MiniportReserved[0] field.
                    netBufferList->MiniportReserved[0] = Irp;
                    netBufferList->MiniportReserved[1] = NULL;

                    // Set flag indicating that this is P2P packet
                    TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                    TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_P2P);

                    // Increment in-flight receive NBL count.
                    nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                    ASSERT(nblCount > 0 );

                    //
                    // Indicate the packet
                    //
                    NdisMIndicateReceiveNetBufferLists(
                        adapter->MiniportAdapterHandle,
                        netBufferList,
                        NDIS_DEFAULT_PORT_NUMBER,
                        1,      // NumberOfNetBufferLists
                        0       // ReceiveFlags
                        );

                    ntStatus = STATUS_PENDING;
                }
                else
                {
                    mdl->Next = NULL;
                    NdisFreeMdl(mdl);

                    DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                        MINIPORT_INSTANCE_ID (adapter)));
                    NOTE_ERROR ();

                    // Fail the IRP
                    Irp->IoStatus.Information = 0;
                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateMdl failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else
        {
            DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
                MINIPORT_INSTANCE_ID (adapter),
                irpSp->Parameters.Write.Length));
            NOTE_ERROR ();

            Irp->IoStatus.Information = 0;	// ETHERNET_HEADER_SIZE;
            Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
        }
    }
    else
    {
        DEBUGP (("[%s] Lying send in IRP_MJ_WRITE while adapter paused\n",
            MINIPORT_INSTANCE_ID (adapter)));

        ntStatus = STATUS_SUCCESS;
    }

    if (ntStatus != STATUS_PENDING)
    {
        Irp->IoStatus.Status = ntStatus;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }

    return ntStatus;
}
Esempio n. 5
0
NDIS_STATUS
AdapterCreate(__in NDIS_HANDLE MiniportAdapterHandle, __in NDIS_HANDLE MiniportDriverContext,
              __in PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters) {
  PTAP_ADAPTER_CONTEXT adapter = NULL;
  NDIS_STATUS status;

  UNREFERENCED_PARAMETER(MiniportDriverContext);
  UNREFERENCED_PARAMETER(MiniportInitParameters);

  DEBUGP(("[TAP] --> AdapterCreate\n"));

  do {
    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES regAttributes = {0};
    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES genAttributes = {0};
    NDIS_PNP_CAPABILITIES pnpCapabilities = {0};

    //
    // Allocate adapter context structure and initialize all the
    // memory resources for sending and receiving packets.
    //
    // Returns with reference count initialized to one.
    //
    adapter = tapAdapterContextAllocate(MiniportAdapterHandle);

    if (adapter == NULL) {
      DEBUGP(("[TAP] Couldn't allocate adapter memory\n"));
      status = NDIS_STATUS_RESOURCES;
      break;
    }

    // Enter the Initializing state.
    DEBUGP(("[TAP] Miniport State: Initializing\n"));

    tapAdapterAcquireLock(adapter, FALSE);
    adapter->Locked.AdapterState = MiniportInitializingState;
    tapAdapterReleaseLock(adapter, FALSE);

    //
    // First read adapter configuration from registry.
    // -----------------------------------------------
    // Subsequent device registration will fail if NetCfgInstanceId
    // has not been successfully read.
    //
    status = tapReadConfiguration(adapter);

    //
    // Set the registration attributes.
    //
    {
      C_ASSERT(sizeof(regAttributes) >=
               NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1);
    }
    regAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
    regAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
    regAttributes.Header.Revision = NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;

    regAttributes.MiniportAdapterContext = adapter;
    regAttributes.AttributeFlags = TAP_ADAPTER_ATTRIBUTES_FLAGS;

    regAttributes.CheckForHangTimeInSeconds = TAP_ADAPTER_CHECK_FOR_HANG_TIME_IN_SECONDS;
    regAttributes.InterfaceType = TAP_INTERFACE_TYPE;

    // NDIS_DECLARE_MINIPORT_ADAPTER_CONTEXT(TAP_ADAPTER_CONTEXT);
    status = NdisMSetMiniportAttributes(MiniportAdapterHandle,
                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&regAttributes);

    if (status != NDIS_STATUS_SUCCESS) {
      DEBUGP(("[TAP] NdisSetOptionalHandlers failed; Status 0x%08x\n", status));
      break;
    }

    //
    // Next, set the general attributes.
    //
    {
      C_ASSERT(sizeof(genAttributes) >= NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1);
    }
    genAttributes.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
    genAttributes.Header.Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
    genAttributes.Header.Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;

    //
    // Specify the medium type that the NIC can support but not
    // necessarily the medium type that the NIC currently uses.
    //
    genAttributes.MediaType = TAP_MEDIUM_TYPE;

    //
    // Specifiy medium type that the NIC currently uses.
    //
    genAttributes.PhysicalMediumType = TAP_PHYSICAL_MEDIUM;

    //
    // Specifiy the maximum network frame size, in bytes, that the NIC
    // supports excluding the header.
    //
    genAttributes.MtuSize = TAP_FRAME_MAX_DATA_SIZE;
    genAttributes.MaxXmitLinkSpeed = TAP_XMIT_SPEED;
    genAttributes.XmitLinkSpeed = TAP_XMIT_SPEED;
    genAttributes.MaxRcvLinkSpeed = TAP_RECV_SPEED;
    genAttributes.RcvLinkSpeed = TAP_RECV_SPEED;

    if (adapter->MediaStateAlwaysConnected) {
      DEBUGP(("[%s] Initial MediaConnectState: Connected\n", MINIPORT_INSTANCE_ID(adapter)));

      genAttributes.MediaConnectState = MediaConnectStateConnected;
    } else {
      DEBUGP(("[%s] Initial MediaConnectState: Disconnected\n", MINIPORT_INSTANCE_ID(adapter)));

      genAttributes.MediaConnectState = MediaConnectStateDisconnected;
    }

    genAttributes.MediaDuplexState = MediaDuplexStateFull;

    //
    // The maximum number of bytes the NIC can provide as lookahead data.
    // If that value is different from the size of the lookahead buffer
    // supported by bound protocols, NDIS will call MiniportOidRequest to
    // set the size of the lookahead buffer provided by the miniport driver
    // to the minimum of the miniport driver and protocol(s) values. If the
    // driver always indicates up full packets with
    // NdisMIndicateReceiveNetBufferLists, it should set this value to the
    // maximum total frame size, which excludes the header.
    //
    // Upper-layer drivers examine lookahead data to determine whether a
    // packet that is associated with the lookahead data is intended for
    // one or more of their clients. If the underlying driver supports
    // multipacket receive indications, bound protocols are given full net
    // packets on every indication. Consequently, this value is identical
    // to that returned for OID_GEN_RECEIVE_BLOCK_SIZE.
    //
    genAttributes.LookaheadSize = TAP_MAX_LOOKAHEAD;
    genAttributes.MacOptions = TAP_MAC_OPTIONS;
    genAttributes.SupportedPacketFilters = TAP_SUPPORTED_FILTERS;

    //
    // The maximum number of multicast addresses the NIC driver can manage.
    // This list is global for all protocols bound to (or above) the NIC.
    // Consequently, a protocol can receive NDIS_STATUS_MULTICAST_FULL from
    // the NIC driver when attempting to set the multicast address list,
    // even if the number of elements in the given list is less than the
    // number originally returned for this query.
    //
    genAttributes.MaxMulticastListSize = TAP_MAX_MCAST_LIST;
    genAttributes.MacAddressLength = MACADDR_SIZE;

    //
    // Return the MAC address of the NIC burnt in the hardware.
    //
    ETH_COPY_NETWORK_ADDRESS(genAttributes.PermanentMacAddress, adapter->PermanentAddress);

    //
    // Return the MAC address the NIC is currently programmed to use. Note
    // that this address could be different from the permananent address as
    // the user can override using registry. Read NdisReadNetworkAddress
    // doc for more info.
    //
    ETH_COPY_NETWORK_ADDRESS(genAttributes.CurrentMacAddress, adapter->CurrentAddress);

    genAttributes.RecvScaleCapabilities = NULL;
    genAttributes.AccessType = TAP_ACCESS_TYPE;
    genAttributes.DirectionType = TAP_DIRECTION_TYPE;
    genAttributes.ConnectionType = TAP_CONNECTION_TYPE;
    genAttributes.IfType = TAP_IFTYPE;
    genAttributes.IfConnectorPresent = TAP_HAS_PHYSICAL_CONNECTOR;
    genAttributes.SupportedStatistics = TAP_SUPPORTED_STATISTICS;
    genAttributes.SupportedPauseFunctions =
        NdisPauseFunctionsUnsupported;  // IEEE 802.3 pause frames
    genAttributes.DataBackFillSize = 0;
    genAttributes.ContextBackFillSize = 0;

    //
    // The SupportedOidList is an array of OIDs for objects that the
    // underlying driver or its NIC supports.  Objects include general,
    // media-specific, and implementation-specific objects. NDIS forwards a
    // subset of the returned list to protocols that make this query. That
    // is, NDIS filters any supported statistics OIDs out of the list
    // because protocols never make statistics queries.
    //
    genAttributes.SupportedOidList = TAPSupportedOids;
    genAttributes.SupportedOidListLength = sizeof(TAPSupportedOids);
    genAttributes.AutoNegotiationFlags = NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED;

    //
    // Set power management capabilities
    //
    NdisZeroMemory(&pnpCapabilities, sizeof(pnpCapabilities));
    pnpCapabilities.WakeUpCapabilities.MinMagicPacketWakeUp = NdisDeviceStateUnspecified;
    pnpCapabilities.WakeUpCapabilities.MinPatternWakeUp = NdisDeviceStateUnspecified;
    genAttributes.PowerManagementCapabilities = &pnpCapabilities;

    status = NdisMSetMiniportAttributes(MiniportAdapterHandle,
                                        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&genAttributes);

    if (status != NDIS_STATUS_SUCCESS) {
      DEBUGP(("[TAP] NdisMSetMiniportAttributes failed; Status 0x%08x\n", status));
      break;
    }

    //
    // Create the Win32 device I/O interface.
    //
    status = CreateTapDevice(adapter);

    if (status == NDIS_STATUS_SUCCESS) {
      // Add this adapter to the global adapter list.
      tapAdapterContextAddToGlobalList(adapter);
    } else {
      DEBUGP(("[TAP] CreateTapDevice failed; Status 0x%08x\n", status));
      break;
    }
  } while (FALSE);

  if (status == NDIS_STATUS_SUCCESS) {
    // Enter the Paused state if initialization is complete.
    DEBUGP(("[TAP] Miniport State: Paused\n"));

    tapAdapterAcquireLock(adapter, FALSE);
    adapter->Locked.AdapterState = MiniportPausedState;
    tapAdapterReleaseLock(adapter, FALSE);
  } else {
    if (adapter != NULL) {
      DEBUGP(("[TAP] Miniport State: Halted\n"));

      //
      // Remove reference when adapter context was allocated
      // ---------------------------------------------------
      // This should result in freeing adapter context memory
      // and assiciated resources.
      //
      tapAdapterContextDereference(adapter);
      adapter = NULL;
    }
  }

  DEBUGP(("[TAP] <-- AdapterCreate; status = %8.8X\n", status));

  return status;
}
Esempio n. 6
0
NDIS_STATUS
tapReadConfiguration(__in PTAP_ADAPTER_CONTEXT Adapter) {
  NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  NDIS_CONFIGURATION_OBJECT configObject;
  NDIS_HANDLE configHandle;

  DEBUGP(("[TAP] --> tapReadConfiguration\n"));

  //
  // Setup defaults in case configuration cannot be opened.
  //
  Adapter->MtuSize = ETHERNET_MTU;
  Adapter->MediaStateAlwaysConnected = FALSE;
  Adapter->LogicalMediaState = FALSE;
  Adapter->AllowNonAdmin = FALSE;
  //
  // Open the registry for this adapter to read advanced
  // configuration parameters stored by the INF file.
  //
  NdisZeroMemory(&configObject, sizeof(configObject));

  { C_ASSERT(sizeof(configObject) >= NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1); }
  configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
  configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
  configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;

  configObject.NdisHandle = Adapter->MiniportAdapterHandle;
  configObject.Flags = 0;

  status = NdisOpenConfigurationEx(&configObject, &configHandle);

  // Read on the opened configuration handle.
  if (status == NDIS_STATUS_SUCCESS) {
    NDIS_CONFIGURATION_PARAMETER *configParameter;
    NDIS_STRING mkey = NDIS_STRING_CONST("NetCfgInstanceId");

    //
    // Read NetCfgInstanceId from the registry.
    // ------------------------------------
    // NetCfgInstanceId is required to create device and associated
    // symbolic link for the adapter device.
    //
    // NetCfgInstanceId is  a GUID string provided by NDIS that identifies
    // the adapter instance. An example is:
    //
    //    NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0}
    //
    // Other names are derived from NetCfgInstanceId. For example, MiniportName:
    //
    //    MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0}
    //
    NdisReadConfiguration(&status, &configParameter, configHandle, &mkey, NdisParameterString);

    if (status == NDIS_STATUS_SUCCESS) {
      if (configParameter->ParameterType == NdisParameterString &&
          configParameter->ParameterData.StringData.Length <=
              sizeof(Adapter->NetCfgInstanceIdBuffer) - sizeof(WCHAR)) {
        DEBUGP(("[TAP] NdisReadConfiguration (NetCfgInstanceId=%wZ)\n",
                &configParameter->ParameterData.StringData));

        // Save NetCfgInstanceId as UNICODE_STRING.
        Adapter->NetCfgInstanceId.Length = Adapter->NetCfgInstanceId.MaximumLength =
            configParameter->ParameterData.StringData.Length;

        Adapter->NetCfgInstanceId.Buffer = Adapter->NetCfgInstanceIdBuffer;

        NdisMoveMemory(Adapter->NetCfgInstanceId.Buffer,
                       configParameter->ParameterData.StringData.Buffer,
                       Adapter->NetCfgInstanceId.Length);

        // Save NetCfgInstanceId as ANSI_STRING as well.
        if (RtlUnicodeStringToAnsiString(&Adapter->NetCfgInstanceIdAnsi,
                                         &configParameter->ParameterData.StringData,
                                         TRUE) != STATUS_SUCCESS) {
          DEBUGP(("[TAP] NetCfgInstanceId ANSI name conversion failed\n"));
          status = NDIS_STATUS_RESOURCES;
        }
      } else {
        DEBUGP(("[TAP] NetCfgInstanceId has invalid type\n"));
        status = NDIS_STATUS_INVALID_DATA;
      }
    } else {
      DEBUGP(("[TAP] NetCfgInstanceId failed\n"));
      status = NDIS_STATUS_INVALID_DATA;
    }

    if (status == NDIS_STATUS_SUCCESS) {
      NDIS_STATUS localStatus;  // Use default if these fail.
      NDIS_CONFIGURATION_PARAMETER *configParameter;
      NDIS_STRING mtuKey = NDIS_STRING_CONST("MTU");
      NDIS_STRING mediaStatusKey = NDIS_STRING_CONST("MediaStatus");
#if ENABLE_NONADMIN
      NDIS_STRING allowNonAdminKey = NDIS_STRING_CONST("AllowNonAdmin");
#endif

      // Read MTU from the registry.
      NdisReadConfiguration(&localStatus, &configParameter, configHandle, &mtuKey,
                            NdisParameterInteger);

      if (localStatus == NDIS_STATUS_SUCCESS) {
        if (configParameter->ParameterType == NdisParameterInteger) {
          int mtu = configParameter->ParameterData.IntegerData;

          if (mtu == 0) {
            mtu = ETHERNET_MTU;
          }

          // Sanity check
          if (mtu < MINIMUM_MTU) {
            mtu = MINIMUM_MTU;
          } else if (mtu > MAXIMUM_MTU) {
            mtu = MAXIMUM_MTU;
          }

          Adapter->MtuSize = mtu;
        }
      }

      DEBUGP(("[%s] Using MTU %d\n", MINIPORT_INSTANCE_ID(Adapter), Adapter->MtuSize));

      // Read MediaStatus setting from registry.
      NdisReadConfiguration(&localStatus, &configParameter, configHandle, &mediaStatusKey,
                            NdisParameterInteger);

      if (localStatus == NDIS_STATUS_SUCCESS) {
        if (configParameter->ParameterType == NdisParameterInteger) {
          if (configParameter->ParameterData.IntegerData == 0) {
            // Connect state is appplication controlled.
            DEBUGP(("[%s] Initial MediaConnectState: Application Controlled\n",
                    MINIPORT_INSTANCE_ID(Adapter)));

            Adapter->MediaStateAlwaysConnected = FALSE;
            Adapter->LogicalMediaState = FALSE;
          } else {
            // Connect state is always connected.
            DEBUGP(("[%s] Initial MediaConnectState: Always Connected\n",
                    MINIPORT_INSTANCE_ID(Adapter)));

            Adapter->MediaStateAlwaysConnected = TRUE;
            Adapter->LogicalMediaState = TRUE;
          }
        }
      }

      // Read MAC PermanentAddress setting from registry.
      tapReadPermanentAddress(Adapter, configHandle, Adapter->PermanentAddress);

      DEBUGP(("[%s] Using MAC PermanentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
              MINIPORT_INSTANCE_ID(Adapter), Adapter->PermanentAddress[0],
              Adapter->PermanentAddress[1], Adapter->PermanentAddress[2],
              Adapter->PermanentAddress[3], Adapter->PermanentAddress[4],
              Adapter->PermanentAddress[5]));

      // Now seed the current MAC address with the permanent address.
      ETH_COPY_NETWORK_ADDRESS(Adapter->CurrentAddress, Adapter->PermanentAddress);

      DEBUGP(("[%s] Using MAC CurrentAddress %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
              MINIPORT_INSTANCE_ID(Adapter), Adapter->CurrentAddress[0], Adapter->CurrentAddress[1],
              Adapter->CurrentAddress[2], Adapter->CurrentAddress[3], Adapter->CurrentAddress[4],
              Adapter->CurrentAddress[5]));

      // Read optional AllowNonAdmin setting from registry.
#if ENABLE_NONADMIN
      NdisReadConfiguration(&localStatus, &configParameter, configHandle, &allowNonAdminKey,
                            NdisParameterInteger);

      if (localStatus == NDIS_STATUS_SUCCESS) {
        if (configParameter->ParameterType == NdisParameterInteger) {
          Adapter->AllowNonAdmin = TRUE;
        }
      }
#endif
    }

    // Close the configuration handle.
    NdisCloseConfiguration(configHandle);
  } else {
    DEBUGP(("[TAP] Couldn't open adapter registry\n"));
  }

  DEBUGP(("[TAP] <-- tapReadConfiguration; status = %8.8X\n", status));

  return status;
}
Esempio n. 7
0
// IRP_MJ_CREATE
NTSTATUS
TapDeviceCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*++

Routine Description:

    This routine is called by the I/O system when the device is opened.

    No action is performed other than completing the request successfully.

Arguments:

    DeviceObject - a pointer to the object that represents the device
    that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    NT status code

--*/
{
  NDIS_STATUS status;
  PIO_STACK_LOCATION irpSp;  // Pointer to current stack location
  PTAP_ADAPTER_CONTEXT adapter = NULL;
  PFILE_OBJECT originalFileObject;

  PAGED_CODE();

  DEBUGP(("[TAP] --> TapDeviceCreate\n"));

  irpSp = IoGetCurrentIrpStackLocation(Irp);

  //
  // Invalidate file context
  //
  irpSp->FileObject->FsContext = NULL;
  irpSp->FileObject->FsContext2 = NULL;

  //
  // Find adapter context for this device.
  // -------------------------------------
  // Returns with added reference on adapter context.
  //
  adapter = tapAdapterContextFromDeviceObject(DeviceObject);

  // Insure that adapter exists.
  ASSERT(adapter);

  if (adapter == NULL) {
    DEBUGP(("[TAP] release [%d.%d] open request; adapter not found\n", TAP_DRIVER_MAJOR_VERSION,
            TAP_DRIVER_MINOR_VERSION));

    Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
    Irp->IoStatus.Information = 0;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return STATUS_DEVICE_DOES_NOT_EXIST;
  }

  DEBUGP(("[%s] [TAP] release [%d.%d] open request (TapFileIsOpen=%d)\n",
          MINIPORT_INSTANCE_ID(adapter), TAP_DRIVER_MAJOR_VERSION, TAP_DRIVER_MINOR_VERSION,
          adapter->TapFileIsOpen));

  // Enforce exclusive access
  originalFileObject =
      InterlockedCompareExchangePointer(&adapter->TapFileObject, irpSp->FileObject, NULL);

  if (originalFileObject == NULL) {
    irpSp->FileObject->FsContext = adapter;  // Quick reference

    status = STATUS_SUCCESS;
  } else {
    status = STATUS_UNSUCCESSFUL;
  }

  // Release the lock.
  // tapAdapterReleaseLock(adapter,FALSE);

  if (status == STATUS_SUCCESS) {
    // Reset adapter state on successful open.
    tapResetAdapterState(adapter);

    adapter->TapFileIsOpen = 1;  // Legacy...

    // NOTE!!! Reference added by tapAdapterContextFromDeviceObject
    // will be removed when file is closed.
  } else {
    DEBUGP(("[%s] TAP is presently unavailable (TapFileIsOpen=%d)\n", MINIPORT_INSTANCE_ID(adapter),
            adapter->TapFileIsOpen));

    NOTE_ERROR();

    // Remove reference added by tapAdapterContextFromDeviceObject.
    tapAdapterContextDereference(adapter);
  }

  // Complete the IRP.
  Irp->IoStatus.Status = status;
  Irp->IoStatus.Information = 0;

  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  DEBUGP(("[TAP] <-- TapDeviceCreate; status = %8.8X\n", status));

  return status;
}