From: ivan Date: Tue, 7 Nov 2000 15:00:37 +0000 (+0000) Subject: session monitor X-Git-Tag: freeside_1_3_0~69 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=7f07089722bfcabe3bf42619bb2bdb81fd8d44e1 session monitor --- diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index b0bfb0b3c..59472c898 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -731,10 +731,10 @@ Check/untaint ip addresses. IPv4 only for now. sub ut_ip { my( $self, $field ) = @_; - $self->getfield($field) =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/; + $self->getfield($field) =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ or return "Illegal (IP address) $field: ". $self->getfield($field); - for ( $1 $2 $3 $4 ) { return "Illegal (IP address) $field" if $_ > 255; }; - $self->$setfield($field, "$1.$2.$3.$3"); + for ( $1, $2, $3, $4 ) { return "Illegal (IP address) $field" if $_ > 255; } + $self->setfield($field, "$1.$2.$3.$3"); ''; } @@ -895,7 +895,7 @@ sub hfields { =head1 VERSION -$Id: Record.pm,v 1.8 2000-10-27 20:15:50 ivan Exp $ +$Id: Record.pm,v 1.9 2000-11-07 15:00:37 ivan Exp $ =head1 BUGS diff --git a/FS/FS/nas.pm b/FS/FS/nas.pm index 5ed95f92e..873c9bce6 100644 --- a/FS/FS/nas.pm +++ b/FS/FS/nas.pm @@ -117,11 +117,21 @@ sub check { || $self->ut_numbern('last'); } +=sub heartbeat TIMESTAMP + +Updates the timestamp for this nas + +=cut + +sub heartbeat { + warn "warning: heartbeat unimplemented!" +} + =back =head1 VERSION -$Id: nas.pm,v 1.1 2000-10-27 20:18:32 ivan Exp $ +$Id: nas.pm,v 1.2 2000-11-07 15:00:37 ivan Exp $ =head1 BUGS diff --git a/FS/FS/session.pm b/FS/FS/session.pm index 0d766bd22..b85a5822f 100644 --- a/FS/FS/session.pm +++ b/FS/FS/session.pm @@ -4,6 +4,8 @@ use strict; use vars qw( @ISA ); use FS::Record qw( qsearchs ); use FS::svc_acct; +use FS::port; +use FS::nas; @ISA = qw(FS::Record); @@ -31,6 +33,8 @@ FS::session - Object methods for session records $error = $record->check; + $error = $record->nas_heartbeat($timestamp); + =head1 DESCRIPTION An FS::session object represents an user login session. FS::session inherits @@ -57,7 +61,7 @@ from FS::Record. The following fields are currently supported: =item new HASHREF -Creates a new example. To add the example to the database, see L<"insert">. +Creates a new session. To add the session to the database, see L<"insert">. Note that this stores the hash reference, not a distinct copy of the hash it points to. You can ask the object for a copy with the I method. @@ -95,6 +99,8 @@ sub insert { $error = $self->SUPER::insert; return $error if $error; + $self->nas_heartbeat($self->getfield('login')); + #session-starting callback! ''; @@ -136,6 +142,8 @@ sub replace { $error = $self->SUPER::replace; return $error if $error; + $self->nas_heartbeat($self->getfield('logout')); + #session-ending callback! ''; @@ -143,7 +151,7 @@ sub replace { =item check -Checks all fields to make sure this is a valid example. If there is +Checks all fields to make sure this is a valid session. If there is an error, returns the error, otherwise returns false. Called by the insert and replace methods. @@ -167,11 +175,24 @@ sub check { ''; } +=item nas_heartbeat + +Heartbeats the nas associated with this session (see L). + +=cut + +sub nas_heartbeat { + my $self = shift; + my $port = qsearchs('port',{'portnum'=>$self->portnum}); + my $nas = qsearchs('nas',{'nasnum'=>$port->nasnum}); + $nas->heartbeat(shift); +} + =back =head1 VERSION -$Id: session.pm,v 1.1 2000-10-27 20:18:32 ivan Exp $ +$Id: session.pm,v 1.2 2000-11-07 15:00:37 ivan Exp $ =head1 BUGS diff --git a/FS/MANIFEST b/FS/MANIFEST index e0b5b51e5..91d2e2fc0 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -40,12 +40,16 @@ FS/svc_acct_pop.pm FS/svc_acct_sm.pm FS/svc_domain.pm FS/type_pkgs.pm +FS/nas.pm +FS/port.pm +FS/session.pm MANIFEST MANIFEST.SKIP Makefile.PL test.pl README bin/freeside-bill +bin/freeside-print-batch FS/domain_record.pm FS/prepay_credit.pm FS/svc_www.pm diff --git a/bin/fs-setup b/bin/fs-setup index b0f47610f..602dc7274 100755 --- a/bin/fs-setup +++ b/bin/fs-setup @@ -1,6 +1,6 @@ #!/usr/bin/perl -Tw # -# $Id: fs-setup,v 1.28 2000-10-30 10:47:26 ivan Exp $ +# $Id: fs-setup,v 1.29 2000-11-07 15:00:37 ivan Exp $ # # ivan@sisd.com 97-nov-8,9 # @@ -32,7 +32,10 @@ # fix radius attributes ivan@sisd.com 98-sep-27 # # $Log: fs-setup,v $ -# Revision 1.28 2000-10-30 10:47:26 ivan +# Revision 1.29 2000-11-07 15:00:37 ivan +# session monitor +# +# Revision 1.28 2000/10/30 10:47:26 ivan # nas.last can't be defined NULL if indexed # # Revision 1.26 2000/07/06 08:57:27 ivan @@ -751,9 +754,7 @@ sub tables_hash_hack { 'nas', 'varchar', '', $char_d, 'nasip', 'varchar', '', 15, 'nasfqdn', 'varchar', '', $char_d, -# 'last', 'timestamp', '', '', -#change to above when move to DBIx::DBSchema!!! - 'last', 'datetime', '', '', + 'last', @date_type, ], 'primary_key' => 'nasnum', 'unique' => [ [ 'nas' ], [ 'nasip' ] ], @@ -765,11 +766,8 @@ sub tables_hash_hack { 'sessionnum', 'int', '', '', 'portnum', 'int', '', '', 'svcnum', 'int', '', '', -# 'login', 'timestamp', '', '', -# 'logout', 'timestamp', '', '', -#change to above when move to DBIx::DBSchema!!! - 'login', 'datetime', '', '', - 'logout', 'datetime', NULL, '', + 'login', @date_type, + 'logout', @date_type, ], 'primary_key' => 'sessionnum', 'unique' => [], diff --git a/fs_sesmon/FS-SessionClient/MANIFEST b/fs_sesmon/FS-SessionClient/MANIFEST index 3ced1df17..6da7b22e9 100644 --- a/fs_sesmon/FS-SessionClient/MANIFEST +++ b/fs_sesmon/FS-SessionClient/MANIFEST @@ -7,3 +7,5 @@ test.pl fs_sessiond cgi/logon.cgi cgi/logoff.cgi +bin/freeside-login +bin/freeside-logoff diff --git a/fs_sesmon/FS-SessionClient/Makefile.PL b/fs_sesmon/FS-SessionClient/Makefile.PL index 8dff176a7..1f598474a 100644 --- a/fs_sesmon/FS-SessionClient/Makefile.PL +++ b/fs_sesmon/FS-SessionClient/Makefile.PL @@ -4,7 +4,7 @@ use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'FS::SessionClient', 'VERSION_FROM' => 'SessionClient.pm', # finds $VERSION - 'EXE_FILES' => [ 'fs_sessiond' ], + 'EXE_FILES' => [ qw(fs_sessiond freeside-login freeside-logoff) ], 'INSTALLSCRIPT' => '/usr/local/sbin', 'PERM_RWX' => '750', ); diff --git a/fs_sesmon/FS-SessionClient/SessionClient.pm b/fs_sesmon/FS-SessionClient/SessionClient.pm index fd50e8908..97332cb26 100644 --- a/fs_sesmon/FS-SessionClient/SessionClient.pm +++ b/fs_sesmon/FS-SessionClient/SessionClient.pm @@ -1,7 +1,7 @@ package FS::SessionClient; use strict; -use vars qw($VERSION @ISA @EXPORT_OK $fs_sessiond_socket); +use vars qw($AUTOLOAD $VERSION @ISA @EXPORT_OK $fs_sessiond_socket); use Exporter; use Socket; use FileHandle; @@ -10,7 +10,7 @@ use IO::Handle; $VERSION = '0.01'; @ISA = qw( Exporter ); -@EXPORT_OK = qw( login logoff ); +@EXPORT_OK = qw( login logoff portnum ); $fs_sessiond_socket = "/usr/local/freeside/fs_sessiond_socket"; @@ -104,7 +104,7 @@ sub AUTOLOAD { =head1 VERSION -$Id: SessionClient.pm,v 1.1 2000-10-27 20:15:50 ivan Exp $ +$Id: SessionClient.pm,v 1.2 2000-11-07 15:00:37 ivan Exp $ =head1 BUGS diff --git a/fs_sesmon/FS-SessionClient/bin/freeside-login b/fs_sesmon/FS-SessionClient/bin/freeside-login new file mode 100644 index 000000000..6ca4455f8 --- /dev/null +++ b/fs_sesmon/FS-SessionClient/bin/freeside-login @@ -0,0 +1,36 @@ +#!/usr/bin/perl -Tw + +#false-laziness hack w freeside-logoff + +use strict; +use FS::SessionClient qw( login portnum ); + +my $username = shift; + +my $portnum; +if ( scalar(@ARGV) == 1 ) { + my $arg = shift; + if ( $arg =~ /^(\d+)$/ ) { + $portnum = $1; + } elsif ( $arg =~ /^([\d\.]+)$/ ) { + $portnum = portnum( { 'ip' => $1 } ) or die "unknown ip!" + } else { + &usage; + } +} elsif ( scalar(@ARGV) == 2 ) { + $portnum = portnum( { 'nasnum' => shift, 'nasport' => shift } ) + or die "unknown nasnum/nasport"; +} else { + &usage; +} + +my $error = login ( { + 'username' => $username, + 'portnum' => $portnum, +} ); + +warn $error if $error; + +sub usage { + die "Usage:\n\n freeside-login username ( portnum | ip | nasnum nasport )"; +} diff --git a/fs_sesmon/FS-SessionClient/bin/freeside-logoff b/fs_sesmon/FS-SessionClient/bin/freeside-logoff new file mode 100644 index 000000000..f7b876b33 --- /dev/null +++ b/fs_sesmon/FS-SessionClient/bin/freeside-logoff @@ -0,0 +1,37 @@ +#!/usr/bin/perl -Tw + +#false-laziness hack w freeside-login + +use strict; +use FS::SessionClient qw( logoff portnum ); + +my $username = shift; + +my $portnum; +if ( scalar(@ARGV) == 1 ) { + my $arg = shift; + if ( $arg =~ /^(\d+)$/ ) { + $portnum = $1; + } elsif ( $arg =~ /^([\d\.]+)$/ ) { + $portnum = portnum( { 'ip' => $1 } ) or die "unknown ip!" + } else { + &usage; + } +} elsif ( scalar(@ARGV) == 2 ) { + $portnum = portnum( { 'nasnum' => shift, 'nasport' => shift } ) + or die "unknown nasnum/nasport"; +} else { + &usage; +} + +my $error = login ( { + 'username' => $username, + 'portnum' => $portnum, +} ); + +warn $error if $error; + +sub usage { + die "Usage:\n\n freeside-logoff username ( portnum | ip | nasnum nasport )"; +} + diff --git a/fs_sesmon/fs_session_server b/fs_sesmon/fs_session_server index be0a01710..46e53d118 100644 --- a/fs_sesmon/fs_session_server +++ b/fs_sesmon/fs_session_server @@ -12,6 +12,8 @@ use FS::Record qw( qsearch qsearchs ); #use FS::cust_main_county; #use FS::cust_main; use FS::session; +use FS::port; +use FS::svc_acct; #require "configfile"; $Debug = 1; @@ -42,12 +44,70 @@ while (1) { } if ( $command eq 'login' ) { - + $error = &login(\%hash); + print $writer "$error\n"; } elsif ( $command eq 'logoff' ) { - + $error = &logoff(\%hash); + print $writer "$error\n"; } elsif ( $command eq 'portnum' ) { - + if ( exists $hash{'ip'} ) { + $hash{'ip'} =~ /^([\d\.]+)$/ or $1='nomatch'; + $port = qsearchs('port', { 'ip' => $1 } ); + } else { + $hash{'nasnum'} =~ /^(\d+)$/ and my $nasnum = $1; + $hash{'nasport'} =~ /^(\d+)$/ and my $nasport = $1; + $port = qsearchs('port', { 'nasnum'=>$nasnum, 'nasport'=>$nasport } ); + } + print $writer ( $port ? $port->portnum : '' ), "\n"; } else { warn "$me WARNING: unrecognized command"; } + } + #won't ever reach without code above to throw out of loop, but... + close $writer; + close $reader; + warn "connection to $machine lost!\n" + sleep 5; + warn "reconnecting...\n"; +} + +sub login { + my $href = shift; + $href->{'username'} =~ /^([a-z0-9_\-\.]+)$/ or return "Illegal username"; + my $username = $1; + $svc_acct = qsearchs('svc_acct', { 'username' => $username } ) + or return "Unknown user"; + return "Incorrect password" + if defined($href->{'password'}) + && $href->{'password'} ne $svc_acct->_password; + my $session = new FS::session { + 'portnum' => $href->{'portnum'}, + 'svcnum' => $svc_acct->svcnum, + 'login' => $href->{'login'}, + }; + $session->insert; +} + +sub logout { + my $href = shift; + $href->{'username'} =~ /^([a-z0-9_\-\.]+)$/ or return "Illegal username"; + my $username = $1; + $svc_acct = qsearchs('svc_acct', { 'username' => $username } ) + or return "Unknown user"; + return "Incorrect password" + if defined($href->{'password'}) + && $href->{'password'} ne $svc_acct->_password; + my $session = qsearchs FS::session { + 'portnum' => $href->{'portnum'}, + 'svcnum' => $svc_acct->svcnum, + 'logoff' => '', + }; + return "No currently open sessios found for that user/port!" unless $session; + my $nsession = new FS::session ( { $old->hash } ); + $nsession->replace($session); +} + +sub usage { + die "Usage:\n\n fs_session_server user machine\n"; +} diff --git a/htdocs/docs/index.html b/htdocs/docs/index.html index f4155c1b8..f5c43d02c 100644 --- a/htdocs/docs/index.html +++ b/htdocs/docs/index.html @@ -20,6 +20,7 @@
  • File exporting and remote setup
  • fs_passwd
  • Signup server +
  • Session monitor
  • Billing
  • Troubleshooting
  • Schema reference diff --git a/htdocs/docs/schema.html b/htdocs/docs/schema.html index 1ab0e7f62..474a3501a 100644 --- a/htdocs/docs/schema.html +++ b/htdocs/docs/schema.html @@ -143,6 +143,14 @@
  • pkgnum - package
  • svcpart - Service definition +
  • nas - Network Access Server (terminal server) +
      +
    • nasnum - primary key +
    • nas - NAS name +
    • nasip - NAS ip address +
    • nasfqdn - NAS fully-qualified domain name +
    • last - timestamp indicating the last instant the NAS was in a known state (used by the session monitoring). +
  • part_pkg - Package definitions
    • pkgpart - primary key @@ -176,12 +184,28 @@
    • svcpart - Service definition
    • quantity - quantity of this service that this package includes
    +
  • port - individual port on a nas +
      +
    • portnum - primary key +
    • ip - IP address of this port +
    • nasport - port number on the NAS +
    • nasnum - NAS +
  • prepay_credit
    • prepaynum - primary key
    • identifier - text or numeric string used to receive this credit
    • amount - amount of credit
    +
  • session +
      +
    • sessionnum - primary key +
    • portnum - Port +
    • svcnum - Account +
    • login - timestamp indicating the beginning of this user session. +
    • logout - timestamp indicating the end of this user session. May be null, which indicates a currently open session. +
    +
  • svc_acct - Accounts