local wa = require "luci.tools.webadmin"
local nw = require "luci.model.network"
+local ut = require "luci.util"
+local nt = require "luci.sys".net
local fs = require "nixio.fs"
arg[1] = arg[1] or ""
m = Map("wireless", "",
translate("The <em>Device Configuration</em> section covers physical settings of the radio " ..
- "hardware such as channel, transmit power or antenna selection which is shared among all " ..
+ "hardware such as channel, transmit power or antenna selection which are shared among all " ..
"defined wireless networks (if the radio hardware is multi-SSID capable). Per network settings " ..
"like encryption or operation mode are grouped in the <em>Interface Configuration</em>."))
wdev:set("disabled", nil)
nw:commit("wireless")
- luci.sys.call("(env -i /sbin/wifi down; env -i /sbin/wifi up) >/dev/null 2>/dev/null")
+ luci.sys.call("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null")
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1]))
return
return (list[#list] and list[#list].driver_dbm) or pwr or 0
end
-local function arplist(opt)
- local _, e, mac, ip, name
- local arp = { }
-
- for _, e in ipairs(luci.sys.net.arptable()) do
- arp[e["HW address"]:upper()] = { e["IP address"] }
- end
-
- if fs.access("/etc/ethers") then
- for e in io.lines("/etc/ethers") do
- mac, ip = e:match("^([a-f0-9]%S+) (%S+)")
- if mac and ip then arp[mac:upper()] = { ip } end
- end
- end
-
- if fs.access("/var/dhcp.leases") then
- for e in io.lines("/var/dhcp.leases") do
- mac, ip, name = e:match("^%d+ (%S+) (%S+) (%S+)")
- if mac and ip then arp[mac:upper()] = { ip, name ~= "*" and name } end
- end
- end
-
- for mac, e in luci.util.kspairs(arp) do
- opt:value(mac, "%s (%s)" %{ mac, e[2] or e[1] })
- end
-end
-
local iw = luci.sys.wifi.getiwinfo(arg[1])
local hw_modes = iw.hwmodelist or { }
local tx_power_list = txpower_list(iw)
local hwtype = wdev:get("type")
-local htcaps = wdev:get("ht_capab") and true or false
-- NanoFoo
local nsantenna = wdev:get("antenna")
--- Check whether there is a client interface on the same radio,
--- if yes, lock the channel choice as the station will dicatate the freq
-local has_sta = nil
+-- Check whether there are client interfaces on the same radio,
+-- if yes, lock the channel choice as these stations will dicatate the freq
+local found_sta = nil
local _, net
-for _, net in ipairs(wdev:get_wifinets()) do
- if net:mode() == "sta" and net:id() ~= wnet:id() then
- has_sta = net
- break
+if wnet:mode() ~= "sta" then
+ for _, net in ipairs(wdev:get_wifinets()) do
+ if net:mode() == "sta" then
+ if not found_sta then
+ found_sta = {}
+ found_sta.channel = net:channel()
+ found_sta.names = {}
+ end
+ found_sta.names[#found_sta.names+1] = net:shortname()
+ end
end
end
-if has_sta then
+if found_sta then
ch = s:taboption("general", DummyValue, "choice", translate("Channel"))
- ch.value = translatef("Locked to channel %d used by %s",
- has_sta:channel(), has_sta:shortname())
+ ch.value = translatef("Locked to channel %d used by: %s",
+ found_sta.channel, table.concat(found_sta.names, ", "))
else
- ch = s:taboption("general", Value, "channel", translate("Channel"))
- ch:value("auto", translate("auto"))
- for _, f in ipairs(iw and iw.freqlist or luci.sys.wifi.channels()) do
- if not f.restricted then
- ch:value(f.channel, "%i (%.3f GHz)" %{ f.channel, f.mhz / 1000 })
- end
+ ch = s:taboption("general", Value, "_mode_freq", '<br />'..translate("Operating frequency"))
+ ch.hwmodes = iw.hwmodelist
+ ch.freqlist = iw.freqlist
+ ch.template = "cbi/wireless_modefreq"
+
+ function ch.cfgvalue(self, section)
+ return {
+ m:get(section, "hwmode") or "",
+ m:get(section, "channel") or "auto",
+ m:get(section, "htmode") or ""
+ }
+ end
+
+ function ch.formvalue(self, section)
+ return {
+ m:formvalue(self:cbid(section) .. ".band") or (iw.hwmodelist.g and "11g" or "11a"),
+ m:formvalue(self:cbid(section) .. ".channel") or "auto",
+ m:formvalue(self:cbid(section) .. ".htmode") or ""
+ }
+ end
+
+ function ch.write(self, section, value)
+ m:set(section, "hwmode", value[1])
+ m:set(section, "channel", value[2])
+ m:set(section, "htmode", value[3])
end
end
------------------- MAC80211 Device ------------------
if hwtype == "mac80211" then
- tp = s:taboption("general",
- (#tx_power_list > 0) and ListValue or Value,
- "txpower", translate("Transmit Power"), "dBm")
-
- tp.rmempty = true
- tp.default = tx_power_cur
-
- function tp.cfgvalue(...)
- return txpower_current(Value.cfgvalue(...), tx_power_list)
- end
-
- for _, p in ipairs(tx_power_list) do
- tp:value(p.driver_dbm, "%i dBm (%i mW)"
- %{ p.display_dbm, p.display_mw })
- end
+ if #tx_power_list > 1 then
+ tp = s:taboption("general", ListValue,
+ "txpower", translate("Transmit Power"), "dBm")
+ tp.rmempty = true
+ tp.default = tx_power_cur
+ function tp.cfgvalue(...)
+ return txpower_current(Value.cfgvalue(...), tx_power_list)
+ end
- mode = s:taboption("advanced", ListValue, "hwmode", translate("Mode"))
- mode:value("", translate("auto"))
- if hw_modes.b then mode:value("11b", "802.11b") end
- if hw_modes.g then mode:value("11g", "802.11g") end
- if hw_modes.a then mode:value("11a", "802.11a") end
-
- if htcaps then
- if hw_modes.g and hw_modes.n then mode:value("11ng", "802.11g+n") end
- if hw_modes.a and hw_modes.n then mode:value("11na", "802.11a+n") end
-
- htmode = s:taboption("advanced", ListValue, "htmode", translate("HT mode"))
- htmode:depends("hwmode", "11na")
- htmode:depends("hwmode", "11ng")
- htmode:value("HT20", "20MHz")
- htmode:value("HT40-", translate("40MHz 2nd channel below"))
- htmode:value("HT40+", translate("40MHz 2nd channel above"))
-
- --htcapab = s:taboption("advanced", DynamicList, "ht_capab", translate("HT capabilities"))
- --htcapab:depends("hwmode", "11na")
- --htcapab:depends("hwmode", "11ng")
+ for _, p in ipairs(tx_power_list) do
+ tp:value(p.driver_dbm, "%i dBm (%i mW)"
+ %{ p.display_dbm, p.display_mw })
+ end
end
local cl = iw and iw.countrylist
s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
translate("Distance to farthest network member in meters."))
+ -- external antenna profiles
+ local eal = iw and iw.extant
+ if eal and #eal > 0 then
+ ea = s:taboption("advanced", ListValue, "extant", translate("Antenna Configuration"))
+ for _, eap in ipairs(eal) do
+ ea:value(eap.id, "%s (%s)" %{ eap.name, eap.description })
+ if eap.selected then
+ ea.default = eap.id
+ end
+ end
+ end
+
s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
end
%{ p.display_dbm, p.display_mw })
end
- mode = s:taboption("advanced", ListValue, "hwmode", translate("Mode"))
- mode:value("", translate("auto"))
- if hw_modes.b then mode:value("11b", "802.11b") end
- if hw_modes.g then mode:value("11g", "802.11g") end
- if hw_modes.a then mode:value("11a", "802.11a") end
- if hw_modes.g then mode:value("11bg", "802.11b+g") end
- if hw_modes.g then mode:value("11gst", "802.11g + Turbo") end
- if hw_modes.a then mode:value("11ast", "802.11a + Turbo") end
- mode:value("fh", translate("Frequency Hopping"))
-
s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
if not nsantenna then
%{ p.display_dbm, p.display_mw })
end
- mode = s:taboption("advanced", ListValue, "hwmode", translate("Mode"))
- mode:value("11bg", "802.11b+g")
- mode:value("11b", "802.11b")
- mode:value("11g", "802.11g")
- mode:value("11gst", "802.11g + Turbo")
-
ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
ant1.widget = "radio"
ant1:depends("diversity", "")
bssid = s:taboption("general", Value, "bssid", translate("<abbr title=\"Basic Service Set Identifier\">BSSID</abbr>"))
network = s:taboption("general", Value, "network", translate("Network"),
- translate("Choose the network you want to attach to this wireless interface. " ..
- "Select <em>unspecified</em> to not attach any network or fill out the " ..
- "<em>create</em> field to define a new network."))
+ translate("Choose the network(s) you want to attach to this wireless interface or " ..
+ "fill out the <em>create</em> field to define a new network."))
network.rmempty = true
network.template = "cbi/network_netlist"
-network.widget = "radio"
+network.widget = "checkbox"
+network.novirtual = true
function network.write(self, section, value)
local i = nw:get_interface(section)
if n then n:del_interface(i) end
end
else
- local n = nw:get_network(value)
- if n then
- n:set("type", "bridge")
- n:add_interface(i)
+ local v
+ for _, v in ipairs(i:get_networks()) do
+ v:del_interface(i)
+ end
+ for v in ut.imatch(value) do
+ local n = nw:get_network(v)
+ if n then
+ if not n:is_empty() then
+ n:set("type", "bridge")
+ end
+ n:add_interface(i)
+ end
end
end
end
ml.datatype = "macaddr"
ml:depends({macfilter="allow"})
ml:depends({macfilter="deny"})
- arplist(ml)
+ nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
hidden:depends({mode="ap"})
hidden:depends({mode="ap-wds"})
+
+ wmm = s:taboption("general", Flag, "wmm", translate("WMM Mode"))
+ wmm:depends({mode="ap"})
+ wmm:depends({mode="ap-wds"})
+ wmm.default = wmm.enabled
end
ml.datatype = "macaddr"
ml:depends({macpolicy="allow"})
ml:depends({macpolicy="deny"})
- arplist(ml)
+ nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
s:taboption("advanced", Value, "mcast_rate", translate("Multicast Rate"))
ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
ml:depends({macpolicy="allow"})
ml:depends({macpolicy="deny"})
- arplist(ml)
+ nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
local supplicant = fs.access("/usr/sbin/wpa_supplicant")
local hostapd = fs.access("/usr/sbin/hostapd")
- -- Probe EAP support
- local has_ap_eap = (os.execute("hostapd -veap >/dev/null 2>/dev/null") == 0)
+ -- Probe EAP support
+ local has_ap_eap = (os.execute("hostapd -veap >/dev/null 2>/dev/null") == 0)
local has_sta_eap = (os.execute("wpa_supplicant -veap >/dev/null 2>/dev/null") == 0)
if hostapd and supplicant then
password:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
end
+if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
+ local wpasupplicant = fs.access("/usr/sbin/wpa_supplicant")
+ local hostcli = fs.access("/usr/sbin/hostapd_cli")
+ if hostcli and wpasupplicant then
+ wps = s:taboption("encryption", Flag, "wps_pushbutton", translate("Enable WPS pushbutton, requires WPA(2)-PSK"))
+ wps.enabled = "1"
+ wps.disabled = "0"
+ wps.rmempty = false
+ wps:depends("encryption", "psk")
+ wps:depends("encryption", "psk2")
+ wps:depends("encryption", "psk-mixed")
+ end
+end
+
return m