mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
130 lines
5.1 KiB
C#
130 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Cosmos.Sys.Network
|
|
{
|
|
// http://en.wikipedia.org/wiki/IPv4
|
|
public abstract class IP4Packet : Packet {
|
|
protected byte mHeaderSize = 20;
|
|
protected int mHeaderBegin;
|
|
|
|
/// <summary>
|
|
/// Initialized the IPv4 packet.
|
|
/// </summary>
|
|
/// <param name="aData"></param>
|
|
/// <param name="aHeaderSize"></param>
|
|
/// <param name="aProtocol"></param>
|
|
/// <param name="aSrcAddr"></param>
|
|
/// <param name="aDestAddr"></param>
|
|
/// <returns></returns>
|
|
protected int Initialize(byte[] aData, int aHeaderSize, byte aProtocol, uint aSrcAddr, uint aDestAddr) {
|
|
mHeaderBegin = base.Initialize(aData, mHeaderSize + aHeaderSize);
|
|
// Version + Header length
|
|
// 0x40 is the version (4 in high nibble, i.e. 4x)
|
|
// Length is # of 32 bit words in header
|
|
mData[mHeaderBegin] = (byte)(0x40 | (mHeaderSize >> 2));
|
|
// Differentiated Services Field
|
|
mData[mHeaderBegin + 1] = 0x00;
|
|
// Total Length - IP Packet + sub packets + data (i.e. IP + UDP + UPD Data)
|
|
int xSize = mData.Length - mHeaderBegin;
|
|
mData[mHeaderBegin + 2] = (byte)(xSize >> 8);
|
|
mData[mHeaderBegin + 3] = (byte)xSize;
|
|
// IP - Identification - Varies
|
|
// This field is an identification field and is primarily used for uniquely identifying fragments of an original IP datagram. Some experimental work has suggested using the ID field for other purposes, such as for adding packet-tracing information to datagrams in order to help trace back datagrams with spoofed source addresses.
|
|
mData[mHeaderBegin + 4] = 0x5a;
|
|
mData[mHeaderBegin + 5] = 0xf8;
|
|
// Flags + Fragment Offset
|
|
mData[mHeaderBegin + 6] = 0x00;
|
|
mData[mHeaderBegin + 7] = 0x00;
|
|
// TTL
|
|
mData[mHeaderBegin + 8] = 0x80;
|
|
Protocol = aProtocol;
|
|
// IP - Header Checksum - Varies
|
|
// In 1's complement, there are 2 representations for zero: 0000000000000000 and 1111111111111111.
|
|
// Note that flipping the bits of the one gives you the other. A header checksum of "0"
|
|
// (allowed for some protocols, e.g. UDP) denotes that the checksum was not calculated.
|
|
// Thus, implementations which do calculate a checksum make sure to give a result of 0xffff rather
|
|
// that 0, when the checksum is actually zero.
|
|
mData[mHeaderBegin + 10] = 0x00;
|
|
mData[mHeaderBegin + 11] = 0x00;
|
|
SourceAddress = aSrcAddr;
|
|
DestinationAddress = aDestAddr;
|
|
|
|
return mHeaderBegin + mHeaderSize;
|
|
}
|
|
|
|
public byte Protocol {
|
|
get {
|
|
return mData[mHeaderBegin + 9];
|
|
}
|
|
set {
|
|
mData[mHeaderBegin + 9] = value;
|
|
}
|
|
}
|
|
|
|
public uint SourceAddress {
|
|
get {
|
|
return (uint)(
|
|
mData[mHeaderBegin + 12] << 24
|
|
| mData[mHeaderBegin + 13] << 16
|
|
| mData[mHeaderBegin + 14] << 8
|
|
| mData[mHeaderBegin + 15]);
|
|
}
|
|
set {
|
|
mData[mHeaderBegin + 12] = (byte)(value >> 24);
|
|
mData[mHeaderBegin + 13] = (byte)(value >> 16);
|
|
mData[mHeaderBegin + 14] = (byte)(value >> 8);
|
|
mData[mHeaderBegin + 15] = (byte)value;
|
|
}
|
|
}
|
|
|
|
public uint DestinationAddress {
|
|
get {
|
|
return (uint)(
|
|
mData[mHeaderBegin + 16] << 24
|
|
| mData[mHeaderBegin + 17] << 16
|
|
| mData[mHeaderBegin + 18] << 8
|
|
| mData[mHeaderBegin + 19]);
|
|
}
|
|
set {
|
|
mData[mHeaderBegin + 16] = (byte)(value >> 24);
|
|
mData[mHeaderBegin + 17] = (byte)(value >> 16);
|
|
mData[mHeaderBegin + 18] = (byte)(value >> 8);
|
|
mData[mHeaderBegin + 19] = (byte)value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Concludes the IP4Packet by setting checksum, etc.
|
|
/// </summary>
|
|
protected override void Conclude() {
|
|
base.Conclude();
|
|
this.SetChecksum();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates and saves the checksum for the IPv4 packet.
|
|
/// </summary>
|
|
private void SetChecksum()
|
|
{
|
|
//Blank out checksum bytes
|
|
mData[mHeaderBegin + 10] = 0;
|
|
mData[mHeaderBegin + 11] = 0;
|
|
|
|
// TODO: Change this to a ASM and use 32 bit addition
|
|
UInt32 xResult = 0;
|
|
for (int i = 0; i < mHeaderSize; i = i + 2)
|
|
{
|
|
xResult += (UInt16)((mData[mHeaderBegin + i] << 8) + mData[mHeaderBegin + i + 1]);
|
|
}
|
|
xResult = (~((xResult & 0xFFFF) + (xResult >> 16)));
|
|
// Store result
|
|
mData[mHeaderBegin + 10] = (byte)(xResult >> 8);
|
|
mData[mHeaderBegin + 11] = (byte)xResult;
|
|
}
|
|
|
|
|
|
}
|
|
}
|