欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[C#] WinPcap API,Ethernet/ARP/IP/TCP/UDP/ICMP 头部声明与 checksum 计算

程序员文章站 2022-07-10 14:33:51
...
// Code By TZWSOHO 2019.07.09

using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace WinPcap
{
    public static class WinPcap
    {
        public const UInt16 ETHERNET_IP = 0x0800;
        public const UInt16 ETHERNET_ARP = 0x0806;
        public const UInt16 ETHERNET_RARP = 0x8035;
        public const UInt16 ETHERNET_PPPoE = 0x8864;
        public const UInt16 ETHERNET_IPv6 = 0x86DD;
        public const UInt16 ETHERNET_802_1Q_tag = 0x8100; // 802.1Q tag
        public const UInt16 ETHERNET_MPLS_Label = 0x8847; // MPLS Label

        public const UInt16 ARP_HARDWARE = 0x0001; // Dummy type for 802.3 frames

        public const UInt16 ARP_REQUEST = 0x0001;
        public const UInt16 ARP_REPLY = 0x0002;

        public const int PCAP_IF_LOOPBACK = 0x00000001;

        public const int PCAP_SNAPLEN = 65535;

        public const int DLT_EN10MB = 1;

        public const int PCAP_OPENFLAG_PROMISCUOUS = 1;
        public const int PCAP_OPENFLAG_DATATX_UDP = 2;
        public const int PCAP_OPENFLAG_NOCAPTURE_RPCAP = 4;

        public const string PCAP_SRC_FILE_STRING = "file://";
        public const string PCAP_SRC_IF_STRING = "rpcap://";

        [StructLayout(LayoutKind.Sequential)]
        public class bpf_program
        {
            public uint bf_len;
            public IntPtr bf_insns;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class SOCKADDR
        {
            public int sa_family;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 14)]
            public byte[] sa_data;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class PCAP_ADDR
        {
            public IntPtr Next;
            public IntPtr Addr;
            public IntPtr Netmask;
            public IntPtr Broadaddr;
            public IntPtr Dstaddr;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class PCAP_IF
        {
            public IntPtr Next;
            public string Name;
            public string Description;
            public IntPtr Addresses;
            public uint Flags;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class PCAP_PKTDATA
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10000)]
            public byte[] bytes;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class PCAP_PKTHDR
        {
            public uint tv_sec;
            public uint tv_usec;
            public int caplen;
            public int len;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential)]
        public class pcap_send_queue
        {
            public uint maxlen;
            public uint len;
            public IntPtr ptrBuff;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public class ETHERNET_HEADER
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            internal Byte[] m_DstAddr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            internal Byte[] m_SrcAddr;
            internal Int16 m_nType;

            public string GetENDestinationAddress()
            {
                return BitConverter.ToString(m_DstAddr).Replace('-', ':');
            }

            public void SetENDestinationAddress(Byte[] dst_addr)
            {
                if (6 != dst_addr.Length) return;

                m_DstAddr = dst_addr;
            }

            public string GetENSourceAddress()
            {
                return BitConverter.ToString(m_SrcAddr).Replace('-', ':');
            }

            public void SetENSourceAddress(Byte[] src_addr)
            {
                if (6 != src_addr.Length) return;

                m_SrcAddr = src_addr;
            }

            public UInt16 GetENType()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nType);
            }

            public void SetENType(UInt16 e_type)
            {
                m_nType = IPAddress.HostToNetworkOrder((Int16)e_type);
            }
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public class ARP_HEADER
        {
            // 以下是头部
            internal Int16 m_nHrdAddr; // 硬件类型
            internal Int16 m_nPtcAddr; // 协议类型
            internal Byte m_nHrdAddrLen; // 硬件地址长度
            internal Byte m_nPtcAddrLen; // 协议地址长度
            internal Int16 m_nOperation; // ARP/RARP operation

            // 以下是正文
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            internal Byte[] m_SndHrdAddr; // 发送者硬件地址
            internal UInt32 m_nSndPtcAddr; // 发送者 IP
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            internal Byte[] m_TrgHrdAddr; // 目标硬件地址
            internal UInt32 m_nTrgPtcAddr; // 目标 IP

            public ARP_HEADER()
            {
                m_nHrdAddr = IPAddress.HostToNetworkOrder((Int16)ARP_HARDWARE);
                m_nPtcAddr = IPAddress.HostToNetworkOrder((Int16)ETHERNET_IP); // IPv4
                m_nHrdAddrLen = 6; // MAC 长度
                m_nPtcAddrLen = 4; // IPv4 长度
            }

            public Int16 GetARPHardwareAddress()
            {
                return IPAddress.NetworkToHostOrder(m_nHrdAddr);
            }

            public void SetARPHardwareAddress(UInt16 hdr_addr)
            {
                m_nHrdAddr = IPAddress.HostToNetworkOrder((Int16)hdr_addr);
            }

            public Int16 GetARPProtocolAddress()
            {
                return IPAddress.NetworkToHostOrder(m_nPtcAddr);
            }

            public void SetARPProtocolAddress(UInt16 ptc_addr)
            {
                m_nPtcAddr = IPAddress.HostToNetworkOrder((Int16)ptc_addr);
            }

            public Byte GetARPHardwareAddressLength()
            {
                return m_nHrdAddrLen;
            }

            public void SetARPHardwareAddressLength(Byte hdr_addr_len)
            {
                m_nHrdAddrLen = hdr_addr_len;
            }

            public Byte GetARPProtocolAddressLength()
            {
                return m_nPtcAddrLen;
            }

            public void SetARPProtocolAddressLength(Byte ptc_addr_len)
            {
                m_nPtcAddrLen = ptc_addr_len;
            }

            public UInt16 GetARPOperation()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nOperation);
            }

            public void SetARPOperation(UInt16 op)
            {
                m_nOperation = IPAddress.HostToNetworkOrder((Int16)op);
            }

            public string GetARPSenderMAC()
            {
                return BitConverter.ToString(m_SndHrdAddr).Replace('-', ':');
            }

            public void SetARPSenderMAC(Byte[] snd_hdr_addr)
            {
                if (6 != snd_hdr_addr.Length) return;

                m_SndHrdAddr = snd_hdr_addr;
            }

            public string GetARPSenderIP()
            {
                return new IPAddress((long)m_nSndPtcAddr).ToString();
            }

            public void SetARPSourceIP(IPAddress src_ip)
            {
                m_nSndPtcAddr = BitConverter.ToUInt32(src_ip.GetAddressBytes(), 0);
            }

            public void SetARPSourceIP(long src_ip)
            {
                SetARPSourceIP(new IPAddress(src_ip));
            }

            public void SetARPSourceIP(Byte[] src_ip)
            {
                SetARPSourceIP(new IPAddress(src_ip));
            }

            public void SetARPSourceIP(string src_ip)
            {
                SetARPSourceIP(IPAddress.Parse(src_ip));
            }

            public string GetARPTargetMAC()
            {
                return BitConverter.ToString(m_TrgHrdAddr).Replace('-', ':');
            }

            public void SetARPTargetMAC(Byte[] trg_hdr_addr)
            {
                if (6 != trg_hdr_addr.Length) return;

                m_TrgHrdAddr = trg_hdr_addr;
            }

            public string GetARPTargetIP()
            {
                return new IPAddress((long)m_nTrgPtcAddr).ToString();
            }

            public void SetARPTargetIP(IPAddress trg_ip)
            {
                m_nTrgPtcAddr = BitConverter.ToUInt32(trg_ip.GetAddressBytes(), 0);
            }

            public void SetARPTargetIP(long trg_ip)
            {
                SetARPTargetIP(new IPAddress(trg_ip));
            }

            public void SetARPTargetIP(Byte[] trg_ip)
            {
                SetARPTargetIP(new IPAddress(trg_ip));
            }

            public void SetARPTargetIP(string trg_ip)
            {
                SetARPTargetIP(IPAddress.Parse(trg_ip));
            }
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class IP_HEADER
        {
            [FieldOffset(0)]
            internal Byte m_nVersionLen;
            [FieldOffset(1)]
            internal Byte m_nTOS; // Type of Service
            [FieldOffset(2)]
            internal Int16 m_nLen; // Total length of the packet
            [FieldOffset(4)]
            internal Int16 m_nId;
            [FieldOffset(6)]
            internal Int16 m_nFlags; // Flags and Offset
            [FieldOffset(8)]
            internal Byte m_nTTL; // Time to Live
            [FieldOffset(9)]
            internal Byte m_nProtocol;
            [FieldOffset(10)]
            internal Int16 m_nCheckSum; // IP Header CheckSum
            [FieldOffset(12)]
            internal UInt32 m_nSrcIP;
            [FieldOffset(16)]
            internal UInt32 m_nDstIP;

            public IP_HEADER()
            {
                m_nVersionLen = (Byte)0x45; // Version = 4, Header Length = 5 * 4
            }

            public Byte GetIPVersion()
            {
                return (Byte)((m_nVersionLen >> 4) & 0x0F);
            }

            public void SetIPVersion(Byte ver)
            {
                m_nVersionLen = (Byte)((m_nVersionLen & 0x0F) | ((ver << 4) & 0xF0));
            }

            public UInt16 GetIPHeaderLength()
            {
                // 单位是双字,乘四
                return (UInt16)((m_nVersionLen & 0x0F) * 4);
            }

            public void SetIPHeaderLength(Byte hdr_len)
            {
                m_nVersionLen = (Byte)((m_nVersionLen & 0xF0) | (hdr_len & 0x0F));
            }

            public Byte GetIPTypeOfService()
            {
                return m_nTOS;
            }

            public void SetIPTypeOfService(Byte tos)
            {
                m_nTOS = tos;
            }

            public UInt16 GetIPPacketLength()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nLen);
            }

            public void SetIPPacketLength(UInt16 pkt_len)
            {
                m_nLen = IPAddress.HostToNetworkOrder((Int16)pkt_len);
            }

            public UInt16 GetIPID()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nId);
            }

            public void SetIPID(UInt16 id)
            {
                m_nId = IPAddress.HostToNetworkOrder((Int16)id);
            }

            public UInt16 GetIPFlags()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nFlags);
            }

            public void SetIPFlags(UInt16 flags)
            {
                m_nFlags = IPAddress.HostToNetworkOrder((Int16)flags);
            }

            public bool GetIPDontFragment()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x4000);
            }

            public void SetIPDontFragment(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x4000));
                }
                else
	            {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x4000));
	            }
            }

            public bool GetIPMoreFragments()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x2000);
            }

            public void SetIPMoreFragments(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x2000));
                }
                else
	            {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x2000));
	            }
            }

            public UInt16 GetIPFragmentOffset()
            {
                return (UInt16)(IPAddress.NetworkToHostOrder(m_nFlags) & 0x1FFF);
            }

            public void SetIPMoreFragments(UInt16 offset)
            {
                m_nFlags = IPAddress.HostToNetworkOrder((Int16)(
                    (IPAddress.NetworkToHostOrder(m_nFlags) & ~0x1FFF) |
                    (offset & 0x1FFF)));
            }

            public Byte GetIPTimeToLive()
            {
                return m_nTTL;
            }

            public void SetIPTimeToLive(Byte ttl)
            {
                m_nTTL = ttl;
            }

            public ProtocolType GetIPProtocol()
            {
                return (ProtocolType)m_nProtocol;
            }

            public void SetIPProtocol(ProtocolType ptc)
            {
                m_nProtocol = (Byte)ptc;
            }

            public UInt16 GetIPChecksum()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nCheckSum);
            }

            public UInt32 GetIPSrcIP()
            {
                return m_nSrcIP;
            }

            public string GetIPSourceIP()
            {
                return new IPAddress(BitConverter.GetBytes(m_nSrcIP)).ToString();
            }

            public void SetIPSourceIP(IPAddress src_ip)
            {
                m_nSrcIP = BitConverter.ToUInt32(src_ip.GetAddressBytes(), 0);
            }

            public void SetIPSourceIP(long src_ip)
            {
                SetIPSourceIP(new IPAddress(src_ip));
            }

            public void SetARPTargetIP(Byte[] src_ip)
            {
                SetIPSourceIP(new IPAddress(src_ip));
            }

            public void SetARPTargetIP(string src_ip)
            {
                SetIPSourceIP(IPAddress.Parse(src_ip));
            }

            public UInt32 GetIPDstIP()
            {
                return m_nDstIP;
            }

            public string GetIPDestinationIP()
            {
                return new IPAddress(BitConverter.GetBytes(m_nDstIP)).ToString();
            }

            public void SetIPDestinationIP(IPAddress dst_ip)
            {
                m_nDstIP = BitConverter.ToUInt32(dst_ip.GetAddressBytes(), 0);
            }

            public void SetIPDestinationIP(long dst_ip)
            {
                SetIPDestinationIP(new IPAddress(dst_ip));
            }

            public void SetIPDestinationIP(Byte[] dst_ip)
            {
                SetIPDestinationIP(new IPAddress(dst_ip));
            }

            public void SetIPDestinationIP(string dst_ip)
            {
                SetIPDestinationIP(IPAddress.Parse(dst_ip));
            }

            public void RecalcChecksum(IntPtr pData)
            {
                //Int16 org_chk_sum = m_nCheckSum;

                Byte[] ip_data = new Byte[GetIPHeaderLength()];

                Marshal.Copy(pData, ip_data, 0, GetIPHeaderLength());
                ip_data[10] = 0; // Checksum 置零
                ip_data[11] = 0;

                Int16 chk_sum = CalcChecksum(ip_data);
                //System.Diagnostics.Debug.Assert(chk_sum == org_chk_sum);
                //m_nCheckSum = org_chk_sum;

                m_nCheckSum = chk_sum;
            }
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class IP_HEADER2 : IP_HEADER
        {
            [FieldOffset(20)]
            internal UInt32 m_nOptions;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class TCP_UDP_PSEUDO_HEADER
        {
            [FieldOffset(0)]
            internal UInt32 m_nSrcIP;
            [FieldOffset(4)]
            internal UInt32 m_nDstIP;
            [FieldOffset(8)]
            internal Byte m_nZero;
            [FieldOffset(9)]
            internal Byte m_nProtocol;
            [FieldOffset(10)]
            internal UInt16 m_nIPLength;
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class TCP_HEADER
        {
            [FieldOffset(0)]
            internal Int16 m_nSrcPort;
            [FieldOffset(2)]
            internal Int16 m_nDstPort;
            [FieldOffset(4)]
            internal Int32 m_nSeqNum;
            [FieldOffset(8)]
            internal Int32 m_nAckNum;
            [FieldOffset(12)]
            internal Int16 m_nFlags; // 低 4 位:头部大小,第 4~6 位:保留,第 10 位:URG,第 11 位:ACK,第 12 位:PSH,第 13 位:RST,第 14 位:SYN,第 15 位:FIN
            [FieldOffset(14)]
            internal Int16 m_nWindow;
            [FieldOffset(16)]
            internal Int16 m_nCheckSum;
            [FieldOffset(18)]
            internal Int16 m_nUrgentPointer;

            public UInt16 GetTCPSourcePort()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nSrcPort);
            }

            public void SetTCPSourcePort(UInt16 src_port)
            {
                m_nSrcPort = IPAddress.HostToNetworkOrder((Int16)src_port);
            }

            public UInt16 GetTCPDestinationPort()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nDstPort);
            }

            public void SetTCPDestinationPort(UInt16 dst_port)
            {
                m_nDstPort = IPAddress.HostToNetworkOrder((Int16)dst_port);
            }

            public UInt32 GetTCPSequenceNumber()
            {
                return (UInt32)IPAddress.NetworkToHostOrder(m_nSeqNum);
            }

            public void SetTCPSequenceNumber(UInt32 seq_num)
            {
                m_nSeqNum = IPAddress.HostToNetworkOrder((Int32)seq_num);
            }

            public UInt32 GetTCPAcknowledgementNumber()
            {
                return (UInt32)IPAddress.NetworkToHostOrder(m_nAckNum);
            }

            public void SetTCPAcknowledgementNumber(UInt32 ack_num)
            {
                m_nAckNum = IPAddress.HostToNetworkOrder((Int32)ack_num);
            }

            // Code By TZWSOHO 2019.07.09
            public UInt16 GetTCPFlags()
            {
                return (UInt16)(IPAddress.NetworkToHostOrder(m_nFlags) & 0xFFF);
            }

            public void SetTCPFlags(UInt16 flags)
            {
                m_nFlags = IPAddress.HostToNetworkOrder((Int16)(flags & 0xFFF));
            }

            public Byte GetTCPHeaderLength()
            {
                return (Byte)((((IPAddress.NetworkToHostOrder(m_nFlags) & 0xF000) >> 12) & 0x0F) * 4);
            }

            public void SetTCPHeaderLength(Byte hdr_len)
            {
                m_nFlags = IPAddress.HostToNetworkOrder((Int16)(
                    (IPAddress.NetworkToHostOrder(m_nFlags) & ~0xF000) |
                    (((hdr_len / 4) << 12) & 0xF000)));
            }

            public bool GetTCPNonceFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x100);
            }

            public void SetTCPNonceFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x100));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x100));
                }
            }

            public bool GetTCPCWRFlag() // Congestion Window Reduced
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x080);
            }

            public void SetTCPCWRFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x080));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x080));
                }
            }

            public bool GetTCPECNFlag() // ECN-Echo
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x040);
            }

            public void SetTCPECNFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x040));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x040));
                }
            }

            public bool GetTCPUrgentFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x020);
            }

            public void SetTCPUrgentFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x020));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x020));
                }
            }

            public bool GetTCPAcknowledgeFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x010);
            }

            public void SetTCPAcknowledgeFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x010));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x010));
                }
            }

            public bool GetTCPPushFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x008);
            }

            public void SetTCPPushFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x008));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x008));
                }
            }

            public bool GetTCPResetFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x004);
            }

            public void SetTCPResetFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x004));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x004));
                }
            }

            public bool GetTCPSynchronisationFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x002);
            }

            public void SetTCPSynchronisationFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x002));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x002));
                }
            }

            public bool GetTCPFinishFlag()
            {
                return 0 != (IPAddress.NetworkToHostOrder(m_nFlags) & 0x001);
            }

            public void SetTCPFinishFlag(bool is_set)
            {
                if (is_set)
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) | 0x001));
                }
                else
                {
                    m_nFlags = IPAddress.HostToNetworkOrder((Int16)(IPAddress.NetworkToHostOrder(m_nFlags) & ~0x001));
                }
            }

            public UInt16 GetTCPWindow()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nWindow);
            }

            public void SetTCPWindow(UInt16 window)
            {
                m_nWindow = IPAddress.HostToNetworkOrder((Int16)window);
            }

            public UInt16 GetTCPChecksum()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nCheckSum);
            }

            public UInt16 GetTCPUrgentPointer()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nUrgentPointer);
            }

            public void SetTCPUrgentPointer(UInt16 urg_ptr)
            {
                m_nUrgentPointer = IPAddress.HostToNetworkOrder((Int16)urg_ptr);
            }

            public void RecalcChecksum(IntPtr pData, IP_HEADER ip_hdr)
            {
                //Int16 org_chk_sum = m_nCheckSum;

                int tcp_hdr_size = Marshal.SizeOf(typeof(TCP_HEADER));
                int ip_psd_size = Marshal.SizeOf(typeof(TCP_UDP_PSEUDO_HEADER));
                int size_without_ip_hdr = ip_hdr.GetIPPacketLength() - ip_hdr.GetIPHeaderLength();
                Byte[] tcp_chk = new Byte[ip_psd_size + size_without_ip_hdr];

                TCP_UDP_PSEUDO_HEADER ip_psd_hdr = new TCP_UDP_PSEUDO_HEADER();
                ip_psd_hdr.m_nSrcIP = ip_hdr.GetIPSrcIP();
                ip_psd_hdr.m_nDstIP = ip_hdr.GetIPDstIP();
                ip_psd_hdr.m_nZero = 0;
                ip_psd_hdr.m_nProtocol = (Byte)ProtocolType.Tcp;
                ip_psd_hdr.m_nIPLength = (UInt16)IPAddress.HostToNetworkOrder((Int16)size_without_ip_hdr);

                GCHandle gch_psd = GCHandle.Alloc(ip_psd_hdr, GCHandleType.Pinned);
                Marshal.Copy(gch_psd.AddrOfPinnedObject(), tcp_chk, 0, ip_psd_size);

                m_nCheckSum = 0;
                GCHandle gch_tcp = GCHandle.Alloc(this, GCHandleType.Pinned);
                Marshal.Copy(gch_tcp.AddrOfPinnedObject(), tcp_chk, ip_psd_size, tcp_hdr_size);

                int data_size = size_without_ip_hdr - tcp_hdr_size;
                Marshal.Copy(pData + tcp_hdr_size, tcp_chk, ip_psd_size + tcp_hdr_size, data_size);

                Int16 chk_sum = CalcChecksum(tcp_chk);
                //System.Diagnostics.Debug.Assert(chk_sum == org_chk_sum);
                //m_nCheckSum = org_chk_sum;

                m_nCheckSum = chk_sum;
            }
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class UDP_HEADER
        {
            [FieldOffset(0)]
            internal Int16 m_nSrcPort;
            [FieldOffset(2)]
            internal Int16 m_nDstPort;
            [FieldOffset(4)]
            internal Int16 m_nLen;
            [FieldOffset(6)]
            internal Int16 m_nCheckSum;

            public UInt16 GetUDPSourcePort()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nSrcPort);
            }

            public void SetUDPSourcePort(UInt16 src_port)
            {
                m_nSrcPort = IPAddress.HostToNetworkOrder((Int16)src_port);
            }

            public UInt16 GetUDPDestinationPort()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nDstPort);
            }

            public void SetUDPDestinationPort(UInt16 dst_port)
            {
                m_nDstPort = IPAddress.HostToNetworkOrder((Int16)dst_port);
            }

            public UInt16 GetUDPPacketLength()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nLen);
            }

            public void SetUDPPacketLength(UInt16 len)
            {
                m_nLen = IPAddress.HostToNetworkOrder((Int16)len);
            }

            public UInt16 GetUDPChecksum()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nCheckSum);
            }

            public void RecalcChecksum(IntPtr pData, IP_HEADER ip_hdr)
            {
                //Int16 org_chk_sum = m_nCheckSum;

                int udp_hdr_size = Marshal.SizeOf(typeof(UDP_HEADER));
                int ip_psd_size = Marshal.SizeOf(typeof(TCP_UDP_PSEUDO_HEADER));
                int size_without_ip_hdr = ip_hdr.GetIPPacketLength() - ip_hdr.GetIPHeaderLength();
                Byte[] udp_chk = new Byte[ip_psd_size + size_without_ip_hdr];

                TCP_UDP_PSEUDO_HEADER ip_psd_hdr = new TCP_UDP_PSEUDO_HEADER();
                ip_psd_hdr.m_nSrcIP = ip_hdr.GetIPSrcIP();
                ip_psd_hdr.m_nDstIP = ip_hdr.GetIPDstIP();
                ip_psd_hdr.m_nZero = 0;
                ip_psd_hdr.m_nProtocol = (Byte)ProtocolType.Udp;
                ip_psd_hdr.m_nIPLength = (UInt16)IPAddress.HostToNetworkOrder((Int16)size_without_ip_hdr);

                GCHandle gch_psd = GCHandle.Alloc(ip_psd_hdr, GCHandleType.Pinned);
                Marshal.Copy(gch_psd.AddrOfPinnedObject(), udp_chk, 0, ip_psd_size);

                m_nCheckSum = 0;
                GCHandle gch_udp = GCHandle.Alloc(this, GCHandleType.Pinned);
                Marshal.Copy(gch_udp.AddrOfPinnedObject(), udp_chk, ip_psd_size, udp_hdr_size);

                int data_size = size_without_ip_hdr - udp_hdr_size;
                Marshal.Copy(pData + udp_hdr_size, udp_chk, ip_psd_size + udp_hdr_size, data_size);

                Int16 chk_sum = CalcChecksum(udp_chk);
                //System.Diagnostics.Debug.Assert(chk_sum == org_chk_sum);
                //m_nCheckSum = org_chk_sum;

                m_nCheckSum = chk_sum;
            }
        }

        // Code By TZWSOHO 2019.07.09
        [StructLayout(LayoutKind.Explicit)]
        public class ICMP_HEADER
        {
            [FieldOffset(0)]
            internal Byte m_nType;
            [FieldOffset(1)]
            internal Byte m_nCode;
            [FieldOffset(2)]
            internal Int16 m_nCheckSum;
            [FieldOffset(4)]
            internal Int16 m_nId;
            [FieldOffset(6)]
            internal Int16 m_nSeqNum;

            public Byte GetICMPType()
            {
                return m_nType;
            }

            public void SetICMPType(Byte t)
            {
                m_nType = t;
            }

            public Byte GetICMPCode()
            {
                return m_nCode;
            }

            public void SetICMPCode(Byte c)
            {
                m_nCode = c;
            }

            public UInt16 GetICMPChecksum()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nCheckSum);
            }

            public UInt16 GetICMPID()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nId);
            }

            public void SetICMPID(UInt16 id)
            {
                m_nId = IPAddress.HostToNetworkOrder((Int16)id);
            }

            public UInt16 GetICMPSequenceNumber()
            {
                return (UInt16)IPAddress.NetworkToHostOrder(m_nSeqNum);
            }

            public void SetICMPSequenceNumber(UInt16 seq_num)
            {
                m_nSeqNum = IPAddress.HostToNetworkOrder((Int16)seq_num);
            }

            public void RecalcChecksum(IntPtr pData, IP_HEADER ip_hdr)
            {
                //Int16 org_chk_sum = m_nCheckSum;

                int icmp_hdr_size = Marshal.SizeOf(typeof(ICMP_HEADER));
                int size_without_ip_hdr = ip_hdr.GetIPPacketLength() - ip_hdr.GetIPHeaderLength();
                Byte[] icmp_chk = new Byte[size_without_ip_hdr];

                m_nCheckSum = 0;
                GCHandle gch_icmp = GCHandle.Alloc(this, GCHandleType.Pinned);
                Marshal.Copy(gch_icmp.AddrOfPinnedObject(), icmp_chk, 0, icmp_hdr_size);

                int data_size = size_without_ip_hdr - icmp_hdr_size;
                Marshal.Copy(pData + icmp_hdr_size, icmp_chk, icmp_hdr_size, data_size);

                Int16 chk_sum = CalcChecksum(icmp_chk);
                //System.Diagnostics.Debug.Assert(chk_sum == org_chk_sum);
                //m_nCheckSum = org_chk_sum;

                m_nCheckSum = chk_sum;
            }
        }

        public static Int16 CalcChecksum(Byte[] data)
        {
            Byte[] tmp_data = new Byte[0 == data.Length % 2 ? data.Length : data.Length + 1];
            data.CopyTo(tmp_data, 0);

            UInt32 chk_sum = 0;
            for (int i = 0; i < tmp_data.Length; i += 2)
            {
                UInt16 tmp = BitConverter.ToUInt16(tmp_data, i);
                chk_sum += tmp;
            }

            while (0 != (chk_sum & 0xFFFF0000))
            {
                chk_sum = ((chk_sum >> 16) & 0x0000FFFF) + (chk_sum & 0x0000FFFF);
            }

            return (Int16)~chk_sum;
        }

        // Code By TZWSOHO 2019.07.09
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void pcap_close(IntPtr adaptHandle);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_compile(IntPtr adaptHandle, IntPtr fp, string str, int optimize, uint netmask);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_datalink(IntPtr adaptHandle);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void pcap_dump(IntPtr user, IntPtr h, IntPtr sp);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void pcap_dump_close(IntPtr p);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_dump_file(IntPtr p);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_dump_flush(IntPtr p);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_dump_open(IntPtr adaptHandle, string fname);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_findalldevs(ref IntPtr alldevs, StringBuilder errbuf);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_findalldevs_ex(string source, IntPtr auth, ref IntPtr alldevs, StringBuilder errbuf);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void pcap_freealldevs(IntPtr alldevs);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_geterr(IntPtr adaptHandle);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_lib_version();
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_loop(IntPtr adaptHandle, int count, PcapHandler callback, IntPtr ptr);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_dispatch(IntPtr adaptHandle, int count, PcapHandler callback, IntPtr ptr);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_next_ex(IntPtr adaptHandle, ref IntPtr header, ref IntPtr data);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_open(string dev, int packetLen, int mode, int timeout, IntPtr auth, StringBuilder errbuf);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_open_live(string dev, int packetLen, int mode, int timeout, StringBuilder errbuf);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_open_offline(string fname, StringBuilder errbuf);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_sendpacket(IntPtr adaptHandle, IntPtr data, int size);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr pcap_sendqueue_alloc(int memsize);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern void pcap_sendqueue_destroy(IntPtr queue);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_sendqueue_queue(IntPtr queue, IntPtr header, IntPtr data);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_sendqueue_transmit(IntPtr p, IntPtr queue, int sync);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_setfilter(IntPtr adaptHandle, IntPtr fp);
        [DllImport("wpcap.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int pcap_setmode(IntPtr p, int mode);

        public delegate void PcapHandler(IntPtr param, IntPtr header, IntPtr pkt_data);
    }
}

计算校验和的算法真是搞死人,算法很简单,但是需要注意的细节有很多,忘了其中一步就会算错。