session monitor
authorivan <ivan>
Tue, 7 Nov 2000 15:00:37 +0000 (15:00 +0000)
committerivan <ivan>
Tue, 7 Nov 2000 15:00:37 +0000 (15:00 +0000)
13 files changed:
FS/FS/Record.pm
FS/FS/nas.pm
FS/FS/session.pm
FS/MANIFEST
bin/fs-setup
fs_sesmon/FS-SessionClient/MANIFEST
fs_sesmon/FS-SessionClient/Makefile.PL
fs_sesmon/FS-SessionClient/SessionClient.pm
fs_sesmon/FS-SessionClient/bin/freeside-login [new file with mode: 0644]
fs_sesmon/FS-SessionClient/bin/freeside-logoff [new file with mode: 0644]
fs_sesmon/fs_session_server
htdocs/docs/index.html
htdocs/docs/schema.html

index b0bfb0b..59472c8 100644 (file)
@@ -731,10 +731,10 @@ Check/untaint ip addresses.  IPv4 only for now.
 
 sub ut_ip {
   my( $self, $field ) = @_;
 
 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);
     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
 
 
 =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
 
 
 =head1 BUGS
 
index 5ed95f9..873c9bc 100644 (file)
@@ -117,11 +117,21 @@ sub check {
     || $self->ut_numbern('last');
 }
 
     || $self->ut_numbern('last');
 }
 
+=sub heartbeat TIMESTAMP
+
+Updates the timestamp for this nas
+
+=cut
+
+sub heartbeat {
+  warn "warning: heartbeat unimplemented!"
+}
+
 =back
 
 =head1 VERSION
 
 =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
 
 
 =head1 BUGS
 
index 0d766bd..b85a582 100644 (file)
@@ -4,6 +4,8 @@ use strict;
 use vars qw( @ISA );
 use FS::Record qw( qsearchs );
 use FS::svc_acct;
 use vars qw( @ISA );
 use FS::Record qw( qsearchs );
 use FS::svc_acct;
+use FS::port;
+use FS::nas;
 
 @ISA = qw(FS::Record);
 
 
 @ISA = qw(FS::Record);
 
@@ -31,6 +33,8 @@ FS::session - Object methods for session records
 
   $error = $record->check;
 
 
   $error = $record->check;
 
+  $error = $record->nas_heartbeat($timestamp);
+
 =head1 DESCRIPTION
 
 An FS::session object represents an user login session.  FS::session inherits
 =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
 
 
 =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<hash> method.
 
 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<hash> method.
@@ -95,6 +99,8 @@ sub insert {
   $error = $self->SUPER::insert;
   return $error if $error;
 
   $error = $self->SUPER::insert;
   return $error if $error;
 
+  $self->nas_heartbeat($self->getfield('login'));
+
   #session-starting callback!
 
   '';
   #session-starting callback!
 
   '';
@@ -136,6 +142,8 @@ sub replace {
   $error = $self->SUPER::replace;
   return $error if $error;
 
   $error = $self->SUPER::replace;
   return $error if $error;
 
+  $self->nas_heartbeat($self->getfield('logout'));
+
   #session-ending callback!
 
   '';
   #session-ending callback!
 
   '';
@@ -143,7 +151,7 @@ sub replace {
 
 =item check
 
 
 =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.
 
 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<FS::nas>).
+
+=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
 
 =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
 
 
 =head1 BUGS
 
index e0b5b51..91d2e2f 100644 (file)
@@ -40,12 +40,16 @@ FS/svc_acct_pop.pm
 FS/svc_acct_sm.pm
 FS/svc_domain.pm
 FS/type_pkgs.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
 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
 FS/domain_record.pm
 FS/prepay_credit.pm
 FS/svc_www.pm
index b0f4761..602dc72 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -Tw
 #
 #!/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
 #
 #
 # ivan@sisd.com 97-nov-8,9
 #
 # fix radius attributes ivan@sisd.com 98-sep-27
 #
 # $Log: fs-setup,v $
 # 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
 # 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,
         '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' ] ],
       ],
       'primary_key' => 'nasnum',
       'unique'      => [ [ 'nas' ], [ 'nasip' ] ],
@@ -765,11 +766,8 @@ sub tables_hash_hack {
         'sessionnum', 'int',       '',   '',
         'portnum',    'int',       '',   '',
         'svcnum',     'int',       '',   '',
         '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'      => [],
       ],
       'primary_key' => 'sessionnum',
       'unique'      => [],
index 3ced1df..6da7b22 100644 (file)
@@ -7,3 +7,5 @@ test.pl
 fs_sessiond
 cgi/logon.cgi
 cgi/logoff.cgi
 fs_sessiond
 cgi/logon.cgi
 cgi/logoff.cgi
+bin/freeside-login
+bin/freeside-logoff
index 8dff176..1f59847 100644 (file)
@@ -4,7 +4,7 @@ use ExtUtils::MakeMaker;
 WriteMakefile(
     'NAME'          => 'FS::SessionClient',
     'VERSION_FROM'  => 'SessionClient.pm', # finds $VERSION
 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',
 );
     'INSTALLSCRIPT' => '/usr/local/sbin',
     'PERM_RWX'      => '750',
 );
