File Coverage

blib/lib/RAS/HiPerARC.pm
Criterion Covered Total %
statement 9 106 8.4
branch 0 30 0.0
condition 0 6 0.0
subroutine 3 10 30.0
pod 7 7 100.0
total 19 159 11.9


line stmt bran cond sub pod time code
1             ## RAS::HiPerARC.pm
2             ### PERL module for accessing a 3Com/USR Total Control HiPerARC
3             #########################################################
4              
5             package RAS::HiPerARC;
6             $VERSION = "1.03";
7              
8 1     1   680 use strict "subs"; use strict "refs";
  1     1   2  
  1         31  
  1         4  
  1         1  
  1         21  
9              
10             # This uses Net::Telnet to connect to the RAS
11 1     1   2351 use Net::Telnet ;
  1         59859  
  1         1437  
12              
13             # The name $ras will be used consistently as the
14             # reference to the RAS::HiPerARC object we're handling
15              
16             # The constructor method, of course
17             sub new {
18 0     0 1   my($class) = shift ;
19 0           my($ras) = {} ;
20 0           %$ras = @_ ;
21              
22 0 0 0       unless ($ras->{hostname}) { warn "ERROR: ", (ref($class) || $class), " - Hostname not specified.\n"; return(); }
  0            
  0            
23 0           $ras->{'VERSION'} = $VERSION;
24 0 0         $ras->{prompt} = 'HiPer>> ' unless $ras->{prompt};
25              
26 0   0       bless($ras, ref($class) || $class);
27             }
28              
29              
30             # for debugging - printenv() prints to STDERR
31             # the entire contents of %$ras
32             sub printenv {
33 0     0 1   my($ras) = shift;
34 0           while (($key,$value) = each(%$ras)) { warn "$key = $value\n"; }
  0            
35             }
36              
37              
38             # This runs the specified commands on the router and returns
39             # a list of refs to arrays containing the commands' output
40             sub run_command {
41 0     0 1   my($ras) = shift;
42 0           my(@returnlist);
43 0           my($prompt) = '/' . $ras->{prompt} . '$/';
44              
45 0           while ($command = shift) {
46 0           my($session) = new Net::Telnet;
47 0           $session->errmode("return");
48 0           $session->open($ras->{hostname});
49 0 0         if ($session->errmsg) {
50 0           warn "ERROR: ",ref($ras)," - Cannot connect to host $ras->{hostname} - ",$session->errmsg,"\n"; return(); }
  0            
51 0           $session->login($ras->{login},$ras->{password});
52 0 0         if ($session->errmsg) {
53 0           warn "ERROR: ",ref($ras)," - Logging in to host $ras->{hostname} - ",$session->errmsg,"\n"; return(); }
  0            
54 0           $session->print("\n"); $session->waitfor($prompt);
  0            
55 0 0         if ($session->errmsg) {
56 0           warn "ERROR: ",ref($ras)," - Waiting for command prompt on host $ras->{hostname} - ",$session->errmsg,"\n"; return(); }
  0            
57 0           $session->print($command);
58 0           my(@output);
59              
60 0           while (1) {
61 0           $session->print(""); my($line) = $session->getline ;
  0            
62 0 0         if ($session->errmsg) {
63 0           warn "ERROR: ",ref($ras)," - Waiting on output from command \"$command\" on host $ras->{hostname} - ",$session->errmsg,"\n"; return(); }
  0            
64 0 0         if ($line =~ /^$ras->{prompt}$/) { $session->print('quit'); $session->close; last; }
  0            
  0            
  0            
65              
66             # After the 1st More prompt, the ARC sends
67             # ^M\s{a whole line's worth}^M to clear each line for printing
68 0           $line =~ s/^--More--\s+\015?\s*\015?//;
69             # Trim off trailing whitespace
70 0           $line =~ s/\s*$/\n/;
71              
72 0           push(@output, $line);
73             }
74              
75 0           shift(@output); # Trim the echoed command
76 0           push(@returnlist, \@output);
77             } # end of shifting commands
78              
79             # We're returning a list of references to lists.
80             # Each ref points to an array containing the returned text
81             # from the command, and the list of refs corresponds
82             # to the list of commands we were given
83 0           return(@returnlist);
84             } # end of run_command
85              
86              
87             # usergrep() - takes a username and returns an array of
88             # ports on which the user was found
89             sub usergrep {
90 0     0 1   my($ras) = shift;
91 0 0         my($username) = shift; return() unless $username;
  0            
92 0           my($output) = $ras->run_command('list connections');
93 0           my(@ports);
94              
95 0           foreach (@$output) {
96 0           my($port,$user);
97 0 0         next unless /^slot:\d+\/mod:\d+\s+/;
98 0           $port = unpack("x0 a15", $_) ; $port =~ s/^\s*(\S+)\s*$/$1/;
  0            
99 0           $user = unpack("x15 a20", $_); $user =~ s/^\s*(\S+)\s*$/$1/;
  0            
100 0 0         ($user eq $username) && push(@ports,$port);
101             }
102 0           return(@ports);
103             }
104              
105              
106             # userports() returns a hash of arrays
107             # keys are the usernames of all users currently connected
108             # values are arrays of ports that that user in connected on
109             sub userports {
110 0     0 1   my($ras) = shift;
111 0           my($output) = $ras->run_command('list conn');
112 0           my(%userports);
113              
114 0           foreach (@$output) {
115 0           my($port,$user);
116 0 0         next unless /^slot:\d+\/mod:\d+\s+/;
117 0           $port = unpack("x0 a15", $_) ; $port =~ s/^\s*(\S+)\s*$/$1/;
  0            
118 0           $user = unpack("x15 a20", $_); $user =~ s/^\s*(\S+)\s*$/$1/;
  0            
119 0           push(@{$userports{$user}},$port);
  0            
120             }
121 0           return(%userports);
122             }
123              
124              
125             # portusage() returns a list: # of ports, list of users
126             sub portusage {
127 0     0 1   my($ras) = shift;
128 0           my($interfaces,$connections) = $ras->run_command('list interfaces','list connections');
129 0           my(@users);
130              
131 0           @$interfaces = grep(/^slot:\d+\/mod:\d+\s+Up\s+Up\s*$/, @$interfaces);
132              
133 0           foreach (@$connections) {
134 0           my($port,$user);
135 0 0         next unless /^slot:\d+\/mod:\d+\s+/;
136 0           $user = unpack("x15 a20", $_); $user =~ s/^\s*(\S+)\s*$/$1/;
  0            
137 0 0         next if ($user =~ /^\s*$/);
138 0           push(@users,$user);
139             }
140              
141 0           return(scalar(@$interfaces),@users);
142             }
143              
144              
145             # This does a usergrep() and then disconnects the specified user
146             sub userkill {
147 0     0 1   my($ras) = shift;
148 0 0         my($username); $username = shift; return() unless $username;
  0            
  0            
149 0           my(@ports) = $ras->usergrep($username);
150 0 0         return('') unless @ports;
151              
152 0           my($resetcmd) = "reset modems " . join(',',@ports);
153 0           $ras->run_command($resetcmd);
154 0           return(@ports);
155             }
156              
157              
158             #############################################################
159             1;#So PERL knows we're cool
160             __END__;