mirror of
https://github.com/padavanonly/immortalwrt-mt798x.git
synced 2025-12-18 01:35:16 +00:00
214 lines
4.5 KiB
Awk
214 lines
4.5 KiB
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=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)
|
|
}
|