Пример #1
0
        // set the checksum field, totalSize covers all the fields for
        // which the checksum is calculated
        // offset is points to the beginning of the IP header (!!!)
        // Should be called after the UDP header + data have been written
        public static void SetUdpChecksum(byte[] !packet,
                                          int ipOffset,
                                          ref UdpHeader udpHeader)
        {
            // sum IP pseudo
            ushort ipPayloadSize = 0;
            ushort headerSum     = IPFormat.SumPseudoHeader(packet, ipOffset,
                                                            ref ipPayloadSize);

            Debug.Assert(((ushort)udpHeader.length) == ipPayloadSize);

            // now add it to the udp header + data
            int ipHeaderSize = (packet[ipOffset] & 0xf) * 4;
            int udpOffset    = ipOffset + ipHeaderSize;

            Debug.Assert(packet[udpOffset + 6] == 0);
            Debug.Assert(packet[udpOffset + 7] == 0);

            ushort payloadSum = IPFormat.SumShortValues(packet, udpOffset,
                                                        ipPayloadSize);

            udpHeader.checksum = IPFormat.ComplementAndFixZeroChecksum(
                IPFormat.SumShortValues(headerSum, payloadSum));

            packet[udpOffset + 6] = (byte)(udpHeader.checksum >> 8);
            packet[udpOffset + 7] = (byte)(udpHeader.checksum & 0xff);
        }
Пример #2
0
        // set the checksum field
        // offset points to the beginning of the IP header (!!!)
        // Should be called after the TCP header + data have been written
        public static void SetTcpChecksum(byte[] !packet,
                                          int ipOffset,
                                          ref TcpHeader tcpHeader)
        {
            // sum IP pseudo
            ushort ipPayloadLength = 0;
            ushort headerSum       =
                IPFormat.SumPseudoHeader(packet, ipOffset,
                                         ref ipPayloadLength);

            int ipHeaderSize = (packet[ipOffset] & 0xf) * 4;
            int tcpOffset    = ipOffset + ipHeaderSize;

            Debug.Assert(packet[tcpOffset + 16] == 0);
            Debug.Assert(packet[tcpOffset + 17] == 0);

            // now add it to the TCP header + data
            ushort payloadSum = IPFormat.SumShortValues(packet, tcpOffset,
                                                        ipPayloadLength);

            tcpHeader.checksum = (ushort)
                                 ~(IPFormat.SumShortValues(headerSum, payloadSum));

            // Complement and change +0 to -0 if needed.
            ushort tcpChecksum = IPFormat.ComplementAndFixZeroChecksum(
                (IPFormat.SumShortValues(headerSum, payloadSum)));

            tcpHeader.checksum = tcpChecksum;

            unchecked {
                packet[tcpOffset + 16] = (byte)(tcpChecksum >> 8);
                packet[tcpOffset + 17] = (byte)(tcpChecksum >> 0);
            }
        }
Пример #3
0
        public static bool IsChecksumValid(IPFormat.IPHeader !ipHeader,
                                           TcpHeader tcpHeader,
                                           NetPacket !payload)
        {
            // Compute partial checksums of headers
            ushort checksum = IPFormat.SumPseudoHeader(ipHeader);

            checksum = IPFormat.SumShortValues(checksum,
                                               SumHeader(tcpHeader));

            // Checksum payload (without potential odd byte)
            int  length          = payload.Available;
            int  end             = length & ~1;
            int  i               = 0;
            uint payloadChecksum = 0;

            while (i != end)
            {
                byte b0 = payload.PeekAvailable(i++);
                byte b1 = payload.PeekAvailable(i++);
                payloadChecksum += ((((uint)b0) << 8) + (uint)b1);
            }

            // Handle odd byte.
            if (i != length)
            {
                payloadChecksum += (((uint)payload.PeekAvailable(i++)) << 8);
            }

            // Merge bits from payload checksum
            checksum = IPFormat.SumUInt16AndUInt32Values(checksum, payloadChecksum);

            // Complement and change +0 to -0 if needed.
            checksum = IPFormat.ComplementAndFixZeroChecksum(checksum);

            // Check for match.
            bool checksumMatch = (tcpHeader.checksum == checksum);

            // If checksum error, unconditionally output message to debugger.
            if (checksumMatch == false)
            {
                DebugStub.WriteLine("Bad TCP checksum {0:x4} != {1:x4}:  SEQ {2:x8}  ACK {3:x8}",
                                    __arglist(tcpHeader.checksum, checksum,
                                              tcpHeader.seq,
                                              tcpHeader.ackSeq
                                              ));
            }

            // IsValid is a Match.
            return(checksumMatch);
        }
