More unit tests and a bugfix for echo packet construction

This commit is contained in:
Jeremy Wall 2021-01-16 15:10:38 -05:00
parent f49a16c2f6
commit 8971625151
4 changed files with 82 additions and 5 deletions

View File

@ -19,7 +19,15 @@ pub fn main() {
let mut socket6 = IcmpSocket6::new().unwrap();
socket6.bind("::1".parse::<Ipv6Addr>().unwrap()).unwrap();
let mut echo_socket = echo::EchoSocket6::new(socket6);
echo_socket.send_ping("::1".parse::<Ipv6Addr>().unwrap(), 42, &[]).unwrap();
echo_socket.send_ping("::1".parse::<Ipv6Addr>().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());
}

View File

@ -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)}
}

View File

@ -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<u8>) -> Result<Self, Icmpv6PacketBuildError> {
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<u8>) -> Result<Self, Icmpv6PacketBuildError> {
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<Icmpv6PacketBuildError> 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

View File

@ -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(())
}