Full Code of pyrovski/wrtbwmon for AI

master bdf0350788f9 cached
21 files
20.5 KB
7.2k tokens
1 requests
Download .txt
Repository: pyrovski/wrtbwmon
Branch: master
Commit: bdf0350788f9
Files: 21
Total size: 20.5 KB

Directory structure:
gitextract_s1bbjk0u/

├── .gitignore
├── README.md
├── changelog
├── control
├── copyright
├── debian/
│   ├── .gitignore
│   ├── compat
│   ├── control
│   ├── install
│   └── rules
├── fileMap
├── init/
│   └── wrtbwmon
├── install.sh
├── makefile
├── postinst
├── readDB.awk
├── release-notes
├── todo
├── usage.htm1
├── usage.htm2
└── wrtbwmon

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
*.db
*.htm
*.log
*.old
*~
.RData
\#*
old
TAGS
*.tgz
*.ipk
.gawk*


================================================
FILE: README.md
================================================
# wrtbwmon
Modified from https://code.google.com/p/wrtbwmon/.

## Testers needed for IPv6 support
Experimental release: https://github.com/pyrovski/wrtbwmon/releases/tag/0.37_ipv6

## Features
 - "User" column has mouseover text containing MAC and IP addresses
 - "First seen" and "Total" columns in usage table
 - Monitoring of locally generated traffic on a per-interface basis
 - `remove` function to delete `iptables` rules

### What does it do?
`wrtbwmon` was designed to track bandwidth consumption on home routers. 
It accomplishes this with `iptables` rules, which means you don't need to run an extra process just to track bandwidth. 
`wrtbwmon` conveniently tracks bandwidth consumption on a per-IP address basis, 
so you can easily determine which user/device is the culprit.

Here is an example usage table:
![image](example.png)

