applications/luci-splash:
- rewrote init script, cli - introduce download traffic counters - adept user interface
This commit is contained in:
parent
9525fb76bd
commit
b0771c43ea
4 changed files with 506 additions and 322 deletions
|
@ -24,7 +24,7 @@ function action_activate()
|
|||
local ip = luci.http.getenv("REMOTE_ADDR") or "127.0.0.1"
|
||||
local mac = luci.sys.net.ip4mac(ip:match("^[\[::ffff:]*(%d+.%d+%.%d+%.%d+)\]*$"))
|
||||
if mac and luci.http.formvalue("accept") then
|
||||
os.execute("luci-splash add "..mac.." >/dev/null 2>&1")
|
||||
os.execute("luci-splash lease "..mac.." >/dev/null 2>&1")
|
||||
luci.http.redirect(luci.model.uci.cursor():get("freifunk", "community", "homepage"))
|
||||
else
|
||||
luci.http.redirect(luci.dispatcher.build_url())
|
||||
|
@ -35,63 +35,44 @@ function action_status_admin()
|
|||
local uci = luci.model.uci.cursor_state()
|
||||
local macs = luci.http.formvaluetable("save")
|
||||
|
||||
local function delete_mac(what, mac)
|
||||
uci:delete_all("luci_splash", what,
|
||||
function(s)
|
||||
return ( s.mac and s.mac:lower() == mac )
|
||||
end)
|
||||
end
|
||||
|
||||
local function leases(mac)
|
||||
local leases = { }
|
||||
|
||||
uci:foreach("luci_splash", "lease", function(s)
|
||||
if s.start and s.mac and s.mac:lower() ~= mac then
|
||||
leases[#leases+1] = {
|
||||
start = s.start,
|
||||
mac = s.mac
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
uci:revert("luci_splash")
|
||||
|
||||
return leases
|
||||
end
|
||||
|
||||
local function commit(leases, no_commit)
|
||||
if not no_commit then
|
||||
uci:save("luci_splash")
|
||||
uci:commit("luci_splash")
|
||||
end
|
||||
|
||||
for _, l in ipairs(leases) do
|
||||
uci:section("luci_splash", "lease", nil, l)
|
||||
end
|
||||
|
||||
uci:save("luci_splash")
|
||||
os.execute("/etc/init.d/luci_splash restart")
|
||||
end
|
||||
local changes = {
|
||||
whitelist = { },
|
||||
blacklist = { },
|
||||
lease = { },
|
||||
remove = { }
|
||||
}
|
||||
|
||||
for key, _ in pairs(macs) do
|
||||
local policy = luci.http.formvalue("policy.%s" % key)
|
||||
local mac = luci.http.protocol.urldecode(key)
|
||||
local lslist = leases(policy ~= "kick" and mac)
|
||||
|
||||
delete_mac("blacklist", mac)
|
||||
delete_mac("whitelist", mac)
|
||||
|
||||
if policy == "whitelist" or policy == "blacklist" then
|
||||
uci:section("luci_splash", policy, nil, { mac = mac })
|
||||
elseif policy == "normal" then
|
||||
lslist[#lslist+1] = { mac = mac, start = os.time() }
|
||||
elseif policy == "kick" then
|
||||
for _, l in ipairs(lslist) do
|
||||
if l.mac:lower() == mac then l.kicked="1" end
|
||||
end
|
||||
changes[policy][#changes[policy]+1] = mac
|
||||
elseif policy == "normal" then
|
||||
changes["lease"][#changes["lease"]+1] = mac
|
||||
elseif policy == "kicked" then
|
||||
changes["remove"][#changes["remove"]+1] = mac
|
||||
end
|
||||
end
|
||||
|
||||
commit(lslist)
|
||||
if #changes.whitelist > 0 then
|
||||
os.execute("luci-splash whitelist %s >/dev/null"
|
||||
% table.concat(changes.whitelist))
|
||||
end
|
||||
|
||||
if #changes.blacklist > 0 then
|
||||
os.execute("luci-splash blacklist %s >/dev/null"
|
||||
% table.concat(changes.blacklist))
|
||||
end
|
||||
|
||||
if #changes.lease > 0 then
|
||||
os.execute("luci-splash lease %s >/dev/null"
|
||||
% table.concat(changes.lease))
|
||||
end
|
||||
|
||||
if #changes.remove > 0 then
|
||||
os.execute("luci-splash remove %s >/dev/null"
|
||||
% table.concat(changes.remove))
|
||||
end
|
||||
|
||||
luci.template.render("admin_status/splash", { is_admin = true })
|
||||
|
|
|
@ -35,10 +35,10 @@ uci:foreach("luci_splash", "lease",
|
|||
start = tonumber(s.start),
|
||||
limit = ( tonumber(s.start) + leasetime ),
|
||||
mac = s.mac:upper(),
|
||||
ipaddr = s.ipaddr,
|
||||
policy = "normal",
|
||||
packets = 0,
|
||||
bytes = 0,
|
||||
kicked = s.kicked and true or false
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
@ -58,11 +58,25 @@ for _, r in ipairs(ipt:find({table="nat", chain="luci_splash_leases"})) do
|
|||
end
|
||||
end
|
||||
|
||||
for _, r in ipairs(ipt:find({table="filter", chain="luci_splash_filter", options={"MAC"}})) do
|
||||
local c = clients[r.options[2]:lower()]
|
||||
if c and c.packets == 0 then
|
||||
c.bytes = tonumber(r.bytes)
|
||||
c.packets = tonumber(r.packets)
|
||||
for mac, client in pairs(clients) do
|
||||
client.bytes_in = 0
|
||||
client.bytes_out = 0
|
||||
client.packets_in = 0
|
||||
client.packets_out = 0
|
||||
|
||||
if client.ipaddr then
|
||||
local rin = ipt:find({table="mangle", chain="luci_splash_mark_in", destination=client.ipaddr})
|
||||
local rout = ipt:find({table="mangle", chain="luci_splash_mark_out", options={"MAC", client.mac:upper()}})
|
||||
|
||||
if rin and #rin > 0 then
|
||||
client.bytes_in = rin[1].bytes
|
||||
client.packets_in = rin[1].packets
|
||||
end
|
||||
|
||||
if rout and #rout > 0 then
|
||||
client.bytes_out = rout[1].bytes
|
||||
client.packets_out = rout[1].packets
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -123,7 +137,7 @@ end
|
|||
<th class="cbi-section-table-cell"><%:ff_splash_ip IP Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:ff_splash_mac MAC Address%></th>
|
||||
<th class="cbi-section-table-cell"><%:ff_splash_timeleft Time remaining%></th>
|
||||
<th class="cbi-section-table-cell"><%:ff_splash_traffic Outgoing traffic%></th>
|
||||
<th class="cbi-section-table-cell"><%:ff_splash_traffic Traffic in/out%></th>
|
||||
<th class="cbi-section-table-cell"><%:ff_splash_policy Policy%></th>
|
||||
</tr>
|
||||
|
||||
|
@ -149,7 +163,7 @@ end
|
|||
(c.limit >= os.time()) and wat.date_format(c.limit-os.time()) or
|
||||
(c.policy ~= "normal") and "-" or "<em>" .. translate("ff_splash_expired", "expired") .. "</em>"
|
||||
%></td>
|
||||
<td class="cbi-section-table-cell"><%=wat.byte_format(c.bytes)%></td>
|
||||
<td class="cbi-section-table-cell"><%=wat.byte_format(c.bytes_in)%> / <%=wat.byte_format(c.bytes_out)%></td>
|
||||
<td class="cbi-section-table-cell">
|
||||
<% if is_admin then %>
|
||||
<select name="policy.<%=c.mac:lower()%>" style="width:200px">
|
||||
|
@ -157,7 +171,7 @@ end
|
|||
<option value="normal"<%=c.policy=="normal" and not c.kicked and ' selected="selected"'%>><%:ff_splash_splashed splashed%></option>
|
||||
<option value="blacklist"<%=c.policy=="blacklist" and ' selected="selected"'%>><%:ff_splash_blacklisted blacklisted%></option>
|
||||
<% if c.policy == "normal" then -%>
|
||||
<option value="kick"<%=c.kicked and ' selected="selected"'%>><%:ff_splash_tempblock temporarily blocked%> (<%=wat.date_format(c.limit-os.time())%>)</option>
|
||||
<option value="kicked"><%:ff_splash_tempblock temporarily blocked%></option>
|
||||
<%- end %>
|
||||
</select>
|
||||
<input type="submit" class="cbi-button cbi-button-save" name="save.<%=c.mac:lower()%>" value="<%:save Save%>" />
|
||||
|
|
|
@ -1,15 +1,29 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
|
||||
START=70
|
||||
EXTRA_COMMANDS=clear_leases
|
||||
SPLASH_INTERFACES=""
|
||||
LIMIT_DOWN=0
|
||||
LIMIT_DOWN_BURST=0
|
||||
LIMIT_UP=0
|
||||
|
||||
IPT_REPLAY=/var/run/luci_splash.iptlog
|
||||
LOCK=/var/run/luci_splash.lock
|
||||
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
config_load luci_splash
|
||||
|
||||
set -x
|
||||
|
||||
silent() {
|
||||
"$@" 2>/dev/null
|
||||
}
|
||||
|
||||
ipt_log() {
|
||||
iptables -I "$@"
|
||||
echo iptables -D "$@" >> $IPT_REPLAY
|
||||
}
|
||||
|
||||
iface_add() {
|
||||
local cfg="$1"
|
||||
|
||||
|
@ -37,95 +51,45 @@ iface_add() {
|
|||
|
||||
eval "$(ipcalc.sh $ipaddr $netmask)"
|
||||
|
||||
iptables -t nat -A prerouting_${zone} -j luci_splash_prerouting
|
||||
iptables -t nat -A luci_splash_prerouting -j luci_splash_portal
|
||||
### Add interface specific chain entry rules
|
||||
ipt_log "zone_${zone}_prerouting" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_prerouting -t nat
|
||||
ipt_log "zone_${zone}_forward" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_forwarding -t filter
|
||||
|
||||
iptables -t filter -I luci_splash_filter -s ! "$NETWORK/$PREFIX" -j RETURN
|
||||
iptables -t nat -I luci_splash_leases -s ! "$NETWORK/$PREFIX" -j RETURN
|
||||
|
||||
iptables -t filter -I luci_splash_filter -s "$NETWORK/$PREFIX" -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
iptables -t nat -I luci_splash_leases -s "$NETWORK/$PREFIX" -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
### Allow traffic to the same subnet
|
||||
iptables -t nat -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
iptables -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
|
||||
### Allow traffic to the mesh subnet
|
||||
[ "$parentproto" = "static" -a -n "$parentipaddr" ] && {
|
||||
iptables -t filter -I luci_splash_filter -s "$NETWORK/$PREFIX" -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
|
||||
iptables -t nat -I luci_splash_leases -s "$NETWORK/$PREFIX" -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
|
||||
iptables -t nat -I luci_splash_prerouting -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
|
||||
iptables -t filter -I luci_splash_forwarding -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
|
||||
}
|
||||
|
||||
iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p udp --dport 53 -j RETURN
|
||||
iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p tcp --dport 22 -j RETURN # XXX: ssh really needed?
|
||||
iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -p tcp --dport 80 -j RETURN
|
||||
iptables -t filter -A luci_splash_filter -s "$NETWORK/$PREFIX" -j REJECT --reject-with icmp-admin-prohibited
|
||||
|
||||
qos_iface_add "$ifname"
|
||||
|
||||
append SPLASH_INTERFACES "$ifname"
|
||||
}
|
||||
|
||||
iface_del() {
|
||||
config_get zone "$1" zone
|
||||
[ -n "$zone" ] || return 0
|
||||
|
||||
while iptables -t nat -D prerouting_${zone} -j luci_splash_prerouting 2>&-; do :; done
|
||||
|
||||
config_get net "$1" network
|
||||
[ -n "$net" ] || return 0
|
||||
|
||||
config_get ifname "$net" ifname
|
||||
[ -n "$ifname" ] || return 0
|
||||
|
||||
# Clear interface specific rules
|
||||
[ -s $IPT_REPLAY ] && {
|
||||
grep -- "-i ${ifname%:*}" $IPT_REPLAY | while read ln; do silent $ln; done
|
||||
sed -ie "/-i ${ifname%:*}/d" $IPT_REPLAY
|
||||
}
|
||||
|
||||
qos_iface_del "$ifname"
|
||||
}
|
||||
|
||||
blacklist_add() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get mac "$cfg" mac
|
||||
[ -n "$mac" ] && {
|
||||
iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j DROP
|
||||
iptables -t nat -I luci_splash_leases -m mac --mac-source "$mac" -j DROP
|
||||
}
|
||||
}
|
||||
|
||||
whitelist_add() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get mac "$cfg" mac
|
||||
[ -n "$mac" ] && {
|
||||
iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j RETURN
|
||||
iptables -t nat -I luci_splash_leases -m mac --mac-source "$mac" -j RETURN
|
||||
}
|
||||
}
|
||||
|
||||
lease_add() {
|
||||
local cfg="$1"
|
||||
|
||||
config_get mac "$cfg" mac
|
||||
config_get ban "$cfg" kicked
|
||||
|
||||
ban=${ban:+DROP}
|
||||
|
||||
[ -n "$mac" ] && {
|
||||
local oIFS="$IFS"; IFS=":"
|
||||
set -- $mac
|
||||
IFS="$oIFS"; unset oIFS
|
||||
|
||||
local mac_pre="$1$2"
|
||||
local mac_post="$3$4$5$6"
|
||||
local handle="$6"
|
||||
|
||||
iptables -t filter -I luci_splash_filter -m mac --mac-source "$mac" -j RETURN
|
||||
iptables -t nat -I luci_splash_leases -m mac --mac-source "$mac" -j "${ban:-RETURN}"
|
||||
|
||||
[ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && {
|
||||
iptables -t mangle -I luci_splash_mark -m mac --mac-source "$mac" -j MARK --set-mark 79
|
||||
|
||||
for i in $SPLASH_INTERFACES; do
|
||||
tc filter add dev $i parent 77:0 protocol ip prio 2 handle ::$handle u32 \
|
||||
match u16 0x0800 0xFFFF at -2 match u32 0x$mac_post 0xFFFFFFFF at -12 \
|
||||
match u16 0x$mac_pre 0xFFFF at -14 flowid 77:10
|
||||
done
|
||||
}
|
||||
}
|
||||
mac_add() {
|
||||
config_get mac "$1" mac
|
||||
append MACS "$mac"
|
||||
}
|
||||
|
||||
subnet_add() {
|
||||
|
@ -135,8 +99,8 @@ subnet_add() {
|
|||
config_get netmask "$cfg" netmask
|
||||
|
||||
[ -n "$ipaddr" ] && {
|
||||
iptables -t filter -I luci_splash_filter -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
iptables -t nat -I luci_splash_portal -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
iptables -t nat -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
iptables -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +109,8 @@ qos_iface_add() {
|
|||
|
||||
# 77 -> download root qdisc
|
||||
# 78 -> upload root qdisc
|
||||
# 79 -> fwmark
|
||||
# 79 -> fwmark: client->inet
|
||||
# 80 -> fwmark: inet->client
|
||||
|
||||
silent tc qdisc del dev "$iface" root handle 77:
|
||||
|
||||
|
@ -157,16 +122,20 @@ qos_iface_add() {
|
|||
|
||||
# set download limit and burst
|
||||
tc class add dev "$iface" parent 77:1 classid 77:10 htb \
|
||||
rate ${LIMIT_DOWN}kb ceil ${LIMIT_DOWN_BURST}kb prio 2
|
||||
rate ${LIMIT_DOWN}kbit ceil ${LIMIT_DOWN_BURST}kbit prio 2
|
||||
|
||||
tc qdisc add dev "$iface" parent 77:10 handle 78: sfq perturb 10
|
||||
|
||||
# adding ingress can result in "File exists" if qos-scripts are active
|
||||
silent tc qdisc add dev "$iface" ingress
|
||||
|
||||
# set client download speed
|
||||
tc filter add dev "$iface" parent 77: protocol ip prio 2 \
|
||||
handle 80 fw flowid 77:10
|
||||
|
||||
# set client upload speed
|
||||
tc filter add dev "$iface" parent ffff: protocol ip prio 1 \
|
||||
handle 79 fw police rate ${LIMIT_UP}kb mtu 6k burst 6k drop
|
||||
handle 79 fw police rate ${LIMIT_UP}kbit mtu 6k burst 6k drop
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -180,7 +149,7 @@ qos_iface_del() {
|
|||
|
||||
boot() {
|
||||
### Setup splash-relay
|
||||
uci get lucid.splashr || {
|
||||
uci get lucid.splashr 2>/dev/null || {
|
||||
uci batch <<EOF
|
||||
set lucid.splashr=daemon
|
||||
set lucid.splashr.slave=httpd
|
||||
|
@ -202,101 +171,113 @@ EOF
|
|||
}
|
||||
|
||||
start() {
|
||||
### Read chains from config
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
config_load luci_splash
|
||||
|
||||
lock -w $LOCK && lock $LOCK
|
||||
|
||||
### Find QoS limits
|
||||
config_get LIMIT_UP general limit_up
|
||||
config_get LIMIT_DOWN general limit_down
|
||||
config_get LIMIT_DOWN_BURST general limit_down_burst
|
||||
|
||||
LIMIT_UP="${LIMIT_UP:-0}"
|
||||
LIMIT_DOWN="${LIMIT_DOWN:-0}"
|
||||
LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:-$(($LIMIT_DOWN * 2))}"
|
||||
LIMIT_UP="$((8*${LIMIT_UP:-0}))"
|
||||
LIMIT_DOWN="$((8*${LIMIT_DOWN:-0}))"
|
||||
LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:+$((8*$LIMIT_DOWN_BURST))}"
|
||||
LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:-$(($LIMIT_DOWN / 5 * 6))}"
|
||||
|
||||
### Load required modules
|
||||
[ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && {
|
||||
silent insmod cls_fw
|
||||
silent insmod cls_u32
|
||||
silent insmod sch_htb
|
||||
silent insmod sch_sfq
|
||||
silent insmod sch_ingress
|
||||
}
|
||||
|
||||
### Create subchains
|
||||
iptables -t filter -N luci_splash_filter
|
||||
iptables -t nat -N luci_splash_portal
|
||||
iptables -t nat -N luci_splash_leases
|
||||
iptables -t nat -N luci_splash_prerouting
|
||||
iptables -t nat -N luci_splash_leases
|
||||
iptables -t filter -N luci_splash_forwarding
|
||||
iptables -t filter -N luci_splash_filter
|
||||
|
||||
[ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && \
|
||||
iptables -t mangle -N luci_splash_mark
|
||||
### Clear iptables replay log
|
||||
[ -s $IPT_REPLAY ] && . $IPT_REPLAY
|
||||
echo -n > $IPT_REPLAY
|
||||
|
||||
### Build the main and portal rule
|
||||
config_foreach iface_add iface
|
||||
config_foreach subnet_add subnet
|
||||
config_foreach blacklist_add blacklist
|
||||
config_foreach whitelist_add whitelist
|
||||
config_foreach lease_add lease
|
||||
|
||||
### Build the portal rule
|
||||
iptables -t filter -I INPUT -j luci_splash_filter
|
||||
iptables -t filter -I FORWARD -j luci_splash_filter
|
||||
|
||||
[ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && \
|
||||
iptables -t mangle -I PREROUTING -j luci_splash_mark
|
||||
|
||||
### Allow icmp, dns and traceroute
|
||||
iptables -t nat -A luci_splash_portal -p udp --dport 33434:33523 -j RETURN
|
||||
iptables -t nat -A luci_splash_portal -p icmp -j RETURN
|
||||
iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN
|
||||
|
||||
### Redirect the rest into the lease chain
|
||||
iptables -t nat -A luci_splash_portal -j luci_splash_leases
|
||||
|
||||
### Build the leases rule
|
||||
### Add interface independant prerouting rules
|
||||
iptables -t nat -A luci_splash_prerouting -j luci_splash_leases
|
||||
iptables -t nat -A luci_splash_leases -p udp --dport 53 -j REDIRECT --to-ports 53
|
||||
iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082
|
||||
|
||||
|
||||
### Add interface independant forwarding rules
|
||||
iptables -t filter -A luci_splash_forwarding -j luci_splash_filter
|
||||
iptables -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset
|
||||
iptables -t filter -A luci_splash_filter -j REJECT --reject-with icmp-net-prohibited
|
||||
|
||||
### Add QoS chain
|
||||
[ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && {
|
||||
iptables -t mangle -N luci_splash_mark_out
|
||||
iptables -t mangle -N luci_splash_mark_in
|
||||
iptables -t mangle -I PREROUTING -j luci_splash_mark_out
|
||||
iptables -t mangle -I POSTROUTING -j luci_splash_mark_in
|
||||
}
|
||||
|
||||
### Find active mac addresses
|
||||
MACS=""
|
||||
config_foreach mac_add lease
|
||||
config_foreach mac_add blacklist
|
||||
config_foreach mac_add whitelist
|
||||
|
||||
### Add crontab entry
|
||||
test -f /etc/crontabs/root || touch /etc/crontabs/root
|
||||
grep -q luci-splash /etc/crontabs/root || {
|
||||
echo '*/5 * * * * /usr/sbin/luci-splash sync' >> /etc/crontabs/root
|
||||
}
|
||||
|
||||
lock -u $LOCK
|
||||
|
||||
### Populate iptables
|
||||
[ -n "$MACS" ] && luci-splash add-rules $MACS
|
||||
}
|
||||
|
||||
stop() {
|
||||
lock -w $LOCK && lock $LOCK
|
||||
|
||||
### Clear interface rules
|
||||
include /lib/network
|
||||
scan_interfaces
|
||||
config_load luci_splash
|
||||
config_foreach iface_del iface
|
||||
|
||||
silent iptables -t filter -D INPUT -j luci_splash_filter
|
||||
silent iptables -t filter -D FORWARD -j luci_splash_filter
|
||||
silent iptables -t mangle -D PREROUTING -j luci_splash_mark
|
||||
silent iptables -t mangle -D PREROUTING -j luci_splash_mark_out
|
||||
silent iptables -t mangle -D POSTROUTING -j luci_splash_mark_in
|
||||
|
||||
### Clear subchains
|
||||
silent iptables -t nat -F luci_splash_leases
|
||||
silent iptables -t nat -F luci_splash_portal
|
||||
silent iptables -t nat -F luci_splash_prerouting
|
||||
silent iptables -t nat -F luci_splash_leases
|
||||
silent iptables -t filter -F luci_splash_forwarding
|
||||
silent iptables -t filter -F luci_splash_filter
|
||||
silent iptables -t mangle -F luci_splash_mark
|
||||
silent iptables -t mangle -F luci_splash_mark_out
|
||||
silent iptables -t mangle -F luci_splash_mark_in
|
||||
|
||||
### Delete subchains
|
||||
silent iptables -t nat -X luci_splash_leases
|
||||
silent iptables -t nat -X luci_splash_portal
|
||||
silent iptables -t nat -X luci_splash_prerouting
|
||||
silent iptables -t nat -X luci_splash_leases
|
||||
silent iptables -t filter -X luci_splash_forwarding
|
||||
silent iptables -t filter -X luci_splash_filter
|
||||
silent iptables -t mangle -X luci_splash_mark
|
||||
silent iptables -t mangle -X luci_splash_mark_out
|
||||
silent iptables -t mangle -X luci_splash_mark_in
|
||||
|
||||
sed -ie '/\/usr\/sbin\/luci-splash sync/d' /var/spool/cron/crontabs/root
|
||||
|
||||
lock -u $LOCK
|
||||
}
|
||||
|
||||
|
||||
clear_leases() {
|
||||
stop
|
||||
while uci -P /var/state del luci_splash.@lease[0] 2>&-;do :; done
|
||||
start
|
||||
### Find active mac addresses
|
||||
MACS=""
|
||||
config_foreach mac_add lease
|
||||
|
||||
### Clear leases
|
||||
[ -n "$MACS" ] && luci-splash remove $MACS
|
||||
}
|
||||
|
||||
|
|
|
@ -2,185 +2,324 @@
|
|||
|
||||
require("luci.util")
|
||||
require("luci.model.uci")
|
||||
require("luci.sys")
|
||||
require("luci.sys.iptparser")
|
||||
|
||||
-- Init state session
|
||||
local uci = luci.model.uci.cursor_state()
|
||||
local ipt = luci.sys.iptparser.IptParser()
|
||||
local net = luci.sys.net
|
||||
|
||||
local splash_interfaces = { }
|
||||
local limit_up = 0
|
||||
local limit_down = 0
|
||||
|
||||
function lock()
|
||||
os.execute("lock -w /var/run/luci_splash.lock && lock /var/run/luci_splash.lock")
|
||||
end
|
||||
|
||||
function unlock()
|
||||
os.execute("lock -u /var/run/luci_splash.lock")
|
||||
end
|
||||
|
||||
function main(argv)
|
||||
local cmd = argv[1]
|
||||
local arg = argv[2]
|
||||
local cmd = table.remove(argv, 1)
|
||||
local arg = argv[1]
|
||||
|
||||
limit_up = tonumber(uci:get("luci_splash", "general", "limit_up")) or 0
|
||||
limit_down = tonumber(uci:get("luci_splash", "general", "limit_down")) or 0
|
||||
|
||||
uci:foreach("luci_splash", "iface", function(s)
|
||||
if s.network then
|
||||
splash_interfaces[#splash_interfaces+1] = uci:get("network", s.network, "ifname")
|
||||
end
|
||||
end)
|
||||
|
||||
if cmd == "status" and arg then
|
||||
if islisted("whitelist", arg) then
|
||||
print("whitelisted")
|
||||
elseif islisted("blacklist", arg) then
|
||||
print("blacklisted")
|
||||
else
|
||||
local lease = haslease(arg)
|
||||
if lease and lease.kicked then
|
||||
print("kicked")
|
||||
elseif lease then
|
||||
print("lease")
|
||||
if ( cmd == "lease" or cmd == "add-rules" or cmd == "remove" or
|
||||
cmd == "whitelist" or cmd == "blacklist" ) and #argv > 0
|
||||
then
|
||||
lock()
|
||||
|
||||
local arp_cache = net.arptable()
|
||||
local leased_macs = get_known_macs("lease")
|
||||
local blacklist_macs = get_known_macs("blacklist")
|
||||
local whitelist_macs = get_known_macs("whitelist")
|
||||
|
||||
for i, adr in ipairs(argv) do
|
||||
local mac = nil
|
||||
if adr:find(":") then
|
||||
mac = adr:lower()
|
||||
else
|
||||
print("unknown")
|
||||
for _, e in ipairs(arp_cache) do
|
||||
if e["IP address"] == adr then
|
||||
mac = e["HW address"]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if mac and cmd == "add-rules" then
|
||||
if leased_macs[mac] then
|
||||
add_lease(mac, arp_cache, true)
|
||||
elseif blacklist_macs[mac] then
|
||||
add_blacklist_rule(mac)
|
||||
elseif whitelist_macs[mac] then
|
||||
add_whitelist_rule(mac)
|
||||
end
|
||||
elseif mac and ( cmd == "whitelist" or cmd == "blacklist" or cmd == "lease" ) then
|
||||
if cmd ~= "lease" and leased_macs[mac] then
|
||||
print("Removing %s from leases" % mac)
|
||||
remove_lease(mac)
|
||||
leased_macs[mac] = nil
|
||||
end
|
||||
|
||||
if cmd ~= "whitelist" and whitelist_macs[mac] then
|
||||
print("Removing %s from whitelist" % mac)
|
||||
remove_whitelist(mac)
|
||||
whitelist_macs[mac] = nil
|
||||
end
|
||||
|
||||
if cmd ~= "blacklist" and blacklist_macs[mac] then
|
||||
print("Removing %s from blacklist" % mac)
|
||||
remove_blacklist(mac)
|
||||
blacklist_macs[mac] = nil
|
||||
end
|
||||
|
||||
if cmd == "lease" and not leased_macs[mac] then
|
||||
print("Adding %s to leases" % mac)
|
||||
add_lease(mac)
|
||||
leased_macs[mac] = true
|
||||
elseif cmd == "whitelist" and not whitelist_macs[mac] then
|
||||
print("Adding %s to whitelist" % mac)
|
||||
add_whitelist(mac)
|
||||
whitelist_macs[mac] = true
|
||||
elseif cmd == "blacklist" and not blacklist_macs[mac] then
|
||||
print("Adding %s to blacklist" % mac)
|
||||
add_blacklist(mac)
|
||||
blacklist_macs[mac] = true
|
||||
else
|
||||
print("The mac %s is already %sed" %{ mac, cmd })
|
||||
end
|
||||
elseif mac and cmd == "remove" then
|
||||
if leased_macs[mac] then
|
||||
print("Removing %s from leases" % mac)
|
||||
remove_lease(mac)
|
||||
leased_macs[mac] = nil
|
||||
elseif whitelist_macs[mac] then
|
||||
print("Removing %s from whitelist" % mac)
|
||||
remove_whitelist(mac)
|
||||
whitelist_macs[mac] = nil
|
||||
elseif blacklist_macs[mac] then
|
||||
print("Removing %s from blacklist" % mac)
|
||||
remove_blacklist(mac)
|
||||
blacklist_macs[mac] = nil
|
||||
else
|
||||
print("The mac %s is not known" % mac)
|
||||
end
|
||||
else
|
||||
print("Can not find mac for ip %s" % argv[i])
|
||||
end
|
||||
end
|
||||
os.exit(0)
|
||||
elseif cmd == "add" and arg then
|
||||
if not haslease(arg) then
|
||||
add_lease(arg)
|
||||
else
|
||||
print("already leased!")
|
||||
os.exit(2)
|
||||
end
|
||||
os.exit(0)
|
||||
elseif cmd == "remove" and arg then
|
||||
remove_lease(arg)
|
||||
os.exit(0)
|
||||
|
||||
unlock()
|
||||
os.exit(0)
|
||||
elseif cmd == "sync" then
|
||||
sync()
|
||||
os.exit(0)
|
||||
elseif cmd == "list" then
|
||||
list()
|
||||
os.exit(0)
|
||||
else
|
||||
print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
|
||||
print("Usage:")
|
||||
print("\n luci-splash list\n List connected, black- and whitelisted clients")
|
||||
print("\n luci-splash sync\n Synchronize firewall rules and clear expired leases")
|
||||
print("\n luci-splash lease <MAC-or-IP>\n Create a lease for the given address")
|
||||
print("\n luci-splash blacklist <MAC-or-IP>\n Add given address to blacklist")
|
||||
print("\n luci-splash whitelist <MAC-or-IP>\n Add given address to whitelist")
|
||||
print("\n luci-splash remove <MAC-or-IP>\n Remove given address from the lease-, black- or whitelist")
|
||||
print("")
|
||||
|
||||
os.exit(1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get a list of known mac addresses
|
||||
function get_known_macs(list)
|
||||
local leased_macs = { }
|
||||
|
||||
if not list or list == "lease" then
|
||||
uci:foreach("luci_splash", "lease",
|
||||
function(s) leased_macs[s.mac:lower()] = true end)
|
||||
end
|
||||
|
||||
if not list or list == "whitelist" then
|
||||
uci:foreach("luci_splash", "whitelist",
|
||||
function(s) leased_macs[s.mac:lower()] = true end)
|
||||
end
|
||||
|
||||
if not list or list == "blacklist" then
|
||||
uci:foreach("luci_splash", "blacklist",
|
||||
function(s) leased_macs[s.mac:lower()] = true end)
|
||||
end
|
||||
|
||||
return leased_macs
|
||||
end
|
||||
|
||||
|
||||
-- Get a list of known ip addresses
|
||||
function get_known_ips(macs, arp)
|
||||
local leased_ips = { }
|
||||
if not macs then macs = get_known_macs() end
|
||||
for _, e in ipairs(arp or net.arptable()) do
|
||||
if macs[e["HW address"]] then leased_ips[e["IP address"]] = true end
|
||||
end
|
||||
return leased_ips
|
||||
end
|
||||
|
||||
|
||||
-- Helper to delete iptables rules
|
||||
function ipt_delete_all(args, comp, off)
|
||||
off = off or { }
|
||||
for i, r in ipairs(ipt:find(args)) do
|
||||
if comp == nil or comp(r) then
|
||||
off[r.table] = off[r.table] or { }
|
||||
off[r.table][r.chain] = off[r.table][r.chain] or 0
|
||||
|
||||
os.execute("iptables -t %q -D %q %d 2>/dev/null"
|
||||
%{ r.table, r.chain, r.index - off[r.table][r.chain] })
|
||||
|
||||
off[r.table][r.chain] = off[r.table][r.chain] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Add a lease to state and invoke add_rule
|
||||
function add_lease(mac)
|
||||
uci:section("luci_splash", "lease", nil, {
|
||||
mac = mac,
|
||||
start = os.time()
|
||||
})
|
||||
add_rule(mac)
|
||||
|
||||
uci:save("luci_splash")
|
||||
function add_lease(mac, arp, no_uci)
|
||||
mac = mac:lower()
|
||||
|
||||
-- Get current ip address
|
||||
local ipaddr
|
||||
for _, entry in ipairs(arp or net.arptable()) do
|
||||
if entry["HW address"] == mac then
|
||||
ipaddr = entry["IP address"]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Add lease if there is an ip addr
|
||||
if ipaddr then
|
||||
if not no_uci then
|
||||
uci:section("luci_splash", "lease", nil, {
|
||||
mac = mac,
|
||||
ipaddr = ipaddr,
|
||||
start = os.time()
|
||||
})
|
||||
uci:save("luci_splash")
|
||||
end
|
||||
add_lease_rule(mac, ipaddr)
|
||||
else
|
||||
print("Found no active IP for %s, lease not added" % mac)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Remove a lease from state and invoke remove_rule
|
||||
function remove_lease(mac)
|
||||
mac = mac:lower()
|
||||
remove_rule(mac)
|
||||
|
||||
uci:delete_all("luci_splash", "lease",
|
||||
function(s) return ( s.mac:lower() == mac ) end)
|
||||
function(s)
|
||||
if s.mac:lower() == mac then
|
||||
remove_lease_rule(mac, s.ipaddr)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end)
|
||||
|
||||
uci:save("luci_splash")
|
||||
end
|
||||
|
||||
|
||||
-- Add a whitelist entry
|
||||
function add_whitelist(mac)
|
||||
uci:section("luci_splash", "whitelist", nil, { mac = mac })
|
||||
uci:save("luci_splash")
|
||||
uci:commit("luci_splash")
|
||||
add_whitelist_rule(mac)
|
||||
end
|
||||
|
||||
|
||||
-- Add a blacklist entry
|
||||
function add_blacklist(mac)
|
||||
uci:section("luci_splash", "blacklist", nil, { mac = mac })
|
||||
uci:save("luci_splash")
|
||||
uci:commit("luci_splash")
|
||||
add_blacklist_rule(mac)
|
||||
end
|
||||
|
||||
|
||||
-- Remove a whitelist entry
|
||||
function remove_whitelist(mac)
|
||||
mac = mac:lower()
|
||||
uci:delete_all("luci_splash", "whitelist",
|
||||
function(s) return not s.mac or s.mac:lower() == mac end)
|
||||
uci:save("luci_splash")
|
||||
uci:commit("luci_splash")
|
||||
remove_lease_rule(mac)
|
||||
end
|
||||
|
||||
|
||||
-- Remove a blacklist entry
|
||||
function remove_blacklist(mac)
|
||||
mac = mac:lower()
|
||||
uci:delete_all("luci_splash", "blacklist",
|
||||
function(s) return not s.mac or s.mac:lower() == mac end)
|
||||
uci:save("luci_splash")
|
||||
uci:commit("luci_splash")
|
||||
remove_lease_rule(mac)
|
||||
end
|
||||
|
||||
|
||||
-- Add an iptables rule
|
||||
function add_rule(mac)
|
||||
local a, b, c, d, e, f = mac:match("(%w+):(%w+):(%w+):(%w+):(%w+):(%w+)")
|
||||
local mac_pre = "%s%s" %{ a, b }
|
||||
local mac_post = "%s%s%s%s" %{ c, d, e, f }
|
||||
local handle = f
|
||||
|
||||
function add_lease_rule(mac, ipaddr)
|
||||
if limit_up > 0 and limit_down > 0 then
|
||||
os.execute("iptables -t mangle -I luci_splash_mark -m mac --mac-source %q -j MARK --set-mark 79" % mac)
|
||||
|
||||
for _, i in ipairs(splash_interfaces) do
|
||||
os.execute("tc filter add dev %q parent 77:0 protocol ip prio 2 " % i ..
|
||||
"handle ::%q u32 " % handle ..
|
||||
"match u16 0x0800 0xFFFF at -2 match u32 0x%q 0xFFFFFFFF at -12 " % mac_post ..
|
||||
"match u16 0x%q 0xFFFF at -14 flowid 77:10" % mac_pre)
|
||||
end
|
||||
os.execute("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac)
|
||||
os.execute("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80" % ipaddr)
|
||||
end
|
||||
|
||||
os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
|
||||
return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac)
|
||||
os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac)
|
||||
end
|
||||
|
||||
|
||||
-- Remove an iptables rule
|
||||
function remove_rule(mac)
|
||||
local handle = mac:match("%w+:%w+:%w+:%w+:%w+:(%w+)")
|
||||
|
||||
local function ipt_delete_foreach(args)
|
||||
for _, r in ipairs(ipt:find(args)) do
|
||||
os.execute("iptables -t %q -D %q -m mac --mac-source %q %s 2>/dev/null"
|
||||
%{ r.table, r.chain, mac,
|
||||
r.target == "MARK" and "-j MARK --set-mark 79" or
|
||||
r.target and "-j %q" % r.target or "" })
|
||||
end
|
||||
end
|
||||
|
||||
ipt_delete_foreach({table="filter", chain="luci_splash_filter", options={"MAC", mac:upper()}})
|
||||
ipt_delete_foreach({table="mangle", chain="luci_splash_mark", options={"MAC", mac:upper()}})
|
||||
ipt_delete_foreach({table="nat", chain="luci_splash_leases", options={"MAC", mac:upper()}})
|
||||
|
||||
for _, i in ipairs(splash_interfaces) do
|
||||
os.execute("tc filter del dev %q parent 77:0 protocol ip prio 2 " % i ..
|
||||
"handle 800::%q u32 2>/dev/null" % handle)
|
||||
end
|
||||
|
||||
-- Remove lease, black- or whitelist rules
|
||||
function remove_lease_rule(mac, ipaddr)
|
||||
ipt:resync()
|
||||
end
|
||||
|
||||
|
||||
-- Check whether a MAC-Address is listed in the lease state list
|
||||
function haslease(mac)
|
||||
mac = mac:lower()
|
||||
local lease = nil
|
||||
|
||||
uci:foreach("luci_splash", "lease",
|
||||
function (section)
|
||||
if section.mac:lower() == mac then
|
||||
lease = section
|
||||
end
|
||||
end)
|
||||
|
||||
return lease
|
||||
end
|
||||
|
||||
|
||||
-- Check whether a MAC-Address is in given list
|
||||
function islisted(what, mac)
|
||||
mac = mac:lower()
|
||||
|
||||
uci:foreach("luci_splash", what,
|
||||
function (section)
|
||||
if section.mac:lower() == mac then
|
||||
stat = true
|
||||
return
|
||||
end
|
||||
end)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- Returns a list of MAC-Addresses for which a rule is existing
|
||||
function listrules()
|
||||
local macs = { }
|
||||
for i, r in ipairs(ipt:find({table="nat", chain="luci_splash_leases", options={"MAC"}})) do
|
||||
macs[r.options[2]:lower()] = true
|
||||
if ipaddr then
|
||||
ipt_delete_all({table="mangle", chain="luci_splash_mark_in", destination=ipaddr})
|
||||
ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", mac:upper()}})
|
||||
end
|
||||
return luci.util.keys(macs)
|
||||
|
||||
ipt_delete_all({table="filter", chain="luci_splash_filter", options={"MAC", mac:upper()}})
|
||||
ipt_delete_all({table="nat", chain="luci_splash_leases", options={"MAC", mac:upper()}})
|
||||
end
|
||||
|
||||
|
||||
-- Add whitelist rules
|
||||
function add_whitelist_rule(mac)
|
||||
os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
|
||||
os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac)
|
||||
end
|
||||
|
||||
|
||||
-- Add blacklist rules
|
||||
function add_blacklist_rule(mac)
|
||||
os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac)
|
||||
os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j DROP" % mac)
|
||||
end
|
||||
|
||||
|
||||
-- Synchronise leases, remove abandoned rules
|
||||
function sync()
|
||||
local written = {}
|
||||
lock()
|
||||
|
||||
local time = os.time()
|
||||
|
||||
|
||||
-- Current leases in state files
|
||||
local leases = uci:get_all("luci_splash")
|
||||
|
||||
|
@ -191,36 +330,105 @@ function sync()
|
|||
uci:load("luci_splash")
|
||||
uci:revert("luci_splash")
|
||||
|
||||
|
||||
-- For all leases
|
||||
for k, v in pairs(leases) do
|
||||
if v[".type"] == "lease" then
|
||||
if os.difftime(time, tonumber(v.start)) > leasetime then
|
||||
-- Remove expired
|
||||
remove_rule(v.mac)
|
||||
remove_lease_rule(v.mac, v.ipaddr)
|
||||
else
|
||||
-- Rewrite state
|
||||
uci:section("luci_splash", "lease", nil, {
|
||||
mac = v.mac,
|
||||
start = v.start,
|
||||
kicked = v.kicked
|
||||
ipaddr = v.ipaddr,
|
||||
start = v.start
|
||||
})
|
||||
written[v.mac:lower()] = 1
|
||||
end
|
||||
elseif v[".type"] == "whitelist" or v[".type"] == "blacklist" then
|
||||
written[v.mac:lower()] = 1
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Delete rules without state
|
||||
for i, r in ipairs(listrules()) do
|
||||
if #r > 0 and not written[r:lower()] then
|
||||
remove_rule(r)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
uci:save("luci_splash")
|
||||
|
||||
-- Get current IPs and MAC addresses
|
||||
local macs = get_known_macs()
|
||||
local ips = get_known_ips(macs)
|
||||
|
||||
ipt:resync()
|
||||
|
||||
ipt_delete_all({table="filter", chain="luci_splash_filter", options={"MAC"}},
|
||||
function(r) return not macs[r.options[2]:lower()] end)
|
||||
|
||||
ipt_delete_all({table="nat", chain="luci_splash_leases", options={"MAC"}},
|
||||
function(r) return not macs[r.options[2]:lower()] end)
|
||||
|
||||
ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", "MARK", "set"}},
|
||||
function(r) return not macs[r.options[2]:lower()] end)
|
||||
|
||||
ipt_delete_all({table="mangle", chain="luci_splash_mark_in", options={"MARK", "set"}},
|
||||
function(r) return not ips[r.destination] end)
|
||||
|
||||
unlock()
|
||||
end
|
||||
|
||||
-- Show client info
|
||||
function list()
|
||||
-- Get current arp cache
|
||||
local arpcache = { }
|
||||
for _, entry in ipairs(net.arptable()) do
|
||||
arpcache[entry["HW address"]] = { entry["Device"], entry["IP address"] }
|
||||
end
|
||||
|
||||
-- Find traffic usage
|
||||
local function traffic(lease)
|
||||
local traffic_in = 0
|
||||
local traffic_out = 0
|
||||
|
||||
local rin = ipt:find({table="mangle", chain="luci_splash_mark_in", destination=lease.ipaddr})
|
||||
local rout = ipt:find({table="mangle", chain="luci_splash_mark_out", options={"MAC", lease.mac:upper()}})
|
||||
|
||||
if rin and #rin > 0 then traffic_in = math.floor( rin[1].bytes / 1024) end
|
||||
if rout and #rout > 0 then traffic_out = math.floor(rout[1].bytes / 1024) end
|
||||
|
||||
return traffic_in, traffic_out
|
||||
end
|
||||
|
||||
-- Print listings
|
||||
local leases = uci:get_all("luci_splash")
|
||||
|
||||
print(string.format(
|
||||
"%-17s %-15s %-9s %-4s %-7s %20s",
|
||||
"MAC", "IP", "State", "Dur.", "Intf.", "Traffic down/up"
|
||||
))
|
||||
|
||||
-- Leases
|
||||
for _, s in pairs(leases) do
|
||||
if s[".type"] == "lease" and s.mac then
|
||||
local ti, to = traffic(s)
|
||||
local mac = s.mac:lower()
|
||||
local arp = arpcache[mac]
|
||||
print(string.format(
|
||||
"%-17s %-15s %-9s %3dm %-7s %7dKB %7dKB",
|
||||
mac, s.ipaddr, "leased",
|
||||
math.floor(( os.time() - tonumber(s.start) ) / 60),
|
||||
arp and arp[1] or "?", ti, to
|
||||
))
|
||||
end
|
||||
end
|
||||
|
||||
-- Whitelist, Blacklist
|
||||
for _, s in luci.util.spairs(leases,
|
||||
function(a,b) return leases[a][".type"] > leases[b][".type"] end
|
||||
) do
|
||||
if (s[".type"] == "whitelist" or s[".type"] == "blacklist") and s.mac then
|
||||
local mac = s.mac:lower()
|
||||
local arp = arpcache[mac]
|
||||
print(string.format(
|
||||
"%-17s %-15s %-9s %4s %-7s %9s %9s",
|
||||
mac, arp and arp[2] or "?", s[".type"], "- ",
|
||||
arp and arp[1] or "?", "-", "-"
|
||||
))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
main(arg)
|
||||
|
|
Loading…
Reference in a new issue