chiark / gitweb /
prep for addr chk
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 2 Aug 2021 00:27:34 +0000 (01:27 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 2 Aug 2021 00:27:34 +0000 (01:27 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bin/client.rs
src/prelude.rs
src/slip.rs

index 425b82a1f831d6664590a8d12e8653909db86033..600bcbcab185babd1da8610a18d183a4f66543e3 100644 (file)
@@ -197,7 +197,7 @@ async fn run_client<C:HCC>(
           //            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();
         },
index 2b377d9131d84589fdabc642c5c88a5f6c5763c6..5f95506303ecec104570a660c2e7c16886e5e769 100644 (file)
@@ -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};
index 07ae827b6d07ababc50a41d28277477b2fe4c2a0..bce44ca91f7ad8761a74d50e6450a24e8657844c 100644 (file)
@@ -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<EH, const TO_MIME: bool>
-  (mtu: u32, data: &[u8], mut error_handler: EH)
+pub fn check<AC, EH, const TO_MIME: bool>
+  (mtu: u32, data: &[u8], mut addr_chk: AC, mut error_handler: EH)
    -> Vec<Box<[u8]>>
-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<Frames> 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<const DST: bool>(packet: &[u8]) -> Option<IpAddr> {
   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,