1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00

Add macvlan support

This commit is contained in:
Ycarus 2018-01-23 15:36:03 +01:00
parent 40fdd921b9
commit 9f8643647e
255 changed files with 134998 additions and 0 deletions

View file

@ -0,0 +1,115 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<%
local fs = require "nixio.fs"
local has_ping6 = fs.access("/bin/ping6") or fs.access("/usr/bin/ping6")
local has_traceroute6 = fs.access("/usr/bin/traceroute6")
local dns_host = luci.config.diag and luci.config.diag.dns or "dev.openwrt.org"
local ping_host = luci.config.diag and luci.config.diag.ping or "dev.openwrt.org"
local route_host = luci.config.diag and luci.config.diag.route or "dev.openwrt.org"
%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var stxhr = new XHR();
function update_status(field, proto)
{
var tool = field.name;
var addr = field.value;
var protocol = proto ? "6" : "";
var legend = document.getElementById('diag-rc-legend');
var output = document.getElementById('diag-rc-output');
if (legend && output)
{
output.innerHTML =
'<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
'<%:Waiting for command to complete...%>'
;
legend.parentNode.style.display = 'block';
legend.style.display = 'inline';
stxhr.post('<%=url('admin/network')%>/diag_' + tool + protocol + '/' + addr, { token: '<%=token%>' },
function(x)
{
if (x.responseText)
{
legend.style.display = 'none';
output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
}
else
{
legend.style.display = 'none';
output.innerHTML = '<span class="error"><%:Bad address specified!%></span>';
}
}
);
}
}
//]]></script>
<form method="post" action="<%=url('admin/network/diagnostics')%>">
<div class="cbi-map">
<h2 name="content"><%:Diagnostics%></h2>
<fieldset class="cbi-section">
<legend><%:Network Utilities%></legend>
<br />
<div style="width:30%; float:left">
<input style="margin: 5px 0" type="text" value="<%=ping_host%>" name="ping" /><br />
<% if has_ping6 then %>
<select name="ping_proto" style="width:auto">
<option value="" selected="selected"><%:IPv4%></option>
<option value="6"><%:IPv6%></option>
</select>
<input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping, this.form.ping_proto.selectedIndex)" />
<% else %>
<input type="button" value="<%:Ping%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.ping)" />
<% end %>
</div>
<div style="width:33%; float:left">
<input style="margin: 5px 0" type="text" value="<%=route_host%>" name="traceroute" /><br />
<% if has_traceroute6 then %>
<select name="traceroute_proto" style="width:auto">
<option value="" selected="selected"><%:IPv4%></option>
<option value="6"><%:IPv6%></option>
</select>
<input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute, this.form.traceroute_proto.selectedIndex)" />
<% else %>
<input type="button" value="<%:Traceroute%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.traceroute)" />
<% end %>
<% if not has_traceroute6 then %>
<p>&#160;</p>
<p><%:Install iputils-traceroute6 for IPv6 traceroute%></p>
<% end %>
</div>
<div style="width:33%; float:left;">
<input style="margin: 5px 0" type="text" value="<%=dns_host%>" name="nslookup" /><br />
<input type="button" value="<%:Nslookup%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.nslookup)" />
</div>
<br style="clear:both" /><br />
</fieldset>
</div>
<fieldset class="cbi-section" style="display:none">
<legend id="diag-rc-legend"><%:Collecting data...%></legend>
<span id="diag-rc-output"></span>
</fieldset>
</form>
<%+footer%>

View file

@ -0,0 +1,254 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local ntm = require "luci.model.network".init()
local fwm = require "luci.model.firewall".init()
local net
local ifaces = { }
local netlist = { }
for _, net in ipairs(ntm:get_networks()) do
if net:name() ~= "loopback" then
local z = fwm:get_zone_by_network(net:name())
ifaces[#ifaces+1] = net:name()
netlist[#netlist+1] = {
net:name(), z and z:name() or "-", z
}
end
end
table.sort(netlist,
function(a, b)
if a[2] ~= b[2] then
return a[2] < b[2]
else
return a[1] < b[1]
end
end)
-%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
function iface_shutdown(id, reconnect) {
if (!reconnect && !confirm(String.format('<%_Really shutdown interface "%s" ?\nYou might lose access to this device if you are connected via this interface.%>', id)))
return;
var d = document.getElementById(id + '-ifc-description');
if (d)
d.innerHTML = reconnect
? '<em><%:Interface is reconnecting...%></em>'
: '<em><%:Interface is shutting down...%></em>';
var s = document.getElementById('ifc-rc-status');
if (s)
{
s.parentNode.style.display = 'block';
s.innerHTML = '<%:Waiting for changes to be applied...%>';
}
(new XHR()).post('<%=url('admin/network')%>/iface_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
function(x)
{
if (s)
{
s.innerHTML = reconnect
? '<%:Interface reconnected%>'
: '<%:Interface shut down%>';
window.setTimeout(function() {
s.parentNode.style.display = 'none';
}, 1000);
}
}
);
}
function iface_delete(id) {
if (!confirm('<%:Really delete this interface? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this interface.%>'))
return;
(new XHR()).post('<%=url('admin/network/iface_delete')%>/' + id, { token: '<%=token%>' },
function(x) {
location.href = '<%=url('admin/network/network')%>';
}
);
}
var iwxhr = new XHR();
var wifidevs = <%=luci.http.write_json(netdevs)%>;
var arptable = <%=luci.http.write_json(arpcache)%>;
XHR.poll(5, '<%=url('admin/network/iface_status', table.concat(ifaces, ","))%>', null,
function(x, ifcs)
{
if (ifcs)
{
for (var idx = 0; idx < ifcs.length; idx++)
{
var ifc = ifcs[idx];
var html = '';
var s = document.getElementById(ifc.id + '-ifc-devices');
if (s)
{
var stat = String.format(
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px; vertical-align:middle" />',
ifc.type,
ifc.is_up ? '' : '_disabled'
);
if (ifc.subdevices && ifc.subdevices.length)
{
stat += ' <strong>(';
for (var j = 0; j < ifc.subdevices.length; j++)
{
var sif = ifc.subdevices[j];
stat += String.format(
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px; vertical-align:middle" title="%h" />',
sif.type,
sif.is_up ? '' : '_disabled',
sif.name
);
}
stat += ')</strong>';
}
stat += String.format(
'<br /><small>%h</small>',
ifc.name
);
s.innerHTML = stat;
}
var d = document.getElementById(ifc.id + '-ifc-description');
if (d && ifc.proto && ifc.ifname)
{
if (ifc.is_up)
{
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
}
if (ifc.macaddr)
{
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
}
html += String.format(
'<strong><%:RX%></strong>: %.2mB (%d <%:Pkts.%>)<br />' +
'<strong><%:TX%></strong>: %.2mB (%d <%:Pkts.%>)<br />',
ifc.rx_bytes, ifc.rx_packets,
ifc.tx_bytes, ifc.tx_packets
);
if (ifc.ipaddrs && ifc.ipaddrs.length)
{
for (var i = 0; i < ifc.ipaddrs.length; i++)
html += String.format(
'<strong><%:IPv4%>:</strong> %s<br />',
ifc.ipaddrs[i]
);
}
if (ifc.ip6addrs && ifc.ip6addrs.length)
{
for (var i = 0; i < ifc.ip6addrs.length; i++)
html += String.format(
'<strong><%:IPv6%>:</strong> %s<br />',
ifc.ip6addrs[i]
);
}
if (ifc.ip6prefix)
{
html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
}
d.innerHTML = html;
}
else if (d && !ifc.proto)
{
var e = document.getElementById(ifc.id + '-ifc-edit');
if (e)
e.disabled = true;
d.innerHTML = String.format(
'<em><%:Unsupported protocol type.%></em><br />' +
'<a href="%h"><%:Install protocol extensions...%></a>',
'<%=url("admin/system/packages")%>?query=luci-proto&display=available'
);
}
else if (d && !ifc.ifname)
{
d.innerHTML = String.format(
'<em><%:Network without interfaces.%></em><br />' +
'<a href="<%=url("admin/network/network/%s")%>?tab.network.%s=physical"><%:Assign interfaces...%></a>',
ifc.name, ifc.name
);
}
else if (d)
{
d.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
}
}
}
}
);
//]]></script>
<fieldset class="cbi-section" style="display:none">
<legend><%:Reconnecting interface%></legend>
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
<span id="ifc-rc-status"><%:Waiting for changes to be applied...%></span>
</fieldset>
<div class="cbi-map">
<fieldset class="cbi-section">
<legend><%:Interface Overview%></legend>
<table class="cbi-section-table" style="margin:10px; empty-cells:hide">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Network%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Status%></th>
<th class="cbi-section-table-cell"><%:Actions%></th>
</tr>
<%
for i, net in ipairs(netlist) do
local z = net[3]
local c = z and z:get_color() or "#EEEEEE"
local t = z and translate("Part of zone %q" % z:name()) or translate("No zone assigned")
%>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i % 2 + 1%>">
<td class="cbi-value-field" style="padding:3px">
<div class="ifacebox">
<div class="ifacebox-head" style="background-color:<%=c%>" title="<%=pcdata(t)%>">
<strong><%=net[1]:upper()%></strong>
</div>
<div class="ifacebox-body" id="<%=net[1]%>-ifc-devices">
<img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
<small>?</small>
</div>
</div>
</td>
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=net[1]%>-ifc-description">
<em><%:Collecting data...%></em>
</td>
<td style="width:420px">
<input type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', true)" title="<%:Reconnect this interface%>" value="<%:Connect%>" />
<input type="button" class="cbi-button cbi-button-reset" style="width:100px" onclick="iface_shutdown('<%=net[1]%>', false)" title="<%:Shutdown this interface%>" value="<%:Stop%>" />
<input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit" />
<input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="iface_delete('<%=net[1]%>')" value="<%:Delete%>" />
</td>
</tr>
<% end %>
</table>
<input type="button" class="cbi-button cbi-button-add" value="<%:Add new interface...%>" onclick="location.href='<%=url("admin/network/iface_add")%>'" />
</fieldset>
</div>

View file

@ -0,0 +1,87 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url('admin/network/iface_status', self.network)%>', null,
function(x, ifc)
{
if (ifc && (ifc = ifc[0]))
{
var html = '';
var s = document.getElementById('<%=self.option%>-ifc-signal');
if (s)
s.innerHTML = String.format(
'<img src="<%=resource%>/icons/%s%s.png" style="width:16px; height:16px" />' +
'<br /><small>%s</small>',
ifc.type, ifc.is_up ? '' : '_disabled',
ifc.name
);
var d = document.getElementById('<%=self.option%>-ifc-description');
if (d && ifc.ifname)
{
if (ifc.is_up)
{
html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
}
if (ifc.macaddr)
{
html += String.format('<strong><%:MAC-Address%>:</strong> %s<br />', ifc.macaddr);
}
html += String.format(
'<strong><%:RX%></strong>: %.2mB (%d <%:Pkts.%>)<br />' +
'<strong><%:TX%></strong>: %.2mB (%d <%:Pkts.%>)<br />',
ifc.rx_bytes, ifc.rx_packets,
ifc.tx_bytes, ifc.tx_packets
);
if (ifc.ipaddrs && ifc.ipaddrs.length)
{
for (var i = 0; i < ifc.ipaddrs.length; i++)
html += String.format(
'<strong><%:IPv4%>:</strong> %s<br />',
ifc.ipaddrs[i]
);
}
if (ifc.ip6addrs && ifc.ip6addrs.length)
{
for (var i = 0; i < ifc.ip6addrs.length; i++)
html += String.format(
'<strong><%:IPv6%>:</strong> %s<br />',
ifc.ip6addrs[i]
);
}
if (ifc.ip6prefix)
{
html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
}
d.innerHTML = html;
}
else if (d)
{
d.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
}
}
}
);
//]]></script>
<table>
<tr class="cbi-section-table">
<td></td>
<td class="cbi-value-field" style="min-width:16px; padding:3px; text-align:center" id="<%=self.option%>-ifc-signal">
<img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
<small>?</small>
</td>
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=self.option%>-ifc-description">
<em><%:Collecting data...%></em>
</td>
</tr>
</table>
<%+cbi/valuefooter%>

View file

