Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pcap-Net
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Pcap-Net
Commits
a1d11f17
Commit
a1d11f17
authored
Jun 28, 2013
by
Brickner_cp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
IPv6
parent
14e2149e
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
1041 additions
and
29 deletions
+1041
-29
ByteArrayExtensions.cs
PcapDotNet/src/PcapDotNet.Packets/ByteArrayExtensions.cs
+12
-0
IpV6OptionPad1.cs
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionPad1.cs
+3
-8
IpV6OptionPadN.cs
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionPadN.cs
+10
-8
IpV6OptionSimple.cs
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionSimple.cs
+8
-1
IpV6OptionType.cs
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionType.cs
+5
-5
IpV6OptionUnknown.cs
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionUnknown.cs
+1003
-7
No files found.
PcapDotNet/src/PcapDotNet.Packets/ByteArrayExtensions.cs
View file @
a1d11f17
...
@@ -687,6 +687,18 @@ namespace PcapDotNet.Packets
...
@@ -687,6 +687,18 @@ namespace PcapDotNet.Packets
buffer
.
Write
(
offset
,
(
long
)
value
,
endianity
);
buffer
.
Write
(
offset
,
(
long
)
value
,
endianity
);
}
}
/// <summary>
/// Writes the given value to the buffer using the given endianity and increments the offset by the number of bytes written.
/// </summary>
/// <param name="buffer">The buffer to write the value to.</param>
/// <param name="offset">The offset in the buffer to start writing.</param>
/// <param name="value">The value to write.</param>
/// <param name="endianity">The endianity to use when converting the value to bytes.</param>
public
static
void
Write
(
this
byte
[]
buffer
,
ref
int
offset
,
ulong
value
,
Endianity
endianity
)
{
buffer
.
Write
(
offset
,
(
long
)
value
,
endianity
);
}
/// <summary>
/// <summary>
/// Writes the given value to the buffer using the given endianity.
/// Writes the given value to the buffer using the given endianity.
/// </summary>
/// </summary>
...
...
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionPad1.cs
View file @
a1d11f17
using
System
;
namespace
PcapDotNet.Packets.IpV6
namespace
PcapDotNet.Packets.IpV6
{
{
/// <summary>
/// <summary>
...
@@ -7,7 +9,6 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -7,7 +9,6 @@ namespace PcapDotNet.Packets.IpV6
/// | 0 | 0 |
/// | 0 | 0 |
/// +-----+-----+
/// +-----+-----+
/// </summary>
/// </summary>
[
IpV6OptionTypeRegistration
(
IpV6OptionType
.
Pad1
)]
public
class
IpV6OptionPad1
:
IpV6OptionSimple
public
class
IpV6OptionPad1
:
IpV6OptionSimple
{
{
public
const
int
OptionLength
=
sizeof
(
byte
);
public
const
int
OptionLength
=
sizeof
(
byte
);
...
@@ -16,11 +17,6 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -16,11 +17,6 @@ namespace PcapDotNet.Packets.IpV6
:
base
(
IpV6OptionType
.
Pad1
)
:
base
(
IpV6OptionType
.
Pad1
)
{
{
}
}
internal
override
IpV6Option
CreateInstance
(
DataSegment
data
)
{
return
new
IpV6OptionPad1
();
}
}
}
/// <summary>
/// <summary>
...
@@ -31,7 +27,6 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -31,7 +27,6 @@ namespace PcapDotNet.Packets.IpV6
/// | 0 | 0 |
/// | 0 | 0 |
/// +-----+-----+
/// +-----+-----+
/// </summary>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
Pad1
)]
public
class
IpV6MobilityOptionPad1
:
IpV6MobilityOption
public
class
IpV6MobilityOptionPad1
:
IpV6MobilityOption
{
{
public
const
int
OptionLength
=
sizeof
(
byte
);
public
const
int
OptionLength
=
sizeof
(
byte
);
...
@@ -43,7 +38,7 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -43,7 +38,7 @@ namespace PcapDotNet.Packets.IpV6
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
{
return
new
IpV6MobilityOptionPad1
(
);
throw
new
InvalidOperationException
(
"Pad1 options shouldn't be registered."
);
}
}
}
}
}
}
\ No newline at end of file
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionPadN.cs
View file @
a1d11f17
...
@@ -3,14 +3,16 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -3,14 +3,16 @@ namespace PcapDotNet.Packets.IpV6
/// <summary>
/// <summary>
/// RFC 2460.
/// RFC 2460.
/// <pre>
/// <pre>
/// +-----+-------------+--------------+
/// +-----+-------------+
/// | Bit | 0-7 | 8-15 |
/// | Bit | 0-7 |
/// +-----+-------------+--------------+
/// +-----+-------------+
/// | 0 | Option Type | N |
/// | 0 | Option Type |
/// +-----+-------------+--------------+
/// +-----+-------------+
/// | 8 | N |
/// +-----+-------------+
/// | 16 | 0 |
/// | 16 | 0 |
/// | ... | |
/// | ... | |
/// +-----+-------------
---------------
+
/// +-----+-------------+
/// </pre>
/// </pre>
/// </summary>
/// </summary>
[
IpV6OptionTypeRegistration
(
IpV6OptionType
.
PadN
)]
[
IpV6OptionTypeRegistration
(
IpV6OptionType
.
PadN
)]
...
...
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionSimple.cs
View file @
a1d11f17
using
System
;
namespace
PcapDotNet.Packets.IpV6
namespace
PcapDotNet.Packets.IpV6
{
{
/// <summary>
/// <summary>
...
@@ -25,5 +27,10 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -25,5 +27,10 @@ namespace PcapDotNet.Packets.IpV6
{
{
base
.
Write
(
buffer
,
ref
offset
);
base
.
Write
(
buffer
,
ref
offset
);
}
}
internal
override
sealed
IpV6Option
CreateInstance
(
DataSegment
data
)
{
throw
new
InvalidOperationException
(
"Simple options shouldn't be registered."
);
}
}
}
}
}
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionType.cs
View file @
a1d11f17
...
@@ -99,7 +99,7 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -99,7 +99,7 @@ namespace PcapDotNet.Packets.IpV6
/// <summary>
/// <summary>
/// RFC 6275.
/// RFC 6275.
/// </summary>
/// </summary>
AuthorizationData
=
0x05
,
Binding
AuthorizationData
=
0x05
,
/// <summary>
/// <summary>
/// RFC 3963.
/// RFC 3963.
...
@@ -111,25 +111,25 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -111,25 +111,25 @@ namespace PcapDotNet.Packets.IpV6
/// RFC 5568.
/// RFC 5568.
/// Mobility Header Link-Layer Address option.
/// Mobility Header Link-Layer Address option.
/// </summary>
/// </summary>
MobilityHeader
LinkLayerAddress
=
0x07
,
LinkLayerAddress
=
0x07
,
/// <summary>
/// <summary>
/// RFC 4283.
/// RFC 4283.
/// MN-ID-OPTION-TYPE.
/// MN-ID-OPTION-TYPE.
/// </summary>
/// </summary>
M
nId
=
0x08
,
M
obileNodeIdentifier
=
0x08
,
/// <summary>
/// <summary>
/// RFC 4285.
/// RFC 4285.
/// AUTH-OPTION-TYPE.
/// AUTH-OPTION-TYPE.
/// </summary>
/// </summary>
Auth
=
0x09
,
Auth
entication
=
0x09
,
/// <summary>
/// <summary>
/// RFC 4285.
/// RFC 4285.
/// MESG-ID-OPTION-TYPE
/// MESG-ID-OPTION-TYPE
/// </summary>
/// </summary>
MesgId
=
0x0A
,
ReplayProtection
=
0x0A
,
/// <summary>
/// <summary>
/// RFC 4866.
/// RFC 4866.
...
...
PcapDotNet/src/PcapDotNet.Packets/IpV6/IpV6OptionUnknown.cs
View file @
a1d11f17
...
@@ -54,29 +54,1025 @@ namespace PcapDotNet.Packets.IpV6
...
@@ -54,29 +54,1025 @@ namespace PcapDotNet.Packets.IpV6
/// +-----+----------------------------+
/// +-----+----------------------------+
/// </pre>
/// </pre>
/// </summary>
/// </summary>
public
class
IpV6MobilityOptionUnknown
:
IpV6MobilityOption
Complex
public
class
IpV6MobilityOptionUnknown
:
IpV6MobilityOption
SingleDataSegmentField
{
{
public
IpV6MobilityOptionUnknown
(
IpV6MobilityOptionType
type
,
DataSegment
data
)
public
IpV6MobilityOptionUnknown
(
IpV6MobilityOptionType
type
,
DataSegment
data
)
:
base
(
type
,
data
)
{
}
public
DataSegment
Data
{
get
{
return
Value
;
}
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
throw
new
InvalidOperationException
(
"IpV6MobilityOptionUnknown shouldn't be registered."
);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+
/// | Bit | 0-7 |
/// +-----+--------------+
/// | 0 | Option Type |
/// +-----+--------------+
/// | 8 | Opt Data Len |
/// +-----+--------------+
/// | 16 | 0 |
/// | ... | |
/// +-----+--------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
PadN
)]
public
class
IpV6MobilityOptionPadN
:
IpV6MobilityOptionComplex
{
public
IpV6MobilityOptionPadN
(
int
paddingDataLength
)
:
base
(
IpV6MobilityOptionType
.
PadN
)
{
PaddingDataLength
=
paddingDataLength
;
}
public
int
PaddingDataLength
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
return
new
IpV6MobilityOptionPadN
(
data
.
Length
);
}
internal
override
int
DataLength
{
get
{
return
PaddingDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
offset
+=
PaddingDataLength
;
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Refresh Interval |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
BindingRefreshAdvice
)]
public
class
IpV6MobilityOptionBindingRefreshAdvice
:
IpV6MobilityOptionComplex
{
public
const
int
OptionDataLength
=
sizeof
(
ushort
);
public
IpV6MobilityOptionBindingRefreshAdvice
(
ushort
refreshInterval
)
:
base
(
IpV6MobilityOptionType
.
BindingRefreshAdvice
)
{
refreshInterval
=
refreshInterval
;
}
/// <summary>
/// Measured in units of four seconds, and indicates remaining time until the mobile node should send a new home registration to the home agent.
/// The Refresh Interval must be set to indicate a smaller time interval than the Lifetime value of the Binding Acknowledgement.
/// </summary>
public
ushort
RefreshInterval
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
return
new
IpV6MobilityOptionBindingRefreshAdvice
(
data
.
ReadUShort
(
0
,
Endianity
.
Big
));
}
internal
override
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
ref
offset
,
RefreshInterval
,
Endianity
.
Big
);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Alternate Care-of Address |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
AlternateCareOfAddress
)]
public
class
IpV6MobilityOptionAlternateCareOfAddress
:
IpV6MobilityOptionComplex
{
public
const
int
OptionDataLength
=
IpV6Address
.
SizeOf
;
public
IpV6MobilityOptionAlternateCareOfAddress
(
IpV6Address
alternateCareOfAddress
)
:
base
(
IpV6MobilityOptionType
.
AlternateCareOfAddress
)
{
AlternateCareOfAddress
=
alternateCareOfAddress
;
}
/// <summary>
/// Contains an address to use as the care-of address for the binding, rather than using the Source Address of the packet as the care-of address.
/// </summary>
public
IpV6Address
AlternateCareOfAddress
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
return
new
IpV6MobilityOptionAlternateCareOfAddress
(
data
.
ReadIpV6Address
(
0
,
Endianity
.
Big
));
}
internal
override
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
ref
offset
,
AlternateCareOfAddress
,
Endianity
.
Big
);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Home Nonce Index |
/// +-----+-----------------------------+
/// | 32 | Care-of Nonce Index |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
NonceIndices
)]
public
class
IpV6MobilityOptionNonceIndices
:
IpV6MobilityOptionComplex
{
private
static
class
Offset
{
public
const
int
HomeNonceIndex
=
0
;
public
const
int
CareOfNonceIndex
=
HomeNonceIndex
+
sizeof
(
ushort
);
}
public
const
int
OptionDataLength
=
Offset
.
CareOfNonceIndex
+
sizeof
(
ushort
);
public
IpV6MobilityOptionNonceIndices
(
ushort
homeNonceIndex
,
ushort
careOfNonceIndex
)
:
base
(
IpV6MobilityOptionType
.
NonceIndices
)
{
HomeNonceIndex
=
homeNonceIndex
;
CareOfNonceIndex
=
careOfNonceIndex
;
}
/// <summary>
/// Tells the correspondent node which nonce value to use when producing the home keygen token.
/// </summary>
public
ushort
HomeNonceIndex
{
get
;
private
set
;
}
/// <summary>
/// Ignored in requests to delete a binding.
/// Otherwise, it tells the correspondent node which nonce value to use when producing the care-of keygen token.
/// </summary>
public
ushort
CareOfNonceIndex
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
ushort
homeNonceIndex
=
data
.
ReadUShort
(
Offset
.
HomeNonceIndex
,
Endianity
.
Big
);
ushort
careOfNonceIndex
=
data
.
ReadUShort
(
Offset
.
CareOfNonceIndex
,
Endianity
.
Big
);
return
new
IpV6MobilityOptionNonceIndices
(
homeNonceIndex
,
careOfNonceIndex
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
ref
offset
,
HomeNonceIndex
,
Endianity
.
Big
);
buffer
.
Write
(
ref
offset
,
CareOfNonceIndex
,
Endianity
.
Big
);
}
}
/// <summary>
/// RFC 6275.
/// <pre>
/// +-----+--------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+--------------+
/// | 16 | Authenticator |
/// | ... | |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
BindingAuthorizationData
)]
public
class
IpV6MobilityOptionBindingAuthorizationData
:
IpV6MobilityOptionSingleDataSegmentField
{
public
IpV6MobilityOptionBindingAuthorizationData
(
DataSegment
authenticator
)
:
base
(
IpV6MobilityOptionType
.
BindingAuthorizationData
,
authenticator
)
{
}
/// <summary>
/// <para>
/// Contains a cryptographic value that can be used to determine that the message in question comes from the right authority.
/// Rules for calculating this value depends on the used authorization procedure.
/// </para>
/// <para>
/// For the return routability procedure, this option can appear in the Binding Update and Binding Acknowledgements.
/// Rules for calculating the Authenticator value are the following:
/// </para>
/// <para>
/// Mobility Data = care-of address | correspondent | MH Data
/// Authenticator = First (96, HMAC_SHA1 (Kbm, Mobility Data))
/// </para>
/// <para>
/// Where | denotes concatenation.
/// "Care-of address" is the care-of address that will be registered for the mobile node if the Binding Update succeeds,
/// or the home address of the mobile node if this option is used in de-registration.
/// Note also that this address might be different from the source address of the Binding Update message,
/// if the Alternative Care-of Address mobility option is used, or when the lifetime of the binding is set to zero.
/// </para>
/// <para>
/// The "correspondent" is the IPv6 address of the correspondent node.
/// Note that, if the message is sent to a destination that is itself mobile, the "correspondent" address may not be the address found in the
/// Destination Address field of the IPv6 header; instead, the home address from the type 2 Routing header should be used.
/// </para>
/// <para>
/// "MH Data" is the content of the Mobility Header, excluding the Authenticator field itself.
/// The Authenticator value is calculated as if the Checksum field in the Mobility Header was zero.
/// The Checksum in the transmitted packet is still calculated in the usual manner,
/// with the calculated Authenticator being a part of the packet protected by the Checksum.
/// Kbm is the binding management key, which is typically created using nonces provided by the correspondent node.
/// Note that while the contents of a potential Home Address destination option are not covered in this formula,
/// the rules for the calculation of the Kbm do take the home address in account.
/// This ensures that the MAC will be different for different home addresses.
/// </para>
/// <para>
/// The first 96 bits from the MAC result are used as the Authenticator field.
/// </para>
/// </summary>
public
DataSegment
Authenticator
{
get
{
return
Value
;
}
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
return
new
IpV6MobilityOptionBindingAuthorizationData
(
data
);
}
}
/// <summary>
/// RFC 3963.
/// <pre>
/// +-----+--------------+---------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+--------------+---------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+--------------+---------------+
/// | 16 | Reserved | Prefix Length |
/// +-----+--------------+---------------+
/// | 32 | Mobile Network Prefix |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// | | |
/// +-----+------------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
MobileNetworkPrefix
)]
public
class
IpV6MobilityOptionMobileNetworkPrefix
:
IpV6MobilityOptionComplex
{
private
static
class
Offset
{
public
const
int
PrefixLength
=
sizeof
(
ushort
);
public
const
int
MobileNetworkPrefix
=
PrefixLength
+
sizeof
(
ushort
);
}
public
const
int
OptionDataLength
=
Offset
.
MobileNetworkPrefix
+
IpV6Address
.
SizeOf
;
public
IpV6MobilityOptionMobileNetworkPrefix
(
byte
prefixLength
,
IpV6Address
mobileNetworkPrefix
)
:
base
(
IpV6MobilityOptionType
.
MobileNetworkPrefix
)
{
PrefixLength
=
prefixLength
;
MobileNetworkPrefix
=
mobileNetworkPrefix
;
}
/// <summary>
/// Indicates the prefix length of the IPv6 prefix contained in the option.
/// </summary>
public
byte
PrefixLength
{
get
;
private
set
;
}
/// <summary>
/// Contains the Mobile Network Prefix.
/// </summary>
public
IpV6Address
MobileNetworkPrefix
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
byte
prefixLength
=
data
[
Offset
.
PrefixLength
];
IpV6Address
mobileNetworkPrefix
=
data
.
ReadIpV6Address
(
Offset
.
MobileNetworkPrefix
,
Endianity
.
Big
);
return
new
IpV6MobilityOptionMobileNetworkPrefix
(
prefixLength
,
mobileNetworkPrefix
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
offset
+
Offset
.
PrefixLength
,
PrefixLength
);
buffer
.
Write
(
offset
+
Offset
.
MobileNetworkPrefix
,
MobileNetworkPrefix
,
Endianity
.
Big
);
offset
+=
OptionDataLength
;
}
}
public
enum
IpV6MobilityOptionLinkLayerAddressCode
:
byte
{
/// <summary>
/// Wildcard requesting resolution for all nearby access points.
/// </summary>
Wildcard
=
0
,
/// <summary>
/// Link-Layer Address of the New Access Point.
/// The address contains the link-layer address of the access point for which handover is about to be attempted.
/// This is used in the Router Solicitation for Proxy Advertisement message.
/// </summary>
NewAccessPoint
=
1
,
/// <summary>
/// Link-Layer Address of the MN (Mobility Node).
/// The address contains the link-layer address of an MN.
/// It is used in the Handover Initiate message.
/// </summary>
MobilityNode
=
2
,
/// <summary>
/// Link-Layer Address of the NAR (New Access Router) (i.e., Proxied Originator).
/// The address contains the link-layer address of the access router to which the Proxy Router Solicitation message refers.
/// </summary>
NewAccessRouter
=
3
,
/// <summary>
/// Link-Layer Address of the source of RtSolPr (Router Solicitation for Proxy Advertisement) or PrRtAdv (Proxy Router Advertisement) message.
/// </summary>
SourceRouterSolicitationForProxyAdvertisementOrProxyRouterAdvertisement
=
4
,
/// <summary>
/// The access point identified by the LLA belongs to the current interface of the router.
/// </summary>
AccessPoint
=
5
,
/// <summary>
/// No prefix information available for the access point identified by the LLA
/// </summary>
NoPrefixForAccessPoint
=
6
,
/// <summary>
/// No fast handover support available for the access point identified by the LLA
/// </summary>
NoFastHandoverSupportForAccessPoint
=
7
,
}
/// <summary>
/// RFC 5568.
/// <pre>
/// +-----+--------------+
/// | Bit | 0-7 |
/// +-----+--------------+
/// | 0 | Option Type |
/// +-----+--------------+
/// | 8 | Opt Data Len |
/// +-----+--------------+
/// | 16 | Option-Code |
/// +-----+--------------+
/// | 24 | LLA |
/// | ... | |
/// +-----+--------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
LinkLayerAddress
)]
public
class
IpV6MobilityOptionLinkLayerAddress
:
IpV6MobilityOptionComplex
{
private
static
class
Offset
{
public
const
int
OptionCode
=
0
;
public
const
int
LinkLayerAddress
=
OptionCode
+
sizeof
(
byte
);
}
public
const
int
OptionDataMiniumLength
=
Offset
.
LinkLayerAddress
;
public
IpV6MobilityOptionLinkLayerAddress
(
IpV6MobilityOptionLinkLayerAddressCode
code
,
DataSegment
linkLayerAddress
)
:
base
(
IpV6MobilityOptionType
.
LinkLayerAddress
)
{
Code
=
code
;
LinkLayerAddress
=
linkLayerAddress
;
}
public
IpV6MobilityOptionLinkLayerAddressCode
Code
{
get
;
private
set
;
}
/// <summary>
/// Variable-length link-layer address.
/// </summary>
public
DataSegment
LinkLayerAddress
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
<
OptionDataMiniumLength
)
return
null
;
IpV6MobilityOptionLinkLayerAddressCode
code
=
(
IpV6MobilityOptionLinkLayerAddressCode
)
data
[
Offset
.
OptionCode
];
DataSegment
linkLayerAddress
=
data
.
Subsegment
(
Offset
.
LinkLayerAddress
,
data
.
Length
-
Offset
.
LinkLayerAddress
);
return
new
IpV6MobilityOptionLinkLayerAddress
(
code
,
linkLayerAddress
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataMiniumLength
+
LinkLayerAddress
.
Length
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
offset
+
Offset
.
OptionCode
,
(
byte
)
Code
);
LinkLayerAddress
.
Write
(
buffer
,
offset
+
Offset
.
LinkLayerAddress
);
offset
+=
DataLength
;
}
}
/// <summary>
/// RFC 4283.
/// </summary>
public
enum
IpV6MobileNodeIdentifierSubtype
:
byte
{
/// <summary>
/// RFC 4283.
/// Uses an identifier of the form user@realm (RFC 4282).
/// </summary>
NetworkAccessIdentifier
=
1
,
}
/// <summary>
/// RFC 4283.
/// <pre>
/// +-----+--------------+
/// | Bit | 0-7 |
/// +-----+--------------+
/// | 0 | Option Type |
/// +-----+--------------+
/// | 8 | Opt Data Len |
/// +-----+--------------+
/// | 16 | Subtype |
/// +-----+--------------+
/// | 24 | Identifier |
/// | ... | |
/// +-----+--------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
MobileNodeIdentifier
)]
public
class
IpV6MobilityOptionMobileNodeIdentifier
:
IpV6MobilityOptionComplex
{
private
static
class
Offset
{
public
const
int
Subtype
=
0
;
public
const
int
Identifier
=
Subtype
+
sizeof
(
byte
);
}
public
const
int
OptionDataMiniumLength
=
Offset
.
Identifier
;
public
IpV6MobilityOptionMobileNodeIdentifier
(
IpV6MobileNodeIdentifierSubtype
subtype
,
DataSegment
identifier
)
:
base
(
IpV6MobilityOptionType
.
MobileNodeIdentifier
)
{
Subtype
=
subtype
;
Identifier
=
identifier
;
}
/// <summary>
/// Defines the specific type of identifier included in the Identifier field.
/// </summary>
public
IpV6MobileNodeIdentifierSubtype
Subtype
{
get
;
private
set
;
}
/// <summary>
/// A variable length identifier of type, as specified by the Subtype field of this option.
/// </summary>
public
DataSegment
Identifier
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
<
OptionDataMiniumLength
)
return
null
;
IpV6MobileNodeIdentifierSubtype
subtype
=
(
IpV6MobileNodeIdentifierSubtype
)
data
[
Offset
.
Subtype
];
DataSegment
identifier
=
data
.
Subsegment
(
Offset
.
Identifier
,
data
.
Length
-
Offset
.
Identifier
);
return
new
IpV6MobilityOptionMobileNodeIdentifier
(
subtype
,
identifier
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataMiniumLength
+
Identifier
.
Length
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
offset
+
Offset
.
Subtype
,
(
byte
)
Subtype
);
Identifier
.
Write
(
buffer
,
offset
+
Offset
.
Identifier
);
offset
+=
DataLength
;
}
}
/// <summary>
/// RFC 4285
/// </summary>
public
enum
IpV6AuthenticationSubtype
:
byte
{
/// <summary>
/// Used to authenticate the Binding Update and Binding Acknowledgement messages based on the shared-key-based security association
/// between the Mobile Node and the Home Agent.
/// The shared-key-based mobility security association between Mobile Node and Home Agent used within this specification consists of a mobility SPI,
/// a key, an authentication algorithm, and the replay protection mechanism in use.
/// The mobility SPI is a number in the range [0-4294967296], where the range [0-255] is reserved.
/// The key consists of an arbitrary value and is 16 octets in length.
/// The authentication algorithm is HMAC_SHA1.
/// The replay protection mechanism may use the Sequence number as specified in RFC 3775 or the Timestamp option.
/// If the Timestamp option is used for replay protection, the mobility security association includes a "close enough" field to account
/// for clock drift.
/// A default value of 7 seconds should be used.
/// This value should be greater than 3 seconds.
/// The MN-HA mobility message authentication option must be the last option in a message with a mobility header
/// if it is the only mobility message authentication option in the message.
/// The authentication data is calculated on the message starting from the mobility header up to and including the mobility SPI value of this option.
/// Authentication Data = First(96, HMAC_SHA1(MN-HA Shared key, Mobility Data))
/// Mobility Data = care-of address | home address | Mobility Header (MH) Data
/// MH Data is the content of the Mobility Header up to and including the mobility SPI field of this option.
/// The Checksum field in the Mobility Header must be set to 0 to calculate the Mobility Data.
/// The first 96 bits from the Message Authentication Code (MAC) result are used as the Authentication Data field.
/// </summary>
HomeAgent
=
1
,
/// <summary>
/// The MN-AAA authentication mobility option is used to authenticate the Binding Update message based on the shared mobility security association
/// between the Mobile Node and AAA server in Home network (AAAH).
/// It is not used in Binding Acknowledgement messages.
/// The corresponding Binding Acknowledgement messages must be authenticated using the MN-HA mobility message authentication option.
/// The MN-AAA mobility message authentication option must be the last option in a message with a mobility header.
/// The corresponding response must include the MN-HA mobility message authentication option,
/// and must not include the MN-AAA mobility message authentication option.
/// The Mobile Node may use the Mobile Node Identifier option (RFC 4283) to enable the Home Agent to make use of available AAA infrastructure.
/// The authentication data is calculated on the message starting from the mobility header up to and including the mobility SPI value of this option.
/// The authentication data shall be calculated as follows:
/// Authentication data = hash_fn(MN-AAA Shared key, MAC_Mobility Data)
/// hash_fn() is decided by the value of mobility SPI field in the MN-AAA mobility message authentication option.
/// SPI = HMAC_SHA1_SPI:
/// If mobility SPI has the well-known value HMAC_SHA1_SPI, then hash_fn() is HMAC_SHA1.
/// When HMAC_SHA1_SPI is used, the BU is authenticated by AAA using HMAC_SHA1 authentication.
/// In that case, MAC_Mobility Data is calculated as follows:
/// MAC_Mobility Data = SHA1(care-of address | home address | MH Data)
/// MH Data is the content of the Mobility Header up to and including the mobility SPI field of this option.
/// </summary>
AuthenticationAuthorizationAccountingServer
=
2
,
}
/// <summary>
/// RFC 4285.
/// <pre>
/// +-----+---------------------+
/// | Bit | 0-7 |
/// +-----+---------------------+
/// | 0 | Option Type |
/// +-----+---------------------+
/// | 8 | Opt Data Len |
/// +-----+---------------------+
/// | 16 | Subtype |
/// +-----+---------------------+
/// | 24 | Mobility SPI |
/// | | |
/// | | |
/// | | |
/// +-----+---------------------+
/// | 56 | Authentication Data |
/// | ... | |
/// +-----+---------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
Authentication
)]
public
class
IpV6MobilityOptionAuthentication
:
IpV6MobilityOptionComplex
{
private
static
class
Offset
{
public
const
int
Subtype
=
0
;
public
const
int
MobilitySecurityParameterIndex
=
Subtype
+
sizeof
(
byte
);
public
const
int
AuthenticationData
=
MobilitySecurityParameterIndex
+
sizeof
(
uint
);
}
public
const
int
OptionDataMiniumLength
=
Offset
.
AuthenticationData
;
public
IpV6MobilityOptionAuthentication
(
IpV6AuthenticationSubtype
subtype
,
uint
mobilitySecurityParameterIndex
,
DataSegment
authenticationData
)
:
base
(
IpV6MobilityOptionType
.
Authentication
)
{
Subtype
=
subtype
;
MobilitySecurityParameterIndex
=
mobilitySecurityParameterIndex
;
AuthenticationData
=
authenticationData
;
}
/// <summary>
/// A number assigned to identify the entity and/or mechanism to be used to authenticate the message.
/// </summary>
public
IpV6AuthenticationSubtype
Subtype
{
get
;
private
set
;
}
/// <summary>
/// A number in the range [0-4294967296] used to index into the shared-key-based mobility security associations.
/// </summary>
public
uint
MobilitySecurityParameterIndex
{
get
;
private
set
;
}
/// <summary>
/// Has the information to authenticate the relevant mobility entity.
/// This protects the message beginning at the Mobility Header up to and including the mobility SPI field.
/// </summary>
public
DataSegment
AuthenticationData
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
<
OptionDataMiniumLength
)
return
null
;
IpV6AuthenticationSubtype
subtype
=
(
IpV6AuthenticationSubtype
)
data
[
Offset
.
Subtype
];
uint
mobilitySecurityParameterIndex
=
data
.
ReadUInt
(
Offset
.
MobilitySecurityParameterIndex
,
Endianity
.
Big
);
DataSegment
authenticationData
=
data
.
Subsegment
(
Offset
.
AuthenticationData
,
data
.
Length
-
Offset
.
AuthenticationData
);
return
new
IpV6MobilityOptionAuthentication
(
subtype
,
mobilitySecurityParameterIndex
,
authenticationData
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataMiniumLength
+
AuthenticationData
.
Length
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
offset
+
Offset
.
Subtype
,
(
byte
)
Subtype
);
buffer
.
Write
(
offset
+
Offset
.
MobilitySecurityParameterIndex
,
MobilitySecurityParameterIndex
,
Endianity
.
Big
);
AuthenticationData
.
Write
(
buffer
,
offset
+
Offset
.
AuthenticationData
);
offset
+=
DataLength
;
}
}
/// <summary>
/// RFC 4285.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Timestamp |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
ReplayProtection
)]
public
class
IpV6MobilityOptionReplayProtection
:
IpV6MobilityOptionComplex
{
public
const
int
OptionDataLength
=
sizeof
(
ulong
);
public
IpV6MobilityOptionReplayProtection
(
ulong
timestamp
)
:
base
(
IpV6MobilityOptionType
.
ReplayProtection
)
{
Timestamp
=
timestamp
;
}
/// <summary>
/// 64 bit timestamp.
/// </summary>
public
ulong
Timestamp
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
ulong
timestamp
=
data
.
ReadULong
(
0
,
Endianity
.
Big
);
return
new
IpV6MobilityOptionReplayProtection
(
timestamp
);
}
internal
override
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
buffer
.
Write
(
ref
offset
,
Timestamp
,
Endianity
.
Big
);
}
}
public
abstract
class
IpV6MobilityOptionEmpty
:
IpV6MobilityOptionComplex
{
public
const
int
OptionDataLength
=
0
;
public
IpV6MobilityOptionEmpty
(
IpV6MobilityOptionType
type
)
:
base
(
type
)
:
base
(
type
)
{
{
Data
=
data
;
}
}
public
DataSegment
Data
{
get
;
private
set
;
}
internal
override
sealed
int
DataLength
{
get
{
return
OptionDataLength
;
}
}
internal
override
sealed
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
CgaParametersRequest
)]
public
class
IpV6MobilityOptionCgaParametersRequest
:
IpV6MobilityOptionEmpty
{
public
IpV6MobilityOptionCgaParametersRequest
()
:
base
(
IpV6MobilityOptionType
.
CgaParametersRequest
)
{
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
{
throw
new
InvalidOperationException
(
"IpV6MobilityOptionUnknown shouldn't be registered."
);
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
return
new
IpV6MobilityOptionCgaParametersRequest
();
}
}
public
abstract
class
IpV6MobilityOptionSingleDataSegmentField
:
IpV6MobilityOptionComplex
{
public
IpV6MobilityOptionSingleDataSegmentField
(
IpV6MobilityOptionType
type
,
DataSegment
value
)
:
base
(
IpV6MobilityOptionType
.
CgaParameters
)
{
Value
=
value
;
}
internal
DataSegment
Value
{
get
;
private
set
;
}
internal
override
sealed
int
DataLength
{
get
{
return
Value
.
Length
;
}
}
internal
override
sealed
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
Value
.
Write
(
buffer
,
ref
offset
);
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | CGA Parameters |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
CgaParameters
)]
public
class
IpV6MobilityOptionCgaParameters
:
IpV6MobilityOptionSingleDataSegmentField
{
public
const
int
OptionDataMaxLength
=
255
;
public
IpV6MobilityOptionCgaParameters
(
DataSegment
cgaParameters
)
:
base
(
IpV6MobilityOptionType
.
CgaParameters
,
cgaParameters
)
{
}
/// <summary>
/// Contains up to 255 bytes of the CGA Parameters data structure defined in RFC 3972.
/// The concatenation of all CGA Parameters options in the order they appear in the Binding Update message
/// must result in the original CGA Parameters data structure.
/// All CGA Parameters options in the Binding Update message except the last one must contain exactly 255 bytes in the CGA Parameters field,
/// and the Option Length field must be set to 255 accordingly.
/// All CGA Parameters options must appear directly one after another, that is,
/// a mobility option of a different type must not be placed in between two CGA Parameters options.
/// </summary>
public
DataSegment
CgaParameters
{
get
{
return
Value
;
}
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
>
OptionDataMaxLength
)
return
null
;
return
new
IpV6MobilityOptionCgaParameters
(
data
);
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Signature |
/// | ... | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
Signature
)]
public
class
IpV6MobilityOptionSignature
:
IpV6MobilityOptionSingleDataSegmentField
{
public
IpV6MobilityOptionSignature
(
DataSegment
signature
)
:
base
(
IpV6MobilityOptionType
.
Signature
,
signature
)
{
}
/// <summary>
/// Contains the mobile or correspondent node's signature, generated with the mobile or correspondent node's private key.
/// </summary>
public
DataSegment
Signature
{
get
{
return
Value
;
}
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
return
new
IpV6MobilityOptionSignature
(
data
);
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+---------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+---------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+---------------+
/// | 16 | Permanent Home Keygen Token |
/// | ... | |
/// +-----+-----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
PermanentHomeKeygenToken
)]
public
class
IpV6MobilityOptionPermanentHomeKeygenToken
:
IpV6MobilityOptionSingleDataSegmentField
{
public
IpV6MobilityOptionPermanentHomeKeygenToken
(
DataSegment
permanentHomeKeygenToken
)
:
base
(
IpV6MobilityOptionType
.
PermanentHomeKeygenToken
,
permanentHomeKeygenToken
)
{
}
/// <summary>
/// Contains the permanent home keygen token generated by the correspondent node.
/// The content of this field must be encrypted with the mobile node's public key.
/// The length of the permanent home keygen token is 8 octets before encryption, though the ciphertext and, hence,
/// the Permanent Home Keygen Token field may be longer.
/// </summary>
public
DataSegment
PermanentHomeKeygenToken
{
get
{
return
Value
;
}
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
return
new
IpV6MobilityOptionPermanentHomeKeygenToken
(
data
);
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
CareOfTestInit
)]
public
class
IpV6MobilityOptionCareOfTestInit
:
IpV6MobilityOptionEmpty
{
public
IpV6MobilityOptionCareOfTestInit
()
:
base
(
IpV6MobilityOptionType
.
CareOfTestInit
)
{
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
return
new
IpV6MobilityOptionCareOfTestInit
();
}
}
/// <summary>
/// RFC 4866.
/// <pre>
/// +-----+-------------+--------------+
/// | Bit | 0-7 | 8-15 |
/// +-----+-------------+--------------+
/// | 0 | Option Type | Opt Data Len |
/// +-----+-------------+--------------+
/// | 16 | Care-of Keygen Token |
/// | | |
/// | | |
/// | | |
/// +-----+----------------------------+
/// </pre>
/// </summary>
[
IpV6MobilityOptionTypeRegistration
(
IpV6MobilityOptionType
.
CareOfTest
)]
public
class
IpV6MobilityOptionCareOfTest
:
IpV6MobilityOptionComplex
{
public
const
int
OptionDataLength
=
sizeof
(
ulong
);
public
IpV6MobilityOptionCareOfTest
(
ulong
careOfKeygenToken
)
:
base
(
IpV6MobilityOptionType
.
CareOfTest
)
{
}
/// <summary>
/// Contains the care-of keygen token generated by the correspondent node.
/// </summary>
public
ulong
CareOfKeygenToken
{
get
;
private
set
;
}
internal
override
IpV6MobilityOption
CreateInstance
(
DataSegment
data
)
{
if
(
data
.
Length
!=
OptionDataLength
)
return
null
;
ulong
careOfKeygenToken
=
data
.
ReadULong
(
0
,
Endianity
.
Big
);
return
new
IpV6MobilityOptionCareOfTest
(
careOfKeygenToken
);
}
}
internal
override
int
DataLength
internal
override
int
DataLength
{
{
get
{
return
Data
.
Length
;
}
get
{
return
OptionData
Length
;
}
}
}
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
internal
override
void
WriteData
(
byte
[]
buffer
,
ref
int
offset
)
{
{
buffer
.
Write
(
ref
offset
,
Data
);
buffer
.
Write
(
ref
offset
,
CareOfKeygenToken
,
Endianity
.
Big
);
}
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment