/**
* <summary>If we're not creating a packet from scratch, this will keep its
* integrity and transform UDP and TCP headers as well (due to their checksums
* being dependent on source and destination ip addresses.</summary>
* <param name="Packet">The packet to translate.</param>
* <param name="SourceIP">The new source ip.</param>
* <param name="DestinationIP">The new destination ip.</param>
*/
public static MemBlock Translate(MemBlock Packet, MemBlock SourceIP,
MemBlock DestinationIP)
{
byte[] new_packet = new byte[Packet.Length];
Packet.CopyTo(new_packet, 0);
int length = (Packet[0] & 0xF) * 4;
SourceIP.CopyTo(new_packet, 12);
// Do not copy over multicast addresses!
if (new_packet[16] < 224 || new_packet[16] > 239)
{
DestinationIP.CopyTo(new_packet, 16);
}
// Zero out the checksum so we don't use it in our future calculations
new_packet[10] = 0;
new_packet[11] = 0;
MemBlock header = MemBlock.Reference(new_packet, 0, length);
int checksum = GenerateChecksum(header);
new_packet[10] = (byte)((checksum >> 8) & 0xFF);
new_packet[11] = (byte)(checksum & 0xFF);
Protocols p = (Protocols)Packet[9];
bool fragment = ((Packet[6] & 0x1F) | Packet[7]) != 0;
if (p == Protocols.Udp && !fragment)
{
// Zero out the checksum to disable it
new_packet[length + 6] = 0;
new_packet[length + 7] = 0;
}
else if (p == Protocols.Tcp && !fragment)
{
// Zero out the checksum so we don't use it in our future calculations
new_packet[length + 16] = 0;
new_packet[length + 17] = 0;
MemBlock payload = MemBlock.Reference(new_packet).Slice(length);
MemBlock pseudoheader = IPPacket.MakePseudoHeader(SourceIP,
DestinationIP, (byte)Protocols.Tcp, (ushort)(Packet.Length - 20));
checksum = IPPacket.GenerateChecksum(payload, pseudoheader);
new_packet[length + 16] = (byte)((checksum >> 8) & 0xFF);
new_packet[length + 17] = (byte)(checksum & 0xFF);
}
return(MemBlock.Reference(new_packet));
}