10.4. libpcap and PerlThe libpcap examples we have demonstrated so far have been in C, as the libpcap library is a C library. However, many interfaces and wrappers to libpcap exist for higher-level languages, such as Perl and Python. Using a high-level language has a number of advantages for developers not familiar with C, and for developers looking to quickly throw together a tool that works, without necessarily requiring it to be robust, scalable, or even stable. A tool written in Perl or Python is generally a lot smaller than an equivalent tool written in C. Using a high-level language can also have some disadvantages, in that less commonly used functionality and new functionality within libpcap might not be supported properly, or even at all. Also, high-level languages are not a realistic option for tools requiring high throughput of packet processing, so you would not want to write a network IDS in a high-level language. For the Perl scripting language, the package for libpcap is called Net::Pcap. If a Net::Pcap package is not available for your Linux distribution, you should be able to install Net::Pcap as follows: perl -MCPAN -e 'install Net::Pcap' This downloads the source code for the package and automatically builds the package in most cases. If you are using Windows, your install process might be different. The functions in Net::Pcap are very similar to the C functions, as are the parameters passed to the functions. Documentation of these functions is available on the module's home page, at http://search.cpan.org/~kcarnut/Net-Pcap-0.05/Pcap.pm. 10.4.1. Arpsniff in PerlThe following is a quick demonstration of Net::Pcap functionality and a quick reimplementation of the major functionality of the Arpsniff tool in Perl. Note that this tool also uses the NetPacket::Ethernet and NetPacket::ARP packages to easily decompose the packets it captures: #!/usr/bin/env perl use Net::Pcap; use NetPacket::Ethernet; use NetPacket::ARP; my $errbuf; # find a network device $device = Net::Pcap::lookupdev(\$errbuf); if (defined $errbuf) {die "Unable to find device: ", $errbuf;} # open device $handle = Net::Pcap::open_live($device, 2000, 1, 0, \$errbuf); if (!defined $handle) {die "Unable to open ",$device, " - ", $errbuf;} # find netmask so we can set a filter on the interface Net::Pcap::lookupnet(\$device, \$netp, \$maskp, \$errbuf) || die "Can't find network info"; # set filter on interface $filter = "arp"; Net::Pcap::compile($handle, \$fp, $filter, 0, $maskp) && die "Unable to compile BPF"; Net::Pcap::setfilter($handle, $fp) && die "Unable to set filter"; # start sniffing Net::Pcap::loop($handle, -1, \&process_packet, '') || die "Unable to start sniffing"; # close Net::Pcap::close($handle); sub process_packet { my ($user, $header, $packet) = @_; my $eth_data = NetPacket::Ethernet::strip($packet); my $arp = NetPacket::ARP->decode($eth_data); # convert hex number to IP dotted - from rob_au at perlmonks my $spa = join '.', map { hex } ($arp->{'spa'} =~ /([[:xdigit:]]{2})/g); my $tpa = join '.', map { hex } ($arp->{'tpa'} =~ /([[:xdigit:]]{2})/g); print "Source: ",$spa,"\tDestination: ",$tpa, "\n"; } |