This is Info file pm.info, produced by Makeinfo version 1.68 from the
input file bigpm.texi.


File: pm.info,  Node: R3,  Next: R3/conn,  Prev: Quota,  Up: Module List

Perl object oriented client interface to SAP R/3 using RFCSDK
*************************************************************

NAME
====

   R3.pm - Perl object oriented client interface to SAP R/3 using RFCSDK

SYNOPSIS
========

     use R3;
     $conn = new R3::conn (host=>$host, sysnr=>$sysnr, client=>$client,
     user=>$usr, passwd=>$passwd);
     $itab = new R3::itab ($conn, $table_name);
     $func = new R3::func ($conn, $func_name);
     ...

DESCRIPTION
===========

   R3.pm provides an object oriented interface to SAP's RFCSDK for
connection to an R/3 system. R3::conn is the object interface to R/3
connections. R3::itab is the object interface to ABAP internal tables.
R3::func is the object interface to ABAP RFC enabled functions.

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3::conn(3), R3::func(3), R3::itab(3) and R3::rfcapi(3).


File: pm.info,  Node: R3/conn,  Next: R3/func,  Prev: R3,  Up: Module List

Perl extension for handling connection to a SAP R/3 system
**********************************************************

NAME
====

   R3::conn - Perl extension for handling connection to a SAP R/3 system

SYNOPSIS
========

     use R3::conn;

     $conn = new R3::conn (client=>"100", user=>"SAP*",
       password=>"pass", hostname=>"apollo", sysnr=>0);

     undef $conn;

DESCRIPTION
===========

   R3::conn::new creates a new connection to a R/3 system. It takes the
following named parameters:   client => R/3 client   user => user ID
password => user's password   passwd => alias for password   language =>
logon language, defaults to 'E'   lang => alias for language   hostname =>
application server's hosname   host => alias for hostname   systemnr =>
system number   sysnr => alias for systemnr   gwhost => gateway host,
defaults to host   gwservice => gateway service, defaults to service
"sapgw##" with ## = 'sysnr'   trace => rfc trace on if set to 1, defaults
to 0 (off)   pre4 => should be set to true value if target host has R/3
release < 40A

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::func(3), R3::itab(3) and R3::rfcapi(3).


File: pm.info,  Node: R3/func,  Next: R3/itab,  Prev: R3/conn,  Up: Module List

Perl extension for calling remote functions in a R/3 system
***********************************************************

NAME
====

   R3::func - Perl extension for calling remote functions in a R/3 system

SYNOPSIS
========

     use R3::func;
     $func = new R3::func ($conn, $func_name);
     call $func (\@export, \@tables, $field_1, $value_1, $field_2, $value_2,
     $field_3, $value_3, ... $field_n, $value_n);
     undef $func;

DESCRIPTION
===========

   R3::func::new enables a R/3 function to be called from perl. The
function interface is retrieved from the R/3 system. R3::func::new takes
two parameters, first parameter is a R3::conn, second is the name of the
ABAP function.

   R3::func::call calls the ABAP function specified in R3::func::new.
R3::func::call takes two or more parameters. First parameter is a reference
to an array of export variable and export value pairs. Second parameter is
a reference to an array of table name and table handle pairs. Third and
further parameters are import variable name and import variable pairs. Use
references to empty arrays, [], if there is no export variables and/or
tables in the function interface.

   Example:   ...    $func=new R3::func ($conn, "RFC_GET_TABLE_ENTRIES");
$itab=new R3::itab ($conn, "TAB512");   call $func ([TABLE_NAME=>'TVKO',
GEN_KEY=>'2'],     [ENTRIES=>$itab], NUMBER_OF_ENTRIES=>$e);   ...

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::conn(3), R3::itab(3) and R3::rfcapi(3).


File: pm.info,  Node: R3/itab,  Next: RADIUS/Dictionary,  Prev: R3/func,  Up: Module List

Perl extension for handling ABAP internal tables
************************************************

NAME
====

   R3::itab - Perl extension for handling ABAP internal tables

