summaryrefslogtreecommitdiffhomepage
path: root/crates/windivert/src/packet.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/windivert/src/packet.rs')
-rw-r--r--crates/windivert/src/packet.rs90
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(),
+ }
+ }
+}