pcap

MoonBit 抓包绑定层:运行时动态加载 wpcap.dll(Npcap)

pcap
npcap
packet-capture
windows
ffi
Download zip
Author
Version
0.1.1
License
MIT
Last updated
27 days ago
Downloads
2

#moonbit-pcap

MoonBit 抓包绑定层:运行时动态加载 wpcap.dll(Npcap),提供设备枚举、打开设备、轮询收包等 pcap API 的 MoonBit 封装。

仅支持 Windows(x86_64)。构建时零依赖(不需要 Npcap SDK),运行时才要求安装 Npcap。

#特性

  • 运行时动态加载:C stub 用 LoadLibraryW("wpcap.dll") + GetProcAddress 取函数指针,编译期不链接任何 pcap 库
  • 零拷贝收包PacketRaw.data 是拷贝副本,不持有 C 缓冲区,收包后可安全持有
  • 明确错误映射load() 区分"未安装 Npcap / 系统加载失败 / 版本不兼容"三种原因
  • stdout 约定stdout_unbuffered() + eprint() 配合,stdout 专供数据流、日志走 stderr

#环境要求

要求
操作系统Windows 10 / 11(x86_64)
Npcap必须安装(https://npcap.com),保持默认安装
运行权限管理员权限(抓包硬前提)

#安装

moon add chensuiyi/pcap

#快速开始

// moon.pkg: import "chensuiyi/pcap"
fn main {
match pcap.load() {
Err(msg) => {
pcap.eprint(msg)
return
}
Ok(_) => ()
}
pcap.stdout_unbuffered()
let devs = pcap.devices()
if devs.is_empty() {
pcap.eprint("未找到网络设备")
return
}
match pcap.open(devs[0].name, 65535, true, 1000) {
Err(msg) => pcap.eprint("打开设备失败: \{msg}")
Ok(pc) => {
while true {
match pcap.next(pc) {
Some(pkt) => pcap.eprint(
"\{pkt.ts_sec}.\{pkt.ts_usec} len=\{pkt.len} caplen=\{pkt.caplen}",
)
None => () // 超时或错误,继续轮询
}
}
}
}
}

#API 一览

函数说明
load() -> Result[Unit, String]加载 wpcap.dll(进程只需一次)
devices() -> Array[Device]枚举本机网卡(Device { name, description }
open(dev, snaplen, promisc, timeout_ms) -> Result[Pcap, String]打开设备
next(p) -> PacketRaw?轮询收包:Some = 数据包,None = 超时或错误
datalink(p) -> Int链路层类型(1 = Ethernet / DLT_EN10MB)
geterr(p) -> String最近一次操作的错误信息
close(p) -> Unit停止收包循环并关闭设备
local_ips() -> Array[(Bool, Bytes)]枚举本机 IP(GetAdaptersAddresses,v4=4 字节 / v6=16 字节)
stdout_unbuffered() -> Unitstdout 设为无缓冲(管道/重定向时立即输出)
eprint(msg) -> Unit日志输出到 stderr

PacketRaw 字段:ts_sec : Int64(时间戳秒)、ts_usec : Int(微秒)、caplen : Int(实际捕获长度)、len : Int(原始包长)、data : Bytes(包数据副本)。

#与解析层配合

抓到的原始包交由 chensuiyi/packet(纯 MoonBit 解析层)提取五元组、方向与协议;完整采集服务见 chensuiyi/monitor

#License

MIT

Device

pub struct Device {
name : String
description : String
}

网卡设备

PacketRaw

pub struct PacketRaw {
ts_sec : Int64
ts_usec : Int
caplen : Int
len : Int
data : Bytes
}

原始数据包(data 是拷贝副本,不持有 C 缓冲区)

Pcap

pub struct Pcap {
handle : Int64
}

pcap 句柄

close

fn close(p : Pcap) -> Unit

停止收包循环并关闭设备
fn datalink(p : Pcap) -> Int

链路层类型(1 = Ethernet / DLT_EN10MB)

devices

fn devices() -> Array[Device]

枚举本机网卡(无设备或失败返回空数组)

eprint

fn eprint(msg : String) -> Unit

日志输出到 stderr(stdout 专供 JSON 流)

geterr

fn geterr(p : Pcap) -> String

最近一次操作的错误信息

load

fn load() -> Result[Unit, String]

加载 wpcap.dll(进程只需一次;失败原因映射见 npcap_load 返回值约定)

local_ips

fn local_ips() -> Array[(Bool, Bytes)]

枚举本机 IP 地址(GetAdaptersAddresses):(是否 IPv4, 地址字节),v4=4 字节 v6=16 字节
fn next(p : Pcap) -> PacketRaw?

轮询收包:Some = 数据包,None = 超时或错误

open

fn open(dev : String, snaplen : Int, promisc : Bool, timeout_ms : Int) -> Result[Pcap, String]

打开设备(snaplen 抓包长度上限,promisc 混杂模式,timeout_ms 收包超时)

stdout_unbuffered

fn stdout_unbuffered() -> Unit

stdout 设为无缓冲(管道/重定向时 JSON 行立即输出)

Source Files