Пример #4
0
        /// <summary>
        /// Update checksum when a 16-bit value that composed the original
        /// checksum changes.  Useful for recomputing checksum when
        /// TTL changes when acting as a router.
        /// </summary>
        public static ushort UpdateChecksum(ushort checksum,
                                            ushort oldValue,
                                            ushort newValue)
        {
            // From RFC1624
            ushort newChecksum;

            unchecked {
                newChecksum  = (ushort)~checksum;
                newChecksum += (ushort)~oldValue;
                newChecksum += newValue;
            }
            return(IPFormat.ComplementAndFixZeroChecksum(newChecksum));
        }
Пример #5
0
        /// <summary>
        /// Write IP and UDP headers and payload data into a
        /// byte array.
        /// </summary>
        /// <param name="pkt">Array of bytes representing
        /// packet to be sent.</param>
        /// <param name="offset">Offset of IP Header within
        /// packet.</param>
        /// <param name="ipHeader">IP header to be written
        /// to packet.</param>
        /// <param name="udpHeader">UDP header to be written
        /// to packet.</param>
        /// <param name="payload">Payload of UDP Packet.</param>
        /// <param name="payloadOffset">The offset of start
        /// of the payload data within the payload
        /// array.</param>

        /// <param name="payloadLength">The size of the payload data.</param>
        public static void WriteUdpPacket(byte[] !pkt,
                                          int offset,
                                          IPFormat.IPHeader !ipHeader,
                                          ref UdpHeader udpHeader,
                                          byte[] payload,
                                          int payloadOffset,
                                          int payloadLength)
        {
            int udpStart = IPFormat.WriteIPHeader(pkt, offset, ipHeader);
            int udpEnd   = WriteUdpHeader(pkt, udpStart, ref udpHeader);

            if (pkt != payload || udpEnd != payloadOffset)
            {
                Array.Copy(payload, payloadOffset,
                           pkt, udpEnd, payloadLength);
            }
            SetUdpChecksum(pkt, offset, ref udpHeader);
        }
Пример #6
0
            // write an ICMP echo request
            public static int WriteIcmpEchoRequest(byte[] !pkt, int offset, ref IcmpEchoRequest request)
            {
                int o = offset;

                // write the common header
                o = WriteIcmpHeader(pkt, offset, ref request.header);

                // dump the data (endian doesn't matter, since it is a user data)
                Array.Copy(request.data, 0, pkt, o, request.data.Length);

                // calc the checksum
                ushort chk = IPFormat.Checksum(pkt, offset,
                                               request.GetSize());

                pkt[offset + 2]       = (byte)(((ushort)chk) >> 8);
                pkt[offset + 3]       = (byte)(((ushort)chk) & 0xff);
                request.header.chksum = chk;

                return(o);
            }
