summaryrefslogtreecommitdiffhomepage
path: root/crates/windivert/src/address.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/windivert/src/address.rs')
-rw-r--r--crates/windivert/src/address.rs421
1 files changed, 421 insertions, 0 deletions
diff --git a/crates/windivert/src/address.rs b/crates/windivert/src/address.rs
new file mode 100644
index 0000000..f896e03
--- /dev/null
+++ b/crates/windivert/src/address.rs
@@ -0,0 +1,421 @@
+use std::{
+ marker::PhantomData,
+ net::{IpAddr, Ipv4Addr, Ipv6Addr},
+};
+
+use crate::{layer, prelude::*};
+use windivert_sys::address::*;
+
+/// Newtype wrapper around [`WINDIVERT_ADDRESS`] using typestate to provide a safe interface.
+#[repr(transparent)]
+#[derive(Debug, Clone)]
+pub struct WinDivertAddress<L: layer::WinDivertLayerTrait> {
+ data: WINDIVERT_ADDRESS,
+ _layer: PhantomData<L>,
+}
+
+impl<L: layer::WinDivertLayerTrait> WinDivertAddress<L> {
+ #[inline]
+ pub(crate) fn from_raw(data: WINDIVERT_ADDRESS) -> Self {
+ Self {
+ data,
+ _layer: PhantomData,
+ }
+ }
+
+ /// Timestamp of the event. Uses same clock as `QueryPerformanceCounter()`
+ #[inline]
+ pub fn event_timestamp(&self) -> i64 {
+ self.data.timestamp
+ }
+
+ /// Type of captured event
+ #[inline]
+ pub fn event(&self) -> WinDivertEvent {
+ self.data.event()
+ }
+
+ /// The handle's layer
+ #[inline]
+ pub fn event_layer(&self) -> WinDivertLayer {
+ self.data.layer()
+ }
+
+ /// Set to `true` if the event was sniffed (i.e., not blocked), `false` otherwise
+ #[inline]
+ pub fn sniffed(&self) -> bool {
+ self.data.sniffed()
+ }
+
+ /// Set to `true` for outbound packets/event, `false` for inbound or otherwise
+ #[inline]
+ pub fn outbound(&self) -> bool {
+ self.data.outbound()
+ }
+
+ /// Outbound setter
+ #[inline]
+ pub fn set_outbound(&mut self, value: bool) {
+ self.data.set_outbound(value)
+ }
+
+ /// Set to `true` for loopback packets, `false` otherwise
+ #[inline]
+ pub fn loopback(&self) -> bool {
+ self.data.loopback()
+ }
+
+ /// Set to `true` for impostor packets, `false` otherwise.
+ #[inline]
+ pub fn impostor(&self) -> bool {
+ self.data.impostor()
+ }
+
+ /// Impostor setter
+ #[inline]
+ pub fn set_impostor(&mut self, value: bool) {
+ self.data.set_impostor(value)
+ }
+
+ /// Set to `true` for IPv6 packets/events, `false` otherwise
+ #[inline]
+ pub fn ipv6(&self) -> bool {
+ self.data.ipv6()
+ }
+
+ /// Set to `true` if the IPv4 checksum is valid, `false` otherwise.
+ #[inline]
+ pub fn ip_checksum(&self) -> bool {
+ self.data.ipchecksum()
+ }
+
+ /// IPv4 checksum setter
+ #[inline]
+ pub fn set_ip_checksum(&mut self, value: bool) {
+ self.data.set_ipchecksum(value)
+ }
+
+ /// Set to `true` if the TCP checksum is valid, `false` otherwise.
+ #[inline]
+ pub fn tcp_checksum(&self) -> bool {
+ self.data.tcpchecksum()
+ }
+
+ /// TCP checksum setter
+ #[inline]
+ pub fn set_tcp_checksum(&mut self, value: bool) {
+ self.data.set_tcpchecksum(value)
+ }
+
+ /// Set to `true` if the UDP checksum is valid, `false` otherwise.
+ #[inline]
+ pub fn udp_checksum(&self) -> bool {
+ self.data.udpchecksum()
+ }
+
+ /// UDP checksum setter
+ #[inline]
+ pub fn set_udp_checksum(&mut self, value: bool) {
+ self.data.set_udpchecksum(value)
+ }
+}
+
+impl<L: layer::WinDivertLayerTrait> AsRef<WINDIVERT_ADDRESS> for WinDivertAddress<L> {
+ #[inline]
+ fn as_ref(&self) -> &WINDIVERT_ADDRESS {
+ &self.data
+ }
+}
+
+impl<L: layer::WinDivertLayerTrait> AsMut<WINDIVERT_ADDRESS> for WinDivertAddress<L> {
+ #[inline]
+ fn as_mut(&mut self) -> &mut WINDIVERT_ADDRESS {
+ &mut self.data
+ }
+}
+
+impl WinDivertAddress<layer::NetworkLayer> {
+ /// Create a new [`WinDivertAddress`] to inject new packets.
+ /// # Safety
+ /// The default value for address is zeroed memory, caller must fill with valid data before sending.
+ pub unsafe fn new() -> Self {
+ Self {
+ data: Default::default(),
+ _layer: PhantomData,
+ }
+ }
+
+ #[inline]
+ fn data(&self) -> &WINDIVERT_DATA_NETWORK {
+ // SAFETY: Thanks to typestate, we know that self is a network layer address
+ unsafe { &self.data.union_field.Network }
+ }
+
+ #[inline]
+ fn data_mut(&mut self) -> &mut WINDIVERT_DATA_NETWORK {
+ // SAFETY: Thanks to typestate, we know that self is a network layer address
+ unsafe { &mut self.data.union_field.Network }
+ }
+
+ /// The interface index on which the packet arrived (for inbound packets), or is to be sent (for outbound packets)
+ #[inline]
+ pub fn interface_index(&self) -> u32 {
+ self.data().interface_id
+ }
+
+ /// Interface index setter
+ #[inline]
+ pub fn set_interface_index(&mut self, value: u32) {
+ self.data_mut().interface_id = value
+ }
+
+ /// The sub-interface index for `interface_id()`
+ #[inline]
+ pub fn subinterface_index(&self) -> u32 {
+ self.data().subinterface_id
+ }
+
+ /// Sub interface index setter
+ #[inline]
+ pub fn set_subinterface_index(&mut self, value: u32) {
+ self.data_mut().subinterface_id = value
+ }
+}
+
+impl WinDivertAddress<layer::ForwardLayer> {
+ /// Create a new [`WinDivertAddress`] to inject new packets.
+ /// # Safety
+ /// The default value for address is zeroed memory, caller must fill with valid data before sending.
+ pub unsafe fn new() -> Self {
+ Self {
+ data: Default::default(),
+ _layer: PhantomData,
+ }
+ }
+
+ #[inline]
+ fn data(&self) -> &WINDIVERT_DATA_NETWORK {
+ // SAFETY: Thanks to typestate, we know that self is a network layer address
+ unsafe { &self.data.union_field.Network }
+ }
+
+ #[inline]
+ fn data_mut(&mut self) -> &mut WINDIVERT_DATA_NETWORK {
+ // SAFETY: Thanks to typestate, we know that self is a network layer address
+ unsafe { &mut self.data.union_field.Network }
+ }
+
+ /// The interface index on which the packet arrived (for inbound packets), or is to be sent (for outbound packets)
+ #[inline]
+ pub fn interface_index(&self) -> u32 {
+ self.data().interface_id
+ }
+
+ /// Interface index setter
+ #[inline]
+ pub fn set_interface_index(&mut self, value: u32) {
+ self.data_mut().interface_id = value
+ }
+
+ /// The sub-interface index for `interface_id()`
+ #[inline]
+ pub fn subinterface_index(&self) -> u32 {
+ self.data().subinterface_id
+ }
+
+ /// Sub interface index setter
+ #[inline]
+ pub fn set_subinterface_index(&mut self, value: u32) {
+ self.data_mut().subinterface_id = value
+ }
+}
+
+impl WinDivertAddress<layer::FlowLayer> {
+ #[inline]
+ fn data(&self) -> &WINDIVERT_DATA_FLOW {
+ // SAFETY: Thanks to typestate, we know that self is a flow layer address
+ unsafe { &self.data.union_field.Flow }
+ }
+
+ /// The endpoint ID of the flow
+ #[inline]
+ pub fn endpoint_id(&self) -> u64 {
+ self.data().endpoint_id
+ }
+
+ /// The parent endpoint ID of the flow
+ #[inline]
+ pub fn parent_endpoint_id(&self) -> u64 {
+ self.data().parent_endpoint_id
+ }
+
+ /// The parent endpoint ID of the flow
+ #[inline]
+ pub fn process_id(&self) -> u32 {
+ self.data().process_id
+ }
+
+ /// The local address associated with the flow
+ #[inline]
+ pub fn local_address(&self) -> IpAddr {
+ if self.data.ipv6() {
+ IpAddr::V6(Ipv6Addr::from(
+ self.data()
+ .local_addr
+ .iter()
+ .rev()
+ .fold(0u128, |acc, &x| acc << 32 | (x as u128)),
+ ))
+ } else {
+ IpAddr::V4(Ipv4Addr::from(self.data().local_addr[0]))
+ }
+ }
+
+ /// The remote address associated with the flow
+ #[inline]
+ pub fn remote_address(&self) -> IpAddr {
+ if self.data.ipv6() {
+ IpAddr::V6(Ipv6Addr::from(
+ self.data()
+ .remote_addr
+ .iter()
+ .rev()
+ .fold(0u128, |acc, &x| acc << 32 | (x as u128)),
+ ))
+ } else {
+ IpAddr::V4(Ipv4Addr::from(self.data().remote_addr[0]))
+ }
+ }
+
+ /// The locla port associated with the flow
+ #[inline]
+ pub fn local_port(&self) -> u16 {
+ self.data().local_port
+ }
+
+ /// The remote port associated with the flow
+ #[inline]
+ pub fn remote_port(&self) -> u16 {
+ self.data().remote_port
+ }
+
+ /// The protocol associated with the flow
+ #[inline]
+ pub fn protocol(&self) -> u8 {
+ self.data().protocol
+ }
+}
+
+impl WinDivertAddress<layer::SocketLayer> {
+ #[inline]
+ fn data(&self) -> &WINDIVERT_DATA_FLOW {
+ // SAFETY: Thanks to typestate, we know that self is a flow layer address
+ unsafe { &self.data.union_field.Flow }
+ }
+
+ /// The endpoint ID of the flow
+ #[inline]
+ pub fn endpoint_id(&self) -> u64 {
+ self.data().endpoint_id
+ }
+
+ /// The parent endpoint ID of the flow
+ #[inline]
+ pub fn parent_endpoint_id(&self) -> u64 {
+ self.data().parent_endpoint_id
+ }
+
+ /// The parent endpoint ID of the flow
+ #[inline]
+ pub fn process_id(&self) -> u32 {
+ self.data().process_id
+ }
+
+ /// The local address associated with the flow
+ #[inline]
+ pub fn local_address(&self) -> IpAddr {
+ if self.data.ipv6() {
+ IpAddr::V6(Ipv6Addr::from(
+ self.data()
+ .local_addr
+ .iter()
+ .rev()
+ .fold(0u128, |acc, &x| acc << 32 | (x as u128)),
+ ))
+ } else {
+ IpAddr::V4(Ipv4Addr::from(self.data().local_addr[0]))
+ }
+ }
+
+ /// The remote address associated with the flow
+ #[inline]
+ pub fn remote_address(&self) -> IpAddr {
+ if self.data.ipv6() {
+ IpAddr::V6(Ipv6Addr::from(
+ self.data()
+ .remote_addr
+ .iter()
+ .rev()
+ .fold(0u128, |acc, &x| acc << 32 | (x as u128)),
+ ))
+ } else {
+ IpAddr::V4(Ipv4Addr::from(self.data().remote_addr[0]))
+ }
+ }
+
+ /// The locla port associated with the flow
+ #[inline]
+ pub fn local_port(&self) -> u16 {
+ self.data().local_port
+ }
+
+ /// The remote port associated with the flow
+ #[inline]
+ pub fn remote_port(&self) -> u16 {
+ self.data().remote_port
+ }
+
+ /// The protocol associated with the flow
+ #[inline]
+ pub fn protocol(&self) -> u8 {
+ self.data().protocol
+ }
+}
+
+impl WinDivertAddress<layer::ReflectLayer> {
+ #[inline]
+ fn data(&self) -> &WINDIVERT_DATA_REFLECT {
+ // SAFETY: Thanks to typestate, we know that self is a reflect layer address
+ unsafe { &self.data.union_field.Reflect }
+ }
+
+ /// A timestamp indicating when the handle was opened
+ #[inline]
+ pub fn timestamp(&self) -> i64 {
+ self.data().timestamp
+ }
+
+ /// The ID of the process that opened the handle
+ #[inline]
+ pub fn process_id(&self) -> u32 {
+ self.data().process_id
+ }
+
+ /// The layer of the opened handle
+ #[inline]
+ pub fn layer(&self) -> WinDivertLayer {
+ self.data().layer
+ }
+
+ /// The flags of the opened handle
+ #[inline]
+ pub fn flags(&self) -> WinDivertFlags {
+ self.data().flags
+ }
+
+ /// The priority of the opened handle
+ #[inline]
+ pub fn priority(&self) -> i16 {
+ self.data().priority
+ }
+}