1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
//! # Submodule: Basic NDISAPI static filter definitions
//!
//! This submodule contains various structures used for static filters in the NDISAPI Rust library.
//!
//! The `filters` submodule provides a Rust interface for configuring static filters for the Windows Packet
//! Filter driver. It contains structures for specifying filter conditions and actions for various protocols,
//! including Ethernet 802.3, IPv4, IPv6, TCP, UDP, and ICMP. These structures allow users to define complex
//! filtering rules based on multiple packet fields and layers.
//!
//! # Structures
//!
//! * [`Eth8023Filter`] - Represents a static filter for Ethernet 802.3 frames.
//! * [`IpV4Filter`] - Represents a static filter for IPv4 packets.
//! * [`IpV6Filter`] - Represents a static filter for IPv6 packets.
//! * [`TcpUdpFilter`] - Represents a static filter for TCP and UDP packets.
//! * [`IcmpFilter`] - Represents a static filter for ICMP packets.
//! * [`StaticFilter`] - Represents a single static filter entry that combines filter conditions for various
//! layers and the filter action to be taken.
//! * [`StaticFilterTable`] - Represents a table of static filters, used for managing multiple static filter entries.
// Import required external crates and types
use windows::{Win32::Networking::WinSock::IN6_ADDR, Win32::Networking::WinSock::IN_ADDR};
use super::constants::*;
/// This structure is used to define an Ethernet 802.3 filter based on various fields like source and destination addresses, and protocol.
///
/// A Rust equivalent for the [_ETH_802_3_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_eth_802_3_filter/) structure.
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
pub struct Eth8023Filter {
/// A bitmask indicating which fields in the filter are valid.
pub valid_fields: Eth802_3FilterFlags,
/// The source address to filter on.
pub src_address: [u8; ETHER_ADDR_LENGTH],
/// The destination address to filter on.
pub dest_address: [u8; ETHER_ADDR_LENGTH],
/// The protocol (Ethertype) to filter on.
pub protocol: u16,
/// Padding to align the structure.
pub padding: u16,
}
impl Default for Eth8023Filter {
/// Returns a zero-initialized instance of `Eth8023Filter`.
///
/// # Safety
///
/// It is safe to zero-initialize this structure because it contains only values and arrays that
/// can be default initialized with zeroes.
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
/// This structure is used to represent an IPv4 subnet based on an IP address and a subnet mask.
///
/// A Rust equivalent for the [_IP_SUBNET_V4](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_subnet_v4/) structure.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpSubnetV4 {
/// The IPv4 address.
pub ip: IN_ADDR,
/// The subnet mask.
pub ip_mask: IN_ADDR,
}
/// This structure is used to represent an IPv4 address range based on a start and end IP address.
///
/// A Rust equivalent for the [_IP_RANGE_V4](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_range_v4/) structure.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpRangeV4 {
/// The start of the IPv4 address range.
pub start_ip: IN_ADDR,
/// The end of the IPv4 address range.
pub end_ip: IN_ADDR,
}
/// A Rust union representing either an IPv4 subnet (IpSubnetV4) or an IPv4 address range (IpRangeV4).
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub union IpAddressV4Union {
/// The IPv4 subnet representation.
pub ip_subnet: IpSubnetV4,
/// The IPv4 address range representation.
pub ip_range: IpRangeV4,
}
impl Default for IpAddressV4Union {
fn default() -> Self {
// SAFETY: This union contains either a `IpSubnetV4` or a `IpRangeV4`
// IpSubnetV4: when zeroed is equivalent to 0.0.0.0/0
// IpRangeV4: when zeroed is equivalent to 0.0.0.0 - 0.0.0.0
unsafe { std::mem::zeroed() }
}
}
/// Represents an IPv4 address in a format used by the packet filtering mechanism.
///
/// A Rust equivalent for [_IP_ADDRESS_V4](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_address_v4/).
///
/// The `address_type` field indicates whether the address is a subnet or a range.
/// The `address` field contains the actual IPv4 address information in a union format.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpAddressV4 {
pub address_type: u32, // IP_SUBNET_V4_TYPE or IP_RANGE_V4_TYPE
pub address: IpAddressV4Union,
}
/// Represents an IPv4 filter used by the packet filtering mechanism.
///
/// A Rust equivalent for [_IP_V4_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_v4_filter/).
///
/// The `valid_fields` field specifies which fields in the filter structure are used for filtering.
/// The `src_address` field contains the source IPv4 address information.
/// The `dest_address` field contains the destination IPv4 address information.
/// The `protocol` field represents the IP protocol number.
/// The `padding` field is used for alignment purposes.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpV4Filter {
pub valid_fields: IpV4FilterFlags,
pub src_address: IpAddressV4,
pub dest_address: IpAddressV4,
pub protocol: u8,
pub padding: [u8; 3usize],
}
/// Represents an IPv6 subnet used by the packet filtering mechanism.
///
/// A Rust equivalent for [_IP_SUBNET_V6](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_subnet_v6/).
///
/// The `ip` field contains the IPv6 address.
/// The `ip_mask` field contains the subnet mask.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct IpSubnetV6 {
pub ip: IN6_ADDR,
pub ip_mask: IN6_ADDR,
}
/// Represents an IPv6 address range used by the packet filtering mechanism.
///
/// A Rust equivalent for [_IP_RANGE_V6](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_range_v6/).
///
/// The `start_ip` field contains the starting IPv6 address of the range.
/// The `end_ip` field contains the ending IPv6 address of the range.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct IpRangeV6 {
pub start_ip: IN6_ADDR,
pub end_ip: IN6_ADDR,
}
/// This structure is used to store information about a particular address space
/// for packet filtering purposes.
///
/// A Rust union that represents either an IPv6 subnet or an IPv6 address range.
///
/// The `ip_subnet` field contains the IPv6 subnet if the address space is a subnet.
/// The `ip_range` field contains the IPv6 address range if the address space is a range.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub union IpAddressV6Union {
pub ip_subnet: IpSubnetV6,
pub ip_range: IpRangeV6,
}
impl Default for IpAddressV6Union {
fn default() -> Self {
// SAFETY: This union contains either a `IpSubnetV6` or a `IpRangeV6`
// IpSubnetV6: when zeroed is equivalent to ::/0
// IpRangeV6: when zeroed is equivalent to :: - ::
unsafe { std::mem::zeroed() }
}
}
/// This structure is used to store information about an IPv6 address for packet filtering purposes.
///
/// Rust equivalent for [_IP_ADDRESS_V6](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_address_v6/).
///
/// The `address_type` field indicates whether the address is a subnet (IP_SUBNET_V6_TYPE) or a range (IP_RANGE_V6_TYPE).
/// The `address` field contains the specific IPv6 address data, either a subnet or an address range, depending on the `address_type`.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpAddressV6 {
pub address_type: u32, // IP_SUBNET_V6_TYPE or IP_RANGE_V6_TYPE
pub address: IpAddressV6Union,
}
/// This structure is used to define packet filtering rules for IPv6 packets.
///
/// Rust equivalent for [_IP_V6_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ip_v6_filter/).
///
/// The `valid_fields` field contains flags that specify which fields of the filter are active.
/// The `src_address` and `dest_address` fields store information about the source and destination IPv6 addresses respectively.
/// The `protocol` field represents the protocol used in the packet (e.g., TCP, UDP).
/// The `padding` field is reserved for padding to ensure the correct alignment of the structure.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct IpV6Filter {
pub valid_fields: IpV6FilterFlags,
pub src_address: IpAddressV6,
pub dest_address: IpAddressV6,
pub protocol: u8,
pub padding: [u8; 3usize],
}
/// This structure is used to define a range of port numbers for packet filtering rules.
///
/// Rust equivalent for [_PORT_RANGE](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_port_range/).
///
/// The `start_range` field represents the starting port number in the range.
/// The `end_range` field represents the ending port number in the range.
#[repr(C, packed)]
#[derive(Default, Debug, Copy, Clone)]
pub struct PortRange {
pub start_range: u16,
pub end_range: u16,
}
/// This structure is used to define filtering rules for TCP and UDP packets.
///
/// Rust equivalent for [_TCPUDP_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_tcpudp_filter/).
///
/// The `valid_fields` field specifies which fields in the structure are valid for filtering.
/// The `source_port` field represents the range of source port numbers to filter.
/// The `dest_port` field represents the range of destination port numbers to filter.
/// The `tcp_flags` field is used to filter TCP packets based on their flags.
/// The `padding` field ensures proper alignment of the structure.
#[repr(C, packed)]
#[derive(Default, Debug, Copy, Clone)]
pub struct TcpUdpFilter {
pub valid_fields: TcpUdpFilterFlags,
pub source_port: PortRange,
pub dest_port: PortRange,
pub tcp_flags: u8,
pub padding: [u8; 3usize],
}
/// A Rust struct that represents a range of byte values.
///
/// Rust equivalent for _BYTE_RANGE. This structure can be used to define
/// filtering rules based on byte ranges, such as ICMP type or code ranges.
///
/// The `start_range` field represents the start of the byte range.
/// The `end_range` field represents the end of the byte range.
#[repr(C)]
#[derive(Default, Debug, Copy, Clone)]
pub struct ByteRange {
pub start_range: u8,
pub end_range: u8,
}
/// A Rust struct that represents an ICMP filter.
///
/// Rust equivalent for _ICMP_FILTER. This structure can be used to define
/// filtering rules for ICMP packets based on ICMP type and code ranges.
///
/// The `valid_fields` field specifies which fields in the filter are valid for filtering.
/// The `type_range` field represents a range of ICMP types for filtering.
/// The `code_range` field represents a range of ICMP codes for filtering.
#[repr(C, packed)]
#[derive(Default, Debug, Copy, Clone)]
pub struct IcmpFilter {
pub valid_fields: IcmpFilterFlags,
pub type_range: ByteRange,
pub code_range: ByteRange,
}
/// A Rust union that holds an `Eth8023Filter`.
///
/// This union can be extended to include other data link layer filters if needed.
/// Currently, it only contains an `Eth8023Filter` for filtering Ethernet/802.3 packets.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub union DataLinkLayerFilterUnion {
pub eth_8023_filter: Eth8023Filter,
}
impl Default for DataLinkLayerFilterUnion {
fn default() -> Self {
// SAFETY: This union contains an `Eth8023Filter`
// Eth8023Filter: when zeroed is meaningless and ignored by code
unsafe { std::mem::zeroed() }
}
}
/// A Rust struct that represents a data link layer filter.
///
/// Rust equivalent for [_DATA_LINK_LAYER_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/data_link_layer_filter/)
/// This struct can be used to filter packets at the data link layer (e.g., Ethernet/802.3) by specifying the filter type in `union_selector`.
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct DataLinkLayerFilter {
pub union_selector: u32, // ETH_802_3 for Eth8023Filter
pub data_link_layer: DataLinkLayerFilterUnion,
}
/// A Rust union that holds either an `IpV4Filter` or an `IpV6Filter`.
///
/// This union can be used to filter packets at the network layer by specifying the appropriate filter type (IPv4 or IPv6).
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub union NetworkLayerFilterUnion {
pub ipv4: IpV4Filter,
pub ipv6: IpV6Filter,
}
impl Default for NetworkLayerFilterUnion {
fn default() -> Self {
// SAFETY: This union contains either a `IpV4Filter` or `IpV6Filter'
// IpV4Filter: when zeroed is meaningless and ignored by code
// IpV6Filter: when zeroed is meaningless and ignored by code
unsafe { std::mem::zeroed() }
}
}
/// A Rust struct that represents a network layer filter.
///
/// Rust equivalent for [_NETWORK_LAYER_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_network_layer_filter/).
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct NetworkLayerFilter {
/// union_selector: A field that determines the type of the network layer filter.
/// Set to IPV4 for IpV4Filter, and IPV6 for IpV6Filter.
pub union_selector: u32,
/// network_layer: A union that holds either an IpV4Filter or an IpV6Filter,
/// depending on the value of the union_selector field.
pub network_layer: NetworkLayerFilterUnion,
}
/// A Rust union that represents a transport layer filter.
///
/// Holds either a `TcpUdpFilter` or an `IcmpFilter`.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub union TransportLayerFilterUnion {
/// tcp_udp: A TcpUdpFilter struct that represents a TCP/UDP filter.
pub tcp_udp: TcpUdpFilter,
/// icmp: An IcmpFilter struct that represents an ICMP filter.
pub icmp: IcmpFilter,
}
impl Default for TransportLayerFilterUnion {
fn default() -> Self {
// SAFETY: This union contains either a `TcpUdpFilter` or an `IcmpFilter`
// TcpUdpFilter: when zeroed is meaningless and ignored by code
// IcmpFilter: when zeroed is meaningless and ignored by code
unsafe { std::mem::zeroed() }
}
}
/// A Rust struct that represents a transport layer filter.
///
/// Rust equivalent for [_TRANSPORT_LAYER_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_transport_layer_filter/)
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct TransportLayerFilter {
/// union_selector: A u32 flag that selects the appropriate filter.
/// Use TCPUDP for TcpUdpFilter and ICMP for IcmpFilter.
pub union_selector: u32,
/// transport_layer: A TransportLayerFilterUnion that holds either a `TcpUdpFilter` or an `IcmpFilter`.
pub transport_layer: TransportLayerFilterUnion,
}
/// This structure is used to define a single static filter rule for packet filtering. Each rule can specify filtering criteria at
/// the data link, network, and transport layers. The structure also includes counters for incoming and outgoing packets and bytes
/// that match the filter rule.
///
/// * Rust equivalent for [_STATIC_FILTER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_static_filter/)
#[repr(C, packed)]
#[derive(Default, Copy, Clone)]
pub struct StaticFilter {
/// Adapter handle extended to 64 bit size for structure compatibility across x64 and x86 architectures
pub adapter_handle: u64,
/// PACKET_FLAG_ON_SEND or/and PACKET_FLAG_ON_RECEIVE to specify the direction of packets to match
pub direction_flags: DirectionFlags,
/// FILTER_PACKET_XXX to define the action to take when a packet matches the filter
pub filter_action: u32,
/// Specifies which of the fields below contain valid values and should be matched against the packet
pub valid_fields: FilterLayerFlags,
/// Time of the last counters reset (in seconds passed since 1 Jan 1980)
pub last_reset: u32,
/// Incoming packets passed through this filter
pub packets_in: u64,
/// Incoming bytes passed through this filter
pub bytes_in: u64,
/// Outgoing packets passed through this filter
pub packets_out: u64,
/// Outgoing bytes passed through this filter
pub bytes_out: u64,
/// Filter criteria for the data link layer (e.g., Ethernet)
pub data_link_filter: DataLinkLayerFilter,
/// Filter criteria for the network layer (e.g., IPv4, IPv6)
pub network_filter: NetworkLayerFilter,
/// Filter criteria for the transport layer (e.g., TCP, UDP, ICMP)
pub transport_filter: TransportLayerFilter,
}
/// This structure represents an array of static filter rules, each of which is defined by a `StaticFilter` structure.
/// It is used to manage multiple filter rules for packet filtering in a table format.
///
/// * Rust equivalent to the [_STATIC_FILTER_TABLE](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_static_filter_table/)
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct StaticFilterTable<const N: usize> {
/// The number of elements in the static_filters array
pub table_size: u32,
/// Padding to ensure correct memory alignment
pub padding: u32,
/// Array of static filter rules
pub static_filters: [StaticFilter; N],
}
impl<const N: usize> StaticFilterTable<N> {
/// Creates a new `StaticFilterTable` with the specified number of elements.
pub fn new() -> Self {
Self {
table_size: N as u32,
padding: 0u32,
static_filters: [StaticFilter::default(); N],
}
}
}
impl<const N: usize> Default for StaticFilterTable<N> {
/// Initializes a new `StaticFilterTable` with the specified number of elements and default values for each element.
fn default() -> Self {
Self::new()
}
}