Пример #7
0
        // a fast method that uses that modified the ECHO request
        // packet to an ECHO reply.
        // return true if success
        public static void CreateFastEchoReply(byte[] !pkt, int icmpPacketSize)
        {
            // 1. switch the source IP and destination IP
            // 2. change ICMP code to IcmpFormat.IcmpType.ECHO_REPLY
            // 3. should use ARP table to find out the mac address of the target
            //    (if it is on the local network)
            //    CURRENTLY: just switch MAC addresses as well.
            // 4. recompute ICMP and IP checksums

            int ipStart   = EthernetFormat.Size;
            int icmpStart = ipStart + IPFormat.Size;

            pkt[icmpStart] = (byte)IcmpFormat.IcmpType.ECHO_REPLY;
            // zero checksum
            pkt[icmpStart + 2] = 0;
            pkt[icmpStart + 3] = 0;
            ushort chk = IPFormat.Checksum(pkt, icmpStart, icmpPacketSize);

            pkt[icmpStart + 2] = (byte)(chk >> 8);
            pkt[icmpStart + 3] = (byte)chk;

            // switch IPs
            byte[] tmp = new byte[6];
            Array.Copy(pkt, ipStart + 16, tmp, 0, 4);            // dest->tmp
            Array.Copy(pkt, ipStart + 12, pkt, ipStart + 16, 4); // src->dest
            Array.Copy(tmp, 0, pkt, ipStart + 12, 4);            // tmp->src

            // zero the checksum
            pkt[ipStart + 10] = 0;
            pkt[ipStart + 11] = 0;

            // calculate checksum
            chk = IPFormat.Checksum(pkt, ipStart, IPFormat.Size);
            pkt[ipStart + 10] = (byte)(((ushort)chk) >> 8);
            pkt[ipStart + 11] = (byte)(((ushort)chk) & 0xff);

            // TBC: currently just switch mac addresses
            Array.Copy(pkt, 6, tmp, 0, 6);  // src  -> temp
            Array.Copy(pkt, 0, pkt, 6, 6);  // dest -> src
            Array.Copy(tmp, 0, pkt, 0, 6);  // tmp  -> dest
        }
Пример #8
0
        // writes an IP header to a packet
        // return the next place to write to, fixes the checksum field
        public static int WriteIPHeader(byte[] !pkt, int offset, IPHeader !hdr)
        {
            // check we have enough packet space
            if (pkt.Length - offset < Size)
            {
                return(offset);
            }

            int o = offset;

            pkt[o++] = hdr.verLen;
            pkt[o++] = hdr.tos;
            pkt[o++] = (byte)(((ushort)hdr.totalLength) >> 8);
            pkt[o++] = (byte)(((ushort)hdr.totalLength) & 0xff);
            pkt[o++] = (byte)(((ushort)hdr.id) >> 8);
            pkt[o++] = (byte)(((ushort)hdr.id) & 0xff);
            pkt[o++] = (byte)(((ushort)hdr.offset) >> 8);
            pkt[o++] = (byte)(((ushort)hdr.offset) & 0xff);
            pkt[o++] = hdr.ttl;
            pkt[o++] = hdr.protocol;
            pkt[o++] = 0;
            pkt[o++] = 0;

            // set the ip addresses
            hdr.srcAddr.CopyOut(pkt, o);
            o += IPv4.Length;

            hdr.destAddr.CopyOut(pkt, o);
            o += IPv4.Length;

            // calculate checksum
            ushort chk = IPFormat.FixZeroChecksum(Checksum(pkt, offset, Size));

            pkt[offset + 10] = (byte)(((ushort)chk) >> 8);
            pkt[offset + 11] = (byte)(((ushort)chk) & 0xff);

            // save the header checksum
            hdr.checksum = chk;

            return(o);
        }
Пример #9
0
        public static bool IsChecksumValid(IPFormat.IPHeader !ipHeader,
                                           UdpHeader udpHeader,
                                           NetPacket !payload)
        {
            // Compute partial checksums of headers
            ushort checksum = IPFormat.SumPseudoHeader(ipHeader);

            checksum = IPFormat.SumShortValues(checksum,
                                               UdpFormat.SumHeader(udpHeader));

            // Checksum payload
            int length = payload.Available;
            int end    = length & ~1;
            int i      = 0;

            while (i != end)
            {
                int x = ((((int)payload.PeekAvailable(i++)) << 8) +
                         (int)payload.PeekAvailable(i++));

                checksum = IPFormat.SumShortValues(checksum, (ushort)x);
            }

            if (i != length)
            {
                int x = (((int)payload.PeekAvailable(i++)) << 8);
                checksum = IPFormat.SumShortValues(checksum, (ushort)x);
            }

            checksum = IPFormat.ComplementAndFixZeroChecksum(checksum);

            if (udpHeader.checksum != checksum)
            {
                DebugStub.WriteLine("Bad UDP checksum {0:x4} != {1:x4}",
                                    __arglist(udpHeader.checksum, checksum));
            }
            return(udpHeader.checksum == checksum);
        }