SYNOPSIS
========

     use R3::itab;
     $itab = new R3::itab ($conn, "MARA");

     $itab->get_records();
     %h = $itab->get_record($i);
     $itab->set_record($i, %h);
     $itab->ins_record($i, %h);
     $itab->add_record(%h);
     $itab->del_record($i);

     $itab->get_lines();
     $s = $itab->get_line($i);
     $itab->set_line($i, $s);
     $itab->ins_line($i, $s);
     $itab->add_line($s);
     $itab->del_line($i);

     $itab->trunc();

     %h = $itab->line2record($s);
     $s = $itab->record2line(%h);

DESCRIPTION
===========

   First record in a R3::itab is 1. This is the same as in ABAP.

   $itab->get_records() returns the number of records in $itab

   $itab->get_record($i) returns an array of field name, value pairs for
the $i:th record in $itab

   $itab->set_record($i, %h) replaces the values of the $i:th record in
$itab with the values in the field name, value pairs following the first
parameter

   $itab->ins_record($i, %h) inserts a record at the $i:th position in
$itab and sets the values to the value in the field name, value pairs
following the first parameter

   $itab->add_record(%h) appends a new record to the end of $itab and sets
the values to the value in the field name, value pairs in %h

   $itab->del_record($i) deletes the $i:th record from $itab

   $itab->get_lines() returns the number of records in $itab; should be the
same amount as $itab->get_records() returns

   $itab->get_line($i) returns an unpacked hex string with the values of
the $i:th record in $itab

   $itab->set_line($i, $s) replace the values of the $i:th record with the
content in the unpacked hex string in $s

   $itab->ins_line($i, $s) inserts a new record at the $i:th position in
$itab and sets the values to the content in the unpacked hex string $s

   $itab->add_line($s) adds a new record to the end of $itab and sets the
values to the content in the unpacked hex string $s

   $itab->del_line($i) deletes the $i:th record from $itab

   $itab->trunc() deletes all records from $itab

   $itab->line2record($s) returns the unpacked hex string as an array of
field name, value pairs

   $itab->record2line(%h) returns an unpacked hex string corresponding to
the array of field name, value pairs

AUTHOR
======

   Johan Schoen, johan.schon@capgemini.se

SEE ALSO
========

   perl(1), R3(3), R3::conn(3), R3::func(3) and R3::rfcapi(3).


File: pm.info,  Node: RADIUS/Dictionary,  Next: RADIUS/Packet,  Prev: R3/itab,  Up: Module List

RADIUS dictionary parser
************************

NAME
====

   RADIUS::Dictionary - RADIUS dictionary parser

SYNOPSIS
========

     use RADIUS::Dictionary;

     my $dict = new RADIUS::Dictionary "/etc/radius/dictionary";
     $dict->readdict("/some/other/file");
     my $num = $dict->attr_num('User-Name');
     my $name = $dict->attr_name(1);

DESCRIPTION
===========

   This is a simple module that reads a RADIUS dictionary file and parses
it, allowing conversion between dictionary names and numbers.

METHODS
-------

   new

   Returns a new instance of a RADIUS::Dictionary object.  If given an
(optional) filename, it calls *readdict* for you.

   ->*readdict*

   Parses a dictionary file and learns the name<->number mappings.

   ->*attr_num*($attrname)

   Returns the number of the named attribute.

   ->*attr_type*($attrname)

   Returns the type (string, integer, *ipaddr*, or time) of the named
attribute.

   ->*attr_name*($attrnum)

   Returns the name of the attribute with the given number.

   ->*attr_numtype*($attrnum)

   Returns the type of the attribute with the given number.

   ->*attr_has_val*($attrnum)

   Returns a true or false value, depending on whether or not the numbered
attribute has any known value constants.

   ->*val_has_name*($attrnum)

   Alternate (bad) name for *attr_has_val*.

   ->*val_num*($attrnum, $valname)

   Returns the number of the named value for the attribute number supplied.

   ->*val_name*

   Returns the name of the numbered value for the attribute number
supplied.

CAVEATS
=======

   This module is mostly for the internal use of RADIUS::Packet, and may
otherwise cause insanity and/or blindness if studied.

