///|
/// Lockwire-owned native link-driver stubs.
///|
pub fn package_id() -> String {
"lockwire/driver/native"
}
///|
pub(all) suberror NativeLinkError {
SystemError(String, Int, String)
} derive(Eq, Debug)
///|
pub(all) struct NativePcapWriter {
fd : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeUdpSocket {
fd : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapLiveAdapter {
fd : Int
interface_name : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketAdapter {
fd : Int
interface_name : String
ethertype : Int
} derive(Eq, Debug)
///|
pub(all) enum NativeFrameSlotState {
FrameSlotFree
FrameSlotAcquired
FrameSlotFilled
FrameSlotSending
FrameSlotSent
FrameSlotReceiving
FrameSlotReceived
FrameSlotInvalid
} derive(Eq, Debug)
///|
pub(all) struct NativeFrameRef {
pool_id : Int
slot : Int
length : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeFramePool {
id : Int
} derive(Eq, Debug)
///|
pub(all) struct NativeUdpLoopbackSmokeReport {
native_backend_present : Bool
udp_socket_adapter_implemented : Bool
loopback_smoke_passed : Bool
timeout_is_benign : Bool
live_nic_evidence : Bool
bind_port : Int
sent_len : Int
received_len : Int
payload_digest : Int
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeFramePoolSmokeReport {
native_backend_present : Bool
frame_pool_available : Bool
pool_smoke_passed : Bool
zero_copy_live_evidence : Bool
capacity : Int
frame_size : Int
acquired_slot : Int
rx_slot : Int
copied_len : Int
read_len : Int
free_count_after_release : Int
payload_digest : Int
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapProbeReport {
native_backend_present : Bool
npcap_probe_implemented : Bool
npcap_runtime_available : Bool
interface_listing_supported : Bool
interface_count : Int
listing_digest : Int
live_capture_evidence : Bool
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapInterfaceInfo {
name : String
description : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapInterfaceListReport {
native_backend_present : Bool
npcap_runtime_available : Bool
interface_listing_supported : Bool
interfaces : Array[NativeNpcapInterfaceInfo]
interface_count : Int
listing_digest : Int
live_capture_evidence : Bool
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketInterfaceInfo {
name : String
description : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketInterfaceListReport {
native_backend_present : Bool
raw_socket_adapter_surface_implemented : Bool
interface_listing_supported : Bool
interfaces : Array[NativeRawSocketInterfaceInfo]
interface_count : Int
listing_digest : Int
live_capture_evidence : Bool
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapLiveAdapterReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
open_live_abi_present : Bool
send_packet_abi_present : Bool
set_filter_abi_present : Bool
capture_one_abi_present : Bool
close_abi_present : Bool
manual_interface_required : Bool
live_capture_evidence : Bool
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketAdapterReport {
native_backend_present : Bool
raw_socket_adapter_surface_implemented : Bool
raw_socket_runtime_available : Bool
open_abi_present : Bool
send_packet_abi_present : Bool
capture_one_abi_present : Bool
close_abi_present : Bool
manual_interface_required : Bool
live_capture_evidence : Bool
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapManualLiveSmokeReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
interface_name : String
manual_interface_required : Bool
attempted_open : Bool
opened : Bool
filter_expression : String
filter_attempted : Bool
filter_configured : Bool
capture_attempted : Bool
captured_frame_bytes : Int
captured_frame_digest : Int
closed : Bool
live_capture_evidence : Bool
snaplen : Int
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapManualSendSmokeReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
interface_name : String
manual_interface_required : Bool
manual_send_allowed : Bool
attempted_open : Bool
opened : Bool
send_attempted : Bool
sent_len : Int
frame_len : Int
frame_digest : Int
closed : Bool
live_send_evidence : Bool
snaplen : Int
open_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapCapturePcapArtifactReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
interface_name : String
output_path : String
manual_interface_required : Bool
output_path_required : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
filter_expression : String
filter_attempted : Bool
filter_configured : Bool
capture_attempted : Bool
captured_frame_bytes : Int
captured_frame_digest : Int
pcap_write_attempted : Bool
pcap_written_len : Int
pcap_artifact_evidence : Bool
closed : Bool
live_capture_evidence : Bool
snaplen : Int
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapFramePoolCaptureReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
frame_pool_available : Bool
interface_name : String
manual_interface_required : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
filter_expression : String
filter_attempted : Bool
filter_configured : Bool
capture_attempted : Bool
captured_frame_bytes : Int
captured_frame_digest : Int
frame_pool_attempted : Bool
frame_pool_created : Bool
frame_pool_slot : Int
frame_pool_written_len : Int
frame_pool_read_len : Int
frame_pool_payload_digest : Int
frame_pool_released : Bool
frame_pool_destroyed : Bool
free_count_after_release : Int
frame_pool_capture_evidence : Bool
closed : Bool
live_capture_evidence : Bool
live_frame_pool_evidence : Bool
snaplen : Int
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapSendCaptureRoundtripReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
interface_name : String
manual_interface_required : Bool
manual_send_allowed : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
send_attempted : Bool
sent_len : Int
frame_len : Int
frame_digest : Int
capture_attempted : Bool
capture_attempts : Int
filter_expression : String
filter_attempted : Bool
filter_configured : Bool
captured_frame_bytes : Int
captured_frame_digest : Int
captured_matches_sent_frame : Bool
closed : Bool
live_send_evidence : Bool
live_capture_evidence : Bool
live_roundtrip_evidence : Bool
snaplen : Int
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeNpcapRoundtripPcapArtifactReport {
native_backend_present : Bool
npcap_live_adapter_surface_implemented : Bool
npcap_runtime_available : Bool
interface_name : String
output_path : String
manual_interface_required : Bool
output_path_required : Bool
manual_send_allowed : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
send_attempted : Bool
sent_len : Int
frame_len : Int
frame_digest : Int
capture_attempted : Bool
capture_attempts : Int
filter_expression : String
filter_attempted : Bool
filter_configured : Bool
captured_frame_bytes : Int
captured_frame_digest : Int
captured_matches_sent_frame : Bool
pcap_write_attempted : Bool
pcap_written_len : Int
pcap_artifact_evidence : Bool
closed : Bool
live_send_evidence : Bool
live_capture_evidence : Bool
live_roundtrip_evidence : Bool
live_roundtrip_pcap_evidence : Bool
snaplen : Int
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketManualSmokeReport {
native_backend_present : Bool
raw_socket_adapter_surface_implemented : Bool
raw_socket_runtime_available : Bool
interface_name : String
manual_interface_required : Bool
manual_send_allowed : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
send_attempted : Bool
sent_len : Int
frame_len : Int
frame_digest : Int
capture_attempted : Bool
capture_attempts : Int
captured_frame_bytes : Int
captured_frame_digest : Int
captured_matches_sent_frame : Bool
closed : Bool
live_send_evidence : Bool
live_capture_evidence : Bool
live_roundtrip_evidence : Bool
ethertype : Int
promiscuous : Bool
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
pub(all) struct NativeRawSocketRoundtripPcapArtifactReport {
native_backend_present : Bool
raw_socket_adapter_surface_implemented : Bool
raw_socket_runtime_available : Bool
interface_name : String
output_path : String
manual_interface_required : Bool
output_path_required : Bool
manual_send_allowed : Bool
manual_capture_allowed : Bool
attempted_open : Bool
opened : Bool
send_attempted : Bool
sent_len : Int
frame_len : Int
frame_digest : Int
capture_attempted : Bool
capture_attempts : Int
captured_frame_bytes : Int
captured_frame_digest : Int
captured_matches_sent_frame : Bool
pcap_write_attempted : Bool
pcap_written_len : Int
pcap_artifact_evidence : Bool
closed : Bool
live_send_evidence : Bool
live_capture_evidence : Bool
live_roundtrip_evidence : Bool
live_roundtrip_pcap_evidence : Bool
ethertype : Int
promiscuous : Bool
open_timeout_ms : Int
capture_timeout_ms : Int
last_error_code : Int
last_error_message : String
evidence_label : String
} derive(Eq, Debug)
///|
struct CapturedFramePoolResult {
frame_pool_created : Bool
frame_pool_slot : Int
written_len : Int
read_len : Int
payload_digest : Int
released : Bool
destroyed : Bool
free_count_after_release : Int
evidence : Bool
} derive(Eq, Debug)
///|
struct NpcapFilterAttemptResult {
attempted : Bool
configured : Bool
last_error_code : Int
last_error_message : String
} derive(Eq, Debug)
///|
pub(all) struct NativeLinkStubReport {
stub_version : Int
native_backend_present : Bool
lockwire_owns_c_stubs : Bool
highres_clock_available : Bool
pcap_writer_available : Bool
local_pcap_writer_smoke_safe : Bool
frame_pool_available : Bool
raw_socket_adapter_implemented : Bool
udp_socket_adapter_implemented : Bool
npcap_runtime_adapter_implemented : Bool
npcap_live_adapter_surface_implemented : Bool
live_nic_smoke_locked : Bool
} derive(Eq, Debug)
///|
pub fn native_stub_version() -> Int {
ffi_stub_version()
}
///|
pub fn native_last_error_code() -> Int {
ffi_last_error_code()
}
///|
pub fn native_last_error_message() -> String {
@utf8.decode_lossy(ffi_last_error_message())
}
///|
pub fn highres_micros() -> Int64 {
ffi_highres_micros()
}
///|
pub fn NativePcapWriter::open(
path : StringView,
snaplen? : Int = 65535,
linktype? : Int = 1,
) -> NativePcapWriter raise NativeLinkError {
let fd = ffi_pcap_open(@ascii.encode(path), snaplen, linktype)
if fd < 0 {
raise native_link_error("pcap_open")
}
{ fd, }
}
///|
pub fn NativePcapWriter::write_packet(
self : NativePcapWriter,
frame : Bytes,
) -> Int raise NativeLinkError {
let written = ffi_pcap_write_packet(self.fd, frame)
if written < 0 {
raise native_link_error("pcap_write_packet")
}
written
}
///|
pub fn NativePcapWriter::write_packet_at(
self : NativePcapWriter,
frame : Bytes,
sec : Int,
usec : Int,
) -> Int raise NativeLinkError {
let written = ffi_pcap_write_packet_at(self.fd, frame, sec, usec)
if written < 0 {
raise native_link_error("pcap_write_packet_at")
}
written
}
///|
pub fn NativePcapWriter::close(
self : NativePcapWriter,
) -> Unit raise NativeLinkError {
if ffi_pcap_close(self.fd) < 0 {
raise native_link_error("pcap_close")
}
}
///|
pub fn native_npcap_list_interfaces_text() -> String {
@utf8.decode_lossy(ffi_npcap_list_interfaces_text())
}
///|
pub fn native_npcap_parse_interfaces_text(
text : String,
) -> Array[NativeNpcapInterfaceInfo] {
let interfaces : Array[NativeNpcapInterfaceInfo] = []
for raw_line in split_lines(text) {
if raw_line != "" {
interfaces.push(parse_npcap_interface_line(raw_line))
}
}
interfaces
}
///|
pub fn native_npcap_interface_list_report() -> NativeNpcapInterfaceListReport {
let probe = native_npcap_runtime_probe()
let text = if probe.npcap_runtime_available {
native_npcap_list_interfaces_text()
} else {
""
}
let interfaces = native_npcap_parse_interfaces_text(text)
{
native_backend_present: probe.native_backend_present,
npcap_runtime_available: probe.npcap_runtime_available,
interface_listing_supported: probe.interface_listing_supported,
interfaces,
interface_count: interfaces.length(),
listing_digest: bytes_digest(@utf8.encode(text)),
live_capture_evidence: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.interface-list",
}
}
///|
pub fn native_raw_socket_list_interfaces_text() -> String {
@utf8.decode_lossy(ffi_raw_socket_list_interfaces_text())
}
///|
pub fn native_raw_socket_parse_interfaces_text(
text : String,
) -> Array[NativeRawSocketInterfaceInfo] {
let interfaces : Array[NativeRawSocketInterfaceInfo] = []
for raw_line in split_lines(text) {
if raw_line != "" {
let parsed = parse_raw_socket_interface_line(raw_line)
interfaces.push(parsed)
}
}
interfaces
}
///|
pub fn native_raw_socket_interface_list_report() -> NativeRawSocketInterfaceListReport {
let surface = native_raw_socket_adapter_report()
let text = if surface.raw_socket_adapter_surface_implemented {
native_raw_socket_list_interfaces_text()
} else {
""
}
let interfaces = native_raw_socket_parse_interfaces_text(text)
{
native_backend_present: surface.native_backend_present,
raw_socket_adapter_surface_implemented: surface.raw_socket_adapter_surface_implemented,
interface_listing_supported: surface.raw_socket_adapter_surface_implemented,
interfaces,
interface_count: interfaces.length(),
listing_digest: bytes_digest(@utf8.encode(text)),
live_capture_evidence: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.raw-socket.interface-list",
}
}
///|
pub fn NativeNpcapLiveAdapter::open(
interface_name : String,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
timeout_ms? : Int = 50,
) -> NativeNpcapLiveAdapter raise NativeLinkError {
let fd = ffi_npcap_open_live(
@utf8.encode(interface_name),
snaplen,
if promiscuous {
1
} else {
0
},
timeout_ms,
)
if fd < 0 {
raise native_link_error("npcap_open_live")
}
{ fd, interface_name }
}
///|
pub fn NativeNpcapLiveAdapter::send_packet(
self : NativeNpcapLiveAdapter,
frame : Bytes,
) -> Int raise NativeLinkError {
let sent = ffi_npcap_send_packet(self.fd, frame)
if sent < 0 {
raise native_link_error("npcap_send_packet")
}
sent
}
///|
pub fn NativeNpcapLiveAdapter::set_filter(
self : NativeNpcapLiveAdapter,
expression : String,
optimize? : Bool = true,
netmask? : Int = -1,
) -> Unit raise NativeLinkError {
if ffi_npcap_set_filter(
self.fd,
@utf8.encode(expression),
if optimize {
1
} else {
0
},
netmask,
) <
0 {
raise native_link_error("npcap_set_filter")
}
}
///|
pub fn NativeNpcapLiveAdapter::capture_one(
self : NativeNpcapLiveAdapter,
timeout_ms? : Int = 0,
) -> Bytes raise NativeLinkError {
let frame = ffi_npcap_capture_one(self.fd, timeout_ms)
if frame.is_empty() && native_last_error_code() < 0 {
raise native_link_error("npcap_capture_one")
}
frame
}
///|
pub fn NativeNpcapLiveAdapter::close(
self : NativeNpcapLiveAdapter,
) -> Unit raise NativeLinkError {
if ffi_npcap_close_live(self.fd) < 0 {
raise native_link_error("npcap_close_live")
}
}
///|
pub fn NativeRawSocketAdapter::open(
interface_name : String,
ethertype? : Int = 0x88b5,
promiscuous? : Bool = true,
timeout_ms? : Int = 50,
) -> NativeRawSocketAdapter raise NativeLinkError {
let fd = ffi_raw_socket_open(
@utf8.encode(interface_name),
ethertype,
if promiscuous {
1
} else {
0
},
timeout_ms,
)
if fd < 0 {
raise native_link_error("raw_socket_open")
}
{ fd, interface_name, ethertype }
}
///|
pub fn NativeRawSocketAdapter::send_packet(
self : NativeRawSocketAdapter,
frame : Bytes,
) -> Int raise NativeLinkError {
let sent = ffi_raw_socket_send_packet(self.fd, frame)
if sent < 0 {
raise native_link_error("raw_socket_send_packet")
}
sent
}
///|
pub fn NativeRawSocketAdapter::capture_one(
self : NativeRawSocketAdapter,
timeout_ms? : Int = 0,
) -> Bytes raise NativeLinkError {
let frame = ffi_raw_socket_capture_one(self.fd, timeout_ms)
if frame.is_empty() && native_last_error_code() < 0 {
raise native_link_error("raw_socket_capture_one")
}
frame
}
///|
pub fn NativeRawSocketAdapter::close(
self : NativeRawSocketAdapter,
) -> Unit raise NativeLinkError {
if ffi_raw_socket_close(self.fd) < 0 {
raise native_link_error("raw_socket_close")
}
}
///|
fn npcap_configure_optional_filter(
adapter : NativeNpcapLiveAdapter,
filter_expression : String,
) -> NpcapFilterAttemptResult {
if filter_expression == "" {
{
attempted: false,
configured: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
}
} else {
let filtered : Result[Unit, Error] = Result::Ok(
adapter.set_filter(filter_expression),
) catch {
err => Result::Err(err)
}
match filtered {
Ok(_) =>
{
attempted: true,
configured: true,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
}
Err(_) =>
{
attempted: true,
configured: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
}
}
}
}
///|
pub fn native_npcap_runtime_probe() -> NativeNpcapProbeReport {
let native_present = native_stub_version() > 0
let implemented = ffi_npcap_probe_implemented() > 0
let available = implemented && ffi_npcap_runtime_available() > 0
let listing = if available { ffi_npcap_list_interfaces_text() } else { b"" }
let listing_supported = available && native_last_error_code() > 0
{
native_backend_present: native_present,
npcap_probe_implemented: implemented,
npcap_runtime_available: available,
interface_listing_supported: listing_supported,
interface_count: count_non_empty_lines(listing),
listing_digest: bytes_digest(listing),
live_capture_evidence: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.runtime-probe",
}
}
///|
pub fn native_npcap_live_adapter_report() -> NativeNpcapLiveAdapterReport {
let native_present = native_stub_version() > 0
let surface = ffi_npcap_live_adapter_implemented() > 0
let runtime = surface && ffi_npcap_runtime_available() > 0
{
native_backend_present: native_present,
npcap_live_adapter_surface_implemented: surface,
npcap_runtime_available: runtime,
open_live_abi_present: surface,
send_packet_abi_present: surface,
set_filter_abi_present: surface,
capture_one_abi_present: surface,
close_abi_present: surface,
manual_interface_required: true,
live_capture_evidence: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.live-adapter-surface",
}
}
///|
pub fn native_raw_socket_adapter_report() -> NativeRawSocketAdapterReport {
let native_present = native_stub_version() > 0
let surface = ffi_raw_socket_adapter_implemented() > 0
{
native_backend_present: native_present,
raw_socket_adapter_surface_implemented: surface,
raw_socket_runtime_available: surface,
open_abi_present: surface,
send_packet_abi_present: surface,
capture_one_abi_present: surface,
close_abi_present: surface,
manual_interface_required: true,
live_capture_evidence: false,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.raw-socket.adapter-surface",
}
}
///|
pub fn NativeNpcapLiveAdapterReport::passes_surface_boundary(
self : NativeNpcapLiveAdapterReport,
) -> Bool {
!self.live_capture_evidence &&
self.manual_interface_required &&
self.open_live_abi_present == self.npcap_live_adapter_surface_implemented &&
self.send_packet_abi_present == self.npcap_live_adapter_surface_implemented &&
self.set_filter_abi_present == self.npcap_live_adapter_surface_implemented &&
self.capture_one_abi_present == self.npcap_live_adapter_surface_implemented &&
self.close_abi_present == self.npcap_live_adapter_surface_implemented &&
self.evidence_label == "native.npcap.live-adapter-surface"
}
///|
pub fn NativeRawSocketAdapterReport::passes_surface_boundary(
self : NativeRawSocketAdapterReport,
) -> Bool {
!self.live_capture_evidence &&
self.manual_interface_required &&
self.raw_socket_runtime_available ==
self.raw_socket_adapter_surface_implemented &&
self.open_abi_present == self.raw_socket_adapter_surface_implemented &&
self.send_packet_abi_present == self.raw_socket_adapter_surface_implemented &&
self.capture_one_abi_present == self.raw_socket_adapter_surface_implemented &&
self.close_abi_present == self.raw_socket_adapter_surface_implemented &&
self.evidence_label == "native.raw-socket.adapter-surface"
}
///|
pub fn NativeRawSocketInterfaceListReport::passes_no_live_boundary(
self : NativeRawSocketInterfaceListReport,
) -> Bool {
!self.live_capture_evidence &&
self.interface_count == self.interfaces.length() &&
self.interface_count >= 0 &&
self.listing_digest >= 0 &&
self.evidence_label == "native.raw-socket.interface-list"
}
///|
pub fn NativeNpcapInterfaceListReport::passes_no_live_boundary(
self : NativeNpcapInterfaceListReport,
) -> Bool {
!self.live_capture_evidence &&
self.interface_count == self.interfaces.length() &&
self.interface_count >= 0 &&
self.listing_digest >= 0 &&
self.evidence_label == "native.npcap.interface-list"
}
///|
pub fn native_raw_socket_manual_smoke(
interface_name : String,
allow_send? : Bool = false,
allow_capture? : Bool = false,
ethertype? : Int = 0x88b5,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
capture_attempts? : Int = 3,
frame? : Bytes = b"",
) -> NativeRawSocketManualSmokeReport {
let surface = native_raw_socket_adapter_report()
let send_frame = native_select_manual_frame(frame)
let attempts = bounded_capture_attempts(capture_attempts)
let skip = raw_socket_skip_reason(interface_name, allow_send, allow_capture)
if skip != "ok" {
return {
native_backend_present: surface.native_backend_present,
raw_socket_adapter_surface_implemented: surface.raw_socket_adapter_surface_implemented,
raw_socket_runtime_available: surface.raw_socket_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
ethertype,
promiscuous,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: skip,
evidence_label: "native.raw-socket.manual-smoke",
}
}
let opened : Result[NativeRawSocketAdapter, Error] = Result::Ok(
NativeRawSocketAdapter::open(
interface_name,
ethertype~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
raw_socket_adapter_surface_implemented: surface.raw_socket_adapter_surface_implemented,
raw_socket_runtime_available: surface.raw_socket_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: true,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
ethertype,
promiscuous,
open_timeout_ms,
capture_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.raw-socket.manual-smoke",
}
Ok(adapter) => {
let mut sent_len = 0
let mut send_attempted = false
let mut live_send = false
let mut captured_len = 0
let mut captured_digest = 0
let mut captured_matches = false
let mut capture_attempted = false
let mut code = native_last_error_code()
let mut message = native_last_error_message()
if allow_send {
send_attempted = true
let sent : Result[Int, Error] = Result::Ok(
adapter.send_packet(send_frame),
) catch {
err => Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match sent {
Ok(count) => {
sent_len = count
live_send = count == send_frame.length()
}
Err(_) => ()
}
}
if allow_capture {
capture_attempted = true
for _ in 0.. Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match captured {
Ok(bytes) =>
if bytes.length() > 0 && captured_len == 0 {
captured_len = bytes.length()
captured_digest = bytes_digest(bytes)
captured_matches = bytes_equal(send_frame, bytes)
} else if bytes_equal(send_frame, bytes) {
captured_len = bytes.length()
captured_digest = bytes_digest(bytes)
captured_matches = true
}
Err(_) => ()
}
}
}
}
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let close_ok = match closed {
Ok(_) => true
Err(_) => false
}
let live_capture = capture_attempted && captured_len > 0
let live_roundtrip = live_send && live_capture && captured_matches
{
native_backend_present: surface.native_backend_present,
raw_socket_adapter_surface_implemented: surface.raw_socket_adapter_surface_implemented,
raw_socket_runtime_available: surface.raw_socket_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: true,
opened: true,
send_attempted,
sent_len,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted,
capture_attempts: attempts,
captured_frame_bytes: captured_len,
captured_frame_digest: captured_digest,
captured_matches_sent_frame: captured_matches,
closed: close_ok,
live_send_evidence: live_send,
live_capture_evidence: live_capture,
live_roundtrip_evidence: live_roundtrip,
ethertype,
promiscuous,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.raw-socket.manual-smoke",
}
}
}
}
///|
pub fn native_raw_socket_roundtrip_pcap_artifact(
interface_name : String,
output_path : String,
allow_send? : Bool = false,
allow_capture? : Bool = false,
capture_attempts? : Int = 3,
ethertype? : Int = 0x88b5,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
frame? : Bytes = b"",
) -> NativeRawSocketRoundtripPcapArtifactReport {
let surface = native_raw_socket_adapter_report()
let send_frame = native_select_manual_frame(frame)
let attempts = bounded_capture_attempts(capture_attempts)
if interface_name == "" || output_path == "" || !allow_send || !allow_capture {
return {
native_backend_present: surface.native_backend_present,
raw_socket_adapter_surface_implemented: surface.raw_socket_adapter_surface_implemented,
raw_socket_runtime_available: surface.raw_socket_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
pcap_write_attempted: false,
pcap_written_len: 0,
pcap_artifact_evidence: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
live_roundtrip_pcap_evidence: false,
ethertype,
promiscuous,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: roundtrip_artifact_skip_reason(
interface_name, output_path, allow_send, allow_capture,
),
evidence_label: "native.raw-socket.roundtrip-pcap-artifact",
}
}
let roundtrip = native_raw_socket_manual_smoke(
interface_name,
allow_send=true,
allow_capture=true,
ethertype~,
promiscuous~,
open_timeout_ms~,
capture_timeout_ms~,
capture_attempts=attempts,
frame=send_frame,
)
let mut pcap_attempted = false
let mut pcap_written = 0
let mut code = roundtrip.last_error_code
let mut message = roundtrip.last_error_message
let pcap_ready = roundtrip.live_roundtrip_evidence && roundtrip.closed
if pcap_ready {
pcap_attempted = true
let written : Result[Int, Error] = Result::Ok(
write_single_packet_pcap(output_path, send_frame),
) catch {
err => Result::Err(err)
}
match written {
Ok(value) => pcap_written = value
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
}
}
}
let pcap_evidence = pcap_attempted && pcap_written == send_frame.length()
{
native_backend_present: roundtrip.native_backend_present,
raw_socket_adapter_surface_implemented: roundtrip.raw_socket_adapter_surface_implemented,
raw_socket_runtime_available: roundtrip.raw_socket_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_send_allowed: true,
manual_capture_allowed: true,
attempted_open: roundtrip.attempted_open,
opened: roundtrip.opened,
send_attempted: roundtrip.send_attempted,
sent_len: roundtrip.sent_len,
frame_len: roundtrip.frame_len,
frame_digest: roundtrip.frame_digest,
capture_attempted: roundtrip.capture_attempted,
capture_attempts: roundtrip.capture_attempts,
captured_frame_bytes: roundtrip.captured_frame_bytes,
captured_frame_digest: roundtrip.captured_frame_digest,
captured_matches_sent_frame: roundtrip.captured_matches_sent_frame,
pcap_write_attempted: pcap_attempted,
pcap_written_len: pcap_written,
pcap_artifact_evidence: pcap_evidence,
closed: roundtrip.closed,
live_send_evidence: roundtrip.live_send_evidence,
live_capture_evidence: roundtrip.live_capture_evidence,
live_roundtrip_evidence: roundtrip.live_roundtrip_evidence,
live_roundtrip_pcap_evidence: roundtrip.live_roundtrip_evidence &&
pcap_evidence,
ethertype: roundtrip.ethertype,
promiscuous: roundtrip.promiscuous,
open_timeout_ms: roundtrip.open_timeout_ms,
capture_timeout_ms: roundtrip.capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.raw-socket.roundtrip-pcap-artifact",
}
}
///|
pub fn NativeRawSocketManualSmokeReport::passes_manual_boundary(
self : NativeRawSocketManualSmokeReport,
) -> Bool {
if self.interface_name == "" ||
(!self.manual_send_allowed && !self.manual_capture_allowed) {
!self.attempted_open &&
!self.opened &&
!self.send_attempted &&
!self.capture_attempted &&
!self.live_send_evidence &&
!self.live_capture_evidence &&
!self.live_roundtrip_evidence &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.evidence_label == "native.raw-socket.manual-smoke"
} else if !self.opened {
self.attempted_open &&
!self.send_attempted &&
!self.capture_attempted &&
!self.live_send_evidence &&
!self.live_capture_evidence &&
!self.live_roundtrip_evidence &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.evidence_label == "native.raw-socket.manual-smoke"
} else {
self.manual_interface_required &&
self.attempted_open &&
self.opened &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.capture_attempts >= 1 &&
self.sent_len >= 0 &&
self.sent_len <= self.frame_len &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.send_attempted == self.manual_send_allowed &&
self.capture_attempted == self.manual_capture_allowed &&
self.live_send_evidence ==
(self.send_attempted && self.sent_len == self.frame_len) &&
self.live_capture_evidence ==
(self.capture_attempted && self.captured_frame_bytes > 0) &&
self.live_roundtrip_evidence ==
(
self.live_send_evidence &&
self.live_capture_evidence &&
self.captured_matches_sent_frame
) &&
self.evidence_label == "native.raw-socket.manual-smoke"
}
}
///|
pub fn NativeRawSocketRoundtripPcapArtifactReport::passes_manual_boundary(
self : NativeRawSocketRoundtripPcapArtifactReport,
) -> Bool {
if self.interface_name == "" ||
self.output_path == "" ||
!self.manual_send_allowed ||
!self.manual_capture_allowed {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.raw-socket.roundtrip-pcap-artifact" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.sent_len == 0 &&
self.capture_attempts >= 1 &&
!self.attempted_open &&
!self.opened &&
!self.send_attempted &&
!self.capture_attempted &&
self.captured_frame_bytes == 0 &&
self.captured_frame_digest == 0 &&
!self.captured_matches_sent_frame &&
!self.pcap_write_attempted &&
self.pcap_written_len == 0 &&
!self.pcap_artifact_evidence &&
!self.closed &&
!self.live_send_evidence &&
!self.live_capture_evidence &&
!self.live_roundtrip_evidence &&
!self.live_roundtrip_pcap_evidence
} else {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.raw-socket.roundtrip-pcap-artifact" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.capture_attempts >= 1 &&
self.sent_len >= 0 &&
self.sent_len <= self.frame_len &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.pcap_written_len >= 0 &&
self.pcap_written_len <= self.frame_len &&
self.pcap_write_attempted == (self.live_roundtrip_evidence && self.closed) &&
self.pcap_artifact_evidence ==
(self.pcap_write_attempted && self.pcap_written_len == self.frame_len) &&
self.live_roundtrip_pcap_evidence ==
(self.live_roundtrip_evidence && self.pcap_artifact_evidence) &&
self.attempted_open &&
self.send_attempted == self.opened &&
self.capture_attempted == self.opened
}
}
///|
pub fn native_npcap_manual_live_smoke(
interface_name : String,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
filter_expression? : String = "",
) -> NativeNpcapManualLiveSmokeReport {
let surface = native_npcap_live_adapter_report()
if interface_name == "" {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
attempted_open: false,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
closed: false,
live_capture_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: "manual interface required",
evidence_label: "native.npcap.manual-live-smoke",
}
}
let opened : Result[NativeNpcapLiveAdapter, Error] = Result::Ok(
NativeNpcapLiveAdapter::open(
interface_name,
snaplen~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
attempted_open: true,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
closed: false,
live_capture_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.manual-live-smoke",
}
Ok(adapter) => {
let filter = npcap_configure_optional_filter(adapter, filter_expression)
let mut bytes_len = 0
let mut digest = 0
let mut capture_attempted = false
let mut code = filter.last_error_code
let mut message = filter.last_error_message
if filter_expression == "" || filter.configured {
capture_attempted = true
let captured : Result[Bytes, Error] = Result::Ok(
adapter.capture_one(timeout_ms=capture_timeout_ms),
) catch {
err => Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match captured {
Ok(bytes) => {
bytes_len = bytes.length()
digest = bytes_digest(bytes)
}
Err(_) => ()
}
}
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let close_ok = match closed {
Ok(_) => true
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
false
}
}
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
attempted_open: true,
opened: true,
filter_expression,
filter_attempted: filter.attempted,
filter_configured: filter.configured,
capture_attempted,
captured_frame_bytes: bytes_len,
captured_frame_digest: digest,
closed: close_ok,
live_capture_evidence: bytes_len > 0 && close_ok,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.manual-live-smoke",
}
}
}
}
///|
pub fn NativeNpcapManualLiveSmokeReport::passes_manual_boundary(
self : NativeNpcapManualLiveSmokeReport,
) -> Bool {
if self.interface_name == "" {
self.manual_interface_required &&
self.evidence_label == "native.npcap.manual-live-smoke" &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
!self.filter_attempted &&
!self.filter_configured &&
!self.attempted_open &&
!self.opened &&
!self.capture_attempted &&
!self.closed &&
!self.live_capture_evidence
} else {
self.manual_interface_required &&
self.evidence_label == "native.npcap.manual-live-smoke" &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
(
(
self.filter_expression == "" &&
!self.filter_attempted &&
!self.filter_configured
) ||
(self.filter_expression != "" && (!self.opened || self.filter_attempted))
) &&
(!self.filter_configured || self.filter_attempted) &&
self.attempted_open &&
self.capture_attempted ==
(self.opened && (self.filter_expression == "" || self.filter_configured))
}
}
///|
pub fn native_npcap_manual_send_smoke(
interface_name : String,
allow_send? : Bool = false,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
frame? : Bytes = b"",
) -> NativeNpcapManualSendSmokeReport {
let surface = native_npcap_live_adapter_report()
let send_frame = native_npcap_select_manual_frame(frame)
if interface_name == "" {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: allow_send,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
closed: false,
live_send_evidence: false,
snaplen,
open_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: "manual interface required",
evidence_label: "native.npcap.manual-send-smoke",
}
}
if !allow_send {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: false,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
closed: false,
live_send_evidence: false,
snaplen,
open_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: "manual send permission required",
evidence_label: "native.npcap.manual-send-smoke",
}
}
let opened : Result[NativeNpcapLiveAdapter, Error] = Result::Ok(
NativeNpcapLiveAdapter::open(
interface_name,
snaplen~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: true,
attempted_open: true,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
closed: false,
live_send_evidence: false,
snaplen,
open_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.manual-send-smoke",
}
Ok(adapter) => {
let sent : Result[Int, Error] = Result::Ok(
adapter.send_packet(send_frame),
) catch {
err => Result::Err(err)
}
let send_code = native_last_error_code()
let send_message = native_last_error_message()
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let mut sent_len = 0
let mut code = send_code
let mut message = send_message
match sent {
Ok(value) => sent_len = value
Err(_) => ()
}
let close_ok = match closed {
Ok(_) => true
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
false
}
}
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: true,
attempted_open: true,
opened: true,
send_attempted: true,
sent_len,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
closed: close_ok,
live_send_evidence: sent_len == send_frame.length() && close_ok,
snaplen,
open_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.manual-send-smoke",
}
}
}
}
///|
pub fn NativeNpcapManualSendSmokeReport::passes_manual_boundary(
self : NativeNpcapManualSendSmokeReport,
) -> Bool {
if self.interface_name == "" || !self.manual_send_allowed {
self.manual_interface_required &&
self.evidence_label == "native.npcap.manual-send-smoke" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.sent_len == 0 &&
!self.attempted_open &&
!self.opened &&
!self.send_attempted &&
!self.closed &&
!self.live_send_evidence
} else {
self.manual_interface_required &&
self.evidence_label == "native.npcap.manual-send-smoke" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.sent_len >= 0 &&
self.sent_len <= self.frame_len &&
self.attempted_open &&
self.send_attempted == self.opened
}
}
///|
pub fn native_npcap_capture_pcap_artifact(
interface_name : String,
output_path : String,
allow_capture? : Bool = false,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
filter_expression? : String = "",
) -> NativeNpcapCapturePcapArtifactReport {
let surface = native_npcap_live_adapter_report()
if interface_name == "" || output_path == "" || !allow_capture {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
pcap_write_attempted: false,
pcap_written_len: 0,
pcap_artifact_evidence: false,
closed: false,
live_capture_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: capture_artifact_skip_reason(
interface_name, output_path, allow_capture,
),
evidence_label: "native.npcap.capture-pcap-artifact",
}
}
let opened : Result[NativeNpcapLiveAdapter, Error] = Result::Ok(
NativeNpcapLiveAdapter::open(
interface_name,
snaplen~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_capture_allowed: true,
attempted_open: true,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
pcap_write_attempted: false,
pcap_written_len: 0,
pcap_artifact_evidence: false,
closed: false,
live_capture_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.capture-pcap-artifact",
}
Ok(adapter) => {
let filter = npcap_configure_optional_filter(adapter, filter_expression)
let mut captured_len = 0
let mut captured_digest = 0
let mut capture_attempted = false
let mut pcap_attempted = false
let mut pcap_written = 0
let mut code = filter.last_error_code
let mut message = filter.last_error_message
if filter_expression == "" || filter.configured {
capture_attempted = true
let captured : Result[Bytes, Error] = Result::Ok(
adapter.capture_one(timeout_ms=capture_timeout_ms),
) catch {
err => Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match captured {
Ok(bytes) => {
captured_len = bytes.length()
captured_digest = bytes_digest(bytes)
if captured_len > 0 {
pcap_attempted = true
let written : Result[Int, Error] = Result::Ok(
write_single_packet_pcap(output_path, bytes),
) catch {
err => Result::Err(err)
}
match written {
Ok(value) => pcap_written = value
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
}
}
}
}
Err(_) => ()
}
}
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let close_ok = match closed {
Ok(_) => true
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
false
}
}
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_capture_allowed: true,
attempted_open: true,
opened: true,
filter_expression,
filter_attempted: filter.attempted,
filter_configured: filter.configured,
capture_attempted,
captured_frame_bytes: captured_len,
captured_frame_digest: captured_digest,
pcap_write_attempted: pcap_attempted,
pcap_written_len: pcap_written,
pcap_artifact_evidence: pcap_written == captured_len && captured_len > 0,
closed: close_ok,
live_capture_evidence: captured_len > 0 && close_ok,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.capture-pcap-artifact",
}
}
}
}
///|
pub fn NativeNpcapCapturePcapArtifactReport::passes_manual_boundary(
self : NativeNpcapCapturePcapArtifactReport,
) -> Bool {
if self.interface_name == "" ||
self.output_path == "" ||
!self.manual_capture_allowed {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.npcap.capture-pcap-artifact" &&
!self.filter_attempted &&
!self.filter_configured &&
!self.attempted_open &&
!self.opened &&
!self.capture_attempted &&
self.captured_frame_bytes == 0 &&
self.captured_frame_digest == 0 &&
!self.pcap_write_attempted &&
self.pcap_written_len == 0 &&
!self.pcap_artifact_evidence &&
!self.closed &&
!self.live_capture_evidence
} else {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.npcap.capture-pcap-artifact" &&
(
(
self.filter_expression == "" &&
!self.filter_attempted &&
!self.filter_configured
) ||
(self.filter_expression != "" && (!self.opened || self.filter_attempted))
) &&
(!self.filter_configured || self.filter_attempted) &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.pcap_written_len >= 0 &&
self.pcap_written_len <= self.captured_frame_bytes &&
self.pcap_write_attempted == (self.captured_frame_bytes > 0) &&
self.attempted_open &&
self.capture_attempted ==
(self.opened && (self.filter_expression == "" || self.filter_configured))
}
}
///|
pub fn native_npcap_capture_frame_pool(
interface_name : String,
allow_capture? : Bool = false,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
filter_expression? : String = "",
) -> NativeNpcapFramePoolCaptureReport {
let surface = native_npcap_live_adapter_report()
let frame_pool_available = native_stub_version() > 0
if interface_name == "" || !allow_capture {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
frame_pool_available,
interface_name,
manual_interface_required: true,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
frame_pool_attempted: false,
frame_pool_created: false,
frame_pool_slot: -1,
frame_pool_written_len: 0,
frame_pool_read_len: 0,
frame_pool_payload_digest: 0,
frame_pool_released: false,
frame_pool_destroyed: false,
free_count_after_release: -1,
frame_pool_capture_evidence: false,
closed: false,
live_capture_evidence: false,
live_frame_pool_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: frame_pool_capture_skip_reason(
interface_name, allow_capture,
),
evidence_label: "native.npcap.capture-frame-pool",
}
}
let opened : Result[NativeNpcapLiveAdapter, Error] = Result::Ok(
NativeNpcapLiveAdapter::open(
interface_name,
snaplen~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
frame_pool_available,
interface_name,
manual_interface_required: true,
manual_capture_allowed: true,
attempted_open: true,
opened: false,
filter_expression,
filter_attempted: false,
filter_configured: false,
capture_attempted: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
frame_pool_attempted: false,
frame_pool_created: false,
frame_pool_slot: -1,
frame_pool_written_len: 0,
frame_pool_read_len: 0,
frame_pool_payload_digest: 0,
frame_pool_released: false,
frame_pool_destroyed: false,
free_count_after_release: -1,
frame_pool_capture_evidence: false,
closed: false,
live_capture_evidence: false,
live_frame_pool_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.capture-frame-pool",
}
Ok(adapter) => {
let filter = npcap_configure_optional_filter(adapter, filter_expression)
let mut captured_len = 0
let mut captured_digest = 0
let mut capture_attempted = false
let mut frame_pool_attempted = false
let mut frame_pool_created = false
let mut frame_pool_slot = -1
let mut frame_pool_written_len = 0
let mut frame_pool_read_len = 0
let mut frame_pool_payload_digest = 0
let mut frame_pool_released = false
let mut frame_pool_destroyed = false
let mut free_count_after_release = -1
let mut frame_pool_capture_evidence = false
let mut code = filter.last_error_code
let mut message = filter.last_error_message
if filter_expression == "" || filter.configured {
capture_attempted = true
let captured : Result[Bytes, Error] = Result::Ok(
adapter.capture_one(timeout_ms=capture_timeout_ms),
) catch {
err => Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match captured {
Ok(bytes) => {
captured_len = bytes.length()
captured_digest = bytes_digest(bytes)
if captured_len > 0 {
frame_pool_attempted = true
let pool_result : Result[CapturedFramePoolResult, Error] = Result::Ok(
captured_frame_to_pool(bytes),
) catch {
err => Result::Err(err)
}
match pool_result {
Ok(value) => {
frame_pool_created = value.frame_pool_created
frame_pool_slot = value.frame_pool_slot
frame_pool_written_len = value.written_len
frame_pool_read_len = value.read_len
frame_pool_payload_digest = value.payload_digest
frame_pool_released = value.released
frame_pool_destroyed = value.destroyed
free_count_after_release = value.free_count_after_release
frame_pool_capture_evidence = value.evidence
}
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
}
}
}
}
Err(_) => ()
}
}
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let close_ok = match closed {
Ok(_) => true
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
false
}
}
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
frame_pool_available,
interface_name,
manual_interface_required: true,
manual_capture_allowed: true,
attempted_open: true,
opened: true,
filter_expression,
filter_attempted: filter.attempted,
filter_configured: filter.configured,
capture_attempted,
captured_frame_bytes: captured_len,
captured_frame_digest: captured_digest,
frame_pool_attempted,
frame_pool_created,
frame_pool_slot,
frame_pool_written_len,
frame_pool_read_len,
frame_pool_payload_digest,
frame_pool_released,
frame_pool_destroyed,
free_count_after_release,
frame_pool_capture_evidence,
closed: close_ok,
live_capture_evidence: captured_len > 0 && close_ok,
live_frame_pool_evidence: captured_len > 0 &&
frame_pool_capture_evidence &&
close_ok,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.capture-frame-pool",
}
}
}
}
///|
pub fn NativeNpcapFramePoolCaptureReport::passes_manual_boundary(
self : NativeNpcapFramePoolCaptureReport,
) -> Bool {
if self.interface_name == "" || !self.manual_capture_allowed {
self.manual_interface_required &&
self.evidence_label == "native.npcap.capture-frame-pool" &&
!self.filter_attempted &&
!self.filter_configured &&
!self.attempted_open &&
!self.opened &&
!self.capture_attempted &&
self.captured_frame_bytes == 0 &&
self.captured_frame_digest == 0 &&
!self.frame_pool_attempted &&
!self.frame_pool_created &&
self.frame_pool_slot == -1 &&
self.frame_pool_written_len == 0 &&
self.frame_pool_read_len == 0 &&
self.frame_pool_payload_digest == 0 &&
!self.frame_pool_released &&
!self.frame_pool_destroyed &&
self.free_count_after_release == -1 &&
!self.frame_pool_capture_evidence &&
!self.closed &&
!self.live_capture_evidence &&
!self.live_frame_pool_evidence
} else {
self.manual_interface_required &&
self.evidence_label == "native.npcap.capture-frame-pool" &&
(
(
self.filter_expression == "" &&
!self.filter_attempted &&
!self.filter_configured
) ||
(self.filter_expression != "" && (!self.opened || self.filter_attempted))
) &&
(!self.filter_configured || self.filter_attempted) &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.frame_pool_written_len >= 0 &&
self.frame_pool_read_len >= 0 &&
self.frame_pool_payload_digest >= 0 &&
self.frame_pool_attempted == (self.captured_frame_bytes > 0) &&
self.frame_pool_capture_evidence ==
(
self.frame_pool_written_len == self.captured_frame_bytes &&
self.frame_pool_read_len == self.captured_frame_bytes &&
self.frame_pool_payload_digest == self.captured_frame_digest &&
self.frame_pool_released &&
self.frame_pool_destroyed
) &&
self.live_frame_pool_evidence ==
(self.live_capture_evidence && self.frame_pool_capture_evidence) &&
self.attempted_open &&
self.capture_attempted ==
(self.opened && (self.filter_expression == "" || self.filter_configured))
}
}
///|
pub fn native_npcap_send_capture_roundtrip(
interface_name : String,
allow_send? : Bool = false,
allow_capture? : Bool = false,
capture_attempts? : Int = 3,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
filter_expression? : String = "",
frame? : Bytes = b"",
) -> NativeNpcapSendCaptureRoundtripReport {
let surface = native_npcap_live_adapter_report()
let send_frame = native_npcap_select_manual_frame(frame)
let attempts = bounded_capture_attempts(capture_attempts)
if interface_name == "" || !allow_send || !allow_capture {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
filter_expression,
filter_attempted: false,
filter_configured: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: roundtrip_skip_reason(
interface_name, allow_send, allow_capture,
),
evidence_label: "native.npcap.send-capture-roundtrip",
}
}
let opened : Result[NativeNpcapLiveAdapter, Error] = Result::Ok(
NativeNpcapLiveAdapter::open(
interface_name,
snaplen~,
promiscuous~,
timeout_ms=open_timeout_ms,
),
) catch {
err => Result::Err(err)
}
match opened {
Err(_) =>
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: true,
manual_capture_allowed: true,
attempted_open: true,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
filter_expression,
filter_attempted: false,
filter_configured: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: native_last_error_code(),
last_error_message: native_last_error_message(),
evidence_label: "native.npcap.send-capture-roundtrip",
}
Ok(adapter) => {
let mut filter_attempted = false
let mut filter_configured = false
let mut code = native_last_error_code()
let mut message = native_last_error_message()
if filter_expression != "" {
filter_attempted = true
let filtered : Result[Unit, Error] = Result::Ok(
adapter.set_filter(filter_expression),
) catch {
err => Result::Err(err)
}
match filtered {
Ok(_) => {
filter_configured = true
code = native_last_error_code()
message = native_last_error_message()
}
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
}
}
}
let mut send_attempted = false
let mut sent_len = 0
if filter_expression == "" || filter_configured {
send_attempted = true
let sent : Result[Int, Error] = Result::Ok(
adapter.send_packet(send_frame),
) catch {
err => Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match sent {
Ok(value) => sent_len = value
Err(_) => ()
}
}
let mut capture_attempted = false
let mut captured_len = 0
let mut captured_digest = 0
let mut captured_matches = false
if sent_len == send_frame.length() {
for _ in 0.. Result::Err(err)
}
code = native_last_error_code()
message = native_last_error_message()
match captured {
Ok(bytes) =>
if bytes.length() > 0 {
captured_len = bytes.length()
captured_digest = bytes_digest(bytes)
captured_matches = bytes_equal(bytes, send_frame)
}
Err(_) => ()
}
}
}
}
let closed : Result[Unit, Error] = Result::Ok(adapter.close()) catch {
err => Result::Err(err)
}
let close_ok = match closed {
Ok(_) => true
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
false
}
}
{
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
manual_interface_required: true,
manual_send_allowed: true,
manual_capture_allowed: true,
attempted_open: true,
opened: true,
send_attempted,
sent_len,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted,
capture_attempts: attempts,
filter_expression,
filter_attempted,
filter_configured,
captured_frame_bytes: captured_len,
captured_frame_digest: captured_digest,
captured_matches_sent_frame: captured_matches,
closed: close_ok,
live_send_evidence: sent_len == send_frame.length() && close_ok,
live_capture_evidence: captured_len > 0 && close_ok,
live_roundtrip_evidence: sent_len == send_frame.length() &&
captured_matches &&
close_ok,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.send-capture-roundtrip",
}
}
}
}
///|
pub fn NativeNpcapSendCaptureRoundtripReport::passes_manual_boundary(
self : NativeNpcapSendCaptureRoundtripReport,
) -> Bool {
if self.interface_name == "" ||
!self.manual_send_allowed ||
!self.manual_capture_allowed {
self.manual_interface_required &&
self.evidence_label == "native.npcap.send-capture-roundtrip" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.sent_len == 0 &&
self.capture_attempts >= 1 &&
!self.filter_attempted &&
!self.filter_configured &&
!self.attempted_open &&
!self.opened &&
!self.send_attempted &&
!self.capture_attempted &&
self.captured_frame_bytes == 0 &&
self.captured_frame_digest == 0 &&
!self.captured_matches_sent_frame &&
!self.closed &&
!self.live_send_evidence &&
!self.live_capture_evidence &&
!self.live_roundtrip_evidence
} else {
self.manual_interface_required &&
self.evidence_label == "native.npcap.send-capture-roundtrip" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.capture_attempts >= 1 &&
(
(
self.filter_expression == "" &&
!self.filter_attempted &&
!self.filter_configured
) ||
(self.filter_expression != "" && self.filter_attempted)
) &&
(!self.filter_configured || self.filter_attempted) &&
self.sent_len >= 0 &&
self.sent_len <= self.frame_len &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.live_roundtrip_evidence ==
(self.live_send_evidence && self.captured_matches_sent_frame && self.closed) &&
self.attempted_open &&
self.send_attempted ==
(self.opened && (self.filter_expression == "" || self.filter_configured))
}
}
///|
pub fn native_npcap_roundtrip_pcap_artifact(
interface_name : String,
output_path : String,
allow_send? : Bool = false,
allow_capture? : Bool = false,
capture_attempts? : Int = 3,
snaplen? : Int = 65_535,
promiscuous? : Bool = true,
open_timeout_ms? : Int = 50,
capture_timeout_ms? : Int = 50,
filter_expression? : String = "",
frame? : Bytes = b"",
) -> NativeNpcapRoundtripPcapArtifactReport {
let surface = native_npcap_live_adapter_report()
let send_frame = native_npcap_select_manual_frame(frame)
let attempts = bounded_capture_attempts(capture_attempts)
if interface_name == "" || output_path == "" || !allow_send || !allow_capture {
return {
native_backend_present: surface.native_backend_present,
npcap_live_adapter_surface_implemented: surface.npcap_live_adapter_surface_implemented,
npcap_runtime_available: surface.npcap_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_send_allowed: allow_send,
manual_capture_allowed: allow_capture,
attempted_open: false,
opened: false,
send_attempted: false,
sent_len: 0,
frame_len: send_frame.length(),
frame_digest: bytes_digest(send_frame),
capture_attempted: false,
capture_attempts: attempts,
filter_expression,
filter_attempted: false,
filter_configured: false,
captured_frame_bytes: 0,
captured_frame_digest: 0,
captured_matches_sent_frame: false,
pcap_write_attempted: false,
pcap_written_len: 0,
pcap_artifact_evidence: false,
closed: false,
live_send_evidence: false,
live_capture_evidence: false,
live_roundtrip_evidence: false,
live_roundtrip_pcap_evidence: false,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: surface.last_error_code,
last_error_message: roundtrip_artifact_skip_reason(
interface_name, output_path, allow_send, allow_capture,
),
evidence_label: "native.npcap.roundtrip-pcap-artifact",
}
}
let roundtrip = native_npcap_send_capture_roundtrip(
interface_name,
allow_send=true,
allow_capture=true,
capture_attempts=attempts,
snaplen~,
promiscuous~,
open_timeout_ms~,
capture_timeout_ms~,
filter_expression~,
frame=send_frame,
)
let mut pcap_attempted = false
let mut pcap_written = 0
let mut code = roundtrip.last_error_code
let mut message = roundtrip.last_error_message
if roundtrip.live_roundtrip_evidence {
pcap_attempted = true
let written : Result[Int, Error] = Result::Ok(
write_single_packet_pcap(output_path, send_frame),
) catch {
err => Result::Err(err)
}
match written {
Ok(value) => pcap_written = value
Err(_) => {
code = native_last_error_code()
message = native_last_error_message()
}
}
}
let pcap_evidence = pcap_attempted && pcap_written == send_frame.length()
{
native_backend_present: roundtrip.native_backend_present,
npcap_live_adapter_surface_implemented: roundtrip.npcap_live_adapter_surface_implemented,
npcap_runtime_available: roundtrip.npcap_runtime_available,
interface_name,
output_path,
manual_interface_required: true,
output_path_required: true,
manual_send_allowed: true,
manual_capture_allowed: true,
attempted_open: roundtrip.attempted_open,
opened: roundtrip.opened,
send_attempted: roundtrip.send_attempted,
sent_len: roundtrip.sent_len,
frame_len: roundtrip.frame_len,
frame_digest: roundtrip.frame_digest,
capture_attempted: roundtrip.capture_attempted,
capture_attempts: roundtrip.capture_attempts,
filter_expression: roundtrip.filter_expression,
filter_attempted: roundtrip.filter_attempted,
filter_configured: roundtrip.filter_configured,
captured_frame_bytes: roundtrip.captured_frame_bytes,
captured_frame_digest: roundtrip.captured_frame_digest,
captured_matches_sent_frame: roundtrip.captured_matches_sent_frame,
pcap_write_attempted: pcap_attempted,
pcap_written_len: pcap_written,
pcap_artifact_evidence: pcap_evidence,
closed: roundtrip.closed,
live_send_evidence: roundtrip.live_send_evidence,
live_capture_evidence: roundtrip.live_capture_evidence,
live_roundtrip_evidence: roundtrip.live_roundtrip_evidence,
live_roundtrip_pcap_evidence: roundtrip.live_roundtrip_evidence &&
pcap_evidence,
snaplen,
open_timeout_ms,
capture_timeout_ms,
last_error_code: code,
last_error_message: message,
evidence_label: "native.npcap.roundtrip-pcap-artifact",
}
}
///|
pub fn NativeNpcapRoundtripPcapArtifactReport::passes_manual_boundary(
self : NativeNpcapRoundtripPcapArtifactReport,
) -> Bool {
if self.interface_name == "" ||
self.output_path == "" ||
!self.manual_send_allowed ||
!self.manual_capture_allowed {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.npcap.roundtrip-pcap-artifact" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.sent_len == 0 &&
self.capture_attempts >= 1 &&
!self.filter_attempted &&
!self.filter_configured &&
!self.attempted_open &&
!self.opened &&
!self.send_attempted &&
!self.capture_attempted &&
self.captured_frame_bytes == 0 &&
self.captured_frame_digest == 0 &&
!self.captured_matches_sent_frame &&
!self.pcap_write_attempted &&
self.pcap_written_len == 0 &&
!self.pcap_artifact_evidence &&
!self.closed &&
!self.live_send_evidence &&
!self.live_capture_evidence &&
!self.live_roundtrip_evidence &&
!self.live_roundtrip_pcap_evidence
} else {
self.manual_interface_required &&
self.output_path_required &&
self.evidence_label == "native.npcap.roundtrip-pcap-artifact" &&
self.frame_len >= 60 &&
self.frame_digest > 0 &&
self.capture_attempts >= 1 &&
(
(
self.filter_expression == "" &&
!self.filter_attempted &&
!self.filter_configured
) ||
(self.filter_expression != "" && self.filter_attempted)
) &&
(!self.filter_configured || self.filter_attempted) &&
self.sent_len >= 0 &&
self.sent_len <= self.frame_len &&
self.captured_frame_bytes >= 0 &&
self.captured_frame_digest >= 0 &&
self.pcap_written_len >= 0 &&
self.pcap_written_len <= self.frame_len &&
self.pcap_write_attempted == self.live_roundtrip_evidence &&
self.pcap_artifact_evidence ==
(self.pcap_write_attempted && self.pcap_written_len == self.frame_len) &&
self.live_roundtrip_pcap_evidence ==
(self.live_roundtrip_evidence && self.pcap_artifact_evidence) &&
self.attempted_open &&
self.send_attempted ==
(self.opened && (self.filter_expression == "" || self.filter_configured))
}
}
///|
pub fn NativeNpcapProbeReport::passes_no_live_boundary(
self : NativeNpcapProbeReport,
) -> Bool {
!self.live_capture_evidence &&
self.interface_count >= 0 &&
self.listing_digest >= 0 &&
self.evidence_label == "native.npcap.runtime-probe"
}
///|
pub fn NativeUdpSocket::open(
bind_ip : Bytes,
bind_port? : Int = 0,
) -> NativeUdpSocket raise NativeLinkError {
let fd = ffi_udp_open(bind_ip, bind_port)
if fd < 0 {
raise native_link_error("udp_open")
}
{ fd, }
}
///|
pub fn NativeUdpSocket::open_loopback(
bind_port? : Int = 0,
) -> NativeUdpSocket raise NativeLinkError {
NativeUdpSocket::open(native_loopback_ipv4(), bind_port~)
}
///|
pub fn NativeUdpSocket::bound_port(
self : NativeUdpSocket,
) -> Int raise NativeLinkError {
let port = ffi_udp_bound_port(self.fd)
if port < 0 {
raise native_link_error("udp_bound_port")
}
port
}
///|
pub fn NativeUdpSocket::send_to(
self : NativeUdpSocket,
dst_ip : Bytes,
port : Int,
data : Bytes,
) -> Int raise NativeLinkError {
let written = ffi_udp_send_to(self.fd, dst_ip, port, data)
if written < 0 {
raise native_link_error("udp_send_to")
}
written
}
///|
pub fn NativeUdpSocket::send_to_loopback(
self : NativeUdpSocket,
port : Int,
data : Bytes,
) -> Int raise NativeLinkError {
self.send_to(native_loopback_ipv4(), port, data)
}
///|
pub fn NativeUdpSocket::receive(
self : NativeUdpSocket,
timeout_ms : Int,
) -> Bytes raise NativeLinkError {
let data = ffi_udp_receive(self.fd, timeout_ms)
if data.is_empty() && native_last_error_code() < 0 {
raise native_link_error("udp_receive")
}
data
}
///|
pub fn NativeUdpSocket::close(
self : NativeUdpSocket,
) -> Unit raise NativeLinkError {
if ffi_udp_close(self.fd) < 0 {
raise native_link_error("udp_close")
}
}
///|
pub fn NativeFramePool::create(
capacity? : Int = 4,
frame_size? : Int = 1_536,
) -> NativeFramePool raise NativeLinkError {
let id = ffi_frame_pool_create(capacity, frame_size)
if id < 0 {
raise native_link_error("frame_pool_create")
}
{ id, }
}
///|
pub fn NativeFramePool::destroy(
self : NativeFramePool,
) -> Unit raise NativeLinkError {
if ffi_frame_pool_destroy(self.id) < 0 {
raise native_link_error("frame_pool_destroy")
}
}
///|
pub fn NativeFramePool::acquire(
self : NativeFramePool,
) -> NativeFrameRef raise NativeLinkError {
let slot = ffi_frame_pool_acquire(self.id)
if slot < 0 {
raise native_link_error("frame_pool_acquire")
}
{ pool_id: self.id, slot, length: 0 }
}
///|
pub fn NativeFramePool::acquire_rx(
self : NativeFramePool,
) -> NativeFrameRef raise NativeLinkError {
let slot = ffi_frame_pool_acquire_rx(self.id)
if slot < 0 {
raise native_link_error("frame_pool_acquire_rx")
}
{ pool_id: self.id, slot, length: 0 }
}
///|
pub fn NativeFramePool::write(
self : NativeFramePool,
fref : NativeFrameRef,
offset : Int,
src : FixedArray[Byte],
count : Int,
) -> NativeFrameRef raise NativeLinkError {
let written = ffi_frame_pool_write(self.id, fref.slot, offset, src, count)
if written < 0 {
raise native_link_error("frame_pool_write")
}
{ ..fref, length: max_int(fref.length, offset + written) }
}
///|
pub fn NativeFramePool::read_into(
self : NativeFramePool,
fref : NativeFrameRef,
offset : Int,
dst : FixedArray[Byte],
count : Int,
) -> Int raise NativeLinkError {
let read = ffi_frame_pool_read_into(self.id, fref.slot, offset, dst, count)
if read < 0 {
raise native_link_error("frame_pool_read_into")
}
read
}
///|
pub fn NativeFramePool::copy(
self : NativeFramePool,
src : NativeFrameRef,
dst : NativeFrameRef,
count : Int,
) -> Int raise NativeLinkError {
let copied = ffi_frame_pool_copy(self.id, src.slot, dst.slot, count)
if copied < 0 {
raise native_link_error("frame_pool_copy")
}
copied
}
///|
pub fn NativeFramePool::mark_filled(
self : NativeFramePool,
fref : NativeFrameRef,
length : Int,
) -> NativeFrameRef raise NativeLinkError {
if ffi_frame_pool_mark_filled(self.id, fref.slot, length) < 0 {
raise native_link_error("frame_pool_mark_filled")
}
{ ..fref, length, }
}
///|
pub fn NativeFramePool::mark_sending(
self : NativeFramePool,
fref : NativeFrameRef,
) -> Unit raise NativeLinkError {
if ffi_frame_pool_mark_sending(self.id, fref.slot) < 0 {
raise native_link_error("frame_pool_mark_sending")
}
}
///|
pub fn NativeFramePool::mark_sent(
self : NativeFramePool,
fref : NativeFrameRef,
) -> Unit raise NativeLinkError {
if ffi_frame_pool_mark_sent(self.id, fref.slot) < 0 {
raise native_link_error("frame_pool_mark_sent")
}
}
///|
pub fn NativeFramePool::mark_received(
self : NativeFramePool,
fref : NativeFrameRef,
length : Int,
) -> NativeFrameRef raise NativeLinkError {
if ffi_frame_pool_mark_received(self.id, fref.slot, length) < 0 {
raise native_link_error("frame_pool_mark_received")
}
{ ..fref, length, }
}
///|
pub fn NativeFramePool::release(
self : NativeFramePool,
fref : NativeFrameRef,
) -> Unit raise NativeLinkError {
if ffi_frame_pool_release(self.id, fref.slot) < 0 {
raise native_link_error("frame_pool_release")
}
}
///|
pub fn NativeFramePool::free_count(
self : NativeFramePool,
) -> Int raise NativeLinkError {
let count = ffi_frame_pool_free_count(self.id)
if count < 0 {
raise native_link_error("frame_pool_free_count")
}
count
}
///|
pub fn NativeFramePool::slot_state(
self : NativeFramePool,
fref : NativeFrameRef,
) -> NativeFrameSlotState raise NativeLinkError {
let state = ffi_frame_pool_slot_state(self.id, fref.slot)
if state < 0 {
raise native_link_error("frame_pool_slot_state")
}
frame_slot_state_from_int(state)
}
///|
pub fn NativeFramePool::slot_length(
self : NativeFramePool,
fref : NativeFrameRef,
) -> Int raise NativeLinkError {
let length = ffi_frame_pool_slot_length(self.id, fref.slot)
if length < 0 {
raise native_link_error("frame_pool_slot_length")
}
length
}
///|
pub fn native_udp_loopback_smoke(
timeout_ms? : Int = 1_000,
) -> NativeUdpLoopbackSmokeReport raise NativeLinkError {
let rx = NativeUdpSocket::open_loopback()
let port = rx.bound_port()
let tx = NativeUdpSocket::open_loopback()
let payload : Bytes = [0xde, 0xad, 0xbe, 0xef, 0x4c, 0x57]
let sent = tx.send_to_loopback(port, payload)
let received = rx.receive(timeout_ms)
let timeout = rx.receive(20)
tx.close()
rx.close()
{
native_backend_present: native_stub_version() > 0,
udp_socket_adapter_implemented: true,
loopback_smoke_passed: sent == payload.length() && received == payload,
timeout_is_benign: timeout.is_empty(),
live_nic_evidence: false,
bind_port: port,
sent_len: sent,
received_len: received.length(),
payload_digest: bytes_digest(payload),
evidence_label: "native.udp.loopback.local-smoke",
}
}
///|
pub fn native_frame_pool_smoke() -> NativeFramePoolSmokeReport raise NativeLinkError {
let capacity = 4
let frame_size = 64
if native_stub_version() <= 0 {
return {
native_backend_present: false,
frame_pool_available: false,
pool_smoke_passed: false,
zero_copy_live_evidence: false,
capacity,
frame_size,
acquired_slot: -1,
rx_slot: -1,
copied_len: 0,
read_len: 0,
free_count_after_release: -1,
payload_digest: 0,
evidence_label: "native.frame-pool.local-smoke",
}
}
let pool = NativeFramePool::create(capacity~, frame_size~)
let payload : FixedArray[Byte] = [
b'\xde', b'\xad', b'\xbe', b'\xef', b'\x4c', b'\x57',
]
let tx0 = pool.acquire()
let tx1 = pool.write(tx0, 0, payload, payload.length())
let tx = pool.mark_filled(tx1, tx1.length)
pool.mark_sending(tx)
let rx0 = pool.acquire_rx()
let copied = pool.copy(tx, rx0, payload.length())
let rx = pool.mark_received(rx0, copied)
let dst : FixedArray[Byte] = FixedArray::make(payload.length(), b'\x00')
let read = pool.read_into(rx, 0, dst, payload.length())
pool.mark_sent(tx)
pool.release(tx)
pool.release(rx)
let free_count = pool.free_count()
pool.destroy()
{
native_backend_present: true,
frame_pool_available: true,
pool_smoke_passed: read == payload.length() &&
copied == payload.length() &&
fixed_array_prefix_equals(payload, dst, payload.length()) &&
free_count == capacity,
zero_copy_live_evidence: false,
capacity,
frame_size,
acquired_slot: tx.slot,
rx_slot: rx.slot,
copied_len: copied,
read_len: read,
free_count_after_release: free_count,
payload_digest: fixed_array_digest(dst, read),
evidence_label: "native.frame-pool.local-smoke",
}
}
///|
pub fn NativeFramePoolSmokeReport::passes(
self : NativeFramePoolSmokeReport,
) -> Bool {
self.native_backend_present &&
self.frame_pool_available &&
self.pool_smoke_passed &&
!self.zero_copy_live_evidence &&
self.capacity > 0 &&
self.frame_size > 0 &&
self.acquired_slot >= 0 &&
self.rx_slot >= 0 &&
self.acquired_slot != self.rx_slot &&
self.copied_len == self.read_len &&
self.free_count_after_release == self.capacity &&
self.payload_digest > 0 &&
self.evidence_label == "native.frame-pool.local-smoke"
}
///|
pub fn NativeFramePoolSmokeReport::passes_no_live_boundary(
self : NativeFramePoolSmokeReport,
) -> Bool {
!self.zero_copy_live_evidence &&
self.capacity > 0 &&
self.frame_size > 0 &&
self.free_count_after_release >= -1 &&
self.evidence_label == "native.frame-pool.local-smoke"
}
///|
pub fn NativeUdpLoopbackSmokeReport::passes(
self : NativeUdpLoopbackSmokeReport,
) -> Bool {
self.native_backend_present &&
self.udp_socket_adapter_implemented &&
self.loopback_smoke_passed &&
self.timeout_is_benign &&
!self.live_nic_evidence &&
self.bind_port > 0 &&
self.sent_len == self.received_len &&
self.payload_digest > 0 &&
self.evidence_label == "native.udp.loopback.local-smoke"
}
///|
pub fn native_link_stub_report() -> NativeLinkStubReport {
let present = native_stub_version() > 0
let raw_surface = ffi_raw_socket_adapter_implemented() > 0
let npcap_surface = ffi_npcap_live_adapter_implemented() > 0
{
stub_version: native_stub_version(),
native_backend_present: present,
lockwire_owns_c_stubs: true,
highres_clock_available: present,
pcap_writer_available: present,
local_pcap_writer_smoke_safe: true,
frame_pool_available: present,
raw_socket_adapter_implemented: raw_surface,
udp_socket_adapter_implemented: present,
npcap_runtime_adapter_implemented: false,
npcap_live_adapter_surface_implemented: npcap_surface,
live_nic_smoke_locked: true,
}
}
///|
pub fn NativeLinkStubReport::passes_local_smoke_boundary(
self : NativeLinkStubReport,
) -> Bool {
self.lockwire_owns_c_stubs &&
self.local_pcap_writer_smoke_safe &&
self.live_nic_smoke_locked &&
self.frame_pool_available == self.native_backend_present &&
!self.npcap_runtime_adapter_implemented
}
///|
fn native_link_error(op : String) -> NativeLinkError {
NativeLinkError::SystemError(
op,
native_last_error_code(),
native_last_error_message(),
)
}
///|
fn native_loopback_ipv4() -> Bytes {
[127, 0, 0, 1]
}
///|
fn frame_slot_state_from_int(value : Int) -> NativeFrameSlotState {
match value {
0 => FrameSlotFree
1 => FrameSlotAcquired
2 => FrameSlotFilled
3 => FrameSlotSending
4 => FrameSlotSent
5 => FrameSlotReceiving
6 => FrameSlotReceived
_ => FrameSlotInvalid
}
}
///|
fn bytes_digest(bytes : Bytes) -> Int {
let modulus = 65_521
let mut digest = 17
for byte in bytes {
digest = (digest * 31 + byte.to_int()) % modulus
}
digest
}
///|
fn bytes_equal(left : Bytes, right : Bytes) -> Bool {
if left.length() != right.length() {
return false
}
for i in 0.. Int {
let modulus = 65_521
let limit = min_int(max_int(count, 0), bytes.length())
let mut digest = 17
for i in 0.. Bool {
if count < 0 || count > left.length() || count > right.length() {
return false
}
for i in 0.. Int {
if left < right {
left
} else {
right
}
}
///|
fn max_int(left : Int, right : Int) -> Int {
if left > right {
left
} else {
right
}
}
///|
fn count_non_empty_lines(bytes : Bytes) -> Int {
let mut count = 0
let mut has_text = false
for byte in bytes {
if byte == 0x0a {
if has_text {
count = count + 1
}
has_text = false
} else if byte != 0x0d {
has_text = true
}
}
if has_text {
count = count + 1
}
count
}
///|
fn split_lines(text : String) -> Array[String] {
let lines : Array[String] = []
let buf = StringBuilder::new()
for c in text {
if c == '\n' {
lines.push(strip_trailing_cr(buf.to_string()))
buf.reset()
} else {
buf.write_char(c)
}
}
let remaining = strip_trailing_cr(buf.to_string())
if remaining != "" {
lines.push(remaining)
}
lines
}
///|
fn strip_trailing_cr(text : String) -> String {
if text.has_suffix("\r") {
text[:text.length() - 1].to_owned()
} else {
text
}
}
///|
fn parse_npcap_interface_line(line : String) -> NativeNpcapInterfaceInfo {
let name = StringBuilder::new()
let description = StringBuilder::new()
let mut after_tab = false
for c in line {
if c == '\t' && !after_tab {
after_tab = true
} else if after_tab {
description.write_char(c)
} else {
name.write_char(c)
}
}
{ name: name.to_string(), description: description.to_string() }
}
///|
fn parse_raw_socket_interface_line(
line : String,
) -> NativeRawSocketInterfaceInfo {
let name = StringBuilder::new()
let description = StringBuilder::new()
let mut after_tab = false
for c in line {
if c == '\t' && !after_tab {
after_tab = true
} else if after_tab {
description.write_char(c)
} else {
name.write_char(c)
}
}
{ name: name.to_string(), description: description.to_string() }
}
///|
pub fn native_make_ethernet_smoke_frame(
ethertype? : Int = 0x88b5,
dst_mac? : Bytes = b"",
src_mac? : Bytes = b"",
payload? : Bytes = b"",
) -> Bytes {
let out : Array[Byte] = []
push_bytes(
out,
if dst_mac.length() == 6 {
dst_mac
} else {
native_npcap_default_dst_mac()
},
)
push_bytes(
out,
if src_mac.length() == 6 {
src_mac
} else {
native_npcap_default_src_mac()
},
)
let safe_ethertype = if ethertype >= 0 && ethertype <= 0xffff {
ethertype
} else {
0x88b5
}
out.push(((safe_ethertype >> 8) & 0xff).to_byte())
out.push((safe_ethertype & 0xff).to_byte())
push_bytes(
out,
if payload.length() > 0 {
payload
} else {
native_npcap_default_send_payload()
},
)
while out.length() < 60 {
out.push(b'\x00')
}
Bytes::from_array(out)
}
///|
pub fn native_npcap_make_ethernet_smoke_frame(
ethertype? : Int = 0x88b5,
dst_mac? : Bytes = b"",
src_mac? : Bytes = b"",
payload? : Bytes = b"",
) -> Bytes {
native_make_ethernet_smoke_frame(ethertype~, dst_mac~, src_mac~, payload~)
}
///|
fn native_npcap_default_send_smoke_frame() -> Bytes {
native_make_ethernet_smoke_frame()
}
///|
fn native_select_manual_frame(frame : Bytes) -> Bytes {
if frame.length() > 0 {
frame
} else {
native_npcap_default_send_smoke_frame()
}
}
///|
fn native_npcap_select_manual_frame(frame : Bytes) -> Bytes {
native_select_manual_frame(frame)
}
///|
fn native_npcap_default_dst_mac() -> Bytes {
[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
}
///|
fn native_npcap_default_src_mac() -> Bytes {
[0x02, 0x4c, 0x57, 0x00, 0x00, 0x01]
}
///|
fn native_npcap_default_send_payload() -> Bytes {
[
0x4c, 0x4f, 0x43, 0x4b, 0x57, 0x49, 0x52, 0x45, 0x2d, 0x4e, 0x50, 0x43, 0x41,
0x50, 0x2d, 0x53, 0x45, 0x4e, 0x44, 0x2d, 0x53, 0x4d, 0x4f, 0x4b, 0x45, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
]
}
///|
fn push_bytes(out : Array[Byte], bytes : Bytes) -> Unit {
for i in 0.. Int {
min_int(max_int(value, 1), 16)
}
///|
fn capture_artifact_skip_reason(
interface_name : String,
output_path : String,
allow_capture : Bool,
) -> String {
if interface_name == "" {
"manual interface required"
} else if output_path == "" {
"manual output path required"
} else if !allow_capture {
"manual capture permission required"
} else {
"ok"
}
}
///|
fn roundtrip_skip_reason(
interface_name : String,
allow_send : Bool,
allow_capture : Bool,
) -> String {
if interface_name == "" {
"manual interface required"
} else if !allow_send {
"manual send permission required"
} else if !allow_capture {
"manual capture permission required"
} else {
"ok"
}
}
///|
fn raw_socket_skip_reason(
interface_name : String,
allow_send : Bool,
allow_capture : Bool,
) -> String {
if interface_name == "" {
"manual interface required"
} else if !allow_send && !allow_capture {
"manual send or capture permission required"
} else {
"ok"
}
}
///|
fn roundtrip_artifact_skip_reason(
interface_name : String,
output_path : String,
allow_send : Bool,
allow_capture : Bool,
) -> String {
if interface_name == "" {
"manual interface required"
} else if output_path == "" {
"manual output path required"
} else if !allow_send {
"manual send permission required"
} else if !allow_capture {
"manual capture permission required"
} else {
"ok"
}
}
///|
fn frame_pool_capture_skip_reason(
interface_name : String,
allow_capture : Bool,
) -> String {
if interface_name == "" {
"manual interface required"
} else if !allow_capture {
"manual capture permission required"
} else {
"ok"
}
}
///|
fn captured_frame_to_pool(
frame : Bytes,
) -> CapturedFramePoolResult raise NativeLinkError {
let pool = NativeFramePool::create(capacity=1, frame_size=frame.length())
let buffer = bytes_to_fixed_array(frame)
let rx0 = pool.acquire_rx()
let written = pool.write(rx0, 0, buffer, frame.length())
let rx = pool.mark_received(written, written.length)
let dst : FixedArray[Byte] = FixedArray::make(frame.length(), b'\x00')
let read = pool.read_into(rx, 0, dst, frame.length())
let digest = fixed_array_digest(dst, read)
pool.release(rx)
let free_count = pool.free_count()
pool.destroy()
{
frame_pool_created: true,
frame_pool_slot: rx.slot,
written_len: written.length,
read_len: read,
payload_digest: digest,
released: true,
destroyed: true,
free_count_after_release: free_count,
evidence: written.length == frame.length() &&
read == frame.length() &&
digest == bytes_digest(frame) &&
free_count == 1,
}
}
///|
fn bytes_to_fixed_array(bytes : Bytes) -> FixedArray[Byte] {
let out = FixedArray::make(bytes.length(), b'\x00')
for i in 0.. Int raise NativeLinkError {
let writer = NativePcapWriter::open(path)
let written = writer.write_packet(frame)
writer.close()
written
}