#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  prpath.pl prpath.8 Makefile
# Wrapped by tony@mature.ripe.net on Thu Aug 18 15:33:32 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f prpath.pl -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"prpath.pl\"
else
echo shar: Extracting \"prpath.pl\" \(18372 characters\)
sed "s/^X//" >prpath.pl <<'END_OF_prpath.pl'
X#!PERL
X# 
X# Copyright (c) 1993 The RARE Association 
X# 
X# All Rights Reserved
X# 
X# Permission to use, copy, modify, and distribute this software and its 
X# documentation for any purpose and without fee is hereby granted, 
X# provided that the above copyright notice appear in all copies and that
X# both that copyright notice and this permission notice appear in 
X# supporting documentation, and that the name of the author not be
X# used in advertising or publicity pertaining to distribution of the
X# software without specific, written prior permission.  
X# 
X# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
X# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
X# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
X# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X#
X#
X#
X#	$RCSfile: prpath.pl,v $
X#	$Revision: 0.23 $
X#	$Author: tony $
X#	$Date: 1994/08/17 11:44:55 $
X#
X#
Xrequire "getopts.pl";
X$whoishost = "WHOISHOST";
X$keepopen = "KEEPOPEN";
X$fast = "FAST";
X$version = "VERSION";
X$port = PORT;
X$AF_INET = 2;
X$SOCK_STREAM = 1;
X
X
Xsub numerically { $a <=> $b ; }
X
Xsub parsepolicy {
X
X    local($curas, $peer, $weight, $string) = @_;
X    local($val, $left) = "";
X
X    if ($node{$curas}) {
X        $node{$curas} .= "@";
X    }
X    $node{$curas} .= "$peer%$weight%";
X
X    $_ = $string;
X    if ($_ =~ /^\s+$/ || /^$/) {
X        return;
X    }
X
X    s/(ANY|RIPE\-DB|LOCAL|AS[0-9]+|AS\-[A-Z]+)\s+(ANY|RIPE\-DB|LOCAL|AS[0-9]+|AS\-[A-Z]+)/\1 OR \2/g;
X    s/(ANY|RIPE\-DB|LOCAL|AS[0-9]+|AS\-[A-Z]+)\s+(ANY|RIPE\-DB|LOCAL|AS[0-9]+|AS\-[A-Z]+)/\1 OR \2/g;
X
X    $val = &expr;
X    if ($_) {
X        chop;
X        $left = $_;
X    }
X    return;
X}
X
Xsub expr {
X    local($left, $op, $right);
X
X    $left = &term;
X    
X    while ($op = &oper) {
X        $right = &term;
X        if ($op eq "OR") {
X            $op = "";
X        }
X        $left = $left.$op.$right;
X    }
X    $left;
X}
X
Xsub oper {
X    s/^[\s]+//;
X    ((s/^(AND)//) && $1) || ((s/^(OR)//) && $1);
X}
X
Xsub addtolist {
X    local(*array, $index, $value) = @_;
X    $array{$index} .= $value." ";
X}
X
Xsub term {
X    local($val);
X    
X    return if /^\s*$/;    
X    s/^[\s]+//;
X
X    if (s/^(AS[0-9]+)//) {
X        $val = $1;
X        if (!$not) {
X            &addtolist(*node, $curas, $val);
X        }
X    }
X    elsif (s/^(AS\-[A-Z]+)//) {
X	foreach (split(/\s+/, &expasmac($1))) {
X	    if (!$not) {
X		&addtolist(*node, $curas, $_);
X	    }
X	}
X    }
X    elsif (s/^\(//) {
X        $val = &expr;
X        s/^\)// || return;
X    }
X    elsif (s/^(NOT)//) {
X        $not = 1;
X        $val = &expr;
X        $not = 0;
X    }
X    elsif (s/^(ANY)//) {
X        $val = "ANY";
X        if (!$not) {
X            &addtolist(*node, $curas, $val);
X        }
X    }
X    elsif (s/^(RIPE-DB)//) {
X        # $val = "RIPE-DB";
X        # Hack - treat RIPE-DB as ANY for now ;-(
X        $val = "ANY";
X        if (!$not) {
X            &addtolist(*node, $curas, $val);
X	}
X    }
X    elsif (s/^(LOCAL)//) {
X        $val = "LOCAL";
X    }
X    else {
X
X# Left in for now as we should do better messages in the parser itself
X#
X#               print "Cannot parse $_\n";
X#               print "In context $op\n";
X#               print "Syntax error\n";
X        return;
X    }
X    $op = $val;
X    $val;
X}
X#
X# Deal with AS Macros 
X# 
X# They take the form of AS-<MACRO_NAME>
X# Need to deal with recursion as well
X#
Xsub expasmac {
X
X    local($asmac) = @_;
X    local(@data) = ();
X    local($i) = 0;
X    if(!$gotasmac{$asmac}) {
X	&whois($asmac);
X	while(<S>) {
X
X# this is needed for the -k delimeter which is \n\n
X
X	    if ($keepopen) {
X		if (/^\s*$/) {
X		    last if $newline == 1;
X		    $newline = 1;
X		    next;
X		}
X		$newline = 0;
X	    }
X
X	    $data[$i++] = $_;
X	}
X	foreach $i (0..$#data) {
X	    $_ = $data[$i];
X
X	    chop;
X	    if(/^as-macro: / || /^\*am: /) {
X		local($tmp, $rest) = split(/[\s\t]+/, $_, 2);
X		if ($asmac eq $rest) {
X		    $gotasmac{$asmac} = 1;
X		} else {
X		    return ("");
X		}
X	    }
X	    if ((/^as-list: / || /^\*al: /) && $gotasmac{$asmac}) {
X		local($tmp, @aslist) = split(/[\s\t]+/, $_);
X		foreach $i (@aslist) {
X		    if($i =~ /^AS\-[A-Z]+$/) {
X			$asmacros{$asmac} .= &expasmac($i)." ";
X		    } else {
X			$asmacros{$asmac} .= "$i ";
X		    }
X		}
X	    }
X	}
X    }
X    $asmacros{$asmac};
X}
X# Local whois client, to avoid forks and compatibility problems
X# It basically is a fully-fledged RIPE version of the whois client.
X# It leaves the socket descriptor open, the routine reading from the
X# socket is supposed to close the socket again. Besides, the server
X# will most probably close the connection, once all data has been output
X
Xsub whois {
X
X    local($string) = @_;
X    local($key) = "";
X    local($type);
X        
X    if (!$connected) {
X        $sockaddr = 'S n a4 x8';
X        ($name, $aliases, $type, $len, $thataddr) = gethostbyname($whoishost);
X        $that = pack($sockaddr, $AF_INET, $port, $thataddr);
X        socket(S, $AF_INET, $SOCK_STREAM, $proto) || die "socket failed\n";
X        if ( connect(S, $that) ) {
X            if ( $opt_d) {
X                printf "** connecting to whois host %s\n", $whoishost;
X            }
X            if ($keepopen) {
X                $connected = 1;
X            }
X        } else { 
X            die "Connect to whois host $whoishost failed\n";
X        }
X        if ( $opt_d ) {
X            printf "** connected ok\n";
X        }
X    }
X    select(S); $| = 1; select(STDOUT);
X    
X    if ($string =~ /^-a/) {
X        ($tmp, $key) = split(/[\t\s]+/,$string, 2);
X        print S "-a ";
X    }
X    else {
X        $key = $string;
X    }
X    if($keepopen) {
X        print S "-k ";
X    }
X    if($fast) {
X        print S "-F ";
X    }
X    if($version) {
X        printf S "-Vpp%s ", $versionno;
X    }
X    print S "-r $key\n";
X    return S;
X}
X
X
Xsub netinfo {
X    local($netnum) = @_;
X    local($asnum) = "";
X    local($newline) = 0;
X    local(@data) = ();
X    local($i) = 0;
X    
X    if ($opt_d) {
X	print "** netinfo called with argument $netnum\n";
X    }
X    
X    ($first, $second, $third, $fourth) = split(/\./, $netnum);
X    if ($first < 127) {
X	$lookupnet = $first;
X    }
X    elsif ($first < 192) {
X	$lookupnet = "$first.$second";
X    }
X    else {
X	$lookupnet = "$first.$second.$third";
X    }
X    
X    if (!$firstlookup) {
X	$destnet = $lookupnet;
X	$firstlookup = 1;
X    }
X
X    if ($knownas{$lookupnet}) {
X	$asnum = $knownas{$lookupnet};
X    }
X    else {
X	$netwhoisq++;
X	&whois("-a $lookupnet");
X	while (<S>) {
X	    if($keepopen) {
X		if (/^\s*$/) {
X		    last if $newline == 1;
X		    $newline = 1;
X		    next;
X		}
X		$newline = 0;
X	    }
X	    $data[$i++] = $_;
X	}
X	foreach $i (0..$#data) {
X	    $_ = $data[$i];
X	    if (/^aut-sys: / || /^\*as: /) {
X		($tmp, $asnum) = split(/[\s\t]+/, $_);
X		if ($asnum =~ /^AS/) {
X		    $asnum = substr($asnum,2);
X		}
X		$knownas{$lookupnet} = $asnum;
X		if (!$firstas) {
X		    $firstas = "AS$asnum";
X		}
X		$lastas = "AS$asnum";
X		next;
X	    }
X	    if (/^ias-int: / || /^\*ii: /) {
X		if ($opt_d) {
X		    print "** found ias-int line\n";
X		}
X		($tmp, $int, $as) = split(/\s+/, $_);
X		$as =~ s/AS//;
X		$iasint{$int} = $as;
X		$dmz{$netnum} = 1;
X		$dmzas{"$lookupnet%$asnum"} = 1;
X		$dmzas{"$lookupnet%$as"} = 1;
X		next;
X	    }
X	}
X    }
X    if ($iasint{$netnum}) {
X	if ($opt_d) {
X	    print "** found ias-int for this address\n";
X	}
X	$asnum = $iasint{$netnum};
X    }
X    if ($opt_d) {
X	print "** netinfo returns $asnum\n";
X    }
X    return($asnum);
X}
Xsub asinfo {
X    local($asnum) = @_;
X    local($rest) = "";
X    local($as) = "";
X    local($tmp) = "";
X    local($nb) = "";
X    local($wt) = "";
X    local($line) = "";
X    local($d) = "";
X    local($newline) = 0;
X    local(@data) = ();
X    local($i) = 0;
X    
X    
X    if ($opt_d) {
X        print "** asinfo called with argument $asnum\n";
X    }
X
X    return if ($descr{"AS$asnum"} || $descr{$asnum});
X
X    &whois("-a -F $asnum");
X    $aswhoisq++;
X    
X    while (<S>) {
X        if ($keepopen) {
X            if (/^\s*$/) {
X                last if $newline == 1;
X                $newline = 1;
X                next;
X            }
X            $newline = 0;
X        }
X	$data[$i++] = $_;
X    }
X    foreach $i (0..$#data) {
X	$_ = $data[$i];
X	chop;
X        if (/^aut-num:/ || /^\*an: /) {
X            if ($opt_d) {
X                print "** found aut-num line\n";
X            }
X            ($tmp, $as) = split(/[\s\t]+/, $_);
X            next;
X        }
X        
X        if (/^as-in:/ || /^\*ai: /) {
X            if ($opt_d) {
X                print "** found as-in line\n";
X            }
X            ($tmp, $line) = split(/\s+/, $_, 2);
X            ($nb, $wt, $rest) = split(/\s+/, $line, 3);
X            &parsepolicy($as, $nb, $wt, $rest);
X            next;
X        }
X
X        if (/^default:/ || /^\*df: /) {
X            if ($opt_d) {
X                print "** found default line\n";
X            }
X            ($tmp, $nb, $wt) = split(/[\s\t]+/, $_);
X            if ($node{$as}) {
X                $node{$as} .= "\@";
X            }
X            $node{$as} .= "$nb%$wt%DEF";
X            next;
X        }
X        
X        if ((/^descr:/ || /^\*de: /) && !$descr{$as}) {
X            if ($opt_d) {
X                print "** found description line\n";
X            }
X            ($tmp, $d) = split(/[\s\t]+/, $_, 2);
X            $descr{$as} = $d;
X            next;
X        }
X    }
X    $descr{$as} = "??" if !$descr{$as};
X}
X
Xsub nexthop3 {
X    local($dest, $string) = @_;
X    local($i) = 0;
X    local(@peer);
X    local($nweight) = 65536;
X    local($defaultweight) = 65536;
X    local($nexthop) = "";
X    local($defaulthop) = "";
X    local($neigh) = "";
X    local($weight) = "";
X    
X    @peer = split(/@/, $string);
X    
X    foreach $i (0..$#peer) {
X        ($neigh, $weight, $ann) = split(/%/,$peer[$i]);
X        if ($ann =~ /$dest /) {
X            $nexthop .= "$weight%$neigh ";
X        }
X        if ($ann =~ /DEF/) {
X            $tmp = $weight+1000;
X            $nexthop .= "$tmp-D%$neigh ";
X        }
X        if ($ann =~ /ANY/) {
X            $nexthop .= "$weight-A%$neigh ";
X        }
X    }
X
X    if($opt_d) {
X        print "** nexthop returns \"$nexthop\"\n";
X    }
X    return $nexthop;
X}
X
X
Xsub findpath3 {
X
X    local($start, $end, $curpath) = @_;
X    local($nexthop) = "";
X    local($neigh) = "";
X    local(@nexthops) = ();
X    local($i) = 0;
X
X# Find string with all nexthops and weights from &nexthop.
X
X    if (!$node{$start}) {
X	&asinfo($start);
X	&asinfo($end);		# needed only for legend
X    }
X    $nexthop = &nexthop3($end, $node{$start});
X
X# Split into an array containing "weight%neighbor" for each of the possible
X# neighbors. Sort the on the fly on cost (weight).
X
X    @nexthops = sort numerically split(/ /, $nexthop);
X
X# For all the neighbors in the array, try and find a path from this
X# neighbor to the destination.
X
X    foreach $i (0..$#nexthops) {
X	($weight, $neigh) = split(/%/,$nexthops[$i]);
X
X# No neighbor could be found, network unreachable for this path.
X
X	if (!$neigh eq "") {
X	    print "** No next hop found: ";
X	    print "$curpath!N **\n";
X	    last;
X	}
X	else {
X	    if (($neigh ne $end) && ($start ne $end)) {
X
X# If this is a default path (-D in weight and 1000 added to weight)
X# Get rid off the -D and subtract 1000 from weight and flag that path
X# is a default path using a D
X
X		if ($weight =~ /D/) {
X		    ($w) = split(/-/, $weight);
X		    $w-=1000;
X		    if ($opt_v) {
X			$path = $curpath."($w D) $neigh ";
X		    } else {
X			$path = $curpath."$neigh ";
X		    }
X		}
X		else {
X		    if ($opt_v) {
X			$path = $curpath."($weight) $neigh ";
X		    } else {
X			$path = $curpath."$neigh ";
X		    }
X		}
X		
X# Loop detection. Just keep a list of all neighbors seen traversing the
X# current path. If nexthop is already seen, loop and stop.
X
X		if ($seen{$neigh}) {
X		    if($opt_l) {
X			print "** possible loop detected: ";
X			print "$curpath($weight) $neigh **\n";
X		    }
X		    next;
X		} else {
X
X# No loop, so we have now seen this neighbor. Make sure to unflag each
X# neighbor in backtracking, because the same neighbor may appear in 
X# different paths of course ...
X
X		    $seen{$neigh} = 1;
X		    &findpath3($neigh, $end, $path);
X		    $seen{$neigh} = 0;
X		}
X	    }
X	    
X# neighbor is the destination, so we have the complete path. Put in a 
X# global array and increment pointer for this array.
X
X	    else {
X		if ($opt_v) {
X		    if (!$seenpath{"$curpath($weight) $end"}) {
X			$paths[$pathindex] = "$curpath($weight) $end";
X			$seenpath{"$curpath($weight) $end"} = 1;
X			$pathindex++;
X		    }
X		} else {
X		    if (!$seenpath{"$curpath$end"}) {
X			$paths[$pathindex] = "$curpath$end";
X			$seenpath{"$curpath$end"} = 1;
X			$pathindex++;
X		    }
X		}
X	    }
X	}
X    }
X}
X
Xsub parsearg {
X    local($arg) = @_;
X    local($tmp,$n) = "";
X    if($arg =~ /^[Aa][sS]\d+/) {	# Assume an asnum
X	$arg =~ s/as/AS/;
X	if(!&isasnum("$arg")) {
X	    printf "token \"$arg\" is not a valid AS number\n";
X	    exit(1);
X	}
X	return $arg;
X    }
X    if($arg =~ /^\d+\.\d+\.\d+\.\d+/) { # Assume a network or number
X	if (&isnetnum($arg) || &isipaddr($arg)) {
X	    $tmp = &netinfo($arg);
X	    if ($tmp =~ /\d+/) {
X		return ("AS".$tmp);
X	    } else {
X		printf "token \"$arg\" does not translate to an AS number\n";
X		exit(1);
X	    }
X	}
X    } else {
X	($name, $alias, $addrtype, $length, @addr) = gethostbyname($arg);
X        ($a, $b, $c, $d) = unpack('C4', $addr[0]);
X	if($#addr == -1) {
X	    printf "token \"$arg\" is an unknown host\n";
X	    exit(1);
X	}
X	$n = $a.".".$b.".".$c.".".$d; 
X	$tmp = &netinfo($n);
X	if ($tmp =~ /\d+/) {
X	    return ("AS".$tmp);
X	} else {
X	    printf "token \"$arg\" does not translate to an AS number\n";
X	    exit(1);
X	}
X    }
X}
Xsub isasnum {
X    local($str) = @_;
X    if($str !~ /^AS[1-9]+\d*$/ ) {
X	return 0;
X    }
X    $str =~ s/AS//;
X    if($str =~ /[A-z]+/ ) {
X	return 0;
X    }
X    $str = $str + 0 ;
X    if ( $str < 1 || $str > 65535 ) {
X	return 0; 
X    }
X    return 1;
X}
X
Xsub isnetnum {
X    local($str) = @_;
X    local($ind) = 0;
X    local(@add) = split(/\./, $str);
X    if ($#add != 3) {
X	return 0;
X    }
X    foreach $ind (0..$#add) {
X	if (($add[$ind] !~ /^[0-9][0-9]*/) || ($add[$ind] > 255)) {
X	    return 0;
X	}
X    }
X    if (($add[0] < 128) && 
X	(($add[1] != 0 ) || 
X	 ($add[2] != 0 ) || 
X	 ($add[3]  = 0 ))) {
X	return 0;
X    } elsif (($add[0] < 192) && (($add[2] != 0 ) || ($add[3] != 0 ))) {
X	return 0;
X    } elsif (($add[0] < 224) && ($add[3] != 0 )) {
X	return 0;
X    }
X    return 1;
X}
X
Xsub isipaddr {
X    local($str) = @_;
X    local($i) = 0;
X    local(@add) = split(/\./, $str);
X    
X    if ($#add != 3) {
X	return 0;
X    }
X    foreach $i (0..$#add) {
X	if ($add[$ind] < 1 || $add[$ind] > 254 ) {
X	    return 0;
X	}
X    }
X    return 1;
X}
X
Xsub prpaths {
X    if($#paths == -1) {
X	printf "** no paths founds%s **\n",  
X	$opt_l ? "" : ", try running -l flag";
X    } else {
X	$aspath{"$from"} = 1;	
X	foreach $i (0..$#paths) {
X	    printf "%2d: %s ", $i + 1, $from;
X	    print $paths[$i], "\n";
X	    foreach $j (split(/\s+/, $paths[$i])) {
X		if(!$aspath{"$j"}) {
X		    $aspath{"$j"} = 1;
X		}
X	    }
X	}
X    }
X    print "\n";
X    @paths = ();
X    $pathindex = 0;
X}
X# 
X# Return an IP address from a name.
X#
Xsub getadr {
X    local($host) = @_;
X    local($name, $alias, $addrtype, $length, @addr) = gethostbyname($host);
X    if (defined($addr[0])) {
X        local($a, $b, $c, $d) = unpack('C4', $addr[0]);
X        $addr = $a.".".$b.".".$c.".".$d;
X        return($addr);
X    } else {
X        print STDERR "$0: unknown address for $host\n";
X        exit 1;
X    }
X}
X#
X# Return the fully qualified domain name.
X#
Xsub getfqdn {
X    local($host) = @_;
X    if ($host =~ /^[Aa][sS]\d+$/) {
X	return($host);
X    }
X#
X# resolve an address first
X#
X    if($host =~ /^(\d+)+\.(\d+)\.(\d+)\.(\d+)$/) { 
X        local($tmp) = pack('C4', $1, $2, $3, $4);
X        local($name, $alias, $addrtype, $length, @addr) = gethostbyaddr($tmp,2);
X        if (defined($name)) {
X            return($name);
X        } else {
X            return($host);
X        }
X    }   
X#
X# okay then try a name
X#           
X
X    local($name, $alias, $addrtype, $length, @addr) = gethostbyname($host);  
X    if (!defined($name)) {
X        print STDERR "$0: unknown host $host\n";
X        exit 1;
X    }
X    return($name);
X}
X
X
Xsub usage {
X    local($msg) = @_;
X    $0 =~ /([^\/]+)$/;
X    local($com) = $1; 
X    printf "Usage: $com -v -l -d token token [ token ]\n";
X    printf "Possible token values:\n";
X    printf "\tAS number   [ASnnnn]\n";
X    printf "\tIP address  [aaa.bbb.ccc.ddd]\n";
X    printf "\tIP network  [aaa.bbb.ccc.0]\n";
X    printf "\tHostname    [some.where.net]\n";
X}
X
X
X&Getopts('dvlh:p:KFV');
X
Xif($#ARGV < 1 || $#ARGV > 2 ) {
X    &usage();
X    exit(1);
X}
Xif ($opt_h) {
X    $whoishost = $opt_h;
X}
Xif ($ENV{"PRTRACEHOST"}) {
X        $whoishost = &getfqdn($ENV{"PRTRACEHOST"});
X}
Xif ($opt_h) {
X    $whoishost = &getfqdn($opt_h);
X}
Xif ($ENV{"PRTRACEPORT"}) {
X    $port = $ENV{"PRTRACEPORT"};
X}
Xif ($opt_p) {
X    $port = $opt_p;
X}
X
X
Xif ($keepopen =~ /^TRUE$/) {
X    $keepopen = 1;
X} else {
X    $keepopen = 0;
X}
Xif ($opt_K) {
X    $keepopen = 0;
X}
Xif ($fast =~ /^TRUE$/) {
X    $fast = 1;
X} else {
X    $fast = 0;
X}
Xif ($opt_F) {
X    $fast = 0;
X}
Xif ($version=~ /^TRUE$/ ) {
X    $versionno = "\$Revision: 0.23 $"; #" Need to fool emacs with this quote
X    $versionno =~ s/\$Revision\: //;
X    $versionno =~ s/ \$$//;
X    $version = 1;
X} else {
X    $version = 0;
X}
Xif ($opt_V) {
X    $version = 0;
X}
X
X
Xif ($opt_d) {
X    printf "** %s use keepopen feature\n", 
X    $keepopen ? "will" : "will not" ;
X}
X
X$arg1 = &parsearg("$ARGV[0]");
X$arg2 = &parsearg("$ARGV[1]");
X$name1 = &getfqdn("$ARGV[0]");
X$name2 = &getfqdn("$ARGV[1]");
X
Xprint "Possible paths using routing registry information from $whoishost\n";
Xprintf "From \"$arg1\" \($name1\) to \"$arg2\" \($name2\)\n\n";
X$seen{$arg1} = 1;
X&findpath3($arg1, $arg2, "");
X$from = $arg1;
X&prpaths();
X
Xif($#ARGV == 2) {
X    $arg3 = &parsearg("$ARGV[2]");
X    $name3 = &getfqdn("$ARGV[2]");
X
X    print "From \"$arg2\" \($name2\) to \"$arg3\" \($name3\)\n\n";
X    $seen{$arg2} = 1;
X    &findpath3($arg2, $arg3, "");
X    $from = $arg2;
X    &prpaths();
X}
X
X#
X# Now print legend
X#
Xif(%aspath) {
X    print "\nLegend\n\n";
X
X    foreach $i (sort num keys %aspath) {
X    	if (!$done{$i}) {
X	    printf "%6s = %s\n", $i, $descr{"$i"};
X	    $done{$i} = 1;
X    	}
X    }
X}
X
Xsub num {
X    substr($a,2) <=> substr($b,2);
X}
END_OF_prpath.pl
if test 18372 -ne `wc -c <prpath.pl`; then
    echo shar: \"prpath.pl\" unpacked with wrong size!
fi
chmod +x prpath.pl
# end of overwriting check
fi
if test -f prpath.8 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"prpath.8\"
else
echo shar: Extracting \"prpath.8\" \(3344 characters\)
sed "s/^X//" >prpath.8 <<'END_OF_prpath.8'
X.\"
X.\"
X.\" 
X.\" Copyright (c) 1993 The RARE Association 
X.\" 
X.\" All Rights Reserved
X.\" 
X.\" Permission to use, copy, modify, and distribute this software and its 
X.\" documentation for any purpose and without fee is hereby granted, 
X.\" provided that the above copyright notice appear in all copies and that
X.\" both that copyright notice and this permission notice appear in 
X.\" supporting documentation, and that the name of the author not be
X.\" used in advertising or publicity pertaining to distribution of the
X.\" software without specific, written prior permission.  
X.\" 
X.\" THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X.\" ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
X.\" AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X.\" DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
X.\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
X.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X.\"
X.\"
X.\"	$RCSfile: prpath.8,v $
X.\"	$Revision: 0.11 $
X.\"	$Author: tony $
X.\"	$Date: 1994/05/19 15:00:45 $
X.TH prpath 8 "May 19th, 1994"
X.UC 6
X.SH NAME
Xprpath \- print all the possible paths between any two given destinations
X.SH SYNOPSIS
X.B prpath
X[ 
X.B \-d
X] [
X.B \-v
X] [
X.B \-l
X]
X.B
Xtoken
X.B
Xtoken
X[
X.B
Xtoken
X]
X.SH DESCRIPTION
XPrpath is a tool to show all the possible paths between any two given
Xdestinations according to the routing policy information registered in
Xthe routing registry.
X.PP
XOptions are:
X.SH OPTIONS
X.TP 6
X.B \-l
XShow possible loops. This output can be very long so should be used
Xwith caution.
X.TP 
X.B \-d
XDebug output. Gives additional internal information and should not be
Xused for general use.
X.TP
X.B \-v
XVerbose output. This will display some additional information about
Xwhy the path selection was made in such a way.
X.TP
X.B token
XA token can either an AS number, IP address/hostname or network
Xnumber. It expects at least two tokens although an optional third can
Xbe given to show a path back or to another destination.
X.SH EXAMPLES
XA sample use and output might be:
X
X.DS L
X.nf
X.if t .ft C
X% prpath mature tftp.ebone.net ns0.ja.net
XPossible paths using routing registry information from whois.ripe.net
XFrom "AS2122" (mature.ripe.net) to "AS1755" (tftp.ebone.net)
X
X 1: AS3333 AS1103 AS1128 AS1755
X 2: AS3333 AS286 AS1755
X 3: AS1104 AS1103 AS1128 AS1755
X
XFrom "AS1755" (tftp.ebone.net) to "AS786" (ns0.ja.net)
X
X 1: AS1755 AS1128 AS2043 AS786
X
X.fi
X.DE
X.PP
XThis shows in the first case the paths between mature.ripe.net and
Xtftp.ebone.net. Here we see three possible paths with AS3333 to AS1103
Xto AS1128 to AS1755 being the most preferred path. Then a second 
Xpath selection from tftp.ebone.net to ns0.ja.net. Here we only see one
Xpossible path.
X.SH ENVIRONMENT
X.IP "PRTRACEHOST" 8
XThis will change the RR whoishost to use. The \-h option will override
Xthis.
XThe default is WHOISHOST.
X.IP "PRTRACEPORT" 8
XThe will change the port number to use to connect to the RR. The \-p
Xport
Xwill override this. The default is port XPORT.
X.SH AUTHORS
XTony Bates and Marten Terpstra.
X.SH SEE ALSO
Xwhois(1), perl(1).
X.PP 
X"Representation of IP Routing Policies in the RIPE Database -
Xripe-81",
XTony Bates, Jean-Michel Jouanigot, Daniel Karrenberg, Peter Lothberg,
XMarten
XTerpstra.
X
X
END_OF_prpath.8
if test 3344 -ne `wc -c <prpath.8`; then
    echo shar: \"prpath.8\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(2385 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# 
X# Copyright (c) 1993 The RARE Association 
X# 
X# All Rights Reserved
X# 
X# Permission to use, copy, modify, and distribute this software and its 
X# documentation for any purpose and without fee is hereby granted, 
X# provided that the above copyright notice appear in all copies and that
X# both that copyright notice and this permission notice appear in 
X# supporting documentation, and that the name of the author not be
X# used in advertising or publicity pertaining to distribution of the
X# software without specific, written prior permission.  
X# 
X# THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
X# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
X# AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
X# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
X# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
X# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
X#
X#
X#	$RCSfile: Makefile,v $
X#	$Revision: 0.13 $
X#	$Author: tony $
X#	$Date: 1994/06/16 09:32:36 $
X#
X
XSRC=		prpath.pl
XMAN=		prpath.8
X
XBINDIR=		/usr/local/bin
XPERL=		/usr/local/bin/perl
XMANDIR=		/usr/local/man
XMANEXT=		8
XWHOISHOST=	whois.ripe.net
XPORT=		43
X# 
X# If you are running Solaris 2.* set SOCKSTREAM to 2
X# otherwise leave it as it is
X#
XSOCKSTREAM=	1
X#
XKEEPOPEN=	TRUE
XFAST=		TRUE
XVERSION=	TRUE
XSHAR=		shar -odist.shar
X
XOBJ=		prpath
XDIST=		$(SRC) $(MAN) Makefile 
X
Xprpath: prpath.pl Makefile $(DEP)
X	sed     -e 's:WHOISHOST:$(WHOISHOST):' \
X		-e 's: PORT: $(PORT):' \
X		-e 's:PERL:$(PERL):' \
X		-e 's:HOSTCMD:$(HOSTCMD):' \
X		-e 's:TRACEROUTE:$(TRACEROUTE):' \
X		-e 's:KEEPOPEN:$(KEEPOPEN):' \
X		-e 's:SOCKSTREAM:$(SOCKSTREAM):' \
X		-e 's:FAST:$(FAST):' \
X		-e 's:VERSION:$(VERSION):' \
X		< prpath.pl | \
X	$(PERL) -e 'while(<>) { chop; s/\s*$$//; next if (/^# #/); if(/(^.*)(# #.*$$)/) { printf "$$1\n"; next; } print "$$_\n"; }' > $@
X	chmod 755 $@
X
Xinstall: $(OBJ) Makefile $(MAN) $(DEP)
X	sed -e 's:WHOISHOST:$(WHOISHOST):' \
X	    -e 's:XPORT:$(PORT):' $(MAN) > $(MAN).tmp
X	-install -m 755 $(OBJ) $(BINDIR)
X	-install -m 644 ${MAN}.tmp ${MANDIR}/man${MANEXT}/${MAN}
X	-rm $(MAN).tmp
X
X
Xdist.shar: $(DIST) 
X	$(SHAR) $(DIST)
X	
X
Xdist: dist.shar
X
Xall: prpath dist
X
Xman: $(MAN)
X	-install -m 644 ${MAN} ${MANDIR}/man${MANEXT}/${MAN}
X
Xclean:
X	-rm -f core a.out dist.shar *.o ,* $(OBJ)
X
X
END_OF_Makefile
if test 2385 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
