Skip to content

Commit

Permalink
Add Packet support for NDISC packet types
Browse files Browse the repository at this point in the history
Add packet layer support for NDISC packet types.

Closes: #180
Approved by: whitequark
  • Loading branch information
dlrobertson authored and Homu committed Apr 12, 2018
1 parent 27d82a5 commit 4aeeac0
Show file tree
Hide file tree
Showing 3 changed files with 312 additions and 31 deletions.
117 changes: 86 additions & 31 deletions src/wire/icmpv6.rs
Expand Up @@ -10,17 +10,27 @@ enum_with_unknown! {
/// Internet protocol control message type.
pub doc enum Message(u8) {
/// Destination Unreachable.
DstUnreachable = 0x01,
DstUnreachable = 0x01,
/// Packet Too Big.
PktTooBig = 0x02,
PktTooBig = 0x02,
/// Time Exceeded.
TimeExceeded = 0x03,
TimeExceeded = 0x03,
/// Parameter Problem.
ParamProblem = 0x04,
ParamProblem = 0x04,
/// Echo Request
EchoRequest = 0x80,
EchoRequest = 0x80,
/// Echo Reply
EchoReply = 0x81
EchoReply = 0x81,
/// Router Solicitation
RouterSolicit = 0x85,
/// Router Advertisement
RouterAdvert = 0x86,
/// Neighbor Solicitation
NeighborSolicit = 0x87,
/// Neighbor Advertisement
NeighborAdvert = 0x88,
/// Redirect
Redirect = 0x89
}
}

