public static IpV4Options NextIpV4Options(this Random random) { int optionsLength = random.Next(IpV4Options.MaximumBytesLength) / 4 * 4; List <IpV4Option> options = new List <IpV4Option>(); while (optionsLength > 0) { IpV4Option option = random.NextIpV4Option(optionsLength); if (option.IsAppearsAtMostOnce && options.FindIndex(option.Equivalent) != -1) { continue; } options.Add(option); optionsLength -= option.Length; if (option.OptionType == IpV4OptionType.EndOfOptionList) { break; } } return(new IpV4Options(options)); }
/// <summary> /// Serlialize this routing option into something which /// can be passed to an IpV4Packet class. /// </summary> /// <returns> /// An IpV4Option class which can be passed to an IpV4Packet. /// </returns> public IpV4Option Serialize() { IpV4Option newOption = new IpV4Option(); // fill in basic fields newOption.Class = IpV4OptionClass.DebuggingAndMeasurement; newOption.OptionType = IpV4OptionNumber.InternetTimestamp; newOption.IsCopied = false; newOption.Length = (m_timestamps.Length * (m_type == IpV4TimestampType.TimestampAndAddress ? 8 : 4)) + 4; newOption.Data = new byte[newOption.Length - 2]; // first copy in the pointer newOption.Data[0] = (byte)m_pointer; // then the overflow and type newOption.Data[1] = (byte)(m_overflow << 4); newOption.Data[1] |= (byte)m_type; // loop through each field and add that for (int i = 0; i < m_timestamps.Length; i++) { if (m_type == IpV4TimestampType.TimestampAndAddress) { Array.Copy(m_addressstamps[i].GetAddressBytes(), 0, newOption.Data, (i * 8) + 2, 4); Array.Copy(BitConverter.GetBytes(m_timestamps[i]), 0, newOption.Data, (i * 8) + 6, 4); } else { Array.Copy(BitConverter.GetBytes(m_timestamps[i]), 0, newOption.Data, (i * 4) + 2, 4); } } return(newOption); }
/// <summary> /// Serlialize this routing option into something which /// can be passed to an IpV4Packet class. /// </summary> /// <param name="optionType"> /// There are 3 types of routing option: loose source, strict source and record. /// </param> /// <returns> /// An IpV4Option class which can be passed to an IpV4Packet. /// </returns> /// <exception cref="ArgumentException"> /// The option type is not a routing option. /// </exception> public IpV4Option Serialize(IpV4OptionNumber optionType) { IpV4Option newOption = new IpV4Option(); if (optionType != IpV4OptionNumber.LooseSourceRouting && optionType != IpV4OptionNumber.StrictSourceRouting && optionType != IpV4OptionNumber.RecordRoute) { throw new ArgumentException("The option type must be a routing option (strict source routing, loose source routing or record route", "option"); } // fill in basic fields newOption.Class = IpV4OptionClass.Control; newOption.OptionType = optionType; newOption.IsCopied = true; newOption.Length = (m_routeData.Length * 4) + 3; newOption.Data = new byte[(m_routeData.Length * 4) + 1]; // fill in the pointer newOption.Data [0] = (byte)m_pointer; // fill in the route data for (int i = 0; i < m_routeData.Length; i++) { Array.Copy(m_routeData[i].GetAddressBytes(), 0, newOption.Data, (i * 4) + 1, 4); } return(newOption); }
/// <summary> /// Create a new routing option. /// </summary> /// <param name="option"> /// The option to parse. /// </param> /// <exception cref="ArgumentNullException"> /// The option argument is null. /// </exception> /// <exception cref="ArgumentException"> /// The option argument is not a routing option. /// </exception> public IpV4RoutingOption(IpV4Option option) { if (option == null) { throw new ArgumentNullException("option"); } if (option.OptionType != IpV4OptionNumber.LooseSourceRouting && option.OptionType != IpV4OptionNumber.StrictSourceRouting && option.OptionType != IpV4OptionNumber.RecordRoute) { throw new ArgumentException("The option passed was not compatible with this class. This class accepts routing options only", "option"); } // read the pointer m_pointer = (byte)option.Data[0]; // get the number of addresses in the route // and allocate enough space int routeSize = (option.Length - 3) / 4; m_routeData = new IPAddress[routeSize]; // extract each address from the data for (int i = 0; i < m_routeData.Length; i++) { uint address = BitConverter.ToUInt32(option.Data, i * 4 + 1); m_routeData[i] = new IPAddress((long)address); } }
/// <summary> /// Serlialize this routing option into something which /// can be passed to an IpV4Packet class. /// </summary> /// <returns> /// An IpV4Option class which can be passed to an IpV4Packet. /// </returns> public IpV4Option Serialize() { IpV4Option newOption = new IpV4Option(); // fill in basic fields newOption.Class = IpV4OptionClass.Control; newOption.OptionType = IpV4OptionNumber.Security; newOption.IsCopied = true; newOption.Length = 11; newOption.Data = new byte[9]; // fill in the security bytes newOption.Data[0] = (byte)((int)m_level & 0x00ff); newOption.Data[1] = (byte)(((int)m_level & 0xff00) >> 8); // fill in the compartment bytes newOption.Data[2] = (byte)(m_compartment & 0x00ff); newOption.Data[3] = (byte)((m_compartment & 0xff00) >> 8); // fill in the handling bytes newOption.Data[4] = (byte)(m_handling & 0x00ff); newOption.Data[5] = (byte)((m_handling & 0xff00) >> 8); // fill in the transmission control code bytes newOption.Data[6] = (byte)((m_tcc & 0xff0000) >> 16); newOption.Data[7] = (byte)((m_tcc & 0x00ff00) >> 8); newOption.Data[8] = (byte)(m_tcc & 0x0000ff); return(newOption); }
/// <summary> /// Create a new security option. /// </summary> /// <param name="option"> /// The option to parse. /// </param> /// <exception cref="ArgumentNullException"> /// The option argument is null. /// </exception> /// <exception cref="ArgumentException"> /// The option argument is not a security option. /// </exception> public IpV4SecurityOption(IpV4Option option) { if (option == null) { throw new ArgumentNullException("option"); } if (option.OptionType != IpV4OptionNumber.Security) { throw new ArgumentException("The option passed was not compatible with this class. This class accepts security options only", "option"); } // extract the security level field m_level = (IpV4SecurityLevelType)BitConverter.ToUInt16(option.Data, 0); // extract the compartment field m_compartment = BitConverter.ToUInt16(option.Data, 2); // extract the handling restrictions field m_handling = BitConverter.ToUInt16(option.Data, 4); // extract the 24 bits of the transmission control code m_tcc = (uint)(option.Data[6] << 0x10); m_tcc |= (uint)(option.Data[7] << 0x08); m_tcc |= option.Data[8]; }
/// <summary> /// Create a new stream identifier option. /// </summary> /// <param name="option"> /// The option to parse. /// </param> public IpV4StreamIdentifierOption(IpV4Option option) { if (option == null) { throw new ArgumentNullException("option"); } if (option.OptionType != IpV4OptionNumber.StreamId) { throw new ArgumentException("The option passed was not compatible with this class. This class accepts stream id options only", "option"); } // extract the stream id m_id = BitConverter.ToUInt16(option.Data, 0); }
/// <summary> /// Create a new time stamp option. /// </summary> /// <param name="option"> /// The option to parse. /// </param> /// <exception cref="ArgumentNullException"> /// The option argument is null. /// </exception> /// <exception cref="ArgumentException"> /// The option argument is not a timestamp option. /// </exception> public IpV4TimeStampOption(IpV4Option option) { if (option == null) { throw new ArgumentNullException("option"); } if (option.OptionType != IpV4OptionNumber.InternetTimestamp) { throw new ArgumentException("The option passed was not compatible with this class. This class accepts timestamp options only", "option"); } // extract the pointer m_pointer = (byte)option.Data[0]; // extract the overflow field m_overflow = (byte)((option.Data[1] & 0xf0) >> 4); // extract the type m_type = (IpV4TimestampType)(option.Data[1] & 0xf); // calculate how many fields there are and allocate space int numberStamps = (option.Data.Length - 2) / 4; if (m_type == IpV4TimestampType.TimestampAndAddress) { numberStamps /= 2; m_addressstamps = new IPAddress[numberStamps]; } m_timestamps = new uint[numberStamps]; // extract the time stamps and addresses for (int i = 0; i < numberStamps; i++) { if (m_type == IpV4TimestampType.TimestampAndAddress) { uint address = BitConverter.ToUInt32(option.Data, (i * 8) + 2); m_addressstamps[i] = new IPAddress((long)address); m_timestamps[i] = BitConverter.ToUInt32(option.Data, (i * 8) + 6); } else { m_timestamps[i] = BitConverter.ToUInt32(option.Data, (i * 4) + 2); } } }
/// <summary> /// Serlialize this routing option into something which /// can be passed to an IpV4Packet class. /// </summary> /// <returns> /// An IpV4Option class which can be passed to an IpV4Packet. /// </returns> public IpV4Option Serialize() { IpV4Option newOption = new IpV4Option(); // fill in basic fields newOption.Class = IpV4OptionClass.Control; newOption.OptionType = IpV4OptionNumber.StreamId; newOption.IsCopied = true; newOption.Length = 4; newOption.Data = new byte[2]; // copy in the stream id newOption.Data = BitConverter.GetBytes(m_id); return(newOption); }
private static bool HandleCommonOptionSubfield(XElement subfield, IpV4Option option) { switch (subfield.Name()) { case "ip.opt.type": subfield.AssertShowDecimal((byte)option.OptionType); return(true); case "ip.opt.len": subfield.AssertShowDecimal(option.Length); subfield.AssertNoFields(); return(true); default: return(false); } }
private static void CompareIpV4Options(XElement element, IpV4Options options) { int currentOptionIndex = 0; foreach (var field in element.Fields()) { if (currentOptionIndex >= options.Count) { Assert.IsFalse(options.IsValid); Assert.IsTrue(field.Show() == "Commercial IP security option" || field.Show() == "Loose source route (length byte past end of options)" || field.Show() == "Time stamp:" || field.Show().StartsWith("Unknown") || field.Show().StartsWith("Security") || field.Show().StartsWith("Router Alert (with option length = ") || field.Show().StartsWith("Stream identifier (with option length = ") || field.Show().Contains("with too") || field.Show().Contains(" bytes says option goes past end of options") || field.Show().Contains("(length byte past end of options)") || XElementExtensions.Show(field.Fields().First()).StartsWith("Pointer: ") && XElementExtensions.Show(field.Fields().First()).EndsWith(" (points to middle of address)") || field.Fields().Where(value => value.Show() == "(suboption would go past end of option)").Count() != 0, field.Show()); break; } IpV4Option option = options[currentOptionIndex++]; if (option.OptionType == IpV4OptionType.BasicSecurity || option.OptionType == IpV4OptionType.TraceRoute) { Assert.IsTrue(field.Show().StartsWith(option.GetWiresharkString())); continue; // Wireshark doesn't support } field.AssertShow(option.GetWiresharkString()); if ((option is IpV4OptionUnknown)) { continue; } var optionShows = from f in field.Fields() select f.Show(); MoreAssert.AreSequenceEqual(optionShows, option.GetWiresharkSubfieldStrings()); } }
private static void CompareIpV4Options(XElement element, IpV4Datagram ipV4Datagram, IpV4Options options) { int currentOptionIndex = 0; foreach (var field in element.Fields()) { if (currentOptionIndex >= options.Count) { Assert.IsFalse(options.IsValid); Assert.IsTrue(field.Show() == "Commercial IP security option" || field.Show() == "Loose source route (length byte past end of options)" || field.Show() == "Time stamp:" || field.Show().StartsWith("Unknown") || field.Show().StartsWith("Security") || field.Show().StartsWith("Router Alert (with option length = ") || field.Show().StartsWith("Stream ID (with option length = ") || field.Show().Contains("with too") || field.Show().Contains(" bytes says option goes past end of options") || field.Show().Contains("(length byte past end of options)") || XElementExtensions.Show(field.Fields().First()).StartsWith("Pointer: ") && XElementExtensions.Show(field.Fields().First()).EndsWith(" (points to middle of address)") || field.Fields().Where(value => value.Show() == "(suboption would go past end of option)").Count() != 0, field.Show()); break; } IpV4Option option = options[currentOptionIndex++]; switch (option.OptionType) { case IpV4OptionType.NoOperation: case IpV4OptionType.EndOfOptionList: field.AssertShow(option.OptionType == IpV4OptionType.EndOfOptionList ? "End of Options List (EOL)" : "No Operation (NOP)"); foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.BasicSecurity: field.AssertShow("Security (" + option.Length + " bytes)"); var basicSecurity = (IpV4OptionBasicSecurity)option; int basicSecurityFlagsIndex = 0; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.sec_cl": subfield.AssertNoFields(); subfield.AssertShowDecimal((byte)basicSecurity.ClassificationLevel); break; case "ip.opt.sec_prot_auth_flags": foreach (XElement flagField in subfield.Fields()) { flagField.AssertNoFields(); switch (flagField.Name()) { case "ip.opt.sec_prot_auth_genser": flagField.AssertShowDecimal((basicSecurity.ProtectionAuthorities & IpV4OptionSecurityProtectionAuthorities.Genser) == IpV4OptionSecurityProtectionAuthorities.Genser); break; case "ip.opt.sec_prot_auth_siop_esi": flagField.AssertShowDecimal((basicSecurity.ProtectionAuthorities & IpV4OptionSecurityProtectionAuthorities. SingleIntegrationOptionalPlanExtremelySensitiveInformation) == IpV4OptionSecurityProtectionAuthorities. SingleIntegrationOptionalPlanExtremelySensitiveInformation); break; case "ip.opt.sec_prot_auth_sci": flagField.AssertShowDecimal((basicSecurity.ProtectionAuthorities & IpV4OptionSecurityProtectionAuthorities.SensitiveCompartmentedInformation) == IpV4OptionSecurityProtectionAuthorities.SensitiveCompartmentedInformation); break; case "ip.opt.sec_prot_auth_nsa": flagField.AssertShowDecimal((basicSecurity.ProtectionAuthorities & IpV4OptionSecurityProtectionAuthorities.Nsa) == IpV4OptionSecurityProtectionAuthorities.Nsa); break; case "ip.opt.sec_prot_auth_doe": flagField.AssertShowDecimal((basicSecurity.ProtectionAuthorities & IpV4OptionSecurityProtectionAuthorities.DepartmentOfEnergy) == IpV4OptionSecurityProtectionAuthorities.DepartmentOfEnergy); break; case "ip.opt.sec_prot_auth_unassigned": flagField.AssertShowDecimal(0); break; case "ip.opt.sec_prot_auth_fti": flagField.AssertShowDecimal(basicSecurity.Length - basicSecurityFlagsIndex > 4); break; default: throw new InvalidOperationException("Invalid flag field " + flagField.Name()); } } ++basicSecurityFlagsIndex; break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.StreamIdentifier: field.AssertShow("Stream ID (" + option.Length + " bytes): " + ((IpV4OptionStreamIdentifier)option).Identifier); var streamIdentifier = (IpV4OptionStreamIdentifier)option; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.sid": subfield.AssertNoFields(); subfield.AssertShowDecimal(streamIdentifier.Identifier); break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.LooseSourceRouting: field.AssertShow("Loose Source Route (" + option.Length + " bytes)"); var looseSourceRouting = (IpV4OptionLooseSourceRouting)option; int looseRouteIndex = 0; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.ptr": subfield.AssertShowDecimal(IpV4Address.SizeOf * (looseSourceRouting.PointedAddressIndex + 1)); subfield.AssertNoFields(); break; case "ip.rec_rt": case "ip.dst": case "ip.addr": case "ip.dst_host": case "ip.src_rt": subfield.AssertShow(looseSourceRouting.Route[looseRouteIndex].ToString()); subfield.AssertNoFields(); break; case "ip.rec_rt_host": case "ip.host": case "ip.src_rt_host": subfield.AssertShow(looseSourceRouting.Route[looseRouteIndex].ToString()); subfield.AssertNoFields(); ++looseRouteIndex; break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.RecordRoute: field.AssertShow("Record Route (" + option.Length + " bytes)"); var recordRoute = (IpV4OptionRecordRoute)option; int recordRouteIndex = 0; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.ptr": subfield.AssertShowDecimal(IpV4Address.SizeOf * (recordRoute.PointedAddressIndex + 1)); subfield.AssertNoFields(); break; case "ip.rec_rt": case "ip.empty_rt": subfield.AssertShow(recordRoute.Route[recordRouteIndex].ToString()); subfield.AssertNoFields(); break; case "ip.rec_rt_host": case "ip.empty_rt_host": subfield.AssertShow(recordRoute.Route[recordRouteIndex].ToString()); subfield.AssertNoFields(); ++recordRouteIndex; break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.StrictSourceRouting: field.AssertShow("Strict Source Route (" + option.Length + " bytes)"); var strictSourceRouting = (IpV4OptionStrictSourceRouting)option; int strictSourceRoutingIndex = 0; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.ptr": subfield.AssertShowDecimal(IpV4Address.SizeOf * (strictSourceRouting.PointedAddressIndex + 1)); subfield.AssertNoFields(); break; case "ip.dst": case "ip.addr": case "ip.dst_host": case "ip.rec_rt": case "ip.src_rt": subfield.AssertShow(strictSourceRouting.Route[strictSourceRoutingIndex].ToString()); subfield.AssertNoFields(); break; case "ip.host": case "ip.rec_rt_host": case "ip.src_rt_host": subfield.AssertShow(strictSourceRouting.Route[strictSourceRoutingIndex].ToString()); subfield.AssertNoFields(); ++strictSourceRoutingIndex; break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.RouterAlert: var routerAlert = (IpV4OptionRouterAlert)option; field.AssertShow("Router Alert (" + option.Length + " bytes): " + ((routerAlert.Value != 0) ? "Reserved (" + routerAlert.Value + ")" : "Router shall examine packet (0)")); foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } switch (subfield.Name()) { case "ip.opt.ra": subfield.AssertNoFields(); subfield.AssertShowDecimal(routerAlert.Value); break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.TraceRoute: field.AssertShow("Traceroute (" + option.Length + " bytes)"); var traceRoute = (IpV4OptionTraceRoute)option; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } subfield.AssertNoFields(); switch (subfield.Name()) { case "ip.opt.id_number": subfield.AssertShowDecimal(traceRoute.Identification); break; case "ip.opt.ohc": subfield.AssertShowDecimal(traceRoute.OutboundHopCount); break; case "ip.opt.rhc": subfield.AssertShowDecimal(traceRoute.ReturnHopCount); break; case "ip.opt.originator": subfield.AssertShow(traceRoute.OriginatorIpAddress.ToString()); break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.InternetTimestamp: field.AssertShow("Time Stamp (" + option.Length + " bytes)"); var timestamp = (IpV4OptionTimestamp)option; int timestampIndex = 0; foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } subfield.AssertNoFields(); switch (subfield.Name()) { case "": var subfieldParts = subfield.Show().Split(new[] { ':', '=', ',' }, StringSplitOptions.RemoveEmptyEntries); string subfieldValue = subfieldParts[1].Trim(); switch (subfieldParts[0].Trim()) { case "Pointer": Assert.AreEqual(timestamp.PointedIndex, int.Parse(subfieldValue) / 4 - 1); break; case "Overflow": Assert.AreEqual(timestamp.Overflow.ToString(), subfieldValue); break; case "Flag": switch (timestamp.TimestampType) { case IpV4OptionTimestampType.AddressAndTimestamp: Assert.AreEqual("Time stamp and address", subfieldValue); break; case IpV4OptionTimestampType.TimestampOnly: Assert.AreEqual("Time stamps only", subfieldValue); break; case IpV4OptionTimestampType.AddressPrespecified: Assert.AreEqual("Time stamps for prespecified addresses", subfieldValue); break; default: throw new InvalidOperationException("Invalid timestamp type: " + timestamp.TimestampType); } break; case "Time stamp": var timestampOnly = (IpV4OptionTimestampOnly)timestamp; Assert.AreEqual(timestampOnly.Timestamps[timestampIndex].MillisecondsSinceMidnightUniversalTime, uint.Parse(subfieldValue)); ++timestampIndex; break; case "Address": Assert.AreEqual(4, subfieldParts.Length); var timestampAndAddress = (IpV4OptionTimestampAndAddress)timestamp; Assert.AreEqual(timestampAndAddress.TimedRoute[timestampIndex].Address.ToString(), subfieldParts[1].Trim()); Assert.AreEqual("time stamp", subfieldParts[2].Trim()); Assert.AreEqual(timestampAndAddress.TimedRoute[timestampIndex].TimeOfDay.MillisecondsSinceMidnightUniversalTime, uint.Parse(subfieldParts[3])); ++timestampIndex; break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Show()); } break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.QuickStart: IpV4OptionQuickStart quickStart = (IpV4OptionQuickStart)option; StringBuilder quickStartWireshark = new StringBuilder("Quick-Start (" + option.Length + " bytes): "); quickStartWireshark.Append(quickStart.QuickStartFunction == IpV4OptionQuickStartFunction.RateRequest ? "Rate request" : "Rate report"); quickStartWireshark.Append(" (" + (byte)quickStart.QuickStartFunction + ")"); quickStartWireshark.Append(", "); if (quickStart.RateKbps == 0) { quickStartWireshark.Append("0 bit/s"); } else if (quickStart.RateKbps < 1024) { quickStartWireshark.Append(quickStart.RateKbps + " Kbit/s"); } else if (quickStart.RateKbps < 1024 * 1024) { quickStartWireshark.Append(((double)quickStart.RateKbps / 1000).ToString(CultureInfo.InvariantCulture) + " Mbit/s"); } else { quickStartWireshark.Append(((double)quickStart.RateKbps / 1000000).ToString(CultureInfo.InvariantCulture) + " Gbit/s"); } if (quickStart.QuickStartFunction == IpV4OptionQuickStartFunction.RateRequest) { quickStartWireshark.Append(", QS TTL " + quickStart.Ttl + ", QS TTL diff " + (256 + ipV4Datagram.Ttl - quickStart.Ttl) % 256); } field.AssertShow(quickStartWireshark.ToString()); foreach (var subfield in field.Fields()) { if (HandleCommonOptionSubfield(subfield, option)) { continue; } subfield.AssertNoFields(); switch (subfield.Name()) { case "ip.opt.qs_func": subfield.AssertShowDecimal((byte)quickStart.QuickStartFunction); break; case "ip.opt.qs_rate": subfield.AssertShowDecimal(quickStart.Rate); break; case "ip.opt.qs_ttl": case "ip.opt.qs_unused": subfield.AssertShowDecimal(quickStart.Ttl); break; case "ip.opt.qs_ttl_diff": subfield.AssertShowDecimal((256 + ipV4Datagram.Ttl - quickStart.Ttl) % 256); break; case "ip.opt.qs_nonce": subfield.AssertShowDecimal(quickStart.Nonce); break; case "ip.opt.qs_reserved": subfield.AssertShowDecimal(0); break; default: throw new InvalidOperationException("Invalid subfield " + subfield.Name()); } } break; case IpV4OptionType.MaximumTransmissionUnitProbe: // TODO: Support MTU Proble. Assert.IsTrue(field.Show().StartsWith("MTU Probe (" + option.Length + " bytes): ")); break; case (IpV4OptionType)12: // TODO: Support 12. if (option.Length != 4) { field.AssertShow("MTU Reply (with option length = " + option.Length + " bytes; should be 4)"); } else { Assert.IsTrue(field.Show().StartsWith("MTU Reply (4 bytes): ")); } break; case (IpV4OptionType)133: // TODO: Support 133. if (option.Length >= 3) { field.AssertShow("Extended Security (" + option.Length + " bytes)"); } else { field.AssertShow("Extended Security (with option length = " + option.Length + " bytes; should be >= 3)"); } break; case (IpV4OptionType)134: // TODO: Support 134. field.AssertShow("Commercial Security " + (option.Length >= 10 ? "(" + option.Length + " bytes)" : "(with option length = " + option.Length + " bytes; should be >= 10)")); break; case (IpV4OptionType)149: // TODO: Support 149. if (option.Length >= 6) { field.AssertShow("Selective Directed Broadcast (" + option.Length + " bytes)"); } else { field.AssertShow("Selective Directed Broadcast (with option length = " + option.Length + " bytes; should be >= 6)"); } break; default: field.AssertShow("Unknown (0x" + ((byte)option.OptionType).ToString("x2") + ") (" + option.Length + " bytes)"); field.AssertNoFields(); break; } } }
private static bool HandleCommonOptionSubfield(XElement subfield, IpV4Option option) { switch (subfield.Name()) { case "ip.opt.type": subfield.AssertShowDecimal((byte)option.OptionType); return true; case "ip.opt.len": subfield.AssertShowDecimal(option.Length); subfield.AssertNoFields(); return true; default: return false; } }
public void RandomIpV4Test() { MacAddress ethernetSource = new MacAddress("00:01:02:03:04:05"); MacAddress ethernetDestination = new MacAddress("A0:A1:A2:A3:A4:A5"); const EthernetType EthernetType = EthernetType.IpV4; EthernetLayer ethernetLayer = new EthernetLayer { Source = ethernetSource, Destination = ethernetDestination, EtherType = EthernetType }; int seed = new Random().Next(); Console.WriteLine(seed); Random random = new Random(seed); for (int i = 0; i != 1000; ++i) { IpV4Layer ipV4Layer = random.NextIpV4Layer(); ipV4Layer.HeaderChecksum = null; PayloadLayer payloadLayer = random.NextPayloadLayer(random.NextInt(0, 50 * 1024)); Packet packet = PacketBuilder.Build(DateTime.Now, ethernetLayer, ipV4Layer, payloadLayer); Assert.IsTrue(ipV4Layer.Protocol == IpV4Protocol.Ip || ipV4Layer.Protocol == IpV4Protocol.IpV6 || ipV4Layer.Protocol == IpV4Protocol.Udp || ipV4Layer.Protocol == IpV4Protocol.Tcp || ipV4Layer.Protocol == IpV4Protocol.InternetGroupManagementProtocol || ipV4Layer.Protocol == IpV4Protocol.InternetControlMessageProtocol || ipV4Layer.Protocol == IpV4Protocol.Gre || packet.IsValid, "IsValid (" + ipV4Layer.Protocol + ")"); // Ethernet Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.PayloadLength, "PayloadLength"); Assert.AreEqual(ethernetLayer, packet.Ethernet.ExtractLayer(), "Ethernet Layer"); // IpV4 ipV4Layer.HeaderChecksum = ((IpV4Layer)packet.Ethernet.IpV4.ExtractLayer()).HeaderChecksum; Assert.AreEqual(ipV4Layer, packet.Ethernet.IpV4.ExtractLayer(), "IP Layer"); Assert.AreEqual(ipV4Layer.Destination, packet.Ethernet.IpV4.Destination, "Destination"); Assert.AreNotEqual(ipV4Layer, null); Assert.AreNotEqual(ipV4Layer, new PayloadLayer()); Assert.IsNotNull(ipV4Layer.ToString()); Assert.AreEqual(IpV4Datagram.HeaderMinimumLength + ipV4Layer.Options.BytesLength, packet.Ethernet.IpV4.HeaderLength, "IP HeaderLength"); Assert.AreEqual(packet.Length - EthernetDatagram.HeaderLengthValue, packet.Ethernet.IpV4.TotalLength, "IP TotalLength"); Assert.AreNotEqual(2, packet.Ethernet.IpV4.Fragmentation, "IP Fragmentation"); Assert.IsTrue(ipV4Layer.Fragmentation == packet.Ethernet.IpV4.Fragmentation, "IP Fragmentation"); Assert.IsFalse(ipV4Layer.Fragmentation != packet.Ethernet.IpV4.Fragmentation, "IP Fragmentation"); Assert.IsFalse(ipV4Layer.Fragmentation.Equals(0), "IP Fragmentation"); if (ipV4Layer.Fragmentation.Offset != 0) { Assert.AreNotEqual(ipV4Layer.Fragmentation, IpV4Fragmentation.None, "IP Fragmentation"); } Assert.AreEqual(ipV4Layer.Fragmentation.GetHashCode(), packet.Ethernet.IpV4.Fragmentation.GetHashCode(), "IP Fragmentation"); Assert.AreEqual(ipV4Layer.Fragmentation.Options, packet.Ethernet.IpV4.Fragmentation.Options, "IP Fragmentation"); Assert.AreEqual(ipV4Layer.Fragmentation.Offset, packet.Ethernet.IpV4.Fragmentation.Offset, "IP Fragmentation"); if (ipV4Layer.Fragmentation.Equals(IpV4Fragmentation.None)) { Assert.AreEqual(IpV4FragmentationOptions.None, packet.Ethernet.IpV4.Fragmentation.Options, "IP Fragmentation"); Assert.AreEqual(0, packet.Ethernet.IpV4.Fragmentation.Offset, "IP Fragmentation"); } Assert.AreEqual(true, packet.Ethernet.IpV4.IsHeaderChecksumCorrect, "IP HeaderChecksumCorrect"); Assert.AreNotEqual(null, packet.Ethernet.IpV4.Options, "IP Options"); Assert.AreNotEqual(packet.Ethernet.IpV4.Options, null, "IP Options"); Assert.AreNotEqual(new IpV4Options(new IpV4OptionUnknown(0, new byte[35])), packet.Ethernet.IpV4.Options, "IP Options"); Assert.AreEqual(ipV4Layer.Options.GetHashCode(), packet.Ethernet.IpV4.Options.GetHashCode(), "IP Options HashCode"); Assert.IsNotNull(packet.Ethernet.IpV4.Options.ToString()); for (int optionIndex = 0; optionIndex != ipV4Layer.Options.Count; ++optionIndex) { IpV4Option option = ipV4Layer.Options[optionIndex]; Assert.AreEqual(option, packet.Ethernet.IpV4.Options[optionIndex]); Assert.IsFalse(option.Equals(null)); } if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Tcp) { Assert.IsInstanceOfType(packet.Ethernet.IpV4.Transport, typeof(TcpDatagram)); } else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Udp) { Assert.IsInstanceOfType(packet.Ethernet.IpV4.Transport, typeof(UdpDatagram)); } else { Assert.IsNull(packet.Ethernet.IpV4.Transport); } if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.Ip) { Assert.IsInstanceOfType(packet.Ethernet.IpV4.Ip, typeof(IpV4Datagram)); } else if (packet.Ethernet.IpV4.Protocol == IpV4Protocol.IpV6) { Assert.IsInstanceOfType(packet.Ethernet.IpV4.Ip, typeof(IpV6Datagram)); } else { Assert.IsNull(packet.Ethernet.IpV4.Ip); } Assert.AreEqual(payloadLayer.Data, packet.Ethernet.IpV4.Payload, "IP Payload"); } }
public static IEnumerable <string> GetWiresharkSubfieldStrings(this IpV4Option option) { switch (option.OptionType) { case IpV4OptionType.EndOfOptionList: case IpV4OptionType.NoOperation: case IpV4OptionType.StreamIdentifier: case IpV4OptionType.RouterAlert: case IpV4OptionType.QuickStart: break; case IpV4OptionType.LooseSourceRouting: case IpV4OptionType.StrictSourceRouting: case IpV4OptionType.RecordRoute: IpV4OptionRoute routeOption = (IpV4OptionRoute)option; yield return("Pointer: " + (routeOption.PointedAddressIndex * 4 + 4)); for (int i = 0; i != routeOption.Route.Count; ++i) { yield return(routeOption.Route[i] + (routeOption.PointedAddressIndex == i ? " <- (current)" : string.Empty)); } break; case IpV4OptionType.InternetTimestamp: IpV4OptionTimestamp timestampOption = (IpV4OptionTimestamp)option; if (timestampOption.CountTimestamps == 0) { break; } yield return("Pointer: " + (timestampOption.PointedIndex * 4 + 5)); yield return("Overflow: " + timestampOption.Overflow); switch (timestampOption.TimestampType) { case IpV4OptionTimestampType.TimestampOnly: yield return("Flag: Time stamps only"); IpV4OptionTimestampOnly timestampOnlyOption = (IpV4OptionTimestampOnly)option; foreach (IpV4TimeOfDay timeOfDay in timestampOnlyOption.Timestamps) { yield return("Time stamp = " + timeOfDay.MillisecondsSinceMidnightUniversalTime); } break; case IpV4OptionTimestampType.AddressAndTimestamp: yield return("Flag: Time stamp and address"); IpV4OptionTimestampAndAddress timestampAndAddressOption = (IpV4OptionTimestampAndAddress)option; foreach (IpV4OptionTimedAddress timedAddress in timestampAndAddressOption.TimedRoute) { yield return("Address = " + timedAddress.Address + ", " + "time stamp = " + timedAddress.TimeOfDay.MillisecondsSinceMidnightUniversalTime); } break; case IpV4OptionTimestampType.AddressPrespecified: yield return("Flag: Time stamps for prespecified addresses"); IpV4OptionTimestampAndAddress timestampPrespecifiedOption = (IpV4OptionTimestampAndAddress)option; foreach (IpV4OptionTimedAddress timedAddress in timestampPrespecifiedOption.TimedRoute) { yield return(string.Format("Address = {0}, time stamp = {1}", timedAddress.Address, timedAddress.TimeOfDay.MillisecondsSinceMidnightUniversalTime)); } break; default: throw new InvalidOperationException("Illegal timestamp type " + timestampOption.TimestampType); } break; // ReSharper disable RedundantCaseLabel case IpV4OptionType.BasicSecurity: // ReSharper restore RedundantCaseLabel default: if (typeof(IpV4OptionType).GetEnumValues <IpV4OptionType>().Contains(option.OptionType)) { throw new InvalidOperationException("Invalid option type " + option.OptionType); } break; } }
public static string GetWiresharkString(this IpV4Option option) { switch (option.OptionType) { case IpV4OptionType.EndOfOptionList: return("End of Option List (EOL)"); case IpV4OptionType.NoOperation: return("No-Operation (NOP)"); case IpV4OptionType.BasicSecurity: return("Security"); case IpV4OptionType.LooseSourceRouting: return("Loose source route (" + option.Length + " bytes)"); case IpV4OptionType.StrictSourceRouting: return("Strict source route (" + option.Length + " bytes)"); case IpV4OptionType.RecordRoute: return("Record route (" + option.Length + " bytes)"); case IpV4OptionType.StreamIdentifier: return("Stream identifier: " + ((IpV4OptionStreamIdentifier)option).Identifier); case IpV4OptionType.InternetTimestamp: return("Time stamp" + (option.Length < 5 ? " (with option length = " + option.Length + " bytes; should be >= 5)" : ":")); case IpV4OptionType.TraceRoute: return("Unknown (0x52) (12 bytes)"); case IpV4OptionType.RouterAlert: ushort routerAlertValue = ((IpV4OptionRouterAlert)option).Value; return("Router Alert: " + ((routerAlertValue != 0) ? "Unknown (" + routerAlertValue + ")" : "Every router examines packet")); case IpV4OptionType.QuickStart: IpV4OptionQuickStart quickStart = (IpV4OptionQuickStart)option; StringBuilder quickStartWireshark = new StringBuilder("Quick-Start: "); quickStartWireshark.Append(quickStart.Function == IpV4OptionQuickStartFunction.RateRequest ? "Rate request" : "Rate report"); quickStartWireshark.Append(", "); if (quickStart.RateKbps == 0) { quickStartWireshark.Append("0 bit/s"); } else if (quickStart.RateKbps < 1024) { quickStartWireshark.Append(quickStart.RateKbps + " kbit/s"); } else if (quickStart.RateKbps < 1024 * 1024) { quickStartWireshark.Append(((double)quickStart.RateKbps / 1000) + " Mbit/s"); } else { quickStartWireshark.Append(((double)quickStart.RateKbps / 1000000) + " Gbit/s"); } if (quickStart.Function == IpV4OptionQuickStartFunction.RateRequest) { quickStartWireshark.Append(", QS TTL " + quickStart.Ttl); } return(quickStartWireshark.ToString()); case (IpV4OptionType)134: return("Commercial IP security option" + (option.Length >= 10 ? string.Empty : " (with option length = " + option.Length + " bytes; should be >= 10)")); default: if (typeof(IpV4OptionType).GetEnumValues <IpV4OptionType>().Contains(option.OptionType)) { throw new InvalidOperationException("Invalid option type " + option.OptionType); } return("Unknown (0x" + ((byte)option.OptionType).ToString("x2") + ") (" + option.Length + " bytes)"); } }