AUTHOR
======

   Christopher Masto, chris@netmonger.net

SEE ALSO
========

   RADIUS::Packet


File: pm.info,  Node: RADIUS/Packet,  Next: RADIUS/UserFile,  Prev: RADIUS/Dictionary,  Up: Module List

Object-oriented Perl interface to RADIUS packets
************************************************

NAME
====

   RADIUS::Packet - Object-oriented Perl interface to RADIUS packets

SYNOPSIS
========

     use RADIUS::Packet;
     use RADIUS::Dictionary;

     my $d = new RADIUS::Dictionary "/etc/radius/dictionary";

     my $p = new RADIUS::Packet $d, $data;
     $p->dump;

     if ($p->attr('User-Name' eq "lwall") {
       my $resp = new RADIUS::Packet $d;
       $resp->set_code('Access-Accept');
       $resp->set_identifier($p->identifier);
       $resp->set_authenticator($p->authenticator);
       $resp->set_attr('Reply-Message') = "Welcome, Larry!\r\n";
       my $respdat = auth_resp($resp->pack, "mysecret");
       ...

DESCRIPTION
===========

   RADIUS (RFC2138) specifies a binary packet format which contains
various values and attributes.  RADIUS::Packet provides an interface to
turn RADIUS packets into Perl data structures and vice-versa.

   RADIUS::Packet does not provide functions for obtaining RADIUS packets
from the network.  A simple network RADIUS server is provided as an
example at the end of this document.  Also, a RADIUS::Server module is
under development which will simplify the interface.

PACKAGE METHODS
---------------

new RADIUS::Packet $dictionary, $data
     Returns a new RADIUS::Packet object.  $dictionary is an optional
     reference to a RADIUS::Dictionary object.  If not supplied, you must
     call *set_dict*.  If $data is supplied, unpack will be called for you
     to initialize the object.

OBJECT METHODS
--------------

->*set_dict*($dictionary)
     RADIUS::Packet needs access to a RADIUS::Dictionary object to do
     packing and unpacking.  set_dict must be called with an appropriate
     dictionary reference (see *Note RADIUS/Dictionary:
     RADIUS/Dictionary,) before you can use ->pack or ->unpack.

->unpack($data)
     Given a raw RADIUS packet $data, unpacks its contents so that they
     can be retrieved with the other methods (code, attr, etc.).

->pack
     Returns a raw RADIUS packet suitable for sending to a RADIUS client
     or server.

->code
     Returns the Code field as a string.  As of this writing, the following
     codes are defined:

          Access-Request          Access-Accept
          Access-Reject           Accounting-Request
          Accounting-Response     Access-Challenge
          Status-Server           Status-Client

-><set_code>($code)
     Sets the Code field to the string supplied.

->identifier
     Returns the one-byte Identifier used to match requests with responses,
     as a character value.

->*set_identifier*
     Sets the Identifier byte to the character supplied.

->*authenticator*
     Returns the 16-byte Authenticator field as a character string.

->*set_authenticator*
     Sets the Authenticator field to the character string supplied.

->attr($name)
     Retrieves the value of the named Attribute.  Attributes will be
     converted automatically based on their dictionary type:

          STRING     Returned as a string.
          INTEGER    Returned as a Perl integer.
          IPADDR     Returned as a string (a.b.c.d)
          TIME       Returned as an integer

->*set_attr*($name, $val)
     Sets the named Attribute to the given value.  Values should be
     supplied as they would be returned from the attr method.

->password($secret)
     The RADIUS Password attribute is encoded with a shared secret.  Use
     this method to return the decoded version.

->dump
     Prints the packet's contents to STDOUT.

EXPORTED SUBROUTINES
--------------------

*auth_resp*($packed_packet, $secret)
     Given a (packed) RADIUS packet and a shared secret, returns a new
     packet with the Authenticator field changed in accordace with RADIUS
     protocol requirements.

NOTES
=====

   This document is (not yet) intended to be a complete description of how
to implement a RADIUS server.  Please see the RFCs (at
ftp://ftp.livingston.com/pub/radius/) for that.  The following is a brief
description of the procedure:

     1. Recieve a RADIUS request from the network.
     2. Unpack it using this package.
     3. Examine the attributes to determine the appropriate response.
     4. Construct a response packet using this package.
        Copy the Identifier and Authenticator fields from the request,
        set the Code as appropriate, and fill in whatever Attributes
        you wish to convey in to the server.
     5. Call the pack method and use the auth_resp function to
        authenticate it with your shared secret.
     6. Send the response back over the network.
     7. Lather, rinse, repeat.

EXAMPLE
=======

     #!/usr/local/bin/perl -w

     use RADIUS::Dictionary;
     use RADIUS::Packet;
     use Net::Inet;
     use Net::UDP;
     use Fcntl;
     use strict;

     # This is a VERY simple RADIUS authentication server which responds
     # to Access-Request packets with Access-Accept.  This allows anyone
     # to log in.

     my $secret = "mysecret";  # Shared secret on the term server

     # Parse the RADIUS dictionary file (must have dictionary in current dir)
     my $dict = new RADIUS::Dictionary "dictionary"
       or die "Couldn't read dictionary: $!";

     # Set up the network socket (must have radius in /etc/services)
     my $s = new Net::UDP { thisservice => "radius" } or die $!;
     $s->bind or die "Couldn't bind: $!";
     $s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
       or die "Couldn't make socket non-blocking: $!";

     # Loop forever, recieving packets and replying to them
     while (1) {
       my ($rec, $whence);
       # Wait for a packet
       my $nfound = $s->select(1, 0, 1, undef);
       if ($nfound > 0) {
     	# Get the data
     	$rec = $s->recv(undef, undef, $whence);
     	# Unpack it
     	my $p = new RADIUS::Packet $dict, $rec;
     	if ($p->code eq 'Access-Request') {
     	  # Print some details about the incoming request (try ->dump here)
     	  print $p->attr('User-Name'), " logging in with password ",
     		$p->password($secret), "\n";
     	  # Create a response packet
     	  my $rp = new RADIUS::Packet $dict;
     	  $rp->set_code('Access-Accept');
     	  $rp->set_identifier($p->identifier);
     	  $rp->set_authenticator($p->authenticator);
     	  # (No attributes are needed.. but you could set IP addr, etc. here)
     	  # Authenticate with the secret and send to the server.
     	  $s->sendto(auth_resp($rp->pack, $secret), $whence);
     	}
     	else {
     	  # It's not an Access-Request
     	  print "Unexpected packet type recieved.";
     	  $p->dump;
     	}
       }
     }

AUTHOR
======

   Christopher Masto, chris@netmonger.net

SEE ALSO
========

   RADIUS::Dictionary


File: pm.info,  Node: RADIUS/UserFile,  Next: RAS/AS5200,  Prev: RADIUS/Packet,  Up: Module List

Perl extension for manipulating a RADIUS users file.
****************************************************

NAME
====

   RADIUS::UserFile - Perl extension for manipulating a RADIUS users file.

SYNOPSIS
========

     use RADIUS::UserFile;

     my $users = new RADIUS::UserFile File => '/etc/raddb/users';
     $users->load('/usr/local/etc/radius/users');
     
     $users->add(Who        => 'joeuser',
                 Attributes => { key1 => 'val1', key2 => 'val2' },
                 Comment    => 'Created on '. scalar localtime);
     
     $users->update(File => '/etc/raddb/users',
                    Who => qw(joeuser janeuser));

     print $users->format('joeuser');

REQUIRES
========

   Perl5.004, Fcntl, File::Copy, Tie::IxHash

EXPORTS
=======

   Nothing

DESCRIPTION
===========

   This module provides methods for reading information from a RADIUS
users database.

PACKAGE METHODS
---------------

new RADIUS::UserFile
new RADIUS::UserFile(File => *$USERS_FILE*, Who => *$USER*)
new RADIUS::UserFile(File => *$USERS_FILE*, Who => *\@USERS*)
     Creates and returns a new `RADIUS::UserFile' object.

     File specifies the RADIUS users file to load (e.g.
     "/etc/raddb/users").  If no file is specified, one isn't loaded; in
     this case, the load() method can be used to retrieve any user data.
     If an error occurred while reading File, 0 is returned instead.

     Who limits the retrieval of user information to the list of users
     specified.  A single user can be named using a string, or a set of
     users can be passed as a reference to an array.  If Who is left
     undefined, all users will be loaded.

OBJECT METHODS
--------------

->add(Who => *$USER*, Attributes => *\%ATTRS*, Comment => *$TEXT*)
     Adds information about the named user.  This information will
     henceforth be available through users, attributes, comment, etc.  Any
     comments are automatically prefixed with "# ".  Attributes should be
     specified as a reference to a hash; each value should either be an
     array ref or a string.  On success, 1 is returned.  On error, 0 is
     returned and STDERR gets an appropriate message.

->attributes(*$USER*)
     Returns a list of defined attributes for the specified user.  If the
     user doesn't exist, undef is returned.

->comment(*$USER*)
     Returns a string representing the comments that would prefix the given
     user's entry in the users file.  If the user doesn't exist, undef is
     returned.

->dump(*$USER*)
     Prints out the attributes of the named user, in alphabetical order.
     $self is returned.

->files
     Returns a list of files from which we have read user attributes.  The
     list is sorted according to the order in which the files were read.
     If no files have yet been read successfully, an empty array is
     returned.

->format(*$USER*)
     Returns a string containing the attributes of the named user,
     prefixed by any comments, according to the format required for the
     RADIUS users file.  If the user doesn't exist, an empty string is
     returned.

->load(File => *$USERS_FILE*, Who => *$USER*)
->load(File => *$USERS_FILE*, Who => *\@USERS*)
     Loads the contents of the specified RADIUS users file.  The name of
     the file is stored in a first-in, last-out stack enumerating which
     "databases" have been loaded (see files()).  The `RADIUS::UserFile'
     object is returned.  The options are the same as described in new().
     If a user already exists and further info is read about that user
     from the specified file, the new information is just added to what is
     already known.  On success, 1 is returned; on failure, 0 is returned
     and an appropriate message is sent to STDERR.

->read_users(*$USERS_FILE*, *$USER*)
->read_users(*$USERS_FILE*, *\@USERS*)
     Reads in the contents of the specified RADIUS users file, and returns
     a pair of hashes:  one index by user name, with each element
     containing a hash of (attribute name => [ values ]) pairs; and
     another also indexed by user name, containing the comments that
     immediately preceded that user's file entry.  The options are the
     same as in new().  Each comment value is a string.  Each user
     attribute value is a ref to an array of strings.  This is mainly
     designed as a utility function to be used by new() and load(), and
     doesn't affect the calling object.  On failure, 0 is returned.

->remove(*$USER* ...)
     Deletes the specified users from the object.  The list of users
     successfully deleted is returned.

->removed()
     Returns a list of users that have been removed from the object.

->update(File => *$USERS_FILE*, Who => *\@USERS*)
     Updates user attributes in a RADIUS users file.  If the file is
     specified, its contents are updated; otherwise, the last file read is
     modified.  If a list of users is provided, only their entries are
     updated; otherwise, all known users are.  All users to be "updated"
     are printed using the results of format.  Other users are printed as
     found.  It should be noted that some extra newlines can be left in a
     file with this method:  if an empty line follows a given record that
     has been remove()d, then it will still be there in the file being
     updated.  On success, non-zero is returned.  On failure, 0 is
     returned and STDERR gets an appropriate message.

->user(*$USER*)
     Returns a ref to a hash representing the attributes of the named user.
     If the user doesn't exist, undef is returned.

->usernames
     Returns a ref to an anonymous array of strings representing the users
     about which we have attributes defined.  If no users are defined, a
     ref to an empty anonymous array is returned.

->users
     Returns a ref to a hash of user hashes, where each user hash is a set
     of (attribute name => value) pairs.  This is the actual data stored
     in the object, so use with caution.

->values(*$USER*, *$ATTRIBUTE*)
     Returns an array of strings representing the values for the named
     attribute of the given user.  If the user or attribute doesn't exist,
     undef is returned.

AUTHOR
======

   Copyright (c) 2000 O'Shaughnessy Evans <oevans@acm.org>.  All rights
reserved.  This version is distributed under the same terms as Perl itself
(i.e. it's free), so enjoy.

SEE ALSO
========

   *Note RADIUS/Packet: RADIUS/Packet,, *Note RADIUS/Dictionary:
RADIUS/Dictionary,, `Authen::Radius' in this node.


File: pm.info,  Node: RAS/AS5200,  Next: RAS/HiPerARC,  Prev: RADIUS/UserFile,  Up: Module List

PERL Interface to Cisco AS5200 Access Router
********************************************

NAME
====

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

   Version 1.04, June 9, 2000

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. Also, some programs
     based on the RAS:: series of modules will be made available on CPAN
     at the same place as this module.


DESCRIPTION
===========

   At this time, the following methods are implemented:

creating an object with new
     Use the new() method to create a new object.

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

     The following variables are useful:    hostname - The hostname of the
     router to connect to    login - The login name to get a command-line
     on the router    password - The password to the login name supplied
     enablepassword - The enable password to the router
     truncateusernames - See below    prompt - See below

     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 (except for the hostname, which is required), but your
     program will likely not get very far without at least a hostname and
     a correct password. Some older IOS versions such as Version 11.2(15a)
     only require a password and not a login name - if a login name is
     supplied, it is assumed that your router is not one of these and a
     full login-and-password script will be used; if a login name is not
     supplied, it is assumed that your router only requires a password to
     log in.

     The enablepassword is only required if you'll be using commands that
     require enable status on the router. This includes the userkill() and
     killexcessoutoctets() methods and would also include, for example,
     run_command('reload').

     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.

     Prompt handling has been vastly improved. If a prompt is not
     specified, a reasonable default is assumed that should work just
     fine. If you want to specify a prompt, supply a regular expression
     without delimiters or anchors that represents your router's prompt,
     e.g. prompt => 'as5200[>#]' If you get errors about a bad match
     operator or a bad delimiter, you likely specified anchros and/or
     delimiters.

printenv
     This is for debugging. It prints to STDERR 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, 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
     routine.

          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: 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";

userports
     This returns a hash with the key of each item being a username. The
     value of each item is an array of the ports that that username is
     currently using. This provides some information that a simple
     usergrep() lacks.

          Example:
             %userports = $foo->userports;
             foreach $user (keys(%userports)) {
               foreach $port (@{$userports{$user}}) {
                    print "User: $user is on $port\n";
                }
             }

killexcessoutoctets
     Takes a bytelimit as an argument and then checks each port's
     out-octets count. If the out octet count is higher than the
     bytelimit, the interface and its counters are reset. This is useful
     to stop RADIUS counters from wrapping, since a 32-bit signed integer
     wraps into negative at about 2 gig.

          Example:
             # kills users with outoctets of over about 2 gig
             $foo->killexcessoutoctets(2100000000);

EXAMPLE PROGRAMS
================

   These are some examples of how you could use this module. Full-fledged
applications based on the RAS:: family of modules will be made available
at CPAN at the same place as this module. Also, check out the test.pl file
included in this distribution for some sample code.

   ###

     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 supplied is a bit bare but is growing. If you
write a useful function, or if you need a specific function added, please
let me know and I'd be glad to check it out on an in-my-free-time basis.

   There are no known bugs. There are likely a lot of unexpected features,
though. If you find any, PLEASE let me know.

   This module has been tested with an AS5300 with some degree of success.
Last I heard, the userports() function didn't work properly on the AS5300.

CHANGES IN THIS VERSION
=======================

   1.04     Fixed some small typos.

   1.03     Added the userports() and killexcessoutoctets() methods. Added
better prompt support (YAY!). Made error messages more useful. Made the
module work with or without a login prompt, as older IOS (11.2
specifically) doesn't require a login name, only a password.

   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.

AUTHORS, MAINTAINERS, AND CONTACT INFO
======================================

   RAS::AS5200 uses the Net::Telnet module by Jay Rogers <jay@rgrs.com> -
thank you, Jay!

   Gregor Mosheh <stigmata@blackangel.net> wrote RAS::AS5200 and left some
significant problems in it, especially the prompt handling.

   Luke Robins <luker@vicnet.net.au> worked on the prompt handling and
apprised me that later IOSes need different login/password procedures, and
he also wrote the userports() and killexcessoutoctets() methods.

   Todd Caine <todd_caine@eli.net> helped out substantially with the
prompt handling, as well.

   Thank you very much, Luke and Robin, for fixing the most annoying bugs
in RAS::AS5200!

   The maintainer of RAS::AS5200 is Gregor Mosheh, at the address above.

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.


File: pm.info,  Node: RAS/HiPerARC,  Next: RAS/PortMaster,  Prev: RAS/AS5200,  Up: Module List

PERL Interface to 3Com/USR Total Control HiPerARC
*************************************************

NAME
====

   RAS::HiPerARC.pm - PERL Interface to 3Com/USR Total Control HiPerARC

   Version 1.03, June 9, 2000

SYNOPSIS
========

   *RAS::HiPerARC* is a PERL 5 module for interfacing with a 3Com/USR
Total Control HiPerARC remote access server. Using this module, one can
very easily construct programs to find a particular user in a bank of
ARCs, disconnect users, get usage statistics, or execute arbitrary
commands on a ARC.

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 && make test"

  2. If the tests worked all right, "make install"

  3. Check out the examples in this documentation.


DESCRIPTION
===========

   At this time, the following methods are implemented:

creating an object with new
     Use the new() method to create a new object.

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

     The following variables are useful:    hostname - The hostname of the
     router to connect to    login - The login name to get a command-line
     on the router    password - The password to the login name supplied
     prompt - See below

     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 (except for the hostname, which is required), but your
     program will likely not get very far without at least a hostname and
     a correct password.

     Prompt handling has been vastly improved. If a prompt is not
     specified, a reasonable default is assumed that should work just
     fine. If you want to specify a prompt, supply a regular expression
     without delimiters or anchors that represents your router's prompt,
     e.g. prompt => 'hiper>' If you get errors about a bad match operator
     or a bad delimiter, you likely have a bad prompt string.

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 ARC, executes the
     commands, 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.

          Example:
             # Execute a command and print the output
             $command = 'list conn';
             ($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('list interface','list con');
             print "Modems:\n@$output[0]\n\n";;
             print "Current connections:\n@$output[1]\n\n";;

usergrep
     Supply a username as an argument, and usergrep will return an array
     of ports on which that user was found (or an empty array, if they're
     not found). If no username is supplied, returns undefined.
     Internally, this does a run_command('list connections') and parses
     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 array if they weren't found. An undef is
     returned if no username was 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";

userports
     This returns a hash with the key of each item being a username. The
     value of each item is an array of the ports that that username is
     currently using. This provides some information that a simple
     usergrep() lacks.

          Example:
             %userports = $foo->userports;
             foreach $user (keys(%userports)) {
               foreach $port (@{$userports{$user}}) {
                    print "User: $user is on $port\n";
                }
             }

EXAMPLE PROGRAMS
================

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

   use RAS::HiPerARC; $used = $total = 0; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       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::HiPerARC; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       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::HiPerARC; foreach
('arc1.example.com','arc2.example.com','arc3.example.com') {    $foo = new
RAS::HiPerARC(       hostname => $_,       login => '!root',
password => 'mysecret'    );

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

CHANGES IN THIS VERSION
=======================

   1.03     Added userports() method. Added better prompt support (YAY!).
Made error messages more useful.

   1.02     Fixed portusage() to only count Up interfaces. The ARC
remembers modems even when they've been removed, and this accounts for
that oddity. Cleaned up the code substantially. Fixed the prompt-matching
code so that a prompt mismatch will cause run_command() to return instead
of hanging in a loop.

   1.01     Added a test suite. Corrected some errors in the
documentation. Improved error handling a bit.

AUTHORS, MAINTAINERS, AND CONTACT INFO
======================================

   RAS::HiPerARC uses the Net::Telnet module by Jay Rogers <jay@rgrs.com>
- thank you, Jay!

   Gregor Mosheh <stigmata@blackangel.net> wrote RAS::HiPerARC originally,
but the prompt handling needed some help in case people cuztomized their
prompts.

   Luke Robins <luker@vicnet.net.au> and Todd Caine <todd_caine@eli.net>
helped out substantially with the prompt handling with RAS::AS5200 and the
changes were carried over into RAS::HiPerARC. Thank you, Luke and Todd!

   The maintainer of RAS::HiPerARC is Gregor Mosheh, at the address above.

BUGS
====

   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.

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.


File: pm.info,  Node: RAS/PortMaster,  Next: RCGI,  Prev: RAS/HiPerARC,  Up: Module List

PERL Interface to Livingston PortMaster 2
*****************************************

NAME
====

   RAS::PortMaster.pm - PERL Interface to Livingston PortMaster 2

   Version 1.15, January 17, 2000

   Gregor Mosheh (stigmata@blackangel.net)

SYNOPSIS
========

   *RAS::PortMaster* is a PERL 5 module for interfacing with a Livingston
PortMaster remote access server. Using this module, one can very easily
construct programs to find a particular user in a bank of PMs, disconnect
users, get usage statistics, or execute arbitrary commands on a PM.

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 && make test"

  2. If the tests went well, do a "make install"

  3. Check out the EXAMPLES section of this document for examples on how
     you'd want to use this module.


DESCRIPTION
===========

   At this time, the following methods are implemented:

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

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

     Since there's no sense in dynamically changing the hostname,
     password, etc. no methods are supplied for modifying them and they
     must be supplied statically to the constructor. No error will be
     generated if anything is left out, though it's likely that your
     program won't get far without supplying a proper hostname and
     password...

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 PortMaster,
     executes the commands, 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.

          Example:
             # Execute a command and print the output
             $command = 'sho ses';
             ($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('reset S15','sho ses');
             print @$output[1] ;

usergrep
     Supply a username as an argument, and usergrep will return an array
     of ports on which that user was found (or an empty array if they
     weren't found). A undefined value is returned if no username was
     supplied. Internally, this does a run_command("sho ses") and parses
     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 array if they weren't found). An undefined
     value is returned if no username was supplied.

     Because the PortMaster shows even ports that are not in use and shows
     the username as '-', you can userkill a username of "-" to reset all
     idle modems.

          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 parts: The 1st element is the
     number of ports. The rest is a list of users who are currently online.

          Examples:
             @people = $foo->portusage;
             print "There are ", shift(@people), " 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 - Summarizes port usage on a bank of PMs

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

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

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

   #####

   usergrep.pl - Locate a user on a bank of PMs

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

   use RAS::PortMaster;

   foreach ('pm1.example.com','pm2.example.com','pm3.example.com') {
$foo = new RAS::PortMaster(       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 PMs

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

   use RAS::PortMaster;

   foreach ('pm1.example.com','pm2.example.com','pm3.example.com') {
$foo = new RAS::PortMaster(       hostname => $_,       login => '!root',
    password => 'mysecret'    );

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

CHANGES IN THIS VERSION
=======================

   1.15     Cleaned up the code significantly. Fixed the prompt code to
avoid infinite loops in the case of a prompt mismatch - it now times out
appropriately.

   1.14     Fixed a leak in run_command. I swear I test this stuff before
I upload it, really!

   1.13     Added a test suite. Fixed some documentation errors. Added
some error handling.

   1.12     Bug fixes. Optimized userkill() for better performance.

   1.11     The package name got mangled when I zipped everything up, and
was thus useless. This has been fixed. Sorry. Also moved the example
programs into this document for easy availability. Also fixed an
intermittent problem with PERL not liking my use of shift() on a routine
call.

   1.00     First release, November 1999.

BUGS
====

   The set of supplied functions is a bit 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 /^\w+\>\s+/) then you could get "pattern match
timeout" errors. If this happens, you may be using the wrong RAS module to
connect the the router (e.g. don't use RAS::PortMaster to connect to a
Cisco AS5200). Otherwise, 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.

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.


