///|
/// 解析 IPv4 头(偏移 0/9/12/16 是相对 IP 头,帧内需 +14 Ethernet 头)
fn parse_ipv4(
data : Bytes,
ts_sec : Int64,
ts_usec : Int,
local_ips : FixedArray[IpAddr],
) -> ParsedPacket? {
let total = data.length()
let l3 = ETH_HDR
guard total >= l3 + 20 else { return None }
let vihl = data[l3].to_int()
guard vihl >> 4 == 4 else { return None } // 非 IPv4
let ihl = (vihl & 0x0F) * 4
let ip_total = u16(data, l3 + 2)
guard ip_total >= ihl && ip_total <= total - l3 else { return None }
let proto = classify_proto(data[l3 + 9])
let src = { v4: true, bytes: read_bytes(data, l3 + 12, 4) }
let dst = { v4: true, bytes: read_bytes(data, l3 + 16, 4) }
// 传输层解析,返回 (src_port, dst_port, payload_len)
let l4 = match proto {
Tcp => parse_tcp(data, l3 + ihl, ip_total - ihl)
Udp => parse_udp(data, l3 + ihl, ip_total - ihl)
_ => Some((0, 0, ip_total - ihl))
}
let (sport, dport, payload) = match l4 {
Some(x) => x
None => return None
}
Some(
ParsedPacket::new(
ts_sec,
ts_usec,
{ src_ip: src, dst_ip: dst, src_port: sport, dst_port: dport, proto },
direction(src, dst, local_ips),
payload,
ip_total,
),
)
}