### How do I use it?
- Install: Download and install ipk from the [releases page](https://github.com/pyrovski/wrtbwmon/releases/)
- Setup: `wrtbwmon setup`
- Update table: `wrtbwmon update /tmp/usage.db` (you can place the data table anywhere)
- Create html page: `wrtbwmon publish /tmp/usage.db /tmp/usage.htm`
- Dump table to terminal: `wrtbwmon dump /tmp/usage.db`
- Remove: `wrtbwmon remove`

### Installation options
- Install ipk
  - e.g.,: 
    - `cd /tmp`
    - HTTPS: `curl -LO https://github.com/pyrovski/wrtbwmon/releases/download/0.36/wrtbwmon_0.36_all.ipk`
    - HTTP: you're on your own :( Busybox wget usually doesn't have SSL support.
    - OpenWrt: `opkg install /tmp/wrtbwmon_0.36_all.ipk`
- Install deb from [the releases page](https://github.com/pyrovski/wrtbwmon/releases)
- Or, if you don't want to use an ipk or a deb:
  - `cd /tmp`
  - HTTPS: `curl -L https://github.com/pyrovski/wrtbwmon/archive/0.36.tar.gz | tar xvz`
  - `cd wrtbwmon-0.36`
  - `./install.sh wrtbwmon readDB.awk usage.htm1 usage.htm2 wrtbwmon`
    - Currently, this depends on the `install` program. OpenWrt chose to provide this as the "coreutils-install" package.
- Or, if you have `make`, just `make install` as root after cloning/unpacking.

### Configuring the published table
- `wrtbwmon` checks a few files for MAC -> name maps:
  - 4th argument to `wrtbwmon publish <DB> <userDB>`
  - `/tmp/dhcp.leases`
  - `/tmp/dnsmasq.conf`
  - `/etc/dnsmasq.conf`
  - `/etc/hosts`
- If all of the above do not yield a match, the script will optionally perform a reverse DNS lookup directed at the DNS server specified in the `DNS` variable. If `DNS` is blank or unset, the script will not perform such lookups.

### Regular updates
- Add the following to root's crontab:

        # adapt PATH to your needs
        PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
	
        * * * * * <script location> update /tmp/usage.db
        0 * * * * <script location> publish /tmp/usage.db /tmp/usage.htm

- On OpenWRT you need to [enable cron](https://wiki.openwrt.org/doc/howto/cron#activating_cron) as it is disabled by default:

        /etc/init.d/cron start
        /etc/init.d/cron enable

- Enable web serving of the generated page (optional)
  This varies by environment, but for lighttpd:
         
        ln -s /tmp/usage.htm /var/www/html/

### Remove `iptables` rules
 - `wrtbwmon remove`


================================================
FILE: changelog
================================================
wrtbwmon (0.36) UNRELEASED; urgency=medium

  * Packaging changes: remove .sh extension from init script, use 'tar' for final packing step.

 -- Peter Bailey <peter.eldridge.bailey@gmail.com>  Sun, 15 Jan 2017 19:16:40 -0800

wrtbwmon (0.35) unstable; urgency=low

  * Added deb package, changed back to wrtbwmon from wrtbwmon.sh

 -- Peter Bailey <peter.eldridge.bailey@gmail.com>  Sun, 20 Nov 2016 00:58:09 -0800

wrtbwmon (0.34) unstable; urgency=low

  * Added ipk and install targets with default paths for scripts and resources.

 -- Peter Bailey <peter.eldridge.bailey@gmail.com>  Fri, 19 Feb 2016 00:00:00 -0800


================================================
FILE: control
================================================
Package: wrtbwmon
Version: 0.36
Architecture: all
Maintainer: Peter Bailey <peter.eldridge.bailey+wrtbwmon@gmail.com>
Section: net
Priority: optional
Description: wrtbwmon was designed to track bandwidth consumption on home routers. It accomplishes this with iptables rules, which means you don't need to run an extra process just to track bandwidth. wrtbwmon conveniently tracks bandwidth consumption on a per-IP address basis, so you can easily determine which user/device is the culprit.
Source: https://github.com/pyrovski/wrtbwmon
#Depends: gawk | mawk | busybox, iptables, sed | busybox, iproute2 | ip


================================================
FILE: copyright
================================================
wrtbwmon
Copyright (C) 2016 Peter Bailey

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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.


================================================
FILE: debian/.gitignore
================================================
debhelper*
files
wrtbwmon*


================================================
FILE: debian/compat
================================================
9


================================================
FILE: debian/control
================================================
Source: wrtbwmon
Maintainer: Peter Bailey <peter.eldridge.bailey@gmail.com>
Section: net
Priority: optional
Standards-Version: 3.9.7
Build-Depends: debhelper (>= 9)

Package: wrtbwmon
Architecture: all
Depends: iproute2 | iproute, iptables, ${shlibs:Depends}, ${misc:Depends}, 
Description: iptables-based bandwidth monitor
 wrtbwmon was designed to track bandwidth consumption on home
 routers. It accomplishes this with iptables rules, which means you
 don't need to run an extra process just to track bandwidth. wrtbwmon
 conveniently tracks bandwidth consumption on a per-IP address basis,
 so you can easily determine which user/device is the culprit.


================================================
FILE: debian/install
================================================
# TODO: share this between makefile/ipk/deb
wrtbwmon /usr/sbin
readDB.awk /usr/sbin
usage.htm1 /usr/share/wrtbwmon
usage.htm2 /usr/share/wrtbwmon
init/wrtbwmon /etc/init.d


================================================
FILE: debian/rules
================================================
#!/usr/bin/make -f
%:
	dh $@


================================================
FILE: fileMap
================================================
usr/sbin: wrtbwmon readDB.awk
usr/share/wrtbwmon: usage.htm1 usage.htm2
CONTROL: control postinst
etc/init.d: init/wrtbwmon


================================================
FILE: init/wrtbwmon
================================================
#!/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
}


================================================
FILE: install.sh
================================================
do_copy() {
    local dest perm file
    for file in $*; do
	dest=`egrep ".+ $file( |$)" ./fileMap | cut -d':' -f1`
	mkdir -p $DESTDIR/$dest
	if [ -n `echo $dest | egrep '/s*bin$'` ]; then
    	    perm=0744
	else
    	    perm=0644
	fi
	install -m $perm -t $DESTDIR/$dest/ $file
    done
}

base=`basename $0`
if [ "$base" = "mkipk.sh" ]; then
    DESTDIR=$(mktemp -d)
    do_copy $*
    fakeroot -- ipkg-build -c $DESTDIR
    rm -rf $DESTDIR
else
    DESTDIR=${DESTDIR:-"/"}
    do_copy $*
fi


================================================
FILE: makefile
================================================
DESTDIR?=/
install-files=$(shell grep -v CONTROL fileMap  | cut -d: -f2- | tr -d '\n')
ipk-files=$(shell grep CONTROL fileMap | cut -d: -f2-)
version:=$(shell egrep '^Version:' ./control | awk '{print $$2}')
target=wrtbwmon_$(version)_all.ipk

all: $(target)

$(target): $(install-files) $(ipk-files)
	./mkipk.sh $^

install: $(install-files)
	./install.sh $^

deb:
	gbp buildpackage -Pdebian --git-ignore-new

clean:
	rm -f *.ipk

.PHONY: deb install clean

.SUFFIXES:


================================================
FILE: postinst
================================================
#!/bin/sh

# Enable on boot
/etc/init.d/wrtbwmon enable

# Configure our cron
if [ -d "/etc/crontabs" ]; then
  echo "PATH=/usr/sbin:/usr/bin:/sbin:/bin" > /etc/crontabs/wrtbwmon
  echo "* * * * * /usr/sbin/wrtbwmon update /tmp/usage.db" >> /etc/crontabs/wrtbwmon
  echo "0 * * * * /usr/sbin/wrtbwmon publish /tmp/usage.db /tmp/usage.htm" >> /etc/crontabs/wrtbwmon
fi
/etc/init.d/cron reload

# Symlink to our webdir
if [ -d "/var/www/html" ]; then
  ln -s /tmp/usage.htm /var/www/html/usage.htm
elif [ -d "/www" ]; then
 ln -s /tmp/usage.htm /www/usage.htm
fi

exit 0


================================================
FILE: readDB.awk
================================================
#!/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)
}


================================================
FILE: release-notes
================================================
- transition from invocation as "wrtbwmon.sh" back to "wrtbwmon"
- update readme
- add ipk
- install files according a standard filesystem layout
- remove peak/offpeak distinction
- add init script
- perform reverse DNS lookups to find hostnames
- fix locking issues
- add "dump" option


================================================
FILE: todo
================================================
- add logger
- cache DNS results
- use a config file
- check for existence of tool dependencies before using them
- fix DNS reverse lookups for systems without nslookup
- add tests


================================================
FILE: usage.htm1
================================================
<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(


================================================
FILE: usage.htm2
================================================
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>


================================================
FILE: wrtbwmon
================================================
#!/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."
}

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
    
    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
Download .txt
gitextract_s1bbjk0u/

├── .gitignore
├── README.md
├── changelog
├── control
├── copyright
├── debian/
│   ├── .gitignore
│   ├── compat
│   ├── control
│   ├── install
│   └── rules
├── fileMap
├── init/
│   └── wrtbwmon
├── install.sh
├── makefile
├── postinst
├── readDB.awk
├── release-notes
├── todo
├── usage.htm1
├── usage.htm2
└── wrtbwmon
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (23K chars).
[
  {
    "path": ".gitignore",
    "chars": 65,
    "preview": "*.db\n*.htm\n*.log\n*.old\n*~\n.RData\n\\#*\nold\nTAGS\n*.tgz\n*.ipk\n.gawk*\n"
  },
  {
    "path": "README.md",
    "chars": 3243,
    "preview": "# wrtbwmon\nModified from https://code.google.com/p/wrtbwmon/.\n\n## Testers needed for IPv6 support\nExperimental release: "
  },
  {
    "path": "changelog",
    "chars": 620,
    "preview": "wrtbwmon (0.36) UNRELEASED; urgency=medium\n\n  * Packaging changes: remove .sh extension from init script, use 'tar' for "
  },
  {
    "path": "control",
    "chars": 608,
    "preview": "Package: wrtbwmon\nVersion: 0.36\nArchitecture: all\nMaintainer: Peter Bailey <peter.eldridge.bailey+wrtbwmon@gmail.com>\nSe"
  },
  {
    "path": "copyright",
    "chars": 723,
    "preview": "wrtbwmon\nCopyright (C) 2016 Peter Bailey\n\nThis program is free software; you can redistribute it and/or modify\nit under "
  },
  {
    "path": "debian/.gitignore",
    "chars": 27,
    "preview": "debhelper*\nfiles\nwrtbwmon*\n"
  },
  {
    "path": "debian/compat",
    "chars": 2,
    "preview": "9\n"
  },
  {
    "path": "debian/control",
    "chars": 657,
    "preview": "Source: wrtbwmon\nMaintainer: Peter Bailey <peter.eldridge.bailey@gmail.com>\nSection: net\nPriority: optional\nStandards-Ve"
  },
  {
    "path": "debian/install",
    "chars": 172,
    "preview": "# TODO: share this between makefile/ipk/deb\nwrtbwmon /usr/sbin\nreadDB.awk /usr/sbin\nusage.htm1 /usr/share/wrtbwmon\nusage"
  },
  {
    "path": "debian/rules",
    "chars": 29,
    "preview": "#!/usr/bin/make -f\n%:\n\tdh $@\n"
  },
  {
    "path": "fileMap",
    "chars": 124,
    "preview": "usr/sbin: wrtbwmon readDB.awk\nusr/share/wrtbwmon: usage.htm1 usage.htm2\nCONTROL: control postinst\netc/init.d: init/wrtbw"
  },
  {
    "path": "init/wrtbwmon",
    "chars": 451,
    "preview": "#!/bin/sh /etc/rc.common\n#\n# start/stop wrtbwmon bandwidth monitor\n\n### BEGIN INIT INFO\n# Provides:           wrtbwmon\n#"
  },
  {
    "path": "install.sh",
    "chars": 495,
    "preview": "do_copy() {\n    local dest perm file\n    for file in $*; do\n\tdest=`egrep \".+ $file( |$)\" ./fileMap | cut -d':' -f1`\n\tmkd"
  },
  {
    "path": "makefile",
    "chars": 470,
    "preview": "DESTDIR?=/\ninstall-files=$(shell grep -v CONTROL fileMap  | cut -d: -f2- | tr -d '\\n')\nipk-files=$(shell grep CONTROL fi"
  },
  {
    "path": "postinst",
    "chars": 569,
    "preview": "#!/bin/sh\n\n# Enable on boot\n/etc/init.d/wrtbwmon enable\n\n# Configure our cron\nif [ -d \"/etc/crontabs\" ]; then\n  echo \"PA"
  },
  {
    "path": "readDB.awk",
    "chars": 3778,
    "preview": "#!/usr/bin/awk\n\nfunction inInterfaces(host){\n    return(interfaces ~ \"(^| )\"host\"($| )\")\n}\n\nfunction newRule(arp_ip,\n   "
  },
  {
    "path": "release-notes",
    "chars": 287,
    "preview": "- transition from invocation as \"wrtbwmon.sh\" back to \"wrtbwmon\"\n- update readme\n- add ipk\n- install files according a s"
  },
  {
    "path": "todo",
    "chars": 181,
    "preview": "- add logger\n- cache DNS results\n- use a config file\n- check for existence of tool dependencies before using them\n- fix "
  },
  {
    "path": "usage.htm1",
    "chars": 606,
    "preview": "<html><head><title>Traffic</title>\n<script type=\"text/javascript\">\nfunction getSize(size) {\n    var prefix=new Array(\"\","
  },
  {
    "path": "usage.htm2",
    "chars": 700,
    "preview": "var totalIn = 0;\nvar totalOut = 0;\nfor (i=0; i < values.length-1; i++) {\n    totalIn += values[i][3];\n    totalOut += va"
  },
  {
    "path": "wrtbwmon",
    "chars": 7222,
    "preview": "#!/bin/sh\n#\n# wrtbwmon: traffic logging tool for routers\n#\n# Peter Bailey (peter.eldridge.bailey+wrtbwmon AT gmail.com)\n"
  }
]

About this extraction

This page contains the full source code of the pyrovski/wrtbwmon GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 21 files (20.5 KB), approximately 7.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!