fork download
  1. //******************************************************
  2. //Program.fs wrote @furuya02 SIN/SAPPOROWORKS
  3. //******************************************************
  4. #nowarn "9"
  5. #nowarn "51"
  6.  
  7. open System
  8. open System.Runtime.InteropServices
  9. open System.Text
  10. open System.Threading
  11. open System.Net
  12. open System.Collections.Specialized
  13.  
  14. //******************************************************
  15. //htons htonl
  16. //******************************************************
  17. let htons(n:Int16) =
  18. IPAddress.HostToNetworkOrder(n)
  19. let htonl(n:Int32) =
  20. IPAddress.HostToNetworkOrder(n)
  21.  
  22. //******************************************************
  23. //文字列への変換
  24. //******************************************************
  25. let macStr(buf:byte[]) =
  26. sprintf "%02x:%02x:%02x:%02x:%02x:%02x" (buf.[0]) (buf.[1]) (buf.[2]) (buf.[3]) (buf.[4]) (buf.[5])
  27. let ipStr(buf:byte[])=
  28. (new IPAddress(buf)).ToString()
  29.  
  30. //******************************************************
  31. //ヘッダ表示
  32. //******************************************************
  33. let dispHeda(hdr:WinPcap.pcap_pkthdr)=
  34. printf "size=%dbyte " hdr.len
  35.  
  36. //***********************************e*******************
  37. //Ether表示
  38. //******************************************************
  39. let dispEther(buf:byte[])=
  40. printfn "%s => %s protocol=0x%02x%02x" (macStr(buf.[6..11])) (macStr(buf.[0..5])) buf.[12] buf.[13]
  41. match (buf.[12],buf.[13]) with
  42. | 0x08uy,0x00uy -> "IPv4"
  43. | 0x08uy,0x06uy -> "ARP"
  44. | 0x86uy,0xdduy -> "IPv6"
  45. |_ -> sprintf "%02x%02x" buf.[12] buf.[13]
  46.  
  47. //******************************************************
  48. //ダンプ表示
  49. //******************************************************
  50. let dispDump(buf:byte[],offset:int) =
  51. let max = if buf.Length > 30 then 30 else buf.Length-1
  52. [offset..max]
  53. |>Seq.iter(fun i -> printf "%02x" buf.[i])
  54. printfn ""
  55.  
  56. //******************************************************
  57. //ARP表示
  58. //******************************************************
  59. [<Struct;StructLayout(LayoutKind.Sequential)>]
  60. type ArpHeader =
  61. val hardwareType : UInt16
  62. val protocolType : UInt16
  63. val hardwareSize : byte
  64. val protocolSize : byte
  65. val opcode : Int16
  66. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=6)>]
  67. val srcMac : System.Byte[]
  68. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=4)>]
  69. val srcIp : System.Byte[]
  70. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=6)>]
  71. val dstMac : System.Byte[]
  72. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=4)>]
  73. val dstIp : System.Byte[]
  74. let dispArp(buf:byte[],offset:int) =
  75. //構造体へのコピー
  76. let s = Marshal.SizeOf(typeof<ArpHeader>)//構造体のサイズ
  77. let p = Marshal.AllocHGlobal(s)//メモリ確保
  78. Marshal.Copy(buf, offset,p,s)
  79. let h = Marshal.PtrToStructure(p, typeof<ArpHeader>):?>ArpHeader //ヘッダ構造体への変換
  80. //変換
  81. let opcode = htons(h.opcode) //制御コード
  82. let srcIp = ipStr(h.srcIp) //送り元IP
  83. let dstIp = ipStr(h.dstIp) //送り元MAC
  84. let srcMac = macStr(h.srcMac) //宛て先IP
  85. let dstMac = macStr(h.dstMac) //宛て先MAC
  86. //表示
  87. match opcode with
  88. |0x0001s -> printfn " ARP Who has %s? Tell %s" dstIp srcIp //ARO要求
  89. |0x0002s -> printfn " ARP %s is at %s" srcIp srcMac //ARP応答
  90. |_ -> printfn " ARP opcode=%d src=%s(%s) dst=%s(%s)" opcode srcIp srcMac dstIp dstMac
  91. Marshal.FreeHGlobal(p)//メモリ解放
  92.  
  93. //******************************************************
  94. //IPv6表示
  95. //******************************************************
  96. [<Struct;StructLayout(LayoutKind.Sequential)>]
  97. type IPv6Header =
  98. val Ver_TrafficClass_FlowLabel : BitVector32
  99. val PayloadLength : Int16
  100. val NextHeader : byte
  101. val HopLimit : byte
  102. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=16)>]
  103. val srcIp : System.Byte[]
  104. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=16)>]
  105. val dstIp : System.Byte[]
  106. let dispIPv6(buf:byte[],offset:int) =
  107. //構造体へのコピー
  108. let s = Marshal.SizeOf(typeof<IPv6Header>)//構造体のサイズ
  109. let p = Marshal.AllocHGlobal(s)//メモリ確保
  110. Marshal.Copy(buf, offset,p,s)
  111. let h = Marshal.PtrToStructure(p, typeof<IPv6Header>):?>IPv6Header //ヘッダ構造体への変換
  112. //変換
  113. let srcIp = ipStr(h.srcIp)
  114. let dstIp = ipStr(h.dstIp)
  115. let payloadLength = htons(h.PayloadLength)
  116. let NextHeader =
  117. match h.NextHeader with
  118. | 0x00uy -> "ICMP Option(hop by hop)"
  119. | 0x01uy -> "ICMP"
  120. | 0x02uy -> "IGMP"
  121. | 0x03uy -> "IP"
  122. | 0x06uy -> "TCP"
  123. | 0x11uy -> "UDP"
  124. | 0x29uy -> "IPv6"
  125. | 0x3auy -> "ICMPv6"
  126. | 0x3buy -> "No Next Header"
  127. |_ -> sprintf "0x%02x" h.NextHeader
  128. //表示
  129. printfn " IPv6 src=%s dst=%s payloadLength=%d hopLimit=%d nextHeader=%s" srcIp dstIp payloadLength h.HopLimit NextHeader
  130. Marshal.FreeHGlobal(p)//メモリ解放
  131.  
  132. //******************************************************
  133. //IPv4表示
  134. //******************************************************
  135. [<Struct;StructLayout(LayoutKind.Sequential)>]
  136. type IPv4Header =
  137. val VerLen : byte
  138. val TOS : byte
  139. val TotalLength : UInt16
  140. val Id : UInt16
  141. val OffSet: UInt16
  142. val TTL : byte
  143. val Protocol : byte
  144. val Checksum : UInt16
  145. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=4)>]
  146. val srcIp : System.Byte[]
  147. [<MarshalAs(UnmanagedType.ByValArray, SizeConst=4)>]
  148. val dstIp : System.Byte[]
  149.  
  150. let dispIPv4(buf:byte[],offset:int) =
  151. //構造体へのコピー
  152. let s = Marshal.SizeOf(typeof<IPv4Header>)//構造体のサイズ
  153. let p = Marshal.AllocHGlobal(s)//メモリ確保
  154. Marshal.Copy(buf, offset,p,s)
  155. let h = Marshal.PtrToStructure(p, typeof<IPv4Header>):?>IPv4Header //ヘッダ構造体への変換
  156. //変換
  157. let srcIp = ipStr(h.srcIp) //送り元IPアドレス
  158. let dstIp = ipStr(h.dstIp) //宛先IPアドレス
  159. let protocol = match h.Protocol with
  160. | 1uy -> "ICMP"
  161. | 2uy -> "IGMP"
  162. | 6uy -> "TCP"
  163. | 8uy -> "EGP"
  164. | 9uy -> "IGP"
  165. | 17uy -> "UDP"
  166. | 41uy -> "IPv6"
  167. | 43uy -> "IPv6-Route"
  168. | 44uy -> "IPv6-Frag"
  169. | 58uy -> "IPv6-ICMP"
  170. | 59uy -> "IPv6-NoNext"
  171. | 60uy -> "IPv6-Opts"
  172. | 68uy -> "IPv6-ICMP"
  173. | 88uy -> "EIGRP"
  174. | 89uy -> "OSPF"
  175. | 115uy -> "L2TP"
  176. |_ -> sprintf "0x%02x" h.Protocol
  177. //表示
  178. printfn " IPv4 proto=%s src=%s dst=%s ttl=%d check=0x%04x" protocol srcIp dstIp h.TTL h.Checksum
  179. Marshal.FreeHGlobal(p)//メモリ解放
  180.  
  181. //******************************************************
  182. //1パケットの表示
  183. //******************************************************
  184. let disp(pkt_data:IntPtr,pkt_hdr:IntPtr) =
  185. //ヘッダ取得
  186. let hdr = Marshal.PtrToStructure(pkt_hdr,typeof<WinPcap.pcap_pkthdr>):?>WinPcap.pcap_pkthdr
  187. //データ取得
  188. let data:byte[] = Array.zeroCreate hdr.caplen
  189. Marshal.Copy(pkt_data,data,0,(int)(hdr.caplen))
  190.  
  191. dispHeda(hdr)//ヘッダ表示
  192. let offset = ref(14)//オフセット移動
  193. match dispEther(data) with //Ether表示
  194. | "ARP" -> dispArp(data,!offset)//ARP表示
  195. | "IPv4" -> dispIPv4(data,!offset)//IPv4表示
  196. | "IPv6" -> dispIPv6(data,!offset)//IPv6表示
  197. |_ -> dispDump(data,!offset)//ダンプ表示
  198.  
  199. //******************************************************
  200. //キャプチャ開始(ループ)
  201. //******************************************************
  202. let capture devName =
  203. printfn "%s" devName //デバイス名表示
  204. let MAX_RECV_SIZE = 1600 //受信バッファサイズ
  205. let timeout = 20 //タイムアウト
  206. let Promiscast = 1 //プロミスキャスモード
  207. let ebuf = new StringBuilder(WinPcap.PCAP_ERRBUF_SIZE) //エラーメッセージ取得バッファ
  208. let handle = WinPcap.pcap_open(devName,MAX_RECV_SIZE,Promiscast,timeout,IntPtr.Zero,ebuf)
  209.  
  210. let mutable pkt_data = new IntPtr();
  211. let mutable pkt_hdr = new IntPtr();
  212. while true do //受信ループ
  213. match WinPcap.pcap_next_ex(handle, &&pkt_hdr,&&pkt_data) with //データ取得
  214. | -1 -> printfn "ERROR" //エラー
  215. | 0 -> Thread.Sleep(1)//タイムアウト(データ受信なし)
  216. | _ -> disp(pkt_data,pkt_hdr)|>ignore//1パケットの表示
  217.  
  218.  
  219. //******************************************************
  220. //main
  221. //******************************************************
  222. //デバイス一覧取得
  223. let devs =
  224. [
  225. let mutable alldevs = IntPtr()//情報取得用のバッファ
  226. let ebuf = new StringBuilder(WinPcap.PCAP_ERRBUF_SIZE) //エラーメッセージ取得バッファ
  227. if WinPcap.pcap_findalldevs_ex("rpcap://",IntPtr.Zero,&&alldevs,ebuf) <> -1 then
  228. let p = ref(alldevs)
  229. while (!p <> IntPtr.Zero) do
  230. let pcap_if = Marshal.PtrToStructure(!p,typeof<WinPcap.pcap_if>) :?> WinPcap.pcap_if
  231. yield pcap_if
  232. p := pcap_if.next
  233. ]
  234.  
  235. //デバイス一覧の表示
  236. [0..devs.Length-1]|>List.iter(fun i -> printfn "%d %s" (i+1) devs.[i].description)
  237.  
  238. //デバイス選択
  239. printf "\nモニタするデバイスを選択してください\n[1-%d] >" devs.Length
  240. let key = Console.ReadKey()
  241. let index = int(key.KeyChar)-49 //'1'->0 , '2'->1 , '3'->2 変換
  242.  
  243. //選択が有効かどうかの判定
  244. if 0<= index && index<devs.Length then
  245. capture devs.[index].name //キャプチャ開始(ループ)
  246. else
  247. printfn "無効なデバイスを選択しました"|>ignore
  248.  
  249.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty