The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

RAS::AS5200.pm - PERL Interface to Cisco AS5200 Access Router

Version 1.02, January 17, 2000

Gregor Mosheh (stigmata@blackangel.net)

SYNOPSIS

RAS::AS5200 is a PERL 5 module for interfacing with a Cisco AS5200 access router. Using this module, one can very easily construct programs to find a particular user in a bank of AS5200s, disconnect users, get usage statistics, or execute arbitrary commands on a AS5200.

PREREQUISITES AND INSTALLATION

This module uses Jay Rogers' Net::Telnet module. If you don't have Net::Telnet, get it from CPAN or this module won't do much for you.

Installation is easy, thanks to MakeMaker:

  1. "perl Makefile.PL && make"

  2. "make test" to run the test suite. Check the test output. It should seem correct. If there are errors, check the hostname and passwords and try again.

  3. If all is good, do a "make install"

  4. Check out the examples in this documentation.

DESCRIPTION

At this time, the following methods are implemented:

creating an object with new

Call the new method while supplying the "hostname", "login", "password", and "enablepassword" values, and you'll get an object reference returned.

   Example:
      use RAS::AS5200;
      $foo = new RAS::AS5200(
         hostname => 'dialup1.example.com',
         login => '!root',
         password => 'mysecret',
         truncateusernames => 'true'
      );

At this time, the enablepassword is only required for the userkill() method, and doesn't need to be defined if you don't intend to use userkill().

Since there's no point in dynamically changing the hostname, login, etc. these settings are static and must be supplied to the constructor. No error will be returned if these settings are not specified, but your program will likely not get very far without at least a hostname, and a correct password tends to help, too. ;)

If the "truncateusernames" option is set to non-null, then usernames supplied to user-seeking functions such as userkill() and usergrep() will be internally truncated to 10 characters. This is to work around a "feature" of the AS5200 that only the first 10 characters of a login name are displayed, which would cause usergrep('johnjjschmidt') to never work, as the AS5200 displays the login name as 'johnjjschm'. See the TRUNCATING USER NAMES section for more discussion on this.

printenv

This is for debugging only. It prints to STDOUT a list of its configuration hash, e.g. the hostname, login, and password. The printenv method does not return a value.

   Example:
      $foo->printenv;
run_command

This takes a list of commands to be executed on the AS5200, executes the commands on the AS5200, and returns a list of references to arrays containg the text of each command's output.

Repeat: It doesn't return an array, it returns an array of references to arrays. Each array contains the text output of each command. Think of it as an array-enhanced version of PERL's `backtick` operator.

Some router functions (e.g. rebooting) ask for confirmation - confirmation will be automatically supplied by the module's interface routines.

   Example:
      # Execute a command and print the output
      $command = 'show modems';
      ($x) = $foo->run_command($command);
      print "Output of command \'$command\':\n", @$x ;

   Example:
      # Execute a string of commands
      # and show the output from one of them
      (@output) = $foo->run_command('show isdn status','show modems');
      print "Modems:\n@$output[0]\n\n";;
      print "Current connections:\n@$output[1]\n\n";;

In Cisco-land, some functions are only available in enabled mode. To specify that a command should be run in enabled mode, prefix the command with "ENABLE " - that's all caps and a single space between the ENABLE and the rest of the command.

   Example:
      # Reboot the router
      $foo->run_command('ENABLE reload');
usergrep

Supply a username as an argument, and usergrep will return an array of ports on which that user was found (thus, an empty list if they weren't found). An undefined value is returned if no username was supplied. Internally, this does a run_command('show users') and processes the output.

   Example:
      @ports = $foo->usergrep('gregor');
      print "User gregor was found on ports @ports\n";
userkill

This does a usergrep, but with a twist: it disconnects the user by resetting the modem on which they're connected. Like usergrep, it returns an array of ports to which the user was connected before they were reset (or an empty list if they weren't found). The undefined value is returned if no username is supplied.

   Examples:
      @foo = $foo->userkill('gregor');
      print "Gregor was on ports @foo - HA HA!\n" if @ports ;

      @duh = $foo->userkill('-');
      print "There were ", scalar(@duh), " ports open.\n";
portusage

