#[non_exhaustive]pub enum NdpOption {
Generic {
ty: u8,
value: Vec<u8>,
length: Option<u8>,
},
Unknown {
ty: u8,
bytes: Vec<u8>,
length: Option<u8>,
},
}Expand description
A single Neighbor Discovery option (RFC 4861 section 4.6).
This is the framework-level representation: a {type, value-bytes} option
with the length field auto-filled (or preserved verbatim when set on
purpose). Self::Generic holds a recognized option type with its raw
value bytes, and Self::Unknown preserves an unrecognized option’s value
bytes byte-for-byte so they round-trip. Both carry an optional explicit
length override so a deliberately-wrong length survives encode().
Typed option views and constructors (Source/Target Link-Layer Address,
Prefix Information, MTU, …) build on top of this representation in later
steps; this enum is #[non_exhaustive] so those variants can be added
without breaking the framework’s callers.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Generic
A recognized option type carried as raw value bytes (the bytes after the
two-byte Type/Length header), with the length field auto-filled unless
length is set.
Fields
ty: u8Option type codepoint (a recognized ndp_option_type_is_known
value).
Unknown
An unrecognized option type, preserved verbatim so its bytes round-trip unchanged.
Implementations§
Source§impl NdpOption
impl NdpOption
Sourcepub fn generic(ty: u8, value: impl Into<Vec<u8>>) -> Self
pub fn generic(ty: u8, value: impl Into<Vec<u8>>) -> Self
Build a recognized-type option from its type codepoint and raw value bytes, with the length field auto-filled on encode.
Sourcepub fn unknown(ty: u8, bytes: impl Into<Vec<u8>>) -> Self
pub fn unknown(ty: u8, bytes: impl Into<Vec<u8>>) -> Self
Build an unrecognized-type option whose bytes are preserved verbatim, with the length field auto-filled on encode.
Sourcepub fn source_link_layer_address(mac: MacAddr) -> Self
pub fn source_link_layer_address(mac: MacAddr) -> Self
Build a Source Link-Layer Address option (type 1) carrying an Ethernet / IEEE 802 (48-bit) MAC address.
RFC 4861 section 4.6.1: the option contains the link-layer address of the
sender of the packet. For IEEE 802 addresses the option occupies one
8-octet unit — a two-byte Type/Length header plus the six-byte address —
so the auto-filled length is 1. This is a typed constructor over the
framework: it produces a NdpOption::Generic whose six value bytes are
the MAC, so it round-trips through NdpOptions exactly like any other
recognized option, and NdpOption::link_layer_address reads it back.
Sourcepub fn target_link_layer_address(mac: MacAddr) -> Self
pub fn target_link_layer_address(mac: MacAddr) -> Self
Build a Target Link-Layer Address option (type 2) carrying an Ethernet / IEEE 802 (48-bit) MAC address.
RFC 4861 section 4.6.1: the option contains the link-layer address of the target; it shares the Source Link-Layer Address layout and is used by Neighbor and Router Advertisements (modeled in later steps). Provided here alongside the source option so both link-layer-address codepoints share one typed constructor/accessor pair.
Sourcepub fn link_layer_address(&self) -> Option<MacAddr>
pub fn link_layer_address(&self) -> Option<MacAddr>
Read the Ethernet / IEEE 802 (48-bit) MAC carried by a Source (type 1) or Target (type 2) Link-Layer Address option.
Returns None when the option is not a link-layer-address option or when
its value does not hold a full six-byte IEEE 802 address (for example a
non-Ethernet link layer with a different address width, or a truncated
option). The first six value bytes are interpreted as the address, which
matches the RFC 4861 section 4.6.1 Ethernet layout (length 1, no padding).
Sourcepub fn prefix_information(
prefix: Ipv6Addr,
prefix_len: u8,
on_link: bool,
autonomous: bool,
valid_lifetime: u32,
preferred_lifetime: u32,
) -> Self
pub fn prefix_information( prefix: Ipv6Addr, prefix_len: u8, on_link: bool, autonomous: bool, valid_lifetime: u32, preferred_lifetime: u32, ) -> Self
Build a Prefix Information option (type 3) carrying an IPv6 prefix and the SLAAC-relevant lifetimes and flags (RFC 4861 section 4.6.2).
The 30-byte value (everything after the two-byte Type/Length header) is laid out per RFC 4861 section 4.6.2:
Prefix Length (1) | Flags (1: L|A|Reserved1) |
Valid Lifetime (4) | Preferred Lifetime (4) | Reserved2 (4) | Prefix (16)With the two-byte header that is exactly 32 bytes — four 8-octet units —
so the auto-filled Length is 4 (NDP_PREFIX_INFORMATION_UNITS) and no
padding is needed. This is a typed constructor over the framework: it
produces a NdpOption::Generic whose value bytes are the option fields,
so it round-trips through NdpOptions exactly like any other recognized
option, and the NdpOption::prefix / NdpOption::prefix_length /
NdpOption::prefix_on_link / NdpOption::prefix_autonomous /
NdpOption::prefix_valid_lifetime /
NdpOption::prefix_preferred_lifetime accessors read each field back.
on_link sets the L flag (RFC 4861 sec 4.6.2: prefix usable for on-link
determination); autonomous sets the A flag (RFC 4862 sec 5.5.3: prefix
usable for stateless address autoconfiguration). The two flags are
independent. The six Reserved1 bits and the 32-bit Reserved2 field are sent
zero; NdpOption::prefix_reserved1 / NdpOption::prefix_reserved2
read them back, and NdpOption::prefix_information_raw sets them on
purpose. Lifetimes are in seconds; NDP_PREFIX_LIFETIME_INFINITY
(0xffffffff) means infinity.
Sourcepub fn prefix_information_raw(
prefix: Ipv6Addr,
prefix_len: u8,
flags: u8,
valid_lifetime: u32,
preferred_lifetime: u32,
reserved2: u32,
) -> Self
pub fn prefix_information_raw( prefix: Ipv6Addr, prefix_len: u8, flags: u8, valid_lifetime: u32, preferred_lifetime: u32, reserved2: u32, ) -> Self
Build a Prefix Information option (type 3) with the full flags octet and Reserved2 field set explicitly (RFC 4861 section 4.6.2).
This is the honored-overrides escape hatch behind
NdpOption::prefix_information: it writes the flags octet
(L | A | the six Reserved1 bits) and the 32-bit reserved2 field verbatim,
so an agent can set the Reserved1 bits or Reserved2 — which RFC 4861 says to
send as zero — on purpose, for a forward-compatible or deliberately
malformed packet. Those values survive an encode/decode round-trip
untouched.
Sourcepub fn prefix_length(&self) -> Option<u8>
pub fn prefix_length(&self) -> Option<u8>
Read the Prefix Length field (0..=128) of a Prefix Information option
(type 3), or None for any other option or a truncated value.
Sourcepub fn prefix_on_link(&self) -> Option<bool>
pub fn prefix_on_link(&self) -> Option<bool>
Read the on-link (L) flag of a Prefix Information option (type 3), or
None for any other option or a truncated value (RFC 4861 sec 4.6.2).
Sourcepub fn prefix_autonomous(&self) -> Option<bool>
pub fn prefix_autonomous(&self) -> Option<bool>
Read the autonomous address-configuration (A) flag of a Prefix Information
option (type 3), or None for any other option or a truncated value
(RFC 4861 sec 4.6.2 / RFC 4862 sec 5.5.3).
Sourcepub fn prefix_reserved1(&self) -> Option<u8>
pub fn prefix_reserved1(&self) -> Option<u8>
Read the six Reserved1 bits (the low six bits of the flags octet) of a
Prefix Information option (type 3), preserved verbatim, or None for any
other option or a truncated value (RFC 4861 sec 4.6.2).
Sourcepub fn prefix_valid_lifetime(&self) -> Option<u32>
pub fn prefix_valid_lifetime(&self) -> Option<u32>
Read the Valid Lifetime (seconds; 0xffffffff = infinity) of a Prefix
Information option (type 3), or None for any other option or a truncated
value (RFC 4861 sec 4.6.2).
Sourcepub fn prefix_preferred_lifetime(&self) -> Option<u32>
pub fn prefix_preferred_lifetime(&self) -> Option<u32>
Read the Preferred Lifetime (seconds; 0xffffffff = infinity) of a Prefix
Information option (type 3), or None for any other option or a truncated
value (RFC 4861 sec 4.6.2).
Sourcepub fn prefix_reserved2(&self) -> Option<u32>
pub fn prefix_reserved2(&self) -> Option<u32>
Read the 32-bit Reserved2 field of a Prefix Information option (type 3),
preserved verbatim, or None for any other option or a truncated value
(RFC 4861 sec 4.6.2).
Sourcepub fn prefix(&self) -> Option<Ipv6Addr>
pub fn prefix(&self) -> Option<Ipv6Addr>
Read the Prefix (128-bit IPv6 address/prefix) of a Prefix Information
option (type 3), or None for any other option or a truncated value
(RFC 4861 sec 4.6.2).
Sourcepub fn mtu(mtu: u32) -> Self
pub fn mtu(mtu: u32) -> Self
Build an MTU option (type 5) carrying the recommended link MTU (RFC 4861 section 4.6.4).
The 6-byte value (after the two-byte Type/Length header) is a 16-bit
Reserved field (sent zero) followed by the 32-bit MTU, giving exactly one
8-octet unit — so the auto-filled Length is 1
(NDP_MTU_OPTION_UNITS). This is a typed constructor over the framework:
it produces a NdpOption::Generic and NdpOption::mtu_value reads the
MTU back.
Sourcepub fn mtu_value(&self) -> Option<u32>
pub fn mtu_value(&self) -> Option<u32>
Read the MTU (octets) carried by an MTU option (type 5), or None for any
other option or a truncated value (RFC 4861 section 4.6.4).
Sourcepub fn redirected_header(original_packet: &[u8]) -> Self
pub fn redirected_header(original_packet: &[u8]) -> Self
Build a Redirected Header option (type 4) carrying as much of the original
packet that triggered a Redirect as original_packet supplies (RFC 4861
section 4.6.3).
The value (everything after the two-byte Type/Length header) is laid out per RFC 4861 section 4.6.3:
Reserved (6 octets, sent zero) | IP header + dataThe “IP header + data” is the original datagram (its IPv6 header and as
much of the payload as fits); RFC 4861 section 4.6.3 truncates it “to
ensure that the size of the redirect message does not exceed the minimum
MTU required to support IPv6”. crafter preserves whatever bytes the
caller passes verbatim — the embedded portion is opaque, so no decode is
required — and the framework auto-fills the option Length to the next
8-octet boundary, zero-padding the embedded bytes to fill the last unit.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the six Reserved octets
followed by the embedded packet, so it round-trips through NdpOptions
exactly like any other recognized option, and
NdpOption::redirected_header_data reads the embedded bytes back.
The 6-octet Reserved area (a 16-bit field in the first word and a 32-bit
field in the second) is sent zero per RFC 4861 section 4.6.3; to set it on
purpose, build the option with NdpOption::generic and a hand-laid value.
Sourcepub fn redirected_header_data(&self) -> Option<&[u8]>
pub fn redirected_header_data(&self) -> Option<&[u8]>
Read the embedded “IP header + data” of a Redirected Header option (type 4): the bytes after the 6-octet Reserved area (RFC 4861 section 4.6.3).
Returns None for any other option, or when the value is too short to hold
the 6-octet Reserved area. The returned slice is the embedded original
packet exactly as carried on the wire, including any zero padding the
option Length auto-fill appended to reach the 8-octet boundary — callers
that need the unpadded original must track its length out of band, since
RFC 4861 section 4.6.3 does not record the embedded length in the option.
Sourcepub fn route_information(
prefix: Ipv6Addr,
prefix_len: u8,
preference: Prf,
route_lifetime: u32,
) -> Self
pub fn route_information( prefix: Ipv6Addr, prefix_len: u8, preference: Prf, route_lifetime: u32, ) -> Self
Build a Route Information option (type 24) advertising a more-specific route and its preference (RFC 4191 section 2.3).
The number of 8-octet units the option occupies is chosen from
prefix_len, per RFC 4191 section 2.3 (“The Prefix field is 0, 8, or 16
octets depending on Length”, and the Length field “is 1, 2, or 3 depending
on the Prefix Length”):
prefix_len == 0→Length1, no Prefix octets (a default-route preference);1..=64→Length2, the high 8 octets of the prefix;65..=128→Length3, the full 16-octet prefix.
The encoded value (after the two-byte Type/Length header) is laid out per RFC 4191 section 2.3:
Prefix Length (1) | Resvd|Prf|Resvd (1) | Route Lifetime (4) | Prefix (0/8/16)where the flags byte carries the Prf preference in bits 0x18
(NDP_PRF_MASK) and all other bits Reserved (sent zero). The prefix is
truncated to the number of octets the chosen Length carries, so only the
leading bits that prefix_len covers are placed on the wire (RFC 4191
section 2.3: “The bits in the prefix after the prefix length are reserved
and MUST be initialized to zero by the sender and ignored by the
receiver”). route_lifetime is in seconds;
NDP_ROUTE_LIFETIME_INFINITY (0xffffffff) means infinity.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the option fields, so it
round-trips through NdpOptions exactly like any other recognized
option, and NdpOption::route_prefix /
NdpOption::route_prefix_length / NdpOption::route_preference /
NdpOption::route_lifetime read each field back. To choose the encoded
Length (and therefore the carried prefix octets) independently of
prefix_len, or to set the Reserved bits on purpose, use
NdpOption::route_information_raw.
Sourcepub fn route_information_raw(
prefix: Ipv6Addr,
prefix_len: u8,
flags: u8,
route_lifetime: u32,
prefix_octets: usize,
) -> Self
pub fn route_information_raw( prefix: Ipv6Addr, prefix_len: u8, flags: u8, route_lifetime: u32, prefix_octets: usize, ) -> Self
Build a Route Information option (type 24) with the full flags byte and an explicit number of carried prefix octets (RFC 4191 section 2.3).
This is the honored-overrides escape hatch behind
NdpOption::route_information: flags is written verbatim (so the Prf
bits and the Reserved bits — which RFC 4191 says to send as zero — survive
untouched, for a forward-compatible or deliberately malformed packet), and
prefix_octets selects exactly how many leading octets of prefix are
placed on the wire. prefix_octets is clamped to 16; passing 0, 8, or 16
yields the RFC 4191 section 2.3 Length 1/2/3 forms (the auto-filled
option Length rounds the whole option up to the 8-octet boundary). Any
carried prefix octets beyond prefix_octets are dropped; if prefix_octets
is not a multiple of 8, the framework’s length auto-fill zero-pads the value
up to the next unit.
Sourcepub fn route_prefix_length(&self) -> Option<u8>
pub fn route_prefix_length(&self) -> Option<u8>
Read the Prefix Length field (0..=128) of a Route Information option (type
24), or None for any other option or a truncated value (RFC 4191 sec
2.3).
Sourcepub fn route_preference(&self) -> Option<Prf>
pub fn route_preference(&self) -> Option<Prf>
Read the Route Preference (Prf) of a Route Information option (type 24),
decoded from the 0x18 bits of the flags byte (RFC 4191 sec 2.3), or
None for any other option or a truncated value.
Sourcepub fn route_lifetime(&self) -> Option<u32>
pub fn route_lifetime(&self) -> Option<u32>
Read the Route Lifetime (seconds; 0xffffffff = infinity) of a Route
Information option (type 24), or None for any other option or a truncated
value (RFC 4191 sec 2.3).
Sourcepub fn route_prefix(&self) -> Option<Ipv6Addr>
pub fn route_prefix(&self) -> Option<Ipv6Addr>
Read the Prefix carried by a Route Information option (type 24) as a full
128-bit Ipv6Addr, zero-extending the trailing octets that the option’s
Length form did not carry (RFC 4191 sec 2.3: a Length-1 option carries no
prefix octets, Length-2 the high 8, Length-3 all 16).
Returns None for any other option or a value too short to hold the
6-octet fixed head (Prefix Length, flags, Route Lifetime). The carried
prefix octets are taken verbatim and the rest are zero — matching the wire,
where the bits beyond the prefix length are reserved and sent zero.
Sourcepub fn rdnss(lifetime: u32, servers: &[Ipv6Addr]) -> Self
pub fn rdnss(lifetime: u32, servers: &[Ipv6Addr]) -> Self
Build a Recursive DNS Server (RDNSS) option (type 25) advertising one or more recursive DNS resolvers and the lifetime over which they may be used (RFC 8106 section 5.1).
The value (everything after the two-byte Type/Length header) is laid out per RFC 8106 section 5.1:
Reserved (2, sent zero) | Lifetime (4) | Address[0..n] (16 each)With the two-byte header that is 8 + 16 * n bytes — exactly 1 + 2 * n
8-octet units (ndp_rdnss_length_units) — so no padding is needed and
the framework’s auto-fill produces the RFC’s “minimum value is 3 if one
IPv6 address” length. lifetime is in seconds;
NDP_DNS_LIFETIME_INFINITY (0xffffffff) means infinity and a value of
zero means the addresses MUST no longer be used.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the option fields, so it
round-trips through NdpOptions exactly like any other recognized
option, and NdpOption::rdnss_lifetime / NdpOption::rdnss_servers
read the fields back. RFC 8106 section 5.1 says the option SHOULD carry at
least one address, but crafter does not reject an empty list so an agent
can emit a deliberately malformed option to exercise a parser.
Sourcepub fn rdnss_lifetime(&self) -> Option<u32>
pub fn rdnss_lifetime(&self) -> Option<u32>
Read the Lifetime (seconds; 0xffffffff = infinity, 0 = no longer use)
of an RDNSS option (type 25), or None for any other option or a value
too short to hold the Reserved + Lifetime head (RFC 8106 section 5.1).
Sourcepub fn rdnss_servers(&self) -> Option<Vec<Ipv6Addr>>
pub fn rdnss_servers(&self) -> Option<Vec<Ipv6Addr>>
Read the recursive DNS server addresses carried by an RDNSS option (type
25), in order, or None for any other option (RFC 8106 section 5.1).
Returns an empty Vec for a well-formed option that carries no addresses.
Any trailing bytes that do not form a complete 16-byte address (a
truncated or padded value) are ignored, so the accessor never panics on a
malformed option.
Sourcepub fn dnssl<S: AsRef<str>>(lifetime: u32, domains: &[S]) -> Self
pub fn dnssl<S: AsRef<str>>(lifetime: u32, domains: &[S]) -> Self
Build a DNS Search List (DNSSL) option (type 31) advertising one or more DNS search-list domain names and the lifetime over which they may be used (RFC 8106 section 5.2).
The value (everything after the two-byte Type/Length header) is laid out per RFC 8106 section 5.2:
Reserved (2, sent zero) | Lifetime (4) | Domain Names | zero paddingEach domain name is encoded with the crate’s existing RFC 1035 Section 3.1
label codec (DnsName::encode_uncompressed) — length-prefixed labels
terminated by a zero-length (root) label, without compression pointers,
exactly as RFC 8106 section 5.2 requires (“MUST be encoded as described in
Section 3.1 of RFC 1035” and “MUST NOT be encoded in the compressed
form”). The concatenated names are then zero-padded so the whole value
reaches a multiple of 8 octets; the framework’s Self::encode length
auto-fill performs that padding (the trailing zero octets are
indistinguishable from extra root labels, which RFC 8106 section 5.2 notes
a parser must tolerate). lifetime is in seconds;
NDP_DNS_LIFETIME_INFINITY (0xffffffff) means infinity and zero means
the domain names MUST no longer be used.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the option fields, and
NdpOption::dnssl_lifetime / NdpOption::dnssl_domains read the
fields back. A domain string that does not parse as an RFC 1035 name (an
over-long label or name) is skipped rather than aborting the build, so the
infallible builder call sites keep composing; use
NdpOption::dnssl_checked when an encoding error is meaningful.
Sourcepub fn dnssl_checked<S: AsRef<str>>(
lifetime: u32,
domains: &[S],
) -> Result<Self>
pub fn dnssl_checked<S: AsRef<str>>( lifetime: u32, domains: &[S], ) -> Result<Self>
Build a DNS Search List (DNSSL) option (type 31), surfacing an RFC 1035 name-encoding error instead of silently skipping the offending domain (RFC 8106 section 5.2).
This is the fallible form behind NdpOption::dnssl: each domain is
parsed and encoded with DnsName::encode_uncompressed, and the first
label/name that violates the RFC 1035 length bounds returns a structured
CrafterError.
Sourcepub fn dnssl_lifetime(&self) -> Option<u32>
pub fn dnssl_lifetime(&self) -> Option<u32>
Read the Lifetime (seconds; 0xffffffff = infinity, 0 = no longer use)
of a DNSSL option (type 31), or None for any other option or a value too
short to hold the Reserved + Lifetime head (RFC 8106 section 5.2).
Sourcepub fn dnssl_domains(&self) -> Option<Vec<String>>
pub fn dnssl_domains(&self) -> Option<Vec<String>>
Read the DNS search-list domain names carried by a DNSSL option (type 31), in order, as canonical trailing-dot presentation strings (RFC 8106 section 5.2).
Returns None for any other option. The names are decoded with the
crate’s RFC 1035 Section 3.1 label codec
(crate::protocols::dns::decode_dns_name_typed, no compression in this
context). Decoding stops at the trailing zero padding: RFC 8106 section
5.2 pads the value to the 8-octet boundary with zero octets, which decode
as empty (root) names, so a zero-length name marks the end of the real
search list and is not reported. A name that runs past the option value
(a truncated/malformed option) ends the walk without a panic, returning the
names decoded so far.
Sourcepub fn ra_flags_extension(bits: [u8; 6]) -> Self
pub fn ra_flags_extension(bits: [u8; 6]) -> Self
Build an RA Flags Extension option (type 26) carrying the 48-bit Bit Fields area that extends the Router Advertisement flags (RFC 5175 section 4). NDP option family: RaFlagsExtension.
RFC 5175 section 4: the Router Advertisement flags byte has room for only
eight flags, so this option carries 48 more flag bits “available for
assignment”, numbered 8..=55 (continuing the RA flags). The option is
exactly one 8-octet unit — a two-byte Type/Length header plus the six
Bit Fields octets — so the auto-filled Length is 1
(NDP_RA_FLAGS_EXTENSION_UNITS) and no padding is needed. crafter
treats the Bit Fields area as a six-byte raw bitfield the agent sets and
inspects directly; no individual extension flags are assigned yet (the
registry leaves them unallocated), so the caller carries whatever bits it
needs.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose six value bytes are bits, so it round-trips
through NdpOptions exactly like any other recognized option, and
NdpOption::ra_flags_extension_bits reads the bytes back.
Sourcepub fn ra_flags_extension_bits(&self) -> Option<[u8; 6]>
pub fn ra_flags_extension_bits(&self) -> Option<[u8; 6]>
Read the 48-bit Bit Fields area of an RA Flags Extension option (type 26)
as a six-byte array, or None for any other option or a value too short
to hold the six octets (RFC 5175 section 4).
Sourcepub fn nonce(nonce: &[u8]) -> Self
pub fn nonce(nonce: &[u8]) -> Self
Build a Nonce option (type 14) carrying the random nonce SEND and RFC 7527 Enhanced DAD use to detect looped-back solicitations (RFC 3971 section 5.3.2).
RFC 3971 section 5.3.2: the option is “Type, Length, and Nonce fields”
and “The length of the random number MUST be at least 6 bytes. The length
of the random number MUST be selected so that the length of the nonce
option is a multiple of 8 octets.” There is no separate nonce-length
subfield: the option’s Length (in 8-octet units) governs the whole
option, and the nonce occupies everything after the two-byte Type/Length
header.
crafter stores the caller’s nonce bytes verbatim and lets the
framework auto-fill the option Length, zero-padding the value to the
next 8-octet boundary on Self::encode. Because RFC 3971 records no
nonce length separately, NdpOption::nonce_value returns the whole
value area on decode — including any zero padding the boundary alignment
appended — so a caller that needs the exact original nonce must track its
length out of band. crafter does not enforce the 6-byte minimum, so an
agent can emit a deliberately short nonce to exercise a parser.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the nonce, so it round-trips
through NdpOptions exactly like any other recognized option.
Sourcepub fn nonce_value(&self) -> Option<&[u8]>
pub fn nonce_value(&self) -> Option<&[u8]>
Read the Nonce value carried by a Nonce option (type 14): the whole value area after the two-byte Type/Length header (RFC 3971 section 5.3.2).
Returns None for any other option. RFC 3971 section 5.3.2 records no
separate nonce-length field, so the returned slice is the entire value
area — on a decoded option that includes whatever zero padding the option
Length carried to reach the 8-octet boundary. A caller that needs the
unpadded nonce must know its length out of band.
Sourcepub fn pref64(
scaled_lifetime: u16,
prefix_length: u8,
prefix: Ipv6Addr,
) -> Result<Self>
pub fn pref64( scaled_lifetime: u16, prefix_length: u8, prefix: Ipv6Addr, ) -> Result<Self>
Build a PREF64 option (type 38) advertising a NAT64 prefix and the scaled lifetime over which it is valid (RFC 8781 section 4).
The value (everything after the two-byte Type/Length header) is laid out per RFC 8781 section 4:
Scaled Lifetime (13 bits) | PLC (3 bits) | Highest 96 Bits of Prefix (12 octets)With the two-byte header that is exactly 16 bytes — two 8-octet units —
so the auto-filled Length is 2 (NDP_PREF64_UNITS) and no padding is
needed. scaled_lifetime is a 13-bit unsigned value in units of 8 seconds
(RFC 8781 sec 4); it is masked to 13 bits (NDP_PREF64_SCALED_LIFETIME_MAX).
prefix_length is the NAT64 prefix length in bits and MUST be one of the
six RFC 8781 section 4 lengths (96, 64, 56, 48, 40, 32) — any other value
returns a structured CrafterError; use NdpOption::pref64_raw to
emit a reserved PLC code on purpose. Only the high 96 bits of prefix are
placed on the wire; the low 32 bits are dropped per the option layout.
This is a typed constructor over the framework: it produces a
NdpOption::Generic whose value bytes are the option fields, so it
round-trips through NdpOptions exactly like any other recognized
option, and NdpOption::pref64_scaled_lifetime /
NdpOption::pref64_prefix_length / NdpOption::pref64_plc /
NdpOption::pref64_prefix read each field back.
Sourcepub fn pref64_raw(scaled_lifetime: u16, plc: u8, prefix: Ipv6Addr) -> Self
pub fn pref64_raw(scaled_lifetime: u16, plc: u8, prefix: Ipv6Addr) -> Self
Build a PREF64 option (type 38) with an explicit raw PLC (Prefix Length Code) value (RFC 8781 section 4).
This is the honored-overrides escape hatch behind NdpOption::pref64:
plc is written verbatim into the low three bits of the first 16-bit
word, so an agent can emit a reserved PLC code (6 or 7) — which RFC 8781
section 4 does not assign — on purpose for a forward-compatible or
deliberately malformed packet. scaled_lifetime is masked to its 13-bit
field and plc to its 3-bit field; only the high 96 bits of prefix are
carried.
Sourcepub fn pref64_scaled_lifetime(&self) -> Option<u16>
pub fn pref64_scaled_lifetime(&self) -> Option<u16>
Read the 13-bit Scaled Lifetime field (units of 8 seconds) of a PREF64
option (type 38), or None for any other option or a truncated value
(RFC 8781 section 4).
Sourcepub fn pref64_plc(&self) -> Option<Pref64Plc>
pub fn pref64_plc(&self) -> Option<Pref64Plc>
Read the PLC (Prefix Length Code) of a PREF64 option (type 38) as a
typed Pref64Plc, or None for any other option or a truncated value
(RFC 8781 section 4).
Sourcepub fn pref64_prefix_length(&self) -> Option<u8>
pub fn pref64_prefix_length(&self) -> Option<u8>
Read the NAT64 prefix length, in bits, of a PREF64 option (type 38),
decoded from its PLC (RFC 8781 section 4), or None for any other option,
a truncated value, or a reserved PLC code (6 or 7) that maps to no
assigned length.
Sourcepub fn pref64_prefix(&self) -> Option<Ipv6Addr>
pub fn pref64_prefix(&self) -> Option<Ipv6Addr>
Read the NAT64 prefix carried by a PREF64 option (type 38) as a full
128-bit Ipv6Addr, zero-extending the low 32 bits the option does not
carry (RFC 8781 section 4: only the high 96 bits are on the wire).
Returns None for any other option or a value too short to hold the
16-bit word plus the 12-octet prefix.
Sourcepub fn captive_portal(uri: &str) -> Self
pub fn captive_portal(uri: &str) -> Self
Build a Captive Portal option (type 37) carrying the URI of the captive portal API endpoint (RFC 8910 section 2.3). NDP option family: CaptivePortal.
RFC 8910 section 2.3: the option carries a UTF-8 URI after the two-byte Type/Length header, and “This MUST be padded with NUL (0x00) to make the total option length (including the Type and Length fields) a multiple of 8 bytes.” The URI “is not guaranteed to be null terminated”, so a receiver recovers it by taking the value area (option length minus the two-byte header) and stripping the trailing NUL padding.
crafter stores the URI’s UTF-8 bytes verbatim and lets the framework
auto-fill the option Length, zero (NUL)-padding the value to the next
8-octet boundary on Self::encode. This is a typed constructor over the
framework: it produces a NdpOption::Generic whose value bytes are the
URI, so it round-trips through NdpOptions exactly like any other
recognized option, and NdpOption::captive_portal_uri reads the URI
back, stripping the trailing NUL padding.
Sourcepub fn captive_portal_uri(&self) -> Option<String>
pub fn captive_portal_uri(&self) -> Option<String>
Read the captive portal URI carried by a Captive Portal option (type 37), stripping the trailing NUL padding (RFC 8910 section 2.3).
Returns None for any other option or when the value (after stripping the
trailing NUL bytes) is not valid UTF-8. RFC 8910 section 2.3 pads the URI
with NUL (0x00) to the 8-octet boundary and the URI “is not guaranteed to
be null terminated”, so this accessor strips all trailing NUL octets —
which a well-formed URI never contains internally — before decoding the
remaining bytes as UTF-8.
Sourcepub fn length(self, length: u8) -> Self
pub fn length(self, length: u8) -> Self
Pin the Length field (in units of 8 octets) to an explicit value.
The pinned value is emitted verbatim by Self::encode, even when it
disagrees with the value bytes — generated tools often need a malformed
option to exercise a peer’s parser (the honored-overrides rule). Pass a
fresh option through Self::generic/Self::unknown (or
Self::clear_length) to return to auto-fill.
Sourcepub fn clear_length(self) -> Self
pub fn clear_length(self) -> Self
Drop any explicit Length override so the field auto-fills on encode.
Sourcepub const fn option_type(&self) -> u8
pub const fn option_type(&self) -> u8
Option type codepoint.
Sourcepub fn value(&self) -> &[u8] ⓘ
pub fn value(&self) -> &[u8] ⓘ
Option value bytes (everything after the two-byte Type/Length header).
Sourcepub const fn explicit_length(&self) -> Option<u8>
pub const fn explicit_length(&self) -> Option<u8>
Explicit Length field (in units of 8 octets) when one is pinned, else
None (auto-fill on encode).
Sourcepub fn effective_length(&self) -> Result<u8>
pub fn effective_length(&self) -> Result<u8>
The Length field (in units of 8 octets) that Self::encode will
emit: the pinned value when set, otherwise the auto-filled length that
rounds the whole option up to the next 8-octet boundary.
Returns an error only when the auto-filled length would exceed the
one-byte field’s range (a value longer than 255 * 8 - 2 bytes); a
pinned length is always returned as-is.
Sourcepub fn encoded_len(&self) -> Result<usize>
pub fn encoded_len(&self) -> Result<usize>
Total encoded length of this option in bytes, including the Type/Length header and any zero padding implied by the (auto-filled or pinned) length field.
A pinned length drives the encoded size (the honored-overrides rule), so a deliberately-wrong length yields a deliberately-wrong size.
Sourcepub fn encode(&self) -> Result<Vec<u8>>
pub fn encode(&self) -> Result<Vec<u8>>
Encode this single option to bytes (RFC 4861 section 4.6 layout).
The Length field is auto-filled to round the whole option (header plus
value) up to the next 8-octet boundary, zero-padding the value, unless
the agent pinned a length via Self::length — in which case the
pinned length is emitted verbatim and the value is padded (or, for a too
small pinned length, truncated) to match, so the wrong value survives.
Sourcepub fn encode_into(&self, out: &mut Vec<u8>) -> Result<()>
pub fn encode_into(&self, out: &mut Vec<u8>) -> Result<()>
Append this single encoded option to an existing buffer.
Sourcepub fn decode_one(bytes: &[u8]) -> Result<(Self, usize)>
pub fn decode_one(bytes: &[u8]) -> Result<(Self, usize)>
Decode a single option from the front of bytes, returning the option
and the number of bytes it consumed.
Returns a structured CrafterError (never a panic) when fewer than two
bytes are available, when the Length field is zero (RFC 4861 sec 4.6:
“The value 0 is invalid”), or when the declared length runs past the end
of bytes.
The whole declared option (header plus value, including any padding) is captured as the option’s value bytes so it round-trips verbatim, and the decoded length is pinned on the returned option so re-encoding reproduces the original bytes.