mirror of
https://github.com/sirpdboy/sirpdboy-package.git
synced 2025-01-07 03:17:03 +08:00
up
This commit is contained in:
parent
bd39b68101
commit
d882abd050
@ -14,7 +14,7 @@ PKG_LICENSE:=Apache-2.0
|
||||
PKG_MAINTAINER:=
|
||||
|
||||
LUCI_TITLE:=A Luci module that uses wrtbwmon to track bandwidth usage
|
||||
LUCI_DEPENDS:=+luci-app-nlbwmon
|
||||
LUCI_DEPENDS:=+wrtbwmon
|
||||
LUCI_PKGARCH:=all
|
||||
|
||||
include $(TOPDIR)/feeds/luci/luci.mk
|
||||
|
@ -1,10 +1,20 @@
|
||||
module("luci.controller.wrtbwmon", package.seeall)
|
||||
|
||||
function index()
|
||||
|
||||
entry({"admin", "nlbw", "usage"},alias("admin", "nlbw", "usage", "details"),_("Usage"), 1)
|
||||
entry({"admin", "nlbw", "usage", "details"}, template("wrtbwmon"),_("Details"), 10).leaf=true
|
||||
entry({"admin", "nlbw", "usage", "config"},arcombine(cbi("wrtbwmon/config")),_("Configuration"), 20).leaf=true
|
||||
entry({"admin", "nlbw", "usage", "custom"},form("wrtbwmon/custom"),_("User file"), 30).leaf=true
|
||||
if not nixio.fs.access("/etc/config/wrtbwmon") then
|
||||
return
|
||||
end
|
||||
entry({"admin", "nlbw", "usage"},
|
||||
alias("admin", "nlbw", "usage", "details"),
|
||||
_("Usage"), 1)
|
||||
entry({"admin", "nlbw", "usage", "details"},
|
||||
template("wrtbwmon"),
|
||||
_("Details"), 10).leaf=true
|
||||
entry({"admin", "nlbw", "usage", "config"},
|
||||
arcombine(cbi("wrtbwmon/config")),
|
||||
_("Configuration"), 20).leaf=true
|
||||
entry({"admin", "nlbw", "usage", "custom"},
|
||||
form("wrtbwmon/custom"),
|
||||
_("User file"), 30).leaf=true
|
||||
end
|
||||
|
||||
|
@ -1,4 +0,0 @@
|
||||
|
||||
config wrtbwmon 'general'
|
||||
option persist '0'
|
||||
|
@ -1,22 +0,0 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
#
|
||||
# start/stop wrtbwmon bandwidth monitor
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: wrtbwmon
|
||||
# Required-Start: $network $local_fs $remote_fs
|
||||
# Required-Stop: $local_fs $remote_fs
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: iptables-based bandwidth monitor
|
||||
### END INIT INFO
|
||||
|
||||
START=91
|
||||
|
||||
start(){
|
||||
/usr/sbin/wrtbwmon setup /tmp/usage.db
|
||||
}
|
||||
|
||||
stop(){
|
||||
/usr/sbin/wrtbwmon remove
|
||||
}
|
@ -6,7 +6,6 @@ uci -q batch <<-EOF >/dev/null
|
||||
set ucitrack.@wrtbwmon[-1].init=wrtbwmon
|
||||
commit ucitrack
|
||||
EOF
|
||||
/etc/init.d/wrtbwmon enable
|
||||
/etc/init.d/wrtbwmon start
|
||||
|
||||
rm -f /tmp/luci-indexcache
|
||||
exit 0
|
||||
|
@ -1 +0,0 @@
|
||||
/etc/init.d/wrtbwmon restart >/dev/null 2>&1
|
@ -1,157 +0,0 @@
|
||||
#!/usr/bin/awk
|
||||
|
||||
function inInterfaces(host){
|
||||
return(interfaces ~ "(^| )"host"($| )")
|
||||
}
|
||||
|
||||
function newRule(arp_ip,
|
||||
ipt_cmd){
|
||||
# checking for existing rules shouldn't be necessary if newRule is
|
||||
# always called after db is read, arp table is read, and existing
|
||||
# iptables rules are read.
|
||||
ipt_cmd="iptables -t mangle -j RETURN -s " arp_ip
|
||||
system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD")
|
||||
ipt_cmd="iptables -t mangle -j RETURN -d " arp_ip
|
||||
system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD")
|
||||
}
|
||||
|
||||
function total(i){
|
||||
return(bw[i "/in"] + bw[i "/out"])
|
||||
}
|
||||
|
||||
function date( cmd, d){
|
||||
cmd="date +%d-%m-%Y_%H:%M:%S"
|
||||
cmd | getline d
|
||||
close(cmd)
|
||||
#!@todo could start a process with "while true; do date ...; done"
|
||||
return(d)
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
od=""
|
||||
fid=1
|
||||
debug=0
|
||||
rrd=0
|
||||
}
|
||||
|
||||
/^#/ { # get DB filename
|
||||
FS=","
|
||||
dbFile=FILENAME
|
||||
next
|
||||
}
|
||||
|
||||
# data from database; first file
|
||||
FNR==NR { #!@todo this doesn't help if the DB file is empty.
|
||||
if($2 == "NA")
|
||||
#!@todo could get interface IP here
|
||||
n=$1
|
||||
else
|
||||
n=$2
|
||||
|
||||
hosts[n] = "" # add this host/interface to hosts
|
||||
mac[n] = $1
|
||||
ip[n] = $2
|
||||
inter[n] = $3
|
||||
bw[n "/in"] = $4
|
||||
bw[n "/out"] = $5
|
||||
firstDate[n] = $7
|
||||
lastDate[n] = $8
|
||||
next
|
||||
}
|
||||
|
||||
# not triggered on the first file
|
||||
FNR==1 {
|
||||
FS=" "
|
||||
fid++ #!@todo use fid for all files; may be problematic for empty files
|
||||
next
|
||||
}
|
||||
|
||||
# arp: ip hw flags hw_addr mask device
|
||||
fid==2 {
|
||||
#!@todo regex match IPs and MACs for sanity
|
||||
arp_ip = $1
|
||||
arp_flags = $3
|
||||
arp_mac = $4
|
||||
arp_dev = $6
|
||||
if(arp_flags != "0x0" && !(arp_ip in ip)){
|
||||
if(debug)
|
||||
print "new host:", arp_ip, arp_flags > "/dev/stderr"
|
||||
hosts[arp_ip] = ""
|
||||
mac[arp_ip] = arp_mac
|
||||
ip[arp_ip] = arp_ip
|
||||
inter[arp_ip] = arp_dev
|
||||
bw[arp_ip "/in"] = bw[arp_ip "/out"] = 0
|
||||
firstDate[arp_ip] = lastDate[arp_ip] = date()
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
#!@todo could use mangle chain totals or tailing "unnact" rules to
|
||||
# account for data for new hosts from their first presence on the
|
||||
# network to rule creation. The "unnact" rules would have to be
|
||||
# maintained at the end of the list, and new rules would be inserted
|
||||
# at the top.
|
||||
|
||||
# skip line
|
||||
# read the chain name and deal with the data accordingly
|
||||
fid==3 && $1 == "Chain"{
|
||||
rrd=$2 ~ /RRDIPT_.*/
|
||||
next
|
||||
}
|
||||
|
||||
fid==3 && rrd && (NF < 9 || $1=="pkts"){ next }
|
||||
|
||||
fid==3 && rrd { # iptables input
|
||||
if($6 != "*"){
|
||||
m=$6
|
||||
n=m "/out"
|
||||
} else if($7 != "*"){
|
||||
m=$7
|
||||
n=m "/in"
|
||||
} else if($8 != "0.0.0.0/0"){
|
||||
m=$8
|
||||
n=m "/out"
|
||||
} else { # $9 != "0.0.0.0/0"
|
||||
m=$9
|
||||
n=m "/in"
|
||||
}
|
||||
|
||||
# remove host from array; any hosts left in array at END get new
|
||||
# iptables rules
|
||||
|
||||
#!@todo this deletes a host if any rule exists; if only one
|
||||
# directional rule is removed, this will not remedy the situation
|
||||
delete hosts[m]
|
||||
|
||||
if($2 > 0){ # counted some bytes
|
||||
if(mode == "diff" || mode == "noUpdate")
|
||||
print n, $2
|
||||
if(mode!="noUpdate"){
|
||||
if(inInterfaces(m)){ # if label is an interface
|
||||
if(!(m in mac)){ # if label was not in db (also not in
|
||||
# arp table, but interfaces won't be
|
||||
# there anyway)
|
||||
firstDate[m] = date()
|
||||
mac[m] = inter[m] = m
|
||||
ip[m] = "NA"
|
||||
bw[m "/in"]=bw[m "/out"]= 0
|
||||
}
|
||||
}
|
||||
bw[n]+=$2
|
||||
lastDate[m] = date()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if(mode=="noUpdate") exit
|
||||
close(dbFile)
|
||||
system("rm -f " dbFile)
|
||||
print "#mac,ip,iface,in,out,total,first_date,last_date" > dbFile
|
||||
OFS=","
|
||||
for(i in mac)
|
||||
print mac[i], ip[i], inter[i], bw[i "/in"], bw[i "/out"], total(i), firstDate[i], lastDate[i] > dbFile
|
||||
close(dbFile)
|
||||
# for hosts without rules
|
||||
for(host in hosts) if(!inInterfaces(host)) newRule(host)
|
||||
}
|
@ -1,313 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# wrtbwmon: traffic logging tool for routers
|
||||
#
|
||||
# Peter Bailey (peter.eldridge.bailey+wrtbwmon AT gmail.com)
|
||||
#
|
||||
# Based on work by:
|
||||
# Emmanuel Brucy (e.brucy AT qut.edu.au)
|
||||
# Fredrik Erlandsson (erlis AT linux.nu)
|
||||
# twist - http://wiki.openwrt.org/RrdTrafficWatch
|
||||
|
||||
trap "rm -f /tmp/*_$$.tmp; kill $$" INT
|
||||
binDir=/usr/sbin
|
||||
dataDir=/usr/share/wrtbwmon
|
||||
lockDir=/tmp/wrtbwmon.lock
|
||||
pidFile=$lockDir/pid
|
||||
networkFuncs=/lib/functions/network.sh
|
||||
uci=`which uci 2>/dev/null`
|
||||
nslookup=`which nslookup 2>/dev/null`
|
||||
nvram=`which nvram 2>/dev/null`
|
||||
|
||||
chains='INPUT OUTPUT FORWARD'
|
||||
DEBUG=
|
||||
interfaces='eth0 tun0' # in addition to detected WAN
|
||||
DB=$2
|
||||
mode=
|
||||
|
||||
# DNS server for reverse lookups provided in "DNS".
|
||||
# don't perform reverse DNS lookups by default
|
||||
DO_RDNS=${DNS-}
|
||||
|
||||
header="#mac,ip,iface,in,out,total,first_date,last_date"
|
||||
|
||||
createDbIfMissing()
|
||||
{
|
||||
[ ! -f "$DB" ] && echo $header > "$DB"
|
||||
}
|
||||
|
||||
checkDbArg()
|
||||
{
|
||||
[ -z "$DB" ] && echo "ERROR: Missing argument 2 (database file)" && exit 1
|
||||
}
|
||||
|
||||
checkDB()
|
||||
{
|
||||
[ ! -f "$DB" ] && echo "ERROR: $DB does not exist" && exit 1
|
||||
[ ! -w "$DB" ] && echo "ERROR: $DB is not writable" && exit 1
|
||||
}
|
||||
|
||||
checkWAN()
|
||||
{
|
||||
[ -z "$wan" ] && echo "Warning: failed to detect WAN interface."
|
||||
}
|
||||
|
||||
checkIptIfMissing()
|
||||
{
|
||||
iptables-save | grep 'RRDIPT_INPUT' >/dev/null 2>&1; CHK1=$?
|
||||
iptables-save | grep 'RRDIPT_OUTPUT' >/dev/null 2>&1; CHK2=$?
|
||||
iptables-save | grep 'RRDIPT_FORWARD' >/dev/null 2>&1; CHK3=$?
|
||||
if [ "$CHK1" != "0" ] || [ "$CHK2" != "0" ] || [ "$CHK3" != "0" ]
|
||||
then
|
||||
/etc/init.d/wrtbwmon restart
|
||||
fi
|
||||
}
|
||||
|
||||
lookup()
|
||||
{
|
||||
MAC=$1
|
||||
IP=$2
|
||||
userDB=$3
|
||||
for USERSFILE in $userDB /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do
|
||||
[ -e "$USERSFILE" ] || continue
|
||||
case $USERSFILE in
|
||||
/tmp/dhcp.leases )
|
||||
USER=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ')
|
||||
;;
|
||||
/etc/hosts )
|
||||
USER=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ')
|
||||
;;
|
||||
* )
|
||||
USER=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,)
|
||||
;;
|
||||
esac
|
||||
[ "$USER" = "*" ] && USER=
|
||||
[ -n "$USER" ] && break
|
||||
done
|
||||
if [ -n "$DO_RDNS" -a -z "$USER" -a "$IP" != "NA" -a -n "$nslookup" ]; then
|
||||
USER=`$nslookup $IP $DNS | awk '!/server can/{if($4){print $4; exit}}' | sed -re 's/[.]$//'`
|
||||
fi
|
||||
[ -z "$USER" ] && USER=${MAC}
|
||||
echo $USER
|
||||
}
|
||||
|
||||
detectIF()
|
||||
{
|
||||
if [ -f "$networkFuncs" ]; then
|
||||
IF=`. $networkFuncs; network_get_device netdev $1; echo $netdev`
|
||||
[ -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
|
||||
if [ -n "$uci" -a -x "$uci" ]; then
|
||||
IF=`$uci get network.${1}.ifname 2>/dev/null`
|
||||
[ $? -eq 0 -a -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
|
||||
if [ -n "$nvram" -a -x "$nvram" ]; then
|
||||
IF=`$nvram get ${1}_ifname 2>/dev/null`
|
||||
[ $? -eq 0 -a -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
}
|
||||
|
||||
detectLAN()
|
||||
{
|
||||
[ -e /sys/class/net/br-lan ] && echo br-lan && return
|
||||
lan=$(detectIF lan)
|
||||
[ -n "$lan" ] && echo $lan && return
|
||||
}
|
||||
|
||||
detectWAN()
|
||||
{
|
||||
[ -n "$WAN_IF" ] && echo $WAN_IF && return
|
||||
wan=$(detectIF wan)
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
wan=$(ip route show 2>/dev/null | grep default | sed -re '/^default/ s/default.*dev +([^ ]+).*/\1/')
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
[ -f "$networkFuncs" ] && wan=$(. $networkFuncs; network_find_wan wan; echo $wan)
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
}
|
||||
|
||||
lock()
|
||||
{
|
||||
attempts=0
|
||||
while [ $attempts -lt 10 ]; do
|
||||
mkdir $lockDir 2>/dev/null && break
|
||||
attempts=$((attempts+1))
|
||||
pid=`cat $pidFile 2>/dev/null`
|
||||
if [ -n "$pid" ]; then
|
||||
if [ -d "/proc/$pid" ]; then
|
||||
[ -n "$DEBUG" ] && echo "WARNING: Lockfile detected but process $(cat $pidFile) does not exist !"
|
||||
rm -rf $lockDir
|
||||
else
|
||||
sleep 1
|
||||
fi
|
||||
fi
|
||||
done
|
||||
mkdir $lockDir 2>/dev/null
|
||||
echo $$ > $pidFile
|
||||
[ -n "$DEBUG" ] && echo $$ "got lock after $attempts attempts"
|
||||
trap '' INT
|
||||
}
|
||||
|
||||
unlock()
|
||||
{
|
||||
rm -rf $lockDir
|
||||
[ -n "$DEBUG" ] && echo $$ "released lock"
|
||||
trap "rm -f /tmp/*_$$.tmp; kill $$" INT
|
||||
}
|
||||
|
||||
# chain
|
||||
newChain()
|
||||
{
|
||||
chain=$1
|
||||
# Create the RRDIPT_$chain chain (it doesn't matter if it already exists).
|
||||
iptables -t mangle -N RRDIPT_$chain 2> /dev/null
|
||||
|
||||
# Add the RRDIPT_$chain CHAIN to the $chain chain if not present
|
||||
iptables -t mangle -C $chain -j RRDIPT_$chain 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
[ -n "$DEBUG" ] && echo "DEBUG: iptables chain misplaced, recreating it..."
|
||||
iptables -t mangle -I $chain -j RRDIPT_$chain
|
||||
fi
|
||||
}
|
||||
|
||||
# chain tun
|
||||
newRuleIF()
|
||||
{
|
||||
chain=$1
|
||||
IF=$2
|
||||
|
||||
#!@todo test
|
||||
if [ "$chain" = "OUTPUT" ]; then
|
||||
cmd="iptables -t mangle -o $IF -j RETURN"
|
||||
eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain"
|
||||
elif [ "$chain" = "INPUT" ]; then
|
||||
cmd="iptables -t mangle -i $IF -j RETURN"
|
||||
eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain"
|
||||
fi
|
||||
}
|
||||
|
||||
update()
|
||||
{
|
||||
#!@todo could let readDB.awk handle this; that would place header
|
||||
#!info in fewer places
|
||||
createDbIfMissing
|
||||
checkIptIfMissing
|
||||
|
||||
checkDB
|
||||
checkWAN
|
||||
|
||||
> /tmp/iptables_$$.tmp
|
||||
lock
|
||||
# only zero our own chains
|
||||
for chain in $chains; do
|
||||
iptables -nvxL RRDIPT_$chain -t mangle -Z >> /tmp/iptables_$$.tmp
|
||||
done
|
||||
# the iptables and readDB commands have to be separate. Otherwise,
|
||||
# they will fight over iptables locks
|
||||
awk -v mode="$mode" -v interfaces=\""$interfaces"\" -f $binDir/readDB.awk \
|
||||
$DB \
|
||||
/proc/net/arp \
|
||||
/tmp/iptables_$$.tmp
|
||||
unlock
|
||||
}
|
||||
|
||||
############################################################
|
||||
|
||||
case $1 in
|
||||
"dump" )
|
||||
checkDbArg
|
||||
lock
|
||||
tr ',' '\t' < "$DB"
|
||||
unlock
|
||||
;;
|
||||
|
||||
"update" )
|
||||
checkDbArg
|
||||
wan=$(detectWAN)
|
||||
interfaces="$interfaces $wan"
|
||||
update
|
||||
rm -f /tmp/*_$$.tmp
|
||||
exit
|
||||
;;
|
||||
|
||||
"publish" )
|
||||
checkDbArg
|
||||
[ -z "$3" ] && echo "ERROR: Missing argument 3 (output html file)" && exit 1
|
||||
|
||||
# sort DB
|
||||
lock
|
||||
|
||||
# busybox sort truncates numbers to 32 bits
|
||||
grep -v '^#' $DB | awk -F, '{OFS=","; a=sprintf("%f",$4/1e6); $4=""; print a,$0}' | tr -s ',' | sort -rn | awk -F, '{OFS=",";$1=sprintf("%f",$1*1e6);print}' > /tmp/sorted_$$.tmp
|
||||
|
||||
# create HTML page
|
||||
rm -f $3.tmp
|
||||
cp $dataDir/usage.htm1 $3.tmp
|
||||
|
||||
#!@todo fix publishing
|
||||
while IFS=, read PEAKUSAGE_IN MAC IP IFACE PEAKUSAGE_OUT TOTAL FIRSTSEEN LASTSEEN
|
||||
do
|
||||
echo "
|
||||
new Array(\"$(lookup $MAC $IP $4)\",\"$MAC\",\"$IP\",
|
||||
$PEAKUSAGE_IN,$PEAKUSAGE_OUT,$TOTAL,\"$FIRSTSEEN\",\"$LASTSEEN\")," >> $3.tmp
|
||||
done < /tmp/sorted_$$.tmp
|
||||
echo "0);" >> $3.tmp
|
||||
|
||||
sed "s/(date)/`date`/" < $dataDir/usage.htm2 >> $3.tmp
|
||||
mv $3.tmp $3
|
||||
|
||||
unlock
|
||||
|
||||
#Free some memory
|
||||
rm -f /tmp/*_$$.tmp
|
||||
;;
|
||||
|
||||
"setup" )
|
||||
checkDbArg
|
||||
[ -w "$DB" ] && echo "Warning: using existing $DB"
|
||||
createDbIfMissing
|
||||
|
||||
for chain in $chains; do
|
||||
newChain $chain
|
||||
done
|
||||
|
||||
#lan=$(detectLAN)
|
||||
wan=$(detectWAN)
|
||||
checkWAN
|
||||
interfaces="$interfaces $wan"
|
||||
|
||||
# track local data
|
||||
for chain in INPUT OUTPUT; do
|
||||
for interface in $interfaces; do
|
||||
[ -n "$interface" ] && [ -e "/sys/class/net/$interface" ] && newRuleIF $chain $interface
|
||||
done
|
||||
done
|
||||
|
||||
# this will add rules for hosts in arp table
|
||||
update
|
||||
|
||||
rm -f /tmp/*_$$.tmp
|
||||
;;
|
||||
|
||||
"remove" )
|
||||
iptables-save | grep -v RRDIPT | iptables-restore
|
||||
rm -rf "$lockDir"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo \
|
||||
"Usage: $0 {setup|update|publish|remove} [options...]
|
||||
Options:
|
||||
$0 setup database_file
|
||||
$0 update database_file
|
||||
$0 publish database_file path_of_html_report [user_file]
|
||||
Examples:
|
||||
$0 setup /tmp/usage.db
|
||||
$0 update /tmp/usage.db
|
||||
$0 publish /tmp/usage.db /www/user/usage.htm /jffs/users.txt
|
||||
$0 remove
|
||||
Note: [user_file] is an optional file to match users with MAC addresses.
|
||||
Its format is \"00:MA:CA:DD:RE:SS,username\", with one entry per line."
|
||||
;;
|
||||
esac
|
@ -1,23 +0,0 @@
|
||||
<html><head><title>Traffic</title>
|
||||
<script type="text/javascript">
|
||||
function getSize(size) {
|
||||
var prefix=new Array("","k","M","G","T","P","E","Z"); var base=1000;
|
||||
var pos=0;
|
||||
while (size>base) {
|
||||
size/=base; pos++;
|
||||
}
|
||||
if (pos > 2) precision=1000; else precision = 1;
|
||||
return (Math.round(size*precision)/precision)+' '+prefix[pos];}
|
||||
</script></head>
|
||||
<body><h1>Total Usage:</h1>
|
||||
<table border="1">
|
||||
<tr bgcolor=silver>
|
||||
<th>User</th>
|
||||
<th>Download</th>
|
||||
<th>Upload</th>
|
||||
<th>Total</th>
|
||||
<th>First seen</th>
|
||||
<th>Last seen</th>
|
||||
</tr>
|
||||
<script type="text/javascript">
|
||||
var values = new Array(
|
@ -1,14 +0,0 @@
|
||||
var totalIn = 0;
|
||||
var totalOut = 0;
|
||||
for (i=0; i < values.length-1; i++) {
|
||||
totalIn += values[i][3];
|
||||
totalOut += values[i][4];
|
||||
document.write("<tr><td><div title=\"" + values[i][1] + " (" + values[i][2] + ")" + "\">" + values[i][0] + "</div></td>");
|
||||
for (j=3; j < 6; j++)
|
||||
document.write("<td>" + getSize(values[i][j]) + "</td>");
|
||||
document.write("<td>" + values[i][6] + "</td><td>" + values[i][7] + "</td></tr>");
|
||||
}
|
||||
document.write("<tr><td>TOTAL</td><td>" + getSize(totalIn) + "</td><td>" + getSize(totalOut) + "</td><td>" + getSize(totalIn + totalOut) + "</td><td></td><td></td></tr>");
|
||||
</script></table>
|
||||
<br /><small>This page was generated on (date)</small>
|
||||
</body></html>
|
50
wrtbwmon/Makefile
Normal file
50
wrtbwmon/Makefile
Normal file
@ -0,0 +1,50 @@
|
||||
#
|
||||
# Copyright (C) 2006-2011 Xmlad.com
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=wrtbwmon
|
||||
PKG_VERSION:=1.2.1
|
||||
PKG_RELEASE:=3
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Package/wrtbwmon
|
||||
SECTION:=net
|
||||
CATEGORY:=Network
|
||||
DEPENDS:=+iptables +@BUSYBOX_CONFIG_IP
|
||||
TITLE:=A Traffic Usage Monitor
|
||||
SUBMENU:=Tools
|
||||
PKGARCH:=all
|
||||
endef
|
||||
|
||||
define Package/wrtbwmon/description
|
||||
An CERNET client daemon,
|
||||
Most usually used in China collages.
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
endef
|
||||
|
||||
define Build/Configure
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/wrtbwmon/install
|
||||
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/wrtbwmon
|
||||
$(INSTALL_BIN) ./net/usr/sbin/* $(1)/usr/sbin/
|
||||
$(INSTALL_BIN) ./net/usr/share/wrtbwmon/* $(1)/usr/share/wrtbwmon/
|
||||
|
||||
$(INSTALL_DIR) $(1)/etc/config $(1)/etc/init.d $(1)/etc/hotplug.d/iface
|
||||
$(INSTALL_BIN) ./net/etc/init.d/wrtbwmon $(1)/etc/init.d/wrtbwmon
|
||||
$(INSTALL_BIN) ./net/etc/config/wrtbwmon $(1)/etc/config/wrtbwmon
|
||||
$(INSTALL_BIN) ./net/etc/hotplug.d/iface/99-wrtbwmon $(1)/etc/hotplug.d/iface/99-wrtbwmon
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,wrtbwmon))
|
5
wrtbwmon/net/etc/config/wrtbwmon
Normal file
5
wrtbwmon/net/etc/config/wrtbwmon
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
config wrtbwmon 'general'
|
||||
option enabled '1'
|
||||
option path '/tmp/usage.db'
|
||||
|
9
wrtbwmon/net/etc/hotplug.d/iface/99-wrtbwmon
Normal file
9
wrtbwmon/net/etc/hotplug.d/iface/99-wrtbwmon
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
[ "$ACTION" = ifup -o "$ACTION" = ifupdate ] || exit 0
|
||||
[ "$ACTION" = ifupdate -a -z "$IFUPDATE_ADDRESSES" -a -z "$IFUPDATE_DATA" ] && exit 0
|
||||
|
||||
/etc/init.d/wrtbwmon restart
|
||||
|
||||
logger -t wrtbwmon "Restart for $ACTION of $INTERFACE ($DEVICE)"
|
||||
|
44
wrtbwmon/net/etc/init.d/wrtbwmon
Normal file
44
wrtbwmon/net/etc/init.d/wrtbwmon
Normal file
@ -0,0 +1,44 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2019 OpenWrt.org
|
||||
|
||||
START=99
|
||||
USE_PROCD=1
|
||||
|
||||
NAME=wrtbwmon
|
||||
PID_FILE=/var/run/wrtbwmon.pid
|
||||
args=/usr/sbin/wrtbwmon
|
||||
|
||||
create_instance() {
|
||||
procd_open_instance
|
||||
procd_set_param command $args
|
||||
procd_set_param respawn
|
||||
procd_set_param user root
|
||||
# procd_set_param pidfile $PID_FILE
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
service_triggers()
|
||||
{
|
||||
procd_add_reload_trigger "$NAME"
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local db enabled
|
||||
config_load $NAME
|
||||
|
||||
config_get db general path
|
||||
[ -z "$db" ] && db="/tmp/usage.db"
|
||||
append args " -46"
|
||||
append args "-f $db"
|
||||
append args "-p /tmp/usage.htm"
|
||||
append args "-u /etc/wrtbwmon.user"
|
||||
append args "-d"
|
||||
|
||||
config_get enabled general enabled
|
||||
[ "$enabled"0 -eq 0 ] || create_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
procd_kill wrtbwmon
|
||||
kill -CONT $(cat $PID_FILE)
|
||||
}
|
213
wrtbwmon/net/usr/sbin/readDB.awk
Normal file
213
wrtbwmon/net/usr/sbin/readDB.awk
Normal file
@ -0,0 +1,213 @@
|
||||
#!/usr/bin/awk
|
||||
|
||||
function inInterfaces(host) {
|
||||
return(interfaces ~ "(^| )" host "($| )")
|
||||
}
|
||||
|
||||
function newRule(arp_ip, ipt_cmd) {
|
||||
# checking for existing rules shouldn't be necessary if newRule is
|
||||
# always called after db is read, arp table is read, and existing
|
||||
# iptables rules are read.
|
||||
ipt_cmd=iptKey " -t mangle -j RETURN -s " arp_ip
|
||||
system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD")
|
||||
ipt_cmd=iptKey " -t mangle -j RETURN -d " arp_ip
|
||||
system(ipt_cmd " -C RRDIPT_FORWARD 2>/dev/null || " ipt_cmd " -A RRDIPT_FORWARD")
|
||||
}
|
||||
|
||||
function delRule(arp_ip, ipt_cmd) {
|
||||
ipt_cmd=iptKey " -t mangle -D RRDIPT_FORWARD -j RETURN "
|
||||
system(ipt_cmd "-s " arp_ip " 2>/dev/null")
|
||||
system(ipt_cmd "-d " arp_ip " 2>/dev/null")
|
||||
}
|
||||
|
||||
function total(i) {
|
||||
return(bw[i "/in"] + bw[i "/out"])
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
if (ipv6) {
|
||||
iptNF = 8
|
||||
iptKey = "ip6tables"
|
||||
} else {
|
||||
iptNF = 9
|
||||
iptKey = "iptables"
|
||||
}
|
||||
}
|
||||
|
||||
/^#/ { # get DB filename
|
||||
FS = ","
|
||||
dbFile = FILENAME
|
||||
next
|
||||
}
|
||||
|
||||
# data from database; first file
|
||||
ARGIND==1 { #!@todo this doesn't help if the DB file is empty.
|
||||
lb=$1
|
||||
|
||||
if (lb !~ "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$") next
|
||||
|
||||
if (!(lb in mac)) {
|
||||
mac[lb] = $1
|
||||
ip[lb] = $2
|
||||
inter[lb] = $3
|
||||
speed[lb "/in"] = 0
|
||||
speed[lb "/out"]= 0
|
||||
bw[lb "/in"] = $6
|
||||
bw[lb "/out"] = $7
|
||||
firstDate[lb] = $9
|
||||
lastDate[lb] = $10
|
||||
ignore[lb] = 1
|
||||
} else {
|
||||
if ($9 < firstDate[lb])
|
||||
firstDate[lb] = $9
|
||||
if ($10 > lastDate[lb]) {
|
||||
ip[lb] = $2
|
||||
inter[lb] = $3
|
||||
lastDate[lb] = $10
|
||||
}
|
||||
bw[lb "/in"] += $6
|
||||
bw[lb "/out"] += $7
|
||||
ignore[lb] = 0
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
# not triggered on the first file
|
||||
FNR==1 {
|
||||
FS=" "
|
||||
if(ARGIND == 2) next
|
||||
}
|
||||
|
||||
# arp: ip hw flags hw_addr mask device
|
||||
ARGIND==2 {
|
||||
#!@todo regex match IPs and MACs for sanity
|
||||
if (ipv6) {
|
||||
statFlag= ($4 != "FAILED" && $4 != "INCOMPLETE")
|
||||
macAddr = $5
|
||||
hwIF = $3
|
||||
} else {
|
||||
statFlag= ($3 != "0x0")
|
||||
macAddr = $4
|
||||
hwIF = $6
|
||||
}
|
||||
|
||||
lb=$1
|
||||
if (hwIF != wanIF && statFlag && macAddr ~ "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$") {
|
||||
hosts[lb] = 1
|
||||
arp_mac[lb] = macAddr
|
||||
arp_ip[lb] = $1
|
||||
arp_inter[lb] = hwIF
|
||||
arp_bw[lb "/in"] = 0
|
||||
arp_bw[lb "/out"] = 0
|
||||
arp_firstDate[lb] = systime()
|
||||
arp_lastDate[lb] = arp_firstDate[lb]
|
||||
arp_ignore[lb] = 1
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
#!@todo could use mangle chain totals or tailing "unnact" rules to
|
||||
# account for data for new hosts from their first presence on the
|
||||
# network to rule creation. The "unnact" rules would have to be
|
||||
# maintained at the end of the list, and new rules would be inserted
|
||||
# at the top.
|
||||
ARGIND==3 && NF==iptNF && $1!="pkts" { # iptables input
|
||||
if (ipv6) {
|
||||
lfn = 5
|
||||
tag = "::/0"
|
||||
} else {
|
||||
lfn = 6
|
||||
tag = "0.0.0.0/0"
|
||||
}
|
||||
|
||||
if ($(lfn) != "*") {
|
||||
m = $(lfn)
|
||||
n = m "/in"
|
||||
} else if ($(++lfn) != "*") {
|
||||
m = $(lfn)
|
||||
n = m "/out"
|
||||
} else if ($(++lfn) != tag) {
|
||||
m = $(lfn)
|
||||
n = m "/out"
|
||||
} else { # $(++lfn) != tag
|
||||
m = $(++lfn)
|
||||
n = m "/in"
|
||||
}
|
||||
|
||||
if (mode == "diff" || mode == "noUpdate") print n, $2
|
||||
if (mode != "noUpdate") {
|
||||
if (inInterfaces(m)) { # if label is an interface
|
||||
if (!(m in arp_mac)) {
|
||||
cmd = "cat /sys/class/net/" m "/address"
|
||||
cmd | getline arp_mac[m]
|
||||
close(cmd)
|
||||
|
||||
if (length(arp_mac[m]) == 0) arp_mac[m] = "00:00:00:00:00:00"
|
||||
|
||||
arp_ip[m] = "NA"
|
||||
arp_inter[m] = m
|
||||
arp_bw[m "/in"] = 0
|
||||
arp_bw[m "/out"] = 0
|
||||
arp_firstDate[m] = systime()
|
||||
arp_lastDate[m] = arp_firstDate[m]
|
||||
arp_ignore[lb] = 1
|
||||
}
|
||||
} else {
|
||||
if (!(m in arp_mac)) hosts[m] = 0
|
||||
else delete hosts[m]
|
||||
}
|
||||
|
||||
if ($2 > 0) {
|
||||
arp_bw[n] = $2
|
||||
arp_lastDate[m] = systime()
|
||||
arp_ignore[m] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
if (mode == "noUpdate") exit
|
||||
|
||||
for (i in arp_ip) {
|
||||
lb = arp_mac[i]
|
||||
if (!arp_ignore[i] || !(lb in mac)) {
|
||||
ignore[lb] = 0
|
||||
|
||||
if (lb in mac) {
|
||||
bw[lb "/in"] += arp_bw[i "/in"]
|
||||
bw[lb "/out"] += arp_bw[i "/out"]
|
||||
lastDate[lb] = arp_lastDate[i]
|
||||
} else {
|
||||
bw[lb "/in"] = arp_bw[i "/in"]
|
||||
bw[lb "/out"] = arp_bw[i "/out"]
|
||||
firstDate[lb] = arp_firstDate[i]
|
||||
lastDate[lb] = arp_lastDate[i]
|
||||
}
|
||||
mac[lb] = arp_mac[i]
|
||||
ip[lb] = arp_ip[i]
|
||||
inter[lb] = arp_inter[i]
|
||||
|
||||
if (interval != 0) {
|
||||
speed[lb "/in"] = int(arp_bw[i "/in"] / interval)
|
||||
speed[lb "/out"]= int(arp_bw[i "/out"] / interval)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(dbFile)
|
||||
for (i in mac) {
|
||||
if (!ignore[i]) {
|
||||
print "#mac,ip,iface,speed_in,speed_out,in,out,total,first_date,last_date" > dbFile
|
||||
OFS=","
|
||||
for (i in mac)
|
||||
print mac[i], ip[i], inter[i], speed[i "/in"], speed[i "/out"], bw[i "/in"], bw[i "/out"], total(i), firstDate[i], lastDate[i] > dbFile
|
||||
close(dbFile)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# for hosts without rules
|
||||
for (i in hosts)
|
||||
if (hosts[i]) newRule(i)
|
||||
else delRule(i)
|
||||
}
|
460
wrtbwmon/net/usr/sbin/wrtbwmon
Normal file
460
wrtbwmon/net/usr/sbin/wrtbwmon
Normal file
@ -0,0 +1,460 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
|
||||
# Default input parameters for wrtbwmon.
|
||||
runMode=0
|
||||
Monitor46=4
|
||||
|
||||
# Some parameters for monitor process.
|
||||
for46=
|
||||
updatePID=
|
||||
logFile=/var/log/wrtbwmon.log
|
||||
lockFile=/var/lock/wrtbwmon.lock
|
||||
pidFile=/var/run/wrtbwmon.pid
|
||||
tmpDir=/var/tmp/wrtbwmon
|
||||
interval4=0
|
||||
interval6=0
|
||||
|
||||
# Debug parameters for readDB.awk.
|
||||
mode=
|
||||
DEBUG=
|
||||
|
||||
# Constant parameter for wrtbwmon.
|
||||
binDir=/usr/sbin
|
||||
dataDir=/usr/share/wrtbwmon
|
||||
|
||||
networkFuncs=/lib/functions/network.sh
|
||||
uci=`which uci 2>/dev/null`
|
||||
nslookup=`which nslookup 2>/dev/null`
|
||||
nvram=`which nvram 2>/dev/null`
|
||||
|
||||
chains='INPUT OUTPUT FORWARD'
|
||||
interfaces='eth0 tun0 br-lan' # in addition to detected WAN
|
||||
|
||||
# DNS server for reverse lookups provided in "DNS".
|
||||
# don't perform reverse DNS lookups by default
|
||||
DO_RDNS=${DNS-}
|
||||
|
||||
header="#mac,ip,iface,speed_in,speed_out,in,out,total,first_date,last_date"
|
||||
|
||||
createDbIfMissing() {
|
||||
[ ! -f "$DB" ] && echo $header > "$DB"
|
||||
[ ! -f "$DB6" ] && echo $header > "$DB6"
|
||||
}
|
||||
|
||||
checkDbArg() {
|
||||
[ -z "$DB" ] && echo "ERROR: Missing argument 2 (database file)" && exit 1
|
||||
}
|
||||
|
||||
checkDB() {
|
||||
[ ! -f "$DB" ] && echo "ERROR: $DB does not exist" && exit 1
|
||||
[ ! -w "$DB" ] && echo "ERROR: $DB is not writable" && exit 1
|
||||
[ ! -f "$DB6" ] && echo "ERROR: $DB6 does not exist" && exit 1
|
||||
[ ! -w "$DB6" ] && echo "ERROR: $DB6 is not writable" && exit 1
|
||||
}
|
||||
|
||||
checkWAN() {
|
||||
[ -z "$1" ] && echo "Warning: failed to detect WAN interface."
|
||||
}
|
||||
|
||||
lookup() {
|
||||
local MAC=$1
|
||||
local IP=$2
|
||||
local userDB=$3
|
||||
local USERSFILE=
|
||||
local USER=
|
||||
for USERSFILE in $userDB /tmp/dhcp.leases /tmp/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do
|
||||
[ -e "$USERSFILE" ] || continue
|
||||
|
||||
case $USERSFILE in
|
||||
/tmp/dhcp.leases )
|
||||
USER=$(grep -i "$MAC" $USERSFILE | cut -f4 -s -d' ')
|
||||
;;
|
||||
/etc/hosts )
|
||||
USER=$(grep "^$IP " $USERSFILE | cut -f2 -s -d' ')
|
||||
;;
|
||||
* )
|
||||
USER=$(grep -i "$MAC" "$USERSFILE" | cut -f2 -s -d,)
|
||||
;;
|
||||
esac
|
||||
|
||||
[ "$USER" = "*" ] && USER=
|
||||
[ -n "$USER" ] && break
|
||||
|
||||
done
|
||||
|
||||
if [ -n "$DO_RDNS" -a -z "$USER" -a "$IP" != "NA" -a -n "$nslookup" ]; then
|
||||
USER=`$nslookup $IP $DNS | awk '!/server can/{if($4){print $4; exit}}' | sed -re 's/[.]$//'`
|
||||
fi
|
||||
|
||||
[ -z "$USER" ] && USER=${MAC}
|
||||
echo $USER
|
||||
}
|
||||
|
||||
detectIF() {
|
||||
local IF=
|
||||
if [ -f "$networkFuncs" ]; then
|
||||
IF=`. $networkFuncs; network_get_device netdev $1; echo $netdev`
|
||||
[ -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
|
||||
if [ -n "$uci" -a -x "$uci" ]; then
|
||||
IF=`$uci get network.${1}.ifname 2>/dev/null`
|
||||
[ $? -eq 0 -a -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
|
||||
if [ -n "$nvram" -a -x "$nvram" ]; then
|
||||
IF=`$nvram get ${1}_ifname 2>/dev/null`
|
||||
[ $? -eq 0 -a -n "$IF" ] && echo $IF && return
|
||||
fi
|
||||
}
|
||||
|
||||
detectLAN() {
|
||||
[ -e /sys/class/net/br-lan ] && echo br-lan && return
|
||||
local lan=$(detectIF lan)
|
||||
[ -n "$lan" ] && echo $lan && return
|
||||
}
|
||||
|
||||
detectWAN() {
|
||||
local wan=$(detectIF wan)
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
wan=$(ip route show 2>/dev/null | grep default | sed -re '/^default/ s/default.*dev +([^ ]+).*/\1/')
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
[ -f "$networkFuncs" ] && wan=$(. $networkFuncs; network_find_wan wan; echo $wan)
|
||||
[ -n "$wan" ] && echo $wan && return
|
||||
}
|
||||
|
||||
lockFunc() {
|
||||
#Realize the lock function by busybox lock or flock command.
|
||||
# if !(lock -n $lockFile) >/dev/null 2>&1; then
|
||||
# exit 1
|
||||
# fi
|
||||
#The following lock method is realized by other's function.
|
||||
|
||||
local attempts=0
|
||||
local flag=0
|
||||
|
||||
while [ "$flag" = 0 ]; do
|
||||
local tempfile=$(mktemp $tmpDir/lock.XXXXXX)
|
||||
ln $tempfile $lockFile >/dev/null 2>&1 && flag=1
|
||||
rm $tempfile
|
||||
|
||||
if [ "$flag" = 1 ]; then
|
||||
[ -n "$DEBUG" ] && echo ${updatePID} "got lock after $attempts attempts"
|
||||
flag=1
|
||||
else
|
||||
sleep 1
|
||||
attempts=$(($attempts+1))
|
||||
[ -n "$DEBUG" ] && echo ${updatePID} "The $attempts attempts."
|
||||
[ "$attempts" -ge 10 ] && exit
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
unlockFunc() {
|
||||
#Realize the lock function by busybox lock or flock command.
|
||||
# lock -u $lockFile
|
||||
# rm -f $lockFile
|
||||
# [ -n "$DEBUG" ] && echo ${updatePID} "released lock"
|
||||
#The following lock method is realized by other's function.
|
||||
|
||||
rm -f $lockFile
|
||||
[ -n "$DEBUG" ] && echo ${updatePID} "released lock"
|
||||
}
|
||||
|
||||
# chain
|
||||
newChain() {
|
||||
local chain=$1
|
||||
local ipt=$2
|
||||
# Create the RRDIPT_$chain chain (it doesn't matter if it already exists).
|
||||
|
||||
$ipt -t mangle -N RRDIPT_$chain 2> /dev/null
|
||||
|
||||
# Add the RRDIPT_$chain CHAIN to the $chain chain if not present
|
||||
$ipt -t mangle -C $chain -j RRDIPT_$chain 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
[ -n "$DEBUG" ] && echo "DEBUG: $ipt chain misplaced, recreating it..."
|
||||
$ipt -t mangle -I $chain -j RRDIPT_$chain
|
||||
fi
|
||||
}
|
||||
|
||||
# chain tun
|
||||
newRuleIF() {
|
||||
local chain=$1
|
||||
local IF=$2
|
||||
local ipt=$3
|
||||
local cmd=
|
||||
|
||||
if [ "$chain" = "OUTPUT" ]; then
|
||||
cmd="$ipt -t mangle -o $IF -j RETURN"
|
||||
elif [ "$chain" = "INPUT" ]; then
|
||||
cmd="$ipt -t mangle -i $IF -j RETURN"
|
||||
fi
|
||||
[ -n "$cmd" ] && eval $cmd " -C RRDIPT_$chain 2>/dev/null" || eval $cmd " -A RRDIPT_$chain"
|
||||
}
|
||||
|
||||
publish() {
|
||||
# sort DB
|
||||
# busybox sort truncates numbers to 32 bits
|
||||
grep -v '^#' $DB | awk -F, '{OFS=","; a=sprintf("%f",$6/1e6); $6=""; print a,$0}' | tr -s ',' | sort -rn | awk -F, '{OFS=",";$1=sprintf("%f",$1*1e6);print}' > $tmpDir/sorted_${updatePID}.tmp
|
||||
|
||||
# create HTML page
|
||||
local htmPage="$tmpDir/${pb_html##*/}"
|
||||
rm -f $htmPage
|
||||
cp $dataDir/usage.htm1 $htmPage
|
||||
|
||||
while IFS=, read PEAKUSAGE_IN MAC IP IFACE SPEED_IN SPEED_OUT PEAKUSAGE_OUT TOTAL FIRSTSEEN LASTSEEN
|
||||
do
|
||||
echo "
|
||||
new Array(\"$(lookup $MAC $IP $user_def)\",\"$MAC\",\"$IP\",$SPEED_IN,$SPEED_OUT,
|
||||
$PEAKUSAGE_IN,$PEAKUSAGE_OUT,$TOTAL,\"$FIRSTSEEN\",\"$LASTSEEN\")," >> $htmPage
|
||||
done < $tmpDir/sorted_${updatePID}.tmp
|
||||
echo "0);" >> $htmPage
|
||||
|
||||
sed "s/(date)/`date`/" < $dataDir/usage.htm2 >> $htmPage
|
||||
mv $htmPage "$pb_html"
|
||||
}
|
||||
|
||||
updatePrepare() {
|
||||
checkDbArg
|
||||
createDbIfMissing
|
||||
checkDB
|
||||
[ -e $tmpDir ] || mkdir -p $tmpDir
|
||||
|
||||
for46="$Monitor46"
|
||||
local timeNow=$(cat /proc/uptime | awk '{print $1}')
|
||||
|
||||
if [ -e "$logFile" ]; then
|
||||
local timeLast4=$(awk -F'[: ]+' '/ipv4/{print $2}' "$logFile")
|
||||
local timeLast6=$(awk -F'[: ]+' '/ipv6/{print $2}' "$logFile")
|
||||
interval4=$(awk -v now=$timeNow -v last=$timeLast4 'BEGIN{print (now-last)}');
|
||||
interval6=$(awk -v now=$timeNow -v last=$timeLast6 'BEGIN{print (now-last)}');
|
||||
|
||||
for ii in 4 6; do
|
||||
[[ -n "$(echo $for46 | grep ${ii})" ]] && {
|
||||
if [[ "$(eval echo \$interval${ii})" \> "0.9" ]]; then
|
||||
sed -i "s/^ipv${ii}: [0-9\.]\{1,\}/ipv${ii}: $timeNow/ig" "$logFile"
|
||||
else
|
||||
for46=`echo "$for46" | sed "s/${ii}//g"`
|
||||
fi
|
||||
}
|
||||
done
|
||||
else
|
||||
echo -e "ipv4: $timeNow\nipv6: $timeNow" >"$logFile"
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
update() {
|
||||
updatePID=$( sh -c 'echo $PPID' )
|
||||
|
||||
lockFunc
|
||||
|
||||
local wan=$(detectWAN)
|
||||
checkWAN $wan
|
||||
interfaces="$interfaces $wan"
|
||||
|
||||
[ "$for46" = 4 ] && IPT='iptables'
|
||||
[ "$for46" = 6 ] && IPT='ip6tables'
|
||||
[ "$for46" = 46 ] && IPT='iptables ip6tables'
|
||||
|
||||
for ii in $IPT ; do
|
||||
if [ -z "$( ${ii}-save | grep RRDIPT )" ]; then
|
||||
|
||||
for chain in $chains; do
|
||||
newChain $chain $ii
|
||||
done
|
||||
|
||||
# track local data
|
||||
for chain in INPUT OUTPUT; do
|
||||
for interface in $interfaces; do
|
||||
[ -n "$interface" ] && [ -e "/sys/class/net/$interface" ] && newRuleIF $chain $interface $ii
|
||||
done
|
||||
done
|
||||
fi
|
||||
# this will add rules for hosts in arp table
|
||||
> $tmpDir/${ii}_${updatePID}.tmp
|
||||
|
||||
for chain in $chains; do
|
||||
$ii -nvxL RRDIPT_$chain -t mangle -Z >> $tmpDir/${ii}_${updatePID}.tmp
|
||||
done
|
||||
done
|
||||
|
||||
[ -f $tmpDir/iptables_${updatePID}.tmp ] && (
|
||||
awk -v mode="$mode" -v interfaces="$interfaces" -v wanIF="$wan" -v interval=$interval4 \
|
||||
-v ipv6="0" -f $binDir/readDB.awk \
|
||||
$DB \
|
||||
/proc/net/arp \
|
||||
$tmpDir/iptables_${updatePID}.tmp
|
||||
)
|
||||
|
||||
[ -f $tmpDir/ip6tables_${updatePID}.tmp ] && (
|
||||
echo "This file is geneated by 'ip -6 neigh'" > $tmpDir/ip6addr_${updatePID}.tmp
|
||||
`ip -6 neigh >> $tmpDir/ip6addr_${updatePID}.tmp`;
|
||||
|
||||
awk -v mode="$mode" -v interfaces="$interfaces" -v wanIF="$wan" -v interval=$interval6 \
|
||||
-v ipv6="1" -f $binDir/readDB.awk \
|
||||
"$DB6" \
|
||||
$tmpDir/ip6addr_${updatePID}.tmp \
|
||||
$tmpDir/ip6tables_${updatePID}.tmp
|
||||
)
|
||||
|
||||
[ "$Monitor46" = 46 ] && (
|
||||
cp $DB $DB46
|
||||
cat $DB6 >> $DB46
|
||||
awk -f $binDir/readDB.awk "$DB46"
|
||||
)
|
||||
|
||||
[ -n "$pb_html" ] && publish
|
||||
|
||||
rm -f $tmpDir/*_${updatePID}.tmp
|
||||
unlockFunc
|
||||
}
|
||||
|
||||
renamefile() {
|
||||
local base=$(basename -- "$1")
|
||||
local ext=$([ -z "${base/*.*/}" ] && echo ".${base##*.}" || echo '')
|
||||
local base="${base%.*}"
|
||||
echo "$(dirname $1)/${base}$2$ext" && return
|
||||
}
|
||||
|
||||
ending() {
|
||||
iptables-save | grep -v RRDIPT | iptables-restore
|
||||
ip6tables-save | grep -v RRDIPT | ip6tables-restore
|
||||
|
||||
if checkPid $pidFile; then
|
||||
local pid=$( cat $pidFile )
|
||||
rm -rf $lockFile $logFile $pidFile $tmpDir/*
|
||||
kill -9 $pid >> /dev/null 2>&1
|
||||
fi
|
||||
echo "exit!!"
|
||||
}
|
||||
|
||||
checkPid() {
|
||||
[ -e "$1" ] && local pid=$(cat $1) || return 1
|
||||
[ -d "/proc/$pid" ] && {
|
||||
[ -n "$( cat /proc/$pid/cmdline | grep wrtbwmon )" ] && return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
sleepProcess() {
|
||||
sleep 1m
|
||||
kill -CONT $1 >>/dev/null 2>&1
|
||||
}
|
||||
|
||||
loop() {
|
||||
trap 'ending' INT TERM HUP QUIT
|
||||
if checkPid $pidFile; then
|
||||
echo "Another wrtbwmon is on running!!!"
|
||||
else
|
||||
local loopPID=$( sh -c 'echo $PPID' )
|
||||
local SPID=
|
||||
echo $loopPID > $pidFile
|
||||
while true ;do
|
||||
[ -n "$SPID" ] && kill -9 $SPID >>/dev/null 2>&1
|
||||
sleepProcess $loopPID &
|
||||
SPID=$!
|
||||
updatePrepare && update
|
||||
kill -STOP $loopPID >>/dev/null 2>&1
|
||||
done
|
||||
fi
|
||||
trap INT TERM HUP QUIT
|
||||
}
|
||||
|
||||
tips() {
|
||||
echo \
|
||||
"Usage: $0 [options...]
|
||||
Options:
|
||||
-k Exit the wrtbwmon!
|
||||
-f dbfile Set the DB file path
|
||||
-u usrfile Set the user_def file path
|
||||
-p htmlfile Set the publish htm file path
|
||||
-d Enter the foreground mode.
|
||||
-D Enter the daemo mode.
|
||||
-4 Listen to ipv4 only.
|
||||
-6 Listen to ipv6 only.
|
||||
-46 Listen to ipv4 and ipv6.
|
||||
|
||||
Note: [user_file] is an optional file to match users with MAC addresses.
|
||||
Its format is \"00:MA:CA:DD:RE:SS,username\", with one entry per line."
|
||||
}
|
||||
|
||||
############################################################
|
||||
|
||||
while [ $# != 0 ];do
|
||||
case $1 in
|
||||
"-k" )
|
||||
/etc/init.d/wrtbwmon stop
|
||||
exit 0
|
||||
;;
|
||||
"-f" )
|
||||
shift
|
||||
if [ $# -gt 0 ];then
|
||||
DB=$1
|
||||
DB6="$(renamefile $DB .6)"
|
||||
DB46="$(renamefile $DB .46)"
|
||||
else
|
||||
echo "No db file path seted, exit!!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"-u")
|
||||
shift
|
||||
if [ $# -gt 0 ];then
|
||||
user_def=$1
|
||||
else
|
||||
echo "No user define file path seted, exit!!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
"-p")
|
||||
shift
|
||||
if [ $# -gt 0 ];then
|
||||
pb_html=$1
|
||||
else
|
||||
echo "No publish html file path seted, exit!!"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
"-d")
|
||||
runMode=1
|
||||
;;
|
||||
|
||||
"-D")
|
||||
runMode=2
|
||||
;;
|
||||
|
||||
"-4")
|
||||
Monitor46=4
|
||||
;;
|
||||
|
||||
"-6")
|
||||
Monitor46=6
|
||||
;;
|
||||
|
||||
"-46")
|
||||
Monitor46=46
|
||||
;;
|
||||
|
||||
"&&" | "||" | ";")
|
||||
break
|
||||
;;
|
||||
|
||||
"*")
|
||||
tips
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$runMode" = '1' ]; then
|
||||
loop
|
||||
elif [ "$runMode" = '2' ]; then
|
||||
loop >>/dev/null 2>&1 &
|
||||
else
|
||||
updatePrepare && update
|
||||
fi
|
34
wrtbwmon/net/usr/share/wrtbwmon/usage.htm1
Normal file
34
wrtbwmon/net/usr/share/wrtbwmon/usage.htm1
Normal file
@ -0,0 +1,34 @@
|
||||
<html><head><title>Traffic</title>
|
||||
<script type="text/javascript">
|
||||
function getSize(size) {
|
||||
if (size === 0) return '0 ';
|
||||
var prefix=["","k","M","G","T","P","E","Z"];
|
||||
var base=1024, precision = 1;
|
||||
var pos=Math.floor(Math.log(size)/Math.log(base));
|
||||
if (pos > 2) precision=100;
|
||||
return (Math.round(size/Math.pow(base,pos)*precision)/precision)+' '+prefix[pos];
|
||||
}
|
||||
function padstr(str) {
|
||||
return str < 10 ? '0' + str : str;
|
||||
}
|
||||
function dateToString(date) {
|
||||
var d = new Date((/\W/g).test(date) ? date : date * 1000);
|
||||
var Y = d.getFullYear(), M = d.getMonth(), D = d.getDate();
|
||||
var hh = d.getHours(), mm = d.getMinutes(), ss = d.getSeconds();
|
||||
return Y + '/' + padstr(M) + '/' + padstr(D) + ' ' + padstr(hh) + ':' + padstr(mm) + ':' + padstr(ss);
|
||||
}
|
||||
</script></head>
|
||||
<body><h1>Total Usage:</h1>
|
||||
<table border="1">
|
||||
<tr bgcolor=silver>
|
||||
<th>User</th>
|
||||
<th>Down Speed</th>
|
||||
<th>Up Speed</th>
|
||||
<th>Download</th>
|
||||
<th>Upload</th>
|
||||
<th>Total</th>
|
||||
<th>First seen</th>
|
||||
<th>Last seen</th>
|
||||
</tr>
|
||||
<script type="text/javascript">
|
||||
var values = new Array(
|
18
wrtbwmon/net/usr/share/wrtbwmon/usage.htm2
Normal file
18
wrtbwmon/net/usr/share/wrtbwmon/usage.htm2
Normal file
@ -0,0 +1,18 @@
|
||||
var speedIn = 0;
|
||||
var speedOut = 0;
|
||||
var totalIn = 0;
|
||||
var totalOut = 0;
|
||||
for (i=0; i < values.length-1; i++) {
|
||||
speedIn += values[i][3];
|
||||
speedOut += values[i][4]
|
||||
totalIn += values[i][5];
|
||||
totalOut += values[i][6];
|
||||
document.write("<tr><td><div title=\"" + values[i][1] + " (" + values[i][2] + ")" + "\">" + values[i][0] + "</div></td>");
|
||||
for (j=3; j < 8; j++)
|
||||
document.write("<td>" + getSize(values[i][j]) + ((j == 3) || (j ==4) ? 'B/s' : 'B') + "</td>");
|
||||
document.write("<td>" + dateToString(values[i][8]) + "</td><td>" + dateToString(values[i][9]) + "</td></tr>");
|
||||
}
|
||||
document.write("<tr><td>TOTAL</td><td>" + getSize(speedIn) + "B/s" + "</td><td>" + getSize(speedOut) + "B/s" + "</td><td>" + getSize(totalIn) + "</td><td>" + getSize(totalOut) + "</td><td>" + getSize(totalIn + totalOut) + "</td><td></td><td></td></tr>");
|
||||
</script></table>
|
||||
<br /><small>This page was generated on (date)</small>
|
||||
</body></html>
|
Loading…
Reference in New Issue
Block a user