public bool Receive() { //Buffer pointer IntPtr bufferPtr = Marshal.AllocHGlobal(NativeConstants.WinDivertMaxBuffer); byte[] bufferArr = new byte[NativeConstants.WinDivertMaxBuffer]; //Adderss pointer WINDIVERT_ADDRESS pAddress = new WINDIVERT_ADDRESS(); IntPtr pAddressPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_ADDRESS))); Marshal.StructureToPtr(pAddress, pAddressPtr, true); //Read pointer IntPtr readPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))); //Packet parsing IntPtr ipHdr = IntPtr.Zero; IntPtr ipv6Hdr = IntPtr.Zero; IntPtr icmpHdr = IntPtr.Zero; IntPtr icmpv6Hdr = IntPtr.Zero; IntPtr tcpHdr = IntPtr.Zero; IntPtr udpHdr = IntPtr.Zero; IntPtr ppData = IntPtr.Zero; IntPtr ppReadLen = IntPtr.Zero; try { //Invoke WinDivertRecv if (NativeMethods.WinDivertRecv(_divert_handle, bufferPtr, (uint)NativeConstants.WinDivertMaxBuffer, pAddressPtr, readPtr) == true) { //We received a packet pAddress = (WINDIVERT_ADDRESS)Marshal.PtrToStructure(pAddressPtr, typeof(WINDIVERT_ADDRESS)); //This line is used to copy buffer data to managed Byte[] //Marshal.Copy(bufferPtr, bufferArr, 0, bufferArr.Length); //Packet length uint readlen = (uint)Marshal.ReadInt32(readPtr); //Try to parse data ipHdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_IPHDR))); ipv6Hdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_IPV6HDR))); icmpHdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_ICMPHDR))); icmpv6Hdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_ICMPV6HDR))); tcpHdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_TCPHDR))); udpHdr = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WINDIVERT_UDPHDR))); ppData = IntPtr.Zero; //Marshal.AllocHGlobal(NativeConstants.WinDivertMaxBuffer); ppReadLen = IntPtr.Zero; //Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int))); //But WinDivertHelperParsePacket always return FALSE //if (NativeMethods.WinDivertHelperParsePacket(bufferPtr, readlen, ref ipHdr, ref ipv6Hdr, ref icmpHdr, ref icmpv6Hdr, ref tcpHdr, ref udpHdr, ref ppData, ppReadLen) == true) //{ NativeMethods.WinDivertHelperParsePacket(bufferPtr, readlen, ref ipHdr, ref ipv6Hdr, ref icmpHdr, ref icmpv6Hdr, ref tcpHdr, ref udpHdr, ref ppData, ppReadLen); if (ipHdr != IntPtr.Zero) { Console.Write("IPV4 Src Address : "); WINDIVERT_IPHDR dvIP = (WINDIVERT_IPHDR)Marshal.PtrToStructure(ipHdr, typeof(WINDIVERT_IPHDR)); Console.WriteLine(dvIP.SrcAddr); } if (ipv6Hdr != IntPtr.Zero) { Console.Write("IPV6 Src Address : "); WINDIVERT_IPV6HDR dvIP = (WINDIVERT_IPV6HDR)Marshal.PtrToStructure(ipv6Hdr, typeof(WINDIVERT_IPV6HDR)); //Console.WriteLine(dvIP.SrcAddr); byte[] ipArr = new byte[4]; ipArr[0] = (byte)dvIP.SrcAddr[0]; ipArr[1] = (byte)dvIP.SrcAddr[1]; ipArr[2] = (byte)dvIP.SrcAddr[2]; ipArr[3] = (byte)dvIP.SrcAddr[3]; System.Net.IPAddress ipAd = new System.Net.IPAddress(ipArr); Console.WriteLine(ipAd.ToString()); } if (icmpHdr != IntPtr.Zero) { Console.Write("ICMP Body : "); WINDIVERT_ICMPHDR dvIP = (WINDIVERT_ICMPHDR)Marshal.PtrToStructure(ipv6Hdr, typeof(WINDIVERT_ICMPHDR)); Console.WriteLine(dvIP.Body); } //} //Write to console Console.WriteLine(String.Format(@"Direction : {0}, Idfx : {1}, Subidfx : {2}", pAddress.Direction, pAddress.IfIdx, pAddress.SubIfIdx)); return(true); } else { return(false); } } finally { //Release all resources Marshal.FreeHGlobal(pAddressPtr); Marshal.FreeHGlobal(bufferPtr); Marshal.FreeHGlobal(readPtr); } }
/// <summary> /// Gets whether or not given ipv4 header has the more fragments flag set. /// </summary> /// <param name="hdr"> /// The ipv4 header. /// </param> /// <returns> /// True if the given ipv4 has the more fragments flag set, false otherwise. /// </returns> public static bool WINDIVERT_IPHDR_GET_MF(WINDIVERT_IPHDR hdr) { return((ushort)((hdr.FragOff0) & 0x0020) != 0); }
/// <summary> /// Gets the fragment offset for the given ipv4 header. /// </summary> /// <param name="hdr"> /// The ipv4 header. /// </param> /// <returns> /// The extracted fragment offset from the given ipv4 header. /// </returns> public static ushort WINDIVERT_IPHDR_GET_FRAGOFF(WINDIVERT_IPHDR hdr) { return((ushort)((hdr.FragOff0) & 0xFF1F)); }
/// <summary> /// Sets the reserved flag to the given value. /// </summary> /// <param name="hdr"> /// The ipv4 header. /// </param> /// <param name="val"> /// The reserved flag value. /// </param> public static void WINDIVERT_IPHDR_SET_RESERVED(WINDIVERT_IPHDR header, ushort val) { header.FragOff0 = (ushort)(((header.FragOff0) & 0xFF7F) | (((val) & 0x0001) << 7)); }
/// <summary> /// Sets the don't fragment flag to the given value. /// </summary> /// <param name="hdr"> /// The ipv4 header. /// </param> /// <param name="val"> /// The don't fragment flag value. /// </param> public static void WINDIVERT_IPHDR_SET_DF(WINDIVERT_IPHDR header, ushort val) { header.FragOff0 = (ushort)(((header.FragOff0) & 0xFFBF) | (((val) & 0x0001) << 6)); }
/// <summary> /// Sets the fragment offset for the given ipv4 header. /// </summary> /// <param name="hdr"> /// The ipv4 header. /// </param> /// <param name="val"> /// The fragment offset. /// </param> public static void WINDIVERT_IPHDR_SET_FRAGOFF(WINDIVERT_IPHDR header, ushort val) { header.FragOff0 = (ushort)(((header.FragOff0) & 0x00E0) | ((val) & 0xFF1F)); }