Example #1
0
        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));
        }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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);
        }
Example #4
0
        /// <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);
            }
        }
Example #5
0
        /// <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);
        }
Example #6
0
        /// <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];
        }
Example #7
0
        /// <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);
        }
Example #8
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);
                }
            }
        }
Example #9
0
        /// <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);
            }
        }
Example #11
0
        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;
            }
        }
Example #14
0
        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");
            }
        }
Example #15
0
        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;
            }
        }
Example #16
0
        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)");
            }
        }