- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2023-04-22T17:21:05+09:00","","")
#navi(../)
*ARPテーブルを取得し表示するサンプル・GetIpNetTable API [#z9b3d394]
iphlpapi.dll の GetIpNetTable API を使用しARPリストを取得しIPアドレス、MACアドレス、タイプを表示するコンソールアプリケーションのC#サンプルコードを公開しました。~
#contents
* 関連記事 [#ka7de2a8]
-[[IPv4からMACアドレス取得するSendARP()APIを使ってみる>.NET/IPv4からMACアドレス取得する・SendARP]]
* 参考サイト [#fa1ec922]
- c# get arp cache~
https://gist.github.com/invictus-0x90/2e1ebcfefd8d7478e695131b88ce2926
- SIN@SAPPOROWORKSの覚書 ARPテーブルの取得 (C#)(F#)~
https://furuya02.hatenablog.com/entry/20111107/1399766912
- Microsoft GetIpNetTable 関数 (iphlpapi.h)~
https://learn.microsoft.com/ja-jp/windows/win32/api/iphlpapi/nf-iphlpapi-getipnettable
- Microsoft MIB_IPNETTABLE structure (ipmib.h)~
https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipnettable
- Microsoft MIB_IPNETROW_LH structure (ipmib.h)
https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipnetrow_lh
* 動作確認環境 [#qc949720]
- Windows 10 ver.22H2
- .NET6.0
- Visual Studio 2022
* C#サンプルコード [#e6de880e]
GetIpNetTable API を使用し取得したARPテーブル情報を表示するC#サンプルコードを以下に記します。~
説明に関してはコメントを参照してください。
#ref(Program.cs)
using System.Runtime.InteropServices;
namespace ARPList
{
internal class Program
{
// GetIpNetTable 関数 (iphlpapi.h): https://learn.microsoft.com/ja-jp/windows/win32/api/iphlpapi/nf-iphlpapi-getipnettable
[DllImport("iphlpapi.dll", EntryPoint = "GetIpNetTable")]
static extern int GetIpNetTable(IntPtr pIpNetTable, ref int pdwSize, bool bOrder);
[StructLayout(LayoutKind.Sequential)]
struct MIB_IPNETROW
{
[MarshalAs(UnmanagedType.U4)]
public uint dwIndex;
[MarshalAs(UnmanagedType.U4)]
public uint dwPhysAddrLen;
[MarshalAs(UnmanagedType.U1)]
public byte mac0;
[MarshalAs(UnmanagedType.U1)]
public byte mac1;
[MarshalAs(UnmanagedType.U1)]
public byte mac2;
[MarshalAs(UnmanagedType.U1)]
public byte mac3;
[MarshalAs(UnmanagedType.U1)]
public byte mac4;
[MarshalAs(UnmanagedType.U1)]
public byte mac5;
[MarshalAs(UnmanagedType.U1)]
public byte mac6;
[MarshalAs(UnmanagedType.U1)]
public byte mac7;
[MarshalAs(UnmanagedType.U4)]
public uint dwAddr;
[MarshalAs(UnmanagedType.U4)]
public uint dwType;
}
private const int SUCCESS = 0;
private const int ERROR_INSUFFICIENT_BUFFER = 0x007A;
private const uint MIB_IPNET_TYPE_OTHER = 1;
private const uint MIB_IPNET_TYPE_INVALID = 2;
private const uint MIB_IPNET_TYPE_DYNAMIC = 3;
private const uint MIB_IPNET_TYPE_STATIC = 4;
static void Main(string[] args)
{
int result;
int requestBuffSize = 0;
// ARPテーブル格納用のメモリエリアを確保する
// 格納メモリ不足の ERROR_INSUFFICIENT_BUFFER が返却され、requestBuffSize に必要なメモリサイズが返却される
// ERROR_INSUFFICIENT_BUFFER 以外が返却された場合は処理を中止する
// GetIpNetTable: https://learn.microsoft.com/ja-jp/windows/win32/api/iphlpapi/nf-iphlpapi-getipnettable
result = GetIpNetTable(IntPtr.Zero, ref requestBuffSize, true);
if (result != ERROR_INSUFFICIENT_BUFFER)
{
Console.Error.WriteLine("GetIpNetTable API Error:" + result);
Environment.Exit((int)result);
}
try
{
// Marshal.AllocCoTaskMem: https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.interopservices.marshal.alloccotaskmem
IntPtr resultBuff = Marshal.AllocCoTaskMem(requestBuffSize);
// 確保した格納用メモリを引数に設定し GetIpNetTable API を実行する
// 0(SUCCESS)以外が返却された場合は処理を中止する
result = GetIpNetTable(resultBuff, ref requestBuffSize, true);
if (result != 0)
{
Environment.Exit(result);
}
// ARPエントリ数が0の場合、処理を終了する
int entries = Marshal.ReadInt32(resultBuff);
if (entries == 0)
{
Environment.Exit(0);
}
// GetIpNetTable API から返却された MIB_IPNETTABLE.dwNumEntries DWORD分を移動
// MIB_IPNETTABLE: https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipnettable
IntPtr currentPtr = IntPtr.Add(resultBuff, sizeof(Int32));
// 取得したARP情報を格納するListオブジェクトを準備
List<MIB_IPNETROW> arpTableList = new List<MIB_IPNETROW>();
for (int i = 0; i < entries; i++)
{
// List<MIB_IPNETROW> に追加
arpTableList.Add((MIB_IPNETROW)Marshal.PtrToStructure(currentPtr, typeof(MIB_IPNETROW)));
// 次のデータの先頭に移動
currentPtr = IntPtr.Add(currentPtr, Marshal.SizeOf(typeof(MIB_IPNETROW)));
}
// メモリの解放
Marshal.FreeHGlobal(resultBuff);
// 取得したARPテーブルからMACアドレス、IPアドレスの表示する
foreach (var item in arpTableList)
{
//IPアドレス
Byte[] b = BitConverter.GetBytes(item.dwAddr);
string ip = string.Format("{0}.{1}.{2}.{3}", b[0], b[1], b[2], b[3]);
string mac = string.Format("{0:x2}-{1:x2}-{2:x2}-{3:x2}-{4:x2}-{5:x2}", item.mac0, item.mac1, item.mac2, item.mac3, item.mac4, item.mac5);
// TYPE
// MIB_IPNET_TYPE:https://learn.microsoft.com/en-us/windows/win32/api/ipmib/ns-ipmib-mib_ipnetrow_lh
string type = string.Empty;
switch (item.dwType)
{
case MIB_IPNET_TYPE_OTHER:
type = "OTHER";
break;
case MIB_IPNET_TYPE_INVALID:
type = "INVALID";
break;
case MIB_IPNET_TYPE_DYNAMIC:
type = "DYNAMIC";
break;
case MIB_IPNET_TYPE_STATIC:
type = "STATIC";
break;
}
Console.WriteLine("| {0,-15} | {1} | {2,-7} |", ip, mac, type);
}
}
catch (Exception e)
{
Console.Error.WriteLine("Exception thrown:" + e.Message);
Environment.Exit(1);
}
}
}
}
* 実行結果 [#d1174116]
マルチキャストアドレスも表示されていますね。~
ネットワーク上のARPキャッシュの情報が表示されました。
#br
#ref(01.png)
以上、GetIpNetTable API を使ってARPテーブル情報を表示するC#サンプルコードでした。