ndisapi_rs/driver/base.rs
1//! # Submodule: Basic NDISAPI Structures
2//!
3//! This submodule provides Rust equivalents of several structures used in the NDISAPI Rust library
4//! for communicating with the Windows Packet Filter driver.
5//!
6//! The structures in this submodule are related to network adapters, Ethernet packets, adapter events,
7//! and Remote Access Service (RAS) links.
8//!
9//! For a detailed description of each structure, refer to their respective documentation within the
10//! submodule.
11
12// Import required external crates and types
13use std::mem::size_of;
14use windows::{
15 core::Result,
16 Win32::Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_INVALID_PARAMETER, HANDLE},
17};
18
19use super::constants::*;
20
21/// The `TcpAdapterList` structure is the Rust equivalent of the
22/// [_TCP_AdapterList](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_tcp_adapterlist/)
23/// structure in the Windows Packet Filter documentation. It represents a list of network adapters,
24/// along with their properties, such as adapter names, handles, medium types, current addresses, and MTUs.
25///
26/// # Fields
27///
28/// * `adapter_count`: A 32-bit unsigned integer representing the total number of adapters in the list.
29/// * `adapter_name_list`: An array of arrays, with each inner array containing `ADAPTER_NAME_SIZE` bytes,
30/// representing the adapter names in the list.
31/// * `adapter_handle`: An array of `HANDLE` values, representing the handles of the adapters in the list.
32/// * `adapter_medium_list`: An array of 32-bit unsigned integers, representing the medium types of the
33/// adapters in the list.
34/// * `current_address`: An array of arrays, with each inner array containing `ETHER_ADDR_LENGTH` bytes,
35/// representing the current addresses of the adapters in the list.
36/// * `mtu`: An array of 16-bit unsigned integers, representing the Maximum Transmission Units (MTUs) of the
37/// adapters in the list.
38#[repr(C, packed)]
39#[derive(Debug, Copy, Clone)]
40pub struct TcpAdapterList {
41 pub adapter_count: u32,
42 pub adapter_name_list: [[u8; ADAPTER_NAME_SIZE]; ADAPTER_LIST_SIZE],
43 pub adapter_handle: [HANDLE; ADAPTER_LIST_SIZE],
44 pub adapter_medium_list: [u32; ADAPTER_LIST_SIZE],
45 pub current_address: [[u8; ETHER_ADDR_LENGTH]; ADAPTER_LIST_SIZE],
46 pub mtu: [u16; ADAPTER_LIST_SIZE],
47}
48
49/// The `ListEntry` structure is the Rust equivalent of the
50/// [_LIST_ENTRY](https://learn.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-list_entry)
51/// structure in the Windows API. It represents a doubly-linked list entry, containing forward and backward
52/// pointers to adjacent list entries.
53///
54/// # Fields
55///
56/// * `flink`: A mutable raw pointer to the next `ListEntry` in the list (forward link).
57/// * `blink`: A mutable raw pointer to the previous `ListEntry` in the list (backward link).
58#[repr(C)]
59#[derive(Debug, Copy, Clone)]
60pub struct ListEntry {
61 pub flink: *mut ListEntry,
62 pub blink: *mut ListEntry,
63}
64
65/// The `IntermediateBufferHeaderUnion` structure is the Rust equivalent of the union
66/// used for `INTERMEDIATE_BUFFER` in the driver API. It represents a union between a
67/// `HANDLE` and a `ListEntry`, providing a way to access either of them based on the context.
68///
69/// # Fields
70///
71/// * `adapter_handle`: A `HANDLE` representing the adapter handle.
72/// * `list_entry`: A `ListEntry` structure representing a doubly-linked list entry.
73#[repr(C, packed)]
74#[derive(Copy, Clone)]
75pub union IntermediateBufferHeaderUnion {
76 pub adapter_handle: HANDLE,
77 pub list_entry: ListEntry,
78}
79
80/// Provides a default implementation for the `IntermediateBufferHeaderUnion` structure.
81///
82/// # Safety
83///
84/// This implementation is safe because the union contains either a `HANDLE` or a `ListEntry`.
85/// The `ListEntry` is a union of raw pointers, which can be safely zeroed as long as they are not dereferenced.
86/// The `HANDLE` is a wrapper around an `isize`, which can also be safely zeroed.
87impl Default for IntermediateBufferHeaderUnion {
88 fn default() -> Self {
89 // SAFETY: This union contains either a `HANDLE` or a `ListEntry`
90 // ListEntry: is an union of raw pointers which can be safely zeroed(as long as you not dereference it)
91 // HANDLE: is just an `isize` wrapper which can also be zeroed
92 unsafe { core::mem::zeroed() }
93 }
94}
95
96/// The `IntermediateBuffer` structure represents an intermediate buffer that stores packet data along with some
97/// additional information. This structure is used internally by the packet filter driver.
98///
99/// Rust equivalent for [_INTERMEDIATE_BUFFER](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_intermediate_buffer/).
100///
101/// # Fields
102/// * `header`: An `IntermediateBufferHeaderUnion` which is a union of `HANDLE` and `ListEntry`.
103/// * `device_flags`: A `DirectionFlags` value that indicates the direction of the packet (send or receive).
104/// * `length`: A `u32` representing the length of the packet data.
105/// * `flags`: A `u32` value containing various flags related to the packet.
106/// * `vlan_8021q`: A `u32` value representing the VLAN tag (802.1Q) associated with the packet.
107/// * `filter_id`: A `u32` value identifying the filter that processed the packet.
108/// * `reserved`: A reserved `[u32; 4usize]` array for future use.
109/// * `buffer`: A `Buffer` structure containing the actual packet data.
110#[repr(C, packed)]
111#[derive(Copy, Clone, Default)]
112pub struct IntermediateBuffer {
113 pub header: IntermediateBufferHeaderUnion,
114 pub device_flags: DirectionFlags,
115 pub length: u32,
116 pub flags: u32,
117 pub vlan_8021q: u32,
118 pub filter_id: u32,
119 pub reserved: [u32; 4usize],
120 pub buffer: Buffer,
121}
122
123/// This structure represents the buffer used for storing the actual packet data.
124///
125/// A wrapper around an array of bytes with a size of `MAX_ETHER_FRAME`.
126#[repr(transparent)]
127#[derive(Copy, Clone)]
128pub struct Buffer(pub [u8; MAX_ETHER_FRAME]);
129
130impl Default for Buffer {
131 fn default() -> Self {
132 Self([0; MAX_ETHER_FRAME])
133 }
134}
135
136/// IntermediateBuffer implementation
137impl IntermediateBuffer {
138 /// Creates a new `IntermediateBuffer` with default values.
139 ///
140 /// # Returns
141 /// A new `IntermediateBuffer` instance.
142 pub fn new() -> Self {
143 Self::default()
144 }
145
146 /// Gets the `DirectionFlags` value associated with the `IntermediateBuffer`.
147 ///
148 /// # Returns
149 /// The `DirectionFlags` value indicating the direction of the packet (send or receive).
150 pub fn get_device_flags(&self) -> DirectionFlags {
151 self.device_flags
152 }
153
154 /// Gets the length of the packet data stored in the `IntermediateBuffer`.
155 ///
156 /// # Returns
157 /// A `u32` value representing the length of the packet data.
158 pub fn get_length(&self) -> u32 {
159 self.length
160 }
161
162 /// Sets the length of the packet data stored in the `IntermediateBuffer`.
163 ///
164 /// # Arguments
165 /// * `length`: A `u32` value representing the new length of the packet data.
166 pub fn set_length(&mut self, length: u32) {
167 self.length = length
168 }
169
170 /// Returns a reference to the data stored in the buffer.
171 ///
172 /// This method returns a reference to the data stored in the buffer as a slice of bytes.
173 /// The length of the slice is determined by the `length` field of the `buffer` struct.
174 pub fn get_data(&self) -> &[u8] {
175 &self.buffer.0[..self.length as usize]
176 }
177
178 /// Returns a mutable reference to the data stored in the buffer.
179 ///
180 /// This method returns a mutable reference to the data stored in the buffer as a slice of bytes.
181 /// The length of the slice is determined by the `length` field of the `buffer` struct.
182 pub fn get_data_mut(&mut self) -> &mut [u8] {
183 &mut self.buffer.0[..self.length as usize]
184 }
185}
186
187/// This structure is used to define the mode of an adapter with a specified handle and filter flags.
188///
189/// A Rust equivalent for the [_ADAPTER_MODE](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/adapter_mode/) structure.
190#[repr(C, packed)]
191#[derive(Debug, Copy, Clone, Default)]
192pub struct AdapterMode {
193 /// A `HANDLE` representing the adapter handle.
194 pub adapter_handle: HANDLE,
195 /// `FilterFlags` representing the filter flags associated with the adapter mode.
196 pub flags: FilterFlags,
197}
198
199/// This structure represents an Ethernet packet with an optional mutable reference to an `IntermediateBuffer`.
200///
201/// A Rust equivalent for the [_NDISRD_ETH_Packet](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ndisrd_eth_packet/) structure.
202///
203/// The `buffer` field is an Option wrapping a mutable reference to an `IntermediateBuffer`. This design allows for flexibility
204/// when manipulating Ethernet packets, as a packet may not always have a buffer associated with it (i.e., the buffer may be `None`).
205#[repr(C)]
206pub struct EthPacket<'a> {
207 /// An optional mutable reference to an `IntermediateBuffer` representing the buffer for this Ethernet packet.
208 pub buffer: Option<&'a mut IntermediateBuffer>,
209}
210
211/// Implements the `Into` trait for `EthPacket`.
212///
213/// The purpose of this implementation is to facilitate the conversion of an `EthPacket` into an `Option<&'a mut IntermediateBuffer>`.
214///
215/// The conversion is valuable when there is a need to directly manipulate the buffer of a packet. By implementing `Into` for `EthPacket`,
216/// we provide a convenient and idiomatic way to perform this transformation.
217impl<'a> From<EthPacket<'a>> for Option<&'a mut IntermediateBuffer> {
218 fn from(val: EthPacket<'a>) -> Self {
219 val.buffer
220 }
221}
222
223/// Implements the `Default` trait for `EthPacket`.
224///
225/// This implementation allows for the creation of an "empty" `EthPacket`, i.e., a packet without a buffer. This is useful when
226/// initializing a variable of type `EthPacket` without immediately associating a buffer with it.
227impl<'a> Default for EthPacket<'a> {
228 fn default() -> Self {
229 EthPacket { buffer: None }
230 }
231}
232
233/// This structure represents a request for an Ethernet packet, containing a network adapter handle and an `EthPacket`.
234///
235/// A Rust equivalent for the [_ETH_REQUEST](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_eth_request/) structure.
236///
237/// `adapter_handle` is a handle to the network adapter associated with this request. The `packet` field is an `EthPacket` that represents the Ethernet packet for this request.
238#[repr(C)]
239pub struct EthRequest<'a> {
240 /// A handle to the network adapter associated with this request.
241 pub adapter_handle: HANDLE,
242 /// An `EthPacket` representing the Ethernet packet for this request.
243 pub packet: EthPacket<'a>,
244}
245
246/// Provides methods for manipulating the `EthPacket` within an `EthRequest`.
247impl<'a> EthRequest<'a> {
248 /// Creates a new `EthRequest` with the specified adapter handle and an empty `EthPacket`.
249 ///
250 /// # Arguments
251 ///
252 /// * `adapter_handle` - A handle to the network adapter to be associated with this request.
253 ///
254 /// # Returns
255 ///
256 /// * A new `EthRequest` instance with the specified adapter handle and an empty `EthPacket`.
257 pub fn new(adapter_handle: HANDLE) -> Self {
258 Self {
259 adapter_handle,
260 packet: EthPacket { buffer: None },
261 }
262 }
263
264 /// Takes the `EthPacket` out from the `EthRequest`, replacing it with `None`.
265 ///
266 /// This is useful when you want to use the packet's buffer elsewhere, while ensuring that the `EthRequest` no longer has access to it.
267 pub fn take_packet(&mut self) -> Option<&'a mut IntermediateBuffer> {
268 self.packet.buffer.take()
269 }
270
271 /// Sets the `EthPacket` for the `EthRequest` using a mutable reference to an `IntermediateBuffer`.
272 ///
273 /// This method allows you to associate a new buffer with the `EthRequest`. This is useful when you have a buffer that you want to send with the `EthRequest`.
274 pub fn set_packet(&mut self, buffer: &'a mut IntermediateBuffer) {
275 self.packet = EthPacket {
276 buffer: Some(buffer),
277 };
278 }
279}
280
281/// This structure represents a request for multiple Ethernet packets, containing a network adapter handle, packet number, packet success count, and an array of `EthPacket` instances.
282///
283/// A Rust equivalent for the [_ETH_M_REQUEST](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_eth_m_request/) structure.
284///
285/// `adapter_handle` is a handle to the network adapter associated with this request. `packet_number` is the number of packets in the `packets` array. `packet_success` is the number of packets that have been successfully processed. `packets` is an array of `EthPacket` instances representing the Ethernet packets for this request.
286#[repr(C)]
287pub struct EthMRequest<'a, const N: usize> {
288 /// A handle to the network adapter associated with this request.
289 adapter_handle: HANDLE,
290 /// The number of packets in the `packets` array.
291 packet_number: u32,
292 /// The number of successfully processed packets.
293 packet_success: u32,
294 /// An array of `EthPacket` representing the Ethernet packets for this request.
295 packets: [EthPacket<'a>; N],
296}
297
298/// Provides methods for manipulating the `EthPacket` instances within an `EthMRequest`.
299impl<'a, const N: usize> EthMRequest<'a, N> {
300 /// Creates a new `EthMRequest` with the specified adapter handle.
301 ///
302 /// All packets in the request are initialized to empty.
303 pub fn new(adapter_handle: HANDLE) -> Self {
304 let packets = [(); N].map(|_| EthPacket { buffer: None });
305 Self {
306 adapter_handle,
307 packet_number: 0,
308 packet_success: 0,
309 packets,
310 }
311 }
312
313 /// Creates a new `EthMRequest` from an iterator over `&mut IntermediateBuffer`.
314 ///
315 /// This constructor will attempt to consume up to `N` items from the iterator to initialize the `packets` array.
316 /// If the iterator contains fewer than `N` items, the remaining entries in the `packets` array will be left as `None`.
317 ///
318 /// # Arguments
319 ///
320 /// * `adapter_handle`: A handle to the network adapter associated with this request.
321 /// * `iter`: An iterator over mutable references to `IntermediateBuffer`.
322 ///
323 /// # Returns
324 ///
325 /// A new `EthMRequest`.
326 pub fn from_iter(
327 adapter_handle: HANDLE,
328 iter: impl Iterator<Item = &'a mut IntermediateBuffer>,
329 ) -> Self {
330 let mut packets = [(); N].map(|_| EthPacket { buffer: None });
331 let mut packet_number = 0;
332
333 for (buffer, packet) in iter.zip(packets.iter_mut()) {
334 packet.buffer = Some(buffer);
335 packet_number += 1;
336 }
337
338 Self {
339 adapter_handle,
340 packet_number,
341 packet_success: 0,
342 packets,
343 }
344 }
345
346 /// Returns an iterator that yields `Some(IntermediateBuffer)` for each non-empty buffer in `packets`, in order,
347 /// up to `packet_success`.
348 ///
349 /// # Description
350 ///
351 /// This function, `drain_success`, operates on mutable reference to the current instance of the struct.
352 /// It returns an iterator that goes over each non-empty buffer in `packets`, in their
353 /// original order, but only up to the index specified by `packet_success`. This iterator will
354 /// yield `Some(IntermediateBuffer)` for each of these buffers. These buffers represent packets
355 /// that have been successfully read from the driver.
356 ///
357 /// Once called, this method drains the non-empty buffers from `packets`, up to `packet_success` making them empty (`None`).
358 ///
359 /// # Returns
360 ///
361 /// This function returns an implementation of Iterator trait. The iterator item type is a mutable reference
362 /// to an `IntermediateBuffer` (`&'a mut IntermediateBuffer`). This iterator can be used to iterate over the drained buffers.
363 pub fn drain_success(&mut self) -> impl Iterator<Item = &'a mut IntermediateBuffer> + '_ {
364 self.packets
365 .iter_mut()
366 .take(self.packet_success as usize)
367 .filter_map(|packet| {
368 if packet.buffer.is_some() {
369 self.packet_number -= 1;
370 packet.buffer.take()
371 } else {
372 None
373 }
374 })
375 }
376
377 /// Returns an iterator that yields `Some(IntermediateBuffer)` for each non-empty buffer in `packets`.
378 ///
379 /// # Description
380 ///
381 /// This function, `drain`, operates on mutable reference to the current instance of the struct.
382 /// It returns an iterator which yields mutable references to `IntermediateBuffer` for each non-empty buffer in `packets`,
383 /// and it yields them in the order they occur in `packets`.
384 ///
385 /// Once called, this method drains the non-empty buffers from `packets`, making them empty (`None`).
386 ///
387 /// # Returns
388 ///
389 /// This function returns an implementation of Iterator trait. The iterator item type is a mutable reference
390 /// to an `IntermediateBuffer` (`&'a mut IntermediateBuffer`). This iterator can be used to iterate over the drained buffers.
391 pub fn drain(&mut self) -> impl Iterator<Item = &'a mut IntermediateBuffer> + '_ {
392 self.packets.iter_mut().filter_map(|packet| {
393 if packet.buffer.is_some() {
394 self.packet_number -= 1;
395 packet.buffer.take()
396 } else {
397 None
398 }
399 })
400 }
401
402 /// Sets the `IntermediateBuffer` for the `EthPacket` at the specified index.
403 ///
404 /// This method allows you to associate a new buffer with the `EthPacket` at the given index.
405 fn set_packet(&mut self, index: usize, buffer: &'a mut IntermediateBuffer) -> Result<()> {
406 if index < N {
407 self.packets[index].buffer = Some(buffer);
408 Ok(())
409 } else {
410 Err(ERROR_INVALID_PARAMETER.into())
411 }
412 }
413
414 /// Returns the number of packets in the `packets` array.
415 ///
416 /// This provides a count of all packets, regardless of whether they've been successfully processed.
417 pub fn get_packet_number(&self) -> u32 {
418 self.packet_number
419 }
420
421 /// Erases all `EthPacket` instances within the `packets` array and releases all references.
422 ///
423 /// After this method is called, all `EthPacket` instances within the `packets` array will be empty (i.e., their `buffer` fields will be `None`), and the packet number will be reset to 0.
424 pub fn reset(&mut self) {
425 for packet in self.packets.iter_mut() {
426 packet.buffer = None;
427 }
428 self.packet_number = 0;
429 self.packet_success = 0;
430 }
431
432 /// Returns the number of successfully processed packets
433 pub fn get_packet_success(&self) -> u32 {
434 self.packet_success
435 }
436
437 /// Adds an `IntermediateBuffer` to the `packets` array if there's available space.
438 /// This effectively wraps the buffer into an `EthPacket` and stores it in the array.
439 ///
440 /// The `packet_number` field of the `EthMRequest` is automatically incremented to reflect the addition of the new packet.
441 ///
442 /// If there is no available space in the array (i.e., if the `packet_number` is equal to the array length `N`), this method returns an error, specifically `ERROR_INVALID_PARAMETER`.
443 ///
444 /// This method provides an idiomatic way of adding new packets to an `EthMRequest` in Rust.
445 ///
446 /// # Arguments
447 ///
448 /// * `packet` - A mutable reference to the `IntermediateBuffer` to be added to the `packets` array.
449 ///
450 /// # Returns
451 ///
452 /// * `Ok(())` if the buffer was successfully added as a packet.
453 /// * `Err(ERROR_BUFFER_OVERFLOW.into())` if the `packets` array is full.
454 pub fn push(&mut self, packet: &'a mut IntermediateBuffer) -> Result<()> {
455 if (self.packet_number as usize) < N {
456 if let Some(index) = self.first_empty_packet() {
457 self.packets[index] = EthPacket {
458 buffer: Some(packet),
459 };
460 self.packet_number += 1;
461 Ok(())
462 } else {
463 Err(ERROR_BUFFER_OVERFLOW.into())
464 }
465 } else {
466 Err(ERROR_BUFFER_OVERFLOW.into())
467 }
468 }
469
470 /// Returns the index of the first `EthPacket` which contains `None`.
471 ///
472 /// # Returns
473 /// * An `Option<usize>` representing the index of the first empty `EthPacket`.
474 /// If no empty `EthPacket` is found, returns `None`.
475 fn first_empty_packet(&self) -> Option<usize> {
476 self.packets
477 .iter()
478 .position(|packet| packet.buffer.is_none())
479 }
480
481 /// Consumes packets from an Iterator, moving them into `self`.
482 ///
483 /// # Arguments
484 /// * `packets` - An iterator yielding mutable references to IntermediateBuffer.
485 ///
486 /// # Returns
487 /// * Result indicating success or failure.
488 pub fn append<I>(&mut self, packets: I) -> Result<()>
489 where
490 I: Iterator<Item = &'a mut IntermediateBuffer>,
491 {
492 for buffer in packets {
493 if self.packet_number as usize >= N {
494 return Err(ERROR_BUFFER_OVERFLOW.into());
495 }
496
497 if let Some(empty_slot) = self.first_empty_packet() {
498 self.set_packet(empty_slot, buffer)?;
499 self.packet_number += 1;
500 } else {
501 return Err(ERROR_BUFFER_OVERFLOW.into());
502 }
503 }
504
505 Ok(())
506 }
507}
508
509/// This structure represents an adapter event, containing an adapter handle and an event handle.
510///
511/// A Rust equivalent for the [_ADAPTER_EVENT](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/adapter_event/) structure.
512#[repr(C, packed)]
513#[derive(Debug, Copy, Clone)]
514pub struct AdapterEvent {
515 /// A handle to the network adapter associated with this event.
516 pub adapter_handle: HANDLE,
517 /// A handle to the event associated with this adapter.
518 pub event_handle: HANDLE,
519}
520
521/// This structure is used to make queries or set parameters on a network adapter.
522///
523/// A Rust equivalent for the [_PACKET_OID_DATA](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_packet_oid_data/) structure.
524#[repr(C, packed)]
525pub struct PacketOidData<T> {
526 /// A handle to the network adapter associated with this query or parameter setting.
527 pub adapter_handle: HANDLE,
528 /// The OID (Object Identifier) that represents the query or parameter to be set.
529 pub oid: u32,
530 /// The length of the data in bytes.
531 pub length: u32,
532 /// The data associated with the query or parameter.
533 pub data: T,
534}
535
536impl<T> PacketOidData<T> {
537 /// Creates a new PacketOidData instance.
538 ///
539 /// # Arguments
540 ///
541 /// * `adapter_handle` - A handle to the network adapter associated with this query or parameter setting.
542 /// * `oid` - The OID (Object Identifier) that represents the query or parameter to be set.
543 /// * `data` - The data associated with the query or parameter.
544 pub fn new(adapter_handle: HANDLE, oid: u32, data: T) -> Self {
545 Self {
546 adapter_handle,
547 oid,
548 length: size_of::<T>() as u32,
549 data,
550 }
551 }
552}
553
554/// This structure contains information about a RAS (Remote Access Service) link.
555///
556/// A Rust equivalent for the [_RAS_LINK_INFO](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ras_link_info/) structure.
557#[repr(C, packed)]
558#[derive(Debug, Copy, Clone)]
559pub struct RasLinkInformation {
560 /// The link speed in bits per second.
561 link_speed: u32,
562 /// The maximum total size, in bytes.
563 maximum_total_size: u32,
564 /// The remote MAC address.
565 remote_address: [u8; ETHER_ADDR_LENGTH],
566 /// The local MAC address.
567 local_address: [u8; ETHER_ADDR_LENGTH],
568 /// The length of the protocol buffer, in bytes.
569 protocol_buffer_length: u32,
570 /// The buffer containing information about the RAS-managed protocols.
571 protocol_buffer: [u8; RAS_LINK_BUFFER_LENGTH],
572}
573
574impl RasLinkInformation {
575 /// Returns the link speed in bits per second.
576 pub fn get_link_speed(&self) -> u32 {
577 self.link_speed
578 }
579
580 /// Returns the maximum total size.
581 pub fn get_maximum_total_size(&self) -> u32 {
582 self.maximum_total_size
583 }
584
585 /// Returns the remote MAC address.
586 pub fn get_remote_address(&self) -> &[u8; ETHER_ADDR_LENGTH] {
587 &self.remote_address
588 }
589
590 /// Returns the local MAC address.
591 pub fn get_local_address(&self) -> &[u8; ETHER_ADDR_LENGTH] {
592 &self.local_address
593 }
594
595 /// Returns the length of the protocol buffer, in bytes.
596 pub fn get_protocol_buffer_length(&self) -> usize {
597 self.protocol_buffer_length as usize
598 }
599
600 /// Returns the buffer containing information about the RAS-managed protocols.
601 pub fn get_protocol_buffer(&self) -> &[u8; RAS_LINK_BUFFER_LENGTH] {
602 &self.protocol_buffer
603 }
604}
605
606/// This structure is a container for RAS (Remote Access Service) link information structures.
607///
608/// A Rust equivalent for the [_RAS_LINKS](https://www.ntkernel.com/docs/windows-packet-filter-documentation/structures/_ras_links/) structure.
609/// Note that this struct may be too large to be allocated on the stack in Rust and may result in a stack overflow.
610#[repr(C, packed)]
611#[derive(Debug, Copy, Clone)]
612pub struct RasLinks {
613 /// The number of RAS links in the array.
614 number_of_links: u32,
615 /// The array of RAS link information structures.
616 pub ras_links: [RasLinkInformation; RAS_LINKS_MAX],
617}
618
619impl Default for RasLinks {
620 /// Returns a zero-initialized instance of `RasLinks`.
621 ///
622 /// # Safety
623 ///
624 /// This structure is filled by the information by NDIS filter driver when passed as a memory buffer
625 /// along with IOCTL_NDISRD_GET_RAS_LINKS. It is safe to be zeroed because contains only values and arrays that
626 /// can be default initialized with zeroes.
627 fn default() -> Self {
628 unsafe { std::mem::zeroed() }
629 }
630}
631
632impl RasLinks {
633 /// Returns the number of RAS links in the array.
634 pub fn get_number_of_links(&self) -> usize {
635 self.number_of_links as usize
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::*;
642
643 #[test]
644 fn size_of_ethpacket() {
645 assert_eq!(
646 std::mem::size_of::<*mut IntermediateBuffer>(),
647 std::mem::size_of::<EthPacket>()
648 );
649 }
650
651 #[test]
652 fn size_of_ethrequest() {
653 assert_eq!(
654 std::mem::size_of::<EthPacket>() + std::mem::size_of::<HANDLE>(),
655 std::mem::size_of::<EthRequest>()
656 );
657 }
658
659 #[test]
660 fn size_of_ethmrequest() {
661 assert_eq!(
662 std::mem::size_of::<EthPacket>()
663 + std::mem::size_of::<HANDLE>()
664 + 2 * std::mem::size_of::<u32>(),
665 std::mem::size_of::<EthMRequest<1>>()
666 );
667 }
668}