#!/usr/bin/perl -T
use strict;
use warnings;
$|=1;

BEGIN {
    if ( $> && ($^O ne 'VMS') ) {
        print "$0 requires root privileges\n";
        exit 0;
    }
};

use Net::Traceroute::PurePerl;
use Getopt::Long;

use vars qw(
    $opt_V $opt_h $opt_f $opt_p $opt_m $opt_w $opt_q $opt_S $opt_i
    $opt_l $opt_I $opt_D $opt_N $opt_n $host $VERSION
);

$VERSION="1.1";

Getopt::Long::Configure('bundling');

GetOptions (
    "V"   => \$opt_V, "version"      => \$opt_V,
    "h"   => \$opt_h, "help"         => \$opt_h,
    "D+"  => \$opt_D, "debug+"       => \$opt_D,
    "f=i" => \$opt_f, "first_ttl=i"  => \$opt_f,
    "p=i" => \$opt_p, "baseport=i"   => \$opt_p,
    "m=i" => \$opt_m, "maxttl=i"     => \$opt_m,
    "w=i" => \$opt_w, "timeout=i"    => \$opt_w,
    "q=i" => \$opt_q, "nqueries=i"   => \$opt_q,
    "S=s" => \$opt_S, "sourceaddr=s" => \$opt_S,
    "i=s" => \$opt_i, "interface=s"  => \$opt_i,
    "l=i" => \$opt_l, "packetlen=i"  => \$opt_l,
    "N=i" => \$opt_N, "concurrent=i" => \$opt_N,
    "I"   => \$opt_I, "icmp"         => \$opt_I,
    "n"   => \$opt_n,
);
       
if ($opt_V) {
    print "$0 version $VERSION\n";
    exit 0;
}

if ($opt_h) {
    usage();
    exit 0;
}

my $debug      = $opt_D || 0;
my $first_ttl  = $opt_f || 1;
my $baseport   = $opt_p || 33434;
my $maxttl     = $opt_m || 30;
my $qtimeout   = $opt_w || 3;
my $queries    = $opt_q || 3;
my $sourceaddr = $opt_S || '0.0.0.0';
my $interface  = $opt_i || undef;
my $packetlen  = $opt_l || 128;
my $useicmp    = $opt_I || 0;
my $concurrent = $opt_N || 6;

my $resolve  = ($opt_n)   ? 0      : 1;
my $protocol = ($useicmp) ? 'icmp' : 'udp';

$host = $ARGV[0];
if (!$host) {
    usage();
    exit 1;
}

my $t = Net::Traceroute::PurePerl->new(
    host            => $host,
    debug           => $debug,
    first_ttl       => $first_ttl,
    base_port       => $baseport,
    max_ttl         => $maxttl,
    query_timeout   => $qtimeout,
    queries         => $queries,
    source_address  => $sourceaddr,
    packetlen       => $packetlen,
    protocol        => $protocol,
    concurrent_hops => $concurrent,
    device          => $interface,
);
      
$t->traceroute();
$t->pretty_print($resolve);

sub usage {
    print "usage: $0 [-hV] [-I] [-f first_ttl] [-m max_hops] [-p port]\n",
        "\t[-S source_addr] [-i interface] [-l packetlen] [-N concurrent]\n",
        "\t[-w timeout] [-q nqueries] host\n";

    if ($opt_h) {
        print "\n",
            "  -h, --help        display this help and exit\n",
            "  -V, --version     display the version and exit\n",
            "  -n                don't resolve router IPs to host names\n",
            "  -I, --icmp        use ICMP instead of UDP\n",
            "  -f, --first_ttl   set the first hop TTL\n",
            "  -m, --maxttl      set the maximum TTL before stopping\n",
            "  -p, --baseport    set the first UDP port to use\n",
            "  -S, --sourceaddr  set the source address to trace from\n",
            "  -i, --interface   set the source interface to trace from\n",
            "  -l, --packetlen   set the size of the packets to use\n",
            "  -w, --timeout     set the query timeout\n",
            "  -q, --queries     set the number of queries per hop\n";
            "  -N, --concurrent  set the max number of concurrent queries\n";
    }
}
