#!/usr/bin/perl -w

######################################################################
#
# Keep scanning the 'netstat -t' but filter out local connects and service.
#
# 1996-09-03 turbo: begun
#
# $Header: /usr/lib/cvs/root/tcpquota/topnet,v 1.18 1998/08/01 19:57:59 turbo Exp $
#
# $Log: topnet,v $
# Revision 1.18  1998/08/01 19:57:59  turbo
# * First quick port to use the generic database interface 'DBI' instead of
#   the 'Msql' interface. This is so that we can go from using mSQL as
#   database, to use the much quicker mySQL server. But by using this generic
#   interface, we can have both... More or less :)
# # Any reference to the Msql function 'query' had to be replaced with, first
#   a 'prepare' then a 'execute'. If the execute fails, then die, or log, or
#   what evere takes us fancy...
# * Any reference to the Msql functions 'fetchrow' and 'numrows', had to be
#   replaced with 'fetchrow_array' and 'rows'.
# * Found a 'open_sql_server()' function in the 'tcp_masq_openfw' script. Move
#   that to the library, so that we can reuse the function all over the board.
# # Added a lot of '&' to the call of our own functions... They glow with such
#   a pretty blue color in X... :)
#
# Revision 1.17  1998/05/24 15:57:26  turbo
# * Had to add a dummy 'logg()' function...
# * Open the debug file if we are running in debug mode...
#
# Revision 1.16  1998/03/31 12:16:10  turbo
# Make sure we search and opens the correct config file,
# set by the variables '{lib|conf}_dir' at the top...
#
# Revision 1.15  1998/03/14 23:02:59  turbo
# If we can't open a connection to the mSQL database, say so and include the
# information to _WHICH_ server we can not connect to...
#
# Revision 1.14  1997/11/26 21:57:10  turbo
# Some fixes in the output, better language, perhaps? :)
#
# Revision 1.13  1997/11/26 21:29:57  turbo
# Removed a lot of config file variables, that could possibly confuse a new
# user/admin of the package... We asume that whoever chooses to install the
# package, use our default... If not, they can go in and change the stuff
# themselvs!!
#
# Revision 1.12  1997/11/19 22:49:09  turbo
# Removed the PERIOD=5, we have that value in the configfile, which we read
# anyway...
#
# Revision 1.11  1997/11/19 20:02:49  turbo
# * Use the built in perl function 'getnetent()' to find the network address.
# * Instead of using '/bin/netstat -te' to get the network connections, use
#   our own function 'get_netstat()' to gather that information instead.
# * When checking local network connection, I found that this was _OLD_ code,
#   stole the whole thing from 'tcpquotad' instead, only modified it a little...
# * Same with the masquerading stuff...
# * Instead of using '/sbin/ipfwadm -Mln' to gather masqueraded host information,
#   use our own function 'get_masquerade()' to gather that information instead.
#
# Revision 1.10  1997/11/11 14:18:38  turbo
# Added a new row to the database, 'free', to allow a host free surfing...
# Make sure that we do not delete the host from the masquerading table if
# this is set to 1...
#
# Revision 1.9  1997/11/04 14:53:33  turbo
# We should require './lib/tcpquota.pl' instead of 'lib/tcpquota.pl'...
#
# Revision 1.8  1997/10/16 21:28:33  turbo
# Moved the function 'find_fqdn()' to the library, since it was needed else were...
#
# Revision 1.7  1997/10/10 02:10:41  turbo
# If 'host' can not find the FQDN of an IP address, it gets wierd... Just
# redirect STDERR to /dev/null...
#
# Revision 1.6  1997/10/08 20:25:45  turbo
# Stole the 'check_masquerade()' function from the daemon, and rewrote it some,
# to better suit topnet... The function only output's the IP addresses, so
# call '/usr/bin/host' to look it up, that's what the new function 'find_fqdn()'
# does...
#
# Revision 1.5  1997/10/08 18:27:56  turbo
# * Removed some lines in the fucked up header...
# * Added support for masquerading, no it first print the users from localhost
#   with a total of local, then users which is masqueraded with a total of
#   masqueraded, then a line telling us how many total of users which is using
#   the link...
#
# Revision 1.4  1997/10/06 00:46:08  turbo
# * Added special support for X11... We want a thinner output, and only the
#   user and destination address, no need for source address. Start with
#   'topnet -x11'.
#
# Revision 1.3  1997/10/05 21:28:48  turbo
# * Do not ignore root's connect's... Could be intresting to know _ALL_ external
#   connects...
# * Use printf as it is supposed to be used, 'printf("%-30s", variable)'...
#   Gives better looking output... maby... :)
#
# Revision 1.2  1997/08/17 17:29:14  turbo
# * Moved some functions to the library file.
# * Deleted some variables, they exists in the config file.
# * Added the global config variables 'LANGUAGE' and 'MONEY_VALUE' in the
#   config file...
# * Changed some hardcoded site specific entries, and language. We cant
#   release it if much of it is specific to CCW...
# * Made sure that all the script's understand '--help', '-h' and '?', just
#   in case...
# * Some of the config file variables can be used by all the scripts, therefor
#   made non-program specific ('TABLE=xxx', instead of 'tcpquotad.TABLE=xxx').
# * Fixed some calculation buggs in the admin program, and also more information
#   in the menu.
#
#

# Include some magic...
use DBI;
use POSIX;
package main;

$lib_dir  = "./lib";
$conf_dir = "./confs";

require "$lib_dir/tcpquota.pl";

# check period, in seconds
$USE_X11 = 0;

