#!/usr/local/sbin/slipsh
#
# This script monitors activity on all attached slip interfaces
# on a regular basis and logs information to a file. This is useful
# for providing detailed information of SLIP usage, especially in
# conjunction with sliplogin, where you can write additional records
# to the log file from the slip.login and slip.logout files.
# The slipmon script catches the HUP signal, so that you can add the
# following lines to slip.login/logout:
#
# login:
#	killall -HUP slipmon
#
# logout:
#	killall -HUP slipmon; sleep 2
#
#
# The following variables control the behavior of slipmon:
#
# interval	time in seconds between regular interface checks.
#		In addition, slipmon will check the interfaces
#		every time it receives a SIGHUP.
# logcont	set to 1 if you want continuous logging of interface
#		statistics every interval seconds
# watchpat	The pattern an interface has to match in order for
#		slipmon to monitor it. This is a string in shell
#		glob-style syntax.
# logfile	This variale is defined in common.tcl. If this file
#		exists, the cilentA and clientB sample scripts
#		will log information to this file, too. The default
#		is /var/log/slipstat.
# 

set watchpat	"sl*"
set interval	600
set logcont	1

source "/usr/local/lib/slipsh/common.tcl"

##################################################################
# Get interface packet statistics
##################################################################
proc set_ifstat {if} {

    global ipkt opkt ierr oerr

    net ifstats -ipackets inpkt -opackets outpkt \
		-ierrors  inerr -oerrors  outerr $if
    set ipkt($if) $inpkt
    set ierr($if) $inerr
    set opkt($if) $outpkt
    set oerr($if) $outerr
}

##################################################################
# Log interface statistics
##################################################################
proc log_ifstat {if} {

    global ipkt opkt ierr oerr

    set stat [format "%-5s %6d %6d %6d %6d"  \
		$if $ipkt($if) $opkt($if) $ierr($if) $oerr($if)]
    sliplog "stat $stat"
}

##################################################################
# Log the fact that an interface has been broght up.
##################################################################
proc up_iface {if} {

    global tickmark
    global ipkt opkt ierr oerr

    set_ifstat $if
    set tickmark($if) [sys time]

    net ifstats -resolve -address myname -peeraddress peername $if
    net ifstats -address myaddr -peeraddress peeraddr $if
    sliplog [format "up   %-5s %s (%s) -> %s (%s)" \
		$if $myname $myaddr $peername $peeraddr];
    log_ifstat $if
}

##################################################################
# Log the fact that an interface has been broght down.
##################################################################
proc down_iface {if} {

    global tickmark

    log_ifstat $if
    sliplog "down $if"
    unset tickmark($if)
}

##################################################################
# Set the tickmark and stats of an active interface
##################################################################
proc tick_iface {if} {

    global tickmark 

    if {![info exists tickmark($if)]} {
	up_iface $if
    } else {
	set_ifstat $if
        set tickmark($if) [sys time]
    }
}

proc check_config {} {

    global tickmark
    global watchpat
    global logcont

    set now [sys time]

    # first, find all active interfaces and update their tickmarks
    set active_ifs [net iflist];
    foreach if $active_ifs {
	tick_iface $if
    }

    # now, find out which ones interest us
    set watch_ifs [array names tickmark]
    foreach if $watch_ifs {
	if {[string match $watchpat $if]} {
	    if {$logcont != 0} {
		log_ifstat $if
	    }
	    if {$tickmark($if) < $now} {
		down_iface $if
	    }
	    # Here, we could test for an idle condition.
	    # I'm too lazy right now.
	}
    }
}

##################################################################
# main routine
##################################################################
sys signal SIGHUP  {check_config; sys sleep 3; check_config}
sys signal SIGTERM {check_config; exit 0}

while 1 {
    sys sleep $interval
    check_config
}
