| Sniffer-HTTP documentation | Contained in the Sniffer-HTTP distribution. |
Net::Pcap::FindDevice - find the "best" network device for sniffing
use Net::Pcap; use Net::Pcap::FindDevice; my $device = find_device($ARGV[0]); my $pcap = Net::Pcap::open_live($device, 128000, -1, 500, \$err);
This module exports only one subroutine, find_device,
which employs a dwimish method to find a network
device suitable for sniffing with Net::Pcap.
find_device DEVICEFinds a good Net::Pcap device based on some criteria:
If the parameter given is a regular expression, is used to scan the names and descriptions of the Net::Pcap device list. The name of the first matching element is returned.
If a Net::Pcap device matching the
stringified parameter exists, it is returned.
If there exists no matching device for the scalar,
undef is returned.
If there is only one network device, the name of that device is returned.
If there is only one device left after removing all network devices with IP address 127.0.0.1, the name of that device is returned.
The name of the device with the default gateway (if any) is returned.
Otherwise it gives up and returns undef.
interfaces_from_ip IPReturns all interfaces that have the ip IP.
The value of IP must be given as a string of
four numbers.
This method is not exported by default so you need to call it fully specified as
Net::Pcap::FindDevice::interfaces_from_ip('127.0.0.1')
Max Maischein (corion@cpan.org)
Copyright (C) 2005-2011 Max Maischein. All Rights Reserved.
This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Net::Pcap, Wireshark, the Alsace in autumn
| Sniffer-HTTP documentation | Contained in the Sniffer-HTTP distribution. |
package Net::Pcap::FindDevice; use strict; use Net::Pcap; # just for the convenience function below use Carp qw(croak); use Exporter::Lite; use vars qw($VERSION @EXPORT); $VERSION = '0.22'; @EXPORT = qw(find_device);
sub find_device { my ($device_name) = @_; # Set up Net::Pcap my @devs = Net::Pcap::findalldevs(\my %devinfo,\my $err); $err ||= ''; if (! @devs) { croak <<NO_DEVICE Net::Pcap didn't find any device: ($err). This may be because your version of libpcap is too low or you might not have the sufficient privileges. You might also not have any networking installed on this system. NO_DEVICE }; my $device = $device_name; if ($device_name) { if (ref $device_name eq 'Regexp') { ($device) = grep {$_ =~ /$device_name/ || $_ =~ $devinfo{$_}} keys %devinfo; } elsif (exists $devinfo{$device_name}) { $device = $device_name; } elsif ( $device_name =~ m!^\d+\.\d+\.\d+\.\d+$! ) { ($device) = interfaces_from_ip( $device_name ); } else { croak "Don't know how to handle $device_name as a Net::Pcap device"; }; } else { use Data::Dumper; # 'any' is disabled as it returns information in a format # I don't understand #if (exists $devinfo{any}) { # $device = 'any'; #} elsif if (@devs == 1) { $device = $devs[0]; } else { # Now we need to actually look at the devices and select the # one with the default gateway: # First, get the default gateway by using # `netstat -rn` my $device_ip; my $re_if = $^O eq 'MSWin32' ? qr/^\s*(?:0.0.0.0)\s+(\S+)\s+(\S+)\s+/ : qr/^(?:0.0.0.0|default)\s+(\S+)\s+.*?(\S+)\s*$/; for (qx{netstat -rn}) { if ( /$re_if/ ) { $device_ip = $2; last; }; }; #if (! $device_ip) { # croak "Couldn't find IP address/interface of the default gateway interface. Maybe 'netstat' is unavailable?"; #}; #for (keys %devinfo) { # warn $_; #}; if (exists $devinfo{$device_ip}) { return $device_ip }; # Looks like we got an IP and not an interface name. # This should all go into # sub interface_from_ip {} # So scan all interfaces if they have that IP address. my @good_devices = interfaces_from_ip($device_ip); if (@good_devices == 1) { $device = $good_devices[0]; } elsif (@good_devices > 1) { croak "Too many device candidates found (@good_devices)"; } }; }; return $device };
sub interfaces_from_ip { my ($ip) = @_; my $good_address = unpack "N", pack "C4", (split /\./, $ip); my @devs = Net::Pcap::findalldevs(\my %devinfo,\my $err); my @result; for my $device (@devs) { #warn "$device/$ip"; (Net::Pcap::lookupnet($device, \(my $address), \(my $netmask), \$err) == 0) or next; #print "$device / $address / $netmask\n"; #for ($address,$netmask) { # print ((join ".", unpack "C4", pack "N", $_),"\n"); #}; $address != 0 or next; for ($address,$netmask) { $_ = unpack "N", pack "N", $_; }; #print "$device / $address / $netmask\n"; if ($address == ($good_address & $netmask)) { push @result, $device; }; }; @result }; 1; __END__