# Does we have any arguments?
if( $ARGV[0] ) {
    # Ohh yes.... Process it...

    foreach $arg (@ARGV) {
        if( $arg eq '-x11' ) {
            $USE_X11 = 1;
        }

        if( $arg eq '--help' || $arg eq '-h' || $arg eq '?' ) {
            print "\nUse: $0 -x11 to run the program in special X11 mode...\n\n";
            exit 0;
        }
    }
}

# A global dummy variable...
$dummy       = "";

$local       = "Local Address";
$foreign     = "Foreign address";
$user_line   = "User";

$CF_FILE="tcpquota.cf";
$CF_FILE="tcpquota.cf.debug" if (defined $ENV{DEBUG} or $DEBUG);

%cf=(); # config array.
&readconfig("$conf_dir/$CF_FILE","tcpquotad");

######################################################################
#
# main loop
#

# Open up the database connection...
&open_sql_server();

# Get the network address...
$localnet = (getnetent())[1];

while(1) {
    $local_users = 0;
    $masqd_users = 0;

    # Clear the screen.
    system('clear');

    print_header();

    # ===== C H E C K  F O R  L O C A L  U S E R S =====

    # Get the connect to and from us, not counting any localnet comm...
    %NETSTAT = &get_netstat();

    $j = 0; $i = 0;
    while($NETSTAT{$j}) {
	$loc = (split(' ', $NETSTAT{$j}))[0];
	$rem = (split(' ', $NETSTAT{$j}))[1];
	$uid = (split(' ', $NETSTAT{$j}))[2];

	# Get the 'Foreign Address' and 'TCP port'.
	($for_name, $for_port) = split(':', $rem);

	# Get the 'Local Address' and 'TCP port'.
	($loc_name, $dummy)    = split(':', $loc);

	# Get the A, B and C net number...
	($ipA, $ipB, $ipC, $dummy) = split('\.', $for_name);
	($ip1, $ip2, $ip3, $dummy) = split('\.', $localnet);

	# ignore connections on our own C-Net and ftp-data streams.
	if( ($ip1 != $ipA) && ($ip2 != $ipB) && ($ip3 != $ipC) && ($for_port != 20) ) {
	    # Count one user for each turn in the loop.
	    $i++;

	    # Remember this user...
	    $user = (getpwuid($uid))[0];

	    # Print out the relevant parts.
	    if( $USE_X11 ) {
		printf("local:  %-10s %-30s\n", $user, &find_fqdn($loc_name));
	    } else {
		printf("local:  %-30s %-30s %-10s\n",  &find_fqdn($loc_name), &find_fqdn($for_name), $user);
	    }
	}

	$j++;
    }

    # Remember how many users that is online...
    $local_users = $i;

    print "local:  $local_users connect(s)\n\n";

    # ===== C H E C K  F O R  M A S Q U E R A D E D  U S E R S =====

    # Get all masq users and add them to our local userlist..
    if( $cf{'MASQUERADE'} ) {
	@USER = ();

	&check_masqueraded();

	$i = 0;
	foreach $user (@USER) {
	    $i++;

	    # Print out the relevant parts.
	    if( $USE_X11 ) {
		printf("masqed: %-12s %-30s\n", $user, $dest{$user});
	    } else {
		printf("masqed: %-30s%-30s %-10s\n", $source{$user}, $dest{$user}, $user);
	    }
	}

	# Save the value in the counter to its relevant var.
	$masqd_users = $i;
    } else {
	$masqd_users = 0;
    }

    $total = $masqd_users + $local_users;
    print "masqed: $masqd_users connect(s)\n\n";
    print "Total number of connections: $total connect(s)\n";

    sleep $cf{'PERIOD'};
}

######################################################################
#
# check_masqueraded()
#
sub check_masqueraded {
    local($name, $sth, $host, $time, $cnts, $tic, $count);
    local($src, $dst, $d, $c_cnts, $free);

    $sth = $dbh->prepare("select * from masq");
    $sth->execute || printf("Error while fetching from masq: $sth->errstr\n");

    # Fetch each hit..
    while( ($host, $name, $cnts, $tic, $count, $free) = $sth->fetchrow_array ) {
	($src,$dst,$d,$c_cnts) = (0,0,0,0);

	# Read from 'ipfwadm'...
	%MASQ = &get_masquerade(); $i = 0;
	while($MASQ{$i}) {
	    ($src, $dst, $time, $dummy) = split(' ', $MASQ{$i});

	    # Tcp kopplingar har 15 minuter som initial timout.
	    # vi tar bara med en kopplin under PERIOD sek
	    # sedan den var aktiv..
	    ($minutes, $time)  = split(/:/,  $time);
	    ($seconds, $dummy) = split(/\./, $time);

	    if( $minutes >= 14 && ($seconds >= 30 - $cf{'PERIOD'}) ) {
		$cnts++;

		# Remember the name...
		push( @USER, $name );

		# Find the FQDN of the source host...
		$src = &find_fqdn($src);

		# Find the FQDN of the dest host...
		$dst = &find_fqdn($dst);

		# Remember the destination...
		$dest{$name}   = $dst;

		# Remember the source...
		$source{$name} = $src;
	    }

	    $i++;
	}
    }
}

# print out the leading info lines.
sub print_header {
    print "\n";

    if( $USE_X11 ) {
	printf("        %-10s %-30s\n", $user_line, $foreign);
    } else {
	printf("        %-30s %-30s %-10s\n", $local, $foreign, $user_line);
    }
}

sub logg {
    return(0);
}
