Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 74 additions & 74 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion etherparse/src/transport/icmp_echo_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
/// node SHOULD also implement an application-layer interface for
/// originating Echo Requests and receiving Echo Replies, for diagnostic
/// purposes.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct IcmpEchoHeader {
/// An identifier to aid in matching Echo Replies to Echo Requests. May be zero.
pub id: u16,
Expand Down
2 changes: 1 addition & 1 deletion etherparse/src/transport/icmpv6/dest_unreachable_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use super::*;
/// that cannot be delivered to its destination address for reasons other
/// than congestion. (An ICMPv6 message MUST NOT be generated if a
/// packet is dropped due to congestion.)
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum DestUnreachableCode {
/// No route to destination
NoRoute = 0,
Expand Down
7 changes: 5 additions & 2 deletions etherparse/src/transport/icmpv6/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ pub use parameter_problem_header::*;
mod time_exceeded_code;
pub use time_exceeded_code::*;

mod neighbour_discovery;
pub use neighbour_discovery::*;
mod neighbor_advertisement_header;
pub use neighbor_advertisement_header::*;

mod router_advertisement_header;
pub use router_advertisement_header::*;

/// The maximum number of bytes/octets the ICMPv6 part of a packet can contain.
///
Expand Down
103 changes: 103 additions & 0 deletions etherparse/src/transport/icmpv6/neighbor_advertisement_header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/// ICMPv6 neighbor advertisement header (part of "Neighbor Discovery Protocol"
/// [RFC 4861](https://datatracker.ietf.org/doc/html/rfc4861)).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct NeighborAdvertisementHeader {
pub router: bool,
pub solicited: bool,
pub r#override: bool,
}

impl NeighborAdvertisementHeader {
/// Mask to read out the "router" flag out of the 5th byte of the ICMPv6 header.
pub const ROUTER_MASK: u8 = 0b10000000;

/// Mask to read out the "solicited" flag out of the 5th byte of the ICMPv6 header.
pub const SOLICITED_MASK: u8 = 0b01000000;

/// Mask to read out the "override" flag out of the 5th byte of the ICMPv6 header.
pub const OVERRIDE_MASK: u8 = 0b00100000;

/// Decodes the header from the on the wire bytes.
pub fn from_bytes(bytes: [u8; 4]) -> Self {
let first_byte = bytes[0];

Self {
router: (first_byte & Self::ROUTER_MASK) == Self::ROUTER_MASK,
solicited: (first_byte & Self::SOLICITED_MASK) == Self::SOLICITED_MASK,
r#override: (first_byte & Self::OVERRIDE_MASK) == Self::OVERRIDE_MASK,
}
}

/// Converts the header to the on the wire bytes.
pub fn to_bytes(&self) -> [u8; 4] {
let mut first_byte = 0u8;

if self.router {
first_byte |= Self::ROUTER_MASK;
}
if self.solicited {
first_byte |= Self::SOLICITED_MASK;
}
if self.r#override {
first_byte |= Self::OVERRIDE_MASK;
}

[first_byte, 0, 0, 0]
}
}

