Net-Traceroute6
view release on metacpan or search on metacpan
Traceroute6.pm view on Meta::CPAN
$VERSION = "0.03"; # Version number is only incremented by
# hand.
@ISA = qw(Exporter);
@EXPORT = qw(TRACEROUTE_OK
TRACEROUTE_TIMEOUT
TRACEROUTE_UNKNOWN
TRACEROUTE_BSDBUG
TRACEROUTE_UNREACH_NET
TRACEROUTE_UNREACH_HOST
TRACEROUTE_UNREACH_PROTO
TRACEROUTE_UNREACH_NEEDFRAG
TRACEROUTE_UNREACH_SRCFAIL
TRACEROUTE_UNREACH_ADDR
TRACEROUTE_UNREACH_FILTER_PROHIB);
###
## Exported functions.
# Perl's facist mode gets very grumbly if a few things aren't declared
# first.
sub TRACEROUTE_OK { 0 }
sub TRACEROUTE_TIMEOUT { 1 }
sub TRACEROUTE_UNKNOWN { 2 }
sub TRACEROUTE_BSDBUG { 3 }
sub TRACEROUTE_UNREACH_NET { 4 }
sub TRACEROUTE_UNREACH_HOST { 5 }
sub TRACEROUTE_UNREACH_PROTO { 6 }
sub TRACEROUTE_UNREACH_NEEDFRAG { 7 }
sub TRACEROUTE_UNREACH_SRCFAIL { 8 }
sub TRACEROUTE_UNREACH_FILTER_PROHIB { 9 }
sub TRACEROUTE_UNREACH_ADDR { 10 }
## Internal data used throughout the module
# Instance variables that are nothing special, and have an obvious
# corresponding accessor/mutator method.
my @simple_instance_vars = qw(base_port
debug
host
max_ttl
queries
query_timeout
timeout
af
host_address);
# Field offsets for query info array
my $query_stat_offset = 0;
my $query_host_offset = 1;
my $query_time_offset = 2;
#real address family if you specify PF_UNSPEC
my $real_af = -1;
# check whether we have IPv6 support;
my $inet6 = defined(eval 'PF_INET6');
###
# Public methods
# Constructor
sub new {
my $self = shift;
my $type = ref($self) || $self;
my %hash = ();
my %arg = @_;
my $me = bless \%hash, $type;
# If we've been called through an object, use that one as a template.
# Does a shallow copy of the hash key/values to the new hash.
if(ref($self)) {
my($key, $val);
while(($key, $val) = each %{$self}) {
$me->{$key} = $val;
}
}
# Take our constructer arguments and initialize the attributes with
# them.
my $var;
foreach $var (@simple_instance_vars) {
if(defined($arg{$var})) {
$me->$var($arg{$var});
}
}
# Initialize debug if it isn't already.
$me->debug(0) if(!defined($me->debug));
$me->debug_print(1, "Running in debug mode\n");
# Initialize status
$me->stat(TRACEROUTE_UNKNOWN);
# Initialize address family
$me->af(PF_UNSPEC) if (!defined($me->af));
if(defined($me->host)) {
$me->traceroute;
}
$me->debug_print(9, Dumper($me));
$me;
}
##
# Methods
# Do the actual work. Not really a published interface; completely
# useable from the constructor.
Traceroute6.pm view on Meta::CPAN
}
sub queries {
my $self = shift;
my $elem = "queries";
my $old = $self->{$elem};
$self->{$elem} = $_[0] if @_;
return $old;
}
sub query_timeout {
my $self = shift;
my $elem = "query_timeout";
my $old = $self->{$elem};
$self->{$elem} = $_[0] if @_;
return $old;
}
sub host {
my $self = shift;
my $elem = "host";
my $old = $self->{$elem};
$self->{$elem} = $_[0] if @_;
return $old;
}
sub host_address {
my $self = shift;
my $elem = "host_address";
my $old = $self->{$elem};
# Internal representation always uses IP address in string form.
if(@_) {
$self->{$elem} = $_[0];
}
return $old;
}
sub timeout {
my $self = shift;
my $elem = "timeout";
my $old = $self->{$elem};
$self->{$elem} = $_[0] if @_;
return $old;
}
sub af {
my $self = shift;
my $elem = "af";
my $old = $self->{$elem};
if (@_) {
$self->{$elem} = PF_UNSPEC if ($_[0]== PF_UNSPEC) ;
$self->{$elem} = PF_INET if ($_[0]== PF_INET) ;
$self->{$elem} = PF_INET6 if ($inet6 && ($_[0] == PF_INET6));
}
return $old;
}
# Accessor for status of this traceroute object. Externally read only
# (not enforced).
sub stat {
my $self = shift;
my $elem = "stat";
my $old = $self->{$elem};
$self->{$elem} = $_[0] if @_;
return $old;
}
##
# Hop and query functions
sub hops {
my $self = shift;
my $hop_ary = $self->{"hops"};
return() unless $hop_ary;
return(int(@{$hop_ary}));
}
sub hop_queries {
my $self = shift;
my $hop = (shift) - 1;
$self->{"hops"} && $self->{"hops"}->[$hop] &&
int(@{$self->{"hops"}->[$hop]});
}
sub found {
my $self = shift;
my $hops = $self->hops();
if($hops) {
my $host_address = $self->host_address;
my $last_hop = $self->hop_query_host($hops, 0);
my $stat = $self->hop_query_stat($hops, 0);
if( $last_hop eq $host_address &&
(($stat == TRACEROUTE_OK) || ($stat == TRACEROUTE_BSDBUG) ||
($stat == TRACEROUTE_UNREACH_PROTO))) {
return(1);
}
}
return(undef);
}
sub hop_query_stat {
_query_accessor_common(@_,$query_stat_offset);
}
sub hop_query_host {
_query_accessor_common(@_,$query_host_offset);
}
sub hop_query_time {
_query_accessor_common(@_,$query_time_offset);
}
###
# Various internal methods
# Many of these would be useful to override in a derived class.
# Build and return the pipe that talks to our child traceroute.
sub _make_pipe {
my $self = shift;
my @tr_args = $self->_tr_program_name();
push(@tr_args, $self->_tr_cmd_args());
push(@tr_args, $self->host_address());
# XXX we probably shouldn't throw stderr away.
open(SAVESTDERR, ">&STDERR");
#open(STDERR, ">/tmp/log");
open(STDERR, ">/dev/null");
my $pipe = new IO::Pipe;
# IO::Pipe is very unhelpful about error catching. It calls die
# in the child program, but returns a reasonable looking object in
# the parent. This is really a standard unix fork/exec issue, but
# the library really doesn't help us.
my $result = $pipe->reader(@tr_args);
open(STDERR, ">& SAVESTDERR");
close(SAVESTDERR);
# XXX We're going to assume that an eof right after fork/exec is
# actually a failure. This is quite dubious.
if($result->eof) {
die "No output from traceroute. Exec failure?";
}
$result;
}
# Return the name of the traceroute executable itself
sub _tr_program_name {
my $self = shift;
my @args; # collector of arguments
my $os=$Config{'osname'};
my $prg_sw;
OSNAMESW: {
# here comes Solaris
if ($os = ~ /solaris/) {
push (@args, "traceroute");
push (@args, "-A");
$prg_sw = ($self->af == PF_INET6) ? "inet6" : "inet";
push (@args, $prg_sw);
last OSNAMESW;
}
# here comes AIX
#
# here comes Tru64 UNIX
#
# here comes W2K
#
# for the rest we assume traceroute6/traceroute
$prg_sw = ($self->af == PF_INET6) ? "traceroute6" : "traceroute";
push (@args, $prg_sw);
last OSNAMESW;
}
@args;
}
# How to map some of the instance variables to command line arguments
my %cmdline_map = ("base_port" => "-p",
"max_ttl" => "-m",
"queries" => "-q",
"query_timeout" => "-w");
# Build a list of command line arguments
sub _tr_cmd_args {
my $self = shift;
my @result;
push(@result, "-n");
my($key, $flag);
while(($key, $flag) = each %cmdline_map) {
my $val = $self->$key();
if(defined $val) {
push(@result, $flag, $val);
}
}
@result;
}
# Map !<Mumble> notation traceroute uses for various icmp packet types
# it may receive.
my %icmp_map = (N => TRACEROUTE_UNREACH_NET,
H => TRACEROUTE_UNREACH_HOST,
P => TRACEROUTE_UNREACH_PROTO,
F => TRACEROUTE_UNREACH_NEEDFRAG,
S => TRACEROUTE_UNREACH_SRCFAIL,
A => TRACEROUTE_UNREACH_ADDR,
X => TRACEROUTE_UNREACH_FILTER_PROHIB);
# Do the grunt work of parsing the output.
sub _parse {
my $self = shift;
my $tr_output = shift;
ttl:
( run in 0.921 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )