// eprintln!("packet={:x?}", &packet);
packets = check
- ::<_,_,true>(ic.mtu, &data, |_| Ok(()), |e| match e {
+ ::<_,_,true>(ic.mtu, &data, |header| {
+ let addr = ip_packet_addr::<false>(header)?;
+ if addr != ic.link.client.0 { throw!(PE::UnexpectedSrc(addr)) }
+ Ok(())
+ }, |e| match e {
e => error!("PACKET ERROR {}", e), // xxx
}).into();
},
#[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),
+ #[error("unexpected src addr {0:?}")] UnexpectedSrc(IpAddr),
+ #[error("unexpected dst addr {0:?}")] UnexpectedDst(IpAddr),
+ #[error("bad, IPv{vsn}, len={len}")] Bad { len: usize, vsn: u8 },
}
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 AC: FnMut(&[u8]) -> Result<(), IpAddr>,
+where AC: FnMut(&[u8]) -> Result<(), PacketError>,
EH: FnMut(PacketError),
{
// eprintln!("before: {:?}", DumpHex(data));
}
let _ = wheader.write(walk);
- addr_chk(&header).map_err(PacketError::UnexpectedAddr)?;
+ addr_chk(&header)?;
Ok(packet)
})() {
const HEADER_FOR_ADDR: usize = 40;
-pub fn ip_packet_addr<const DST: bool>(packet: &[u8]) -> Option<IpAddr> {
- Some(match packet.get(0)? & 0xf0 {
+#[throws(PacketError)]
+pub fn ip_packet_addr<const DST: bool>(packet: &[u8]) -> IpAddr {
+ let vsn = (packet.get(0).ok_or_else(|| PE::Empty)? & 0xf0) >> 4;
+ match vsn {
4 if packet.len() >= 20 => {
let slice = &packet[if DST { 16 } else { 12 }..][0..4];
Ipv4Addr::from(*<&[u8;4]>::try_from(slice).unwrap()).into()
Ipv6Addr::from(*<&[u8;16]>::try_from(slice).unwrap()).into()
},
- _ => None?,
- })
+ _ => throw!(PE::Bad{ vsn, len: packet.len() }),
+ }
}
#[derive(Copy,Clone,Eq,PartialEq,Ord,PartialOrd,Hash)]