/// <summary>
 /// Creates an instance from subtype and identifier.
 /// </summary>
 /// <param name="subtype">
 /// Defines the specific type of identifier included in the Identifier field.
 /// </param>
 /// <param name="identifier">
 /// A variable length identifier of type, as specified by the Subtype field of this option.
 /// </param>
 public IpV6MobilityOptionMobileNodeIdentifier(IpV6MobileNodeIdentifierSubtype subtype, DataSegment identifier)
     : base(IpV6MobilityOptionType.MobileNodeIdentifier)
 {
     if (identifier == null) 
         throw new ArgumentNullException("identifier");
     if (subtype == IpV6MobileNodeIdentifierSubtype.NetworkAccessIdentifier && identifier.Length < MinNetworkAccessIdentifierLength)
         throw new ArgumentOutOfRangeException("identifier", identifier,
                                               string.Format(CultureInfo.InvariantCulture, "Network Access Identifier must be at least {0} bytes long.",
                                                             MinNetworkAccessIdentifierLength));
     Subtype = subtype;
     Identifier = identifier;
 }
 /// <summary>
 /// Creates an instance from subtype and identifier.
 /// </summary>
 /// <param name="subtype">
 /// Defines the specific type of identifier included in the Identifier field.
 /// </param>
 /// <param name="identifier">
 /// A variable length identifier of type, as specified by the Subtype field of this option.
 /// </param>
 public IpV6MobilityOptionMobileNodeIdentifier(IpV6MobileNodeIdentifierSubtype subtype, DataSegment identifier)
     : base(IpV6MobilityOptionType.MobileNodeIdentifier)
 {
     if (identifier == null)
     {
         throw new ArgumentNullException("identifier");
     }
     if (subtype == IpV6MobileNodeIdentifierSubtype.NetworkAccessIdentifier && identifier.Length < MinNetworkAccessIdentifierLength)
     {
         throw new ArgumentOutOfRangeException("identifier", identifier,
                                               string.Format(CultureInfo.InvariantCulture, "Network Access Identifier must be at least {0} bytes long.",
                                                             MinNetworkAccessIdentifierLength));
     }
     Subtype    = subtype;
     Identifier = identifier;
 }
        internal override IpV6MobilityOption CreateInstance(DataSegment data)
        {
            if (data.Length < OptionDataMinimumLength)
            {
                return(null);
            }

            IpV6MobileNodeIdentifierSubtype subtype = (IpV6MobileNodeIdentifierSubtype)data[Offset.Subtype];
            DataSegment identifier = data.Subsegment(Offset.Identifier, data.Length - Offset.Identifier);

            if (subtype == IpV6MobileNodeIdentifierSubtype.NetworkAccessIdentifier && identifier.Length < MinNetworkAccessIdentifierLength)
            {
                return(null);
            }

            return(new IpV6MobilityOptionMobileNodeIdentifier(subtype, identifier));
        }
        public static IpV6MobilityOption NextIpV6MobilityOption(this Random random)
        {
            IpV6MobilityOptionType optionType = random.NextEnum <IpV6MobilityOptionType>();

            switch (optionType)
            {
            case IpV6MobilityOptionType.Pad1:
                return(new IpV6MobilityOptionPad1());

            case IpV6MobilityOptionType.PadN:
                return(new IpV6MobilityOptionPadN(random.NextInt(0, 10)));

            case IpV6MobilityOptionType.BindingRefreshAdvice:
                return(new IpV6MobilityOptionBindingRefreshAdvice(random.NextUShort()));

            case IpV6MobilityOptionType.AlternateCareOfAddress:
                return(new IpV6MobilityOptionAlternateCareOfAddress(random.NextIpV6Address()));

            case IpV6MobilityOptionType.NonceIndexes:
                return(new IpV6MobilityOptionNonceIndexes(random.NextUShort(), random.NextUShort()));

            case IpV6MobilityOptionType.BindingAuthorizationData:
                return(new IpV6MobilityOptionBindingAuthorizationData(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.MobileNetworkPrefix:
                return(new IpV6MobilityOptionMobileNetworkPrefix(random.NextByte(), random.NextIpV6Address()));

            case IpV6MobilityOptionType.LinkLayerAddress:
                return(new IpV6MobilityOptionLinkLayerAddress(random.NextEnum <IpV6MobilityLinkLayerAddressCode>(),
                                                              random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.MobileNodeIdentifier:
                IpV6MobileNodeIdentifierSubtype mobileNodeIdentifierSubtype = random.NextEnum <IpV6MobileNodeIdentifierSubtype>();
                return(new IpV6MobilityOptionMobileNodeIdentifier(
                           mobileNodeIdentifierSubtype,
                           random.NextDataSegment(random.NextInt(mobileNodeIdentifierSubtype == IpV6MobileNodeIdentifierSubtype.NetworkAccessIdentifier ? 1 : 0,
                                                                 100))));

            case IpV6MobilityOptionType.Authentication:
                return(new IpV6MobilityOptionAuthentication(random.NextEnum <IpV6AuthenticationSubtype>(), random.NextUInt(),
                                                            random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.ReplayProtection:
                return(new IpV6MobilityOptionReplayProtection(random.NextULong()));

            case IpV6MobilityOptionType.CryptographicallyGeneratedAddressParametersRequest:
                return(new IpV6MobilityOptionCryptographicallyGeneratedAddressParametersRequest());

            case IpV6MobilityOptionType.CryptographicallyGeneratedAddressParameters:
                return(new IpV6MobilityOptionCryptographicallyGeneratedAddressParameters(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.Signature:
                return(new IpV6MobilityOptionSignature(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.PermanentHomeKeygenToken:
                return(new IpV6MobilityOptionPermanentHomeKeygenToken(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.CareOfTestInit:
                return(new IpV6MobilityOptionCareOfTestInit());

            case IpV6MobilityOptionType.CareOfTest:
                return(new IpV6MobilityOptionCareOfTest(random.NextULong()));

            case IpV6MobilityOptionType.DnsUpdate:
                return(new IpV6MobilityOptionDnsUpdate(random.NextEnum <IpV6DnsUpdateStatus>(), random.NextBool(),
                                                       random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.Experimental:
                return(new IpV6MobilityOptionExperimental(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.VendorSpecific:
                return(new IpV6MobilityOptionVendorSpecific(random.NextUInt(), random.NextByte(), random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.ServiceSelection:
                return(new IpV6MobilityOptionServiceSelection(random.NextDataSegment(random.NextInt(1, 100))));

            case IpV6MobilityOptionType.BindingAuthorizationDataForFmIpV6:
                return(new IpV6MobilityOptionBindingAuthorizationDataForFmIpV6(random.NextUInt(), random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.HomeNetworkPrefix:
                return(new IpV6MobilityOptionHomeNetworkPrefix(random.NextByte(), random.NextIpV6Address()));

            case IpV6MobilityOptionType.HandoffIndicator:
                return(new IpV6MobilityOptionHandoffIndicator(random.NextEnum <IpV6HandoffIndicator>()));

            case IpV6MobilityOptionType.AccessTechnologyType:
                return(new IpV6MobilityOptionAccessTechnologyType(random.NextEnum <IpV6AccessTechnologyType>()));

            case IpV6MobilityOptionType.MobileNodeLinkLayerIdentifier:
                return(new IpV6MobilityOptionMobileNodeLinkLayerIdentifier(random.NextDataSegment(random.NextInt(0, 100))));

            case IpV6MobilityOptionType.LinkLocalAddress:
                return(new IpV6MobilityOptionLinkLocalAddress(random.NextIpV6Address()));

            case IpV6MobilityOptionType.Timestamp:
                return(new IpV6MobilityOptionTimestamp(random.NextULong() % (500000000000L << 16)));

            case IpV6MobilityOptionType.RestartCounter:
                return(new IpV6MobilityOptionRestartCounter(random.NextUInt()));

            case IpV6MobilityOptionType.IpV4HomeAddress:
                return(new IpV6MobilityOptionIpV4HomeAddress(random.NextByte(IpV6MobilityOptionIpV4HomeAddress.MaxPrefixLength + 1), random.NextBool(),
                                                             random.NextIpV4Address()));

            case IpV6MobilityOptionType.IpV4AddressAcknowledgement:
                return(new IpV6MobilityOptionIpV4AddressAcknowledgement(random.NextEnum <IpV6AddressAcknowledgementStatus>(),
                                                                        random.NextByte(IpV6MobilityOptionIpV4AddressAcknowledgement.MaxPrefixLength + 1),
                                                                        random.NextIpV4Address()));

            case IpV6MobilityOptionType.NatDetection:
                return(new IpV6MobilityOptionNatDetection(random.NextBool(), random.NextUInt()));

            case IpV6MobilityOptionType.IpV4CareOfAddress:
                return(new IpV6MobilityOptionIpV4CareOfAddress(random.NextIpV4Address()));

            case IpV6MobilityOptionType.GreKey:
                return(new IpV6MobilityOptionGreKey(random.NextUInt()));

            case IpV6MobilityOptionType.IpV6AddressPrefix:
                return(new IpV6MobilityOptionIpV6AddressPrefix(random.NextEnum <IpV6MobilityIpV6AddressPrefixCode>(),
                                                               random.NextByte(IpV6MobilityOptionIpV6AddressPrefix.MaxPrefixLength + 1),
                                                               random.NextIpV6Address()));

            case IpV6MobilityOptionType.BindingIdentifier:
                ushort bindingId = random.NextUShort();
                IpV6BindingAcknowledgementStatus status = random.NextEnum <IpV6BindingAcknowledgementStatus>();
                bool simultaneousHomeAndForeignBinding  = random.NextBool();
                byte priority = random.NextByte(IpV6MobilityOptionBindingIdentifier.MaxPriority + 1);
                if (random.NextBool(3))
                {
                    return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority));
                }
                if (random.NextBool())
                {
                    return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, random.NextIpV4Address()));
                }
                return(new IpV6MobilityOptionBindingIdentifier(bindingId, status, simultaneousHomeAndForeignBinding, priority, random.NextIpV6Address()));

            case IpV6MobilityOptionType.IpV4HomeAddressRequest:
                return(new IpV6MobilityOptionIpV4HomeAddressRequest(random.NextByte(IpV6MobilityOptionIpV4HomeAddressRequest.MaxPrefixLength + 1),
                                                                    random.NextIpV4Address()));

            case IpV6MobilityOptionType.IpV4HomeAddressReply:
                return(new IpV6MobilityOptionIpV4HomeAddressReply(random.NextEnum <IpV6IpV4HomeAddressReplyStatus>(),
                                                                  random.NextByte(IpV6MobilityOptionIpV4HomeAddressReply.MaxPrefixLength + 1),
                                                                  random.NextIpV4Address()));

            case IpV6MobilityOptionType.IpV4DefaultRouterAddress:
                return(new IpV6MobilityOptionIpV4DefaultRouterAddress(random.NextIpV4Address()));

            case IpV6MobilityOptionType.IpV4DhcpSupportMode:
                return(new IpV6MobilityOptionIpV4DhcpSupportMode(random.NextBool()));

            case IpV6MobilityOptionType.ContextRequest:
                return
                    (new IpV6MobilityOptionContextRequest(
                         ((Func <IpV6MobilityOptionContextRequestEntry>)(() => new IpV6MobilityOptionContextRequestEntry(
                                                                             random.NextByte(), random.NextDataSegment(random.NextInt(0, 25))))).
                         GenerateArray(random.NextInt(0, 10))));

            case IpV6MobilityOptionType.LocalMobilityAnchorAddress:
                if (random.NextBool())
                {
                    return(new IpV6MobilityOptionLocalMobilityAnchorAddress(random.NextIpV4Address()));
                }
                return(new IpV6MobilityOptionLocalMobilityAnchorAddress(random.NextIpV6Address()));

            case IpV6MobilityOptionType.MobileNodeLinkLocalAddressInterfaceIdentifier:
                return(new IpV6MobilityOptionMobileNodeLinkLocalAddressInterfaceIdentifier(random.NextULong()));

            case IpV6MobilityOptionType.TransientBinding:
                return(new IpV6MobilityOptionTransientBinding(random.NextBool(), random.NextByte()));

            case IpV6MobilityOptionType.FlowSummary:
                return(new IpV6MobilityOptionFlowSummary(((Func <ushort>)(random.NextUShort)).GenerateArray(random.NextInt(1, 10))));

            case IpV6MobilityOptionType.FlowIdentification:
                return(new IpV6MobilityOptionFlowIdentification(random.NextUShort(), random.NextUShort(), random.NextEnum <IpV6FlowIdentificationStatus>(),
                                                                random.NextIpV6FlowIdentificationSubOptions()));

            case IpV6MobilityOptionType.RedirectCapability:
                return(new IpV6MobilityOptionRedirectCapability());

            case IpV6MobilityOptionType.Redirect:
                if (random.NextBool())
                {
                    return(new IpV6MobilityOptionRedirect(random.NextIpV4Address()));
                }
                return(new IpV6MobilityOptionRedirect(random.NextIpV6Address()));

            case IpV6MobilityOptionType.LoadInformation:
                return(new IpV6MobilityOptionLoadInformation(random.NextUShort(), random.NextUInt(), random.NextUInt(), random.NextUInt(), random.NextUInt()));

            case IpV6MobilityOptionType.AlternateIpV4CareOfAddress:
                return(new IpV6MobilityOptionAlternateIpV4CareOfAddress(random.NextIpV4Address()));

            case IpV6MobilityOptionType.MobileNodeGroupIdentifier:
                return(new IpV6MobilityOptionMobileNodeGroupIdentifier(random.NextEnum <IpV6MobileNodeGroupIdentifierSubtype>(), random.NextUInt()));

            case IpV6MobilityOptionType.MobileAccessGatewayIpV6Address:
                return(new IpV6MobilityOptionMobileAccessGatewayIpV6Address(random.NextIpV6Address()));

            case IpV6MobilityOptionType.AccessNetworkIdentifier:
                return(new IpV6MobilityOptionAccessNetworkIdentifier(random.NextIpV6AccessNetworkIdentifierSubOptions()));

            default:
                throw new InvalidOperationException(string.Format("Invalid optionType value {0}", optionType));
            }
        }