luci-base: support disconnecting (deauthenticating) wireless clients

Add a button to each row in the wireless assoclist table to allow
disconnecting clients using the ubus del_client method if the underlying
radio interface supports it.

Ref: https://github.com/openwrt/luci/pull/2271
Submitted-by: Wang805447391 <805447391@qq.com>
[move deauth function to luci-base next to the existing assoclist function,
 require post security, fix parameter check condition, hide button if not
 supported by the radio, disable button after call, squash commits, fix
 whitespace, reword subject, add commit message]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Wang805447391 2018-11-12 15:03:31 +08:00 committed by Jo-Philipp Wich
parent 8aeb78d1c1
commit 09ac96ede9
2 changed files with 57 additions and 1 deletions

View file

@ -80,6 +80,9 @@ function index()
if has_wifi then
page = entry({"admin", "wireless_assoclist"}, call("wifi_assoclist"), nil)
page.leaf = true
page = entry({"admin", "wireless_deauth"}, post("wifi_deauth"), nil)
page.leaf = true
end
page = entry({"admin", "translations"}, call("action_translations"), nil)
@ -144,3 +147,18 @@ function wifi_assoclist()
luci.http.prepare_content("application/json")
luci.http.write_json(s.wifi_assoclist())
end
function wifi_deauth()
local iface = luci.http.formvalue("iface")
local bssid = luci.http.formvalue("bssid")
if iface and bssid then
luci.util.ubus("hostapd.%s" % iface, "del_client", {
addr = bssid,
deauth = true,
reason = 5,
ban_time = 60000
})
end
luci.http.status(200, "OK")
end

View file

@ -1,4 +1,21 @@
<%
local supports_deauth = {}
local _, v
for _, v in ipairs(luci.util.ubus()) do
local iface = v:match("^hostapd%.(.+)$")
if iface then
local funcs = luci.util.ubus(v)
if type(funcs) == "table" and funcs.del_client then
supports_deauth[iface] = true
end
end
end
%>
<script type="text/javascript">//<![CDATA[
var supports_deauth = <%= luci.http.write_json(supports_deauth) %>;
function wifirate(bss, rx) {
var p = rx ? 'rx_' : 'tx_',
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
@ -17,6 +34,16 @@
return s;
}
function handleDeauth(ev) {
(new XHR()).post('<%=url('admin/wireless_deauth')%>', {
token: '<%=token%>',
iface: ev.target.getAttribute('data-iface'),
bssid: ev.target.getAttribute('data-bssid')
}, function() {
ev.target.disabled = true;
});
}
XHR.poll(5, '<%=url('admin/wireless_assoclist')%>', null,
function(x, st)
{
@ -58,7 +85,15 @@
E('span', wifirate(bss, true)),
E('br'),
E('span', wifirate(bss, false))
])
]),
supports_deauth[bss.ifname] ? E('input', {
type: 'button',
class: 'cbi-button cbi-button-remove',
value: '<%:Disconnect%>',
'data-bssid': bss.bssid,
'data-iface': bss.ifname,
click: handleDeauth
}) : '-'
]);
});
@ -75,6 +110,9 @@
<div class="th nowrap"><%:Host%></div>
<div class="th nowrap"><%:Signal%> / <%:Noise%></div>
<div class="th nowrap"><%:RX Rate%> / <%:TX Rate%></div>
<% if next(supports_deauth) then %>
<div class="th right"><%:Disconnect%></div>
<% end %>
</div>
<div class="tr placeholder">
<div class="td"><em><%:Collecting data...%></em></div>