This returns an array consisting of 2 items: The 1st element is the number of ports. The rest is a list of users who are currently online.

   Examples:
      ($ports,@people) = $foo->portusage;
      print "There are $ports total ports.\n";
      print "There are ", scalar(@people), "people online.\n";
      print "They are: @people\n";

      ($ports,@people) = $foo->portusage;
      print "Ports free: ", $ports - scalar(@people), "\n";
      print "Ports used: ", scalar(@people), "\n";
      print "Ports total: ", $ports, "\n";

EXAMPLE PROGRAMS

   portusage.pl - Prints a summary of port usage on a bank of modems

   use RAS::AS5200;
   $used = $total = 0;
   foreach ('dialup1.example.com','dialup2.example.com') {
   $foo = new RAS::AS5200(
      hostname => $_,
      login => '!root',
      password => 'mysecret'
   );

   local($ports,@ports) = $foo->portusage;
   $total += $ports;
   $used += scalar(@ports);
}

print "$used out of $total ports are in use.\n";

###

   usergrep.pl - Finds a user on a bank of modems

   ($username) = @ARGV;
   die "Usage: $0 <username>\nFinds the specified user.\n" unless $username ;

   use RAS::AS5200;
   foreach ('dialup1.example.com','dialup2.example.com') {
   $foo = new RAS::AS5200(
      hostname => $_,
      login => '!root',
      password => 'mysecret'
   );

   @ports = $foo->usergrep($username);
   (@ports) && print "Found user $username on $_ ports @ports\n";
}

###

   userkill.pl - Kick a user off a bank of modems. Makes a great cron job. ;)

   ($username) = @ARGV;
   die "Usage: $0 <username>\nDisconnects the specified user.\n" unless $username ;

   use RAS::AS5200;
   foreach ('dialup1.example.com','dialup2.example.com') {
   $foo = new RAS::AS5200(
      hostname => $_,
      login => '!root',
      password => 'mysecret'
   );

   @ports = $foo->userkill($username);
   (@ports) && print "$_ : Killed ports @ports\n";
}

TRUNCATING USER NAMES

A "feature" of the Cisco AS5200 is that only the first 10 characters of login names are displayed. As such, doing a usergrep('johnjjschmidt') would never find the fellow, as the AS5200 truncates the username to 'johnjjschm'.

To work around this, you may set the "truncateusernames" flag in your constructor (see above). This will cause user-matching functions such as usergrep and userkill to internally truncate usernames to 10 characters for matching purposes. This means that usergrep('johnjjschmidt') would internally be treated as usergrep('johnjjschm') so that it would match.

So, you have your choice of two evils. If you don't enable username truncation, you'll miss users with login names over 10 characters in length. If you enable it, you could accidentally userkill user 'johnjjschm' when you meant to kill 'johnjjschmidt'. Sorry - Cisco screwed up and we get to suffer for it.

BUGS

The set of functions is somewhat bare. Since we use this for port usage monitoring, new functions will be added slowly on an as-needed basis. If you need some specific functionality let me know and I'll see what I can do. If you write an addition for this, please send it in and I'll incororate it and give credit.

I make some assumptions about router prompts based on what I have on hand for experimentation. If I make an assumption that doesn't apply to you (e.g. all prompts are /^as5200[#>]\s+$/) then you'll get "pattern match timed out" errors. Check the regexps in the loop within run_command, and make sure your prompt fits this regex. If not, either fix the regex and/or (even better) PLEASE send me some details on your prompt and what commands you used to set your prompt so I can experiment with it. A similar situation can occur if you use the wrong RAS module to connect to a router - a Livingston PortMaster, for example, has a different prompt than a AS5200 - if you accidentally point to a PortMaster using RAS::AS5200, you'll get pattern match timeouts.

CHANGES IN THIS VERSION

1.02 Cleaned up the code substantially. Fixed a "bug" that truncated usernames at 8 characters. Added the "truncateusernames" option. Tested the userkill() function on ISDN clients - works.

1.01 Improved the error handling a tad. Touched up the docs.

1.00 First released version of RAS::AS5200.

LICENSE AND WARRANTY

Where would we be if Larry Wall were tight-fisted with PERL itself? For God's sake, it's PERL code. It's free!

This software is hereby released into the Public Domain, where it may be freely distributed, modified, plagiarized, used, abused, and deleted without regard for the original author.

Bug reports and feature requests will be handled ASAP, but without guarantee. The warranty is the same as for most freeware: It Works For Me, Your Mileage May Vary.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 291:

You forgot a '=back' before '=head1'