From: Ian Jackson Date: Mon, 2 Aug 2021 00:27:34 +0000 (+0100) Subject: prep for addr chk X-Git-Tag: hippotat/1.0.0~386 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=d4b80478a1226f3fc598d50a0007dfcdec97fbf7;p=hippotat.git prep for addr chk Signed-off-by: Ian Jackson --- diff --git a/src/bin/client.rs b/src/bin/client.rs index 425b82a..600bcbc 100644 --- a/src/bin/client.rs +++ b/src/bin/client.rs @@ -197,7 +197,7 @@ async fn run_client( // eprintln!("packet={:x?}", &packet); packets = check - ::<_, true>(ic.mtu, &data, |e| match e { + ::<_,_,true>(ic.mtu, &data, |_| Ok(()), |e| match e { e => error!("PACKET ERROR {}", e), // xxx }).into(); }, diff --git a/src/prelude.rs b/src/prelude.rs index 2b377d9..5f95506 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -10,7 +10,7 @@ pub use std::cmp::{min, max}; pub use std::fs; pub use std::fmt::{self, Debug, Display, Write as _}; pub use std::future::Future; -pub use std::io::{self, ErrorKind, Read as _}; +pub use std::io::{self, ErrorKind, Read as _, Write as _}; pub use std::iter; pub use std::mem; pub use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; diff --git a/src/slip.rs b/src/slip.rs index 07ae827..bce44ca 100644 --- a/src/slip.rs +++ b/src/slip.rs @@ -11,12 +11,14 @@ pub enum PacketError { #[error("empty packet")] Empty, #[error("MTU exceeded ({len} > {mtu})")] MTU { len: usize, mtu: u32 }, #[error("Invalid SLIP escape sequence")] SLIP, + #[error("unexpected address {0:?}")] UnexpectedAddr(IpAddr), } -pub fn check - (mtu: u32, data: &[u8], mut error_handler: EH) +pub fn check + (mtu: u32, data: &[u8], mut addr_chk: AC, mut error_handler: EH) -> Vec> -where EH: FnMut(PacketError) +where AC: FnMut(&[u8]) -> Result<(), IpAddr>, + EH: FnMut(PacketError), { // eprintln!("before: {:?}", DumpHex(data)); @@ -33,6 +35,8 @@ where EH: FnMut(PacketError) let mut packet: Box<[u8]> = packet.to_owned().into(); let mut walk: &mut [u8] = &mut packet; + let mut header = [0u8; HEADER_FOR_ADDR]; + let mut wheader = &mut header[..]; while let Some((i, was_mime)) = walk.iter().enumerate().find_map( |(i,&c)| match c { @@ -41,18 +45,24 @@ where EH: FnMut(PacketError) _ => None, } ) { + let _ = wheader.write(&walk[0..i]); walk[i] = if was_mime { SLIP_ESC } else { SLIP_MIME_ESC }; if was_mime != TO_MIME { - match walk.get(i+1) { - Some(&SLIP_ESC_END) | - Some(&SLIP_ESC_ESC) => Ok(()), - _ => Err(PacketError::SLIP), - }?; + let c = match walk.get(i+1) { + Some(&SLIP_ESC_END) => SLIP_ESC, + Some(&SLIP_ESC_ESC) => SLIP_END, + _ => throw!(PacketError::SLIP), + }; + let _ = wheader.write(&[c]); walk = &mut walk[i+2 ..]; } else { + let _ = wheader.write(&[SLIP_MIME_ESC]); walk = &mut walk[i+1 ..]; } } + let _ = wheader.write(walk); + + addr_chk(&header).map_err(PacketError::UnexpectedAddr)?; Ok(packet) })() { @@ -103,17 +113,19 @@ impl From for FramesData { fn from(frames: Frames) -> FramesData { frames.frames } } -pub fn ip_packet_addrs(packet: &[u8]) -> Option<(IpAddr, IpAddr)> { +const HEADER_FOR_ADDR: usize = 40; + +pub fn ip_packet_addr(packet: &[u8]) -> Option { Some(match packet.get(0)? & 0xf0 { - 4 if packet.len() >= 20 => ( - Ipv4Addr::from(*<&[u8;4]>::try_from(&packet[12..16]).unwrap()).into(), - Ipv4Addr::from(*<&[u8;4]>::try_from(&packet[16..20]).unwrap()).into(), - ), + 4 if packet.len() >= 20 => { + let slice = &packet[if DST { 16 } else { 12 }..][0..4]; + Ipv4Addr::from(*<&[u8;4]>::try_from(slice).unwrap()).into() + }, - 6 if packet.len() >= 40 => ( - Ipv6Addr::from(*<&[u8;16]>::try_from(&packet[ 8..24]).unwrap()).into(), - Ipv6Addr::from(*<&[u8;16]>::try_from(&packet[24..40]).unwrap()).into(), - ), + 6 if packet.len() >= 40 => { + let slice = &packet[if DST { 24 } else { 8 }..][0..16]; + Ipv6Addr::from(*<&[u8;16]>::try_from(slice).unwrap()).into() + }, _ => None?, }) @@ -135,7 +147,7 @@ fn mime_slip_to_mime() { fn chk(i: &[u8], exp_p: &[&[u8]], exp_e: &[PacketError]) { let mut got_e = vec![]; - let got_p = check::<_,true>(MTU, i, |e| got_e.push(e)); + let got_p = check::<_,_,true>(MTU, i, |_|Ok(()), |e| got_e.push(e)); assert_eq!( got_p.iter().map(|b| DumpHex(b)).collect_vec(), exp_p.iter().map(|b| DumpHex(b)).collect_vec() ); assert_eq!( got_e,