228 lines
9.2 KiB
VB.net
228 lines
9.2 KiB
VB.net
#Region "Microsoft.VisualBasic::35d325d3625c8644eac5a0c27067b109, Microsoft.VisualBasic.Core\Net\Tcp\IPTools\LAN.vb"
|
|
|
|
' Author:
|
|
'
|
|
' asuka (amethyst.asuka@gcmodeller.org)
|
|
' xie (genetics@smrucc.org)
|
|
' xieguigang (xie.guigang@live.com)
|
|
'
|
|
' Copyright (c) 2018 GPL3 Licensed
|
|
'
|
|
'
|
|
' GNU GENERAL PUBLIC LICENSE (GPL3)
|
|
'
|
|
'
|
|
' This program is free software: you can redistribute it and/or modify
|
|
' it under the terms of the GNU General Public License as published by
|
|
' the Free Software Foundation, either version 3 of the License, or
|
|
' (at your option) any later version.
|
|
'
|
|
' This program is distributed in the hope that it will be useful,
|
|
' but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
' GNU General Public License for more details.
|
|
'
|
|
' You should have received a copy of the GNU General Public License
|
|
' along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
' /********************************************************************************/
|
|
|
|
' Summaries:
|
|
|
|
' Module LANTools
|
|
'
|
|
' Function: GetAllDevicesOnLAN, GetIPAddress, GetIpNetTable, GetMacAddress, IsMulticast
|
|
' Structure MIB_IPNETROW
|
|
'
|
|
'
|
|
'
|
|
'
|
|
'
|
|
'
|
|
' /********************************************************************************/
|
|
|
|
#End Region
|
|
|
|
Imports System.Net
|
|
Imports System.Net.NetworkInformation
|
|
Imports System.Runtime.InteropServices
|
|
Imports System.Runtime.InteropServices.Marshal
|
|
|
|
Namespace Net
|
|
|
|
''' <summary>
|
|
''' http://www.codeproject.com/Tips/358946/Retrieving-IP-and-MAC-addresses-for-a-LAN
|
|
''' </summary>
|
|
''' <code>
|
|
''' ' Get my PC IP address
|
|
''' Call Console.WriteLine("My IP : {0}", GetIPAddress())
|
|
'''
|
|
''' ' Get My PC MAC address
|
|
''' Call Console.WriteLine("My MAC: {0}", GetMacAddress())
|
|
'''
|
|
''' ' Get all devices on network
|
|
''' Dim all As Dictionary(Of IPAddress, PhysicalAddress) = GetAllDevicesOnLAN()
|
|
''' For Each kvp As KeyValuePair(Of IPAddress, PhysicalAddress) In all
|
|
''' Console.WriteLine("IP : {0}" & vbLf & " MAC {1}", kvp.Key, kvp.Value)
|
|
''' Next
|
|
''' </code>
|
|
Public Module LANTools
|
|
|
|
''' <summary>
|
|
''' MIB_IPNETROW structure returned by GetIpNetTable
|
|
''' DO NOT MODIFY THIS STRUCTURE.
|
|
''' </summary>
|
|
<StructLayout(LayoutKind.Sequential)>
|
|
Private Structure MIB_IPNETROW
|
|
<MarshalAs(UnmanagedType.U4)>
|
|
Public dwIndex As Integer
|
|
<MarshalAs(UnmanagedType.U4)>
|
|
Public dwPhysAddrLen As Integer
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac0 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac1 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac2 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac3 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac4 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac5 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac6 As Byte
|
|
<MarshalAs(UnmanagedType.U1)>
|
|
Public mac7 As Byte
|
|
<MarshalAs(UnmanagedType.U4)>
|
|
Public dwAddr As Integer
|
|
<MarshalAs(UnmanagedType.U4)>
|
|
Public dwType As Integer
|
|
End Structure
|
|
|
|
''' <summary>
|
|
''' GetIpNetTable external method
|
|
''' </summary>
|
|
''' <param name="pIpNetTable"></param>
|
|
''' <param name="pdwSize"></param>
|
|
''' <param name="bOrder"></param>
|
|
''' <returns></returns>
|
|
<DllImport("IpHlpApi.dll")>
|
|
Private Function GetIpNetTable(pIpNetTable As IntPtr, <MarshalAs(UnmanagedType.U4)> ByRef pdwSize As Integer, bOrder As Boolean) As <MarshalAs(UnmanagedType.U4)> Integer
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Error codes GetIpNetTable returns that we recognise
|
|
''' </summary>
|
|
Const ERROR_INSUFFICIENT_BUFFER As Integer = 122
|
|
|
|
''' <summary>
|
|
''' Get the IP and MAC addresses of all known devices on the LAN
|
|
''' </summary>
|
|
''' <remarks>
|
|
''' 1) This table is not updated often - it can take some human-scale time
|
|
''' to notice that a device has dropped off the network, or a new device
|
|
''' has connected.
|
|
''' 2) This discards non-local devices if they are found - these are multicast
|
|
''' and can be discarded by IP address range.
|
|
''' </remarks>
|
|
''' <returns></returns>
|
|
Public Function GetAllDevicesOnLAN() As Dictionary(Of IPAddress, PhysicalAddress)
|
|
Dim all As New Dictionary(Of IPAddress, PhysicalAddress)()
|
|
' Add this PC to the list...
|
|
all.Add(GetIPAddress(), GetMacAddress())
|
|
Dim spaceForNetTable As Integer = 0
|
|
' Get the space needed
|
|
' We do that by requesting the table, but not giving any space at all.
|
|
' The return value will tell us how much we actually need.
|
|
GetIpNetTable(IntPtr.Zero, spaceForNetTable, False)
|
|
' Allocate the space
|
|
' We use a try-finally block to ensure release.
|
|
Dim rawTable As IntPtr = IntPtr.Zero
|
|
Try
|
|
rawTable = AllocCoTaskMem(spaceForNetTable)
|
|
' Get the actual data
|
|
Dim errorCode As Integer = GetIpNetTable(rawTable, spaceForNetTable, False)
|
|
If errorCode <> 0 Then
|
|
' Failed for some reason - can do no more here.
|
|
Throw New Exception(String.Format("Unable to retrieve network table. Error code {0}", errorCode))
|
|
End If
|
|
' Get the rows count
|
|
Dim rowsCount As Integer = ReadInt32(rawTable)
|
|
Dim currentBuffer As New IntPtr(rawTable.ToInt64() + Marshal.SizeOf(GetType(Int32)))
|
|
' Convert the raw table to individual entries
|
|
Dim rows As MIB_IPNETROW() = New MIB_IPNETROW(rowsCount - 1) {}
|
|
For index As Integer = 0 To rowsCount - 1
|
|
rows(index) = CType(PtrToStructure(New IntPtr(currentBuffer.ToInt64() + (index * Marshal.SizeOf(GetType(MIB_IPNETROW)))), GetType(MIB_IPNETROW)), MIB_IPNETROW)
|
|
Next
|
|
' Define the dummy entries list (we can discard these)
|
|
Dim virtualMAC As New PhysicalAddress(New Byte() {0, 0, 0, 0, 0, 0})
|
|
Dim broadcastMAC As New PhysicalAddress(New Byte() {255, 255, 255, 255, 255, 255})
|
|
For Each row As MIB_IPNETROW In rows
|
|
Dim ip As New IPAddress(BitConverter.GetBytes(row.dwAddr))
|
|
Dim rawMAC As Byte() = New Byte() {row.mac0, row.mac1, row.mac2, row.mac3, row.mac4, row.mac5}
|
|
Dim pa As New PhysicalAddress(rawMAC)
|
|
If Not pa.Equals(virtualMAC) AndAlso Not pa.Equals(broadcastMAC) AndAlso Not IsMulticast(ip) Then
|
|
'Console.WriteLine("IP: {0}\t\tMAC: {1}", ip.ToString(), pa.ToString());
|
|
If Not all.ContainsKey(ip) Then
|
|
all.Add(ip, pa)
|
|
End If
|
|
End If
|
|
Next
|
|
Finally
|
|
' Release the memory.
|
|
FreeCoTaskMem(rawTable)
|
|
End Try
|
|
Return all
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Gets the IP address of the current PC
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Function GetIPAddress() As IPAddress
|
|
Dim strHostName As String = Dns.GetHostName()
|
|
Dim ipEntry As IPHostEntry = Dns.GetHostEntry(strHostName)
|
|
Dim addr As IPAddress() = ipEntry.AddressList
|
|
For Each ip As IPAddress In addr
|
|
If Not ip.IsIPv6LinkLocal Then
|
|
Return (ip)
|
|
End If
|
|
Next
|
|
Return If(addr.Length > 0, addr(0), Nothing)
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Gets the MAC address of the current PC.
|
|
''' </summary>
|
|
''' <returns></returns>
|
|
Public Function GetMacAddress() As PhysicalAddress
|
|
For Each nic As NetworkInterface In NetworkInterface.GetAllNetworkInterfaces()
|
|
' Only consider Ethernet network interfaces
|
|
If nic.NetworkInterfaceType = NetworkInterfaceType.Ethernet AndAlso nic.OperationalStatus = OperationalStatus.Up Then
|
|
Return nic.GetPhysicalAddress()
|
|
End If
|
|
Next
|
|
Return Nothing
|
|
End Function
|
|
|
|
''' <summary>
|
|
''' Returns true if the specified IP address is a multicast address
|
|
''' </summary>
|
|
''' <param name="ip"></param>
|
|
''' <returns></returns>
|
|
Public Function IsMulticast(ip As IPAddress) As Boolean
|
|
Dim result As Boolean = True
|
|
If Not ip.IsIPv6Multicast Then
|
|
Dim highIP As Byte = ip.GetAddressBytes()(0)
|
|
If highIP < 224 OrElse highIP > 239 Then
|
|
result = False
|
|
End If
|
|
End If
|
|
Return result
|
|
End Function
|
|
End Module
|
|
End Namespace
|