windowsdriverndisminiport

Windows Network Device Driver: Set link UP/DOWN from within the driver


I am writing a network driver for Windows. I want to do something like the pseudocode below:

Init_interface_link_status = disconnected (Equivalent to DOWN in Linux)
Repeat using delayed workitem:
  if (condition is true)
    interface_link_status = connected (UP)
    break
  else
    interface_link_status = disconnected (DOWN)

All this happens inside the driver code.

I am using Windows Driver Samples as reference. I have found something that looks promising: https://github.com/microsoft/Windows-driver-samples/blob/master/network/ndis/netvmini/6x/adapter.c#L353 AdapterGeneral.MediaConnectState = HWGetMediaConnectStatus(Adapter); I can set this MediaConnectSate to MediaConnectStateDisconnected here and the driver initialises in Disconnected state which is what I want. But I can't find a way to change this state elsewhere after the driver is initialised.


Solution

  • Found inspiration from a proprietary network driver code. This function turns interface on/off:

    
    VOID NSUChangeAdapterLinkState(
        _In_ PMP_ADAPTER Adapter,
        _In_ BOOLEAN TurnInterfaceUP)
    /*++
    Routine Description:
        Change Adapter Link's state. This is equivalent to doing ifup/ifdown on Linux.
    Arguments:
        Adapter              - Pointer to our adapter
        TurnInterfaceUP      - Pass TRUE to turn interface UP, FALSE to turn DOWN
    Return Value:
        None
    --*/
    {
        NDIS_LINK_STATE LinkState;
        NDIS_STATUS_INDICATION StatusIndication;
    
        RtlZeroMemory(&LinkState, sizeof(LinkState));
        LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
        LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
        LinkState.Header.Size = NDIS_SIZEOF_LINK_STATE_REVISION_1;
    
        if (TurnInterfaceUP)
        {
            LinkState.MediaConnectState = MediaConnectStateConnected;
            MP_CLEAR_FLAG(Adapter, fMP_DISCONNECTED);
        } else
        {
            LinkState.MediaConnectState = MediaConnectStateDisconnected;
            MP_SET_FLAG(Adapter, fMP_DISCONNECTED);
        }
    
        LinkState.RcvLinkSpeed = Adapter->ulLinkRecvSpeed;
        LinkState.XmitLinkSpeed = Adapter->ulLinkSendSpeed; 
        LinkState.MediaDuplexState = MediaDuplexStateFull;
    
        RtlZeroMemory(&StatusIndication, sizeof(StatusIndication));
        StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
        StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
        StatusIndication.Header.Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1;
        StatusIndication.SourceHandle = Adapter->AdapterHandle;
        StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
        StatusIndication.StatusBuffer = &LinkState;
        StatusIndication.StatusBufferSize = sizeof(NDIS_LINK_STATE);
    
        NdisMIndicateStatusEx(Adapter->AdapterHandle, &StatusIndication);
    }