Пример #10
0
        public static bool IsCheckSumOK(IPHeader !hdr)
        {
            ushort sum = (ushort)((((int)hdr.verLen) << 8) + ((int)hdr.tos));

            sum = SumShortValues(sum, hdr.totalLength);
            sum = SumShortValues(sum, hdr.id);
            sum = SumShortValues(sum, hdr.offset);
            sum = SumShortValues(sum, (ushort)((((int)hdr.ttl) << 8) + ((int)hdr.protocol)));
            sum = SumShortValues(sum, (ushort)(((uint)hdr.srcAddr) >> 16));
            sum = SumShortValues(sum, (ushort)(((uint)hdr.srcAddr) & 0xFFFFU));
            sum = SumShortValues(sum, (ushort)(((uint)hdr.destAddr) >> 16));
            sum = SumShortValues(sum, (ushort)(((uint)hdr.destAddr) & 0xFFFFU));

            sum = IPFormat.ComplementAndFixZeroChecksum(sum);

            if (sum != hdr.checksum)
            {
                DebugStub.WriteLine("Bad IP Checksum {0:x4} != {1:x4}",
                                    __arglist(hdr.checksum, sum));
            }

            return(sum == hdr.checksum);
        }
Пример #11
0
        // a helper method to write the TCP segment (without data)
        public static void WriteTcpSegment(byte[] !pktData,
                                           ushort localPort,
                                           ushort destPort,
                                           uint ackSeq,
                                           uint seq,
                                           ushort wnd,
                                           IPv4 sIP,
                                           IPv4 dIP,
                                           ushort dataLen,
                                           bool isAck,
                                           bool isSyn,
                                           bool isRst,
                                           bool isFin,
                                           bool withOptions)
        {
            // now create the IP,TCP headers!
            int start = EthernetFormat.Size;

            // prepare it...
            TcpFormat.TcpHeader tcpHeader = new TcpFormat.TcpHeader();
            tcpHeader.sourcePort = localPort;
            tcpHeader.destPort   = destPort;
            if (withOptions)
            {
                tcpHeader.off_res1 = 0x60;
            }
            else
            {
                tcpHeader.off_res1 = 0x50;
            }

            tcpHeader.ackSeq = ackSeq;
            tcpHeader.seq    = seq;
            tcpHeader.window = wnd;

            if (isFin)
            {
                TcpFormat.SetFIN(ref tcpHeader);
            }
            if (isSyn)
            {
                TcpFormat.SetSYN(ref tcpHeader);
            }
            if (isAck)
            {
                TcpFormat.SetACK(ref tcpHeader);
            }
            if (isRst)
            {
                TcpFormat.SetReset(ref tcpHeader);
            }

            IPFormat.IPHeader ipHeader = new IPFormat.IPHeader();
            ipHeader.SetDefaults(IPFormat.Protocol.TCP);
            ipHeader.totalLength = (ushort)(IPFormat.Size + TcpFormat.Size + dataLen);
            ipHeader.srcAddr     = sIP;
            ipHeader.destAddr    = dIP;
            IPFormat.SetDontFragBit(ipHeader);

            // write the ip header + ip checksum
            start = IPFormat.WriteIPHeader(pktData, start, ipHeader);

            // write TCP header, no checksum
            start = TcpFormat.WriteTcpHeader(pktData, start, ref tcpHeader);

            // calc the checksum...
            TcpFormat.SetTcpChecksum(pktData, EthernetFormat.Size, ref tcpHeader);
        }