#[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));
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 {
_ => 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)
})() {
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?,
})
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,