diff --git a/examples/ping6.rs b/examples/ping6.rs index c5b73ff..f45aeb0 100644 --- a/examples/ping6.rs +++ b/examples/ping6.rs @@ -19,7 +19,15 @@ pub fn main() { let mut socket6 = IcmpSocket6::new().unwrap(); socket6.bind("::1".parse::().unwrap()).unwrap(); let mut echo_socket = echo::EchoSocket6::new(socket6); - echo_socket.send_ping("::1".parse::().unwrap(), 42, &[]).unwrap(); + echo_socket.send_ping("::1".parse::().unwrap(), 42, &[ + 0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, + 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20, 0x77, 0x6f, + 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, + 0x20, 0x62, 0x75, 0x74, 0x20, 0x61, 0x20, 0x73, + 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, + 0x6b, 0x6e, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, + 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20]).unwrap(); + let _ = echo_socket.recv_ping(); let resp = echo_socket.recv_ping().unwrap(); println!("seq: {}, identifier: {} payload: {}", resp.sequence, resp.identifier, resp.payload.len()); } \ No newline at end of file diff --git a/src/echo.rs b/src/echo.rs index 07f5dd9..2dec637 100644 --- a/src/echo.rs +++ b/src/echo.rs @@ -105,6 +105,7 @@ pub struct EchoSocket6 { impl EchoSocket6 { pub fn new(sock: IcmpSocket6) -> Self { + // TODO(jwall): How to set ICMPv6 filters. EchoSocket6{inner:sock, sequence: 0, buf: Vec::with_capacity(512)} } diff --git a/src/packet.rs b/src/packet.rs index 4fe215a..743f5b2 100644 --- a/src/packet.rs +++ b/src/packet.rs @@ -39,7 +39,7 @@ fn sum_big_endian_words(bs: &[u8]) -> u32 { return sum; } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum Icmpv6Message { // NOTE(JWALL): All of the below integers should be parsed as big endian on the // wire. @@ -300,7 +300,7 @@ impl Icmpv6Packet { /// Construct a packet for Echo Request messages. pub fn with_echo_request(identifier: u16, sequence: u16, payload: Vec) -> Result { Ok(Self { - typ: 4, + typ: 128, code: 0, checksum: 0, message: EchoRequest{ @@ -314,7 +314,7 @@ impl Icmpv6Packet { /// Construct a packet for Echo Reply messages. pub fn with_echo_reply(identifier: u16, sequence: u16, payload: Vec) -> Result { Ok(Self { - typ: 4, + typ: 129, code: 0, checksum: 0, message: EchoReply{ @@ -326,6 +326,7 @@ impl Icmpv6Packet { } } +#[derive(Debug, PartialEq)] pub enum Icmpv6PacketBuildError { InvalidCode(u8), } @@ -349,6 +350,72 @@ impl From for std::io::Error { mod checksum_tests { use super::*; + #[test] + fn packet_construction_echo_request_test() { + let pkt = Icmpv6Packet::with_echo_request(42, 1, vec![1,2,3,4]).unwrap(); + assert_eq!(pkt.typ, 128); + assert_eq!(pkt.code, 0); + assert_eq!(pkt.message, EchoRequest{ + identifier: 42, sequence: 1, payload: vec![1,2,3,4], + }); + } + + #[test] + fn packet_construction_echo_reply_test() { + let pkt = Icmpv6Packet::with_echo_reply(42, 1, vec![1,2,3,4]).unwrap(); + assert_eq!(pkt.typ, 129); + assert_eq!(pkt.code, 0); + assert_eq!(pkt.message, EchoReply{ + identifier: 42, sequence: 1, payload: vec![1,2,3,4], + }); + } + + #[test] + fn packet_construction_too_big_test() { + let pkt = Icmpv6Packet::with_packet_too_big(3, vec![1,2,3,4]).unwrap(); + assert_eq!(pkt.typ, 2); + assert_eq!(pkt.code, 0); + assert_eq!(pkt.message, PacketTooBig{ + mtu: 3, invoking_packet: vec![1,2,3,4], + }); + } + + #[test] + fn packet_construction_time_exceeded() { + let pkt = Icmpv6Packet::with_time_exceeded(0, vec![1,2,3,4]).unwrap(); + assert_eq!(pkt.typ, 3); + assert_eq!(pkt.code, 0); + assert_eq!(pkt.message, TimeExceeded{ + _unused: 0, invoking_packet: vec![1,2,3,4], + }); + } + + #[test] + fn packet_construction_time_exceeded_invalid_code() { + let pkt = Icmpv6Packet::with_time_exceeded(2, vec![1,2,3,4]); + assert!(pkt.is_err()); + let e = pkt.unwrap_err(); + assert_eq!(e, Icmpv6PacketBuildError::InvalidCode(2)); + } + + #[test] + fn packet_construction_parameter_problem() { + let pkt = Icmpv6Packet::with_parameter_problem(0, 30, vec![1,2,3,4,5,6,7,8,9,10]).unwrap(); + assert_eq!(pkt.typ, 4); + assert_eq!(pkt.code, 0); + assert_eq!(pkt.message, ParameterProblem{ + pointer: 30, invoking_packet: vec![1,2,3,4,5,6,7,8,9,10], + }); + } + + #[test] + fn packet_construction_parameter_problem_invalid_code() { + let pkt = Icmpv6Packet::with_parameter_problem(3, 30, vec![1,2,3,4]); + assert!(pkt.is_err()); + let e = pkt.unwrap_err(); + assert_eq!(e, Icmpv6PacketBuildError::InvalidCode(3)); + } + #[test] fn echo_packet_parse_test() { // NOTE(jwall): I am shamelessly ripping ff the cases for this from libpnet diff --git a/src/socket.rs b/src/socket.rs index 33ee35a..ce4eb59 100644 --- a/src/socket.rs +++ b/src/socket.rs @@ -103,7 +103,8 @@ impl IcmpSocket6 { packet = packet.with_checksum(source, &dest); let dest = ip_to_socket(&IpAddr::V6(dest)); self.inner.set_unicast_hops_v6(self.opts.hops)?; - self.inner.send_to(&packet.get_bytes(true), &(dest.into()))?; + let pkt = packet.get_bytes(true); + self.inner.send_to(&pkt, &(dest.into()))?; Ok(()) }