Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Howto display multiple pages in telnet?

Status
Not open for further replies.

BSOD2600

Technical User
May 26, 2003
9
US
I've got a ZyXEL P334W router and am trying to write a Perl telnet script to retrieve some information. The problem I'm running into is that when I issue the ip nat iface enif1 st command, the router displays it in several pages. It wants a space or Enter press to display the other pages. Since the script doesn't do this (I can't figure out how), this hangs up the script, which then terminates the telnet connection and leaves the router hung until its rebooted.

1) How can I make the router display all pages at once with a single command?

2) If #1 isn't possible, how to I get the Perl Net::Telnet library to properly send/receive the several pages of data the router sends back? I've already tried playing around with the prompt setting, but can't get it to work.

Anyone have an idea?
 
1. First question might be answered in any cisco forum.

2. Have a look at Perl Module "IPC::Open2" it allows you to control process.

You can check as well use perl "Expect"module.

Cheers

dmazzini
GSM System and Telecomm Consultant

 
I would go with the 'Expect' option, either perl's version or use the TCL implementation for the OS you're running on (there is ActiveState's ActiveTcl for windows.)

I had to do a similar operation in the past; I used expect to log in, run a command, and hit enter a few times until the command prompt showed up again.

Dump all the output to a text file and you can use perl to grab the info you need.
 
1) There is already a telnet library specifically for Cisco: It seems when cisco has multiple pages, it displays some text like -more-, which of course can be easily matched. My router displays no prompts.

2) I'm not sure how the Open2 module would allow me to do what I need with the Perl Net::Telnet module.
 
Hi man
You can use the module Net-Telnet-Cisco, it does what you are looking for.
Not tested


[Autopage => $boolean,] # 1 or 0

Code:
use Net::Telnet::Cisco;
  my $session = Net::Telnet::Cisco->new(Host => '123.123.123.123');

  $session->login('login', 'password');

  $session->autopage(0);  # try it 

  # Execute a command
  my @output = $session->cmd('show version');
  print @output;
  # Enable mode
  if ($session->enable("enable_password") ) {
      @output = $session->cmd('show privilege');
      print "My privileges: @output\n";
  } else {
      warn "Can't enable: " . $session->errmsg;
  }
  $session->close;




dmazzini
GSM System and Telecomm Consultant

 
Thanks for the idea dmazzini, but the autopage command by default matches '/(?m:\s*--More--)/' (via more_prompt). My router doesn't show anything when it wants user input.

I've tried setting the prompt to just \n, but it didn't work.
 
Ok. Unfortunetaly I don't have any router to test...

Hi

I have two ideas. Please test it since I don't have routers to test it and let us know

Solution 1:

Code:
#Using a router function (terminal length 0).  # Turn off paging Send it after login

  use Net::Telnet::Cisco;
  my $session = Net::Telnet::Cisco->new(Host => '123.123.123.123');

  $session->login('login', 'password');

  $my @cmd_output = $session->cmd( 'terminal length 0' );

  # Execute a command
  my @output = $session->cmd('show version');
  print @output;
  # Enable mode
  if ($session->enable("enable_password") ) {
      @output = $session->cmd('show privilege');
      print "My privileges: @output\n";
  } else {
      warn "Can't enable: " . $session->errmsg;
  }
  $session->close;
  


Description: 

length  Your desired number of lines on the screen. 

The remote access server uses this value to determine when to pause during multiple-screen output.
The default length is 24 lines. A value of zero prevents the server from pausing between screens of output. 
When the output exceeds the screen length, it scrolls past.


Solution 2:

Code:
 use Net::Telnet::Cisco;
  my $session = Net::Telnet::Cisco->new(Host => '123.123.123.123');

  $session->login('login', 'password');

  $session->autopage();   
  my @out = $session->cmd('show ver');    
  autopage() if ( $out[-1] !~ /--More--/ );
  autopage() if ($session->last_prompt !~ /--More--/);  

  # Execute a command
  my @output = $session->cmd('show version');
  print @output;
  # Enable mode
  if ($session->enable("enable_password") ) {
      @output = $session->cmd('show privilege');
      print "My privileges: @output\n";
  } else {
      warn "Can't enable: " . $session->errmsg;
  }
  $session->close;

Cheers



dmazzini
GSM System and Telecomm Consultant

 
Thanks for the ideas dmazzini. Unfortunately, my ZyXEL router does not have a terminal length command nor splits pages up with --More--.

