You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Harden Win32 FFI boundary and fix safety/correctness issues (0.7.0)
Addresses a batch of safety, correctness, and robustness findings around
the Win32/driver boundary, and bumps the crate to 0.7.0.
Breaking changes:
- Ndisapi no longer implements Clone. It owns the driver HANDLE and closes
it on Drop, so cloning risked a double-close / use of a reused OS handle.
Use Arc<Ndisapi> for shared ownership (as the async API and examples do).
- ndis_get_request / ndis_set_request are now `unsafe fn`: the driver
reads/writes the generic T as raw bytes, so T must be plain old data.
The safe u32 wrappers (get/set_hw_packet_filter) are unchanged.
Critical / High:
- SockAddrStorage: add length-aware from_raw_sockaddr and use it during
adapter enumeration so IPv6 addresses are no longer truncated to 16
bytes; zero-initialize storage in all constructors (no more reads of
uninitialized memory).
- win32_event_stream: register the waker before re-checking readiness
(fixes a lost-wakeup race); UnregisterWaitEx now waits for in-flight
callbacks (INVALID_HANDLE_VALUE) and, if that fails, leaks rather than
freeing the callback / closing the event (avoids use-after-free and
use-after-close).
- AsyncNdisapiAdapter::new no longer leaks the event handle on partial
construction.
- static_api registry getters wrote through a *mut derived from a shared
reference (UB) and leaked the HKEY; now use a real &mut, validate
REG_DWORD/size, and close the key via an RAII guard.
- set_friendly_name now writes a UTF-16 REG_SZ value (was UTF-8) and only
updates the cached name after the registry write succeeds.
Medium:
- IntermediateBuffer::set_length clamps to MAX_ETHER_FRAME and the data
accessors clamp defensively, so a bad length can no longer panic.
- Centralize IPv4 -> IN_ADDR conversion to network byte order (the
from_ip_string path stored host order, reversing addresses on
little-endian Windows); fix add_ndp_entry_ipv4 to match; add round-trip
tests.
- delete_routes / reset_* / delete_unicast_address_* accumulate per-entry
failures instead of masking them.
- get_tcpip_bound_adapters_info clamps the driver-reported adapter count to
ADAPTER_LIST_SIZE and uses lossy UTF-8 for adapter names.
- Async batch send (send_packets_to_adapter/mstcp) returns the number of
packets submitted instead of the always-zero packet_success counter.
Also runs cargo fmt and fixes doc-comment lints so `cargo clippy -- -D
warnings` is clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
notif:Win32EventStream::new(event_handle)?,// Creating a new Win32EventStream with the event handle.
100
+
notif,
88
101
})
89
102
}
90
103
@@ -227,7 +240,7 @@ impl AsyncNdisapiAdapter {
227
240
/// # Arguments
228
241
///
229
242
/// * `packet` - An `IntermediateBuffer` that will be encapsulated in an `EthPacket`
230
-
/// representing the Ethernet packet to be sent.
243
+
/// representing the Ethernet packet to be sent.
231
244
///
232
245
/// # Safety
233
246
///
@@ -277,7 +290,7 @@ impl AsyncNdisapiAdapter {
277
290
///
278
291
/// # Returns
279
292
///
280
-
/// On successful operation, this function returns an `Ok(usize)` that represents the number of packets successfully sent to the network adapter. If the operation fails, an error is returned.
293
+
/// On successful operation, this function returns an `Ok(usize)` with the number of packets that were submitted to the driver for sending. If the operation fails, an error is returned.
// The send IOCTL takes no output buffer, so the driver never writes back the
305
+
// `packet_success` counter (unlike the read path); it would always read as 0 here.
306
+
// Report the number of packets submitted in the request instead, which is the
307
+
// meaningful value on the success path.
308
+
self.driver
309
+
.send_packets_to_adapter(&request)
310
+
.map(|_| request.get_packet_number()asusize)
294
311
}
295
312
296
313
/// Sends an Ethernet packet upwards through the network stack to the Microsoft TCP/IP protocol driver.
@@ -346,7 +363,7 @@ impl AsyncNdisapiAdapter {
346
363
///
347
364
/// # Returns
348
365
///
349
-
/// On successful operation, this function returns `Ok(usize)`, where `usize` is the number of packets sent. If the operation fails, an error is returned.
366
+
/// On successful operation, this function returns `Ok(usize)`, where `usize` is the number of packets submitted to the driver for sending. If the operation fails, an error is returned.
0 commit comments