diff options
Diffstat (limited to 'crates/windivert/src/packet.rs')
| -rw-r--r-- | crates/windivert/src/packet.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/crates/windivert/src/packet.rs b/crates/windivert/src/packet.rs new file mode 100644 index 0000000..ea81fe9 --- /dev/null +++ b/crates/windivert/src/packet.rs @@ -0,0 +1,90 @@ +use windivert_sys::{ChecksumFlags, WinDivertHelperCalcChecksums}; + +use crate::{address::WinDivertAddress, layer, prelude::WinDivertError}; + +use std::{ + borrow::{BorrowMut, Cow}, + ffi::c_void, + fmt::Debug, +}; + +/// Raw captured packet +#[derive(Debug, Clone)] +pub struct WinDivertPacket<'a, L: layer::WinDivertLayerTrait> { + /// Address data + pub address: WinDivertAddress<L>, + /// Raw captured data + pub data: Cow<'a, [u8]>, +} + +impl<'a> WinDivertPacket<'a, layer::NetworkLayer> { + /// Create a new network packet from a raw buffer + /// # Safety + /// `address` is zeroed, user must fill it with correct data before sending. + pub unsafe fn new(data: Vec<u8>) -> Self { + Self { + address: WinDivertAddress::<layer::NetworkLayer>::new(), + data: Cow::from(data), + } + } + + /// Recalculate the checksums of the packet + /// This is a noop if the packet is not owned. + pub fn recalculate_checksums(&mut self, flags: ChecksumFlags) -> Result<(), WinDivertError> { + if let Cow::Owned(ref mut data) = self.data.borrow_mut() { + let res = unsafe { + WinDivertHelperCalcChecksums( + data.as_mut_ptr() as *mut c_void, + data.len() as u32, + self.address.as_mut(), + flags, + ) + }; + if !res.as_bool() { + return Err(WinDivertError::from(windows::core::Error::from_win32())); + } + } + Ok(()) + } +} + +impl<'a> WinDivertPacket<'a, layer::ForwardLayer> { + /// Create a new network forward packet from a raw buffer + /// # Safety + /// `address` is zeroed, user must fill it with correct data before sending. + pub unsafe fn new(data: Vec<u8>) -> Self { + Self { + address: WinDivertAddress::<layer::ForwardLayer>::new(), + data: Cow::from(data), + } + } + + /// Recalculate the checksums of the packet + /// This is a noop if the packet is not owned. + pub fn recalculate_checksums(&mut self, flags: ChecksumFlags) -> Result<(), WinDivertError> { + if let Cow::Owned(ref mut data) = self.data.borrow_mut() { + let res = unsafe { + WinDivertHelperCalcChecksums( + data.as_mut_ptr() as *mut c_void, + data.len() as u32, + self.address.as_mut(), + flags, + ) + }; + if !res.as_bool() { + return Err(WinDivertError::from(windows::core::Error::from_win32())); + } + } + Ok(()) + } +} + +impl<'a, L: layer::WinDivertLayerTrait> WinDivertPacket<'a, L> { + /// Create an owned packet from a borrowed packet + pub fn into_owned(self) -> WinDivertPacket<'static, L> { + WinDivertPacket { + address: self.address, + data: self.data.into_owned().into(), + } + } +} |
