ndisapi_rs/ndisapi/fastio_api.rs
1//! # Submodule: Fast I/O operations
2//!
3//! This submodule offers methods to interact with the NDIS filter driver, allowing users to
4//! initialize the fast I/O mechanism, add a secondary fast I/O shared memory sections, and forward
5//! packets to the driver or to the target network interface or protocol layer. The methods in this
6//! submodule are designed to be highly flexible, allowing for parameterization by the size of the shared
7//! memory section or the number of packets to send. This submodule is part of the larger NDISAPI module,
8//! which provides a high-level API for the Windows Packet Filter on Windows.
9//!
10
11use std::mem::size_of;
12
13use windows::{core::Result, Win32::Foundation::GetLastError, Win32::System::IO::DeviceIoControl};
14
15use super::Ndisapi;
16use crate::driver::*;
17
18impl Ndisapi {
19 /// This function adds a secondary Fast I/O shared memory section to the NDIS filter driver,
20 /// allowing faster communication between user-mode applications and the driver.
21 ///
22 /// # Type Parameters
23 ///
24 /// * `N`: The size of the Fast I/O shared memory section.
25 ///
26 /// # Arguments
27 ///
28 /// * `fast_io_section`: A mutable reference to a `FastIoSection<N>` object representing
29 /// the shared memory section to be added.
30 ///
31 /// # Returns
32 ///
33 /// * `Result<()>`: If successful, returns `Ok(())`. Otherwise, returns an error.
34 pub fn add_secondary_fast_io<const N: usize>(
35 &self,
36 fast_io_section: &mut FastIoSection<N>,
37 ) -> Result<()> {
38 let params = InitializeFastIoParams::<N> {
39 header_ptr: fast_io_section as *mut FastIoSection<N>,
40 data_size: N as u32,
41 };
42
43 let result = unsafe {
44 DeviceIoControl(
45 self.driver_handle,
46 IOCTL_NDISRD_ADD_SECOND_FAST_IO_SECTION,
47 Some(¶ms as *const InitializeFastIoParams<N> as *const std::ffi::c_void),
48 size_of::<InitializeFastIoParams<N>>() as u32,
49 None,
50 0,
51 None,
52 None,
53 )
54 };
55
56 if !result.as_bool() {
57 Err(unsafe { GetLastError() }.into())
58 } else {
59 Ok(())
60 }
61 }
62
63 /// This function initializes the fast I/O mechanism for the NDIS filter driver and
64 /// submits the initial shared memory section for faster communication between
65 /// user-mode applications and the driver.
66 ///
67 /// # Type Parameters
68 ///
69 /// * `N`: The size of the Fast I/O shared memory section.
70 ///
71 /// # Arguments
72 ///
73 /// * `fast_io_section`: A mutable reference to a `FastIoSection<N>` object representing
74 /// the shared memory section to be submitted.
75 ///
76 /// # Returns
77 ///
78 /// * `Result<()>`: If successful, returns `Ok(())`. Otherwise, returns an error.
79 pub fn initialize_fast_io<const N: usize>(
80 &self,
81 fast_io_section: &mut FastIoSection<N>,
82 ) -> Result<()> {
83 let params = InitializeFastIoParams::<N> {
84 header_ptr: fast_io_section as *mut FastIoSection<N>,
85 data_size: N as u32,
86 };
87
88 let result = unsafe {
89 DeviceIoControl(
90 self.driver_handle,
91 IOCTL_NDISRD_INITIALIZE_FAST_IO,
92 Some(¶ms as *const InitializeFastIoParams<N> as *const std::ffi::c_void),
93 size_of::<InitializeFastIoParams<N>>() as u32,
94 None,
95 0,
96 None,
97 None,
98 )
99 };
100
101 if !result.as_bool() {
102 Err(unsafe { GetLastError() }.into())
103 } else {
104 Ok(())
105 }
106 }
107
108 /// This function retrieves queued packets from the NDIS filter driver without considering
109 /// the network interface. It reads packets in an unsorted manner and stores them in the
110 /// provided buffer.
111 ///
112 /// # Type Parameters
113 ///
114 /// * `N`: The number of packets to read.
115 ///
116 /// # Arguments
117 ///
118 /// * `packets`: A mutable reference to an array of `IntermediateBuffer` objects, where the
119 /// read packets will be stored.
120 ///
121 /// # Returns
122 ///
123 /// * `Result<usize>`: If successful, returns `Ok(usize)` with the number of packets read.
124 /// Otherwise, returns an error.
125 pub fn read_packets_unsorted<const N: usize>(
126 &self,
127 packets: &mut [IntermediateBuffer; N],
128 ) -> Result<usize> {
129 let mut request = UnsortedReadSendRequest::<N> {
130 packets: packets as *mut [IntermediateBuffer; N],
131 packets_num: N as u32,
132 };
133
134 let result = unsafe {
135 DeviceIoControl(
136 self.driver_handle,
137 IOCTL_NDISRD_READ_PACKETS_UNSORTED,
138 Some(&request as *const UnsortedReadSendRequest<N> as *const std::ffi::c_void),
139 size_of::<UnsortedReadSendRequest<N>>() as u32,
140 Some(&mut request as *mut UnsortedReadSendRequest<N> as *mut std::ffi::c_void),
141 size_of::<UnsortedReadSendRequest<N>>() as u32,
142 None,
143 None,
144 )
145 };
146
147 if !result.as_bool() {
148 Err(unsafe { GetLastError() }.into())
149 } else {
150 Ok(request.packets_num as usize)
151 }
152 }
153
154 /// This function forwards packets to the NDIS filter driver in an unsorted manner, which then
155 /// sends them to the target network interface. The target adapter handle should be set in the
156 /// `IntermediateBuffer.header.adapter_handle` field.
157 ///
158 /// # Type Parameters
159 ///
160 /// * `N`: The number of packets to send.
161 ///
162 /// # Arguments
163 ///
164 /// * `packets`: A mutable reference to an array of `IntermediateBuffer` objects, which contain
165 /// the packets to be sent.
166 /// * `packets_num`: The number of packets to send from the array.
167 ///
168 /// # Returns
169 ///
170 /// * `Result<usize>`: If successful, returns `Ok(usize)` with the number of packets sent.
171 /// Otherwise, returns an error.
172 pub fn send_packets_to_adapters_unsorted<const N: usize>(
173 &self,
174 packets: &mut [IntermediateBuffer; N],
175 packets_num: usize,
176 ) -> Result<usize> {
177 let mut request = UnsortedReadSendRequest::<N> {
178 packets: packets as *mut [IntermediateBuffer; N],
179 packets_num: packets_num as u32,
180 };
181
182 let result = unsafe {
183 DeviceIoControl(
184 self.driver_handle,
185 IOCTL_NDISRD_SEND_PACKET_TO_ADAPTER_UNSORTED,
186 Some(&request as *const UnsortedReadSendRequest<N> as *const std::ffi::c_void),
187 size_of::<UnsortedReadSendRequest<N>>() as u32,
188 Some(&mut request as *mut UnsortedReadSendRequest<N> as *mut std::ffi::c_void),
189 size_of::<UnsortedReadSendRequest<N>>() as u32,
190 None,
191 None,
192 )
193 };
194
195 if !result.as_bool() {
196 Err(unsafe { GetLastError() }.into())
197 } else {
198 Ok(request.packets_num as usize)
199 }
200 }
201
202 /// This function forwards packets to the NDIS filter driver in an unsorted manner, which then
203 /// sends them to the target protocols layer (MSTCP). The target adapter handle (to be indicated
204 /// from) should be set in the `IntermediateBuffer.header.adapter_handle` field.
205 ///
206 /// # Type Parameters
207 ///
208 /// * `N`: The number of packets to send.
209 ///
210 /// # Arguments
211 ///
212 /// * `packets`: A mutable reference to an array of `IntermediateBuffer` objects, which contain
213 /// the packets to be sent.
214 /// * `packets_num`: The number of packets to send from the array.
215 ///
216 /// # Returns
217 ///
218 /// * `Result<usize>`: If successful, returns `Ok(usize)` with the number of packets sent.
219 /// Otherwise, returns an error.
220 pub fn send_packets_to_mstcp_unsorted<const N: usize>(
221 &self,
222 packets: &mut [IntermediateBuffer; N],
223 packets_num: usize,
224 ) -> Result<usize> {
225 let mut request = UnsortedReadSendRequest::<N> {
226 packets: packets as *mut [IntermediateBuffer; N],
227 packets_num: packets_num as u32,
228 };
229
230 let result = unsafe {
231 DeviceIoControl(
232 self.driver_handle,
233 IOCTL_NDISRD_SEND_PACKET_TO_MSTCP_UNSORTED,
234 Some(&request as *const UnsortedReadSendRequest<N> as *const std::ffi::c_void),
235 size_of::<UnsortedReadSendRequest<N>>() as u32,
236 Some(&mut request as *mut UnsortedReadSendRequest<N> as *mut std::ffi::c_void),
237 size_of::<UnsortedReadSendRequest<N>>() as u32,
238 None,
239 None,
240 )
241 };
242
243 if !result.as_bool() {
244 Err(unsafe { GetLastError() }.into())
245 } else {
246 Ok(request.packets_num as usize)
247 }
248 }
249}