1 use crate::{ 2 err::{packet::SliceError, Layer}, 3 *, 4 }; 5 6 /// Helper class for laxly slicing packets. 7 pub(crate) struct LaxSlicedPacketCursor<'a> { 8 pub offset: usize, 9 pub result: LaxSlicedPacket<'a>, 10 } 11 12 impl<'a> LaxSlicedPacketCursor<'a> { parse_from_ethernet2(slice: &'a [u8]) -> Result<LaxSlicedPacket<'a>, err::LenError>13 pub fn parse_from_ethernet2(slice: &'a [u8]) -> Result<LaxSlicedPacket<'a>, err::LenError> { 14 use ether_type::*; 15 use LinkSlice::*; 16 17 let mut cursor = LaxSlicedPacketCursor { 18 offset: 0, 19 result: LaxSlicedPacket { 20 link: None, 21 vlan: None, 22 net: None, 23 transport: None, 24 stop_err: None, 25 }, 26 }; 27 28 let result = Ethernet2Slice::from_slice_without_fcs(slice)?; 29 30 // cache the ether_type for later 31 let payload = result.payload(); 32 33 // set the new data 34 cursor.offset += result.header_len(); 35 cursor.result.link = Some(Ethernet2(result)); 36 37 // continue parsing (if required) 38 match payload.ether_type { 39 IPV4 => Ok(cursor.slice_ip(payload.payload)), 40 IPV6 => Ok(cursor.slice_ip(payload.payload)), 41 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 42 Ok(cursor.slice_vlan(payload.payload)) 43 } 44 _ => Ok(cursor.result), 45 } 46 } 47 parse_from_ether_type(ether_type: EtherType, slice: &'a [u8]) -> LaxSlicedPacket<'a>48 pub fn parse_from_ether_type(ether_type: EtherType, slice: &'a [u8]) -> LaxSlicedPacket<'a> { 49 let cursor = LaxSlicedPacketCursor { 50 offset: 0, 51 result: LaxSlicedPacket { 52 link: Some(LinkSlice::EtherPayload(EtherPayloadSlice { 53 ether_type, 54 payload: slice, 55 })), 56 vlan: None, 57 net: None, 58 transport: None, 59 stop_err: None, 60 }, 61 }; 62 use ether_type::*; 63 match ether_type { 64 IPV4 => cursor.slice_ip(slice), 65 IPV6 => cursor.slice_ip(slice), 66 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 67 cursor.slice_vlan(slice) 68 } 69 _ => cursor.result, 70 } 71 } 72 parse_from_ip( slice: &'a [u8], ) -> Result<LaxSlicedPacket<'a>, err::ip::LaxHeaderSliceError>73 pub fn parse_from_ip( 74 slice: &'a [u8], 75 ) -> Result<LaxSlicedPacket<'a>, err::ip::LaxHeaderSliceError> { 76 let (ip, stop_err) = LaxIpSlice::from_slice(slice)?; 77 let is_ip_v4 = match &ip { 78 LaxIpSlice::Ipv4(_) => true, 79 LaxIpSlice::Ipv6(_) => false, 80 }; 81 let payload = ip.payload().clone(); 82 let offset = (payload.payload.as_ptr() as usize) - (slice.as_ptr() as usize); 83 Ok(LaxSlicedPacketCursor { 84 offset, 85 result: LaxSlicedPacket { 86 link: None, 87 vlan: None, 88 net: Some(ip.into()), 89 transport: None, 90 stop_err: stop_err.map(|(stop_err, stop_layer)| { 91 use err::ipv6_exts::HeaderError as E; 92 use err::ipv6_exts::HeaderSliceError as I; 93 use err::packet::SliceError as O; 94 ( 95 match stop_err { 96 I::Len(l) => O::Len(l), 97 I::Content(c) => match c { 98 E::HopByHopNotAtStart => O::Ipv6Exts(E::HopByHopNotAtStart), 99 E::IpAuth(auth) => { 100 if is_ip_v4 { 101 O::Ipv4Exts(auth) 102 } else { 103 O::Ipv6Exts(E::IpAuth(auth)) 104 } 105 } 106 }, 107 }, 108 stop_layer, 109 ) 110 }), 111 }, 112 } 113 .slice_transport(payload)) 114 } 115 slice_vlan(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a>116 pub fn slice_vlan(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a> { 117 use ether_type::*; 118 use VlanSlice::*; 119 120 // cache the starting slice so the later combining 121 // of outer & inner vlan is defined behavior (for miri) 122 let outer_start_slice = slice; 123 let outer = match SingleVlanSlice::from_slice(slice) { 124 Ok(v) => v, 125 Err(err) => { 126 self.result.stop_err = Some(( 127 SliceError::Len(err.add_offset(self.offset)), 128 Layer::VlanHeader, 129 )); 130 return self.result; 131 } 132 }; 133 self.result.vlan = Some(VlanSlice::SingleVlan(outer.clone())); 134 self.offset += outer.header_len(); 135 136 //check if it is a double vlan header 137 match outer.ether_type() { 138 //in case of a double vlan header continue with the inner 139 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 140 let inner = match SingleVlanSlice::from_slice(outer.payload_slice()) { 141 Ok(v) => v, 142 Err(err) => { 143 self.result.stop_err = Some(( 144 SliceError::Len(err.add_offset(self.offset)), 145 Layer::VlanHeader, 146 )); 147 return self.result; 148 } 149 }; 150 self.offset += inner.header_len(); 151 152 let inner_ether_type = inner.ether_type(); 153 self.result.vlan = Some(DoubleVlan(DoubleVlanSlice { 154 slice: outer_start_slice, 155 })); 156 157 match inner_ether_type { 158 IPV4 => self.slice_ip(inner.payload_slice()), 159 IPV6 => self.slice_ip(inner.payload_slice()), 160 _ => self.result, 161 } 162 } 163 value => match value { 164 IPV4 => self.slice_ip(outer.payload_slice()), 165 IPV6 => self.slice_ip(outer.payload_slice()), 166 _ => self.result, 167 }, 168 } 169 } 170 slice_ip(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a>171 pub fn slice_ip(mut self, slice: &'a [u8]) -> LaxSlicedPacket<'a> { 172 // ip slice 173 let ip = match LaxIpSlice::from_slice(slice) { 174 Ok(ip) => ip, 175 Err(e) => { 176 use err::ip::LaxHeaderSliceError as I; 177 use err::packet::SliceError as O; 178 self.result.stop_err = Some(match e { 179 I::Len(mut l) => { 180 l.layer_start_offset += self.offset; 181 (O::Len(l), Layer::IpHeader) 182 } 183 I::Content(c) => (O::Ip(c), Layer::IpHeader), 184 }); 185 return self.result; 186 } 187 }; 188 self.result.net = Some(ip.0.clone().into()); 189 190 // stop in case there was a stop error in the ip extension headers 191 if let Some((stop_err, stop_layer)) = ip.1 { 192 use err::ipv6_exts::HeaderError as E; 193 use err::ipv6_exts::HeaderSliceError as I; 194 use err::packet::SliceError as O; 195 self.result.stop_err = Some(( 196 match stop_err { 197 I::Len(l) => O::Len(l.add_offset(self.offset)), 198 I::Content(c) => match c { 199 E::HopByHopNotAtStart => O::Ipv6Exts(E::HopByHopNotAtStart), 200 E::IpAuth(auth) => match &ip.0 { 201 LaxIpSlice::Ipv4(_) => O::Ipv4Exts(auth), 202 LaxIpSlice::Ipv6(_) => O::Ipv6Exts(E::IpAuth(auth)), 203 }, 204 }, 205 }, 206 stop_layer, 207 )); 208 } 209 210 // move offset for the transport layers 211 let payload = ip.0.payload().clone(); 212 self.offset += (payload.payload.as_ptr() as usize) - (slice.as_ptr() as usize); 213 self.slice_transport(payload) 214 } 215 slice_transport(mut self, slice: LaxIpPayloadSlice<'a>) -> LaxSlicedPacket<'a>216 fn slice_transport(mut self, slice: LaxIpPayloadSlice<'a>) -> LaxSlicedPacket<'a> { 217 use err::packet::SliceError as O; 218 if slice.fragmented || self.result.stop_err.is_some() { 219 // if an error occured in an upper layer or the payload is fragmented 220 // stop here 221 return self.result; 222 } 223 match slice.ip_number { 224 ip_number::ICMP => match Icmpv4Slice::from_slice(slice.payload) { 225 Ok(icmp) => { 226 self.offset += icmp.slice().len(); 227 self.result.transport = Some(TransportSlice::Icmpv4(icmp)); 228 } 229 Err(mut err) => { 230 err.layer_start_offset += self.offset; 231 err.len_source = slice.len_source; 232 self.result.stop_err = Some((O::Len(err), Layer::Icmpv4)); 233 } 234 }, 235 ip_number::UDP => match UdpSlice::from_slice_lax(slice.payload) { 236 Ok(udp) => { 237 self.offset += udp.slice().len(); 238 self.result.transport = Some(TransportSlice::Udp(udp)); 239 } 240 Err(mut err) => { 241 err.layer_start_offset += self.offset; 242 err.len_source = slice.len_source; 243 self.result.stop_err = Some((O::Len(err), Layer::UdpHeader)); 244 } 245 }, 246 ip_number::TCP => match TcpSlice::from_slice(slice.payload) { 247 Ok(tcp) => { 248 self.offset += tcp.slice().len(); 249 self.result.transport = Some(TransportSlice::Tcp(tcp)); 250 } 251 Err(err) => { 252 use err::tcp::HeaderSliceError as I; 253 self.result.stop_err = Some(( 254 match err { 255 I::Len(mut l) => { 256 l.layer_start_offset += self.offset; 257 l.len_source = slice.len_source; 258 O::Len(l) 259 } 260 I::Content(c) => O::Tcp(c), 261 }, 262 Layer::TcpHeader, 263 )); 264 } 265 }, 266 ip_number::IPV6_ICMP => match Icmpv6Slice::from_slice(slice.payload) { 267 Ok(icmp) => { 268 self.offset += icmp.slice().len(); 269 self.result.transport = Some(TransportSlice::Icmpv6(icmp)); 270 } 271 Err(mut err) => { 272 err.layer_start_offset += self.offset; 273 err.len_source = slice.len_source; 274 self.result.stop_err = Some((O::Len(err), Layer::Icmpv6)); 275 } 276 }, 277 _ => {} 278 } 279 self.result 280 } 281 } 282