From 4d3ddb03a308629abc4f9c37686c5d2351ce5950 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Sat, 26 Sep 2009 11:10:01 +0000 Subject: [PATCH 1/1] modules/admin-full: initial work on site survey and network join --- .../admin-full/luasrc/controller/admin/network.lua | 92 +++++++- .../luasrc/view/admin_network/wifi_join.htm | 129 +++++++++++ .../view/admin_network/wifi_join_settings.htm | 112 +++++++++ .../luasrc/view/admin_network/wifi_overview.htm | 250 +++++++++++++++++++++ 4 files changed, 582 insertions(+), 1 deletion(-) create mode 100644 modules/admin-full/luasrc/view/admin_network/wifi_join.htm create mode 100644 modules/admin-full/luasrc/view/admin_network/wifi_join_settings.htm create mode 100644 modules/admin-full/luasrc/view/admin_network/wifi_overview.htm diff --git a/modules/admin-full/luasrc/controller/admin/network.lua b/modules/admin-full/luasrc/controller/admin/network.lua index 08a5dd0ef..12dd559bc 100644 --- a/modules/admin-full/luasrc/controller/admin/network.lua +++ b/modules/admin-full/luasrc/controller/admin/network.lua @@ -29,7 +29,7 @@ function index() page.title = i18n("a_n_switch") page.order = 20 - local page = entry({"admin", "network", "wireless"}, arcombine(cbi("admin_network/wireless"), cbi("admin_network/wifi")), i18n("wifi"), 15) + local page = entry({"admin", "network", "wireless"}, arcombine(template("admin_network/wifi_overview"), cbi("admin_network/wifi")), i18n("wifi"), 15) page.i18n = "wifi" page.leaf = true page.subindex = true @@ -43,6 +43,10 @@ function index() end ) + local page = entry({"admin", "network", "wireless_join"}, call("wifi_join"), nil, 16) + page.i18n = "wifi" + page.leaf = true + local page = entry({"admin", "network", "network"}, arcombine(cbi("admin_network/network"), cbi("admin_network/ifaces")), i18n("interfaces", "Schnittstellen"), 10) page.leaf = true page.subindex = true @@ -81,3 +85,89 @@ function index() page.order = 50 end + +function wifi_join() + local function param(x) + return luci.http.formvalue(x) + end + + local function ptable(x) + x = param(x) + return x and (type(x) ~= "table" and { x } or x) or {} + end + + local dev = param("device") + local ssid = param("join") + + if dev and ssid then + local wep = (tonumber(param("wep")) == 1) + local wpa = tonumber(param("wpa_version")) or 0 + local channel = tonumber(param("channel")) + local mode = param("mode") + local bssid = param("bssid") + + local confirm = (param("confirm") == "1") + local cancel = param("cancel") and true or false + + if confirm and not cancel then + local fixed_bssid = (param("fixed_bssid") == "1") + local replace_net = (param("replace_net") == "1") + local autoconnect = (param("autoconnect") == "1") + local attach_intf = param("attach_intf") + + local uci = require "luci.model.uci".cursor() + + if replace_net then + uci:delete_all("wireless", "wifi-iface") + end + + local wificonf = { + device = dev, + mode = (mode == "Ad-Hoc" and "adhoc" or "sta"), + ssid = ssid + } + + if attach_intf and uci:get("network", attach_intf, "ifname") then + -- target network already has a interface, make it a bridge + uci:set("network", attach_intf, "type", "bridge") + uci:save("network") + uci:commit("network") + + if autoconnect then + require "luci.sys".call("/sbin/ifup " .. attach_intf) + end + end + + if fixed_bssid then + wificonf.bssid = bssid + end + + if wep then + wificonf.encryption = "wep" + wificonf.key = param("key") + elseif wpa > 0 then + wificonf.encryption = param("wpa_suite") + wificonf.key = param("key") + end + + uci:section("wireless", "wifi-iface", nil, wificonf) + uci:delete("wireless", dev, "disabled") + uci:set("wireless", dev, "channel", channel) + + uci:save("wireless") + uci:commit("wireless") + + if autoconnect then + require "luci.sys".call("/sbin/wifi") + end + + luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", dev)) + elseif cancel then + luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless_join?device=" .. dev)) + else + luci.template.render("admin_network/wifi_join_settings") + end + else + luci.template.render("admin_network/wifi_join") + end +end diff --git a/modules/admin-full/luasrc/view/admin_network/wifi_join.htm b/modules/admin-full/luasrc/view/admin_network/wifi_join.htm new file mode 100644 index 000000000..3963a5ae2 --- /dev/null +++ b/modules/admin-full/luasrc/view/admin_network/wifi_join.htm @@ -0,0 +1,129 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%- + + 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 and not info.wpa_version then + return "WEP" + elseif info.wpa_version then + return "%s - %s" % { + table.concat(info.pair_ciphers, ", "), + table.concat(info.group_ciphers, ", "), + (info.wpa_version == 3) and "mixed WPA/WPA2" + or (info.wpa_version == 2 and "WPA2" or "WPA"), + table.concat(info.auth_suites, ", ") + } + else + return "None" + end + end + + local dev = luci.http.formvalue("device") + local iw = luci.sys.wifi.getiwinfo(dev) +-%> + +<%+header%> + +

