1

Can someone explain to me how to listen to ARP requests in VB.net or C#?

I need to capture the ARP request and obtain the IP address of the requester.

Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
Leandro
  • 84
  • 1
  • 2
  • 11

2 Answers2

1

At worst you could just process the output of arp -a run periodically.

EDIT: I understand this does not answer the OP, but FYI due to the related answer listed on the RHS, you can obtain the equivalent of arp -a programmatically.

Here's my VB.NET version of the C# code listed at that answer:

Imports System
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Imports System.Net
Imports System.Runtime.CompilerServices

Module Program

' The max length of physical address.
Const MAXLEN_PHYSADDR As Integer = 8

' Define the MIB_IPNETROW structure.
<StructLayout(LayoutKind.Sequential)> _
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

' Declare the GetIpNetTable function.
Declare Function GetIpNetTable Lib "IpHlpApi.dll" (
    ByVal pIpNetTable As IntPtr,
    <MarshalAs(UnmanagedType.U4)>
    ByRef pdwSize As Integer,
    ByVal bOrder As Boolean) As <MarshalAs(UnmanagedType.U4)> Integer

' The insufficient buffer error.
Const ERROR_INSUFFICIENT_BUFFER As Integer = 122

Sub Main(ByVal args() As String)

    ' The number of bytes needed.
    Dim bytesNeeded = 0

    ' The result from the API call.
    Dim result = GetIpNetTable(IntPtr.Zero, bytesNeeded, False)

    ' Call the function, expecting an insufficient buffer.
    If result <> ERROR_INSUFFICIENT_BUFFER Then
        ' Throw an exception.
        Throw New Win32Exception(result)
    End If

    ' Allocate the memory.
    Dim buffer = Marshal.AllocCoTaskMem(bytesNeeded)

    Try
        ' Make the call again. If it did not succeed, then
        ' raise an error.
        result = GetIpNetTable(buffer, bytesNeeded, False)

        ' If the result is not 0 (no error), then throw an exception.
        If result <> 0 Then _
            Throw New Win32Exception(result)

        ' Now we have the buffer, we have to marshal it. We can read
        ' the first 4 bytes to get the length of the buffer.
        Dim entries = Marshal.ReadInt32(buffer)

        Dim currentBuffer = buffer.PtrAdd(GetType(Integer))

        Dim table = New MIB_IPNETROW(0 To entries - 1) {}

        For index = 0 To entries - 1
            table(index) = DirectCast(Marshal.PtrToStructure(
                        currentBuffer.PtrAdd(GetType(MIB_IPNETROW), index), _
                    GetType(MIB_IPNETROW)), MIB_IPNETROW)
        Next

        For index = 0 To entries - 1

            With table(index)

                Dim ip = New IPAddress(BitConverter.GetBytes(.dwAddr))
                Console.Write(" IP: " & ip.ToString() & vbTab & " MAC: ")

                PrintByte(.mac0)

                PrintHyphenByte(.mac1)

                PrintHyphenByte(.mac2)

                PrintHyphenByte(.mac3)

                PrintHyphenByte(.mac4)

                PrintHyphenByte(.mac5)

                If .dwPhysAddrLen <> 6 Then _
                    Console.Write(" Actual length: {0} ", .dwPhysAddrLen)
                Console.Write(" Interface: 0x{0:X} Type: {1} ", .dwIndex, .dwType)
            End With
            Console.WriteLine()
        Next

    Finally
        ' Release the memory.
        Marshal.FreeCoTaskMem(buffer)

    End Try

    If Debugger.IsAttached Then _
        Console.ReadLine()
End Sub

<Extension()>
Private Function PtrAdd(ByVal Ptr As IntPtr, ByVal Type As Type, Optional ByVal Index As Long = 1) As IntPtr
    Return New IntPtr(Ptr.ToInt64() +
        Index * Marshal.SizeOf(Type))
End Function

Private Sub PrintHyphenByte(ByVal b As Byte)
    Console.Write("-")
    PrintByte(b)
End Sub

Private Sub PrintByte(ByVal b As Byte)
    Console.Write(b.ToString("x2"))
End Sub

End Module
Community
  • 1
  • 1
Mark Hurd
  • 10,665
  • 10
  • 68
  • 101
  • I think it will overload the network, so we wanted to monitor the receipt of an ARP protocol on the PC where the application is running. Monitoring the network with wireshark, I noticed that when connecting a compuatador the network, it sends an ARP protocols for the broadcast address. I would like to monitor the receipt of this package. – Leandro May 29 '12 at 13:32
0

There will be no clean API for doing this. ARP requests do not normally propagate to the userland, they are answered by the network stack itself (if not by the NIC driver, I'm not sure). You would have to put the card into promiscuous mode and essentially write a packet sniffer. You can do it with WinPcap, e.g. http://pcapdotnet.codeplex.com/

MK.
  • 33,605
  • 18
  • 74
  • 111
  • Ok, I need to detect when a new pc is connected to the network in order automatically. The only idea I had was this, listen to ARP requests, but the system will run on the client, and I can not require the installation of WinPCap. Do you have any other idea? – Leandro May 28 '12 at 19:24
  • 1
    It's a network engineering question. I'm sure there are network switches which can notify you. Or, assuming system gets its ip address assigned using DHCP service, you could hook something to that... – MK. May 28 '12 at 21:25