#!/usr/bin/perl

# radwho.cgi	a quick hack to show the users on-line
# Version:      @(#)radwho.cgi  0.01  04-Jul-1998  bruno@openline.com.br
#
# Copyright (c) 1998 Bruno Lopes F. Cabral, Openline ISP

#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.

#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.

	use POSIX;
	use Socket;
	use CGI qw/:standard/;

sub who {
	my($utmpsize, $utmpfile, %proto, $i);
	my($login, $nas_port, $session_id, $nas_address, $framed_address);
	my($protocol, $time, $delay, $type, @info, $j, $name, $from);
	my($location, $host, $tm);

  	# Size of radutmp structure
	$utmpsize = 100;
	# Location of utmp file.
	$utmpfile = '/var/log/utmp';

	%proto = (
		'L'	=> 'LOCAL',
		'R'	=> 'RLOGI',
		'S'	=> 'SLIP',
		'C'	=> 'CSLIP',
		'P'	=> 'PPP',
		'E'	=> 'TELNE',
		'T'	=> 'TCPCL',
		'U'	=> 'TCPLO',
		'!'	=> 'CONSO',
		'X'	=> 'SHELL',
		''	=> 'UNKNO',
	);

	open(FD, "<$utmpfile");
	$i=1;
	while (read(FD, $ut, $utmpsize)) {
		($login, $nas_port, $session_id, $nas_address,
			$framed_address, $protocol, $time, $delay,
			$type) = &unpackradutmp($ut);
		next if ! $type;

		@info     = getpwnam($login);
		$j        = index($info[6],',');
		$name     = ($j < 0 ) ? $info[6] : substr($info[6],0,$j);
		$name     = $login if ! $name;

		# FIXME: cache the NASLIST instead of printing NAS IP
		# remember that doing a DNS lookup took a lot of time!
		$from     = join('.',unpack("CCCC",$nas_address));

		$location = join('.',unpack("CCCC",$framed_address));
		$host     = gethostbyip($location);
		$tm       = strftime( "%a %H:%M", localtime($time));

		print <<EOM if $i==1;
<PRE>
Ord Name                 LoginTime  RAS             Host
<HR SIZE=1>
EOM
		printf "%3d %-20.20s %-9.9s %-15.15s %-25.25s%s\n",
			$i++, $name, $tm, $from, $host;

	}
	close FD;
	print <<EOM;
<HR SIZE=1>
</PRE>
EOM

}

#	Unpack RADUTMP file, and return an array consisting of:
#
#	0. char		login[32]	Loginname
#	1. int		nas_port	Port on the terminal server (32 bits)
#	2. char		session_id[8]	Radius session ID (8 first char)
#	3. UINT4	nas_address	IP of portmaster
#	4. UINT4	framed_address	SLIP/PPP address or login-host
#	5. int		proto		Protocol
#	6. time_t	time		Time entry was last updated
#	7. time_t	delay		Delay time of request
#       8. int		type		Type of entry (login/logout)
#	9. char		reserved[32]	8 ints reserved
#
sub unpackradutmp {
	my @tmp;
	my ($la);

	@tmp = unpack("A32 i A8 a4 a4 a4 I I i A32", $_[0]);
	$tmp[5] =~ s/\0+$//g;
	return @tmp;
}

sub gethostbyip {
        my( $ip ) = @_;
        my( $ipadd, $remotehost );

        $ipadd = gethostbyname( $ip );
        ($remotehost) = gethostbyaddr( $ipadd, AF_INET );
        return ($ip, $remotehost);
}

print header(-expires=>'+300s'), start_html(-title=>'Users on-line',
      -author=>'bruno@openline.com.br', -base=>'true', -target=>'_top',
      -BGCOLOR=>'#ffffff'),"\n";
 
&who;

print end_html;

