Some applications only support ipv4 so add ipv4only option to host and hostport datatypes so that for thos applications that when an IP address is specified only and ipv4 ip address gets accepted.
947 lines
33 KiB
Lua
947 lines
33 KiB
Lua
-- Copyright 2008 Steven Barth <steven@midlink.org>
|
|
-- Licensed to the public under the Apache License 2.0.
|
|
|
|
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 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>."))
|
|
|
|
m:chain("network")
|
|
m:chain("firewall")
|
|
m.redirect = luci.dispatcher.build_url("admin/network/wireless")
|
|
|
|
local ifsection
|
|
|
|
function m.on_commit(map)
|
|
local wnet = nw:get_wifinet(arg[1])
|
|
if ifsection and wnet then
|
|
ifsection.section = wnet.sid
|
|
m.title = luci.util.pcdata(wnet:get_i18n())
|
|
end
|
|
end
|
|
|
|
nw.init(m.uci)
|
|
|
|
local wnet = nw:get_wifinet(arg[1])
|
|
local wdev = wnet and wnet:get_device()
|
|
|
|
-- redirect to overview page if network does not exist anymore (e.g. after a revert)
|
|
if not wnet or not wdev then
|
|
luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
|
|
return
|
|
end
|
|
|
|
-- wireless toggle was requested, commit and reload page
|
|
function m.parse(map)
|
|
if m:formvalue("cbid.wireless.%s.__toggle" % wdev:name()) then
|
|
if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then
|
|
wnet:set("disabled", nil)
|
|
else
|
|
wnet:set("disabled", "1")
|
|
end
|
|
wdev:set("disabled", nil)
|
|
|
|
nw:commit("wireless")
|
|
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
|
|
end
|
|
Map.parse(map)
|
|
end
|
|
|
|
m.title = luci.util.pcdata(wnet:get_i18n())
|
|
|
|
|
|
local function txpower_list(iw)
|
|
local list = iw.txpwrlist or { }
|
|
local off = tonumber(iw.txpower_offset) or 0
|
|
local new = { }
|
|
local prev = -1
|
|
local _, val
|
|
for _, val in ipairs(list) do
|
|
local dbm = val.dbm + off
|
|
local mw = math.floor(10 ^ (dbm / 10))
|
|
if mw ~= prev then
|
|
prev = mw
|
|
new[#new+1] = {
|
|
display_dbm = dbm,
|
|
display_mw = mw,
|
|
driver_dbm = val.dbm,
|
|
driver_mw = val.mw
|
|
}
|
|
end
|
|
end
|
|
return new
|
|
end
|
|
|
|
local function txpower_current(pwr, list)
|
|
pwr = tonumber(pwr)
|
|
if pwr ~= nil then
|
|
local _, item
|
|
for _, item in ipairs(list) do
|
|
if item.driver_dbm >= pwr then
|
|
return item.driver_dbm
|
|
end
|
|
end
|
|
end
|
|
return (list[#list] and list[#list].driver_dbm) or pwr or 0
|
|
end
|
|
|
|
local iw = luci.sys.wifi.getiwinfo(arg[1])
|
|
local hw_modes = iw.hwmodelist or { }
|
|
local tx_power_list = txpower_list(iw)
|
|
local tx_power_cur = txpower_current(wdev:get("txpower"), tx_power_list)
|
|
|
|
s = m:section(NamedSection, wdev:name(), "wifi-device", translate("Device Configuration"))
|
|
s.addremove = false
|
|
|
|
s:tab("general", translate("General Setup"))
|
|
s:tab("macfilter", translate("MAC-Filter"))
|
|
s:tab("advanced", translate("Advanced Settings"))
|
|
|
|
--[[
|
|
back = s:option(DummyValue, "_overview", translate("Overview"))
|
|
back.value = ""
|
|
back.titleref = luci.dispatcher.build_url("admin", "network", "wireless")
|
|
]]
|
|
|
|
st = s:taboption("general", DummyValue, "__status", translate("Status"))
|
|
st.template = "admin_network/wifi_status"
|
|
st.ifname = arg[1]
|
|
|
|
en = s:taboption("general", Button, "__toggle")
|
|
|
|
if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then
|
|
en.title = translate("Wireless network is disabled")
|
|
en.inputtitle = translate("Enable")
|
|
en.inputstyle = "apply"
|
|
else
|
|
en.title = translate("Wireless network is enabled")
|
|
en.inputtitle = translate("Disable")
|
|
en.inputstyle = "reset"
|
|
end
|
|
|
|
|
|
local hwtype = wdev:get("type")
|
|
|
|
-- NanoFoo
|
|
local nsantenna = wdev:get("antenna")
|
|
|
|
-- 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
|
|
if wnet:mode() ~= "sta" then
|
|
for _, net in ipairs(wdev:get_wifinets()) do
|
|
if net:mode() == "sta" and net:get("disabled") ~= "1" 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 found_sta then
|
|
ch = s:taboption("general", DummyValue, "choice", translate("Channel"))
|
|
ch.value = translatef("Locked to channel %d used by: %s",
|
|
found_sta.channel, table.concat(found_sta.names, ", "))
|
|
else
|
|
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
|
|
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
|
|
|
|
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
|
|
if cl and #cl > 0 then
|
|
cc = s:taboption("advanced", ListValue, "country", translate("Country Code"), translate("Use ISO/IEC 3166 alpha2 country codes."))
|
|
cc.default = tostring(iw and iw.country or "00")
|
|
for _, c in ipairs(cl) do
|
|
cc:value(c.alpha2, "%s - %s" %{ c.alpha2, c.name })
|
|
end
|
|
else
|
|
s:taboption("advanced", Value, "country", translate("Country Code"), translate("Use ISO/IEC 3166 alpha2 country codes."))
|
|
end
|
|
|
|
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
|
|
|
|
|
|
------------------- Madwifi Device ------------------
|
|
|
|
if hwtype == "atheros" 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
|
|
|
|
s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
|
|
|
|
if not nsantenna then
|
|
ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
|
|
ant1.widget = "radio"
|
|
ant1.orientation = "horizontal"
|
|
ant1:depends("diversity", "")
|
|
ant1:value("0", translate("auto"))
|
|
ant1:value("1", translate("Antenna 1"))
|
|
ant1:value("2", translate("Antenna 2"))
|
|
|
|
ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
|
|
ant2.widget = "radio"
|
|
ant2.orientation = "horizontal"
|
|
ant2:depends("diversity", "")
|
|
ant2:value("0", translate("auto"))
|
|
ant2:value("1", translate("Antenna 1"))
|
|
ant2:value("2", translate("Antenna 2"))
|
|
|
|
else -- NanoFoo
|
|
local ant = s:taboption("advanced", ListValue, "antenna", translate("Transmitter Antenna"))
|
|
ant:value("auto")
|
|
ant:value("vertical")
|
|
ant:value("horizontal")
|
|
ant:value("external")
|
|
end
|
|
|
|
s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
|
|
translate("Distance to farthest network member in meters."))
|
|
s:taboption("advanced", Value, "regdomain", translate("Regulatory Domain"))
|
|
s:taboption("advanced", Value, "country", translate("Country Code"))
|
|
s:taboption("advanced", Flag, "outdoor", translate("Outdoor Channels"))
|
|
|
|
--s:option(Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
|
|
end
|
|
|
|
|
|
|
|
------------------- Broadcom Device ------------------
|
|
|
|
if hwtype == "broadcom" 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
|
|
|
|
ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
|
|
ant1.widget = "radio"
|
|
ant1:depends("diversity", "")
|
|
ant1:value("3", translate("auto"))
|
|
ant1:value("0", translate("Antenna 1"))
|
|
ant1:value("1", translate("Antenna 2"))
|
|
|
|
ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
|
|
ant2.widget = "radio"
|
|
ant2:depends("diversity", "")
|
|
ant2:value("3", translate("auto"))
|
|
ant2:value("0", translate("Antenna 1"))
|
|
ant2:value("1", translate("Antenna 2"))
|
|
|
|
s:taboption("advanced", Flag, "frameburst", translate("Frame Bursting"))
|
|
|
|
s:taboption("advanced", Value, "distance", translate("Distance Optimization"))
|
|
--s:option(Value, "slottime", translate("Slot time"))
|
|
|
|
s:taboption("advanced", Value, "country", translate("Country Code"))
|
|
s:taboption("advanced", Value, "maxassoc", translate("Connection Limit"))
|
|
end
|
|
|
|
|
|
--------------------- HostAP Device ---------------------
|
|
|
|
if hwtype == "prism2" then
|
|
s:taboption("advanced", Value, "txpower", translate("Transmit Power"), "att units").rmempty = true
|
|
|
|
s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
|
|
|
|
s:taboption("advanced", Value, "txantenna", translate("Transmitter Antenna"))
|
|
s:taboption("advanced", Value, "rxantenna", translate("Receiver Antenna"))
|
|
end
|
|
|
|
|
|
----------------------- Interface -----------------------
|
|
|
|
s = m:section(NamedSection, wnet.sid, "wifi-iface", translate("Interface Configuration"))
|
|
ifsection = s
|
|
s.addremove = false
|
|
s.anonymous = true
|
|
s.defaults.device = wdev:name()
|
|
|
|
s:tab("general", translate("General Setup"))
|
|
s:tab("encryption", translate("Wireless Security"))
|
|
s:tab("macfilter", translate("MAC-Filter"))
|
|
s:tab("advanced", translate("Advanced Settings"))
|
|
|
|
ssid = s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
|
|
ssid.datatype = "maxlength(32)"
|
|
|
|
mode = s:taboption("general", ListValue, "mode", translate("Mode"))
|
|
mode.override_values = true
|
|
mode:value("ap", translate("Access Point"))
|
|
mode:value("sta", translate("Client"))
|
|
mode:value("adhoc", translate("Ad-Hoc"))
|
|
|
|
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(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 = "checkbox"
|
|
network.novirtual = true
|
|
|
|
function network.write(self, section, value)
|
|
local i = nw:get_interface(section)
|
|
if i then
|
|
if value == '-' then
|
|
value = m:formvalue(self:cbid(section) .. ".newnet")
|
|
if value and #value > 0 then
|
|
local n = nw:add_network(value, {proto="none"})
|
|
if n then n:add_interface(i) end
|
|
else
|
|
local n = i:get_network()
|
|
if n then n:del_interface(i) end
|
|
end
|
|
else
|
|
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
|
|
end
|
|
|
|
-------------------- MAC80211 Interface ----------------------
|
|
|
|
if hwtype == "mac80211" then
|
|
if fs.access("/usr/sbin/iw") then
|
|
mode:value("mesh", "802.11s")
|
|
end
|
|
|
|
mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
|
|
mode:value("monitor", translate("Monitor"))
|
|
bssid:depends({mode="adhoc"})
|
|
bssid:depends({mode="sta"})
|
|
bssid:depends({mode="sta-wds"})
|
|
|
|
mp = s:taboption("macfilter", ListValue, "macfilter", translate("MAC-Address Filter"))
|
|
mp:depends({mode="ap"})
|
|
mp:depends({mode="ap-wds"})
|
|
mp:value("", translate("disable"))
|
|
mp:value("allow", translate("Allow listed only"))
|
|
mp:value("deny", translate("Allow all except listed"))
|
|
|
|
ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
|
|
ml.datatype = "macaddr"
|
|
ml:depends({macfilter="allow"})
|
|
ml:depends({macfilter="deny"})
|
|
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")})
|
|
|
|
function mode.write(self, section, value)
|
|
if value == "ap-wds" then
|
|
ListValue.write(self, section, "ap")
|
|
m.uci:set("wireless", section, "wds", 1)
|
|
elseif value == "sta-wds" then
|
|
ListValue.write(self, section, "sta")
|
|
m.uci:set("wireless", section, "wds", 1)
|
|
else
|
|
ListValue.write(self, section, value)
|
|
m.uci:delete("wireless", section, "wds")
|
|
end
|
|
end
|
|
|
|
function mode.cfgvalue(self, section)
|
|
local mode = ListValue.cfgvalue(self, section)
|
|
local wds = m.uci:get("wireless", section, "wds") == "1"
|
|
|
|
if mode == "ap" and wds then
|
|
return "ap-wds"
|
|
elseif mode == "sta" and wds then
|
|
return "sta-wds"
|
|
else
|
|
return mode
|
|
end
|
|
end
|
|
|
|
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
|
|
|
|
|
|
|
|
-------------------- Madwifi Interface ----------------------
|
|
|
|
if hwtype == "atheros" then
|
|
mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
|
|
mode:value("monitor", translate("Monitor"))
|
|
mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
|
|
mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
|
|
mode:value("wds", translate("Static WDS"))
|
|
|
|
function mode.write(self, section, value)
|
|
if value == "ap-wds" then
|
|
ListValue.write(self, section, "ap")
|
|
m.uci:set("wireless", section, "wds", 1)
|
|
elseif value == "sta-wds" then
|
|
ListValue.write(self, section, "sta")
|
|
m.uci:set("wireless", section, "wds", 1)
|
|
else
|
|
ListValue.write(self, section, value)
|
|
m.uci:delete("wireless", section, "wds")
|
|
end
|
|
end
|
|
|
|
function mode.cfgvalue(self, section)
|
|
local mode = ListValue.cfgvalue(self, section)
|
|
local wds = m.uci:get("wireless", section, "wds") == "1"
|
|
|
|
if mode == "ap" and wds then
|
|
return "ap-wds"
|
|
elseif mode == "sta" and wds then
|
|
return "sta-wds"
|
|
else
|
|
return mode
|
|
end
|
|
end
|
|
|
|
bssid:depends({mode="adhoc"})
|
|
bssid:depends({mode="ahdemo"})
|
|
bssid:depends({mode="wds"})
|
|
|
|
wdssep = s:taboption("advanced", Flag, "wdssep", translate("Separate WDS"))
|
|
wdssep:depends({mode="ap-wds"})
|
|
|
|
s:taboption("advanced", Flag, "doth", "802.11h")
|
|
hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
|
|
hidden:depends({mode="ap"})
|
|
hidden:depends({mode="adhoc"})
|
|
hidden:depends({mode="ap-wds"})
|
|
hidden:depends({mode="sta-wds"})
|
|
isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
|
|
translate("Prevents client-to-client communication"))
|
|
isolate:depends({mode="ap"})
|
|
s:taboption("advanced", Flag, "bgscan", translate("Background Scan"))
|
|
|
|
mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
|
|
mp:value("", translate("disable"))
|
|
mp:value("allow", translate("Allow listed only"))
|
|
mp:value("deny", translate("Allow all except listed"))
|
|
|
|
ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
|
|
ml.datatype = "macaddr"
|
|
ml:depends({macpolicy="allow"})
|
|
ml:depends({macpolicy="deny"})
|
|
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"))
|
|
s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
|
|
s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
|
|
s:taboption("advanced", Value, "minrate", translate("Minimum Rate"))
|
|
s:taboption("advanced", Value, "maxrate", translate("Maximum Rate"))
|
|
s:taboption("advanced", Flag, "compression", translate("Compression"))
|
|
|
|
s:taboption("advanced", Flag, "bursting", translate("Frame Bursting"))
|
|
s:taboption("advanced", Flag, "turbo", translate("Turbo Mode"))
|
|
s:taboption("advanced", Flag, "ff", translate("Fast Frames"))
|
|
|
|
s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
|
|
s:taboption("advanced", Flag, "xr", translate("XR Support"))
|
|
s:taboption("advanced", Flag, "ar", translate("AR Support"))
|
|
|
|
local swm = s:taboption("advanced", Flag, "sw_merge", translate("Disable HW-Beacon timer"))
|
|
swm:depends({mode="adhoc"})
|
|
|
|
local nos = s:taboption("advanced", Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
|
|
nos:depends({mode="sta"})
|
|
nos:depends({mode="sta-wds"})
|
|
|
|
local probereq = s:taboption("advanced", Flag, "probereq", translate("Do not send probe responses"))
|
|
probereq.enabled = "0"
|
|
probereq.disabled = "1"
|
|
end
|
|
|
|
|
|
-------------------- Broadcom Interface ----------------------
|
|
|
|
if hwtype == "broadcom" then
|
|
mode:value("wds", translate("WDS"))
|
|
mode:value("monitor", translate("Monitor"))
|
|
|
|
hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
|
|
hidden:depends({mode="ap"})
|
|
hidden:depends({mode="adhoc"})
|
|
hidden:depends({mode="wds"})
|
|
|
|
isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
|
|
translate("Prevents client-to-client communication"))
|
|
isolate:depends({mode="ap"})
|
|
|
|
s:taboption("advanced", Flag, "doth", "802.11h")
|
|
s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
|
|
|
|
bssid:depends({mode="wds"})
|
|
bssid:depends({mode="adhoc"})
|
|
end
|
|
|
|
|
|
----------------------- HostAP Interface ---------------------
|
|
|
|
if hwtype == "prism2" then
|
|
mode:value("wds", translate("WDS"))
|
|
mode:value("monitor", translate("Monitor"))
|
|
|
|
hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
|
|
hidden:depends({mode="ap"})
|
|
hidden:depends({mode="adhoc"})
|
|
hidden:depends({mode="wds"})
|
|
|
|
bssid:depends({mode="sta"})
|
|
|
|
mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
|
|
mp:value("", translate("disable"))
|
|
mp:value("allow", translate("Allow listed only"))
|
|
mp:value("deny", translate("Allow all except listed"))
|
|
ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
|
|
ml:depends({macpolicy="allow"})
|
|
ml:depends({macpolicy="deny"})
|
|
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"))
|
|
s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
|
|
end
|
|
|
|
|
|
------------------- WiFI-Encryption -------------------
|
|
|
|
encr = s:taboption("encryption", ListValue, "encryption", translate("Encryption"))
|
|
encr.override_values = true
|
|
encr.override_depends = true
|
|
encr:depends({mode="ap"})
|
|
encr:depends({mode="sta"})
|
|
encr:depends({mode="adhoc"})
|
|
encr:depends({mode="ahdemo"})
|
|
encr:depends({mode="ap-wds"})
|
|
encr:depends({mode="sta-wds"})
|
|
encr:depends({mode="mesh"})
|
|
|
|
cipher = s:taboption("encryption", ListValue, "cipher", translate("Cipher"))
|
|
cipher:depends({encryption="wpa"})
|
|
cipher:depends({encryption="wpa2"})
|
|
cipher:depends({encryption="psk"})
|
|
cipher:depends({encryption="psk2"})
|
|
cipher:depends({encryption="wpa-mixed"})
|
|
cipher:depends({encryption="psk-mixed"})
|
|
cipher:value("auto", translate("auto"))
|
|
cipher:value("ccmp", translate("Force CCMP (AES)"))
|
|
cipher:value("tkip", translate("Force TKIP"))
|
|
cipher:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
|
|
|
|
function encr.cfgvalue(self, section)
|
|
local v = tostring(ListValue.cfgvalue(self, section))
|
|
if v == "wep" then
|
|
return "wep-open"
|
|
elseif v and v:match("%+") then
|
|
return (v:gsub("%+.+$", ""))
|
|
end
|
|
return v
|
|
end
|
|
|
|
function encr.write(self, section, value)
|
|
local e = tostring(encr:formvalue(section))
|
|
local c = tostring(cipher:formvalue(section))
|
|
if value == "wpa" or value == "wpa2" then
|
|
self.map.uci:delete("wireless", section, "key")
|
|
end
|
|
if e and (c == "tkip" or c == "ccmp" or c == "tkip+ccmp") then
|
|
e = e .. "+" .. c
|
|
end
|
|
self.map:set(section, "encryption", e)
|
|
end
|
|
|
|
function cipher.cfgvalue(self, section)
|
|
local v = tostring(ListValue.cfgvalue(encr, section))
|
|
if v and v:match("%+") then
|
|
v = v:gsub("^[^%+]+%+", "")
|
|
if v == "aes" then v = "ccmp"
|
|
elseif v == "tkip+aes" then v = "tkip+ccmp"
|
|
elseif v == "aes+tkip" then v = "tkip+ccmp"
|
|
elseif v == "ccmp+tkip" then v = "tkip+ccmp"
|
|
end
|
|
end
|
|
return v
|
|
end
|
|
|
|
function cipher.write(self, section)
|
|
return encr:write(section)
|
|
end
|
|
|
|
|
|
encr:value("none", "No Encryption")
|
|
encr:value("wep-open", translate("WEP Open System"), {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"}, {mode="adhoc"}, {mode="ahdemo"}, {mode="wds"})
|
|
encr:value("wep-shared", translate("WEP Shared Key"), {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"}, {mode="adhoc"}, {mode="ahdemo"}, {mode="wds"})
|
|
|
|
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
|
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)
|
|
local has_sta_eap = (os.execute("wpa_supplicant -veap >/dev/null 2>/dev/null") == 0)
|
|
|
|
if hostapd and supplicant then
|
|
encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
|
|
encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
|
|
encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
|
|
if has_ap_eap and has_sta_eap then
|
|
encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
|
|
encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
|
|
end
|
|
elseif hostapd and not supplicant then
|
|
encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="ap-wds"})
|
|
encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="ap-wds"})
|
|
encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="ap-wds"})
|
|
if has_ap_eap then
|
|
encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="ap-wds"})
|
|
encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="ap-wds"})
|
|
end
|
|
encr.description = translate(
|
|
"WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
|
|
"and ad-hoc mode) to be installed."
|
|
)
|
|
elseif not hostapd and supplicant then
|
|
encr:value("psk", "WPA-PSK", {mode="sta"}, {mode="sta-wds"})
|
|
encr:value("psk2", "WPA2-PSK", {mode="sta"}, {mode="sta-wds"})
|
|
encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="sta"}, {mode="sta-wds"})
|
|
if has_sta_eap then
|
|
encr:value("wpa", "WPA-EAP", {mode="sta"}, {mode="sta-wds"})
|
|
encr:value("wpa2", "WPA2-EAP", {mode="sta"}, {mode="sta-wds"})
|
|
end
|
|
encr.description = translate(
|
|
"WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
|
|
"and ad-hoc mode) to be installed."
|
|
)
|
|
else
|
|
encr.description = translate(
|
|
"WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
|
|
"and ad-hoc mode) to be installed."
|
|
)
|
|
end
|
|
elseif hwtype == "broadcom" then
|
|
encr:value("psk", "WPA-PSK")
|
|
encr:value("psk2", "WPA2-PSK")
|
|
encr:value("psk+psk2", "WPA-PSK/WPA2-PSK Mixed Mode")
|
|
end
|
|
|
|
auth_server = s:taboption("encryption", Value, "auth_server", translate("Radius-Authentication-Server"))
|
|
auth_server:depends({mode="ap", encryption="wpa"})
|
|
auth_server:depends({mode="ap", encryption="wpa2"})
|
|
auth_server:depends({mode="ap-wds", encryption="wpa"})
|
|
auth_server:depends({mode="ap-wds", encryption="wpa2"})
|
|
auth_server.rmempty = true
|
|
auth_server.datatype = "host(0)"
|
|
|
|
auth_port = s:taboption("encryption", Value, "auth_port", translate("Radius-Authentication-Port"), translatef("Default %d", 1812))
|
|
auth_port:depends({mode="ap", encryption="wpa"})
|
|
auth_port:depends({mode="ap", encryption="wpa2"})
|
|
auth_port:depends({mode="ap-wds", encryption="wpa"})
|
|
auth_port:depends({mode="ap-wds", encryption="wpa2"})
|
|
auth_port.rmempty = true
|
|
auth_port.datatype = "port"
|
|
|
|
auth_secret = s:taboption("encryption", Value, "auth_secret", translate("Radius-Authentication-Secret"))
|
|
auth_secret:depends({mode="ap", encryption="wpa"})
|
|
auth_secret:depends({mode="ap", encryption="wpa2"})
|
|
auth_secret:depends({mode="ap-wds", encryption="wpa"})
|
|
auth_secret:depends({mode="ap-wds", encryption="wpa2"})
|
|
auth_secret.rmempty = true
|
|
auth_secret.password = true
|
|
|
|
acct_server = s:taboption("encryption", Value, "acct_server", translate("Radius-Accounting-Server"))
|
|
acct_server:depends({mode="ap", encryption="wpa"})
|
|
acct_server:depends({mode="ap", encryption="wpa2"})
|
|
acct_server:depends({mode="ap-wds", encryption="wpa"})
|
|
acct_server:depends({mode="ap-wds", encryption="wpa2"})
|
|
acct_server.rmempty = true
|
|
acct_server.datatype = "host(0)"
|
|
|
|
acct_port = s:taboption("encryption", Value, "acct_port", translate("Radius-Accounting-Port"), translatef("Default %d", 1813))
|
|
acct_port:depends({mode="ap", encryption="wpa"})
|
|
acct_port:depends({mode="ap", encryption="wpa2"})
|
|
acct_port:depends({mode="ap-wds", encryption="wpa"})
|
|
acct_port:depends({mode="ap-wds", encryption="wpa2"})
|
|
acct_port.rmempty = true
|
|
acct_port.datatype = "port"
|
|
|
|
acct_secret = s:taboption("encryption", Value, "acct_secret", translate("Radius-Accounting-Secret"))
|
|
acct_secret:depends({mode="ap", encryption="wpa"})
|
|
acct_secret:depends({mode="ap", encryption="wpa2"})
|
|
acct_secret:depends({mode="ap-wds", encryption="wpa"})
|
|
acct_secret:depends({mode="ap-wds", encryption="wpa2"})
|
|
acct_secret.rmempty = true
|
|
acct_secret.password = true
|
|
|
|
wpakey = s:taboption("encryption", Value, "_wpa_key", translate("Key"))
|
|
wpakey:depends("encryption", "psk")
|
|
wpakey:depends("encryption", "psk2")
|
|
wpakey:depends("encryption", "psk+psk2")
|
|
wpakey:depends("encryption", "psk-mixed")
|
|
wpakey.datatype = "wpakey"
|
|
wpakey.rmempty = true
|
|
wpakey.password = true
|
|
|
|
wpakey.cfgvalue = function(self, section, value)
|
|
local key = m.uci:get("wireless", section, "key")
|
|
if key == "1" or key == "2" or key == "3" or key == "4" then
|
|
return nil
|
|
end
|
|
return key
|
|
end
|
|
|
|
wpakey.write = function(self, section, value)
|
|
self.map.uci:set("wireless", section, "key", value)
|
|
self.map.uci:delete("wireless", section, "key1")
|
|
end
|
|
|
|
|
|
wepslot = s:taboption("encryption", ListValue, "_wep_key", translate("Used Key Slot"))
|
|
wepslot:depends("encryption", "wep-open")
|
|
wepslot:depends("encryption", "wep-shared")
|
|
wepslot:value("1", translatef("Key #%d", 1))
|
|
wepslot:value("2", translatef("Key #%d", 2))
|
|
wepslot:value("3", translatef("Key #%d", 3))
|
|
wepslot:value("4", translatef("Key #%d", 4))
|
|
|
|
wepslot.cfgvalue = function(self, section)
|
|
local slot = tonumber(m.uci:get("wireless", section, "key"))
|
|
if not slot or slot < 1 or slot > 4 then
|
|
return 1
|
|
end
|
|
return slot
|
|
end
|
|
|
|
wepslot.write = function(self, section, value)
|
|
self.map.uci:set("wireless", section, "key", value)
|
|
end
|
|
|
|
local slot
|
|
for slot=1,4 do
|
|
wepkey = s:taboption("encryption", Value, "key" .. slot, translatef("Key #%d", slot))
|
|
wepkey:depends("encryption", "wep-open")
|
|
wepkey:depends("encryption", "wep-shared")
|
|
wepkey.datatype = "wepkey"
|
|
wepkey.rmempty = true
|
|
wepkey.password = true
|
|
|
|
function wepkey.write(self, section, value)
|
|
if value and (#value == 5 or #value == 13) then
|
|
value = "s:" .. value
|
|
end
|
|
return Value.write(self, section, value)
|
|
end
|
|
end
|
|
|
|
|
|
if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
|
|
nasid = s:taboption("encryption", Value, "nasid", translate("NAS ID"))
|
|
nasid:depends({mode="ap", encryption="wpa"})
|
|
nasid:depends({mode="ap", encryption="wpa2"})
|
|
nasid:depends({mode="ap-wds", encryption="wpa"})
|
|
nasid:depends({mode="ap-wds", encryption="wpa2"})
|
|
nasid.rmempty = true
|
|
|
|
eaptype = s:taboption("encryption", ListValue, "eap_type", translate("EAP-Method"))
|
|
eaptype:value("tls", "TLS")
|
|
eaptype:value("ttls", "TTLS")
|
|
eaptype:value("peap", "PEAP")
|
|
eaptype:depends({mode="sta", encryption="wpa"})
|
|
eaptype:depends({mode="sta", encryption="wpa2"})
|
|
eaptype:depends({mode="sta-wds", encryption="wpa"})
|
|
eaptype:depends({mode="sta-wds", encryption="wpa2"})
|
|
|
|
cacert = s:taboption("encryption", FileUpload, "ca_cert", translate("Path to CA-Certificate"))
|
|
cacert:depends({mode="sta", encryption="wpa"})
|
|
cacert:depends({mode="sta", encryption="wpa2"})
|
|
cacert:depends({mode="sta-wds", encryption="wpa"})
|
|
cacert:depends({mode="sta-wds", encryption="wpa2"})
|
|
|
|
clientcert = s:taboption("encryption", FileUpload, "client_cert", translate("Path to Client-Certificate"))
|
|
clientcert:depends({mode="sta", encryption="wpa"})
|
|
clientcert:depends({mode="sta", encryption="wpa2"})
|
|
clientcert:depends({mode="sta-wds", encryption="wpa"})
|
|
clientcert:depends({mode="sta-wds", encryption="wpa2"})
|
|
|
|
privkey = s:taboption("encryption", FileUpload, "priv_key", translate("Path to Private Key"))
|
|
privkey:depends({mode="sta", eap_type="tls", encryption="wpa2"})
|
|
privkey:depends({mode="sta", eap_type="tls", encryption="wpa"})
|
|
privkey:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
|
|
privkey:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
|
|
|
|
privkeypwd = s:taboption("encryption", Value, "priv_key_pwd", translate("Password of Private Key"))
|
|
privkeypwd:depends({mode="sta", eap_type="tls", encryption="wpa2"})
|
|
privkeypwd:depends({mode="sta", eap_type="tls", encryption="wpa"})
|
|
privkeypwd:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
|
|
privkeypwd:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
|
|
|
|
|
|
auth = s:taboption("encryption", Value, "auth", translate("Authentication"))
|
|
auth:value("PAP")
|
|
auth:value("CHAP")
|
|
auth:value("MSCHAP")
|
|
auth:value("MSCHAPV2")
|
|
auth:depends({mode="sta", eap_type="peap", encryption="wpa2"})
|
|
auth:depends({mode="sta", eap_type="peap", encryption="wpa"})
|
|
auth:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
|
|
auth:depends({mode="sta", eap_type="ttls", encryption="wpa"})
|
|
auth:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
|
|
auth:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
|
|
auth:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
|
|
auth:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
|
|
|
|
|
|
identity = s:taboption("encryption", Value, "identity", translate("Identity"))
|
|
identity:depends({mode="sta", eap_type="peap", encryption="wpa2"})
|
|
identity:depends({mode="sta", eap_type="peap", encryption="wpa"})
|
|
identity:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
|
|
identity:depends({mode="sta", eap_type="ttls", encryption="wpa"})
|
|
identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
|
|
identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
|
|
identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
|
|
identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
|
|
|
|
password = s:taboption("encryption", Value, "password", translate("Password"))
|
|
password:depends({mode="sta", eap_type="peap", encryption="wpa2"})
|
|
password:depends({mode="sta", eap_type="peap", encryption="wpa"})
|
|
password:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
|
|
password:depends({mode="sta", eap_type="ttls", encryption="wpa"})
|
|
password:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
|
|
password:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
|
|
password:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
|
|
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
|