Abstract
PLOKAMI is a lispy interface to libpcap built on top of a CFFI portability layer. Complete bindings to every function in libpcap are in pcap.lisp although not exported. A higher level lisp-like interface is implemented in plokami.lisp and documented here.Supported: Realtime network packet capture, PCAP dumpfile reading/writing, BPF, timeouts and operation in non-blocking mode.
Also, support exists for win32 through winpcap but see here. The library has been tested on SBCL (linux/darwin), ClozureCL and Lispworks (darwin/win32) but should work on every platform that CFFI supports.The code comes with a BSD-style license so you can basically do with it whatever you want.
make-pcap-live
make-pcap-reader
make-pcap-writer
pcap-live-alive
pcap-live-datalink
pcap-live-interface
pcap-live-promisc
pcap-live-snaplen
pcap-live-timeout
pcap-reader-alive
pcap-reader-datalink
pcap-reader-file
pcap-reader-major
pcap-reader-minor
pcap-reader-snaplen
pcap-reader-swapped
pcap-writer-alive
pcap-writer-datalink
pcap-writer-file
pcap-writer-snaplen
*pcap-version*
find-all-devs
The current STABLE version is 1.0. You can download it here or install it automatically with ASDF-INSTALL. For feature-requests, questions, patches email me at xristos (AT) suspicious.
Latest DEVELOPMENT version in git. Try it if you are having problems with stable.
find-all-devs
returns NIL, make sure you have appropriate permissions for
packet capture (read access on /dev/bpf* devices for OSX/BSD,
root on linux).
PLOKAMI> (find-all-devs)
(("lo0" NIL 1
(((:ADDR :AF_INET "127.0.0.1") (:NETMASK :AF_INET "255.0.0.0"))
((:ADDR :AF_INET6 "fe80:1::1") (:NETMASK :AF_INET6 "ffff:ffff:ffff:ffff::"))
((:ADDR :AF_INET6 "::1")
(:NETMASK :AF_INET6 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))
((:ADDR :AF_LINK "lo0"))))
("wlt1" NIL 0 (((:ADDR :AF_LINK "wlt1"))))
("en1" NIL 0
(((:ADDR :AF_INET "10.0.3.1") (:NETMASK :AF_INET "255.255.255.0")
(:BROADADDR :AF_INET "10.0.3.255"))
((:ADDR :AF_LINK "en1:0.16.cb.b7.37.39"))))
("ppp0" NIL 0
(((:ADDR :AF_INET "10.0.2.15") (:NETMASK :AF_INET "255.0.0.0")
(:DSTADDR :AF_INET "10.0.2.2"))
((:ADDR :AF_LINK "ppp0"))))
("fw0" NIL 0 (((:ADDR :AF_LINK "fw0:0.16.cb.ff.fe.61.7a.b0"))))
("en0" NIL 0
(((:ADDR :AF_INET "192.16.109.30") (:NETMASK :AF_INET "255.255.252.0")
(:BROADADDR :AF_INET "192.16.111.255"))
((:ADDR :AF_LINK "en0:0.16.cb.a5.1e.a2")))))
Read packets from the network in realtime, filter for IP, process
and write them out to a PCAP dumpfile. Interrupt lisp to clean up and exit.
(with-pcap-interface (pcap "en0" :promisc t :snaplen 1500 :timeout 2000)
(with-pcap-writer (writer "session.pcap" :snaplen 1500 :datalink
(pcap-live-datalink pcap))
(set-filter pcap "ip")
(loop
(capture pcap -1
#'(lambda (sec usec caplen len buffer)
;; sec and usec at the time of the capture
;; caplen -> size of captured packet
;; len -> original size of packet (may be > caplen, depends on snaplen)
;; buffer -> byte vector with packet contents
(dump writer buffer :length caplen
:origlength len :sec sec :usec usec)
(format t "Captured ~A bytes [~A]~%" caplen len))))))
Read all packets available in PCAP dumpfile session.pcap and process them.
(with-pcap-reader (reader "session.pcap" :snaplen 1500)
(capture reader -1 #'(lambda (sec usec caplen len buffer)
;; packet processing code here
)))
In all cases, BUFFER vector used in callback supplied to capture is
statically allocated and is overwritten every time capture
gets called. If packet persistence is required, its contents should be copied
before capture gets called again.
Under win32/winpcap, SNAPLEN only takes effect when a filter is used. It is therefore advised that an empty filter be installed, (set-filter instance ""), when capturing on this platform. Also see here.
[Function]
make-pcap-live interface &key promisc nbio (timeout 100) (snaplen 68) => PCAP-LIVE instance
Create and return a PCAP-LIVE instance. INTERFACE is a string that names the network interface used for capture. If NIL, one is selected automatically from the available ones. PROMISC should be T when capturing in promiscuous mode, NIL otherwise. NBIO should be T when non-blocking operation is required. NIL otherwise (default). TIMEOUT should hold read timeout in milliseconds. 0 will wait forever. Only used when in blocking mode. SNAPLEN should contain the number of bytes captured per packet. Default is 68 which should be enough for headers.
[Function]
make-pcap-reader file &key (snaplen 68) => PCAP-READER instance
Create and return a PCAP-READER instance. FILE is the filename to open and read packets from. SNAPLEN should contain the number of bytes read per packet captured. Default is 68 which should be enough for headers.
[Function]
make-pcap-writer file &key (datalink "EN10MB") (snaplen 68) => PCAP-WRITER instance
Create and return a PCAP-WRITER instance. FILE is the filename to open and dump packets to. DATALINK should contain a string that represents the datalink protocol of the network interface used to capture the packets. Default is Ethernet. SNAPLEN should contain the number of bytes read per packet captured and should be the same as the one used when capturing/reading packets.
[Method]
pcap-live-alive (object pcap-live) => result
Returns T when PCAP-LIVE object is live and can be used forcapture. NIL whenstophas been invoked and object is dead.
[Method]
pcap-live-datalink (object pcap-live) => result
Return string representation of the datalink protocol that is used by PCAP-LIVE object.
[Method]
pcap-live-interface (object pcap-live) => result
Return string representation of network interface that is used for packet capture.
[Method]
pcap-live-promisc (object pcap-live) => result
T if capturing in promiscuous mode.
[Method]
pcap-live-snaplen (object pcap-live) => result
Return snapshot length (how many bytes to capture per packet) for PCAP-LIVE object.
[Method]
pcap-live-timeout (object pcap-live) => result
Read timeout in milliseconds. 0 will wait forever. Only used in blocking mode.
[Method]
pcap-reader-alive (object pcap-reader) => result
Returns T when PCAP-READER object is live and can be used forcapture. NIL whenstophas been invoked and object is dead.
[Method]
pcap-reader-datalink (object pcap-reader) => result
Return string representation of the datalink protocol that is used by PCAP-READER object.
[Method]
pcap-reader-file (object pcap-reader) => result
File to read packets from.
[Method]
pcap-reader-major (object pcap-reader) => result
Major version of savefile.
[Method]
pcap-reader-minor (object pcap-reader) => result
Minor version of savefile.
[Method]
pcap-reader-snaplen (object pcap-reader) => result
Number of bytes to read per packet processed.
[Method]
pcap-reader-swapped (object pcap-reader) => result
Savefile uses different byte order from host system.
[Method]
pcap-writer-alive (object pcap-writer) => result
Returns T when PCAP-WRITER object is live and can be used forcapture. NIL whenstophas been invoked and object is dead.
[Method]
pcap-writer-datalink (object pcap-writer) => result
Return string representation of the datalink protocol that is used by PCAP-WRITER object.
[Method]
pcap-writer-file (object pcap-writer) => result
File to write packets to.
[Method]
pcap-writer-snaplen (object pcap-writer) => result
Number of bytes to write per packet processed.
[Generic function]
set-filter pcap-process-mixin string => result
Set a packet filter on a PCAP-LIVE or PCAP-READER instance. The filter should be given as a BPF expression in STRING.PACKET-FILTER-ERRORis signalled on failure. A restart, CONTINUE-NO-FILTER, is also setup that can be invoked to continue.
[Generic function]
set-nonblock pcap-live block-mode => result
Set non-blocking mode if BLOCK-MODE is T, blocking mode if NIL.BLOCK-MODE-ERRORis signalled on failure and a restart is setup, that can be invoked to continue.
[Generic function]
stats pcap-live => result
Return packet capture statistics from the start of the run to the time of the call for live interface capture only. Statistics are returned as multiple values and correspond to packets received, packets dropped and packets dropped by interface (in this order).NETWORK-INTERFACE-ERRORis signalled on failure.
[Generic function]
stop pcap-mixin => result
Deallocate resources for PCAP-LIVE, PCAP-READER, PCAP-WRITER instance.
[Generic function]
dump pcap-writer data &key length origlength sec usec => result
Dump a byte vector DATA on PCAP-WRITER instance (which corresponds to a pcap savefile). LENGTH corresponds to the number of bytes captured and is set to the size of DATA when omitted. ORIGLENGTH corresponds to the number of bytes originally present in the packet and is set to LENGTH when omitted. SEC and USEC correspond to seconds/microseconds since the UNIX epoch at the time of packet capture (timeval structure in C) and are set to current values when omitted.CAPTURE-FILE-ERRORis signalled on errors.
[Generic function]
capture pcap-process-mixin packets handler => result
Only works for PCAP-LIVE or PCAP-READER instances. Capture and process maximum number of PACKETS. Minimum is zero. Return 0 when no packets available (for dumpfiles: when end of file) otherwise return number of packets processed which can be fewer than the maximum given in PACKETS (due to pcap buffer). A count of -1 in PACKETS processes all the packets received so far when live capturing, or all the packets in a file when reading a pcap dumpfile. Handler must be a user defined function that accepts five arguments and will get called once for every packet received. The arguments are SEC, USEC, CAPLEN, LEN and BUFFER. SEC and USEC correspond to seconds/microseconds since the UNIX epoch (timeval structure in C) at the time of capture. CAPLEN corresponds to the number of bytes captured. LEN corresponds to the number of bytes originally present in the packet but not necessarily captured. BUFFER is a statically allocated byte vector with the contents of the captured packet. This means that successive calls of the packet handler will overwrite its contents and if packet persistence is required, contents of BUFFER should be copied somewhere else from within HANDLER. If an error occurs,PACKET-CAPTURE-ERRORis signalled for live interfaces andCAPTURE-FILE-ERRORfor pcap dumpfiles.
[Macro]
with-pcap-interface (pcaplive iface &rest options) declaration* statement* => result
CallMAKE-PCAP-LIVEpassing IFACE, OPTIONS and store the resulting instance in PCAPLIVE. Forms in BODY are wrapped in an UNWIND-PROTECT form that takes care of deallocating resources on error and also returns packet capture statistics when possible. A restart is also automatically invoked whenPACKET-FILTER-ERRORis signalled, skipping the filter setup.
[Macro]
with-pcap-reader (reader file &rest options) declaration* statement* => result
CallMAKE-PCAP-READERpassing FILE, options and store the resulting instance in READER. Forms in body are wrapped in an UNWIND-PROTECT form that takes care of deallocating resources on error. A restart is also automatically invoked whenPACKET-FILTER-ERRORis signalled, skipping the filter setup.
[Macro]
with-pcap-writer (writer file &rest options) declaration* statement* => result
CallMAKE-PCAP-WRITERpassing FILE, OPTIONS and store the resulting instance in WRITER. Forms in body are wrapped in an UNWIND-PROTECT form that takes care of deallocating resources on error.
[Condition type]
network-interface-error
Signaled on all network interface errors.
[Condition type]
packet-capture-error
Signaled on error during live packet capture.
[Condition type]
packet-filter-error
Signaled when a Berkeley packet filter could not be established.
[Condition type]
block-mode-error
Signaled on error when changing blocking mode.
[Condition type]
capture-file-error
Signaled on all pcap file errors.
[Special variable]
*pcap-version*
Version of native LIBPCAP library.
[Function]
find-all-devs => result
Return a list of all network devices that can be opened for capture. Result list mirrors layout explained in pcap_findalldevs().
This documentation was prepared with DOCUMENTATION-TEMPLATE.