Someone asked me about using the MIB_IF_ROW2 structure and setting it up so I provided the below to them as an example and decided i'd post it here also in case anyone else wanted use info on the structure. The rest of the structre can be read as well for the items indicated by their names.
Code: Select all
; setup for x 86 this implementation but should work fine on x64 and x86 with minor changes if needed at all
; this is basic first draft example POC code
; this implementation for hardware NIC's
; example use only
Prototype PRtlZeroMemory(mem, sze) : Prototype PGetIfEntry2(pIfRow) : Prototype PGetIfTable2(pRow)
Prototype PFreeMibTable(pIfRow) : Prototype PStringFromGUID2(rguid, lpsz, cchMax)
Global ZeroMemory.PRtlZeroMemory : Global GetIfEntry2.PGetIfEntry2 : Global GetIfTable2.PGetIfTable2 : Global FreeMibTable.PFreeMibTable
Global StringFromGUID2.PStringFromGUID2
OpenLibrary(1, "Kernel32.dll") : OpenLibrary(2, "iphlpapi.dll") : OpenLibrary(3,"Ole32.dll")
ZeroMemory.PRtlZeroMemory=GetFunction(1, "RtlZeroMemory") : GetIfEntry2.PGetIfEntry2=GetFunction(2,"GetIfEntry2")
GetIfTable2.PGetIfTable2=GetFunction(2,"GetIfTable2") : FreeMibTable.PFreeMibTable=GetFunction(2,"FreeMibTable")
StringFromGUID2.PStringFromGUID2=GetFunction(3,"StringFromGUID2")
Enumeration ;#NET_IF_DIRECTION_TYPE
#NET_IF_DIRECTION_SENDRECEIVE
#NET_IF_DIRECTION_SENDONLY
#NET_IF_DIRECTION_RECEIVEONLY
#NET_IF_DIRECTION_MAXIMUM
EndEnumeration
Enumeration ; NET_IF_MEDIA_CONNECT_STATE
#MediaConnectStateUnknown
#MediaConnectStateConnected
#MediaConnectStateDisconnected
EndEnumeration
Enumeration ; IF_OPER_STATUS - the type in MIB_IF_ROW2
#IfOperStatusUp = 1
#IfOperStatusDown
#IfOperStatusTesting
#IfOperStatusUnknown
#IfOperStatusDormant
#IfOperStatusNotPresent
#IfOperStatusLowerLayerDown
EndEnumeration
#IF_MAX_STRING_SIZE = 256
#IF_MAX_PHYS_ADDRESS_LENGTH = 32
#MAX_ADAPTER_NAME = 128
#MIB_IF_ADMIN_STATUS_UP = 1
#MIB_IF_ADMIN_STATUS_DOWN = 2
#MIB_IF_ADMIN_STATUS_TESTING = 3
Structure MIB_IF_ROW2_FLAGS ;->Structure MIB_IF_ROW2_FLAGS
HardwareInterface.b ;index 0
FilterInterface.b;index 1
ConnectorPresent.b;index 2
NotAuthenticated.b;index 3
NotMediaConnected.b;index 4
Paused.b;index 5
LowPower.b;index 6
EndPointInterface.b;index 7
EndStructure
Structure NET_LUID ;->Structure NET_LUID
Reserved.q[24]
NetLuidIndex.q[24]
IfType.q[16]
EndStructure
Structure MIB_IF_ROW2 ;->Structure MIB_IF_ROW2
StructureUnion ;-> NET_LUID - is another name for IF_LUID
Value.q
*Info.NET_LUID
EndStructureUnion
InterfaceIndex.l
InterfaceGuid.b[16]
Alias.w[#IF_MAX_STRING_SIZE +1]
Description.w[#IF_MAX_STRING_SIZE +1]
PhysicalAddressLength.l
PhysicalAddress.b[#IF_MAX_PHYS_ADDRESS_LENGTH]
PermanentPhysicalAddress.b[#IF_MAX_PHYS_ADDRESS_LENGTH]
Mtu.l
Type.l
TunnelType.l
MediaType.l
PhysicalMediumType.l
AccessType.l
DirectionType.l
*InterfaceAndOperStatusFlags.MIB_IF_ROW2_FLAGS
OperStatus.l
AdminStatus.l
MediaConnectState.l
NetworkGuid.b[16]
ConnectionType.l
pad.l ; need 4 byte pad here on x86 systems to read quad values correctly below ConnectionType member - may not need on x64 but not tested as only need x86 in this use
TransmitLinkSpeed.q
ReceiveLinkSpeed.q
InOctets.q
InUcastPkts.q
InNUcastPkts.q
InDiscards.q
InErrors.q
InUnknownProtos.q
InUcastOctets.q
InMulticastOctets.q
InBroadcastOctets.q
OutOctets.q
OutUcastPkts.q
OutNUcastPkts.q
OutDiscards.q
OutErrors.q
OutUcastOctets.q
OutMulticastOctets.q
OutBroadcastOctets.q
OutQLen.q ; not used
EndStructure
Structure MIB_IF_TABLE2 ;->Structure MIB_IF_TABLE2
NumEntries.l
Table.MIB_IF_ROW2[256]
EndStructure
Procedure.s ReadMIBRowBitField(number.l, index.l, length)
Protected bitfield$
bitfield$=RSet(Bin(number), 32, "0")
ProcedureReturn Mid(bitfield$, 32-index, length)
EndProcedure
Procedure.s GetMACs(mib_mac_ifindex.i, rettype.i = 0)
Protected a.i, retval.i, ifIndex.i
Protected hardwareIf.b, MIBconnectorpresent.b, MIBmediaconnected.b, MIBifendpoint.b
retval = 0
ifIndex = mib_mac_ifindex
*pIfRowmac.MIB_IF_ROW2 = AllocateMemory(SizeOf(MIB_IF_ROW2))
; zero memory to make sure clean from previous enumeration
ZeroMemory(*pIfRowmac, SizeOf(MIB_IF_ROW2))
*pIfRowmac\InterfaceIndex = ifIndex ; the index of the interface for which we need MACs/info
retval = GetIfEntry2(*pIfRowmac)
If retval = #NO_ERROR
retval = #NO_ERROR
ElseIf *pIfRowmac
FreeMemory(*pIfRowmac)
EndIf
; we only want actual hardware interface adapters and not interface software/logical constructs
; interface adapters are hardware, interfaces and seperate non-hardware adapters are software/logical constructs
; ... with actual connector to connect with (for example) lan cable from NIC to router, cable modem, etc...
; (InterfaceAndOperStatusFlags, 0, 1)) = #True if actual hardware interface adapter
; (InterfaceAndOperStatusFlags, 2, 1)) = #True if has an actual connector for lan cable from NIC to router, cable modem, etc...
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 0, 1)) = #True And Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 2, 1)) = #True
; ... that are actually in use and connected to an active network/internet/LAN etc... ... that are actually true interface that actually connect to network/internet/LAN etc...
;(InterfaceAndOperStatusFlags, 4, 1) = #False if actually connected to network media (e.g. actually in use and connected to an active network/internet/LAN etc...)
;(InterfaceAndOperStatusFlags, 7, 1) = #False If true interface that actually connects to a network
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 4, 1)) = #False And Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 7, 1)) = #False
Description$ = PeekS(@*pIfRowmac\Description, -1, #PB_Unicode)
IfIndex$ = Str(*pIfRowmac\InterfaceIndex) ; the LUID network index
ConnectionAlias$ = PeekS(@*pIfRowmac\Alias, -1, #PB_Unicode)
; perm MAC address is the one burned into the NIC and does not change
macPermPhysicalAddress$=""
For a=0 To *pIfRowmac\PhysicalAddressLength-1
If a
macPermPhysicalAddress$+":"
EndIf
byte.b=PeekB(@*pIfRowmac\PermanentPhysicalAddress+a)
If byte>=0
macPermPhysicalAddress$+RSet(Hex(byte),2,"0")
Else
macPermPhysicalAddress$+RSet(Hex(byte+256),2,"0")
EndIf
Next
; physical MAC address is the one that can be set or changed and will be the one in actual use
; overrides perm MAC address use and causes IP address change upon reboot in (most) DHCP assigned systems
; if same as perm MAC address then either set the same or not set/changed
; set in registry at > [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\(registry index key)]
; then set its value to the new MAC address e.g. "NetworkAddress"="001B21A22B0A" , without any spaces or other characters such as ":"
macPhysicalAddress$=""
For a=0 To *pIfRowmac\PhysicalAddressLength -1
If a
macPhysicalAddress$+":"
EndIf
byte.b=PeekB(@*pIfRowmac\PhysicalAddress+a)
If byte>=0
macPhysicalAddress$+RSet(Hex(byte),2,"0")
Else
macPhysicalAddress$+RSet(Hex(byte+256),2,"0")
EndIf
Next
If macPermPhysicalAddress$ = ""
macPermPhysicalAddress$ = " None"
Else
macPermPhysicalAddress$ = macPermPhysicalAddress$
EndIf
If macPhysicalAddress$ = ""
macPhysicalAddress$ = " None"
Else
macPhysicalAddress$ = macPhysicalAddress$
EndIf
TxLinkSpdSet$ = Str(PeekQ(@*pIfRowmac\TransmitLinkSpeed)) + " bits per second"
RxLinkSpdSet$ = Str(PeekQ(@*pIfRowmac\ReceiveLinkSpeed)) + " bits per second"
Select *pIfRowmac\DirectionType
Case #NET_IF_DIRECTION_SENDRECEIVE
directiontyp$ = "Send and Receive"
Case #NET_IF_DIRECTION_SENDONLY
directiontyp$ = "Send only"
Case #NET_IF_DIRECTION_RECEIVEONLY
directiontyp$ = "Receive only"
Default
directiontyp$ = "Direction is unspecific, unknown, or not defined. If you see this you should check for issues or updates."
EndSelect
Select *pIfRowmac\AdminStatus
Case #MIB_IF_ADMIN_STATUS_UP
adminstat$ = "Interface is initialized and enabled but not necessarily ready to transmit/receive data because it depends on the operational use status."
Case #MIB_IF_ADMIN_STATUS_DOWN
adminstat$ = "Interface is down and cannot be used to transmit or receive network data. "
Case #MIB_IF_ADMIN_STATUS_TESTING
adminstat$ = "Interface is in a test mode and no network data can be transmitted or received."
Default
adminstat$ = "Interface Admin status is unknown"
EndSelect
Select *pIfRowmac\MediaConnectState
Case #MediaConnectStateUnknown
ConnectorPlugged$ = "Connector status is unknown."
Case #MediaConnectStateConnected
ConnectorPlugged$ = "Connector is plugged in."
Case #MediaConnectStateDisconnected
ConnectorPlugged$ = "Connector is not plugged in. (On wireless connections may indicate not connected to a network.)"
Default
ConnectorPlugged$ = "Unable to detect Connector status or presence."
EndSelect
Select *pIfRowmac\OperStatus
Case #IfOperStatusUp ;= 1
oper_status$ = "Interface is up and able to pass packets."
Case #IfOperStatusDown ;= 2
oper_status$ = "Interface is down and not in a condition to pass packets."
Case #IfOperStatusTesting ;= 3
oper_status$ = "Interface is in testing mode."
Case #IfOperStatusUnknown ;= 4
oper_status$ = "Interface operational status is unknown."
Case #IfOperStatusDormant ;= 5
oper_status$ = "Interface is not up, but is in a pending state waiting for some external event"
Case #IfOperStatusNotPresent ;= 6
oper_status$ = "Interface is down specifically because some component is not present in the managed system."
Case #IfOperStatusLowerLayerDown ;= 7
oper_status$ = "Interface runs on top of one or more other interfaces and this interface is down because one or more lower-layer interfaces are down"
Default
oper_status$ = "Interface operational status is unknown, or interface is in a fault or malfunction condition."
EndSelect
; small mention blurp in rfc2863 - http://www.ietf.org/rfc/rfc2863.txt - but applicapable to hardware interface adapteres only
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 0, 1)) = 1
If *pIfRowmac\AdminStatus = 1 And *pIfRowmac\OperStatus <> 1
int_adapFault$ + "The interface is possibly in a fault condition."
Else
int_adapFault$ = "The interface does not appear to be in a fault condition."
EndIf
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 0, 1)) = 1
MIBhardwareinterface$ = "Interface is a hardware interface"
Else
MIBhardwareinterface$ = "Interface is a software/logical construct. "
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 1, 1)) = 1
MIBfilterinterface$ = "Interface is a Filter Interface"
Else
MIBfilterinterface$ = "Interface is not a Filter Interface"
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 2, 1)) = 1
MIBconnectorpresent$ = "Interface has a connector present"
Else
MIBconnectorpresent$ = "Interface does not have a connector present"
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 3, 1)) = 1
MIBportauthenticated$ = "Interface port is not authenticated. If this is a wireless device this may indicate not connected to network."
Else
MIBportauthenticated$ = "Interface port is authenticated."
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 4, 1)) = 1
MIBmediaconnected$ = "Interface is not media connected."
Else
MIBmediaconnected$ = "Interface is media connected."
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 5, 1)) = 1
MIBintfacepaused$ = "Interface is paused."
Else
MIBintfacepaused$ = "Interface is not paused."
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 6, 1)) = 1
MIBintfacelowpower$ = "Interface is at low power."
Else
MIBintfacelowpower$ = "Interface is not at low power."
EndIf
If Val(ReadMIBRowBitField(*pIfRowmac\InterfaceAndOperStatusFlags, 7, 1)) = 1
MIBifendpoint$ = "Interface is an End Point device (for example, a smart phone) and not a true interface that connects to a network."
Else
MIBifendpoint$ = "Interface is not an End Point device (for example, a smart phone) and is a true interface that connects to a network."
EndIf
If ConnectionAlias$ = ""
ConnectionAlias$ = " No Alias Assigned" ; because its possible to have a NIC installed and active but not in use and assigned to a connection
Else
ConnectionAlias$ = ConnectionAlias$
EndIf
If Description$ = ""
Description$ = " No Description/Name Assigned" ; because its possible to have a NIC installed and active but the NIC not have a name/description (Windows tracks via GUID and index anyway)
Else
Description$ = Description$
EndIf
MacAddr$ = IfIndex$ + "\" + Description$ + "\" + ConnectionAlias$ + "\" + macPermPhysicalAddress$ + "\" + macPhysicalAddress$
EndIf
EndIf
*BufInterfaceGuid = AllocateMemory(80)
StringFromGUID2(@*pIfRowmac\InterfaceGuid, *BufInterfaceGuid, 80)
Ifguid$ = PeekS(*BufInterfaceGuid, -1, #PB_Unicode)
FreeMemory(*BufInterfaceGuid)
If retval = #NO_ERROR And *pIfRowmac > 0
FreeMemory(*pIfRowmac)
EndIf
Select rettype
Case 0
getmac_return$ = MacAddr$
Case 1
getmac_return$ = macPermPhysicalAddress$
Case 2
getmac_return$ = macPhysicalAddress$
Case 3
getmac_return$ = ConnectionAlias$
Case 4
getmac_return$ = Description$
Case 5
getmac_return$ = Ifguid$
Case 6
getmac_return$ = IfIndex$ ; this is the LUID index
Case 7
getmac_return$ = TxLinkSpdSet$
Case 8
getmac_return$ = RxLinkSpdSet$
Case 9
getmac_return$ = directiontyp$
Case 10
getmac_return$ = ConnectorPlugged$
Case 11
getmac_return$ = oper_status$
Case 12
getmac_return$ = adminstat$
Case 13
getmac_return$ = int_adapFault$
Case 14
getmac_return$ = MIBhardwareinterface$
Case 15
getmac_return$ = MIBfilterinterface$
Case 16
getmac_return$ = MIBconnectorpresent$
Case 17
getmac_return$ = MIBportauthenticated$
Case 18
getmac_return$ = MIBmediaconnected$
Case 19
getmac_return$ = MIBintfacepaused$
Case 20
getmac_return$ = MIBintfacelowpower$
Case 21
getmac_return$ = MIBifendpoint$
Default
getmac_return$ = MacAddr$
EndSelect
ProcedureReturn getmac_return$
EndProcedure
Procedure GetNumEntries() ; the number of entries total which includes both hardware and logical/software constructs
*TableNum.MIB_IF_TABLE2 = #Null
GetIfTable2(@*TableNum)
If *TableNum\NumEntries >= 1
NumEntries.i = *TableNum\NumEntries
FreeMibTable(*TableNum)
Else
NumEntries.i = 0
FreeMibTable(*TableNum)
EndIf
ProcedureReturn NumEntries
EndProcedure
numentry = GetNumEntries()
For x = 1 To numentry
If GetMACs(x) <> ""
Debug "**************************************************************"
Debug "Description : " + GetMACs(x, 4)
Debug "Network GUID : " + GetMACs(x, 5)
Debug "Connection Alias : " + GetMACs(x, 3)
Debug "Is interface an end point device? : " + GetMACs(x, 21)
Debug "Is this a hardware or software/logical construct interface? : " + GetMACs(x, 14)
Debug "Is this a filter interface? : " + GetMACs(x, 15)
Debug "Interface Authentication : " + GetMACs(x, 17)
Debug "Is interface paused? : " + GetMACs(x, 19)
Debug "Is interface at low power? : " + GetMACs(x, 20)
Debug "Administrative Status : " + GetMACs(x, 12)
Debug "Operational Status : " + GetMACs(x, 11)
Debug "Fault Status : " + GetMACs(x, 13)
Debug "Is connector present? : " + GetMACs(x, 16)
Debug "Is connector plugged in? : " + GetMACs(x, 10)
Debug "Is interface connected to media (e.g. network)? : " + GetMACs(x, 18)
Debug "Direction : " + GetMACs(x, 9)
Debug "Permanant MAC Address : " + GetMACs(x, 1)
Debug "In use physical MAC Address : " + GetMACs(x, 2)
Debug "Transmit Link Speed Setting : " + GetMACs(x, 7)
Debug "Receive Link Speed Setting : " + GetMACs(x, 8)
Debug "**************************************************************"
EndIf
Next
CloseLibrary(1)
CloseLibrary(2)
CloseLibrary(3)