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