<%:a_s_iw_scan Wireless Scan%>

+ +
+
+ + + <% for i, net in ipairs(iw.scanlist) do %> + + + + + + <% end %> + +
+ +
+ <%=percent_wifi_signal(net)%>% +
+
+ <%=net.ssid and utl.pcdata(net.ssid) or "hidden"%>
+ Channel: <%=net.channel%> | + Mode: <%=net.mode%> | + BSSID: <%=net.bssid%> | + Encryption: <%=format_wifi_encryption(net)%> +
+
+ + + + + + + <% if net.wpa_version then %> + + <% for _, v in ipairs(net.auth_suites) do %> + <% end; for _, v in ipairs(net.group_ciphers) do %> + <% end; for _, v in ipairs(net.pair_ciphers) do %> + <% end; end %> + + +
+
+
+
+
+
" method="get"> + +
+
+ + +
+
+ +<%+footer%> diff --git a/modules/admin-full/luasrc/view/admin_network/wifi_join_settings.htm b/modules/admin-full/luasrc/view/admin_network/wifi_join_settings.htm new file mode 100644 index 000000000..c914f3edd --- /dev/null +++ b/modules/admin-full/luasrc/view/admin_network/wifi_join_settings.htm @@ -0,0 +1,112 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%- + + local sys = require "luci.sys" + local utl = require "luci.util" + local uci = require "luci.model.uci".cursor_state() + + local ifaces = { } + uci:foreach("network", "interface", function(i) + if i.ifname ~= "lo" then + ifaces[#ifaces+1] = { i['.name'], i.ifname, i.ipaddr } + end + end) + + local dev = luci.http.formvalue("device") + local iw = luci.sys.wifi.getiwinfo(dev) + +-%> + +<%+header%> + +

<%:a_s_iw_join Join Network%>

+ +
+
+
+ <%=luci.i18n.translatef("a_s_iw_join_desc", "You are about to join the wireless network %s. " .. + "In order to complete the process, you need to provide some additional details.", + utl.pcdata(luci.http.formvalue("join") or "(hidden)") + )%> +
+ +
+ + " /> + " /> + " /> + " /> + " /> + " /> + " /> + + <% if luci.http.formvalue("wep") == "1" then %> +
+ +

+ <% elseif tonumber(luci.http.formvalue("wpa_version") or 0) > 0 and luci.http.formvalue("wpa_suites") == "PSK" then %> +
+ + + <% if tonumber(luci.http.formvalue("wpa_version") or 0) == 3 then %> + + <% else %> + " /> + <% end %> + +

+ <% end %> + +
+ + +

+

+ + <% if luci.http.formvalue("mode") == "Ad-Hoc" then %> + + +
+ <% end %> + + <% if iw.mbssid_support then %> + + +
+ <% else %> + + <% end %> + + + +
+
+
+ + +
+
+ +<%+footer%> diff --git a/modules/admin-full/luasrc/view/admin_network/wifi_overview.htm b/modules/admin-full/luasrc/view/admin_network/wifi_overview.htm new file mode 100644 index 000000000..251f767d2 --- /dev/null +++ b/modules/admin-full/luasrc/view/admin_network/wifi_overview.htm @@ -0,0 +1,250 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008-2009 Steven Barth +Copyright 2008-2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%- + + local sys = require "luci.sys" + local utl = require "luci.util" + local uci = require "luci.model.uci".cursor_state() + + function guess_wifi_hw(ifname) + local name, idx = ifname:match("^([a-z]+)(%d+)") + idx = tonumber(idx) + + -- wl.o + if name == "wl" then + local name = "Broadcom 802.11 Wireless Controller" + 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 = string.format( + "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 "Atheros 802.11 Wireless Controller" + + -- ralink + elseif name == "ra" then + return "RaLink 802.11 Wireless Controller" + + -- prism? + elseif name == "eth" then + return "Prism 802.11 Wireless Controller" + + -- dunno yet + else + return "Unkown 802.11 Wireless Controller" + end + end + + function guess_wifi_signal(info) + local snr = -1 * ((info.noise or 0) - (info.signal or 0)) + local scale = math.floor(snr / 5) + local icon + + if not info.bssid or info.bssid == "00:00:00:00:00:00" then + icon = resource .. "/icons/signal-none.png" + elseif scale < 1 then + icon = resource .. "/icons/signal-0.png" + elseif scale < 2 then + icon = resource .. "/icons/signal-0-25.png" + elseif scale < 3 then + icon = resource .. "/icons/signal-25-50.png" + elseif scale < 4 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 find_wifi_devices() + local devs = { } + uci:foreach("wireless", "wifi-device", + function(s) + local dev = s['.name'] + local act = 0 + devs[dev] = { active = 0, networks = { } } + + uci:foreach("wireless", "wifi-iface", + function(s) + if s.device == dev then + if s.up == "1" then act = act + 1 end + devs[dev].networks[#devs[dev].networks+1] = { + active = (s.up == "1"), + ifname = s.ifname, + info = sys.wifi.getiwinfo(s.ifname or s.device) + } + end + end) + + devs[dev].hwname = guess_wifi_hw(dev) + devs[dev].active = (act > 0) + end) + + return devs + end + + function find_wifi_frequency(state) + if state.active then + return string.format("%d (%.03f GHz)", + state.networks[1].info.channel, + state.networks[1].info.frequency / 1000); + else + return "n/a" + end + end + + + local devices = find_wifi_devices() + local arpcache = { } + sys.net.arptable(function(e) arpcache[e["HW address"]] = e["IP address"] end) +-%> + +<%+header%> + +

<%:a_s_iw_overview Wireless Overview%>

+ +
+ + <% for dev, state in utl.kspairs(devices) do %> + +
+ + + + + + + + + + + <% if #state.networks > 0 then %> + <% for i, net in ipairs(state.networks) do %> + + + + + + + <% end %> + <% else %> + + + + + <% end %> + +
.png" style="float:left; margin-right:10px" /> + <%=state.hwname%> (<%=dev%>)
+ Channel: <%=find_wifi_frequency(state)%> | + Bitrate: <%=state.active and (state.networks[1].info.bitrate / 1000) .. " Mb/s" or "n/a"%> +
+ Find and join network + Provide new network +
+
+ <%=percent_wifi_signal(net.info)%>% +
+ SSID: <%=utl.pcdata(net.info.ssid)%> | + Mode: <%=net.info.mode%>
+ BSSID: <%=net.info.bssid%> | + Encryption: <%=net.info.enctype%> +
+ Edit this network + Delete this network +
+ (No network configured on this device) +
+
+ + <% end %> + + + + +

<%:a_s_iw_overview2 Associated Stations%>

+ +
+ + + + + + + + + + + <% local count = -1 %> + <% for dev, state in utl.kspairs(devices) do %> + <% for _, net in ipairs(state.networks) do %> + <% for mac, info in utl.kspairs(net.info.assoclist) do info.bssid = mac; count = count + 1 %> + + + + + + + + + <% end %> + <% end %> + <% end %> + <% if count <= 0 then %> + + + + <% end %> +
SSIDMACAddressSignalNoise
<%=net.info.ssid%><%=mac%><%=arpcache[mac] or "n/a"%><%=info.signal%> dBm<%=info.noise%> dBm
+ No information available +
+
+
+ +<%+footer%> -- 2.11.0