luci-app-serverchan: sync with upstream source
This commit is contained in:
parent
8ce2f7c59f
commit
a472c47065
@ -207,10 +207,10 @@ fi
|
||||
|
||||
# 流量数据
|
||||
function usage(){
|
||||
if [ -f "/usr/bin/serverchan/wrtbwmon/wrtbwmon" ] && [ -f "/usr/bin/serverchan/wrtbwmon/readDB.awk" ] ; then
|
||||
/usr/bin/serverchan/wrtbwmon/wrtbwmon update ${dir}usage.db
|
||||
if [ -f "/usr/sbin/wrtbwmon" ] && [ -f "/etc/init.d/wrtbwmon" ] ; then
|
||||
wrtbwmon update ${dir}usage.db
|
||||
else
|
||||
echo "`date "+%H:%M:%S"` 【!!!】流量数据文件缺失" >> ${logfile}
|
||||
if [ ! -z "$debuglevel" ] && [ "$debuglevel" -ne "1" ] ; then echo "`date "+%H:%M:%S"` 【!!!】未安装 wrtbwmon ,流量统计不可用" >> ${logfile};fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@ -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,302 +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
|
||||
# 提取自 luci-app-wrtbwmon
|
||||
|
||||
trap "rm -f /tmp/serverchan/*_$$.tmp; kill $$" INT
|
||||
binDir=/usr/bin/serverchan/wrtbwmon
|
||||
dataDir=/tmp/serverchan
|
||||
lockDir=/tmp/serverchan/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."
|
||||
}
|
||||
|
||||
lookup()
|
||||
{
|
||||
MAC=$1
|
||||
IP=$2
|
||||
userDB=$3
|
||||
for USERSFILE in $userDB /tmp/serverchan/dhcp.leases /tmp/serverchan/dnsmasq.conf /etc/dnsmasq.conf /etc/hosts; do
|
||||
[ -e "$USERSFILE" ] || continue
|
||||
case $USERSFILE in
|
||||
/tmp/serverchan/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/serverchan/*_$$.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
|
||||
|
||||
checkDB
|
||||
checkWAN
|
||||
|
||||
> /tmp/serverchan/iptables_$$.tmp
|
||||
lock
|
||||
# only zero our own chains
|
||||
for chain in $chains; do
|
||||
iptables -nvxL RRDIPT_$chain -t mangle -Z >> /tmp/serverchan/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/serverchan/iptables_$$.tmp
|
||||
unlock
|
||||
}
|
||||
|
||||
############################################################
|
||||
|
||||
case $1 in
|
||||
"dump" )
|
||||
checkDbArg
|
||||
lock
|
||||
tr ',' '\t' < "$DB"
|
||||
unlock
|
||||
;;
|
||||
|
||||
"update" )
|
||||
checkDbArg
|
||||
wan=$(detectWAN)
|
||||
interfaces="$interfaces $wan"
|
||||
update
|
||||
rm -f /tmp/serverchan/*_$$.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/serverchan/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/serverchan/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/serverchan/*_$$.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/serverchan/*_$$.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/serverchan/usage.db
|
||||
$0 update /tmp/serverchan/usage.db
|
||||
$0 publish /tmp/serverchan/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
|
||||
Loading…
Reference in New Issue
Block a user