private IPPacket(HW.Network.MACAddress srcMAC, HW.Network.MACAddress destMAC, UInt16 dataLength, byte protocol, IPv4Address source, IPv4Address dest) : base(destMAC, srcMAC, 0x0800, dataLength + 14 + 20) { mRawData[14] = 0x45; mRawData[15] = 0; ipLength = (UInt16)(dataLength + 20); ipHeaderLength = 5; mRawData[16] = (byte)((ipLength >> 8) & 0xFF); mRawData[17] = (byte)((ipLength >> 0) & 0xFF); fragmentID = TCPIPStack.NextIPFragmentID(); mRawData[18] = (byte)((fragmentID >> 8) & 0xFF); mRawData[19] = (byte)((fragmentID >> 0) & 0xFF); mRawData[20] = 0x00; mRawData[21] = 0x00; mRawData[22] = 0x80; mRawData[23] = protocol; mRawData[24] = 0x00; mRawData[25] = 0x00; for (int b = 0; b < 4; b++) { mRawData[26 + b] = source.address[b]; mRawData[30 + b] = dest.address[b]; } ipCRC = CalcIPCRC(20); mRawData[24] = (byte)((ipCRC >> 8) & 0xFF); mRawData[25] = (byte)((ipCRC >> 0) & 0xFF); initFields(); }
protected override void initFields() { base.initFields(); mSenderMAC = new HW.Network.MACAddress(mRawData, 22); mSenderIP = new IPv4Address(mRawData, 28); mTargetMAC = new HW.Network.MACAddress(mRawData, 32); mTargetIP = new IPv4Address(mRawData, 38); }
/// <summary> /// Simple constructor for the IGMP header that initializes the member fields. /// </summary> public IgmpHeader() : base() { igmpVersionType = IgmpMembershipQuery; igmpMaxResponseTime = 0; igmpChecksum = 0; igmpGroupAddress = IPv4Address.Any; }
/// <summary> /// Create a new DNS A resource record. /// </summary> /// <param name="Name">The DNS name.</param> /// <param name="Class">The DNS class.</param> /// <param name="TimeToLive">The timestamp when this resource records gets invalidated.</param> /// <param name="IPv4Address">The IPv4 address of this resource record.</param> public A(String Name, DNSQueryClasses Class, TimeSpan TimeToLive, IPv4Address IPv4Address) : base(Name, TypeId, Class, TimeToLive, IPv4Address.ToString()) { this._IPv4Address = IPv4Address; }
public static HW.Network.MACAddress Resolve(IPv4Address ipAddress) { ensureCacheExists(); if (cache.ContainsKey(ipAddress.To32BitNumber()) == false) { return null; } return cache[ipAddress.To32BitNumber()]; }
internal TCPConnection(IPv4Address remoteIP, UInt16 remotePort, IPv4Address localIP, UInt16 localPort, UInt32 initialSeqNumber, State initialState) { this.remoteEndpoint = new IPv4EndPoint(remoteIP, remotePort); this.localEndpoint = new IPv4EndPoint(localIP, localPort); this.remoteSeqNumber = initialSeqNumber; this.localSeqNumber = 0x3040; this.state = initialState; // TODO: have socket be a hash key we can use to find connections quickly this.socket = remotePort; }
private byte ipVersion; // actually only 4 bits #endregion Fields #region Constructors /// <summary> /// Simple constructor that initializes the members to zero. /// </summary> public IPv4Header_old() : base() { ipVersion = 4; ipLength = (byte)Ipv4HeaderLength; // Set the property so it will convert properly ipTypeOfService = 0; ipId = 0; ipOffset = 0; ipTtl = 30; ipProtocol = 0; ipChecksum = 0; ipSourceAddress = IPv4Address.Any; ipDestinationAddress = IPv4Address.Any; }
internal ICMPEchoRequest(IPv4Address source, IPv4Address dest, UInt16 id, UInt16 sequence) : base(source, dest, 8, 0, id, sequence, 40) { for (byte b = 8; b < this.ICMP_DataLength; b++) { mRawData[this.dataOffset + b] = b; } mRawData[this.dataOffset + 2] = 0x00; mRawData[this.dataOffset + 3] = 0x00; icmpCRC = CalcICMPCRC((UInt16)(this.ICMP_DataLength + 8)); mRawData[this.dataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); mRawData[this.dataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); }
protected override void initFields() { base.initFields(); ipVersion = (byte)((mRawData[14] & 0xF0) >> 4); ipHeaderLength = (byte)(mRawData[14] & 0x0F); tos = mRawData[15]; ipLength = (UInt16)((mRawData[16] << 8) | mRawData[17]); fragmentID = (UInt16)((mRawData[18] << 8) | mRawData[19]); flags = (byte)((mRawData[20] & 0xE0) >> 5); fragmentOffset = (UInt16)(((mRawData[20] & 0x1F) << 8) | mRawData[21]); ttl = mRawData[22]; proto = mRawData[23]; ipCRC = (UInt16)((mRawData[24] << 8) | mRawData[25]); sourceIP = new IPv4Address(mRawData, 26); destIP = new IPv4Address(mRawData, 30); dataOffset = (UInt16)(14 + HeaderLength); }
internal ICMPPacket(IPv4Address source, IPv4Address dest, byte type, byte code, UInt16 id, UInt16 seq, UInt16 icmpDataSize) : base(icmpDataSize, 1, source, dest) { mRawData[this.dataOffset] = type; mRawData[this.dataOffset + 1] = code; mRawData[this.dataOffset + 2] = 0x00; mRawData[this.dataOffset + 3] = 0x00; mRawData[this.dataOffset + 4] = (byte)((id >> 8) & 0xFF); mRawData[this.dataOffset + 5] = (byte)((id >> 0) & 0xFF); mRawData[this.dataOffset + 6] = (byte)((seq >> 8) & 0xFF); mRawData[this.dataOffset + 7] = (byte)((seq >> 0) & 0xFF); icmpCRC = CalcICMPCRC((UInt16)(icmpDataSize + 8)); mRawData[this.dataOffset + 2] = (byte)((icmpCRC >> 8) & 0xFF); mRawData[this.dataOffset + 3] = (byte)((icmpCRC >> 0) & 0xFF); initFields(); }
protected ARPPacket_EthernetIPv4(UInt16 operation, HW.Network.MACAddress senderMAC, IPv4Address senderIP, HW.Network.MACAddress targetMAC, IPv4Address targetIP, int packet_size) : base(targetMAC, senderMAC, 1, 0x0800, 6, 4, operation, packet_size) { for (int i = 0; i < 6; i++) { mRawData[22 + i] = senderMAC.bytes[i]; mRawData[32 + i] = targetMAC.bytes[i]; } for (int i = 0; i < 4; i++) { mRawData[28 + i] = senderIP.address[i]; mRawData[38 + i] = targetIP.address[i]; } initFields(); }
public static void Update(IPv4Address ipAddress, HW.Network.MACAddress macAddress) { ensureCacheExists(); UInt32 ip_hash = ipAddress.To32BitNumber(); if (ip_hash == 0) { return; } if (cache.ContainsKey(ip_hash) == false) { cache.Add(ip_hash, macAddress); } else { cache[ip_hash] = macAddress; } }
internal UDPPacket(IPv4Address source, IPv4Address dest, UInt16 srcPort, UInt16 destPort, byte[] data) : base((UInt16)(data.Length+8), 17, source, dest) { mRawData[this.dataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); mRawData[this.dataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); mRawData[this.dataOffset + 2] = (byte)((destPort >> 8) & 0xFF); mRawData[this.dataOffset + 3] = (byte)((destPort >> 0) & 0xFF); udpLen = (UInt16)(data.Length + 8); mRawData[this.dataOffset + 4] = (byte)((udpLen >> 8) & 0xFF); mRawData[this.dataOffset + 5] = (byte)((udpLen >> 0) & 0xFF); mRawData[this.dataOffset + 6] = 0; mRawData[this.dataOffset + 7] = 0; for (int b = 0; b < data.Length; b++) { mRawData[this.dataOffset + 8 + b] = data[b]; } initFields(); }
internal TCPPacket(IPv4Address source, IPv4Address dest, UInt16 srcPort, UInt16 destPort, UInt32 seqNum, UInt32 ackNum, byte tcpFlags, UInt16 winSize, byte[] data, int dataLength, int optionLength) : base((UInt16)(dataLength + 20 + optionLength), 6, source, dest) { numOptions = optionLength / 4; this.optionsLength = optionLength; mRawData[this.dataOffset + 0] = (byte)((srcPort >> 8) & 0xFF); mRawData[this.dataOffset + 1] = (byte)((srcPort >> 0) & 0xFF); mRawData[this.dataOffset + 2] = (byte)((destPort >> 8) & 0xFF); mRawData[this.dataOffset + 3] = (byte)((destPort >> 0) & 0xFF); mRawData[this.dataOffset + 4] = (byte)((seqNum >> 24) & 0xFF); mRawData[this.dataOffset + 5] = (byte)((seqNum >> 16) & 0xFF); mRawData[this.dataOffset + 6] = (byte)((seqNum >> 8) & 0xFF); mRawData[this.dataOffset + 7] = (byte)((seqNum >> 0) & 0xFF); mRawData[this.dataOffset + 8] = (byte)((ackNum >> 24) & 0xFF); mRawData[this.dataOffset + 9] = (byte)((ackNum >> 16) & 0xFF); mRawData[this.dataOffset + 10] = (byte)((ackNum >> 8) & 0xFF); mRawData[this.dataOffset + 11] = (byte)((ackNum >> 0) & 0xFF); mRawData[this.dataOffset + 12] = (byte)((5 + numOptions) << 4); mRawData[this.dataOffset + 13] = tcpFlags; mRawData[this.dataOffset + 14] = (byte)((winSize >> 8) & 0xFF); mRawData[this.dataOffset + 15] = (byte)((winSize >> 0) & 0xFF); mRawData[this.dataOffset + 16] = 0x00; mRawData[this.dataOffset + 17] = 0x00; mRawData[this.dataOffset + 18] = 0x00; mRawData[this.dataOffset + 19] = 0x00; initFields(); if (data != null) { for (int b = 0; b < data.Length; b++) { mRawData[this.tcpDataOffset + b] = data[b]; } } RecalcCRC(); }
// // Parse // // Convert this IPv6 address into a sequence of 8 16-bit numbers // // Inputs: // <member> Name // The validated IPv6 address // // Outputs: // <member> m_Numbers // Array filled in with the numbers in the IPv6 groups // // <member> PrefixLength // Set to the number after the prefix separator (/) if found // // Assumes: // <Name> has been validated and contains only hex digits in groups of // 16-bit numbers, the characters ':' and '/', and a possible IPv4 // address // // Returns: // Nothing // // Throws: // Nothing // internal void Parse() { // // get the address and add a sentinel character for eof string // string address = Name + '!'; int number = 0; int index = 0; int compressorIndex = -1; bool numberIsValid = true; for (int i = 0; address[i] != '!';) { switch (address[i]) { case ':': m_Numbers[index++] = (ushort)number; number = 0; ++i; if (address[i] == ':') { compressorIndex = index; ++i; } else if ((compressorIndex < 0) && (index < 6)) { // // no point checking for IPv4 address if we don't // have a compressor or we haven't seen 6 16-bit // numbers yet // break; } // // check to see if the upcoming number is really an IPv4 // address. If it is, convert it to 2 ushort numbers // for (int j = i; (address[j] != '!') && (address[j] != ':') && (j < i + 4); ++j) { if (address[j] == '.') { // // we have an IPv4 address. Find the end of it: // we know that since we have a valid IPv6 // address, the only things that will terminate // the IPv4 address are the prefix delimiter '/' // or the end-of-string (which we conveniently // delimited with '!') // while ((address[j] != '!') && (address[j] != '/') && (address[j] != '%')) { ++j; } IPv4Address ip4addr = new IPv4Address(address.Substring(i, j - i)); number = ((int)ip4addr[0] * 256) + (int)ip4addr[1]; m_Numbers[index++] = (ushort)number; number = ((int)ip4addr[2] * 256) + (int)ip4addr[3]; m_Numbers[index++] = (ushort)number; i = j; // // set this to avoid adding another number to // the array if there's a prefix // number = 0; numberIsValid = false; break; } } break; case '%': ++i; int begin = i; while (Char.IsDigit(address[i]) || Uri.IsHexDigit(address[i])) { ++i; } if (i > begin) //we had digits { m_ScopeId = address.Substring(begin, i - begin); } break; case '/': if (numberIsValid) { m_Numbers[index++] = (ushort)number; numberIsValid = false; } // // since we have a valid IPv6 address string, the prefix // length is the last token in the string // for (++i; address[i] != '!'; ++i) { PrefixLength = PrefixLength * 10 + (address[i] - '0'); } break; default: number = number * 16 + Uri.FromHex(address[i++]); break; } } // // add number to the array if its not the prefix length or part of // an IPv4 address that's already been handled // if (numberIsValid) { m_Numbers[index++] = (ushort)number; } // // if we had a compressor sequence ("::") then we need to expand the // m_Numbers array // if (compressorIndex > 0) { int toIndex = NumberOfLabels - 1; int fromIndex = index - 1; for (int i = index - compressorIndex; i > 0; --i) { m_Numbers[toIndex--] = m_Numbers[fromIndex]; m_Numbers[fromIndex--] = 0; } } // // is the address loopback? Loopback is defined as one of: // // 0:0:0:0:0:0:0:1 // 0:0:0:0:0:0:127.0.0.1 == 0:0:0:0:0:0:7F00:0001 // 0:0:0:0:0:FFFF:127.0.0.1 == 0:0:0:0:0:FFFF:7F00:0001 // m_IsLoopback = ((m_Numbers[0] == 0) && (m_Numbers[1] == 0) && (m_Numbers[2] == 0) && (m_Numbers[3] == 0) && (m_Numbers[4] == 0)) && (((m_Numbers[5] == 0) && (m_Numbers[6] == 0) && (m_Numbers[7] == 1)) || (((m_Numbers[6] == 0x7F00) && (m_Numbers[7] == 0x0001)) && ((m_Numbers[5] == 0) || (m_Numbers[5] == 0xFFFF)))); }
internal TCPPacket(IPv4Address source, IPv4Address dest, UInt16 srcPort, UInt16 destPort, UInt32 seqNum, UInt32 ackNum, byte tcpFlags, UInt16 winSize) : this(source, dest, srcPort, destPort, seqNum, ackNum, tcpFlags, winSize, null, 0, 0) { }
// nethods // // IsValid // // Determine whether a name is a valid IPv6 address. Rules are: // // * 8 groups of 16-bit hex numbers, separated by ':' // * a *single* run of zeros can be compressed using the symbol '::' // * an optional 1 or 2 character prefix length field delimited by '/' // * the last 32 bits in an address can be represented as an IPv4 address // // Inputs: // <argument> name // Domain name field of a URI to check for pattern match with // IPv6 address // // Outputs: // Nothing // // Assumes: // Nothing // // Returns: // true if <name> has IPv6 format, else false // // Throws: // Nothing // internal static bool IsValid(string name) { int sequenceCount = 0; int sequenceLength = 0; bool haveCompressor = false; bool haveIPv4Address = false; bool havePrefix = false; bool haveScopeId = false; bool expectingNumber = true; int lastSequence = 1; for (int i = 0; i < name.Length; ++i) { if (havePrefix ? Char.IsDigit(name[i]) : Uri.IsHexDigit(name[i])) { ++sequenceLength; expectingNumber = false; } else { if (sequenceLength > 4) { return(false); } if (sequenceLength != 0) { ++sequenceCount; lastSequence = i - sequenceLength; } sequenceLength = 0; switch (name[i]) { case ':': if ((i > 0) && (name[i - 1] == ':')) { if (haveCompressor) { // // can only have one per IPv6 address // return(false); } haveCompressor = true; expectingNumber = false; } else { expectingNumber = true; } break; case '%': if ((sequenceCount == 0) || haveScopeId) { return(false); } expectingNumber = true; haveScopeId = true; break; case '/': if ((sequenceCount == 0) || havePrefix) { return(false); } havePrefix = true; expectingNumber = true; break; case '.': if (haveIPv4Address) { return(false); } int slashIndex = name.IndexOfAny(new char[] { '%', '/' }, i); int length = name.Length; if (slashIndex != -1) { length = Math.Min(slashIndex, length); } --length; if (!IPv4Address.IsValid(name, lastSequence, ref length)) { return(false); } haveIPv4Address = true; // // we have to say there is a sequence here in case // the next token is the prefix separator. This will // cause the sequenceCount to be incremented. Bit // hacky // sequenceLength = 4; i = length - 1; break; default: return(false); } } } // // if the last token was a prefix, check number of digits // if (havePrefix && ((sequenceLength < 1) || (sequenceLength > 2))) { return(false); } // // these sequence counts are -1 because it is implied in end-of-sequence // int expectedSequenceCount = 7 + ((sequenceLength == 0) ? 1 : 0) + (havePrefix ? 1 : 0) + (haveScopeId ? 1 : 0); return(!expectingNumber && (sequenceLength <= 4) && (haveCompressor ? (sequenceCount < expectedSequenceCount) : (sequenceCount == expectedSequenceCount) )); }
public static bool Contains(IPv4Address ipAddress) { ensureCacheExists(); return cache.ContainsKey(ipAddress.To32BitNumber()); }
protected IPPacket(UInt16 dataLength, byte protocol, IPv4Address source, IPv4Address dest) : this(HW.Network.MACAddress.None, HW.Network.MACAddress.None, dataLength, protocol, source, dest) { }
internal TCPPacket(IPv4Address source, IPv4Address dest, UInt16 srcPort, UInt16 destPort, UInt32 seqNum, UInt32 ackNum, byte tcpFlags, UInt16 winSize, byte[] data) : this(source, dest, srcPort, destPort, seqNum, ackNum, tcpFlags, winSize, data, data.Length, 0) { }
/// <summary> /// Parse a DNS A resource record from the given stream. /// </summary> /// <param name="Name">The DNS name.</param> /// <param name="Stream">A stream of bytes.</param> public A(String Name, Stream Stream) : base(Name, TypeId, Stream) { this._IPv4Address = new IPv4Address(Stream); }
// // Parse // // Convert this IPv6 address into a sequence of 8 16-bit numbers // // Inputs: // <member> Name // The validated IPv6 address // // Outputs: // <member> m_Numbers // Array filled in with the numbers in the IPv6 groups // // <member> PrefixLength // Set to the number after the prefix separator (/) if found // // Assumes: // <Name> has been validated and contains only hex digits in groups of // 16-bit numbers, the characters ':' and '/', and a possible IPv4 // address // // Returns: // Nothing // // Throws: // Nothing // internal void Parse() { // // get the address and add a sentinel character for eof string // string address = Name + '!'; int number = 0; int index = 0; int compressorIndex = -1; bool numberIsValid = true; for (int i = 0; address[i] != '!'; ) { switch (address[i]) { case ':': m_Numbers[index++] = (ushort)number; number = 0; ++i; if (address[i] == ':') { compressorIndex = index; ++i; } else if ((compressorIndex < 0) && (index < 6)) { // // no point checking for IPv4 address if we don't // have a compressor or we haven't seen 6 16-bit // numbers yet // break; } // // check to see if the upcoming number is really an IPv4 // address. If it is, convert it to 2 ushort numbers // for (int j = i; (address[j] != '!') && (address[j] != ':') && (j < i + 4); ++j) { if (address[j] == '.') { // // we have an IPv4 address. Find the end of it: // we know that since we have a valid IPv6 // address, the only things that will terminate // the IPv4 address are the prefix delimiter '/' // or the end-of-string (which we conveniently // delimited with '!') // while ((address[j] != '!') && (address[j] != '/')) { ++j; } IPv4Address ip4addr = new IPv4Address(address.Substring(i, j - i)); number = ((int)ip4addr[0] * 256) + (int)ip4addr[1]; m_Numbers[index++] = (ushort)number; number = ((int)ip4addr[2] * 256) + (int)ip4addr[3]; m_Numbers[index++] = (ushort)number; i = j; // // set this to avoid adding another number to // the array if there's a prefix // number = 0; numberIsValid = false; break; } } break; case '/': if (numberIsValid) { m_Numbers[index++] = (ushort)number; numberIsValid = false; } // // since we have a valid IPv6 address string, the prefix // length is the last token in the string // for (++i; address[i] != '!'; ++i) { PrefixLength = PrefixLength * 10 + (address[i] - '0'); } break; default: number = number * 16 + Uri.FromHex(address[i++]); break; } } // // add number to the array if its not the prefix length or part of // an IPv4 address that's already been handled // if (numberIsValid) { m_Numbers[index++] = (ushort)number; } // // if we had a compressor sequence ("::") then we need to expand the // m_Numbers array // if (compressorIndex > 0) { int toIndex = NumberOfLabels - 1; int fromIndex = index - 1; for (int i = index - compressorIndex; i > 0 ; --i) { m_Numbers[toIndex--] = m_Numbers[fromIndex]; m_Numbers[fromIndex--] = 0; } } // // is the address loopback? Loopback is defined as one of: // // 0:0:0:0:0:0:0:1 // 0:0:0:0:0:0:127.0.0.1 == 0:0:0:0:0:0:7F00:0001 // 0:0:0:0:0:FFFF:127.0.0.1 == 0:0:0:0:0:FFFF:7F00:0001 // m_IsLoopback = ((m_Numbers[0] == 0) && (m_Numbers[1] == 0) && (m_Numbers[2] == 0) && (m_Numbers[3] == 0) && (m_Numbers[4] == 0)) && (((m_Numbers[5] == 0) && (m_Numbers[6] == 0) && (m_Numbers[7] == 1)) || (((m_Numbers[6] == 0x7F00) && (m_Numbers[7] == 0x0001)) && ((m_Numbers[5] == 0) || (m_Numbers[5] == 0xFFFF)))); }
/// <summary> /// Parse a DNS A resource record from the given stream. /// </summary> /// <param name="Stream">A stream of bytes.</param> public A(Stream Stream) : base(Stream, TypeId) { this._IPv4Address = new IPv4Address(Stream); }