1 use crate::*; 2 3 /// Helper class for slicing packets 4 pub(crate) struct SlicedPacketCursor<'a> { 5 pub slice: &'a [u8], 6 pub offset: usize, 7 pub len_source: LenSource, 8 pub result: SlicedPacket<'a>, 9 } 10 11 impl<'a> SlicedPacketCursor<'a> { new(slice: &'a [u8]) -> SlicedPacketCursor<'a>12 pub fn new(slice: &'a [u8]) -> SlicedPacketCursor<'a> { 13 SlicedPacketCursor { 14 slice, 15 offset: 0, 16 len_source: LenSource::Slice, 17 result: SlicedPacket { 18 link: None, 19 vlan: None, 20 net: None, 21 transport: None, 22 }, 23 } 24 } 25 move_by(&mut self, len: usize)26 fn move_by(&mut self, len: usize) { 27 unsafe { 28 use core::slice::from_raw_parts; 29 self.slice = from_raw_parts(self.slice.as_ptr().add(len), self.slice.len() - len); 30 } 31 self.offset += len; 32 } 33 slice_ethernet2(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>34 pub fn slice_ethernet2(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 35 use err::packet::SliceError::*; 36 use ether_type::*; 37 use LinkSlice::*; 38 39 let result = Ethernet2Slice::from_slice_without_fcs(self.slice) 40 .map_err(|err| Len(err.add_offset(self.offset)))?; 41 42 //cache the ether_type for later 43 let ether_type = result.ether_type(); 44 45 //set the new data 46 self.move_by(result.header_len()); 47 self.result.link = Some(Ethernet2(result)); 48 49 //continue parsing (if required) 50 match ether_type { 51 ARP => self.slice_arp(), 52 IPV4 => self.slice_ipv4(), 53 IPV6 => self.slice_ipv6(), 54 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => self.slice_vlan(), 55 _ => Ok(self.result), 56 } 57 } 58 slice_linux_sll(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>59 pub fn slice_linux_sll(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 60 use err::packet::SliceError::*; 61 62 let result = LinuxSllSlice::from_slice(self.slice).map_err(|err| match err { 63 err::linux_sll::HeaderSliceError::Len(len) => Len(len.add_offset(self.offset)), 64 err::linux_sll::HeaderSliceError::Content(content) => { 65 err::packet::SliceError::LinuxSll(content) 66 } 67 })?; 68 69 //cache the protocol type for later 70 let protocol_type = result.protocol_type(); 71 72 //set the new data 73 self.move_by(result.header_len()); 74 self.result.link = Some(LinkSlice::LinuxSll(result)); 75 76 //continue parsing (if required) 77 match protocol_type { 78 LinuxSllProtocolType::EtherType(EtherType::ARP) => self.slice_arp(), 79 LinuxSllProtocolType::EtherType(EtherType::IPV4) => self.slice_ipv4(), 80 LinuxSllProtocolType::EtherType(EtherType::IPV6) => self.slice_ipv6(), 81 _ => Ok(self.result), 82 } 83 } 84 slice_vlan(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>85 pub fn slice_vlan(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 86 use err::packet::SliceError::*; 87 use ether_type::*; 88 use VlanSlice::*; 89 90 // cache the starting slice so the later combining 91 // of outer & inner vlan is defined behavior (for miri) 92 let outer_start_slice = self.slice; 93 let outer = SingleVlanSlice::from_slice(self.slice) 94 .map_err(|err| Len(err.add_offset(self.offset)))?; 95 self.result.vlan = Some(SingleVlan(outer.clone())); 96 self.move_by(outer.header_len()); 97 98 //check if it is a double vlan header 99 match outer.ether_type() { 100 //in case of a double vlan header continue with the inner 101 VLAN_TAGGED_FRAME | PROVIDER_BRIDGING | VLAN_DOUBLE_TAGGED_FRAME => { 102 let inner = SingleVlanSlice::from_slice(self.slice) 103 .map_err(|err| Len(err.add_offset(self.offset)))?; 104 self.move_by(inner.header_len()); 105 106 let inner_ether_type = inner.ether_type(); 107 self.result.vlan = Some(DoubleVlan(DoubleVlanSlice { 108 slice: outer_start_slice, 109 })); 110 111 match inner_ether_type { 112 ARP => self.slice_arp(), 113 IPV4 => self.slice_ipv4(), 114 IPV6 => self.slice_ipv6(), 115 _ => Ok(self.result), 116 } 117 } 118 ARP => self.slice_arp(), 119 IPV4 => self.slice_ipv4(), 120 IPV6 => self.slice_ipv6(), 121 _ => Ok(self.result), 122 } 123 } 124 slice_ip(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>125 pub fn slice_ip(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 126 use err::packet::SliceError::*; 127 128 // slice header, extension headers and identify payload range 129 let ip = IpSlice::from_slice(self.slice).map_err(|err| { 130 use err::ip::SliceError as I; 131 match err { 132 I::Len(mut err) => { 133 err.layer_start_offset += self.offset; 134 Len(err) 135 } 136 I::IpHeaders(err) => match err { 137 err::ip::HeadersError::Ip(err) => Ip(err), 138 err::ip::HeadersError::Ipv4Ext(err) => Ipv4Exts(err), 139 err::ip::HeadersError::Ipv6Ext(err) => Ipv6Exts(err), 140 }, 141 } 142 })?; 143 144 // safe data needed 145 let payload = ip.payload().clone(); 146 147 // set the new data 148 self.offset += unsafe { 149 // SAFETY: The payload is a subslice of self.slice. 150 // therefor calculating the offset from it is safe and 151 // the result should always be a positive number. 152 payload.payload.as_ptr().offset_from(self.slice.as_ptr()) as usize 153 }; 154 self.len_source = payload.len_source; 155 self.slice = payload.payload; 156 self.result.net = Some(ip.into()); 157 158 // continue to the lower layers 159 if payload.fragmented { 160 Ok(self.result) 161 } else { 162 match payload.ip_number { 163 ip_number::ICMP => self.slice_icmp4().map_err(Len), 164 ip_number::UDP => self.slice_udp().map_err(Len), 165 ip_number::TCP => self.slice_tcp().map_err(|err| { 166 use err::tcp::HeaderSliceError as I; 167 match err { 168 I::Len(err) => Len(err), 169 I::Content(err) => Tcp(err), 170 } 171 }), 172 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len), 173 _ => Ok(self.result), 174 } 175 } 176 } 177 slice_ipv4(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>178 pub fn slice_ipv4(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 179 use err::packet::SliceError::*; 180 181 // slice ipv4 header & extension headers 182 let ipv4 = Ipv4Slice::from_slice(self.slice).map_err(|err| { 183 use err::ipv4::SliceError as I; 184 match err { 185 I::Len(mut err) => { 186 err.layer_start_offset += self.offset; 187 Len(err) 188 } 189 I::Header(err) => Ipv4(err), 190 I::Exts(err) => Ipv4Exts(err), 191 } 192 })?; 193 194 // safe data needed in following steps 195 let payload = ipv4.payload().clone(); 196 197 // set the new data 198 self.offset += unsafe { 199 // SAFETY: The payload is a subslice of self.slice. 200 // therefor calculating the offset from it is safe and 201 // the result should always be a positive number. 202 payload.payload.as_ptr().offset_from(self.slice.as_ptr()) as usize 203 }; 204 self.len_source = payload.len_source; 205 self.slice = payload.payload; 206 self.result.net = Some(NetSlice::Ipv4(ipv4)); 207 208 if payload.fragmented { 209 Ok(self.result) 210 } else { 211 match payload.ip_number { 212 ip_number::UDP => self.slice_udp().map_err(Len), 213 ip_number::TCP => self.slice_tcp().map_err(|err| { 214 use err::tcp::HeaderSliceError as I; 215 match err { 216 I::Len(err) => Len(err), 217 I::Content(err) => Tcp(err), 218 } 219 }), 220 ip_number::ICMP => self.slice_icmp4().map_err(Len), 221 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len), 222 _ => Ok(self.result), 223 } 224 } 225 } 226 slice_ipv6(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>227 pub fn slice_ipv6(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 228 use err::packet::SliceError::*; 229 230 let ipv6 = Ipv6Slice::from_slice(self.slice).map_err(|err| { 231 use err::ipv6::SliceError as I; 232 match err { 233 I::Len(mut err) => { 234 err.layer_start_offset += self.offset; 235 Len(err) 236 } 237 I::Header(err) => Ipv6(err), 238 I::Exts(err) => Ipv6Exts(err), 239 } 240 })?; 241 242 // safe data needed in following steps 243 let payload = ipv6.payload().clone(); 244 245 // set the new data 246 self.offset += unsafe { 247 // SAFETY: The payload is a subslice of self.slice. 248 // therefor calculating the offset from it is safe and 249 // the result should always be a positive number. 250 ipv6.payload() 251 .payload 252 .as_ptr() 253 .offset_from(self.slice.as_ptr()) as usize 254 }; 255 self.len_source = ipv6.payload().len_source; 256 self.slice = ipv6.payload().payload; 257 self.result.net = Some(NetSlice::Ipv6(ipv6)); 258 259 // only try to decode the transport layer if the payload 260 // is not fragmented 261 if payload.fragmented { 262 Ok(self.result) 263 } else { 264 //parse the data bellow 265 match payload.ip_number { 266 ip_number::ICMP => self.slice_icmp4().map_err(Len), 267 ip_number::UDP => self.slice_udp().map_err(Len), 268 ip_number::TCP => self.slice_tcp().map_err(|err| { 269 use err::tcp::HeaderSliceError as I; 270 match err { 271 I::Len(err) => Len(err), 272 I::Content(err) => Tcp(err), 273 } 274 }), 275 ip_number::IPV6_ICMP => self.slice_icmp6().map_err(Len), 276 _ => Ok(self.result), 277 } 278 } 279 } 280 slice_arp(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError>281 pub fn slice_arp(mut self) -> Result<SlicedPacket<'a>, err::packet::SliceError> { 282 let result = ArpPacketSlice::from_slice(self.slice).map_err(|mut err| { 283 err.layer_start_offset += self.offset; 284 err::packet::SliceError::Len(err) 285 })?; 286 287 //set the new data 288 self.move_by(result.slice().len()); 289 self.result.net = Some(NetSlice::Arp(result.clone())); 290 291 Ok(self.result) 292 } 293 slice_icmp4(mut self) -> Result<SlicedPacket<'a>, err::LenError>294 pub fn slice_icmp4(mut self) -> Result<SlicedPacket<'a>, err::LenError> { 295 use crate::TransportSlice::*; 296 297 let result = Icmpv4Slice::from_slice(self.slice).map_err(|mut err| { 298 err.layer_start_offset += self.offset; 299 if LenSource::Slice == err.len_source { 300 err.len_source = self.len_source; 301 } 302 err 303 })?; 304 305 //set the new data 306 self.move_by(result.slice().len()); 307 self.result.transport = Some(Icmpv4(result.clone())); 308 309 Ok(self.result) 310 } 311 slice_icmp6(mut self) -> Result<SlicedPacket<'a>, err::LenError>312 pub fn slice_icmp6(mut self) -> Result<SlicedPacket<'a>, err::LenError> { 313 use crate::TransportSlice::*; 314 315 let result = Icmpv6Slice::from_slice(self.slice).map_err(|mut err| { 316 err.layer_start_offset += self.offset; 317 if LenSource::Slice == err.len_source { 318 err.len_source = self.len_source; 319 } 320 err 321 })?; 322 323 //set the new data 324 self.move_by(result.slice().len()); 325 self.result.transport = Some(Icmpv6(result.clone())); 326 327 //done 328 Ok(self.result) 329 } 330 slice_udp(mut self) -> Result<SlicedPacket<'a>, err::LenError>331 pub fn slice_udp(mut self) -> Result<SlicedPacket<'a>, err::LenError> { 332 use crate::TransportSlice::*; 333 334 let result = UdpSlice::from_slice(self.slice).map_err(|mut err| { 335 err.layer_start_offset += self.offset; 336 if LenSource::Slice == err.len_source { 337 err.len_source = self.len_source; 338 } 339 err 340 })?; 341 342 //set the new data 343 self.move_by(result.slice().len()); 344 self.result.transport = Some(Udp(result)); 345 346 // done 347 Ok(self.result) 348 } 349 slice_tcp(mut self) -> Result<SlicedPacket<'a>, err::tcp::HeaderSliceError>350 pub fn slice_tcp(mut self) -> Result<SlicedPacket<'a>, err::tcp::HeaderSliceError> { 351 use crate::TransportSlice::*; 352 353 let result = TcpSlice::from_slice(self.slice).map_err(|mut err| { 354 use err::tcp::HeaderSliceError::Len; 355 if let Len(err) = &mut err { 356 err.layer_start_offset += self.offset; 357 if LenSource::Slice == err.len_source { 358 err.len_source = self.len_source; 359 } 360 } 361 err 362 })?; 363 364 //set the new data 365 self.move_by(result.slice().len()); 366 self.result.transport = Some(Tcp(result)); 367 368 // done 369 Ok(self.result) 370 } 371 } 372