Expand All @@ -38,13 +48,18 @@ impl Message {
impl fmt::Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Message::DstUnreachable => write!(f, "destination unreachable"),
&Message::PktTooBig => write!(f, "packet too big"),
&Message::TimeExceeded => write!(f, "time exceeded"),
&Message::ParamProblem => write!(f, "parameter problem"),
&Message::EchoReply => write!(f, "echo reply"),
&Message::EchoRequest => write!(f, "echo request"),
&Message::Unknown(id) => write!(f, "{}", id)
&Message::DstUnreachable => write!(f, "destination unreachable"),
&Message::PktTooBig => write!(f, "packet too big"),
&Message::TimeExceeded => write!(f, "time exceeded"),
&Message::ParamProblem => write!(f, "parameter problem"),
&Message::EchoReply => write!(f, "echo reply"),
&Message::EchoRequest => write!(f, "echo request"),
&Message::RouterSolicit => write!(f, "router solicitation"),
&Message::RouterAdvert => write!(f, "router advertisement"),
&Message::NeighborSolicit => write!(f, "neighbor solicitation"),
&Message::NeighborAdvert => write!(f, "neighbor advert"),
&Message::Redirect => write!(f, "redirect"),
&Message::Unknown(id) => write!(f, "{}", id)
}
}
}
Expand Down Expand Up @@ -145,25 +160,56 @@ impl fmt::Display for TimeExceeded {
/// A read/write wrapper around an Internet Control Message Protocol version 6 packet buffer.
#[derive(Debug, PartialEq, Clone)]
pub struct Packet<T: AsRef<[u8]>> {
buffer: T
pub(super) buffer: T
}

// Ranges and constants describing key boundaries in the ICMPv6 header.
// See https://tools.ietf.org/html/rfc4443 for details.
mod field {
pub(super) mod field {
use wire::field::*;

pub const TYPE: usize = 0;
pub const CODE: usize = 1;
pub const CHECKSUM: Field = 2..4;
pub const TYPE: usize = 0;
pub const CODE: usize = 1;
pub const CHECKSUM: Field = 2..4;

pub const UNUSED: Field = 4..8;
pub const MTU: Field = 4..8;
pub const POINTER: Field = 4..8;
pub const ECHO_IDENT: Field = 4..6;
pub const ECHO_SEQNO: Field = 6..8;
pub const UNUSED: Field = 4..8;
pub const MTU: Field = 4..8;
pub const POINTER: Field = 4..8;
pub const ECHO_IDENT: Field = 4..6;
pub const ECHO_SEQNO: Field = 6..8;

pub const HEADER_END: usize = 8;
pub const HEADER_END: usize = 8;

// Router Advertisement message offsets
pub const CUR_HOP_LIMIT: usize = 4;
pub const ROUTER_FLAGS: usize = 5;
pub const ROUTER_LT: Field = 6..8;
pub const REACHABLE_TM: Field = 8..12;
pub const RETRANS_TM: Field = 12..16;

// Neighbor Solicitation message offsets
pub const TARGET_ADDR: Field = 8..24;

// Neighbor Advertisement message offsets
pub const NEIGH_FLAGS: usize = 4;

// Redirected Header message offsets
pub const DEST_ADDR: Field = 24..40;
}

bitflags! {
pub struct RouterFlags: u8 {
const MANAGED = 0b10000000;
const OTHER = 0b01000000;
}
}

bitflags! {
pub struct NeighborFlags: u8 {
const ROUTER = 0b10000000;
const SOLICITED = 0b01000000;
const OVERRIDE = 0b00100000;
}
}

impl<T: AsRef<[u8]>> Packet<T> {
Expand All @@ -189,7 +235,11 @@ impl<T: AsRef<[u8]>> Packet<T> {
if len < field::HEADER_END {
Err(Error::Truncated)
} else {
Ok(())
if len < self.header_len() {
Err(Error::Truncated)
} else {
Ok(())
}
}
}

Expand Down Expand Up @@ -251,12 +301,17 @@ impl<T: AsRef<[u8]>> Packet<T> {
/// the message type field.
pub fn header_len(&self) -> usize {
match self.msg_type() {
Message::DstUnreachable => field::UNUSED.end,
Message::PktTooBig => field::MTU.end,
Message::TimeExceeded => field::UNUSED.end,
Message::ParamProblem => field::POINTER.end,
Message::EchoRequest => field::ECHO_SEQNO.end,
Message::EchoReply => field::ECHO_SEQNO.end,
Message::DstUnreachable => field::UNUSED.end,
Message::PktTooBig => field::MTU.end,
Message::TimeExceeded => field::UNUSED.end,
Message::ParamProblem => field::POINTER.end,
Message::EchoRequest => field::ECHO_SEQNO.end,
Message::EchoReply => field::ECHO_SEQNO.end,
Message::RouterSolicit => field::UNUSED.end,
Message::RouterAdvert => field::RETRANS_TM.end,
Message::NeighborSolicit => field::TARGET_ADDR.end,
Message::NeighborAdvert => field::TARGET_ADDR.end,
Message::Redirect => field::DEST_ADDR.end,
// For packets that are not included in RFC 4443, do not
// include the last 32 bits of the ICMPv6 header in
// `header_bytes`. This must be done so that these bytes
Expand Down
6 changes: 6 additions & 0 deletions src/wire/mod.rs
Expand Up @@ -98,6 +98,8 @@ mod icmpv6;
#[cfg(feature = "proto-ipv4")]
mod igmp;
#[cfg(feature = "proto-ipv6")]
mod ndisc;
#[cfg(feature = "proto-ipv6")]
mod ndiscoption;
mod udp;
mod tcp;
Expand Down Expand Up @@ -173,6 +175,10 @@ pub use self::icmpv6::{Message as Icmpv6Message,
Packet as Icmpv6Packet,
Repr as Icmpv6Repr};

#[cfg(feature = "proto-ipv6")]
pub use self::icmpv6::{RouterFlags as NdiscRouterFlags,
NeighborFlags as NdiscNeighborFlags};

#[cfg(feature = "proto-ipv6")]
pub use self::ndiscoption::{NdiscOption,
Repr as NdiscOptionRepr,
Expand Down

0 comments on commit 4aeeac0

Please sign in to comment.