index fd50e89..97332cb 100644 (file)
@@ -1,7 +1,7 @@
 package FS::SessionClient;
 
 use strict;
 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;
 use Exporter;
 use Socket;
 use FileHandle;
@@ -10,7 +10,7 @@ use IO::Handle;
 $VERSION = '0.01';
 
 @ISA = qw( Exporter );
 $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";
 
 
 $fs_sessiond_socket = "/usr/local/freeside/fs_sessiond_socket";
 
@@ -104,7 +104,7 @@ sub AUTOLOAD {
 
 =head1 VERSION
 
 
 =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
 
 
 =head1 BUGS
 
diff --git a/fs_sesmon/FS-SessionClient/bin/freeside-login b/fs_sesmon/FS-SessionClient/bin/freeside-login
new file mode 100644 (file)
index 0000000..6ca4455
--- /dev/null
@@ -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 (file)
index 0000000..f7b876b
--- /dev/null
@@ -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 )";
+}
+
index be0a017..46e53d1 100644 (file)
@@ -12,6 +12,8 @@ use FS::Record qw( qsearch qsearchs );
 #use FS::cust_main_county;
 #use FS::cust_main;
 use FS::session;
 #use FS::cust_main_county;
 #use FS::cust_main;
 use FS::session;
+use FS::port;
+use FS::svc_acct;
 
 #require "configfile";
 $Debug = 1;
 
 #require "configfile";
 $Debug = 1;
@@ -42,12 +44,70 @@ while (1) {
     }
 
     if ( $command eq 'login' ) {
     }
 
     if ( $command eq 'login' ) {
-
+      $error = &login(\%hash);
+      print $writer "$error\n";
     } elsif ( $command eq 'logoff' ) {
     } elsif ( $command eq 'logoff' ) {
-
+      $error = &logoff(\%hash);
+      print $writer "$error\n";
     } elsif ( $command eq 'portnum' ) {
     } 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";
     }
     } 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";
+}
 
 
index f4155c1..f5c43d0 100644 (file)
@@ -20,6 +20,7 @@
   <li><a href="export.html">File exporting and remote setup</a>
   <li><a href="passwd.html">fs_passwd</a>
   <li><a href="signup.html">Signup server</a>
   <li><a href="export.html">File exporting and remote setup</a>
   <li><a href="passwd.html">fs_passwd</a>
   <li><a href="signup.html">Signup server</a>
+  <li><a href="session.html">Session monitor</a>
   <li><a href="billing.html">Billing</a>
   <li><a href="trouble.html">Troubleshooting</a>
   <li><a href="schema.html">Schema reference</a>
   <li><a href="billing.html">Billing</a>
   <li><a href="trouble.html">Troubleshooting</a>
   <li><a href="schema.html">Schema reference</a>
index 1ab0e7f..474a350 100644 (file)
         <li>pkgnum - <a href="#cust_pkg">package</a>
         <li>svcpart - <a href="#part_svc">Service definition</a>
       </ul>
         <li>pkgnum - <a href="#cust_pkg">package</a>
         <li>svcpart - <a href="#part_svc">Service definition</a>
       </ul>
+    <li><a name="nas">nas</a> - Network Access Server (terminal server)
+      <ul>
+        <li>nasnum - primary key
+        <li>nas - NAS name
+        <li>nasip - NAS ip address
+        <li>nasfqdn - NAS fully-qualified domain name
+        <li>last - timestamp indicating the last instant the NAS was in a known state (used by the session monitoring).
+      </ul>
     <li><a name="part_pkg">part_pkg</a> - Package definitions
       <ul>
         <li>pkgpart - primary key
     <li><a name="part_pkg">part_pkg</a> - Package definitions
       <ul>
         <li>pkgpart - primary key
         <li>svcpart - <a href="#part_svc">Service definition</a>
         <li>quantity - quantity of this service that this package includes
       </ul>
         <li>svcpart - <a href="#part_svc">Service definition</a>
         <li>quantity - quantity of this service that this package includes
       </ul>
+    <li><a name="port">port</a> - individual port on a <a href="#nas">nas</a>
+      <ul>
+        <li>portnum - primary key
+        <li>ip - IP address of this port
+        <li>nasport - port number on the NAS
+        <li>nasnum - <a href="#nas">NAS</a>
+      </ul>
     <li><a name="prepay_credit">prepay_credit</a>
       <ul>
         <li>prepaynum - primary key
         <li>identifier - text or numeric string used to receive this credit
         <li>amount - amount of credit
       </ul>
     <li><a name="prepay_credit">prepay_credit</a>
       <ul>
         <li>prepaynum - primary key
         <li>identifier - text or numeric string used to receive this credit
         <li>amount - amount of credit
       </ul>
+    <li><a name="session">session</a>
+      <ul>
+        <li>sessionnum - primary key
+        <li>portnum - <a href="#port">Port</a>
+        <li>svcnum - <a href="#svc_acct">Account</a>
+        <li>login - timestamp indicating the beginning of this user session.
+        <li>logout - timestamp indicating the end of this user session.  May be null, which indicates a currently open session.
+      </ul>
+
     <li><a name="svc_acct">svc_acct</a> - Accounts
       <ul>
         <li>svcnum - <a href="#cust_svc">primary key</a>
     <li><a name="svc_acct">svc_acct</a> - Accounts
       <ul>
         <li>svcnum - <a href="#cust_svc">primary key</a>