module Pcap:sig
..end
libpcap
, packet sniffing,
packet injection and pcap file reading and writing.
All I want is sniffing packets:
To grab the first packet from "em1" interface and display it:
# let itf = Pcap.openif "em1";;
val itf : Pcap.iface = {Pcap.handler = ; name = "em1"; caplen = 1500}
# let pkt = Pcap.sniff itf;;
val pkt : Pcap.Pdu.t =
{Pcap.Pdu.source_name = "em1"; caplen = 1500;
dlt = Ethernet (10Mb); ts = 15:09:49.81;
payload = 66 bytes (74 46 a0 a1 28 8e 00...)}
# Packet.Pdu.unpack pkt;;
- : Packet.Pdu.layer list =
[Packet.Pdu.Pcap
{Pcap.Pdu.source_name = "em1"; caplen = 1500;
dlt = Ethernet (10Mb); ts = 15:09:49.81;
payload = 66 bytes (74 46 a2 a1 28 8e 00...)};
Packet.Pdu.Eth
{Eth.Pdu.src = Cisco:25:ac:42;
dst = 74:46:a2:a1:28:8e; proto = IP;
payload = 52 bytes (45 20 00 34 86 aa 40...)};
Packet.Pdu.Ip
{Ip.Pdu.tos = 32; tot_len = 52; id = 34474; dont_frag = true;
more_frags = false; frag_offset = 0; ttl = 58; proto = tcp;
src = 172.16.255.194; dst = 172.28.11.20;
options = ; payload = 32 bytes (02 02 bc c8 a2 6c d0...)};
Packet.Pdu.Tcp
{Tcp.Pdu.src_port = shell; dst_port = 48328;
seq_num = 0xA26CD0EB; ack_num = 0x304E4FC3;
win_size = 501; flags = Ack; urg_ptr = 0;
options = 01 01 08 0a 28 f5 dd 89 - 57 c2 c6 25 .....��.W��%
;
payload = empty}]
Following packets can be dumped easily with just
Pcap.sniff itf |> Packet.Pdu.unpack
("|>" is like the UNIX pipe).
All I want is editing pcap files:
To create a small pcap file with a single packet:
Tcp.Pdu.make ~dst_port:(Tcp.Port.o 5000) (bitstring_of_string "HTTP/1.2 pas glop") |>
Tcp.Pdu.pack |>
Ip.Pdu.make Ip.Proto.tcp (Ip.Addr.random ()) (Ip.Addr.random ()) |>
Ip.Pdu.pack |>
Eth.Pdu.make Arp.HwProto.ip4 (Eth.Addr.random ()) (Eth.Addr.random ()) |>
Eth.Pdu.pack |>
Pcap.save "/tmp/random.pcap";;
To grep a string into a pcap file and obtain another pcap file with matching packets only:
let grep needle haystack = try String.find haystack needle ; true with Not_found -> false in
Pcap.enum_of_file "input.pcap" |>
Enum.filter (fun pdu -> grep "needle" (string_of_bitstring (pdu.Pcap.Pdu.payload :> bitstring))) |>
Pcap.file_of_enum "output.pcap";;
val debug : bool
type
iface_handler
val inject_ : iface_handler -> string -> unit
inject_ iface_handler packet
inject this packet into this interfaceval sniff_ : iface_handler -> Clock.Time.t * string
sniff_ iface_handler
will return the next available packet as a string,
as well as its capture timestamp.val openif_ : string -> bool -> string -> int -> iface_handler
openif_ "eth0" true "port 80" 96
returns the iface representing eth0,
in promiscuous mode, filtering port 80 and capturing only the first 96 bytes
of each packets. Notice that if caplen
is set to 0 then a "default" value
of 65535 will be chosen, which is probably not what you want. You should set
caplen
= your MTU size.module Dlt:sig
..end
type
global_header = {
|
name : |
(* |
The file name.
| *) |
|
endianness : |
(* |
Endianess of the file.
| *) |
|
version_major : |
(* |
Libpcap version.
| *) |
|
version_minor : |
|||
|
this_zone : |
(* |
Time zone (should be zero, unused).
| *) |
|
sigfigs : |
(* |
unused.
| *) |
|
snaplen : |
(* |
Indicate that no caplen will be smaller. We don't use this.
| *) |
|
dlt : |
(* |
The Data Link Type (see
Pcap.Dlt ). | *) |
module Pdu:sig
..end
val save : ?caplen:int -> ?dlt:Dlt.t -> string -> Tools.Payload.outer_t -> unit
save "file.pcap"
returns a function that will save passed bitstrings as packets in
"file.pcap"
.
caplen
: can be used to cap saved packet to a given number of bytesdlt
: can be used to change the file's DLT (required if you do not write Ethernet packets)exception Not_a_pcap_file
val bitstring_of_global_header : global_header -> Bitstring.bitstring
val global_header_of_bitstring : string -> Bitstring.bitstring -> global_header
val read_global_header : string -> global_header * BatIO.input
read_global_header filename
reads the pcap global header from the
given file, and returns both a Pcap.global_header
and the input channel.val read_next_pkt : global_header -> Batteries.IO.input -> Pdu.t
read_next_pkt global_header ic
will return the next Pcap.Pdu.t
that's to
be read from the input stream ic
.val enum_of_file : string -> Pdu.t Batteries.Enum.t
val write_global_header : string -> global_header -> unit BatIO.output
write_global_header filename
write a 'generic' pcap global header and
returns the output channel.val write_next_pkt : unit BatIO.output -> Pdu.t -> unit
write_next_pkt global_header ic
will return the next Pcap.Pdu.t
that's to
be read from the input stream ic
.val file_of_enum : string -> ?dlt:Dlt.t -> Pdu.t Batteries.Enum.t -> unit
type
infos = {
|
filename : |
|
data_link_type : |
|
num_packets : |
|
data_size : |
|
start_time : |
|
stop_time : |
val infos_of : string -> infos
val merge : Pdu.t Batteries.Enum.t list -> Pdu.t Batteries.Enum.t
merge [e1 ; e2 ; e3]
will merge the three Enumt.t
of packets in chronological
order.val repair_file : string -> unit
val play : (Bitstring.bitstring -> 'a) -> string -> unit
play tx "file.pcap"
will read packets from "file.pcap"
and send them to tx
copying the pcap file frame rate. Notice that we use the internal
Clock
for this, so it's both very accurate or not accurate at all,
depending on how you look at it.type
iface = {
|
handler : |
|
name : |
|
caplen : |
val mtu : string -> int
val openif : ?promisc:bool -> ?filter:string -> ?caplen:int -> string -> iface
openif "eth0" true "port 80" 96
returns the iface representing eth0,
in promiscuous mode, filtering port 80 and capturing only the first 96 bytes
of each packets. Notice that if caplen
is not set then MTU for the
device will be chosen.val sniff : iface -> Pdu.t
sniff iface
will return the next available packet as a Pcap.Pdu.t.val packets_injected_ok : Metric.Atomic.t
val packets_injected_err : Metric.Atomic.t
val bytes_out : Metric.Counter.t
val inject : iface -> Bitstring.bitstring -> unit
inject iface bits
inject the packet bits
into interface iface
.val packets_sniffed_ok : Metric.Atomic.t
val bytes_in : Metric.Counter.t
val sniffer : iface -> (Bitstring.bitstring -> unit) -> Thread.t
sniffer iface rx
returns a thread that continuously sniff packets
and pass them to the rx
function (via the Clock).