This is what I see when I issue the command thats multiple pages:
Code:
P334W> ip nat iface enif1 st
Iface enif1 Internet Network Address Translation:
    Table Size: 2048  Timeout: 180 sec  Timer period: 1 sec
    Starting External Port: 10000
    NAT Table - addr: x804e7b00 table: x8069fa00
    Outgoing: Total 13188013, TCP 12938370, UDP 248693, ICMP 950, Unroutable 0
    Incoming: Total 12335535, TCP 12217164, UDP 117383, ICMP 988, Unroutable 1
    Table: Allocated 281371, Freed 281266, Full 0, Expired 275059, Cache hit 8%
Slot Prot   Internal-IP  :Port    Outgoing-IP  :Port    External-IP  :Port  Idle
================================================================================
   0 TCP  192.168.2.108  :3100  68.118.69.211  :14112 83.251.14.140  :1410  0
   5 UDP  192.168.2.108  :1227  68.118.69.211  :13588 212.149.208.178:12652 31
   6 UDP  192.168.2.108  :1227  68.118.69.211  :14019 86.131.152.60  :3921  112
   8 UDP  192.168.2.115  :4910  68.118.69.211  :14051 192.168.100.1  :161   81
  16 UDP  192.168.2.108  :1227  68.118.69.211  :14002 87.78.0.100    :1423  163
  18 UDP  192.168.2.108  :1227  68.118.69.211  :14022 82.182.134.170 :30001 100

I've already tried modifying the telnet->prompt to look for a return, but it didn't work. I enabled the telnet output log and can see the first page DOES get returned, like I want. The problem is since the telnet->cmd times out (because it never gets the prompt it wants), it closes the connection. I don't really want the other pages of info either. I've noticed that the scalar variable I wanted the page of info stored, ends up containing nothing. How do I get around that?
 
Hi

I don't know anything about this ZyXEL router and their cmds. I will recommend you to read router manuals and find the equivalent command to:

Code:
$my @cmd_output = $session->cmd( 'terminal length 0' );

It should be the easy solution.

What about put this question in router forum?

Cheers




dmazzini
GSM System and Telecomm Consultant

 
Here is the entire listing of the routers commands.

If you think the router forum would have people that know how to deal with this ZyXEL issue, that'd be great. I've already posted this question on the dslreports.com ZyZEL and programming forum, but never got anyone that knew anything.
 
Alright, I'm so close to getting this finished now. I've tweaked the errmode setting so it doesn't close the connection and hang the router.

Only problem is that my @nat scalar never contains any data. Why?

Code:
# ----------------------------------------------------------------------------
#   File:       zyxel_stats.pl
#   Author:     BSOD2600 
#   Version:    1.0
#
#   Purpose:    Script used to fetch Firewall, NAT table statistics and CPU
#               usage from a ZyXEL router via Telnet and feed it to Cacti.
#	
#	Usage:	zyxel_stats.pl IP port password
#
#	Info:	This has been tested on WinXP/Win2003 with Perl 5.8.8.  
#
#	History:
#		06-10-2006 1.0	Initial release
#

#my $cli_prompt = "/P443W>/i";

#-------- Don't edit below --------------------------------------------------
use strict;

if ($#ARGV != 2) {
	print("\nUsage: zyxel_nat_stats.pl IP port password\n\n");
        exit(-1);
}

my ($i, $ip, $pw, $port, $t, @nat, @cpu, @firewall,
    $cpu_avg, $tablesize, $allocated, $freed, $full, $expired, $cachehit,
    $icmpidle, $udpidle, $tcpidle, $tcpsynidle, $tcpfinidle, $land, $ipspoof,
    $icmpecho, $icmp, $netbios, $trace, $teardrop, $synflood, $smtp);

$ip = $ARGV[0];
$port = $ARGV[1];
$pw = $ARGV[2];

use Net::Telnet;
$t = new Net::Telnet(
        Dump_log => "dump.txt",        
	Output_log => "output.txt",
	Input_log => "input.txt");

$t->errmode(sub
        {
		if ($t->timed_out) {
			warn "$ip busy: ", $t->errmsg, "\n";
		}
		elsif ($t->eof) {
			warn "$ip offline: ", $t->errmsg, "\n";
		}
		else {
			warn $t->errmsg, "\n";
			$t->print('\r\n');
			$t->errmode('return');
		}
       }
); 

#----- Connecting to router ---------------------------------------------------#
$t->open(Host => $ip,
        Port => $port);

$t->waitfor('/password: $/i');
$t->print($pw);

$t->waitfor('/Number:/i');
$t->print('24');
$t->waitfor('/Number:/i');
$t->print('8');
$t->waitfor('/P334W>/i');
$t->prompt('/P334W>/i');
$t->buffer_empty;

