pcap: reading and dissecting classic pcap capture files
| (require pcap) | package: pcap |
The pcap package reads capture files in the classic pcap
format—
1 Scope
- All four classic magic-number variants are supported, covering both byte orders and both timestamp resolutions:
a1 b2 c3 d4 —
big-endian, microseconds d4 c3 b2 a1 —
little-endian, microseconds a1 b2 3c 4d —
big-endian, nanoseconds 4d 3c b2 a1 —
little-endian, nanoseconds
pcapng files are not supported. Feeding a pcapng file to any reader in this package raises exn:fail with a “bad magic number” message.
Checksums are not validated. IPv6 extension headers are not parsed: decode-ipv6 exposes only the fixed 40-octet header.
2 Reading captures
struct
(struct pcap-header (link-type snaplen) #:extra-constructor-name make-pcap-header) link-type : exact-nonnegative-integer? snaplen : exact-nonnegative-integer?
struct
(struct packet (timestamp link-type data orig-len) #:extra-constructor-name make-packet) timestamp : rational? link-type : exact-nonnegative-integer? data : bytes? orig-len : exact-nonnegative-integer?
procedure
in : input-port?
procedure
(pcap-read-file path) → (listof packet?)
path : path-string?
procedure
(pcap-read-bytes bs) → (listof packet?)
bs : bytes?
procedure
(pcap-read-header in) → pcap-header?
in : input-port?
3 Dissection
struct
(struct ethernet-frame (dst src ether-type payload tagged?) #:extra-constructor-name make-ethernet-frame) dst : string? src : string? ether-type : exact-nonnegative-integer?
payload :
(or/c bytes? ipv4-header? ipv6-header? tcp-header? udp-header?) tagged? : boolean?
struct
(struct ipv4-header (src dst protocol ttl options payload) #:extra-constructor-name make-ipv4-header) src : string? dst : string? protocol : exact-nonnegative-integer? ttl : exact-nonnegative-integer? options : bytes? payload : (or/c bytes? tcp-header? udp-header?)
struct
(struct ipv6-header (src dst next-header hop-limit payload) #:extra-constructor-name make-ipv6-header) src : string? dst : string? next-header : exact-nonnegative-integer? hop-limit : exact-nonnegative-integer? payload : (or/c bytes? tcp-header? udp-header?)
struct
(struct tcp-header (src-port dst-port seq ack flags payload) #:extra-constructor-name make-tcp-header) src-port : exact-nonnegative-integer? dst-port : exact-nonnegative-integer? seq : exact-nonnegative-integer? ack : exact-nonnegative-integer? flags : exact-nonnegative-integer? payload : (or/c bytes? tcp-header? udp-header?)
struct
(struct udp-header (src-port dst-port payload) #:extra-constructor-name make-udp-header) src-port : exact-nonnegative-integer? dst-port : exact-nonnegative-integer? payload : (or/c bytes? tcp-header? udp-header?)
procedure
(decode-ethernet bs) → ethernet-frame?
bs : bytes?
procedure
(decode-ipv4 bs) → ipv4-header?
bs : bytes?
procedure
(decode-ipv6 bs) → ipv6-header?
bs : bytes?
procedure
(decode-tcp bs) → tcp-header?
bs : bytes?
procedure
(decode-udp bs) → udp-header?
bs : bytes?
> (require pcap)
> (define eth (decode-ethernet (bytes 170 187 204 221 238 255 17 34 51 68 85 102 8 0 222 173))) > (ethernet-frame-dst eth) "aa:bb:cc:dd:ee:ff"
> (ethernet-frame-ether-type eth) 2048
> (ethernet-frame-tagged? eth) #f
> (ethernet-frame-payload eth) #"\336\255"
procedure
(decode-packet pkt) → ethernet-frame?
pkt : packet?
4 Errors and limitations
All failures raise exn:fail with descriptive messages: truncated global header, bad magic number (the message notes that pcapng is unsupported), truncated packet record header, and truncated packet data. A record whose captured length exceeds a 16 MiB safety limit is rejected as probably corrupt so that garbage length fields cannot trigger huge allocations.
Limitations: checksums are never validated; IPv6 extension headers, IP fragmentation, and TCP stream reassembly are out of scope; only Ethernet-captured packets are accepted by decode-packet.