NAME
Net::Pcap::Easy - Net::Pcap is awesome, but it's difficult to bootstrap
SYNOPSIS
use Net::Pcap::Easy;
# all arguments to new are optoinal
my $npe = Net::Pcap::Easy->new(
dev => "lo",
filter => "host 127.0.0.1 and icmp",
packets_per_loop => 10,
bytes_to_capture => 1024,
timeout_in_ms => 0, # 0ms means forever
promiscuous => 0, # true or false
icmp_callback => sub {
my ($ether, $ip, $icmp) = @_;
print "ICMP: $ip->{src_ip} -> $ip->{dest_ip}\n";
},
);
1 while $npe->loop;
DESCRIPTION
This module is little more than a collection of macros and convenience functions. Net::Pcap does all the real work (of lifting libpcap into perl anyway).
Every time I began to write a Net::Pcap application, I had to go figure out all these little things all over again. Most of the functions return C-style truth values (0 is ok, non-zero is a problem), installing a filter is un-obvious, how to disassemble the packet is a process of reading four or five pods (e.g. NetPacket::UDP), etc...
What I wanted was one POD that covered everything you need to know, and a wrapper that makes everything perl-esque.
Net::Pcap::Easy METHODS
There are a couple convenience functions available, two control functions, and various blessed-hash keys at your disposal.
dev()
-
Returns the name of the device you're sniffing.
network()
-
Returns the network the device is on (as a text ip number, e.g., 192.168.1.0).
netmask()
-
Returns the netmask of the device (as a text ip number, e.g., 255.255.255.0).
cidr()
-
Returns the network of the device as a Net::Netmask object, which string-interpolates to CIDR notation.
is_local($ip_or_network)
-
Returns true when the first argument is an IP (as text) or network (as text or as a Net::Netmask object) is "in" the listening network. See Net::Netmask for details on this.
loop()
-
Call this over and over until your program is done listening. It collects a number of packets equal to
packets_per_loop
(see below) and passes each packet, one at a time, to any callbacks you've specified (see below).This returns 1 if the count of packets was reached and returns () otherwise.
new()
-
The details are in the OPTIONS section below.
{pcap}
-
This is the actual pcap reference. You can pass it to Net::Pcap functions if you wish.
{network}
-
This is the long (see pack's "l") value of the network.
{netmask}
-
This is the long (see pack's "l") value of the netmask.
OPTIONS
Net::Pcap::Easy takes a small number of options, each of which is purely optional, although it's recommended to specify as many as possible, particularly the device.
The options can only be specified as arguments to the new()
method.
dev
-
The device you wish to listen on, eth0, "Local Area Connection," etc. It's a good idea to specify this device, but if you don't, Net::Pcap::Easy will attempt to locate it with Net::Pcap's
lookupdev()
method. Odds are good that it won't find the device you want, your mileage may vary. packets_per_loop
-
The number of packets to capture on each loop. Most likely, it's more efficient to capture more than one packet per loop. But if you capture too many your program will seem to stutter. Likely there's a nice balance somewhere.
Net::Pcap::Easy defaults to a value of
32
packets per loop. The minimum is1
and Net::Pcap::Easy will silently discard values lower than1
, using the default PPL instead. bytes_to_capture
-
The number of bytes to capture from each packet. Defaults to
1024
. The minimum is256
and Net::Pcap::Easy will silently discard values lower than this, simply using the minimum instead. If you really really want to capture less, you can change the minimum by setting$Net::Pcap::Easy::MIN_SNAPLEN
to whatever value you like. timeout_in_ms
-
Use this to set a timeout for the
loop()
method (see below). The default is0
, meaning: wait until I get my packets. If you set this to some number greater than0
, theloop()
function may return before capturing the requested PPL. promiscuous
-
This is a boolean value (in the perl sense) indicating whether you wish to capture packets not intended for the listening interface. The default is false.
*_callback
-
The captured packets are passed to code refs. There are a variety of callback types to choose from. Each callback must be a code ref.
This is covered in more detail below.
CALLBACKS
Only one callback will get called for each packet.
If a packet would match multiple callbacks it will try to call the most specific match first (whatever that might mean). The callbacks are listed in order of preference.
tcp_callback
-
The callback will receive as arguments:
my ($npe, $ether, $ip, $tcp) = @_;
$npe
is the Net::Pcap::Easy object,$ether
is a NetPacket::Ethernet object,$ip
is a NetPacket::IP object and$tcp
is a NetPacket::TCP object.Each object
NetPacket
object contains a{data}
field that holds the data below the packet headers. Unsurprisingly, the{dest_mac}
and{src_mac}
are available in the$ether
object, the{src_ip}
and{dest_ip}
are in the$ip
object and the{dest_port}
and{src_port}
are in the$tcp
object.Example:
tcp_callback = sub { my ($npe, $ether, $ip, $tcp) = @_; print "TCP: $ip->{src_ip}:$tcp->{src_port} -> $ip->{dest_ip}:$tcp->{dest_port}\n"; print "\t$ether->{src_mac} -> $ether->{dest_mac}\n" if $SHOW_MAC; }
udp_callback
-
The callback will receive as arguments:
my ($npe, $ether, $ip, $udp) = @_;
This works exactly like the
tcp_callback
except that instead of$tcp
, the callback is passed a$udp
argument that is a NetPacket::UDP object. The$udp
object has a{src_port}
and{dest_port}
, just like you'd expect. icmp_callback
-
The callback will receive as arguments:
my ($npe, $ether, $ip, $icmp) = @_;
This callback is quite similar to the
tcp_callback
/udp_callback
s, but the NetPacket::ICMP object doesn't have ports. See that page for details on parsing ICMP packets and/or use the more specific callbacks below, instead of parsing the{type}
by hand.Technically these ICMP are out of preference order (they should be above, not below the
icmp_callback
). However, they all receive identical arguments to the genericicmp_callback
...Specific ICMP Callbacks:
icmpechoreply_callback
,icmpunreach_callback
,icmpsourcequench_callback
,icmpredirect_callback
,icmpecho_callback
,icmprouteradvert_callback
,icmproutersolicit_callback
,icmptimxceed_callback
,icmpparamprob_callback
,icmptstamp_callback
,icmptstampreply_callback
,icmpireq_callback
,icmpireqreply_callback
igmp_callback
-
The callback will receive as arguments:
my ($npe, $ether, $ip, $igmp) = @_;
Please see the NetPacket::IGMP page for details on the
$igmp
argument. ipv4_callback
-
The callback will receive as arguments:
my ($npe, $ether, $ip, $spo) = @_;
$spo
is any of NetPacket::TCP, NetPacket::UDP, NetPacket::ICMP, NetPacket::IGMP, orundef
(see the default callback, below, for an example on parsing the$spo
).The biggest difference between the
ipv4_callback
and thedefault_callback
is that you can say for sure the third argument is a NetPacket::IP object. arp_callback
-
The callback will receive as arguments:
my ($npe, $ether, $arp) = @_;
This callback is also quite similar to the
tcp_callback
/udp_callback
/icmp_callback
s. See the NetPacket::ARP page for details on parsing ARP packets and/or use the more specific callbacks below, instead of parsing the{type}
by hand.Technically these ARP are out of preference order (they should be above, not below the
arp_callback
). However, they all receive identical arguments to the genericarp_callback
...Specific ARP Callbacks:
arpreply_callback
,arpreq_callback
,rarpreply_callback
,rarpreq_callback
ipv6_callback
-
The callback will receive as arguments:
my ($npe, $ether) = @_;
There doesn't seem to be a
NetPacket
decoder for this type of packet, so, this callback gets only theNetPacket::Ethernet
object. snmp_callback
-
The callback will receive as arguments:
my ($npe, $ether) = @_;
There doesn't seem to be a
NetPacket
decoder for this type of packet, so, this callback gets only theNetPacket::Ethernet
object. ppp_callback
-
The callback will receive as arguments:
my ($npe, $ether) = @_;
There doesn't seem to be a
NetPacket
decoder for this type of packet, so, this callback gets only theNetPacket::Ethernet
object. appletalk_callback
-
The callback will receive as arguments:
my ($npe, $ether) = @_;
There doesn't seem to be a
NetPacket
decoder for this type of packet, so, this callback gets only theNetPacket::Ethernet
object.
default_callback
-
Anything not captured above will go to this callback if specified. It receives a variety of arguments, differing based on the packet types. There are seven types of calls it might receive:
my ($npe, $ether, $ip, $tcp) = @_; # TCP packets my ($npe, $ether, $ip, $udp) = @_; # UDP packets my ($npe, $ether, $ip, $icmp) = @_; # ICMP packets my ($npe, $ether, $ip, $igmp) = @_; # IGMP packets my ($npe, $ether, $ip) = @_; # other IP packets my ($npe, $ether, $arp) = @_; # ARP packets my ($npe, $ether) = @_; # everything else
Example:
default_callback = sub { my ($npe, $ether, $po, $spo) = @_; if( $po ) { if( $po->isa("NetPacket::IP") ) { if( $spo ) { if( $spo->isa("NetPacket::TCP") ) { print "TCP packet: $po->{src_ip}:$spo->{src_port} -> ", "$po->{dest_ip}:$spo->{dest_port}\n"; } elsif( $spo->isa("NetPacket::UDP") ) { print "UDP packet: $po->{src_ip}:$spo->{src_port} -> ", "$po->{dest_ip}:$spo->{dest_port}\n"; } else { print "", ref($spo), ": $po->{src_ip} -> ", "$po->{dest_ip} ($po->{type})\n"; } } else { print "IP packet: $po->{src_ip} -> $po->{dest_ip}\n"; } } elsif( $po->isa("NetPacket::ARP") ) { print "ARP packet: $po->{sha} -> $po->{tha}\n"; } } else { print "IPv6 or appletalk or something... huh\n"; } }
AUTHOR
Paul Miller <paul@cpan.org>
I am using this software in my own projects... If you find bugs, please please please let me know. :) Actually, let me know if you find it handy at all. Half the fun of releasing this stuff is knowing that people use it.
If you see anything wrong with the callbacks, the docs, or anything: Definitely let me know! rt.cpan, irc, email, whatever. Just let me know.
COPYRIGHT
Copyright (c) 2007 Paul Miller -- LGPL [attached]
SEE ALSO
perl(1), Net::Pcap, Net::Pcap, Net::Netmask, NetPacket::Ethernet, NetPacket::IP, NetPacket::ARP, NetPacket::TCP, NetPacket::UDP, NetPacket::IGMP, NetPacket::ICMP
6 POD Errors
The following errors were encountered while parsing the POD:
- Around line 47:
=over should be: '=over' or '=over positive_number'
- Around line 85:
=over should be: '=over' or '=over positive_number'
- Around line 110:
=over should be: '=over' or '=over positive_number'
- Around line 166:
=over should be: '=over' or '=over positive_number'
- Around line 265:
=over should be: '=over' or '=over positive_number'
- Around line 305:
=over should be: '=over' or '=over positive_number'