#----- Collect CPU Stats ------------------------------------------------------#
@cpu = $t->cmd(String => "sys cpu disp");
#print @cpu;

for ($i = 0; $i < @cpu; $i++) {
    if ($cpu[$i] =~ /\s+\d+\s\d+\s+(\d+.\d+)\s+\d+\s+\d+\s+(\d+.\d+)\s+\d+\s+\d+\s+(\d+.\d+)\s+\d+\s+\d+\s+(\d+.\d+)/i){
        $cpu_avg += $1 + $2 + $3 + $4;        
    }
}

$cpu_avg = sprintf("%.3f",$cpu_avg/60);

#----- Collect Firewall Stats -------------------------------------------------#
$t->buffer_empty;
@firewall = $t->cmd(String => "sys firewall cnt disp");
#print @firewall;

for ($i = 0; $i < @firewall; $i++) {
    if ($firewall[$i] =~ /ICMP\sIdle\sTimeout:\s(\d+)\s+UDP\sIdle\sTimeout:\s(\d+)/i){
        $icmpidle = $1;
        $udpidle = $2;
    }
    
    if ($firewall[$i] =~ /TCP\sIdle\sTimeout:\s(\d+)\s+TCP\sSYN\sIdle\sTimeout:\s(\d+)/i) {
        $tcpidle = $1;
        $tcpsynidle = $2;
    }
    
    if ($firewall[$i] =~ /TCP\sFIN\sIdle\sTimeout:\s(\d+)/i) {
        $tcpfinidle = $1;
    }
    
    if ($firewall[$i] =~ /Land\sAttack:\s(\d+)\s+IP\sSpoof\sAttack:\s(\d+)/i) {
        $land = $1;
        $ipspoof = $2;
    }
    
    if ($firewall[$i] =~ /ICMP\sEcho\sAttack:\s(\d+)\s+ICMP\sAttack:\s(\d+)/i) {
        $icmpecho = $1;
        $icmp = $2;
    }
    
    if ($firewall[$i] =~ /Netbios\sAttack:\s(\d+)\s+Trace\sRoute\sAttack:\s(\d+)/i) {
        $netbios = $1;
        $trace = $2;
    }
    
    if ($firewall[$i] =~ /Tear\sDrop\sAttack:\s(\d+)\s+Syn\sFlood\sAttack:\s(\d+)/i) {
        $teardrop= $1;
        $synflood = $2;
    }
    if ($firewall[$i] =~ /SMTP\sAttack:\s(\d+)/i) {
        $smtp = $1;
    }
}

#----- Collect NAT Stats ------------------------------------------------------#
$t->buffer_empty;

@nat = $t->cmd(String => "ip nat iface enif1 st",
               Prompt => '/\n*\s*/');
print @nat;
#$t->print('ip nat iface enif1 st'); 'trying stuff
#$t->prompt('/\n*\s*/i');  'trying stuff
#@nat = $t->getlines();  'trying stuff

for ($i = 0; $i < @nat; $i++) {
    if ($nat[$i] =~ /\s*\w*\s\w*:\s(\d+)\s*\w*:\s*\w*\s\w*\s*\w*\s\w*:\s\w*\s\w*\s*/i){
        $tablesize = $1;
    }
    
    if ($nat[$i] =~ /\s*\w*:\s\w*\s(\d+),\s\w*\s(\d+),\s\w*\s(\d+),\s\w*\s(\d+),\s\w*\s\w*\s(\d+)%/i) {
        $allocated = $1;
        $freed = $2;
        $full = $3;
        $expired = $4;
        $cachehit = $5;    
    }
}

sleep(1.5);
$t->print('\r\n');
$t->prompt('/P334W>/i');
print @nat;
$t->print('exit');
$t->waitfor('/Number:/i');
$t->print('99');

print "Tablesize:$tablesize Allocated:$allocated Freed:$freed Full:$full Expired:$expired Cachehit:$cachehit cpu:$cpu_avg ICMPIdle:$icmpidle UDPIdle:$udpidle TCPIdle:$tcpidle TCPSYNIdle:$tcpsynidle TCPFINIdle:$tcpfinidle LandAttack:$land IPSpoof:$ipspoof ICMPEchoAttack:$icmpecho ICMPAttack:$icmp NetBIOSAttack:$netbios TraceRouteAttack:$trace TearDropAttack:$teardrop SynFloodAttack:$synflood SMTPAttack:$smtp";

exit;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top