/// <summary> /// Computes the 16-bit checksum of the specified ICMP packet. /// </summary> /// <param name="packet">The packet to compute the checksum for.</param> /// <param name="withChecksumField">true to include the packet's /// checksum field in the calculation; otherwise false.</param> /// <returns>The checksum of the specified ICMP packet.</returns> /// <exception cref="ArgumentNullException">Thrown if the packet /// argument is null.</exception> public static ushort ComputeChecksum(IcmpPacket packet, bool withChecksumField = false) { packet.ThrowIfNull("packet"); var bytes = new ByteBuilder() .Append((byte) packet.Type) .Append((byte) packet.Code) .Append(withChecksumField ? packet.Checksum : (ushort) 0) .Append(packet.Data) .ToArray(); var sum = 0; // Treat the header bytes as a sequence of unsigned 16-bit values and // sum them up. for (var n = 0; n < bytes.Length; n += 2) sum += BitConverter.ToUInt16(bytes, n); // Use carries to compute the 1's complement sum. sum = (sum >> 16) + (sum & 0xFFFF); // Return the inverted 16-bit result. return (ushort) (~sum); }
/// <summary> /// Computes the 16-bit checksum of the specified IPv4 packet. /// </summary> /// <param name="packet">The packet to compute the checksum for.</param> /// <param name="withChecksumField">true to include the packet's /// checksum field in the calculation; otherwise false.</param> /// <returns>The checksum of the specified IPv4 packet.</returns> /// <exception cref="ArgumentNullException">Thrown if the packet /// argument is null.</exception> public static ushort ComputeChecksum(IpPacket packet, bool withChecksumField = false) { packet.ThrowIfNull("packet"); // The version and IHL fields are 4 bit wide each. var vi = (byte) (((packet.Ihl & 0x0F) << 4) | (((int) packet.Version) & 0x0F)); // The flags field is 3 bits and the fragment offset 13 bits wide. var ffo = (ushort) (((packet.FragmentOffset & 0x1FFF) << 3) | ((int) packet.Flags & 0x07)); var bytes = new ByteBuilder() .Append(vi) .Append(packet.Dscp) .Append(packet.TotalLength) .Append(packet.Identification) .Append(ffo) .Append(packet.TimeToLive) .Append((byte) packet.Protocol) .Append(withChecksumField ? packet.Checksum : (ushort)0) .Append(packet.Source.Bytes) .Append(packet.Destination.Bytes) .ToArray(); var sum = 0; // Treat the header bytes as a sequence of unsigned 16-bit values and // sum them up. for (var n = 0; n < bytes.Length; n += 2) sum += BitConverter.ToUInt16(bytes, n); // Use carries to compute the 1's complement sum. sum = (sum >> 16) + (sum & 0xFFFF); // Return the inverted 16-bit result. return (ushort)(~ sum); }