#[cfg(test)]
mod tests {
use super::*;
use proptest::prelude::*;

proptest! {
#[test]
fn to_and_from_bytes(
router in any::<bool>(),
solicited in any::<bool>(),
r#override in any::<bool>()
) {
let bytes = NeighborAdvertisementHeader{
router,
solicited,
r#override
}.to_bytes();
assert_eq!(
NeighborAdvertisementHeader::from_bytes(bytes),
NeighborAdvertisementHeader {
router,
solicited,
r#override,
}
);
}
}

#[test]
fn reads_router_bit_correctly() {
assert!(NeighborAdvertisementHeader::from_bytes([0b10000000, 0, 0, 0]).router);
assert!(!NeighborAdvertisementHeader::from_bytes([0, 0, 0, 0]).router);
}

#[test]
fn reads_solicited_bit_correctly() {
assert!(NeighborAdvertisementHeader::from_bytes([0b01000000, 0, 0, 0]).solicited);
assert!(!NeighborAdvertisementHeader::from_bytes([0, 0, 0, 0]).solicited);
}

#[test]
fn reads_override_bit_correctly() {
assert!(NeighborAdvertisementHeader::from_bytes([0b00100000, 0, 0, 0]).r#override);
assert!(!NeighborAdvertisementHeader::from_bytes([0, 0, 0, 0]).r#override);
}

#[test]
fn reads_combined_bit_correctly() {
let header = NeighborAdvertisementHeader::from_bytes([0b11100000, 0, 0, 0]);

assert!(header.router);
assert!(header.solicited);
assert!(header.r#override);
}
}
70 changes: 0 additions & 70 deletions etherparse/src/transport/icmpv6/neighbour_discovery.rs

This file was deleted.

2 changes: 1 addition & 1 deletion etherparse/src/transport/icmpv6/parameter_problem_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::*;
/// Code values for ICMPv6 parameter problem messages.
///
/// Source: <https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml#icmpv6-parameters-codes-5>
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum ParameterProblemCode {
/// Erroneous header field encountered (from [RFC 4443](https://tools.ietf.org/html/rfc4443))
ErroneousHeaderField = 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

/// ICMPv6 parameter problem header.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct ParameterProblemHeader {
/// The code can offer additional informations about what kind of parameter
/// problem caused the error.
Expand Down
109 changes: 109 additions & 0 deletions etherparse/src/transport/icmpv6/router_advertisement_header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/// ICMPv6 router advertisement header (part of "Neighbor Discovery Protocol"
/// [RFC 4861](https://datatracker.ietf.org/doc/html/rfc4861)).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub struct RouterAdvertisementHeader {
/// The default value that should be placed in the Hop Count
/// field of the IP header for outgoing IP packets.
///
/// A value of zero means unspecified (by this router).
pub cur_hop_limit: u8,

/// "Managed address configuration" flag.
///
/// When set, it indicates that addresses are available via
/// Dynamic Host Configuration Protocol [DHCPv6].
///
/// If the M flag is set, the O flag is redundant and
/// can be ignored because DHCPv6 will return all
/// available configuration information.
pub managed_address_config: bool,

/// "Other configuration" flag.
///
/// When set, it indicates that other configuration information
/// is available via DHCPv6. Examples of such information are
/// DNS-related information or information on other servers
/// within the network.
pub other_config: bool,

/// The lifetime associated with the default router in units of
/// seconds.
///
/// The field can contain values up to 65535 and receivers should
/// handle any value, while the sending rules in Section 6 of
/// [RFC 4861](https://datatracker.ietf.org/doc/html/rfc4861) limit
/// the lifetime to 9000 seconds. A Lifetime of 0 indicates that
/// the router is not a default router and SHOULD NOT appear on
/// the default router list. The Router Lifetime applies only to
/// the router's usefulness as a default router; it does not apply
/// to information contained in other message fields or options.
/// Options that need time limits for their information include
/// their own lifetime fields.
pub router_lifetime: u16,
}

impl RouterAdvertisementHeader {
/// Mask to read out the "Managed Address Configuration" flag out of
/// the 5th byte of the ICMPv6 header.
pub const MANAGED_ADDRESS_CONFIG_MASK: u8 = 0b1000_0000;

/// Mask to read out the "Other Configuration" flag out of the 5th
/// byte of the ICMPv6 header.
pub const OTHER_CONFIG_MASK: u8 = 0b0100_0000;

/// Decodes the header from the on the wire bytes.
pub fn from_bytes(bytes: [u8; 4]) -> Self {
RouterAdvertisementHeader {
cur_hop_limit: bytes[0],
managed_address_config: 0 != bytes[1] & Self::MANAGED_ADDRESS_CONFIG_MASK,
other_config: 0 != bytes[1] & Self::OTHER_CONFIG_MASK,
router_lifetime: u16::from_be_bytes([bytes[2], bytes[3]]),
}
}

/// Converts the header to the on the wire bytes.
pub fn to_bytes(&self) -> [u8; 4] {
let rl_be = self.router_lifetime.to_be_bytes();
[
self.cur_hop_limit,
(if self.managed_address_config {
Self::MANAGED_ADDRESS_CONFIG_MASK
} else {
0
} | if self.other_config {
Self::OTHER_CONFIG_MASK
} else {
0
}),
rl_be[0],
rl_be[1],
]
}
}

#[cfg(test)]
mod test {
use super::*;
use proptest::prelude::*;

proptest! {
#[test]
fn to_and_from_bytes(
cur_hop_limit in any::<u8>(),
managed_address_config in any::<bool>(),
other_config in any::<bool>(),
router_lifetime in any::<u16>()
) {
let expected = RouterAdvertisementHeader{
cur_hop_limit,
managed_address_config,
other_config,
router_lifetime
};
let actual = RouterAdvertisementHeader::from_bytes(
expected.to_bytes()
);
assert_eq!(actual, expected);
}
}
}
2 changes: 1 addition & 1 deletion etherparse/src/transport/icmpv6/time_exceeded_code.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;

/// Code values for ICMPv6 time exceeded message.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum TimeExceededCode {
/// "hop limit exceeded in transit"
HopLimitExceeded = 0,
Expand Down
Loading
Loading