読者です 読者をやめる 読者になる 読者になる

SIN@SAPPOROWORKSの覚書

C#を中心に、夜な夜な試行錯誤したコードの記録です。

ARPテーブルの追加 (C#)(F#)


iphlpapi.dllの CreateIpNetEntry()でARP追加することができます。追加した、ARPテーブルは、コマンドラインで「arp -a」とする事で確認できます。

CreateIpNetEntry()は、追加情報がすでに存在するときエラーとなるので、サンプルを実行する場合は、「arp -d」でARPテーブルをクリアしながら試してみてください。
なお、 MIB_IPNETROWのIndexは、環境に応じて、インターフェースのインデックス番号を適切に設定する必要があります。

C#サンプル

using System;
using System.Runtime.InteropServices;
using System.Net;

namespace Example {
    class Program {
        
        [DllImport("Iphlpapi.dll")]
        extern static int CreateIpNetEntry(IntPtr pArpEntry);

        [StructLayout(LayoutKind.Sequential)]
        public struct MIB_IPNETROW {
            public int Index;
            public int PhysAddrLen;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte [] PhysAddr;
            public int Addr;
            public int Type;
        }
        enum  MIB_IPNET_TYPE{
            OTHER=1,//その他
            INVALID=2,//無効
            DYNAMIC=3,//動的
            STATIC=4//静的
        }

        static void Main(string[] args) {

            var pArpEntry = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MIB_IPNETROW)));
            var index = 15;//インターフェースのインデックス
            var ip = IPAddress.Parse("192.168.0.100");//IPアドレス
            var mac = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };//MACアドレス 
            
            var p = pArpEntry;//作業用ポインタ
            
            Marshal.WriteInt32(p,index);//Index
            p = IntPtr.Add(p,4);

            Marshal.WriteInt32(p,6);//PhysAddrLen
            p = IntPtr.Add(p,4);

            Marshal.Copy(mac,0,p,6);//PhysAddr
            p = IntPtr.Add(p,8);

            Marshal.WriteInt32(p,(int)ip.Address);//Addr
            p = IntPtr.Add(p, 4);

            Marshal.WriteInt32(p, (int)MIB_IPNET_TYPE.STATIC);//Type
            p = IntPtr.Add(p, 4);

            var ret = CreateIpNetEntry(pArpEntry);
            if (ret == 0) {
                Console.WriteLine("Success");
            } else {
                Console.WriteLine(string.Format("ERROR 0x{0:x}",ret));
            }
            Marshal.FreeHGlobal(pArpEntry);

            Console.WriteLine("何かのキーを押してください。");
            Console.ReadKey();
        }
    }
}

F#サンプル

open System
open System.Runtime.InteropServices
open System.Net

[<DllImport("iphlpapi.dll")>]
extern int CreateIpNetEntry(IntPtr pArpEntry);

[<Struct; StructLayout(LayoutKind.Sequential)>]
type MIB_IPNETROW =
    val Index:int
    val PhysAddrLen:int
    [<MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)>]
    val PhysAddr:byte []
    val Addr:int
    val Type:int

type MIB_IPNET_TYPE = |OTHER=1//その他
                      |INVALID=2//無効
                      |DYNAMIC=3//動的
                      |STATIC=4//静的

let pArpEntry = Marshal.AllocHGlobal(Marshal.SizeOf(typeof<MIB_IPNETROW>))//メモリ確保
let index = 15//インターフェースのインデックス
let ip = IPAddress.Parse("192.168.0.100")//IPアドレス
let mac  = [|0x01uy; 0x02uy; 0x03uy; 0x04uy; 0x05uy; 0x06uy|] //MACアドレス 
    
            
let mutable p = pArpEntry//作業用ポインタ
Marshal.WriteInt32(p,index)//Index
p <- IntPtr.Add(p,4)

Marshal.WriteInt32(p,6)//PhysAddrLen
p <- IntPtr.Add(p,4)

Marshal.Copy(mac,0,p,6)//PhysAddr
p <- IntPtr.Add(p,8)

Marshal.WriteInt32(p,(int)ip.Address);//Addr
p <- IntPtr.Add(p, 4)

Marshal.WriteInt32(p, (int)MIB_IPNET_TYPE.STATIC)//Type
p <- IntPtr.Add(p, 4)

let ret = CreateIpNetEntry(pArpEntry)
if ret = 0 then
    printfn "Success"
else
    printfn "ERROR 0x%x" ret
    
Marshal.FreeHGlobal(pArpEntry)//メモリ開放

printfn "何かのキーを押してください。"
Console.ReadKey() |> ignore