Hello.
I've found that checkrad script is using SNMP_Session perl module that doesn't works correctly, so I would like to post little patch for checkrad script to support Simultaneous-Use check with l2tp LNS/NAS. You have to install Net::SNMP perl module to get this thing working.
--- /usr/ports/net/freeradius/work/freeradius-1.0.2/src/main/checkrad.pl Thu Mar 17 06:00:31 2005 +++ checkrad Fri Mar 18 16:50:06 2005 @@ -28,7 +28,7 @@ # netserver_telnet 1.0 Author: [EMAIL PROTECTED] # versanet_snmp 1.0 Author: [EMAIL PROTECTED] # bay_finger 1.0 Author: [EMAIL PROTECTED] -# cisco_l2tp 1.14 Author: [EMAIL PROTECTED] +# cisco_l2tp 0.1 Author: Volodya Vaynshteyn <[EMAIL PROTECTED]> # mikrotik_telnet 1.1 Author: Evren Yurtesen <[EMAIL PROTECTED]> # mikrotik_snmp 1.0 Author: Evren Yurtesen <[EMAIL PROTECTED]> # redback_telnet Author: Eduardo Roldan @@ -43,6 +43,7 @@ # $naspass is the location of your NAS admin password file # + $prefix = "/usr/local"; $localstatedir = "/var"; $logdir = "/var/log"; @@ -50,7 +51,7 @@ $raddbdir = "${sysconfdir}/raddb"; $debug = ""; -#$debug = "$logdir/checkrad.log"; +$debug = "$logdir/checkrad.log"; $snmpget = "/usr/local/bin/snmpget"; $snmpwalk = "/usr/local/bin/snmpwalk"; @@ -76,6 +77,7 @@ # Do not complain if we cannot find it. # Prefer a locally installed copy. # + BEGIN { unshift @INC, "/usr/local/lib/site_perl"; @@ -1114,47 +1116,89 @@ # Make sure you set the $realm variable at the begining of the file if # needed. The new type for naslist is cisco_l2tp -sub find_l2tp_login -{ - my($host, $community, $port_num) = @_; - my $l2tp_oid = '.1.3.6.1.4.1.9.10.24.1.3.2.1.2.2'; - my $port_oid = '.iso.org.dod.internet.private.enterprises.9.10.51.1.2.1.1.2.2'; - my $port = 'Vi' . $port_num; - - my $sess = new SNMP::Session(DestHost => $host, Community => $community); - my $snmp_var = new SNMP::Varbind(["$port_oid"]); - my $val = $sess->getnext($snmp_var); - - do - { - $sess->getnext($snmp_var); - } until ($snmp_var->[$SNMP::Varbind::val_f] =~ /$port/) || - (!($snmp_var->[$SNMP::Varbind::ref_f] =~ /^$port_oid\.(\d+)\.(\d+)$/)) || - ($sess->{ErrorNum}); - - my $val1 = $snmp_var->[$SNMP::Varbind::ref_f]; - - if ($val1 =~ /^$port_oid/) { - $result = substr($val1, length($port_oid)); - $result =~ /^\.(\d+)\.(\d+)$/; - $tunID = $1; - $sessID = $2; - } - - my $snmp_var1 = new SNMP::Varbind(["$l2tp_oid\.$tunID\.$sessID"]); - $val = $sess->get($snmp_var1); - my $login = $snmp_var1->[$SNMP::Varbind::val_f]; - - return $login; -} - -sub cisco_l2tp_snmp -{ - my $login = find_l2tp_login("$ARGV[1]", $cmmty_string, "$ARGV[2]"); - print LOG " user at port S$ARGV[2]: $login\n" if ($debug); - ($login eq "[EMAIL PROTECTED]") ? 1 : 0; + +sub +cisco_l2tp_snmp { + +use Net::SNMP qw(oid_lex_sort oid_base_match SNMP_VERSION_1 DEBUG_ALL); + + my ($nas_ip,$user) = @_; + my ($method, $community) = naspasswd($nas_ip, 1); + + if ($method eq '') { + $community = $cmmty_string; + } elsif ($method ne 'SNMP') { + print LOG "Error: Need SNMP community string for $nas_ip\n" if ($debug); + return 2; } +my ($s, $e) = Net::SNMP->session( + -hostname => $nas_ip, + -community => $community, + -version => "2c", +); + + if (!defined($s)) { + print LOG $e if ($debug); + return 255; + } else { + + use vars qw( %t_logname %t_port ); + + ## check cvpdnSessionAttrUserName + %t_logname = &get_table_as_hash($s,'.1.3.6.1.4.1.9.10.24.1.3.2.1.2.2.'); + %t_port = &get_table_as_hash($s,'.1.3.6.1.4.1.9.10.51.1.2.1.1.2.2.'); + + foreach $port_table_id (keys(%t_port)) { + if ($t_logname{$port_table_id} eq $user){ + print LOG "User $t_logname{$port_table_id} already logged in at port $t_port{$port_table_id}\n" if ($debug); + return 1; + } + } + print LOG "User $user successfully logged in at port $t_port{$port_table_id}\n" if ($debug); + return 0; + $s->close(); + } + +} + +sub +get_table_as_hash() { + + use vars qw( $num $val $oid %buf ); + my ($s,$oid) = @_; + + my @args = ( + -varbindlist => [$oid], + -maxrepetitions => 25, + ); + + outer: while (defined($s->get_bulk_request(@args))) { + my @oids = oid_lex_sort(keys(%{$s->var_bind_list})); + foreach (@oids) { + if (!oid_base_match($oid, $_)) { + last outer; + } + $num = $_; + $num =~ s/$oid//; + $val = $s->var_bind_list->{$_}; + $buf{$num} = $val; + #printf("%s => %s\n", $num, $val); + if ($s->var_bind_list->{$_} eq 'endOfMibView') { + last outer; + } + } + # Get the last OBJECT IDENTIFIER in the returned list + @args = (-maxrepetitions => 25, -varbindlist => [pop(@oids)]); + } + # Let the user know about any errors + if ($s->error() ne '') { + print $s->error(); + } + return %buf; +} + + sub mikrotik_snmp { # Set SNMP version @@ -1411,7 +1455,7 @@ } elsif ($ARGV[0] eq 'bay') { $ret = &bay_finger; } elsif ($ARGV[0] eq 'cisco_l2tp'){ - $ret = &cisco_l2tp_snmp; + $ret = &cisco_l2tp_snmp($ARGV[1],$ARGV[3]); } elsif ($ARGV[0] eq 'mikrotik'){ $ret = &mikrotik_telnet; } elsif ($ARGV[0] eq 'mikrotik_snmp'){