@ -0,0 +1,138 @@
<script type="text/javascript">//<![CDATA[
function duid2mac(duid) {
// DUID-LLT / Ethernet
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
// DUID-LL / Ethernet
if (duid.length === 24 && duid.substr(0, 8) === '00030001')
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
return null;
}
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
XHR.poll(5, '<%=url('admin/network/dhcplease_status')%>', null,
function(x, st)
{
var tb = document.getElementById('lease_status_table');
if (st && st[0] && tb)
{
/* clear all rows */
while( tb.rows.length > 1 )
tb.deleteRow(1);
for( var i = 0; i < st[0].length; i++ )
{
var timestr;
if (st[0][i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (st[0][i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', st[0][i].expires);
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
tr.insertCell(-1).innerHTML = st[0][i].hostname ? st[0][i].hostname : '?';
tr.insertCell(-1).innerHTML = st[0][i].ipaddr;
tr.insertCell(-1).innerHTML = st[0][i].macaddr;
tr.insertCell(-1).innerHTML = timestr;
}
if( tb.rows.length == 1 )
{
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
}
}
var tb6 = document.getElementById('lease6_status_table');
if (st && st[1] && tb6)
{
tb6.parentNode.style.display = 'block';
/* clear all rows */
while( tb6.rows.length > 1 )
tb6.deleteRow(1);
for( var i = 0; i < st[1].length; i++ )
{
var timestr;
if (st[1][i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (st[1][i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', st[1][i].expires);
var tr = tb6.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
var host = hosts[duid2mac(st[1][i].duid)];
if (host)
tr.insertCell(-1).innerHTML = String.format(
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
((host.name && (host.ipv4 || host.ipv6))
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
);
else
tr.insertCell(-1).innerHTML = st[1][i].hostname ? st[1][i].hostname : '?';
tr.insertCell(-1).innerHTML = st[1][i].ip6addr;
tr.insertCell(-1).innerHTML = st[1][i].duid;
tr.insertCell(-1).innerHTML = timestr;
}
if( tb6.rows.length == 1 )
{
var tr = tb6.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
}
}
}
);
//]]></script>
<fieldset class="cbi-section">
<legend><%:Active DHCP Leases%></legend>
<table class="cbi-section-table" id="lease_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Hostname%></th>
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
<fieldset class="cbi-section" style="display:none">
<legend><%:Active DHCPv6 Leases%></legend>
<table class="cbi-section-table" id="lease6_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Host%></th>
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
<th class="cbi-section-table-cell"><%:DUID%></th>
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>

View file

@ -0,0 +1,44 @@
<script type="text/javascript">//<![CDATA[
var switches = [ '<%=table.concat(self.switches, "', '")%>' ];
XHR.poll(5, '<%=url('admin/network/switch_status')%>/' + switches.join(','), null,
function(x, st)
{
for (var i = 0; i < switches.length; i++)
{
var ports = st[switches[i]];
var th0 = document.getElementById('portstatus-' + switches[i]);
if (th0 && ports && ports.length)
{
if (!th0.innerHTML)
th0.innerHTML = '<%:Port status:%>';
for (var j = 0; j < ports.length; j++)
{
var th = document.getElementById('portstatus-' + switches[i] + '-' + j);
if (!th)
continue;
if (ports[j].link)
{
th.innerHTML = String.format(
'<small><img src="<%=resource%>/icons/port_up.png" />' +
'<br />%d<%:baseT%><br />%s</small>',
ports[j].speed, ports[j].duplex
? '<%:full-duplex%>' : '<%:half-duplex%>'
);
}
else
{
th.innerHTML = String.format(
'<small><img src="<%=resource%>/icons/port_down.png" />' +
'<br /><%:no link%></small>'
);
}
}
}
}
}
);
//]]></script>

View file

@ -0,0 +1,149 @@
<%#
Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local sys = require "luci.sys"
local utl = require "luci.util"
function guess_wifi_signal(info)
local scale = (100 / (info.quality_max or 100) * (info.quality or 0))
local icon
if not info.bssid or info.bssid == "00:00:00:00:00:00" then
icon = resource .. "/icons/signal-none.png"
elseif scale < 15 then
icon = resource .. "/icons/signal-0.png"
elseif scale < 35 then
icon = resource .. "/icons/signal-0-25.png"
elseif scale < 55 then
icon = resource .. "/icons/signal-25-50.png"
elseif scale < 75 then
icon = resource .. "/icons/signal-50-75.png"
else
icon = resource .. "/icons/signal-75-100.png"
end
return icon
end
function percent_wifi_signal(info)
local qc = info.quality or 0
local qm = info.quality_max or 0
if info.bssid and qc > 0 and qm > 0 then
return math.floor((100 / qm) * qc)
else
return 0
end
end
function format_wifi_encryption(info)
if info.wep == true then
return "WEP"
elseif info.wpa > 0 then
return translatef("<abbr title='Pairwise: %s / Group: %s'>%s - %s</abbr>",
table.concat(info.pair_ciphers, ", "),
table.concat(info.group_ciphers, ", "),
(info.wpa == 3) and translate("mixed WPA/WPA2")
or (info.wpa == 2 and "WPA2" or "WPA"),
table.concat(info.auth_suites, ", ")
)
elseif info.enabled then
return "<em>%s</em>" % translate("unknown")
else
return "<em>%s</em>" % translate("open")
end
end
local dev = luci.http.formvalue("device")
local iw = luci.sys.wifi.getiwinfo(dev)
if not iw then
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
return
end
function scanlist(times)
local i, k, v
local l = { }
local s = { }
for i = 1, times do
for k, v in ipairs(iw.scanlist or { }) do
if not s[v.bssid] then
l[#l+1] = v
s[v.bssid] = true
end
end
end
return l
end
-%>
<%+header%>
<h2 name="content"><%:Join Network: Wireless Scan%></h2>
<div class="cbi-map">
<fieldset class="cbi-section">
<table class="cbi-section-table" style="empty-cells:hide">
<!-- scan list -->
<% for i, net in ipairs(scanlist(3)) do net.encryption = net.encryption or { } %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
<td class="cbi-value-field" style="width:16px; padding:3px">
<abbr title="<%:Signal%>: <%=net.signal%> <%:dB%> / <%:Quality%>: <%=net.quality%>/<%=net.quality_max%>">
<img src="<%=guess_wifi_signal(net)%>" /><br />
<small><%=percent_wifi_signal(net)%>%</small>
</abbr>
</td>
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px">
<big><strong><%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%></strong></big><br />
<strong>Channel:</strong> <%=net.channel%> |
<strong>Mode:</strong> <%=net.mode%> |
<strong>BSSID:</strong> <%=net.bssid%> |
<strong>Encryption:</strong> <%=format_wifi_encryption(net.encryption)%>
</td>
<td class="cbi-value-field" style="width:40px">
<form action="<%=url('admin/network/wireless_join')%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
<input type="hidden" name="join" value="<%=utl.pcdata(net.ssid)%>" />
<input type="hidden" name="mode" value="<%=net.mode%>" />
<input type="hidden" name="bssid" value="<%=net.bssid%>" />
<input type="hidden" name="channel" value="<%=net.channel%>" />
<input type="hidden" name="wep" value="<%=net.encryption.wep and 1 or 0%>" />
<% if net.encryption.wpa then %>
<input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>" />
<% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>" />
<% end; for _, v in ipairs(net.encryption.group_ciphers) do %><input type="hidden" name="wpa_group" value="<%=v%>" />
<% end; for _, v in ipairs(net.encryption.pair_ciphers) do %><input type="hidden" name="wpa_pairwise" value="<%=v%>" />
<% end; end %>
<input type="hidden" name="clbridge" value="<%=iw.type == "wl" and 1 or 0%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Join Network%>" />
</form>
</td>
</tr>
<% end %>
<!-- /scan list -->
</table>
</fieldset>
</div>
<div class="cbi-page-actions right">
<form class="inline" action="<%=url("admin/network/wireless")%>" method="get">
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Back to overview%>" />
</form>
<form class="inline" action="<%=url('admin/network/wireless_join')%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="device" value="<%=utl.pcdata(dev)%>" />
<input class="cbi-button cbi-input-find" type="submit" value="<%:Repeat scan%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,470 @@
<%#
Copyright 2008-2009 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local ip = require "luci.ip"
local fs = require "nixio.fs"
local utl = require "luci.util"
local uci = require "luci.model.uci".cursor()
local ntm = require "luci.model.network"
local has_iwinfo = pcall(require, "iwinfo")
ntm.init(uci)
function guess_wifi_hw(dev)
local bands = ""
local ifname = dev:name()
local name, idx = ifname:match("^([a-z]+)(%d+)")
idx = tonumber(idx)
if has_iwinfo then
local bl = dev.iwinfo.hwmodelist
if bl and next(bl) then
if bl.a then bands = bands .. "a" end
if bl.b then bands = bands .. "b" end
if bl.g then bands = bands .. "g" end
if bl.n then bands = bands .. "n" end
if bl.ac then bands = bands .. "ac" end
end
local hw = dev.iwinfo.hardware_name
if hw then
return "%s 802.11%s" %{ hw, bands }
end
end
-- wl.o
if name == "wl" then
local name = translatef("Broadcom 802.11%s Wireless Controller", bands)
local nm = 0
local fd = nixio.open("/proc/bus/pci/devices", "r")
if fd then
local ln
for ln in fd:linesource() do
if ln:match("wl$") then
if nm == idx then
local version = ln:match("^%S+%s+%S%S%S%S([0-9a-f]+)")
name = translatef(
"Broadcom BCM%04x 802.11 Wireless Controller",
tonumber(version, 16)
)
break
else
nm = nm + 1
end
end
end
fd:close()
end
return name
-- madwifi
elseif name == "ath" or name == "wifi" then
return translatef("Atheros 802.11%s Wireless Controller", bands)
-- ralink
elseif name == "ra" then
return translatef("RaLink 802.11%s Wireless Controller", bands)
-- hermes
elseif name == "eth" then
return translate("Hermes 802.11b Wireless Controller")
-- hostap
elseif name == "wlan" and fs.stat("/proc/net/hostap/" .. ifname, "type") == "dir" then
return translate("Prism2/2.5/3 802.11b Wireless Controller")
-- dunno yet
else
return translatef("Generic 802.11%s Wireless Controller", bands)
end
end
local devices = ntm:get_wifidevs()
local netlist = { }
local netdevs = { }
local dev
for _, dev in ipairs(devices) do
local net
for _, net in ipairs(dev:get_wifinets()) do
netlist[#netlist+1] = net:id()
netdevs[net:id()] = dev:name()
end
end
-%>
<%+header%>
<% if not has_iwinfo then %>
<div class="errorbox">
<strong><%:Package libiwinfo required!%></strong><br />
<%_The <em>libiwinfo-lua</em> package is not installed. You must install this component for working wireless configuration!%>
</div>
<% end %>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var wifidevs = <%=luci.http.write_json(netdevs)%>;
var is_reconnecting = false;
function nowrap(s) {
return s.replace(/ /g, '&#160;');
}
function wifirate(bss, rx) {
var p = rx ? 'rx_' : 'tx_',
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
ht = bss[p+'ht'], vht = bss[p+'vht'],
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
if (ht || vht) {
if (vht) s += ', VHT-MCS %d'.format(mcs);
if (nss) s += ', VHT-NSS %d'.format(nss);
if (ht) s += ', MCS %s'.format(mcs);
if (sgi) s += ', <%:Short GI%>';
}
return s;
}
function wifi_shutdown(id, toggle) {
var reconnect = (toggle.getAttribute('active') == 'false');
if (!reconnect && !confirm(String.format('<%:Really shut down network?\nYou might lose access to this device if you are connected via this interface.%>')))
return;
is_reconnecting = true;
var s = document.getElementById('iw-rc-status');
if (s)
{
s.parentNode.style.display = 'block';
s.innerHTML = '<%:Waiting for changes to be applied...%>';
}
for (var net in wifidevs)
{
var st = document.getElementById(net + '-iw-status');
if (st)
st.innerHTML = '<em><%:Wireless is restarting...%></em>';
}
(new XHR()).post('<%=url('admin/network')%>/wireless_' + (reconnect ? 'reconnect' : 'shutdown') + '/' + id, { token: '<%=token%>' },
function(x)
{
if (s)
{
s.innerHTML = reconnect
? '<%:Wireless restarted%>'
: '<%:Wireless shut down%>';
window.setTimeout(function() {
s.parentNode.style.display = 'none';
is_reconnecting = false;
}, 1000);
}
}
);
}
function wifi_delete(id) {
if (!confirm('<%:Really delete this wireless network? The deletion cannot be undone!\nYou might lose access to this device if you are connected via this network.%>'))
return;
(new XHR()).post('<%=url('admin/network/wireless_delete')%>/' + id, { token: '<%=token%>' },
function(x) {
location.href = '<%=url('admin/network/wireless')%>';
}
);
}
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
XHR.poll(5, '<%=url('admin/network/wireless_status', table.concat(netlist, ","))%>', null,
function(x, st)
{
if (st)
{
var assoctable = document.getElementById('iw-assoclist');
if (assoctable)
while (assoctable.rows.length > 1)
assoctable.rows[1].parentNode.removeChild(assoctable.rows[1]);
var devup = { };
var rowstyle = 1;
for( var i = 0; i < st.length; i++ )
{
var iw = st[i];
var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && iw.mode != 'Unknown' && !iw.disabled);
var p = iw.quality;
var q = is_assoc ? p : -1;
var icon;
if (q < 0)
icon = "<%=resource%>/icons/signal-none.png";
else if (q == 0)
icon = "<%=resource%>/icons/signal-0.png";
else if (q < 25)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (q < 50)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (q < 75)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
if (!devup[wifidevs[iw.id]])
devup[wifidevs[iw.id]] = is_assoc;
var sig = document.getElementById(iw.id + '-iw-signal');
if (sig)
sig.innerHTML = String.format(
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>"><img src="%s" /> %d%%</span>',
iw.signal, iw.noise, icon, p
);
var toggle = document.getElementById(iw.id + '-iw-toggle');
if (toggle)
{
if (!iw.disabled)
{
toggle.className = 'cbi-button cbi-button-reset';
toggle.value = '<%:Disable%>';
toggle.title = '<%:Shutdown this network%>';
}
else
{
toggle.className = 'cbi-button cbi-button-reload';
toggle.value = '<%:Enable%>';
toggle.title = '<%:Activate this network%>';
}
toggle.setAttribute('active', !iw.disabled);
}
var info = document.getElementById(iw.id + '-iw-status');
if (info)
{
if (is_assoc)
info.innerHTML = String.format(
'<strong><%:SSID%>:</strong> %h | ' +
'<strong><%:Mode%>:</strong> %s<br />' +
'<strong><%:BSSID%>:</strong> %s | ' +
'<strong><%:Encryption%>:</strong> %s',
iw.ssid, iw.mode, iw.bssid,
iw.encryption ? iw.encryption : '<%:None%>'
);
else
info.innerHTML = String.format(
'<strong><%:SSID%>:</strong> %h | ' +
'<strong><%:Mode%>:</strong> %s<br />' +
'<em>%s</em>',
iw.ssid || '?', iw.mode,
is_reconnecting
? '<em><%:Wireless is restarting...%></em>'
: '<em><%:Wireless is disabled or not associated%></em>'
);
}
var dev = document.getElementById(wifidevs[iw.id] + '-iw-devinfo');
if (dev)
{
if (is_assoc)
dev.innerHTML = String.format(
'<strong><%:Channel%>:</strong> %s (%s <%:GHz%>) | ' +
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%>',
iw.channel ? iw.channel : '?',
iw.frequency ? iw.frequency : '?',
iw.bitrate ? iw.bitrate : '?'
);
else
dev.innerHTML = '';
}
if (assoctable)
{
var assoclist = [ ];
for( var bssid in iw.assoclist )
{
assoclist.push(iw.assoclist[bssid]);
assoclist[assoclist.length-1].bssid = bssid;
}
assoclist.sort(function(a, b) { a.bssid < b.bssid });
for( var j = 0; j < assoclist.length; j++ )
{
var tr = assoctable.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + rowstyle;
var icon;
var q = (-1 * (assoclist[j].noise - assoclist[j].signal)) / 5;
if (q < 1)
icon = "<%=resource%>/icons/signal-0.png";
else if (q < 2)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (q < 3)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (q < 4)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
tr.insertCell(-1).innerHTML = String.format(
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
iw.device.name, iw.ifname
);
tr.insertCell(-1).innerHTML = nowrap(String.format('%h', iw.ssid ? iw.ssid : '?'));
tr.insertCell(-1).innerHTML = assoclist[j].bssid;
var host = hosts[assoclist[j].bssid];
if (host)
tr.insertCell(-1).innerHTML = String.format(
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
((host.name && (host.ipv4 || host.ipv6))
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
);
else
tr.insertCell(-1).innerHTML = '?';
tr.insertCell(-1).innerHTML = String.format(
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
assoclist[j].signal, assoclist[j].noise, assoclist[j].signal - assoclist[j].noise,
icon,
assoclist[j].signal, assoclist[j].noise
);
tr.insertCell(-1).innerHTML = nowrap(wifirate(assoclist[j], true)) + '<br />' + nowrap(wifirate(assoclist[j], false));
rowstyle = (rowstyle == 1) ? 2 : 1;
}
}
}
if (assoctable && assoctable.rows.length == 1)
{
var tr = assoctable.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 8;
td.innerHTML = '<br /><em><%:No information available%></em>';
}
for (var dev in devup)
{
var img = document.getElementById(dev + '-iw-upstate');
if (img)
img.src = '<%=resource%>/icons/wifi_big' + (devup[dev] ? '' : '_disabled') + '.png';
}
}
}
);
//]]></script>
<h2 name="content"><%:Wireless Overview%></h2>
<fieldset class="cbi-section" style="display:none">
<legend><%:Reconnecting interface%></legend>
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
<span id="iw-rc-status"><%:Waiting for changes to be applied...%></span>
</fieldset>
<div class="cbi-map">
<% for _, dev in ipairs(devices) do local nets = dev:get_wifinets() %>
<!-- device <%=dev:name()%> -->
<fieldset class="cbi-section">
<table class="cbi-section-table" style="margin:10px; empty-cells:hide">
<!-- physical device -->
<tr>
<td style="width:34px"><img src="<%=resource%>/icons/wifi_big_disabled.png" style="float:left; margin-right:10px" id="<%=dev:name()%>-iw-upstate" /></td>
<td colspan="2" style="text-align:left">
<big><strong><%=guess_wifi_hw(dev)%> (<%=dev:name()%>)</strong></big><br />
<span id="<%=dev:name()%>-iw-devinfo"></span>
</td>
<td style="width:310px;text-align:right">
<form action="<%=url('admin/network/wireless_join')%>" method="post" class="inline">
<input type="hidden" name="device" value="<%=dev:name()%>" />
<input type="hidden" name="token" value="<%=token%>" />
<input type="submit" class="cbi-button cbi-button-find" style="width:100px" title="<%:Find and join network%>" value="<%:Scan%>" />
</form>
<form action="<%=url('admin/network/wireless_add')%>" method="post" class="inline">
<input type="hidden" name="device" value="<%=dev:name()%>" />
<input type="hidden" name="token" value="<%=token%>" />
<input type="submit" class="cbi-button cbi-button-add" style="width:100px" title="<%:Provide new network%>" value="<%:Add%>" />
</form>
</td>
</tr>
<!-- /physical device -->
<!-- network list -->
<% if #nets > 0 then %>
<% for i, net in ipairs(nets) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
<td></td>
<td class="cbi-value-field" style="vertical-align:middle; padding:3px" id="<%=net:id()%>-iw-signal">
<span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-none.png" /> 0%</span>
</td>
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=net:id()%>-iw-status">
<em><%:Collecting data...%></em>
</td>
<td class="cbi-value-field" style="width:310px;text-align:right">
<input id="<%=net:id()%>-iw-toggle" type="button" class="cbi-button cbi-button-reload" style="width:100px" onclick="wifi_shutdown('<%=net:id()%>', this)" title="<%:Delete this network%>" value="<%:Enable%>" />
<input type="button" class="cbi-button cbi-button-edit" style="width:100px" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
<input type="button" class="cbi-button cbi-button-remove" style="width:100px" onclick="wifi_delete('<%=net:id()%>')" title="<%:Delete this network%>" value="<%:Remove%>" />
</td>
</tr>
<% end %>
<% else %>
<tr class="cbi-section-table-row cbi-rowstyle-2">
<td></td>
<td colspan="3" class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px">
<em><%:No network configured on this device%></em>
</td>
</tr>
<% end %>
<!-- /network list -->
</table>
</fieldset>
<!-- /device <%=dev:name()%> -->
<% end %>
<h2><%:Associated Stations%></h2>
<fieldset class="cbi-section">
<table class="cbi-section-table valign-middle" style="margin:10px" id="iw-assoclist">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"></th>
<th class="cbi-section-table-cell"><%:SSID%></th>
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
<th class="cbi-section-table-cell"><%:Host%></th>
<th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
<th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
</tr>
<tr class="cbi-section-table-row cbi-rowstyle-2">
<td class="cbi-value-field" colspan="6">
<em><%:Collecting data...%></em>
</td>
</tr>
</table>
</fieldset>
</div>
<%+footer%>

View file

@ -0,0 +1,78 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url('admin/network/wireless_status', self.ifname)%>', null,
function(x, iw)
{
if (iw && (iw = iw[0]))
{
var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && !iw.disabled);
var p = iw.quality;
var q = is_assoc ? p : -1;
var icon;
if (q < 0)
icon = "<%=resource%>/icons/signal-none.png";
else if (q == 0)
icon = "<%=resource%>/icons/signal-0.png";
else if (q < 25)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (q < 50)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (q < 75)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
var s = document.getElementById('<%=self.option%>-iw-signal');
if (s)
s.innerHTML = String.format(
'<img src="%s" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>" /><br />' +
'<small>%d%%</small>', icon, iw.signal, iw.noise, p
);
var d = document.getElementById('<%=self.option%>-iw-description');
if (d && is_assoc)
d.innerHTML = String.format(
'<strong><%:Mode%>:</strong> %s | ' +
'<strong><%:SSID%>:</strong> %h<br />' +
'<strong><%:BSSID%>:</strong> %s | ' +
'<strong><%:Encryption%>:</strong> %s<br />' +
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>) | ' +
'<strong><%:Tx-Power%>:</strong> %d <%:dBm%><br />' +
'<strong><%:Signal%>:</strong> %d <%:dBm%> | ' +
'<strong><%:Noise%>:</strong> %d <%:dBm%><br />' +
'<strong><%:Bitrate%>:</strong> %.1f <%:Mbit/s%> | ' +
'<strong><%:Country%>:</strong> %s',
iw.mode, iw.ssid, iw.bssid,
iw.encryption ? iw.encryption : '<%:None%>',
iw.channel, iw.frequency ? iw.frequency : 0,
iw.txpower, iw.signal, iw.noise,
iw.bitrate ? iw.bitrate : 0, iw.country
);
else if (d)
d.innerHTML = String.format(
'<strong><%:SSID%>:</strong> %h | ' +
'<strong><%:Mode%>:</strong> %s<br />' +
'<em><%:Wireless is disabled or not associated%></em>',
iw.ssid || '?', iw.mode
);
}
}
);
//]]></script>
<table>
<tr class="cbi-section-table">
<td></td>
<td class="cbi-value-field" style="width:16px; padding:3px" id="<%=self.option%>-iw-signal">
<img src="<%=resource%>/icons/signal-none.png" title="<%:Not associated%>" /><br />
<small>0%</small>
</td>
<td class="cbi-value-field" style="vertical-align:middle; text-align:left; padding:3px" id="<%=self.option%>-iw-description">
<em><%:Collecting data...%></em>
</td>
</tr>
</table>
<%+cbi/valuefooter%>

View file

@ -0,0 +1,301 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local ntm = require "luci.model.network".init()
local dev
local devices = { }
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
if dev ~= "lo" and not ntm:ignore_interface(dev) then
devices[#devices+1] = dev
end
end
local curdev = luci.http.formvalue("dev") or devices[1]
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var bwxhr = new XHR();
var G;
var TIME = 0;
var RXB = 1;
var RXP = 2;
var TXB = 3;
var TXP = 4;
var width = 760;
var height = 300;
var step = 5;
var data_wanted = Math.floor(width / step);
var data_fill = 0;
var data_stamp = 0;
var data_rx = [ ];
var data_tx = [ ];
var line_rx;
var line_tx;
var label_25;
var label_50;
var label_75;
var label_rx_cur;
var label_rx_avg;
var label_rx_peak;
var label_tx_cur;
var label_tx_avg;
var label_tx_peak;
var label_scale;
function bandwidth_label(bytes, br)
{
var uby = '<%:kB/s%>';
var kby = (bytes / 1024);
if (kby >= 1024)
{
uby = '<%:MB/s%>';
kby = kby / 1024;
}
var ubi = '<%:kbit/s%>';
var kbi = (bytes * 8 / 1024);
if (kbi >= 1024)
{
ubi = '<%:Mbit/s%>';
kbi = kbi / 1024;
}
return String.format("%f %s%s(%f %s)",
kbi.toFixed(2), ubi,
br ? '<br />' : ' ',
kby.toFixed(2), uby
);
}
/* wait for SVG */
window.setTimeout(
function() {
var svg = document.getElementById('bwsvg');
try {
G = svg.getSVGDocument
? svg.getSVGDocument() : svg.contentDocument;
}
catch(e) {
G = document.embeds['bwsvg'].getSVGDocument();
}
if (!G)
{
window.setTimeout(arguments.callee, 1000);
}
else
{
/* find sizes */
width = svg.offsetWidth - 2;
height = svg.offsetHeight - 2;
data_wanted = Math.ceil(width / step);
/* prefill datasets */
for (var i = 0; i < data_wanted; i++)
{
data_rx[i] = 0;
data_tx[i] = 0;
}
/* find svg elements */
line_rx = G.getElementById('rx');
line_tx = G.getElementById('tx');
label_25 = G.getElementById('label_25');
label_50 = G.getElementById('label_50');
label_75 = G.getElementById('label_75');
label_rx_cur = document.getElementById('rx_bw_cur');
label_rx_avg = document.getElementById('rx_bw_avg');
label_rx_peak = document.getElementById('rx_bw_peak');
label_tx_cur = document.getElementById('tx_bw_cur');
label_tx_avg = document.getElementById('tx_bw_avg');
label_tx_peak = document.getElementById('tx_bw_peak');
label_scale = document.getElementById('scale');
/* plot horizontal time interval lines */
for (var i = width % (step * 60); i < width; i += step * 60)
{
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i);
line.setAttribute('y1', 0);
line.setAttribute('x2', i);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
label_25.parentNode.appendChild(line);
label_25.parentNode.appendChild(text);
}
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
/* render datasets, start update interval */
XHR.poll(3, '<%=build_url("admin/status/realtime/bandwidth_status", curdev)%>', null,
function(x, data)
{
var data_max = 0;
var data_scale = 0;
var data_rx_avg = 0;
var data_tx_avg = 0;
var data_rx_peak = 0;
var data_tx_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
/* skip overlapping entries */
if (data[i][TIME] <= data_stamp)
continue;
/* normalize difference against time interval */
if (i > 0)
{
var time_delta = data[i][TIME] - data[i-1][TIME];
if (time_delta)
{
data_rx.push((data[i][RXB] - data[i-1][RXB]) / time_delta);
data_tx.push((data[i][TXB] - data[i-1][TXB]) / time_delta);
}
}
}
/* cut off outdated entries */
data_rx = data_rx.slice(data_rx.length - data_wanted, data_rx.length);
data_tx = data_tx.slice(data_tx.length - data_wanted, data_tx.length);
/* find peak */
for (var i = 0; i < data_rx.length; i++)
{
data_max = Math.max(data_max, data_rx[i]);
data_max = Math.max(data_max, data_tx[i]);
data_rx_peak = Math.max(data_rx_peak, data_rx[i]);
data_tx_peak = Math.max(data_tx_peak, data_tx[i]);
if (i > 0)
{
data_rx_avg = (data_rx_avg + data_rx[i]) / 2;
data_tx_avg = (data_tx_avg + data_tx[i]) / 2;
}
else
{
data_rx_avg = data_rx[i];
data_tx_avg = data_tx[i];
}
}
/* remember current timestamp, calculate horizontal scale */
data_stamp = data[data.length-1][TIME];
data_scale = height / (data_max * 1.1);
/* plot data */
var pt_rx = '0,' + height;
var pt_tx = '0,' + height;
var y_rx = 0;
var y_tx = 0;
for (var i = 0; i < data_rx.length; i++)
{
var x = i * step;
y_rx = height - Math.floor(data_rx[i] * data_scale);
y_tx = height - Math.floor(data_tx[i] * data_scale);
pt_rx += ' ' + x + ',' + y_rx;
pt_tx += ' ' + x + ',' + y_tx;
}
pt_rx += ' ' + width + ',' + y_rx + ' ' + width + ',' + height;
pt_tx += ' ' + width + ',' + y_tx + ' ' + width + ',' + height;
line_rx.setAttribute('points', pt_rx);
line_tx.setAttribute('points', pt_tx);
label_25.firstChild.data = bandwidth_label(1.1 * 0.25 * data_max);
label_50.firstChild.data = bandwidth_label(1.1 * 0.50 * data_max);
label_75.firstChild.data = bandwidth_label(1.1 * 0.75 * data_max);
label_rx_cur.innerHTML = bandwidth_label(data_rx[data_rx.length-1], true);
label_tx_cur.innerHTML = bandwidth_label(data_tx[data_tx.length-1], true);
label_rx_avg.innerHTML = bandwidth_label(data_rx_avg, true);
label_tx_avg.innerHTML = bandwidth_label(data_tx_avg, true);
label_rx_peak.innerHTML = bandwidth_label(data_rx_peak, true);
label_tx_peak.innerHTML = bandwidth_label(data_tx_peak, true);
}
);
}
}, 1000
);
//]]></script>
<h2 name="content"><%:Realtime Traffic%></h2>
<ul class="cbi-tabmenu">
<% for _, dev in ipairs(devices) do %>
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
<% end %>
</ul>
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/bandwidth.svg" />
<div style="text-align:right"><small id="scale">-</small></div>
<br />
<table style="width:100%; table-layout:fixed" cellspacing="5">
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Inbound:%></strong></td>
<td id="rx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="rx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="rx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Outbound:%></strong></td>
<td id="tx_bw_cur">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="tx_bw_avg">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="tx_bw_peak">0 <%:kbit/s%><br />(0 <%:kB/s%>)</td>
</tr>
</table>
<%+footer%>

View file

@ -0,0 +1,376 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var bwxhr = new XHR();
var G;
var TIME = 0;
var UDP = 1;
var TCP = 2;
var OTHER = 3;
var width = 760;
var height = 300;
var step = 5;
var data_wanted = Math.floor(width / step);
var data_fill = 0;
var data_stamp = 0;
var data_udp = [ ];
var data_tcp = [ ];
var data_otr = [ ];
var line_udp;
var line_tcp;
var label_25;
var label_50;
var label_75;
var label_udp_cur;
var label_udp_avg;
var label_udp_peak;
var label_tcp_cur;
var label_tcp_avg;
var label_tcp_peak;
var label_otr_cur;
var label_otr_avg;
var label_otr_peak;
var label_scale;
var conn_table;
var dns_cache = { };
/* wait for SVG */
window.setTimeout(
function() {
var svg = document.getElementById('bwsvg');
try {
G = svg.getSVGDocument
? svg.getSVGDocument() : svg.contentDocument;
}
catch(e) {
G = document.embeds['bwsvg'].getSVGDocument();
}
if (!G)
{
window.setTimeout(arguments.callee, 1000);
}
else
{
/* find sizes */
width = svg.offsetWidth - 2;
height = svg.offsetHeight - 2;
data_wanted = Math.ceil(width / step);
/* prefill datasets */
for (var i = 0; i < data_wanted; i++)
{
data_udp[i] = 0;
data_tcp[i] = 0;
data_otr[i] = 0;
}
/* find svg elements */
line_udp = G.getElementById('udp');
line_tcp = G.getElementById('tcp');
line_otr = G.getElementById('other');
label_25 = G.getElementById('label_25');
label_50 = G.getElementById('label_50');
label_75 = G.getElementById('label_75');
label_udp_cur = document.getElementById('lb_udp_cur');
label_udp_avg = document.getElementById('lb_udp_avg');
label_udp_peak = document.getElementById('lb_udp_peak');
label_tcp_cur = document.getElementById('lb_tcp_cur');
label_tcp_avg = document.getElementById('lb_tcp_avg');
label_tcp_peak = document.getElementById('lb_tcp_peak');
label_otr_cur = document.getElementById('lb_otr_cur');
label_otr_avg = document.getElementById('lb_otr_avg');
label_otr_peak = document.getElementById('lb_otr_peak');
label_scale = document.getElementById('scale');
conn_table = document.getElementById('connections');
/* plot horizontal time interval lines */
for (var i = width % (step * 60); i < width; i += step * 60)
{
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i);
line.setAttribute('y1', 0);
line.setAttribute('x2', i);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
label_25.parentNode.appendChild(line);
label_25.parentNode.appendChild(text);
}
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
/* render datasets, start update interval */
XHR.poll(3, '<%=build_url("admin/status/realtime/connections_status")%>', null,
function(x, json)
{
var conn = json.connections;
while (conn_table.rows.length > 1)
conn_table.rows[0].parentNode.deleteRow(-1);
var lookup_queue = [ ];
conn.sort(function(a, b) {
return b.bytes - a.bytes;
});
for (var i = 0; i < conn.length; i++)
{
var c = conn[i];
if ((c.src == '127.0.0.1' && c.dst == '127.0.0.1')
|| (c.src == '::1' && c.dst == '::1'))
continue;
var tr = conn_table.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
if (!dns_cache[c.src])
lookup_queue.push(c.src);
if (!dns_cache[c.dst])
lookup_queue.push(c.dst);
var src = dns_cache[c.src] || (c.layer3 == 'ipv6' ? '[' + c.src + ']' : c.src);
var dst = dns_cache[c.dst] || (c.layer3 == 'ipv6' ? '[' + c.dst + ']' : c.dst);
tr.insertCell(-1).innerHTML = c.layer3.toUpperCase();
tr.insertCell(-1).innerHTML = c.layer4.toUpperCase();
tr.insertCell(-1).innerHTML = String.format('%s:%d', src, c.sport);
tr.insertCell(-1).innerHTML = String.format('%s:%d', dst, c.dport);
var traf = tr.insertCell(-1);
traf.style.whiteSpace = 'nowrap';
traf.innerHTML = String.format('%1024.2mB (%d <%:Pkts.%>)', c.bytes, c.packets);
}
if (lookup_queue.length > 0)
XHR.get('<%=build_url("admin/status/nameinfo")%>/' + lookup_queue.slice(0, 100).join('/'), null,
function(x, json)
{
for (var addr in json)
dns_cache[addr] = json[addr];
}
);
var data = json.statistics;
var data_max = 0;
var data_scale = 0;
var data_udp_avg = 0;
var data_tcp_avg = 0;
var data_otr_avg = 0;
var data_udp_peak = 0;
var data_tcp_peak = 0;
var data_otr_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
/* skip overlapping entries */
if (data[i][TIME] <= data_stamp)
continue;
data_udp.push(data[i][UDP]);
data_tcp.push(data[i][TCP]);
data_otr.push(data[i][OTHER]);
}
/* cut off outdated entries */
data_udp = data_udp.slice(data_udp.length - data_wanted, data_udp.length);
data_tcp = data_tcp.slice(data_tcp.length - data_wanted, data_tcp.length);
data_otr = data_otr.slice(data_otr.length - data_wanted, data_otr.length);
/* find peak */
for (var i = 0; i < data_udp.length; i++)
{
data_max = Math.max(data_max, data_udp[i]);
data_max = Math.max(data_max, data_tcp[i]);
data_max = Math.max(data_max, data_otr[i]);
data_udp_peak = Math.max(data_udp_peak, data_udp[i]);
data_tcp_peak = Math.max(data_tcp_peak, data_tcp[i]);
data_otr_peak = Math.max(data_otr_peak, data_otr[i]);
if (i > 0)
{
data_udp_avg = (data_udp_avg + data_udp[i]) / 2;
data_tcp_avg = (data_tcp_avg + data_tcp[i]) / 2;
data_otr_avg = (data_otr_avg + data_otr[i]) / 2;
}
else
{
data_udp_avg = data_udp[i];
data_tcp_avg = data_tcp[i];
data_otr_avg = data_otr[i];
}
}
/* remember current timestamp, calculate horizontal scale */
data_stamp = data[data.length-1][TIME];
data_scale = height / (data_max * 1.1);
/* plot data */
var pt_udp = '0,' + height;
var pt_tcp = '0,' + height;
var pt_otr = '0,' + height;
var y_udp = 0;
var y_tcp = 0;
var y_otr = 0;
for (var i = 0; i < data_udp.length; i++)
{
var x = i * step;
y_udp = height - Math.floor(data_udp[i] * data_scale);
y_tcp = height - Math.floor(data_tcp[i] * data_scale);
y_otr = height - Math.floor(data_otr[i] * data_scale);
pt_udp += ' ' + x + ',' + y_udp;
pt_tcp += ' ' + x + ',' + y_tcp;
pt_otr += ' ' + x + ',' + y_otr;
}
pt_udp += ' ' + width + ',' + y_udp + ' ' + width + ',' + height;
pt_tcp += ' ' + width + ',' + y_tcp + ' ' + width + ',' + height;
pt_otr += ' ' + width + ',' + y_otr + ' ' + width + ',' + height;
var order = [
[ line_udp, data_udp[data_udp.length-1] ],
[ line_tcp, data_tcp[data_tcp.length-1] ],
[ line_otr, data_otr[data_otr.length-1] ]
];
order.sort(function(a, b) { return b[1] - a[1] });
for (var i = 0; i < order.length; i++)
order[i][0].parentNode.appendChild(order[i][0]);
line_udp.setAttribute('points', pt_udp);
line_tcp.setAttribute('points', pt_tcp);
line_otr.setAttribute('points', pt_otr);
label_25.firstChild.data = Math.floor(1.1 * 0.25 * data_max);
label_50.firstChild.data = Math.floor(1.1 * 0.50 * data_max);
label_75.firstChild.data = Math.floor(1.1 * 0.75 * data_max);
label_udp_cur.innerHTML = Math.floor(data_udp[data_udp.length-1]);
label_tcp_cur.innerHTML = Math.floor(data_tcp[data_tcp.length-1]);
label_otr_cur.innerHTML = Math.floor(data_otr[data_otr.length-1]);
label_udp_avg.innerHTML = Math.floor(data_udp_avg);
label_tcp_avg.innerHTML = Math.floor(data_tcp_avg);
label_otr_avg.innerHTML = Math.floor(data_otr_avg);
label_udp_peak.innerHTML = Math.floor(data_udp_peak);
label_tcp_peak.innerHTML = Math.floor(data_tcp_peak);
label_otr_peak.innerHTML = Math.floor(data_otr_peak);
}
);
}
}, 1000
);
//]]></script>
<h2 name="content"><%:Realtime Connections%></h2>
<div class="cbi-map-descr"><%:This page gives an overview over currently active network connections.%></div>
<fieldset class="cbi-section" id="cbi-table-table">
<legend><%:Active Connections%></legend>
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/connections.svg" />
<div style="text-align:right"><small id="scale">-</small></div>
<br />
<table style="width:100%; table-layout:fixed" cellspacing="5">
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:UDP:%></strong></td>
<td id="lb_udp_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_udp_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_udp_peak">0</td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:TCP:%></strong></td>
<td id="lb_tcp_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_tcp_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_tcp_peak">0</td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Other:%></strong></td>
<td id="lb_otr_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_otr_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_otr_peak">0</td>
</tr>
</table>
<br />
<div class="cbi-section-node">
<table class="cbi-section-table" id="connections">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Network%></th>
<th class="cbi-section-table-cell"><%:Protocol%></th>
<th class="cbi-section-table-cell"><%:Source%></th>
<th class="cbi-section-table-cell"><%:Destination%></th>
<th class="cbi-section-table-cell"><%:Transfer%></th>
</tr>
<tr><td colspan="5"><em><%:Collecting data...%></em></td></tr>
</table>
</div>
</fieldset>
<%+footer%>

View file

@ -0,0 +1,12 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Kernel Log%></h2>
<div id="content_syslog">
<textarea readonly="readonly" wrap="off" rows="<%=dmesg:cmatch("\n")+2%>" id="syslog"><%=dmesg:pcdata()%></textarea>
</div>
<%+footer%>

View file

@ -0,0 +1,827 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%
local fs = require "nixio.fs"
local util = require "luci.util"
local stat = require "luci.tools.status"
local ver = require "luci.version"
local has_ipv6 = fs.access("/proc/net/ipv6_route")
local has_dhcp = fs.access("/etc/config/dhcp")
local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
local sysinfo = luci.util.ubus("system", "info") or { }
local boardinfo = luci.util.ubus("system", "board") or { }
local unameinfo = nixio.uname() or { }
local meminfo = sysinfo.memory or {
total = 0,
free = 0,
buffered = 0,
shared = 0
}
local swapinfo = sysinfo.swap or {
total = 0,
free = 0
}
local has_dsl = fs.access("/etc/init.d/dsl_control")
if luci.http.formvalue("status") == "1" then
local ntm = require "luci.model.network".init()
local wan = ntm:get_wannet()
local wan6 = ntm:get_wan6net()
local conn_count = tonumber(
fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count")) or 0
local conn_max = tonumber((
luci.sys.exec("sysctl net.nf_conntrack_max") or
luci.sys.exec("sysctl net.ipv4.netfilter.ip_conntrack_max") or
""):match("%d+")) or 4096
local rv = {
uptime = sysinfo.uptime or 0,
localtime = os.date(),
loadavg = sysinfo.load or { 0, 0, 0 },
memory = meminfo,
swap = swapinfo,
connmax = conn_max,
conncount = conn_count,
leases = stat.dhcp_leases(),
leases6 = stat.dhcp6_leases(),
wifinets = stat.wifi_networks()
}
if wan then
rv.wan = {
ipaddr = wan:ipaddr(),
gwaddr = wan:gwaddr(),
netmask = wan:netmask(),
dns = wan:dnsaddrs(),
expires = wan:expires(),
uptime = wan:uptime(),
proto = wan:proto(),
ifname = wan:ifname(),
link = wan:adminlink()
}
end
if wan6 then
rv.wan6 = {
ip6addr = wan6:ip6addr(),
gw6addr = wan6:gw6addr(),
dns = wan6:dns6addrs(),
ip6prefix = wan6:ip6prefix(),
uptime = wan6:uptime(),
proto = wan6:proto(),
ifname = wan6:ifname(),
link = wan6:adminlink()
}
end
if has_dsl then
local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
local dsl_func = loadstring(dsl_stat)
if dsl_func then
rv.dsl = dsl_func()
end
end
luci.http.prepare_content("application/json")
luci.http.write_json(rv)
return
elseif luci.http.formvalue("hosts") == "1" then
luci.http.prepare_content("application/json")
luci.http.write_json(luci.sys.net.host_hints())
return
end
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
function progressbar(v, m)
{
var vn = parseInt(v) || 0;
var mn = parseInt(m) || 100;
var pc = Math.floor((100 / mn) * vn);
return String.format(
'<div style="width:200px; position:relative; border:1px solid #999999">' +
'<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
'<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
'<small>%s / %s (%d%%)</small>' +
'</div>' +
'</div>' +
'</div>', pc, v, m, pc
);
}
function wifirate(bss, rx) {
var p = rx ? 'rx_' : 'tx_',
s = '%.1f <%:Mbit/s%>, %d<%:MHz%>'
.format(bss[p+'rate'] / 1000, bss[p+'mhz']),
ht = bss[p+'ht'], vht = bss[p+'vht'],
mhz = bss[p+'mhz'], nss = bss[p+'nss'],
mcs = bss[p+'mcs'], sgi = bss[p+'short_gi'];
if (ht || vht) {
if (vht) s += ', VHT-MCS %d'.format(mcs);
if (nss) s += ', VHT-NSS %d'.format(nss);
if (ht) s += ', MCS %s'.format(mcs);
if (sgi) s += ', <%:Short GI%>';
}
return s;
}
function duid2mac(duid) {
// DUID-LLT / Ethernet
if (duid.length === 28 && duid.substr(0, 8) === '00010001')
return duid.substr(16).replace(/(..)(?=..)/g, '$1:').toUpperCase();
// DUID-LL / Ethernet
if (duid.length === 24 && duid.substr(0, 8) === '00030001')
return duid.substr(8).replace(/(..)(?=..)/g, '$1:').toUpperCase();
return null;
}
var npoll = 1;
var hosts = <%=luci.http.write_json(luci.sys.net.host_hints())%>;
function updateHosts() {
XHR.get('<%=REQUEST_URI%>', { hosts: 1 }, function(x, data) {
hosts = data;
});
}
XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
function(x, info)
{
if (!(npoll++ % 5))
updateHosts();
var si = document.getElementById('wan4_i');
var ss = document.getElementById('wan4_s');
var ifc = info.wan;
if (ifc && ifc.ifname && ifc.proto != 'none')
{
var s = String.format(
'<strong><%:Type%>: </strong>%s<br />' +
'<strong><%:Address%>: </strong>%s<br />' +
'<strong><%:Netmask%>: </strong>%s<br />' +
'<strong><%:Gateway%>: </strong>%s<br />',
ifc.proto,
(ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
(ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
(ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0'
);
for (var i = 0; i < ifc.dns.length; i++)
{
s += String.format(
'<strong><%:DNS%> %d: </strong>%s<br />',
i + 1, ifc.dns[i]
);
}
if (ifc.expires > -1)
{
s += String.format(
'<strong><%:Expires%>: </strong>%t<br />',
ifc.expires
);
}
if (ifc.uptime > 0)
{
s += String.format(
'<strong><%:Connected%>: </strong>%t<br />',
ifc.uptime
);
}
ss.innerHTML = String.format('<small>%s</small>', s);
si.innerHTML = String.format(
'<img src="<%=resource%>/icons/ethernet.png" />' +
'<br /><small><a href="%s">%s</a></small>',
ifc.link, ifc.ifname
);
}
else
{
si.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
ss.innerHTML = '<em><%:Not connected%></em>';
}
<% if has_ipv6 then %>
var si6 = document.getElementById('wan6_i');
var ss6 = document.getElementById('wan6_s');
var ifc6 = info.wan6;
if (ifc6 && ifc6.ifname && ifc6.proto != 'none')
{
var s = String.format(
'<strong><%:Type%>: </strong>%s%s<br />',
ifc6.proto, (ifc6.ip6prefix) ? '-pd' : ''
);
if (!ifc6.ip6prefix)
{
s += String.format(
'<strong><%:Address%>: </strong>%s<br />',
(ifc6.ip6addr) ? ifc6.ip6addr : '::'
);
}
else
{
s += String.format(
'<strong><%:Prefix Delegated%>: </strong>%s<br />',
ifc6.ip6prefix
);
if (ifc6.ip6addr)
{
s += String.format(
'<strong><%:Address%>: </strong>%s<br />',
ifc6.ip6addr
);
}
}
s += String.format(
'<strong><%:Gateway%>: </strong>%s<br />',
(ifc6.gw6addr) ? ifc6.gw6addr : '::'
);
for (var i = 0; i < ifc6.dns.length; i++)
{
s += String.format(
'<strong><%:DNS%> %d: </strong>%s<br />',
i + 1, ifc6.dns[i]
);
}
if (ifc6.uptime > 0)
{
s += String.format(
'<strong><%:Connected%>: </strong>%t<br />',
ifc6.uptime
);
}
ss6.innerHTML = String.format('<small>%s</small>', s);
si6.innerHTML = String.format(
'<img src="<%=resource%>/icons/ethernet.png" />' +
'<br /><small><a href="%s">%s</a></small>',
ifc6.link, ifc6.ifname
);
}
else
{
si6.innerHTML = '<img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small>';
ss6.innerHTML = '<em><%:Not connected%></em>';
}
<% end %>
<% if has_dsl then %>
var dsl_i = document.getElementById('dsl_i');
var dsl_s = document.getElementById('dsl_s');
var s = String.format(
'<strong><%:Status%>: </strong>%s<br />' +
'<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
'<strong><%:Line Mode%>: </strong>%s<br />' +
'<strong><%:Annex%>: </strong>%s<br />' +
'<strong><%:Profile%>: </strong>%s<br />' +
'<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
'<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
'<strong><%:Latency%>: </strong>%s / %s<br />' +
'<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
'<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
'<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
'<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
'<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
'<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
'<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
'<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
'<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
'<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
'<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
'<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
'<strong><%:Line Uptime%>: </strong>%s<br />' +
'<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
'<strong><%:Power Management Mode%>: </strong>%s<br />',
info.dsl.line_state, info.dsl.line_state_detail,
info.dsl.line_state_num,
info.dsl.line_mode_s,
info.dsl.annex_s,
info.dsl.profile_s,
info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
info.dsl.latency_num_down, info.dsl.latency_num_up,
info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
info.dsl.noise_margin_down, info.dsl.noise_margin_up,
info.dsl.actatp_down, info.dsl.actatp_up,
info.dsl.errors_fec_near, info.dsl.errors_fec_far,
info.dsl.errors_es_near, info.dsl.errors_es_far,
info.dsl.errors_ses_near, info.dsl.errors_ses_far,
info.dsl.errors_loss_near, info.dsl.errors_loss_far,
info.dsl.errors_uas_near, info.dsl.errors_uas_far,
info.dsl.errors_hec_near, info.dsl.errors_hec_far,
info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
info.dsl.line_uptime_s,
info.dsl.atuc_vendor_id,
info.dsl.power_mode_s
);
dsl_s.innerHTML = String.format('<small>%s</small>', s);
dsl_i.innerHTML = String.format(
'<img src="<%=resource%>/icons/ethernet.png" />' +
'<br /><small>DSL</small>'
);
<% end %>
<% if has_dhcp then %>
var ls = document.getElementById('lease_status_table');
if (ls)
{
/* clear all rows */
while( ls.rows.length > 1 )
ls.rows[0].parentNode.deleteRow(1);
for( var i = 0; i < info.leases.length; i++ )
{
var timestr;
if (info.leases[i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (info.leases[i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', info.leases[i].expires);
var tr = ls.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
tr.insertCell(-1).innerHTML = info.leases[i].hostname ? info.leases[i].hostname : '?';
tr.insertCell(-1).innerHTML = info.leases[i].ipaddr;
tr.insertCell(-1).innerHTML = info.leases[i].macaddr;
tr.insertCell(-1).innerHTML = timestr;
}
if( ls.rows.length == 1 )
{
var tr = ls.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
}
}
var ls6 = document.getElementById('lease6_status_table');
if (ls6 && info.leases6)
{
ls6.parentNode.style.display = 'block';
/* clear all rows */
while( ls6.rows.length > 1 )
ls6.rows[0].parentNode.deleteRow(1);
for( var i = 0; i < info.leases6.length; i++ )
{
var timestr;
if (info.leases6[i].expires === false)
timestr = '<em><%:unlimited%></em>';
else if (info.leases6[i].expires <= 0)
timestr = '<em><%:expired%></em>';
else
timestr = String.format('%t', info.leases6[i].expires);
var tr = ls6.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
var host = hosts[duid2mac(info.leases6[i].duid)];
if (host)
tr.insertCell(-1).innerHTML = String.format(
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
((host.name && (host.ipv4 || host.ipv6))
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
);
else
tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
tr.insertCell(-1).innerHTML = info.leases6[i].duid;
tr.insertCell(-1).innerHTML = timestr;
}
if( ls6.rows.length == 1 )
{
var tr = ls6.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 4;
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
}
}
<% end %>
<% if has_wifi then %>
var assoclist = [ ];
var ws = document.getElementById('wifi_status_table');
if (ws)
{
var wsbody = ws.rows[0].parentNode;
while (ws.rows.length > 0)
wsbody.deleteRow(0);
for (var didx = 0; didx < info.wifinets.length; didx++)
{
var dev = info.wifinets[didx];
var tr = wsbody.insertRow(-1);
var td;
td = tr.insertCell(-1);
td.width = "33%";
td.innerHTML = dev.name;
td.style.verticalAlign = "top";
td = tr.insertCell(-1);
var s = '';
for (var nidx = 0; nidx < dev.networks.length; nidx++)
{
var net = dev.networks[nidx];
var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
var icon;
if (!is_assoc)
icon = "<%=resource%>/icons/signal-none.png";
else if (net.quality == 0)
icon = "<%=resource%>/icons/signal-0.png";
else if (net.quality < 25)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (net.quality < 50)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (net.quality < 75)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
s += String.format(
'<table><tr><td style="text-align:center; width:32px; padding:3px">' +
'<img src="%s" title="<%:Signal%>: %d dBm / <%:Noise%>: %d dBm" />' +
'<br /><small>%d%%</small>' +
'</td><td style="text-align:left; padding:3px"><small>' +
'<strong><%:SSID%>:</strong> <a href="%s">%h</a><br />' +
'<strong><%:Mode%>:</strong> %s<br />' +
'<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
'<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%><br />',
icon, net.signal, net.noise,
net.quality,
net.link, net.ssid || '?',
net.mode,
net.channel, net.frequency,
net.bitrate || '?'
);
if (is_assoc)
{
s += String.format(
'<strong><%:BSSID%>:</strong> %s<br />' +
'<strong><%:Encryption%>:</strong> %s',
net.bssid || '?',
net.encryption
);
}
else
{
s += '<em><%:Wireless is disabled or not associated%></em>';
}
s += '</small></td></tr></table>';
for (var bssid in net.assoclist)
{
var bss = net.assoclist[bssid];
bss.bssid = bssid;
bss.link = net.link;
bss.name = net.name;
bss.ifname = net.ifname;
bss.radio = dev.name;
assoclist.push(bss);
}
}
if (!s)
s = '<em><%:No information available%></em>';
td.innerHTML = s;
}
}
var ac = document.getElementById('wifi_assoc_table');
if (ac)
{
/* clear all rows */
while( ac.rows.length > 1 )
ac.rows[0].parentNode.deleteRow(1);
assoclist.sort(function(a, b) {
return (a.name == b.name)
? (a.bssid < b.bssid)
: (a.name > b.name )
;
});
for( var i = 0; i < assoclist.length; i++ )
{
var tr = ac.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (1 + (i % 2));
var icon;
var q = (-1 * (assoclist[i].noise - assoclist[i].signal)) / 5;
if (q < 1)
icon = "<%=resource%>/icons/signal-0.png";
else if (q < 2)
icon = "<%=resource%>/icons/signal-0-25.png";
else if (q < 3)
icon = "<%=resource%>/icons/signal-25-50.png";
else if (q < 4)
icon = "<%=resource%>/icons/signal-50-75.png";
else
icon = "<%=resource%>/icons/signal-75-100.png";
tr.insertCell(-1).innerHTML = String.format(
'<span class="ifacebadge" title="%q"><img src="<%=resource%>/icons/wifi.png" /> %h</span>',
assoclist[i].radio, assoclist[i].ifname
);
tr.insertCell(-1).innerHTML = String.format(
'<a href="%s">%s</a>',
assoclist[i].link,
'%h'.format(assoclist[i].name).nobr()
);
tr.insertCell(-1).innerHTML = assoclist[i].bssid;
var host = hosts[assoclist[i].bssid];
if (host)
tr.insertCell(-1).innerHTML = String.format(
'<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
((host.name && (host.ipv4 || host.ipv6))
? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
: '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
);
else
tr.insertCell(-1).innerHTML = '?';
tr.insertCell(-1).innerHTML = String.format(
'<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%> / <%:SNR%>: %d"><img src="%s" /> %d / %d <%:dBm%></span>',
assoclist[i].signal, assoclist[i].noise, assoclist[i].signal - assoclist[i].noise,
icon,
assoclist[i].signal, assoclist[i].noise
);
tr.insertCell(-1).innerHTML = wifirate(assoclist[i], true).nobr() + '<br />' + wifirate(assoclist[i], false).nobr();
}
if (ac.rows.length == 1)
{
var tr = ac.rows[0].parentNode.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 7;
td.innerHTML = '<br /><em><%:No information available%></em>';
}
}
<% end %>
var e;
if (e = document.getElementById('localtime'))
e.innerHTML = info.localtime;
if (e = document.getElementById('uptime'))
e.innerHTML = String.format('%t', info.uptime);
if (e = document.getElementById('loadavg'))
e.innerHTML = String.format(
'%.02f, %.02f, %.02f',
info.loadavg[0] / 65535.0,
info.loadavg[1] / 65535.0,
info.loadavg[2] / 65535.0
);
if (e = document.getElementById('memtotal'))
e.innerHTML = progressbar(
((info.memory.free + info.memory.buffered) / 1024) + " <%:kB%>",
(info.memory.total / 1024) + " <%:kB%>"
);
if (e = document.getElementById('memfree'))
e.innerHTML = progressbar(
(info.memory.free / 1024) + " <%:kB%>",
(info.memory.total / 1024) + " <%:kB%>"
);
if (e = document.getElementById('membuff'))
e.innerHTML = progressbar(
(info.memory.buffered / 1024) + " <%:kB%>",
(info.memory.total / 1024) + " <%:kB%>"
);
if (e = document.getElementById('swaptotal'))
e.innerHTML = progressbar(
(info.swap.free / 1024) + " <%:kB%>",
(info.swap.total / 1024) + " <%:kB%>"
);
if (e = document.getElementById('swapfree'))
e.innerHTML = progressbar(
(info.swap.free / 1024) + " <%:kB%>",
(info.swap.total / 1024) + " <%:kB%>"
);
if (e = document.getElementById('conns'))
e.innerHTML = progressbar(info.conncount, info.connmax);
}
);
//]]></script>
<h2 name="content"><%:Status%></h2>
<fieldset class="cbi-section">
<legend><%:System%></legend>
<table width="100%" cellspacing="10">
<tr><td width="33%"><%:Hostname%></td><td><%=luci.sys.hostname() or "?"%></td></tr>
<tr><td width="33%"><%:Model%></td><td><%=pcdata(boardinfo.model or boardinfo.system or "?")%></td></tr>
<tr><td width="33%"><%:Firmware Version%></td><td>
<%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
<%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
</td></tr>
<tr><td width="33%"><%:Kernel Version%></td><td><%=unameinfo.release or "?"%></td></tr>
<tr><td width="33%"><%:Local Time%></td><td id="localtime">-</td></tr>
<tr><td width="33%"><%:Uptime%></td><td id="uptime">-</td></tr>
<tr><td width="33%"><%:Load Average%></td><td id="loadavg">-</td></tr>
</table>
</fieldset>
<fieldset class="cbi-section">
<legend><%:Memory%></legend>
<table width="100%" cellspacing="10">
<tr><td width="33%"><%:Total Available%></td><td id="memtotal">-</td></tr>
<tr><td width="33%"><%:Free%></td><td id="memfree">-</td></tr>
<tr><td width="33%"><%:Buffered%></td><td id="membuff">-</td></tr>
</table>
</fieldset>
<% if swapinfo.total > 0 then %>
<fieldset class="cbi-section">
<legend><%:Swap%></legend>
<table width="100%" cellspacing="10">
<tr><td width="33%"><%:Total Available%></td><td id="swaptotal">-</td></tr>
<tr><td width="33%"><%:Free%></td><td id="swapfree">-</td></tr>
</table>
</fieldset>
<% end %>
<fieldset class="cbi-section">
<legend><%:Network%></legend>
<table width="100%" cellspacing="10">
<tr><td width="33%" style="vertical-align:top"><%:IPv4 WAN Status%></td><td>
<table><tr>
<td id="wan4_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
<td id="wan4_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
</tr></table>
</td></tr>
<% if has_ipv6 then %>
<tr><td width="33%" style="vertical-align:top"><%:IPv6 WAN Status%></td><td>
<table><tr>
<td id="wan6_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
<td id="wan6_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
</tr></table>
</td></tr>
<% end %>
<tr><td width="33%"><%:Active Connections%></td><td id="conns">-</td></tr>
</table>
</fieldset>
<% if has_dhcp then %>
<fieldset class="cbi-section">
<legend><%:DHCP Leases%></legend>
<table class="cbi-section-table" id="lease_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Hostname%></th>
<th class="cbi-section-table-cell"><%:IPv4-Address%></th>
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
<fieldset class="cbi-section" style="display:none">
<legend><%:DHCPv6 Leases%></legend>
<table class="cbi-section-table" id="lease6_status_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Host%></th>
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
<th class="cbi-section-table-cell"><%:DUID%></th>
<th class="cbi-section-table-cell"><%:Leasetime remaining%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="4"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
<% end %>
<% if has_dsl then %>
<fieldset class="cbi-section">
<legend><%:DSL%></legend>
<table width="100%" cellspacing="10">
<tr><td width="33%" style="vertical-align:top"><%:DSL Status%></td><td>
<table><tr>
<td id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></td>
<td id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></td>
</tr></table>
</td></tr>
</table>
</fieldset>
<% end %>
<% if has_wifi then %>
<fieldset class="cbi-section">
<legend><%:Wireless%></legend>
<table id="wifi_status_table" width="100%" cellspacing="10">
<tr><td><em><%:Collecting data...%></em></td></tr>
</table>
</fieldset>
<fieldset class="cbi-section">
<legend><%:Associated Stations%></legend>
<table class="cbi-section-table valign-middle" id="wifi_assoc_table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell">&#160;</th>
<th class="cbi-section-table-cell"><%:Network%></th>
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
<th class="cbi-section-table-cell"><%:Host%></th>
<th class="cbi-section-table-cell"><%:Signal%> / <%:Noise%></th>
<th class="cbi-section-table-cell"><%:RX Rate%> / <%:TX Rate%></th>
</tr>
<tr class="cbi-section-table-row">
<td colspan="6"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>
<% end %>
<%-
local incdir = util.libpath() .. "/view/admin_status/index/"
if fs.access(incdir) then
local inc
for inc in fs.dir(incdir) do
if inc:match("%.htm$") then
include("admin_status/index/" .. inc:gsub("%.htm$", ""))
end
end
end
-%>
<%+footer%>

View file

@ -0,0 +1,156 @@
<%#
Copyright 2008-2009 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
require "luci.sys.iptparser"
local wba = require "luci.tools.webadmin"
local fs = require "nixio.fs"
local io = require "io"
local has_ip6tables = fs.access("/usr/sbin/ip6tables")
local mode = 4
if has_ip6tables then
mode = luci.dispatcher.context.requestpath
mode = tonumber(mode[#mode] ~= "iptables" and mode[#mode]) or 4
end
local ipt = luci.sys.iptparser.IptParser(mode)
local rowcnt = 1
function rowstyle()
rowcnt = rowcnt + 1
return (rowcnt % 2) + 1
end
function link_target(t,c)
if ipt:is_custom_target(c) then
return '<a href="#rule_%s_%s">%s</a>' %{ t:lower(), c, c }
end
return c
end
function link_iface(i)
local net = wba.iface_get_network(i)
if net and i ~= "lo" then
return '<a href="%s">%s</a>' %{
url("admin/network/network", net), i
}
end
return i
end
local tables = { "Filter", "NAT", "Mangle", "Raw" }
if mode == 6 then
tables = { "Filter", "Mangle", "Raw" }
local ok, lines = pcall(io.lines, "/proc/net/ip6_tables_names")
if ok and lines then
local line
for line in lines do
if line == "nat" then
tables = { "Filter", "NAT", "Mangle", "Raw" }
end
end
end
end
-%>
<%+header%>
<style type="text/css">
span:target {
color: blue;
text-decoration: underline;
}
</style>
<h2 name="content"><%:Firewall Status%></h2>
<br />
<% if has_ip6tables then %>
<ul class="cbi-tabmenu">
<li class="cbi-tab<%= mode ~= 4 and "-disabled" %>"><a href="<%=url("admin/status/iptables/4")%>"><%:IPv4 Firewall%></a></li>
<li class="cbi-tab<%= mode ~= 6 and "-disabled" %>"><a href="<%=url("admin/status/iptables/6")%>"><%:IPv6 Firewall%></a></li>
</ul>
<% end %>
<div class="cbi-map" style="position: relative">
<form method="post" action="<%=url("admin/status/iptables_action")%>" style="position: absolute; right: 0">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="family" value="<%=mode%>" />
<input type="submit" class="cbi-button" name="zero" value="<%:Reset Counters%>" />
<input type="submit" class="cbi-button" name="restart" value="<%:Restart Firewall%>" />
</form>
<fieldset class="cbi-section">
<% for _, tbl in ipairs(tables) do chaincnt = 0 %>
<h3><%:Table%>: <%=tbl%></h3>
<table class="cbi-section-table" style="font-size:90%">
<% for _, chain in ipairs(ipt:chains(tbl)) do
rowcnt = 0
chaincnt = chaincnt + 1
chaininfo = ipt:chain(tbl, chain)
%>
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
<th class="cbi-section-table-cell" style="text-align:left" colspan="11">
<br /><span id="rule_<%=tbl:lower()%>_<%=chain%>">
<%:Chain%> <em><%=chain%></em>
(<%- if chaininfo.policy then -%>
<%:Policy%>: <em><%=chaininfo.policy%></em>, <%:Packets%>: <%=chaininfo.packets%>, <%:Traffic%>: <%=wba.byte_format(chaininfo.bytes)-%>
<%- else -%>
<%:References%>: <%=chaininfo.references-%>
<%- end -%>)</span>
</th>
</tr>
<tr class="cbi-section-table-descr">
<th class="cbi-section-table-cell"><%:Pkts.%></th>
<th class="cbi-section-table-cell"><%:Traffic%></th>
<th class="cbi-section-table-cell"><%:Target%></th>
<th class="cbi-section-table-cell"><%:Prot.%></th>
<th class="cbi-section-table-cell"><%:In%></th>
<th class="cbi-section-table-cell"><%:Out%></th>
<th class="cbi-section-table-cell"><%:Source%></th>
<th class="cbi-section-table-cell"><%:Destination%></th>
<th class="cbi-section-table-cell" style="width:30%"><%:Options%></th>
</tr>
<% for _, rule in ipairs(ipt:find({table=tbl, chain=chain})) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
<td><%=rule.packets%></td>
<td style="white-space: nowrap"><%=wba.byte_format(rule.bytes)%></td>
<td><%=rule.target and link_target(tbl, rule.target) or "-"%></td>
<td><%=rule.protocol%></td>
<td><%=link_iface(rule.inputif)%></td>
<td><%=link_iface(rule.outputif)%></td>
<td><%=rule.source%></td>
<td><%=rule.destination%></td>
<td style="width:30%"><small><%=#rule.options > 0 and luci.util.pcdata(table.concat(rule.options, " ")) or "-"%></small></td>
</tr>
<% end %>
<% if rowcnt == 1 then %>
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
<td colspan="9"><em><%:No rules in this chain%></em></td>
</tr>
<% end %>
<% end %>
<% if chaincnt == 0 then %>
<tr class="cbi-section-table-titles cbi-rowstyle-<%=rowstyle()%>">
<td colspan="9"><em><%:No chains in this table%></em></td>
</tr>
<% end %>
</table>
<br /><br />
<% end %>
</fieldset>
</div>
<%+footer%>

View file

@ -0,0 +1,284 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var bwxhr = new XHR();
var G;
var TIME = 0;
var L01 = 1;
var L05 = 2;
var L15 = 3;
var width = 760;
var height = 300;
var step = 5;
var data_wanted = Math.floor(width / step);
var data_fill = 0;
var data_stamp = 0;
var data_01 = [ ];
var data_05 = [ ];
var data_15 = [ ];
var line_01;
var line_05;
var line_15;
var label_25;
var label_050;
var label_75;
var label_01_cur;
var label_01_avg;
var label_01_peak;
var label_05_cur;
var label_05_avg;
var label_05_peak;
var label_15_cur;
var label_15_avg;
var label_15_peak;
var label_scale;
/* wait for SVG */
window.setTimeout(
function() {
var svg = document.getElementById('bwsvg');
try {
G = svg.getSVGDocument
? svg.getSVGDocument() : svg.contentDocument;
}
catch(e) {
G = document.embeds['bwsvg'].getSVGDocument();
}
if (!G)
{
window.setTimeout(arguments.callee, 1000);
}
else
{
/* find sizes */
width = svg.offsetWidth - 2;
height = svg.offsetHeight - 2;
data_wanted = Math.ceil(width / step);
/* prefill datasets */
for (var i = 0; i < data_wanted; i++)
{
data_01[i] = 0;
data_05[i] = 0;
data_15[i] = 0;
}
/* find svg elements */
line_01 = G.getElementById('load01');
line_05 = G.getElementById('load05');
line_15 = G.getElementById('load15');
label_25 = G.getElementById('label_25');
label_50 = G.getElementById('label_50');
label_75 = G.getElementById('label_75');
label_01_cur = document.getElementById('lb_load01_cur');
label_01_avg = document.getElementById('lb_load01_avg');
label_01_peak = document.getElementById('lb_load01_peak');
label_05_cur = document.getElementById('lb_load05_cur');
label_05_avg = document.getElementById('lb_load05_avg');
label_05_peak = document.getElementById('lb_load05_peak');
label_15_cur = document.getElementById('lb_load15_cur');
label_15_avg = document.getElementById('lb_load15_avg');
label_15_peak = document.getElementById('lb_load15_peak');
label_scale = document.getElementById('scale');
/* plot horizontal time interval lines */
for (var i = width % (step * 60); i < width; i += step * 60)
{
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i);
line.setAttribute('y1', 0);
line.setAttribute('x2', i);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
label_25.parentNode.appendChild(line);
label_25.parentNode.appendChild(text);
}
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
/* render datasets, start update interval */
XHR.poll(3, '<%=build_url("admin/status/realtime/load_status")%>', null,
function(x, data)
{
var data_max = 0;
var data_scale = 0;
var data_01_avg = 0;
var data_05_avg = 0;
var data_15_avg = 0;
var data_01_peak = 0;
var data_05_peak = 0;
var data_15_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
/* skip overlapping entries */
if (data[i][TIME] <= data_stamp)
continue;
data_01.push(data[i][L01]);
data_05.push(data[i][L05]);
data_15.push(data[i][L15]);
}
/* cut off outdated entries */
data_01 = data_01.slice(data_01.length - data_wanted, data_01.length);
data_05 = data_05.slice(data_05.length - data_wanted, data_05.length);
data_15 = data_15.slice(data_15.length - data_wanted, data_15.length);
/* find peak */
for (var i = 0; i < data_01.length; i++)
{
data_max = Math.max(data_max, data_01[i]);
data_max = Math.max(data_max, data_05[i]);
data_max = Math.max(data_max, data_15[i]);
data_01_peak = Math.max(data_01_peak, data_01[i]);
data_05_peak = Math.max(data_05_peak, data_05[i]);
data_15_peak = Math.max(data_15_peak, data_15[i]);
if (i > 0)
{
data_01_avg = (data_01_avg + data_01[i]) / 2;
data_05_avg = (data_05_avg + data_05[i]) / 2;
data_15_avg = (data_15_avg + data_15[i]) / 2;
}
else
{
data_01_avg = data_01[i];
data_05_avg = data_05[i];
data_15_avg = data_15[i];
}
}
/* remember current timestamp, calculate horizontal scale */
data_stamp = data[data.length-1][TIME];
data_scale = height / (data_max * 1.1);
/* plot data */
var pt_01 = '0,' + height;
var pt_05 = '0,' + height;
var pt_15 = '0,' + height;
var y_01 = 0;
var y_05 = 0;
var y_15 = 0;
for (var i = 0; i < data_01.length; i++)
{
var x = i * step;
y_01 = height - Math.floor(data_01[i] * data_scale);
y_05 = height - Math.floor(data_05[i] * data_scale);
y_15 = height - Math.floor(data_15[i] * data_scale);
pt_01 += ' ' + x + ',' + y_01;
pt_05 += ' ' + x + ',' + y_05;
pt_15 += ' ' + x + ',' + y_15;
}
pt_01 += ' ' + width + ',' + y_01 + ' ' + width + ',' + height;
pt_05 += ' ' + width + ',' + y_05 + ' ' + width + ',' + height;
pt_15 += ' ' + width + ',' + y_15 + ' ' + width + ',' + height;
line_01.setAttribute('points', pt_01);
line_05.setAttribute('points', pt_05);
line_15.setAttribute('points', pt_15);
label_25.firstChild.data = (1.1 * 0.25 * data_max / 100).toFixed(2);
label_50.firstChild.data = (1.1 * 0.50 * data_max / 100).toFixed(2);
label_75.firstChild.data = (1.1 * 0.75 * data_max / 100).toFixed(2);
label_01_cur.innerHTML = (data_01[data_01.length-1] / 100).toFixed(2);
label_05_cur.innerHTML = (data_05[data_05.length-1] / 100).toFixed(2);
label_15_cur.innerHTML = (data_15[data_15.length-1] / 100).toFixed(2);
label_01_avg.innerHTML = (data_01_avg / 100).toFixed(2);
label_05_avg.innerHTML = (data_05_avg / 100).toFixed(2);
label_15_avg.innerHTML = (data_15_avg / 100).toFixed(2);
label_01_peak.innerHTML = (data_01_peak / 100).toFixed(2);
label_05_peak.innerHTML = (data_05_peak / 100).toFixed(2);
label_15_peak.innerHTML = (data_15_peak / 100).toFixed(2);
}
);
}
}, 1000
);
//]]></script>
<h2 name="content"><%:Realtime Load%></h2>
<embed id="bwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/load.svg" />
<div style="text-align:right"><small id="scale">-</small></div>
<br />
<table style="width:100%; table-layout:fixed" cellspacing="5">
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff0000; white-space:nowrap"><%:1 Minute Load:%></strong></td>
<td id="lb_load01_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_load01_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_load01_peak">0</td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ff6600; white-space:nowrap"><%:5 Minute Load:%></strong></td>
<td id="lb_load05_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_load05_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_load05_peak">0</td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid #ffaa00; white-space:nowrap"><%:15 Minute Load:%></strong></td>
<td id="lb_load15_cur">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="lb_load15_avg">0</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="lb_load15_peak">0</td>
</tr>
</table>
<%+footer%>

View file

@ -0,0 +1,162 @@
<%#
Copyright 2008-2009 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
require "luci.tools.webadmin"
require "nixio.fs"
local ip = require "luci.ip"
local style = true
local _, v
local rtn = {
[255] = "local",
[254] = "main",
[253] = "default",
[0] = "unspec"
}
if nixio.fs.access("/etc/iproute2/rt_tables") then
local ln
for ln in io.lines("/etc/iproute2/rt_tables") do
local i, n = ln:match("^(%d+)%s+(%S+)")
if i and n then
rtn[tonumber(i)] = n
end
end
end
-%>
<%+header%>
<div class="cbi-map" id="cbi-network">
<h2 name="content"><%:Routes%></h2>
<div class="cbi-map-descr"><%:The following rules are currently active on this system.%></div>
<fieldset class="cbi-section">
<legend>ARP</legend>
<div class="cbi-section-node">
<table class="cbi-section-table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Address%></th>
<th class="cbi-section-table-cell"><%_<abbr title="Media Access Control">MAC</abbr>-Address%></th>
<th class="cbi-section-table-cell"><%:Interface%></th>
</tr>
<%
for _, v in ipairs(ip.neighbors({ family = 4 })) do
if v.mac then
%>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=v.dest%></td>
<td class="cbi-value-field"><%=v.mac%></td>
<td class="cbi-value-field"><%=v.dev%></td>
</tr>
<%
style = not style
end
end
%>
</table>
</div>
</fieldset>
<br />
<fieldset class="cbi-section">
<legend><%_Active <abbr title="Internet Protocol Version 4">IPv4</abbr>-Routes%></legend>
<div class="cbi-section-node">
<table class="cbi-section-table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Network%></th>
<th class="cbi-section-table-cell"><%:Target%></th>
<th class="cbi-section-table-cell"><%_<abbr title="Internet Protocol Version 4">IPv4</abbr>-Gateway%></th>
<th class="cbi-section-table-cell"><%:Metric%></th>
<th class="cbi-section-table-cell"><%:Table%></th>
</tr>
<% for _, v in ipairs(ip.routes({ family = 4, type = 1 })) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or v.dev%></td>
<td class="cbi-value-field"><%=v.dest%></td>
<td class="cbi-value-field"><%=v.gw%></td>
<td class="cbi-value-field"><%=v.metric or 0%></td>
<td class="cbi-value-field"><%=rtn[v.table] or v.table%></td>
</tr>
<% style = not style end %>
</table>
</div>
</fieldset>
<br />
<%
if nixio.fs.access("/proc/net/ipv6_route") then
style = true
%>
<fieldset class="cbi-section">
<legend><%_Active <abbr title="Internet Protocol Version 6">IPv6</abbr>-Routes%></legend>
<div class="cbi-section-node">
<table class="cbi-section-table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Network%></th>
<th class="cbi-section-table-cell"><%:Target%></th>
<th class="cbi-section-table-cell"><%:Source%></th>
<th class="cbi-section-table-cell"><%:Metric%></th>
<th class="cbi-section-table-cell"><%:Table%></th>
</tr>
<%
for _, v in ipairs(ip.routes({ family = 6, type = 1 })) do
if v.dest and not v.dest:is6linklocal() then
%>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></td>
<td class="cbi-value-field"><%=v.dest%></td>
<td class="cbi-value-field"><%=v.from%></td>
<td class="cbi-value-field"><%=v.metric or 0%></td>
<td class="cbi-value-field"><%=rtn[v.table] or v.table%></td>
</tr>
<%
style = not style
end
end
%>
</table>
</div>
</fieldset>
<br />
<fieldset class="cbi-section">
<legend><%:IPv6 Neighbours%></legend>
<div class="cbi-section-node">
<table class="cbi-section-table">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:IPv6-Address%></th>
<th class="cbi-section-table-cell"><%:MAC-Address%></th>
<th class="cbi-section-table-cell"><%:Interface%></th>
</tr>
<%
for _, v in ipairs(ip.neighbors({ family = 6 })) do
if v.dest and not v.dest:is6linklocal() and v.mac then
%>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=v.dest%></td>
<td class="cbi-value-field"><%=v.mac%></td>
<td class="cbi-value-field"><%=luci.tools.webadmin.iface_get_network(v.dev) or '(' .. v.dev .. ')'%></td>
</tr>
<%
style = not style
end
end
%>
</table>
</div>
</fieldset>
<br />
<% end %>
</div>
<%+footer%>

View file

@ -0,0 +1,12 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:System Log%></h2>
<div id="content_syslog">
<textarea readonly="readonly" wrap="off" rows="<%=syslog:cmatch("\n")+2%>" id="syslog"><%=syslog:pcdata()%></textarea>
</div>
<%+footer%>

View file

@ -0,0 +1,370 @@
<%#
Copyright 2011 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local ntm = require "luci.model.network".init()
local dev
local devices = { }
for _, dev in luci.util.vspairs(luci.sys.net.devices()) do
if dev:match("^wlan%d") or dev:match("^ath%d") or dev:match("^wl%d") then
devices[#devices+1] = dev
end
end
local curdev = luci.http.formvalue("dev") or devices[1]
-%>
<%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[
var bwxhr = new XHR();
var G, G2;
var TIME = 0;
var RATE = 1;
var RSSI = 2;
var NOISE = 3;
var width = 760;
var height = 300;
var step = 5;
var data_wanted = Math.floor(width / step);
var data_fill = 0;
var data_stamp = 0;
var data_rssi = [ ];
var data_noise = [ ];
var data_rate = [ ];
var line_rssi;
var line_noise;
var line_rate;
var label_25, label_25_2;
var label_50, label_50_2;
var label_75, label_75_2;
var label_rssi_cur;
var label_rssi_avg;
var label_rssi_peak;
var label_noise_cur;
var label_noise_avg;
var label_noise_peak;
var label_rate_cur;
var label_rate_avg;
var label_rate_peak;
var label_scale;
/* wait for SVG */
window.setTimeout(
function() {
var svg = document.getElementById('iwsvg');
var svg2 = document.getElementById('iwsvg2');
try {
G = svg.getSVGDocument
? svg.getSVGDocument() : svg.contentDocument;
G2 = svg2.getSVGDocument
? svg2.getSVGDocument() : svg2.contentDocument;
}
catch(e) {
G = document.embeds['iwsvg'].getSVGDocument();
G2 = document.embeds['iwsvg2'].getSVGDocument();
}
if (!G || !G2)
{
window.setTimeout(arguments.callee, 1000);
}
else
{
/* find sizes */
width = svg.offsetWidth - 2;
height = svg.offsetHeight - 2;
data_wanted = Math.ceil(width / step);
/* prefill datasets */
for (var i = 0; i < data_wanted; i++)
{
data_rssi[i] = 0;
data_noise[i] = 0;
data_rate[i] = 0;
}
/* find svg elements */
line_rssi = G.getElementById('rssi');
line_noise = G.getElementById('noise');
line_rate = G2.getElementById('rate');
label_25 = G.getElementById('label_25');
label_50 = G.getElementById('label_50');
label_75 = G.getElementById('label_75');
label_25_2 = G2.getElementById('label_25');
label_50_2 = G2.getElementById('label_50');
label_75_2 = G2.getElementById('label_75');
label_rssi_cur = document.getElementById('rssi_bw_cur');
label_rssi_avg = document.getElementById('rssi_bw_avg');
label_rssi_peak = document.getElementById('rssi_bw_peak');
label_noise_cur = document.getElementById('noise_bw_cur');
label_noise_avg = document.getElementById('noise_bw_avg');
label_noise_peak = document.getElementById('noise_bw_peak');
label_rate_cur = document.getElementById('rate_bw_cur');
label_rate_avg = document.getElementById('rate_bw_avg');
label_rate_peak = document.getElementById('rate_bw_peak');
label_scale = document.getElementById('scale');
label_scale_2 = document.getElementById('scale2');
/* plot horizontal time interval lines */
for (var i = width % (step * 60); i < width; i += step * 60)
{
var line = G.createElementNS('http://www.w3.org/2000/svg', 'line');
line.setAttribute('x1', i);
line.setAttribute('y1', 0);
line.setAttribute('x2', i);
line.setAttribute('y2', '100%');
line.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text = G.createElementNS('http://www.w3.org/2000/svg', 'text');
text.setAttribute('x', i + 5);
text.setAttribute('y', 15);
text.setAttribute('style', 'fill:#999999; font-size:9pt');
text.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
label_25.parentNode.appendChild(line);
label_25.parentNode.appendChild(text);
var line2 = G2.createElementNS('http://www.w3.org/2000/svg', 'line');
line2.setAttribute('x1', i);
line2.setAttribute('y1', 0);
line2.setAttribute('x2', i);
line2.setAttribute('y2', '100%');
line2.setAttribute('style', 'stroke:black;stroke-width:0.1');
var text2 = G2.createElementNS('http://www.w3.org/2000/svg', 'text');
text2.setAttribute('x', i + 5);
text2.setAttribute('y', 15);
text2.setAttribute('style', 'fill:#999999; font-size:9pt');
text2.appendChild(G.createTextNode(Math.round((width - i) / step / 60) + 'm'));
label_25_2.parentNode.appendChild(line2);
label_25_2.parentNode.appendChild(text2);
}
label_scale.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
label_scale_2.innerHTML = String.format('<%:(%d minute window, %d second interval)%>', data_wanted / 60, 3);
/* render datasets, start update interval */
XHR.poll(3, '<%=build_url("admin/status/realtime/wireless_status", curdev)%>', null,
function(x, data)
{
var noise_floor = 255;
var rate_floor = 60000;
for (var i = 0; i < data.length; i++) {
noise_floor = Math.min(noise_floor, data[i][NOISE]);
rate_floor = Math.min(rate_floor, data[i][RATE]);
}
noise_floor -= 5;
var data_max = 0;
var data_scale = 0;
var data_max_2 = 0;
var data_scale_2 = 0;
var data_rssi_avg = 0;
var data_noise_avg = 0;
var data_rate_avg = 0;
var data_rssi_peak = 0;
var data_noise_peak = 0;
var data_rate_peak = 0;
for (var i = data_stamp ? 0 : 1; i < data.length; i++)
{
/* skip overlapping entries */
if (data[i][TIME] <= data_stamp)
continue;
data_rssi.push(data[i][RSSI] - noise_floor);
data_noise.push(data[i][NOISE] - noise_floor);
data_rate.push(Math.floor(data[i][RATE] / 1000));
}
/* cut off outdated entries */
data_rssi = data_rssi.slice(data_rssi.length - data_wanted, data_rssi.length);
data_noise = data_noise.slice(data_noise.length - data_wanted, data_noise.length);
data_rate = data_rate.slice(data_rate.length - data_wanted, data_rate.length);
/* find peak */
for (var i = 0; i < data_rssi.length; i++)
{
data_max = Math.max(data_max, data_rssi[i]);
data_max_2 = Math.max(data_max_2, data_rate[i]);
data_rssi_peak = Math.max(data_rssi_peak, data_rssi[i]);
data_noise_peak = Math.max(data_noise_peak, data_noise[i]);
data_rate_peak = Math.max(data_rate_peak, data_rate[i]);
if (i > 0)
{
data_rssi_avg = (data_rssi_avg + data_rssi[i]) / 2;
data_noise_avg = (data_noise_avg + data_noise[i]) / 2;
data_rate_avg = (data_rate_avg + data_rate[i]) / 2;
}
else
{
data_rssi_avg = data_rssi[i];
data_noise_avg = data_noise[i];
data_rate_avg = data_rate[i];
}
}
/* remember current timestamp, calculate horizontal scale */
data_stamp = data[data.length-1][TIME];
data_scale = (height / (data_max * 1.1)).toFixed(1);
data_scale_2 = (height / (data_max_2 * 1.1)).toFixed(1);
/* plot data */
var pt_rssi = '0,' + height;
var pt_noise = '0,' + height;
var pt_rate = '0,' + height;
var y_rssi = 0;
var y_noise = 0;
var y_rate = 0;
for (var i = 0; i < data_rssi.length; i++)
{
var x = i * step;
y_rssi = height - Math.floor(data_rssi[i] * data_scale);
y_noise = height - Math.floor(data_noise[i] * data_scale);
y_rate = height - Math.floor(data_rate[i] * data_scale_2);
y_rssi -= Math.floor(y_rssi % (1/data_scale));
y_noise -= Math.floor(y_noise % (1/data_scale));
pt_rssi += ' ' + x + ',' + y_rssi;
pt_noise += ' ' + x + ',' + y_noise;
pt_rate += ' ' + x + ',' + y_rate;
}
pt_rssi += ' ' + width + ',' + y_rssi + ' ' + width + ',' + height;
pt_noise += ' ' + width + ',' + y_noise + ' ' + width + ',' + height;
pt_rate += ' ' + width + ',' + y_rate + ' ' + width + ',' + height;
line_rssi.setAttribute('points', pt_rssi);
line_noise.setAttribute('points', pt_noise);
line_rate.setAttribute('points', pt_rate);
function wireless_label(dbm, noise)
{
if (noise)
return String.format("%d <%:dBm%> (SNR %d <%:dBm%>)", noise_floor + dbm - 255, dbm - noise);
else
return String.format("%d <%:dBm%>", noise_floor + dbm - 255);
}
function rate_label(mbit)
{
return String.format("%d <%:Mbit/s%>", mbit);
}
label_25.firstChild.data = wireless_label(1.1 * 0.25 * data_max);
label_50.firstChild.data = wireless_label(1.1 * 0.50 * data_max);
label_75.firstChild.data = wireless_label(1.1 * 0.75 * data_max);
label_25_2.firstChild.data = rate_label(1.1 * 0.25 * data_max_2);
label_50_2.firstChild.data = rate_label(1.1 * 0.50 * data_max_2);
label_75_2.firstChild.data = rate_label(1.1 * 0.75 * data_max_2);
label_rssi_cur.innerHTML = wireless_label(data_rssi[data_rssi.length-1], data_noise[data_noise.length-1]).nobr();
label_noise_cur.innerHTML = wireless_label(data_noise[data_noise.length-1]).nobr();
label_rssi_avg.innerHTML = wireless_label(data_rssi_avg, data_noise_avg).nobr();
label_noise_avg.innerHTML = wireless_label(data_noise_avg).nobr();
label_rssi_peak.innerHTML = wireless_label(data_rssi_peak, data_noise_peak).nobr();
label_noise_peak.innerHTML = wireless_label(data_noise_peak).nobr();
label_rate_cur.innerHTML = rate_label(data_rate[data_rate.length-1]);
label_rate_avg.innerHTML = rate_label(data_rate_avg);
label_rate_peak.innerHTML = rate_label(data_rate_peak);
}
);
}
}, 1000
);
//]]></script>
<h2 name="content"><%:Realtime Wireless%></h2>
<ul class="cbi-tabmenu">
<% for _, dev in ipairs(devices) do %>
<li class="cbi-tab<%= dev == curdev and "" or "-disabled" %>"><a href="?dev=<%=pcdata(dev)%>"><%=pcdata(dev)%></a></li>
<% end %>
</ul>
<embed id="iwsvg" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wireless.svg" />
<div style="text-align:right"><small id="scale">-</small></div>
<br />
<table style="width:100%; table-layout:fixed" cellspacing="5">
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid blue"><%:Signal:%></strong></td>
<td id="rssi_bw_cur">0 <%:dBm%></td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="rssi_bw_avg">0 <%:dBm%></td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="rssi_bw_peak">0 <%:dBm%></td>
</tr>
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid red"><%:Noise:%></strong></td>
<td id="noise_bw_cur">0 <%:dBm%></td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="noise_bw_avg">0 <%:dBm%></td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="noise_bw_peak">0 <%:dBm%></td>
</tr>
</table>
<br />
<embed id="iwsvg2" style="width:100%; height:300px; border:1px solid #000000; background-color:#FFFFFF" src="<%=resource%>/wifirate.svg" />
<div style="text-align:right"><small id="scale2">-</small></div>
<br />
<table style="width:100%; table-layout:fixed" cellspacing="5">
<tr>
<td style="text-align:right; vertical-align:top"><strong style="border-bottom:2px solid green"><%:Phy Rate:%></strong></td>
<td id="rate_bw_cur">0 MBit/s</td>
<td style="text-align:right; vertical-align:top"><strong><%:Average:%></strong></td>
<td id="rate_bw_avg">0 MBit/s</td>
<td style="text-align:right; vertical-align:top"><strong><%:Peak:%></strong></td>
<td id="rate_bw_peak">0 MBit/s</td>
</tr>
</table>
<%+footer%>

View file

@ -0,0 +1,41 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<html>
<head>
<title><%=luci.sys.hostname()%> - <% if title then %><%=title%><% else %><%:Rebooting...%><% end %></title>
<link rel="stylesheet" type="text/css" media="screen" href="<%=media%>/cascade.css" />
<script type="text/javascript" src="<%=resource%>/xhr.js"></script>
<script type="text/javascript">//<![CDATA[
var interval = window.setInterval(function() {
var img = new Image();
img.onload = function() {
window.clearInterval(interval);
location.href = ('https:' == document.location.protocol ? 'https://' : 'http://') + '<%=addr or luci.http.getenv("SERVER_NAME")%>/';
};
img.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + '<%=addr or luci.http.getenv("SERVER_NAME")%><%=resource%>/icons/loading.gif?' + Math.random();
}, 5000);
//]]></script>
</head>
<body>
<div id="maincontainer">
<div id="maincontent">
<h2 name="content"><%:System%> - <% if title then %><%=title%><% else %><%:Rebooting...%><% end %></h2>
<fieldset class="cbi-section">
<p>
<% if msg then %><%=msg%><% else %><%:Changes applied.%><% end %>
</p>
<p>
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
<%:Waiting for changes to be applied...%>
</p>
</fieldset>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<ul class="cbi-tabmenu">
<li class="cbi-tab-disabled"><a href="<%=url("admin/system/flashops")%>"><%:Actions%></a></li>
<li class="cbi-tab"><a href="#"><%:Configuration%></a></li>
</ul>

View file

@ -0,0 +1,36 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url('admin/system/clock_status')%>', null,
function(x, rv)
{
var s = document.getElementById('<%=self.option%>-clock-status');
if (s)
{
s.innerHTML = rv.timestring || '?';
}
}
);
function sync_clock(btn)
{
btn.disabled = true;
btn.value = '<%:Synchronizing...%>';
(new XHR()).post('<%=url('admin/system/clock_status')%>',
{ token: '<%=token%>', set: Math.floor((new Date()).getTime() / 1000) },
function()
{
btn.disabled = false;
btn.value = '<%:Sync with browser%>';
}
);
return false;
}
//]]></script>
<span id="<%=self.option%>-clock-status"><em><%:Collecting data...%></em></span>
<input type="button" class="cbi-button cbi-button-apply" value="<%:Sync with browser%>" onclick="return sync_clock(this)" />
<%+cbi/valuefooter%>

View file

@ -0,0 +1,93 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Flash operations%></h2>
<ul class="cbi-tabmenu">
<li class="cbi-tab"><a href="#"><%:Actions%></a></li>
<li class="cbi-tab-disabled"><a href="<%=REQUEST_URI%>/backupfiles"><%:Configuration%></a></li>
</ul>
<fieldset class="cbi-section">
<fieldset class="cbi-section">
<legend><%:Backup / Restore%></legend>
<div class="cbi-section-descr"><%:Click "Generate archive" to download a tar archive of the current configuration files. To reset the firmware to its initial state, click "Perform reset" (only possible with squashfs images).%></div>
<div class="cbi-section-node">
<form class="inline" method="post" action="<%=url('admin/system/flashops/backup')%>">
<input type="hidden" name="token" value="<%=token%>" />
<div class="cbi-value<% if not reset_avail then %> cbi-value-last<% end %>">
<label class="cbi-value-title" for="image"><%:Download backup%>:</label>
<div class="cbi-value-field">
<input class="cbi-button cbi-button-apply" type="submit" name="backup" value="<%:Generate archive%>" />
</div>
</div>
</form>
<% if reset_avail then %>
<form class="inline" method="post" action="<%=url('admin/system/flashops/reset')%>">
<input type="hidden" name="token" value="<%=token%>" />
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title"><%:Reset to defaults%>:</label>
<div class="cbi-value-field">
<input onclick="return confirm('<%:Really reset all changes?%>')" class="cbi-button cbi-button-reset" type="submit" name="reset" value="<%:Perform reset%>" />
</div>
</div>
</form>
<% end %>
</div>
<br />
<div class="cbi-section-descr"><%:To restore configuration files, you can upload a previously generated backup archive here.%></div>
<div class="cbi-section-node">
<form class="inline" method="post" action="<%=url('admin/system/flashops/restore')%>" enctype="multipart/form-data">
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title" for="archive"><%:Restore backup%>:</label>
<div class="cbi-value-field">
<input type="hidden" name="token" value="<%=token%>" />
<input type="file" name="archive" id="archive" />
<input type="submit" class="cbi-button cbi-input-apply" name="restore" value="<%:Upload archive...%>" />
</div>
</div>
</form>
</div>
</fieldset>
<br />
<fieldset class="cbi-section">
<legend><%:Flash new firmware image%></legend>
<% if upgrade_avail then %>
<form method="post" action="<%=url('admin/system/flashops/sysupgrade')%>" enctype="multipart/form-data">
<input type="hidden" name="token" value="<%=token%>" />
<div class="cbi-section-descr"><%:Upload a sysupgrade-compatible image here to replace the running firmware. Check "Keep settings" to retain the current configuration (requires a compatible firmware image).%></div>
<div class="cbi-section-node">
<div class="cbi-value">
<label class="cbi-value-title" for="keep"><%:Keep settings%>:</label>
<div class="cbi-value-field">
<input type="checkbox" name="keep" id="keep" checked="checked" />
</div>
</div>
<div class="cbi-value cbi-value-last<% if image_invalid then %> cbi-value-error<% end %>">
<label class="cbi-value-title" for="image"><%:Image%>:</label>
<div class="cbi-value-field">
<input type="file" name="image" id="image" />
<input type="submit" class="cbi-button cbi-input-apply" value="<%:Flash image...%>" />
</div>
</div>
</div>
<% if image_invalid then %>
<div class="cbi-section-error"><%:The uploaded image file does not contain a supported format. Make sure that you choose the generic image format for your platform. %></div>
<% end %>
</form>
<% else %>
<div class="cbi-section-descr"><%:Sorry, there is no sysupgrade support present; a new firmware image must be flashed manually. Please refer to the wiki for device specific install instructions.%></div>
<% end %>
</fieldset>
</fieldset>
<%+footer%>

View file

@ -0,0 +1,10 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<ul class="cbi-tabmenu">
<li class="cbi-tab-disabled"><a href="<%=url("admin/system/packages")%>"><%:Actions%></a></li>
<li class="cbi-tab"><a href="#"><%:Configuration%></a></li>
</ul>

View file

@ -0,0 +1,212 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%-
local opkg = require "luci.model.ipkg"
local fs = require "nixio.fs"
local wa = require "luci.tools.webadmin"
local rowcnt = 1
function rowstyle()
rowcnt = rowcnt + 1
return (rowcnt % 2) + 1
end
local fstat = fs.statvfs(opkg.overlay_root())
local space_total = fstat and fstat.blocks or 0
local space_free = fstat and fstat.bfree or 0
local space_used = space_total - space_free
local used_perc = math.floor(0.5 + ((space_total > 0) and ((100 / space_total) * space_used) or 100))
local free_byte = space_free * fstat.frsize
local filter = { }
local opkg_list = luci.model.ipkg.list_all
local querypat
if query and #query > 0 then
querypat = '*%s*' % query
opkg_list = luci.model.ipkg.find
end
local letterpat
if letter == 35 then
letterpat = "[^a-z]*"
else
letterpat = string.char(letter, 42) -- 'A' '*'
end
-%>
<%+header%>
<h2 name="content"><%:Software%></h2>
<div class="cbi-map">
<ul class="cbi-tabmenu">
<li class="cbi-tab"><a href="#"><%:Actions%></a></li>
<li class="cbi-tab-disabled"><a href="<%=REQUEST_URI%>/ipkg"><%:Configuration%></a></li>
</ul>
<form method="post" action="<%=REQUEST_URI%>">
<input type="hidden" name="exec" value="1" />
<input type="hidden" name="token" value="<%=token%>" />
<fieldset class="cbi-section">
<fieldset class="cbi-section-node">
<% if (install and next(install)) or (remove and next(remove)) or update or upgrade then %>
<div class="cbi-value">
<% if #stdout > 0 then %><pre><%=pcdata(stdout)%></pre><% end %>
<% if #stderr > 0 then %><pre class="error"><%=pcdata(stderr)%></pre><% end %>
</div>
<% end %>
<% if querypat then %>
<div class="cbi-value">
<%:Displaying only packages containing%> <strong>"<%=pcdata(query)%>"</strong>
<input type="button" onclick="location.href='?display=<%=pcdata(display)%>'" href="#" class="cbi-button cbi-button-reset" style="margin-left:1em" value="<%:Reset%>" />
<br style="clear:both" />
</div>
<% end %>
<% if no_lists or old_lists then %>
<div class="cbi-value">
<% if old_lists then %>
<%:Package lists are older than 24 hours%>
<% else %>
<%:No package lists available%>
<% end %>
<input type="submit" name="update" href="#" class="cbi-button cbi-button-apply" style="margin-left:3em" value="<%:Update lists%>" />
</div>
<% end %>
<div class="cbi-value cbi-value-last">
<%:Free space%>: <strong><%=(100-used_perc)%>%</strong> (<strong><%=wa.byte_format(free_byte)%></strong>)
<div style="margin:3px 0; width:300px; height:10px; border:1px solid #000000; background-color:#80C080">
<div style="background-color:#F08080; border-right:1px solid #000000; height:100%; width:<%=used_perc%>%">&#160;</div>
</div>
</div>
</fieldset>
<br />
<fieldset class="cbi-section-node">
<input type="hidden" name="display" value="<%=pcdata(display)%>" />
<div class="cbi-value">
<label class="cbi-value-title"><%:Download and install package%>:</label>
<div class="cbi-value-field">
<input type="text" name="url" size="30" value="" />
<input class="cbi-button cbi-input-save" type="submit" name="go" value="<%:OK%>" />
</div>
</div>
<div class="cbi-value cbi-value-last">
<label class="cbi-value-title"><%:Filter%>:</label>
<div class="cbi-value-field">
<input type="text" name="query" size="20" value="<%=pcdata(query)%>" />
<input type="submit" class="cbi-button cbi-input-find" name="search" value="<%:Find package%>" />
</div>
</div>
</fieldset>
</fieldset>
</form>
<h3><%:Status%></h3>
<ul class="cbi-tabmenu">
<li class="cbi-tab<% if display ~= "installed" then %>-disabled<% end %>"><a href="?display=installed&amp;query=<%=pcdata(query)%>"><%:Installed packages%><% if query then %> (<%=pcdata(query)%>)<% end %></a></li>
<li class="cbi-tab<% if display ~= "available" then %>-disabled<% end %>"><a href="?display=available&amp;query=<%=pcdata(query)%>"><%:Available packages%><% if query then %> (<%=pcdata(query)%>)<% end %></a></li>
</ul>
<% if display ~= "available" then %>
<fieldset class="cbi-section">
<table class="cbi-section-table" style="width:100%">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="text-align:left">&#160;</th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Package name%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Version%></th>
</tr>
<% local empty = true; luci.model.ipkg.list_installed(querypat, function(n, v, s, d) empty = false; filter[n] = true %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
<td style="text-align:left; width:10%">
<form method="post" class="inline" action="<%=REQUEST_URI%>">
<input type="hidden" name="exec" value="1" />
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="remove" value="<%=pcdata(n)%>" />
<a onclick="window.confirm('<%:Remove%> &quot;<%=luci.util.pcdata(n)%>&quot; ?') &#38;&#38; this.parentNode.submit(); return false" href="#"><%:Remove%></a>
</form>
</td>
<td style="text-align:left"><%=luci.util.pcdata(n)%></td>
<td style="text-align:left"><%=luci.util.pcdata(v)%></td>
</tr>
<% end) %>
<% if empty then %>
<tr class="cbi-section-table-row">
<td style="text-align:left">&#160;</td>
<td style="text-align:left"><em><%:none%></em></td>
<td style="text-align:left"><em><%:none%></em></td>
</tr>
<% end %>
</table>
</fieldset>
<% else %>
<fieldset class="cbi-section">
<% if not querypat then %>
<ul class="cbi-tabmenu">
<% local i; for i = 65, 90 do %>
<li class="cbi-tab<% if letter ~= i then %>-disabled<% end %>"><a href="?display=available&amp;letter=<%=string.char(i)%>"><%=string.char(i)%></a></li>
<% end %>
<li class="cbi-tab<% if letter ~= 35 then %>-disabled<% end %>"><a href="?display=available&amp;letter=%23">#</a></li>
</ul>
<div class="cbi-section-node">
<% end %>
<table class="cbi-section-table" style="width:100%">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" style="text-align:left">&#160;</th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Package name%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Version%></th>
<th class="cbi-section-table-cell" style="text-align:right"><%:Size (.ipk)%></th>
<th class="cbi-section-table-cell" style="text-align:left"><%:Description%></th>
</tr>
<% local empty = true; opkg_list(querypat or letterpat, function(n, v, s, d) if filter[n] then return end; empty = false %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=rowstyle()%>">
<td style="text-align:left; width:10%">
<form method="post" class="inline" action="<%=REQUEST_URI%>">
<input type="hidden" name="exec" value="1" />
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="install" value="<%=pcdata(n)%>" />
<a onclick="window.confirm('<%:Install%> &quot;<%=luci.util.pcdata(n)%>&quot; ?') &#38;&#38; this.parentNode.submit(); return false" href="#"><%:Install%></a>
</form>
</td>
<td style="text-align:left"><%=luci.util.pcdata(n)%></td>
<td style="text-align:left"><%=luci.util.pcdata(v)%></td>
<td style="text-align:right"><%=luci.util.pcdata(s)%></td>
<td style="text-align:left"><%=luci.util.pcdata(d)%></td>
</tr>
<% end) %>
<% if empty then %>
<tr class="cbi-section-table-row">
<td style="text-align:left">&#160;</td>
<td style="text-align:left"><em><%:none%></em></td>
<td style="text-align:left"><em><%:none%></em></td>
<td style="text-align:right"><em><%:none%></em></td>
<td style="text-align:left"><em><%:none%></em></td>
</tr>
<% end %>
</table>
<% if not querypat then %>
</div>
<% end %>
</fieldset>
<% end %>
</div>
<%+footer%>

View file

@ -0,0 +1,59 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Reboot%></h2>
<br />
<p><%:Reboots the operating system of your device%></p>
<%- local c = require("luci.model.uci").cursor():changes(); if c and next(c) then -%>
<p class="alert-message warning"><%:Warning: There are unsaved changes that will get lost on reboot!%></p>
<%- end -%>
<hr />
<script type="text/javascript">//<![CDATA[
var tries = 0;
function ok() {
window.location = '<%=controller%>/admin';
}
function check() {
if (tries++ < 12)
window.setTimeout(ping, 5000);
else
alert('<%:Device unreachable%>');
}
function ping() {
var img = document.createElement('img');
img.onload = ok;
img.onerror = check;
img.src = '<%=resource%>/icons/loading.gif?' + Math.random();
document.getElementById('reboot-message').innerHTML = '<%:Waiting for device...%>';
}
function reboot(button) {
button.style.display = 'none';
document.getElementById('reboot-message').parentNode.style.display = '';
(new XHR()).post('<%=controller%>/admin/system/reboot/call', { token: '<%=token%>' }, check);
}
//]]></script>
<input class="cbi-button cbi-button-apply" type="button" value="<%:Perform reboot%>" onclick="reboot(this)" />
<p class="alert-message" style="display:none">
<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" />
<span id="reboot-message"><%:Device is rebooting...%></span>
</p>
<%+footer%>

View file

@ -0,0 +1,59 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2009 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Flash Firmware%> - <%:Verify%></h2>
<p>
<%_ The flash image was uploaded.
Below is the checksum and file size listed,
compare them with the original file to ensure data integrity.<br />
Click "Proceed" below to start the flash procedure. %>
<% if storage > 0 and size > storage then %>
<br /><br />
<div class="error"><%:It appears that you are trying to
flash an image that does not fit into the flash memory, please verify
the image file! %></div>
<% end %>
</p>
<fieldset class="cbi-section">
<ul>
<li><%:Checksum%><br />
<%:MD5%>: <code><%=checksum%></code><br />
<%:SHA256%>: <code><%=sha256ch%></code></li>
<li><%:Size%>: <%
local w = require "luci.tools.webadmin"
write(w.byte_format(size))
if storage > 0 then
write(luci.i18n.translatef(
" (%s available)",
w.byte_format(storage)
))
end
%></li>
<li><% if keep then %>
<%:Configuration files will be kept.%>
<% else %>
<%:Note: Configuration files will be erased.%>
<% end %></li>
</ul>
</fieldset>
<div class="cbi-page-actions right">
<form class="inline" action="<%=REQUEST_URI%>" method="post">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="step" value="2" />
<input type="hidden" name="keep" value="<%=keep and "1" or ""%>" />
<input class="cbi-button cbi-button-reset" name="cancel" type="submit" value="<%:Cancel%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,23 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Configuration%> / <%:Apply%></h2>
<% if changes then %>
<%+cbi/apply_xhr%>
<%+admin_uci/changelog%>
<%- cbi_apply_xhr('uci-apply', configs) -%>
<p><strong><%:The following changes have been committed%>:</strong></p>
<%- uci_changelog(changes) -%>
<% else %>
<p><strong><%:There are no pending changes to apply!%></strong></p>
<% end %>
<%+footer%>

View file

@ -0,0 +1,79 @@
<%#
Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<% export("uci_changelog", function(changes) -%>
<fieldset class="cbi-section">
<strong><%:Legend:%></strong>
<div class="uci-change-legend">
<div class="uci-change-legend-label"><ins>&#160;</ins> <%:Section added%></div>
<div class="uci-change-legend-label"><del>&#160;</del> <%:Section removed%></div>
<div class="uci-change-legend-label"><var><ins>&#160;</ins></var> <%:Option changed%></div>
<div class="uci-change-legend-label"><var><del>&#160;</del></var> <%:Option removed%></div>
<br style="clear:both" />
</div>
<br />
<div class="uci-change-list"><%
local util = luci.util
local ret = { }
for r, tbl in pairs(changes) do
for s, os in pairs(tbl) do
-- section add
if os['.type'] and os['.type'] ~= "" then
ret[#ret+1] = "<ins>%s.%s=<strong>%s</strong>" %{ r, s, os['.type'] }
for o, v in util.kspairs(os) do
if o:sub(1,1) ~= "." then
if type(v) == "table" then
local i
for i = 1, #v do
ret[#ret+1] = "<br />%s.%s.%s+=<strong>%s</strong>"
%{ r, s, o, util.pcdata(v[i]) }
end
else
ret[#ret+1] = "<br />%s.%s.%s=<strong>%s</strong>"
%{ r, s, o, util.pcdata(v) }
end
end
end
ret[#ret+1] = "</ins><br />"
-- section delete
elseif os['.type'] and os['.type'] == "" then
ret[#ret+1] = "<del>%s.<strong>%s</strong></del><br />" %{ r, s }
-- modifications
else
ret[#ret+1] = "<var>%s.%s<br />" %{ r, s }
for o, v in util.kspairs(os) do
if o:sub(1,1) ~= "." then
if v and #v > 0 then
ret[#ret+1] = "<ins>"
if type(v) == "table" then
local i
for i = 1, #v do
ret[#ret+1] = "%s.%s.%s+=<strong>%s</strong><br />"
%{ r, s, o, util.pcdata(v[i]) }
end
else
ret[#ret+1] = "%s.%s.%s=<strong>%s</strong><br />"
%{ r, s, o, util.pcdata(v) }
end
ret[#ret+1] = "</ins>"
else
ret[#ret+1] = "<del>%s.%s.<strong>%s</strong><br /></del>" %{ r, s, o }
end
end
end
ret[#ret+1] = "</var><br />"
end
end
end
write(table.concat(ret))
%></div>
</fieldset>
<%- end) %>

View file

@ -0,0 +1,46 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2015 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Configuration%> / <%:Changes%></h2>
<% if changes then %>
<%+admin_uci/changelog%>
<%- uci_changelog(changes) -%>
<% else %>
<p><strong><%:There are no pending changes!%></strong></p>
<% end %>
<div class="cbi-page-actions">
<% local r = luci.http.formvalue("redir"); if r and #r > 0 then %>
<div style="float:left">
<form class="inline" method="get" action="<%=luci.util.pcdata(r)%>">
<input class="cbi-button cbi-button-link" style="float:left; margin:0" type="submit" value="<%:Back%>" />
</form>
</div>
<% end %>
<div style="text-align:right">
<form class="inline" method="post" action="<%=controller%>/admin/uci/apply">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Apply%>" />
</form>
<form class="inline" method="post" action="<%=controller%>/admin/uci/saveapply">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
<input class="cbi-button cbi-button-save" type="submit" value="<%:Save & Apply%>" />
</form>
<form class="inline" method="post" action="<%=controller%>/admin/uci/revert">
<input type="hidden" name="token" value="<%=token%>" />
<input type="hidden" name="redir" value="<%=pcdata(luci.http.formvalue("redir"))%>" />
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Revert%>" />
</form>
</div>
</div>
<%+footer%>

View file

@ -0,0 +1,27 @@
<%#
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
Licensed to the public under the Apache License 2.0.
-%>
<%+header%>
<h2 name="content"><%:Configuration%> / <%:Revert%></h2>
<% if changes then %>
<%+cbi/apply_xhr%>
<%+admin_uci/changelog%>
<p><strong><%:The following changes have been reverted%>:</strong></p>
<%- uci_changelog(changes) -%>
<% else %>
<p><strong><%:There are no pending changes to revert!%></strong></p>
<% end %>
<div class="cbi-page-actions">
<form class="inline" method="get" action="<%=luci.util.pcdata(luci.http.formvalue("redir"))%>">
<input class="cbi-button cbi-button-link" style="margin:0" type="submit" value="<%:Back%>" />
</form>
</div>
<%+footer%>

View file

@ -0,0 +1,168 @@
<%+cbi/valueheader%>
<script type="text/javascript">//<![CDATA[
var freqlist = <%= luci.http.write_json(self.freqlist) %>;
var hwmodes = <%= luci.http.write_json(self.hwmodes) %>;
var htmodes = <%= luci.http.write_json(self.htmodes) %>;
var channels = {
'11g': [
'auto', 'auto', true
],
'11a': [
'auto', 'auto', true
]
};
for (var i = 0; i < freqlist.length; i++)
channels[(freqlist[i].mhz > 2484) ? '11a' : '11g'].push(
freqlist[i].channel,
'%d (%d MHz)'.format(freqlist[i].channel, freqlist[i].mhz),
!freqlist[i].restricted
);
var modes = [
'', 'Legacy', true,
'n', 'N', hwmodes.n,
'ac', 'AC', hwmodes.ac
];
var htmodes = {
'': [
'', '-', true
],
'n': [
'HT20', '20 MHz', htmodes.HT20,
'HT40', '40 MHz', htmodes.HT40
],
'ac': [
'VHT20', '20 MHz', htmodes.VHT20,
'VHT40', '40 MHz', htmodes.VHT40,
'VHT80', '80 MHz', htmodes.VHT80,
'VHT160', '160 MHz', htmodes.VHT160
]
};
var bands = {
'': [
'11g', '2.4 GHz', (channels['11g'].length > 3),
'11a', '5 GHz', (channels['11a'].length > 3)
],
'n': [
'11g', '2.4 GHz', (channels['11g'].length > 3),
'11a', '5 GHz', (channels['11a'].length > 3)
],
'ac': [
'11a', '5 GHz', true
]
};
function cbi_set_values(sel, vals)
{
if (sel.vals)
sel.vals.selected = sel.selectedIndex;
while (sel.options[0])
sel.remove(0);
for (var i = 0; vals && i < vals.length; i += 3)
{
if (!vals[i+2])
continue;
var opt = document.createElement('option');
opt.value = vals[i+0];
opt.text = vals[i+1];
sel.add(opt);
}
if (!isNaN(vals.selected))
sel.selectedIndex = vals.selected;
sel.parentNode.style.display = (sel.options.length <= 1) ? 'none' : '';
sel.vals = vals;
}
function cbi_toggle_wifi_mode(id)
{
cbi_toggle_wifi_htmode(id);
cbi_toggle_wifi_band(id);
}
function cbi_toggle_wifi_htmode(id)
{
var mode = document.getElementById(id + '.mode');
var bwdt = document.getElementById(id + '.htmode');
cbi_set_values(bwdt, htmodes[mode.value]);
}
function cbi_toggle_wifi_band(id)
{
var mode = document.getElementById(id + '.mode');
var band = document.getElementById(id + '.band');
cbi_set_values(band, bands[mode.value]);
cbi_toggle_wifi_channel(id);
}
function cbi_toggle_wifi_channel(id)
{
var band = document.getElementById(id + '.band');
var chan = document.getElementById(id + '.channel');
cbi_set_values(chan, channels[band.value]);
}
function cbi_init_wifi(id)
{
var mode = document.getElementById(id + '.mode');
var band = document.getElementById(id + '.band');
var chan = document.getElementById(id + '.channel');
var bwdt = document.getElementById(id + '.htmode');
cbi_set_values(mode, modes);
if (/VHT20|VHT40|VHT80|VHT160/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
mode.value = 'ac';
else if (/HT20|HT40/.test(<%= luci.http.write_json(self.map:get(section, "htmode")) %>))
mode.value = 'n';
else
mode.value = '';
cbi_toggle_wifi_mode(id);
if (/a/.test(<%= luci.http.write_json(self.map:get(section, "hwmode")) %>))
band.value = '11a';
else
band.value = '11g';
cbi_toggle_wifi_band(id);
bwdt.value = <%= luci.http.write_json(self.map:get(section, "htmode")) %>;
chan.value = <%= luci.http.write_json(self.map:get(section, "channel")) %>;
}
//]]></script>
<label style="float:left; margin-right:3px">
<%:Mode%><br />
<select style="width:auto" id="<%= cbid %>.mode" name="<%= cbid %>.mode" onchange="cbi_toggle_wifi_mode('<%= cbid %>')"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Band%><br />
<select style="width:auto" id="<%= cbid %>.band" name="<%= cbid %>.band" onchange="cbi_toggle_wifi_band('<%= cbid %>')"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Channel%><br />
<select style="width:auto" id="<%= cbid %>.channel" name="<%= cbid %>.channel"></select>
</label>
<label style="float:left; margin-right:3px">
<%:Width%><br />
<select style="width:auto" id="<%= cbid %>.htmode" name="<%= cbid %>.htmode"></select>
</label>
<br style="clear:left" />
<script type="text/javascript">cbi_init_wifi('<%= cbid %>');</script>
<%+cbi/valuefooter%>