このエントリーをはてなブックマークに追加


ARPテーブルを取得し表示するサンプル・GetIpNetTable API

iphlpapi.dll の GetIpNetTable API を使用しARPリストを取得しIPアドレス、MACアドレス、タイプを表示するコンソールアプリケーションのC#サンプルコードを公開しました。

関連記事

参考サイト

動作確認環境

  • Windows 10 ver.22H2
  • .NET6.0
  • Visual Studio 2022

C#サンプルコード

GetIpNetTable API を使用し取得したARPテーブル情報を表示するC#サンプルコードを以下に記します。
説明に関してはコメントを参照してください。

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);
            }
        }
    }
}

実行結果

マルチキャストアドレスも表示されていますね。
ネットワーク上のARPキャッシュの情報が表示されました。

 
01.png

以上、GetIpNetTable API を使ってARPテーブル情報を表示するC#サンプルコードでした。


添付ファイル: file01.png 64件 [詳細] fileProgram.cs 70件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-04-22 (土) 17:23:57