I've been running it once per minute lately, and it seems to be working fine;
no problems with system or network load.
See http://prime-mover.cc.waikato.ac.nz/Bastard.html if you don't get name.
#!/usr/local/bin/perl5
#
# bofh.pl - version 1.0 Copyright 1998 Stefan Hudson <hudson@mbay.net>
# Distribution permitted in unmodified form only.
#
# Run from a crontab with somethine like this:
# 0,5,10,15,20,25,30,35,40,45,50,55 * * * * (/usr/local/sbin/bofh.pl)>/dev/null 2>/dev/null
#
# Bugs/missing features:
# - No facility for excepting special users (staff or full time accounts)
# - In rare cases, MP users will get kicked if the second channel is just coming
# up and still has a 0.0.0.0 IP address.
$PMCOM='/usr/local/sbin/pmcom'; # Location of the "pmcom" command.
$BUSY = 360; # Number of ports that must be used before we start kicking people off
$IDLE = 570; # Idle timer in seconds (9.5 minutes) (when we are over $BUSY)
$LIMIT = 28800; # Session timer in seconds (8 hours) (all the time)
# Specify terminal servers to monitor here.
@SERVERS=("pm1.foo.net", "pm2.foo.net", "pm3.foo.net");
$COMMUNITY="public"; # SNMP read community for portmasters
$LOGSERV = 'local5|info'; # syslog service for logging. I use the same one the PMs use.
# You shouldn't need to modify anything below here...
use SNMP 1.6;
use Sys::Syslog;
$Sys::Syslog::host = "localhost";
foreach $pm (@SERVERS) {
$session = new SNMP::Session ( DestHost => $pm, Community => $COMMUNITY );
next if(!$session);
$pm = $session->{DestAddr}; # make sure host is dotted decimal ip addr
$pinfo = new SNMP::VarList (
['livingstonSerialUser', 1], # 0
['livingstonSerialPortName', 1], # 1
['livingstonSerialStarted', 1], # 2
['livingstonSerialIdle', 1], # 3
['livingstonSerialIpAddress', 1], # 4
);
@ret = $session->get($pinfo);
while(@ret) {
# print join(" ", @ret), "\n";
@ret = $session->getnext($pinfo);
next if(!$ret[0]);
last if($pinfo->[0][$SNMP::Varbind::tag_f] ne 'livingstonSerialUser');
next if ($ret[0] eq 'PPP');
$ret[0]=~ s/(.ppp|.slip|.cslip)//;
$port[0] = $pm;
$port[1] = $ret[1]; # port name
$port[2] = $ret[0]; # username
$port[3] = join('.', unpack("C4", $ret[4])); # address
$port[4] = int($ret[2]/100); # uptime
$port[5] = int($ret[3]/100); # busy
# print("$port[3]\n");
push(@ports, [@port]);
push(@{$users{$port[2]}}, [@port]);
}
}
foreach(@ports) { # Check idle/session timeouts
if(($#ports > $BUSY && ($_->[5] > $IDLE)) || $ports{$_}[4] > $LIMIT) {
# print("$_->[1] $_->[2] $_->[3] $_->[4] $_->[5]\n");
&killport(@$_);
}
}
foreach $user (sort(keys(%users))) { # Check for multiple connections
if($#{@users{$user}}) { # More than one port in use
# print("$user $users{$user}[0]->[3] $port->[3]\n");
foreach $port (@{$users{$user}}) { # Check each port user is on
if($port->[3] ne $users{$user}[0]->[3]) {
printf("%s duplicate $user ($users{$user}[0]->[3] $port->[3])\n", scalar(localtime()));
syslog($LOGSERV, "portcheck: duplicate $user ($users{$user}[0]->[3] $port->[3])\n");
foreach $port (@{$users{$user}}) {&killport(@{$port})};
last;
}
}
}
}
#print("$_ $#{@users{$_}} $users{$_}[0]->[3] $users{$_}[1]->[3]\n");
sub killport {
local(@port)=@_;
printf("%s terminating %s %s (up %s idle %s)\n", scalar(localtime()), $port[2], $port[3], timestr($port[4]), timestr($port[5]));
syslog($LOGSERV, "portcheck: terminating %s %s (up %s idle %s)\n", $port[2], $port[3], timestr($port[4]), timestr($port[5]));
system($PMCOM, $port[0], "reset $port[1]");
}
sub timestr {
local($ttime) = @_;
$str=sprintf("%02d:%02d:%02d", int(($ttime%86400)/3600), int(($ttime%3600)/60), $ttime%60);
$str=sprintf("%d $str", int($ttime/86400)) if($ttime>86400);
return($str);
}
-- /// Stefan Hudson <hudson@mbay.net> __ /// Senior Network Administrator - Monterey Bay Internet \\\/// http://www.mbay.net/ - Email: info@mbay.net \XX/ Voice: 408-642-6100 Fax: 408-642-6101 Modem: 408-642-6102 - To unsubscribe, email 'majordomo@livingston.com' with 'unsubscribe portmaster-users' in the body of the message.