wifi.lua 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local wa = require "luci.tools.webadmin"
  4. local nw = require "luci.model.network"
  5. local ut = require "luci.util"
  6. local nt = require "luci.sys".net
  7. local fs = require "nixio.fs"
  8. arg[1] = arg[1] or ""
  9. m = Map("wireless", "",
  10. translate("The <em>Device Configuration</em> section covers physical settings of the radio " ..
  11. "hardware such as channel, transmit power or antenna selection which are shared among all " ..
  12. "defined wireless networks (if the radio hardware is multi-SSID capable). Per network settings " ..
  13. "like encryption or operation mode are grouped in the <em>Interface Configuration</em>."))
  14. m:chain("network")
  15. m:chain("firewall")
  16. m.redirect = luci.dispatcher.build_url("admin/network/wireless")
  17. local ifsection
  18. function m.on_commit(map)
  19. local wnet = nw:get_wifinet(arg[1])
  20. if ifsection and wnet then
  21. ifsection.section = wnet.sid
  22. m.title = luci.util.pcdata(wnet:get_i18n())
  23. end
  24. end
  25. nw.init(m.uci)
  26. local wnet = nw:get_wifinet(arg[1])
  27. local wdev = wnet and wnet:get_device()
  28. -- redirect to overview page if network does not exist anymore (e.g. after a revert)
  29. if not wnet or not wdev then
  30. luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
  31. return
  32. end
  33. -- wireless toggle was requested, commit and reload page
  34. function m.parse(map)
  35. local new_cc = m:formvalue("cbid.wireless.%s.country" % wdev:name())
  36. local old_cc = m:get(wdev:name(), "country")
  37. if m:formvalue("cbid.wireless.%s.__toggle" % wdev:name()) then
  38. if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then
  39. wnet:set("disabled", nil)
  40. else
  41. wnet:set("disabled", "1")
  42. end
  43. wdev:set("disabled", nil)
  44. nw:commit("wireless")
  45. luci.sys.call("(env -i /bin/ubus call network reload) >/dev/null 2>/dev/null")
  46. luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1]))
  47. return
  48. end
  49. Map.parse(map)
  50. if m:get(wdev:name(), "type") == "mac80211" and new_cc and new_cc ~= old_cc then
  51. luci.sys.call("iw reg set %q" % new_cc)
  52. luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1]))
  53. return
  54. end
  55. end
  56. m.title = luci.util.pcdata(wnet:get_i18n())
  57. local function txpower_list(iw)
  58. local list = iw.txpwrlist or { }
  59. local off = tonumber(iw.txpower_offset) or 0
  60. local new = { }
  61. local prev = -1
  62. local _, val
  63. for _, val in ipairs(list) do
  64. local dbm = val.dbm + off
  65. local mw = math.floor(10 ^ (dbm / 10))
  66. if mw ~= prev then
  67. prev = mw
  68. new[#new+1] = {
  69. display_dbm = dbm,
  70. display_mw = mw,
  71. driver_dbm = val.dbm,
  72. driver_mw = val.mw
  73. }
  74. end
  75. end
  76. return new
  77. end
  78. local function txpower_current(pwr, list)
  79. pwr = tonumber(pwr)
  80. if pwr ~= nil then
  81. local _, item
  82. for _, item in ipairs(list) do
  83. if item.driver_dbm >= pwr then
  84. return item.driver_dbm
  85. end
  86. end
  87. end
  88. return pwr or ""
  89. end
  90. local iw = luci.sys.wifi.getiwinfo(arg[1])
  91. local hw_modes = iw.hwmodelist or { }
  92. local tx_power_list = txpower_list(iw)
  93. local tx_power_cur = txpower_current(wdev:get("txpower"), tx_power_list)
  94. s = m:section(NamedSection, wdev:name(), "wifi-device", translate("Device Configuration"))
  95. s.addremove = false
  96. s:tab("general", translate("General Setup"))
  97. s:tab("macfilter", translate("MAC-Filter"))
  98. s:tab("advanced", translate("Advanced Settings"))
  99. --[[
  100. back = s:option(DummyValue, "_overview", translate("Overview"))
  101. back.value = ""
  102. back.titleref = luci.dispatcher.build_url("admin", "network", "wireless")
  103. ]]
  104. st = s:taboption("general", DummyValue, "__status", translate("Status"))
  105. st.template = "admin_network/wifi_status"
  106. st.ifname = arg[1]
  107. en = s:taboption("general", Button, "__toggle")
  108. if wdev:get("disabled") == "1" or wnet:get("disabled") == "1" then
  109. en.title = translate("Wireless network is disabled")
  110. en.inputtitle = translate("Enable")
  111. en.inputstyle = "apply"
  112. else
  113. en.title = translate("Wireless network is enabled")
  114. en.inputtitle = translate("Disable")
  115. en.inputstyle = "reset"
  116. end
  117. local hwtype = wdev:get("type")
  118. -- NanoFoo
  119. local nsantenna = wdev:get("antenna")
  120. -- Check whether there are client interfaces on the same radio,
  121. -- if yes, lock the channel choice as these stations will dicatate the freq
  122. local found_sta = nil
  123. local _, net
  124. if wnet:mode() ~= "sta" then
  125. for _, net in ipairs(wdev:get_wifinets()) do
  126. if net:mode() == "sta" and net:get("disabled") ~= "1" then
  127. if not found_sta then
  128. found_sta = {}
  129. found_sta.channel = net:channel()
  130. found_sta.names = {}
  131. end
  132. found_sta.names[#found_sta.names+1] = net:shortname()
  133. end
  134. end
  135. end
  136. if found_sta then
  137. ch = s:taboption("general", DummyValue, "choice", translate("Channel"))
  138. ch.value = translatef("Locked to channel %s used by: %s",
  139. found_sta.channel or "(auto)", table.concat(found_sta.names, ", "))
  140. else
  141. ch = s:taboption("general", Value, "_mode_freq", '<br />'..translate("Operating frequency"))
  142. ch.hwmodes = hw_modes
  143. ch.htmodes = iw.htmodelist
  144. ch.freqlist = iw.freqlist
  145. ch.template = "cbi/wireless_modefreq"
  146. function ch.cfgvalue(self, section)
  147. return {
  148. m:get(section, "hwmode") or "",
  149. m:get(section, "channel") or "auto",
  150. m:get(section, "htmode") or ""
  151. }
  152. end
  153. function ch.formvalue(self, section)
  154. return {
  155. m:formvalue(self:cbid(section) .. ".band") or (hw_modes.g and "11g" or "11a"),
  156. m:formvalue(self:cbid(section) .. ".channel") or "auto",
  157. m:formvalue(self:cbid(section) .. ".htmode") or ""
  158. }
  159. end
  160. function ch.write(self, section, value)
  161. m:set(section, "hwmode", value[1])
  162. m:set(section, "channel", value[2])
  163. m:set(section, "htmode", value[3])
  164. end
  165. end
  166. ------------------- MAC80211 Device ------------------
  167. if hwtype == "mac80211" then
  168. if #tx_power_list > 0 then
  169. tp = s:taboption("general", ListValue,
  170. "txpower", translate("Transmit Power"), "dBm")
  171. tp.rmempty = true
  172. tp.default = tx_power_cur
  173. function tp.cfgvalue(...)
  174. return txpower_current(Value.cfgvalue(...), tx_power_list)
  175. end
  176. tp:value("", translate("auto"))
  177. for _, p in ipairs(tx_power_list) do
  178. tp:value(p.driver_dbm, "%i dBm (%i mW)"
  179. %{ p.display_dbm, p.display_mw })
  180. end
  181. end
  182. local cl = iw and iw.countrylist
  183. if cl and #cl > 0 then
  184. cc = s:taboption("advanced", ListValue, "country", translate("Country Code"), translate("Use ISO/IEC 3166 alpha2 country codes."))
  185. cc.default = tostring(iw and iw.country or "00")
  186. for _, c in ipairs(cl) do
  187. cc:value(c.alpha2, "%s - %s" %{ c.alpha2, c.name })
  188. end
  189. else
  190. s:taboption("advanced", Value, "country", translate("Country Code"), translate("Use ISO/IEC 3166 alpha2 country codes."))
  191. end
  192. s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
  193. translate("Distance to farthest network member in meters."))
  194. -- external antenna profiles
  195. local eal = iw and iw.extant
  196. if eal and #eal > 0 then
  197. ea = s:taboption("advanced", ListValue, "extant", translate("Antenna Configuration"))
  198. for _, eap in ipairs(eal) do
  199. ea:value(eap.id, "%s (%s)" %{ eap.name, eap.description })
  200. if eap.selected then
  201. ea.default = eap.id
  202. end
  203. end
  204. end
  205. s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
  206. s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
  207. end
  208. ------------------- Madwifi Device ------------------
  209. if hwtype == "atheros" then
  210. tp = s:taboption("general",
  211. (#tx_power_list > 0) and ListValue or Value,
  212. "txpower", translate("Transmit Power"), "dBm")
  213. tp.rmempty = true
  214. tp.default = tx_power_cur
  215. function tp.cfgvalue(...)
  216. return txpower_current(Value.cfgvalue(...), tx_power_list)
  217. end
  218. tp:value("", translate("auto"))
  219. for _, p in ipairs(tx_power_list) do
  220. tp:value(p.driver_dbm, "%i dBm (%i mW)"
  221. %{ p.display_dbm, p.display_mw })
  222. end
  223. s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
  224. if not nsantenna then
  225. ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
  226. ant1.widget = "radio"
  227. ant1.orientation = "horizontal"
  228. ant1:depends("diversity", "")
  229. ant1:value("0", translate("auto"))
  230. ant1:value("1", translate("Antenna 1"))
  231. ant1:value("2", translate("Antenna 2"))
  232. ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
  233. ant2.widget = "radio"
  234. ant2.orientation = "horizontal"
  235. ant2:depends("diversity", "")
  236. ant2:value("0", translate("auto"))
  237. ant2:value("1", translate("Antenna 1"))
  238. ant2:value("2", translate("Antenna 2"))
  239. else -- NanoFoo
  240. local ant = s:taboption("advanced", ListValue, "antenna", translate("Transmitter Antenna"))
  241. ant:value("auto")
  242. ant:value("vertical")
  243. ant:value("horizontal")
  244. ant:value("external")
  245. end
  246. s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
  247. translate("Distance to farthest network member in meters."))
  248. s:taboption("advanced", Value, "regdomain", translate("Regulatory Domain"))
  249. s:taboption("advanced", Value, "country", translate("Country Code"))
  250. s:taboption("advanced", Flag, "outdoor", translate("Outdoor Channels"))
  251. --s:option(Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
  252. end
  253. ------------------- Broadcom Device ------------------
  254. if hwtype == "broadcom" then
  255. tp = s:taboption("general",
  256. (#tx_power_list > 0) and ListValue or Value,
  257. "txpower", translate("Transmit Power"), "dBm")
  258. tp.rmempty = true
  259. tp.default = tx_power_cur
  260. function tp.cfgvalue(...)
  261. return txpower_current(Value.cfgvalue(...), tx_power_list)
  262. end
  263. tp:value("", translate("auto"))
  264. for _, p in ipairs(tx_power_list) do
  265. tp:value(p.driver_dbm, "%i dBm (%i mW)"
  266. %{ p.display_dbm, p.display_mw })
  267. end
  268. mode = s:taboption("advanced", ListValue, "hwmode", translate("Band"))
  269. if hw_modes.b then
  270. mode:value("11b", "2.4GHz (802.11b)")
  271. if hw_modes.g then
  272. mode:value("11bg", "2.4GHz (802.11b+g)")
  273. end
  274. end
  275. if hw_modes.g then
  276. mode:value("11g", "2.4GHz (802.11g)")
  277. mode:value("11gst", "2.4GHz (802.11g + Turbo)")
  278. mode:value("11lrs", "2.4GHz (802.11g Limited Rate Support)")
  279. end
  280. if hw_modes.a then mode:value("11a", "5GHz (802.11a)") end
  281. if hw_modes.n then
  282. if hw_modes.g then
  283. mode:value("11ng", "2.4GHz (802.11g+n)")
  284. mode:value("11n", "2.4GHz (802.11n)")
  285. end
  286. if hw_modes.a then
  287. mode:value("11na", "5GHz (802.11a+n)")
  288. mode:value("11n", "5GHz (802.11n)")
  289. end
  290. htmode = s:taboption("advanced", ListValue, "htmode", translate("HT mode (802.11n)"))
  291. htmode:depends("hwmode", "11ng")
  292. htmode:depends("hwmode", "11na")
  293. htmode:depends("hwmode", "11n")
  294. htmode:value("HT20", "20MHz")
  295. htmode:value("HT40", "40MHz")
  296. end
  297. ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
  298. ant1.widget = "radio"
  299. ant1:depends("diversity", "")
  300. ant1:value("3", translate("auto"))
  301. ant1:value("0", translate("Antenna 1"))
  302. ant1:value("1", translate("Antenna 2"))
  303. ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
  304. ant2.widget = "radio"
  305. ant2:depends("diversity", "")
  306. ant2:value("3", translate("auto"))
  307. ant2:value("0", translate("Antenna 1"))
  308. ant2:value("1", translate("Antenna 2"))
  309. s:taboption("advanced", Flag, "frameburst", translate("Frame Bursting"))
  310. s:taboption("advanced", Value, "distance", translate("Distance Optimization"))
  311. --s:option(Value, "slottime", translate("Slot time"))
  312. s:taboption("advanced", Value, "country", translate("Country Code"))
  313. s:taboption("advanced", Value, "maxassoc", translate("Connection Limit"))
  314. end
  315. --------------------- HostAP Device ---------------------
  316. if hwtype == "prism2" then
  317. s:taboption("advanced", Value, "txpower", translate("Transmit Power"), "att units").rmempty = true
  318. s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
  319. s:taboption("advanced", Value, "txantenna", translate("Transmitter Antenna"))
  320. s:taboption("advanced", Value, "rxantenna", translate("Receiver Antenna"))
  321. end
  322. ----------------------- Interface -----------------------
  323. s = m:section(NamedSection, wnet.sid, "wifi-iface", translate("Interface Configuration"))
  324. ifsection = s
  325. s.addremove = false
  326. s.anonymous = true
  327. s.defaults.device = wdev:name()
  328. s:tab("general", translate("General Setup"))
  329. s:tab("encryption", translate("Wireless Security"))
  330. s:tab("macfilter", translate("MAC-Filter"))
  331. s:tab("advanced", translate("Advanced Settings"))
  332. ssid = s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
  333. ssid.datatype = "maxlength(32)"
  334. mode = s:taboption("general", ListValue, "mode", translate("Mode"))
  335. mode.override_values = true
  336. mode:value("ap", translate("Access Point"))
  337. mode:value("sta", translate("Client"))
  338. mode:value("adhoc", translate("Ad-Hoc"))
  339. bssid = s:taboption("general", Value, "bssid", translate("<abbr title=\"Basic Service Set Identifier\">BSSID</abbr>"))
  340. network = s:taboption("general", Value, "network", translate("Network"),
  341. translate("Choose the network(s) you want to attach to this wireless interface or " ..
  342. "fill out the <em>create</em> field to define a new network."))
  343. network.rmempty = true
  344. network.template = "cbi/network_netlist"
  345. network.widget = "checkbox"
  346. network.novirtual = true
  347. function network.write(self, section, value)
  348. local i = nw:get_interface(section)
  349. if i then
  350. if value == '-' then
  351. value = m:formvalue(self:cbid(section) .. ".newnet")
  352. if value and #value > 0 then
  353. local n = nw:add_network(value, {proto="none"})
  354. if n then n:add_interface(i) end
  355. else
  356. local n = i:get_network()
  357. if n then n:del_interface(i) end
  358. end
  359. else
  360. local v
  361. for _, v in ipairs(i:get_networks()) do
  362. v:del_interface(i)
  363. end
  364. for v in ut.imatch(value) do
  365. local n = nw:get_network(v)
  366. if n then
  367. if not n:is_empty() then
  368. n:set("type", "bridge")
  369. end
  370. n:add_interface(i)
  371. end
  372. end
  373. end
  374. end
  375. end
  376. -------------------- MAC80211 Interface ----------------------
  377. if hwtype == "mac80211" then
  378. if fs.access("/usr/sbin/iw") then
  379. mode:value("mesh", "802.11s")
  380. end
  381. mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
  382. mode:value("monitor", translate("Monitor"))
  383. bssid:depends({mode="adhoc"})
  384. bssid:depends({mode="sta"})
  385. bssid:depends({mode="sta-wds"})
  386. mp = s:taboption("macfilter", ListValue, "macfilter", translate("MAC-Address Filter"))
  387. mp:depends({mode="ap"})
  388. mp:depends({mode="ap-wds"})
  389. mp:value("", translate("disable"))
  390. mp:value("allow", translate("Allow listed only"))
  391. mp:value("deny", translate("Allow all except listed"))
  392. ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
  393. ml.datatype = "macaddr"
  394. ml:depends({macfilter="allow"})
  395. ml:depends({macfilter="deny"})
  396. nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
  397. mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
  398. mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
  399. function mode.write(self, section, value)
  400. if value == "ap-wds" then
  401. ListValue.write(self, section, "ap")
  402. m.uci:set("wireless", section, "wds", 1)
  403. elseif value == "sta-wds" then
  404. ListValue.write(self, section, "sta")
  405. m.uci:set("wireless", section, "wds", 1)
  406. else
  407. ListValue.write(self, section, value)
  408. m.uci:delete("wireless", section, "wds")
  409. end
  410. end
  411. function mode.cfgvalue(self, section)
  412. local mode = ListValue.cfgvalue(self, section)
  413. local wds = m.uci:get("wireless", section, "wds") == "1"
  414. if mode == "ap" and wds then
  415. return "ap-wds"
  416. elseif mode == "sta" and wds then
  417. return "sta-wds"
  418. else
  419. return mode
  420. end
  421. end
  422. hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
  423. hidden:depends({mode="ap"})
  424. hidden:depends({mode="ap-wds"})
  425. wmm = s:taboption("general", Flag, "wmm", translate("WMM Mode"))
  426. wmm:depends({mode="ap"})
  427. wmm:depends({mode="ap-wds"})
  428. wmm.default = wmm.enabled
  429. ifname = s:taboption("advanced", Value, "ifname", translate("Interface name"), translate("Override default interface name"))
  430. ifname.optional = true
  431. end
  432. -------------------- Madwifi Interface ----------------------
  433. if hwtype == "atheros" then
  434. mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
  435. mode:value("monitor", translate("Monitor"))
  436. mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
  437. mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
  438. mode:value("wds", translate("Static WDS"))
  439. function mode.write(self, section, value)
  440. if value == "ap-wds" then
  441. ListValue.write(self, section, "ap")
  442. m.uci:set("wireless", section, "wds", 1)
  443. elseif value == "sta-wds" then
  444. ListValue.write(self, section, "sta")
  445. m.uci:set("wireless", section, "wds", 1)
  446. else
  447. ListValue.write(self, section, value)
  448. m.uci:delete("wireless", section, "wds")
  449. end
  450. end
  451. function mode.cfgvalue(self, section)
  452. local mode = ListValue.cfgvalue(self, section)
  453. local wds = m.uci:get("wireless", section, "wds") == "1"
  454. if mode == "ap" and wds then
  455. return "ap-wds"
  456. elseif mode == "sta" and wds then
  457. return "sta-wds"
  458. else
  459. return mode
  460. end
  461. end
  462. bssid:depends({mode="adhoc"})
  463. bssid:depends({mode="ahdemo"})
  464. bssid:depends({mode="wds"})
  465. wdssep = s:taboption("advanced", Flag, "wdssep", translate("Separate WDS"))
  466. wdssep:depends({mode="ap-wds"})
  467. s:taboption("advanced", Flag, "doth", "802.11h")
  468. hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
  469. hidden:depends({mode="ap"})
  470. hidden:depends({mode="adhoc"})
  471. hidden:depends({mode="ap-wds"})
  472. hidden:depends({mode="sta-wds"})
  473. isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
  474. translate("Prevents client-to-client communication"))
  475. isolate:depends({mode="ap"})
  476. s:taboption("advanced", Flag, "bgscan", translate("Background Scan"))
  477. mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
  478. mp:value("", translate("disable"))
  479. mp:value("allow", translate("Allow listed only"))
  480. mp:value("deny", translate("Allow all except listed"))
  481. ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
  482. ml.datatype = "macaddr"
  483. ml:depends({macpolicy="allow"})
  484. ml:depends({macpolicy="deny"})
  485. nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
  486. s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
  487. s:taboption("advanced", Value, "mcast_rate", translate("Multicast Rate"))
  488. s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
  489. s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
  490. s:taboption("advanced", Value, "minrate", translate("Minimum Rate"))
  491. s:taboption("advanced", Value, "maxrate", translate("Maximum Rate"))
  492. s:taboption("advanced", Flag, "compression", translate("Compression"))
  493. s:taboption("advanced", Flag, "bursting", translate("Frame Bursting"))
  494. s:taboption("advanced", Flag, "turbo", translate("Turbo Mode"))
  495. s:taboption("advanced", Flag, "ff", translate("Fast Frames"))
  496. s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
  497. s:taboption("advanced", Flag, "xr", translate("XR Support"))
  498. s:taboption("advanced", Flag, "ar", translate("AR Support"))
  499. local swm = s:taboption("advanced", Flag, "sw_merge", translate("Disable HW-Beacon timer"))
  500. swm:depends({mode="adhoc"})
  501. local nos = s:taboption("advanced", Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
  502. nos:depends({mode="sta"})
  503. nos:depends({mode="sta-wds"})
  504. local probereq = s:taboption("advanced", Flag, "probereq", translate("Do not send probe responses"))
  505. probereq.enabled = "0"
  506. probereq.disabled = "1"
  507. end
  508. -------------------- Broadcom Interface ----------------------
  509. if hwtype == "broadcom" then
  510. mode:value("wds", translate("WDS"))
  511. mode:value("monitor", translate("Monitor"))
  512. hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
  513. hidden:depends({mode="ap"})
  514. hidden:depends({mode="adhoc"})
  515. hidden:depends({mode="wds"})
  516. isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
  517. translate("Prevents client-to-client communication"))
  518. isolate:depends({mode="ap"})
  519. s:taboption("advanced", Flag, "doth", "802.11h")
  520. s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
  521. bssid:depends({mode="wds"})
  522. bssid:depends({mode="adhoc"})
  523. end
  524. ----------------------- HostAP Interface ---------------------
  525. if hwtype == "prism2" then
  526. mode:value("wds", translate("WDS"))
  527. mode:value("monitor", translate("Monitor"))
  528. hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
  529. hidden:depends({mode="ap"})
  530. hidden:depends({mode="adhoc"})
  531. hidden:depends({mode="wds"})
  532. bssid:depends({mode="sta"})
  533. mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
  534. mp:value("", translate("disable"))
  535. mp:value("allow", translate("Allow listed only"))
  536. mp:value("deny", translate("Allow all except listed"))
  537. ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
  538. ml:depends({macpolicy="allow"})
  539. ml:depends({macpolicy="deny"})
  540. nt.mac_hints(function(mac, name) ml:value(mac, "%s (%s)" %{ mac, name }) end)
  541. s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
  542. s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
  543. s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
  544. end
  545. ------------------- WiFI-Encryption -------------------
  546. encr = s:taboption("encryption", ListValue, "encryption", translate("Encryption"))
  547. encr.override_values = true
  548. encr.override_depends = true
  549. encr:depends({mode="ap"})
  550. encr:depends({mode="sta"})
  551. encr:depends({mode="adhoc"})
  552. encr:depends({mode="ahdemo"})
  553. encr:depends({mode="ap-wds"})
  554. encr:depends({mode="sta-wds"})
  555. encr:depends({mode="mesh"})
  556. cipher = s:taboption("encryption", ListValue, "cipher", translate("Cipher"))
  557. cipher:depends({encryption="wpa"})
  558. cipher:depends({encryption="wpa2"})
  559. cipher:depends({encryption="psk"})
  560. cipher:depends({encryption="psk2"})
  561. cipher:depends({encryption="wpa-mixed"})
  562. cipher:depends({encryption="psk-mixed"})
  563. cipher:value("auto", translate("auto"))
  564. cipher:value("ccmp", translate("Force CCMP (AES)"))
  565. cipher:value("tkip", translate("Force TKIP"))
  566. cipher:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
  567. function encr.cfgvalue(self, section)
  568. local v = tostring(ListValue.cfgvalue(self, section))
  569. if v == "wep" then
  570. return "wep-open"
  571. elseif v and v:match("%+") then
  572. return (v:gsub("%+.+$", ""))
  573. end
  574. return v
  575. end
  576. function encr.write(self, section, value)
  577. local e = tostring(encr:formvalue(section))
  578. local c = tostring(cipher:formvalue(section))
  579. if value == "wpa" or value == "wpa2" then
  580. self.map.uci:delete("wireless", section, "key")
  581. end
  582. if e and (c == "tkip" or c == "ccmp" or c == "tkip+ccmp") then
  583. e = e .. "+" .. c
  584. end
  585. self.map:set(section, "encryption", e)
  586. end
  587. function cipher.cfgvalue(self, section)
  588. local v = tostring(ListValue.cfgvalue(encr, section))
  589. if v and v:match("%+") then
  590. v = v:gsub("^[^%+]+%+", "")
  591. if v == "aes" then v = "ccmp"
  592. elseif v == "tkip+aes" then v = "tkip+ccmp"
  593. elseif v == "aes+tkip" then v = "tkip+ccmp"
  594. elseif v == "ccmp+tkip" then v = "tkip+ccmp"
  595. end
  596. end
  597. return v
  598. end
  599. function cipher.write(self, section)
  600. return encr:write(section)
  601. end
  602. encr:value("none", "No Encryption")
  603. encr:value("wep-open", translate("WEP Open System"), {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"}, {mode="adhoc"}, {mode="ahdemo"}, {mode="wds"})
  604. encr:value("wep-shared", translate("WEP Shared Key"), {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"}, {mode="adhoc"}, {mode="ahdemo"}, {mode="wds"})
  605. if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
  606. local supplicant = fs.access("/usr/sbin/wpa_supplicant")
  607. local hostapd = fs.access("/usr/sbin/hostapd")
  608. -- Probe EAP support
  609. local has_ap_eap = (os.execute("hostapd -veap >/dev/null 2>/dev/null") == 0)
  610. local has_sta_eap = (os.execute("wpa_supplicant -veap >/dev/null 2>/dev/null") == 0)
  611. if hostapd and supplicant then
  612. encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
  613. encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
  614. encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
  615. if has_ap_eap and has_sta_eap then
  616. encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
  617. encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
  618. end
  619. elseif hostapd and not supplicant then
  620. encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="ap-wds"})
  621. encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="ap-wds"})
  622. encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="ap-wds"})
  623. if has_ap_eap then
  624. encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="ap-wds"})
  625. encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="ap-wds"})
  626. end
  627. encr.description = translate(
  628. "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
  629. "and ad-hoc mode) to be installed."
  630. )
  631. elseif not hostapd and supplicant then
  632. encr:value("psk", "WPA-PSK", {mode="sta"}, {mode="sta-wds"})
  633. encr:value("psk2", "WPA2-PSK", {mode="sta"}, {mode="sta-wds"})
  634. encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="sta"}, {mode="sta-wds"})
  635. if has_sta_eap then
  636. encr:value("wpa", "WPA-EAP", {mode="sta"}, {mode="sta-wds"})
  637. encr:value("wpa2", "WPA2-EAP", {mode="sta"}, {mode="sta-wds"})
  638. end
  639. encr.description = translate(
  640. "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
  641. "and ad-hoc mode) to be installed."
  642. )
  643. else
  644. encr.description = translate(
  645. "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
  646. "and ad-hoc mode) to be installed."
  647. )
  648. end
  649. elseif hwtype == "broadcom" then
  650. encr:value("psk", "WPA-PSK")
  651. encr:value("psk2", "WPA2-PSK")
  652. encr:value("psk+psk2", "WPA-PSK/WPA2-PSK Mixed Mode")
  653. end
  654. auth_server = s:taboption("encryption", Value, "auth_server", translate("Radius-Authentication-Server"))
  655. auth_server:depends({mode="ap", encryption="wpa"})
  656. auth_server:depends({mode="ap", encryption="wpa2"})
  657. auth_server:depends({mode="ap-wds", encryption="wpa"})
  658. auth_server:depends({mode="ap-wds", encryption="wpa2"})
  659. auth_server.rmempty = true
  660. auth_server.datatype = "host(0)"
  661. auth_port = s:taboption("encryption", Value, "auth_port", translate("Radius-Authentication-Port"), translatef("Default %d", 1812))
  662. auth_port:depends({mode="ap", encryption="wpa"})
  663. auth_port:depends({mode="ap", encryption="wpa2"})
  664. auth_port:depends({mode="ap-wds", encryption="wpa"})
  665. auth_port:depends({mode="ap-wds", encryption="wpa2"})
  666. auth_port.rmempty = true
  667. auth_port.datatype = "port"
  668. auth_secret = s:taboption("encryption", Value, "auth_secret", translate("Radius-Authentication-Secret"))
  669. auth_secret:depends({mode="ap", encryption="wpa"})
  670. auth_secret:depends({mode="ap", encryption="wpa2"})
  671. auth_secret:depends({mode="ap-wds", encryption="wpa"})
  672. auth_secret:depends({mode="ap-wds", encryption="wpa2"})
  673. auth_secret.rmempty = true
  674. auth_secret.password = true
  675. acct_server = s:taboption("encryption", Value, "acct_server", translate("Radius-Accounting-Server"))
  676. acct_server:depends({mode="ap", encryption="wpa"})
  677. acct_server:depends({mode="ap", encryption="wpa2"})
  678. acct_server:depends({mode="ap-wds", encryption="wpa"})
  679. acct_server:depends({mode="ap-wds", encryption="wpa2"})
  680. acct_server.rmempty = true
  681. acct_server.datatype = "host(0)"
  682. acct_port = s:taboption("encryption", Value, "acct_port", translate("Radius-Accounting-Port"), translatef("Default %d", 1813))
  683. acct_port:depends({mode="ap", encryption="wpa"})
  684. acct_port:depends({mode="ap", encryption="wpa2"})
  685. acct_port:depends({mode="ap-wds", encryption="wpa"})
  686. acct_port:depends({mode="ap-wds", encryption="wpa2"})
  687. acct_port.rmempty = true
  688. acct_port.datatype = "port"
  689. acct_secret = s:taboption("encryption", Value, "acct_secret", translate("Radius-Accounting-Secret"))
  690. acct_secret:depends({mode="ap", encryption="wpa"})
  691. acct_secret:depends({mode="ap", encryption="wpa2"})
  692. acct_secret:depends({mode="ap-wds", encryption="wpa"})
  693. acct_secret:depends({mode="ap-wds", encryption="wpa2"})
  694. acct_secret.rmempty = true
  695. acct_secret.password = true
  696. wpakey = s:taboption("encryption", Value, "_wpa_key", translate("Key"))
  697. wpakey:depends("encryption", "psk")
  698. wpakey:depends("encryption", "psk2")
  699. wpakey:depends("encryption", "psk+psk2")
  700. wpakey:depends("encryption", "psk-mixed")
  701. wpakey.datatype = "wpakey"
  702. wpakey.rmempty = true
  703. wpakey.password = true
  704. wpakey.cfgvalue = function(self, section, value)
  705. local key = m.uci:get("wireless", section, "key")
  706. if key == "1" or key == "2" or key == "3" or key == "4" then
  707. return nil
  708. end
  709. return key
  710. end
  711. wpakey.write = function(self, section, value)
  712. self.map.uci:set("wireless", section, "key", value)
  713. self.map.uci:delete("wireless", section, "key1")
  714. end
  715. wepslot = s:taboption("encryption", ListValue, "_wep_key", translate("Used Key Slot"))
  716. wepslot:depends("encryption", "wep-open")
  717. wepslot:depends("encryption", "wep-shared")
  718. wepslot:value("1", translatef("Key #%d", 1))
  719. wepslot:value("2", translatef("Key #%d", 2))
  720. wepslot:value("3", translatef("Key #%d", 3))
  721. wepslot:value("4", translatef("Key #%d", 4))
  722. wepslot.cfgvalue = function(self, section)
  723. local slot = tonumber(m.uci:get("wireless", section, "key"))
  724. if not slot or slot < 1 or slot > 4 then
  725. return 1
  726. end
  727. return slot
  728. end
  729. wepslot.write = function(self, section, value)
  730. self.map.uci:set("wireless", section, "key", value)
  731. end
  732. local slot
  733. for slot=1,4 do
  734. wepkey = s:taboption("encryption", Value, "key" .. slot, translatef("Key #%d", slot))
  735. wepkey:depends("encryption", "wep-open")
  736. wepkey:depends("encryption", "wep-shared")
  737. wepkey.datatype = "wepkey"
  738. wepkey.rmempty = true
  739. wepkey.password = true
  740. function wepkey.write(self, section, value)
  741. if value and (#value == 5 or #value == 13) then
  742. value = "s:" .. value
  743. end
  744. return Value.write(self, section, value)
  745. end
  746. end
  747. if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
  748. -- Probe 802.11r support (and EAP support as a proxy for Openwrt)
  749. local has_80211r = (os.execute("hostapd -v11r 2>/dev/null || hostapd -veap 2>/dev/null") == 0)
  750. ieee80211r = s:taboption("encryption", Flag, "ieee80211r",
  751. translate("802.11r Fast Transition"),
  752. translate("Enables fast roaming among access points that belong " ..
  753. "to the same Mobility Domain"))
  754. ieee80211r:depends({mode="ap", encryption="wpa"})
  755. ieee80211r:depends({mode="ap", encryption="wpa2"})
  756. ieee80211r:depends({mode="ap-wds", encryption="wpa"})
  757. ieee80211r:depends({mode="ap-wds", encryption="wpa2"})
  758. if has_80211r then
  759. ieee80211r:depends({mode="ap", encryption="psk"})
  760. ieee80211r:depends({mode="ap", encryption="psk2"})
  761. ieee80211r:depends({mode="ap", encryption="psk-mixed"})
  762. end
  763. ieee80211r.rmempty = true
  764. nasid = s:taboption("encryption", Value, "nasid", translate("NAS ID"),
  765. translate("Used for two different purposes: RADIUS NAS ID and " ..
  766. "802.11r R0KH-ID. Not needed with normal WPA(2)-PSK."))
  767. nasid:depends({mode="ap", encryption="wpa"})
  768. nasid:depends({mode="ap", encryption="wpa2"})
  769. nasid:depends({mode="ap-wds", encryption="wpa"})
  770. nasid:depends({mode="ap-wds", encryption="wpa2"})
  771. nasid:depends({ieee80211r="1"})
  772. nasid.rmempty = true
  773. mobility_domain = s:taboption("encryption", Value, "mobility_domain",
  774. translate("Mobility Domain"),
  775. translate("4-character hexadecimal ID"))
  776. mobility_domain:depends({ieee80211r="1"})
  777. mobility_domain.placeholder = "4f57"
  778. mobility_domain.datatype = "and(hexstring,rangelength(4,4))"
  779. mobility_domain.rmempty = true
  780. r0_key_lifetime = s:taboption("encryption", Value, "r0_key_lifetime",
  781. translate("R0 Key Lifetime"), translate("minutes"))
  782. r0_key_lifetime:depends({ieee80211r="1"})
  783. r0_key_lifetime.placeholder = "10000"
  784. r0_key_lifetime.datatype = "uinteger"
  785. r0_key_lifetime.rmempty = true
  786. r1_key_holder = s:taboption("encryption", Value, "r1_key_holder",
  787. translate("R1 Key Holder"),
  788. translate("6-octet identifier as a hex string - no colons"))
  789. r1_key_holder:depends({ieee80211r="1"})
  790. r1_key_holder.placeholder = "00004f577274"
  791. r1_key_holder.datatype = "and(hexstring,rangelength(12,12))"
  792. r1_key_holder.rmempty = true
  793. reassociation_deadline = s:taboption("encryption", Value, "reassociation_deadline",
  794. translate("Reassociation Deadline"),
  795. translate("time units (TUs / 1.024 ms) [1000-65535]"))
  796. reassociation_deadline:depends({ieee80211r="1"})
  797. reassociation_deadline.placeholder = "1000"
  798. reassociation_deadline.datatype = "range(1000,65535)"
  799. reassociation_deadline.rmempty = true
  800. pmk_r1_push = s:taboption("encryption", Flag, "pmk_r1_push", translate("PMK R1 Push"))
  801. pmk_r1_push:depends({ieee80211r="1"})
  802. pmk_r1_push.placeholder = "0"
  803. pmk_r1_push.rmempty = true
  804. r0kh = s:taboption("encryption", DynamicList, "r0kh", translate("External R0 Key Holder List"),
  805. translate("List of R0KHs in the same Mobility Domain. " ..
  806. "<br />Format: MAC-address,NAS-Identifier,128-bit key as hex string. " ..
  807. "<br />This list is used to map R0KH-ID (NAS Identifier) to a destination " ..
  808. "MAC address when requesting PMK-R1 key from the R0KH that the STA " ..
  809. "used during the Initial Mobility Domain Association."))
  810. r0kh:depends({ieee80211r="1"})
  811. r0kh.rmempty = true
  812. r1kh = s:taboption("encryption", DynamicList, "r1kh", translate("External R1 Key Holder List"),
  813. translate ("List of R1KHs in the same Mobility Domain. "..
  814. "<br />Format: MAC-address,R1KH-ID as 6 octets with colons,128-bit key as hex string. "..
  815. "<br />This list is used to map R1KH-ID to a destination MAC address " ..
  816. "when sending PMK-R1 key from the R0KH. This is also the " ..
  817. "list of authorized R1KHs in the MD that can request PMK-R1 keys."))
  818. r1kh:depends({ieee80211r="1"})
  819. r1kh.rmempty = true
  820. -- End of 802.11r options
  821. eaptype = s:taboption("encryption", ListValue, "eap_type", translate("EAP-Method"))
  822. eaptype:value("tls", "TLS")
  823. eaptype:value("ttls", "TTLS")
  824. eaptype:value("peap", "PEAP")
  825. eaptype:value("fast", "FAST")
  826. eaptype:depends({mode="sta", encryption="wpa"})
  827. eaptype:depends({mode="sta", encryption="wpa2"})
  828. eaptype:depends({mode="sta-wds", encryption="wpa"})
  829. eaptype:depends({mode="sta-wds", encryption="wpa2"})
  830. cacert = s:taboption("encryption", FileUpload, "ca_cert", translate("Path to CA-Certificate"))
  831. cacert:depends({mode="sta", encryption="wpa"})
  832. cacert:depends({mode="sta", encryption="wpa2"})
  833. cacert:depends({mode="sta-wds", encryption="wpa"})
  834. cacert:depends({mode="sta-wds", encryption="wpa2"})
  835. cacert.rmempty = true
  836. clientcert = s:taboption("encryption", FileUpload, "client_cert", translate("Path to Client-Certificate"))
  837. clientcert:depends({mode="sta", eap_type="tls", encryption="wpa"})
  838. clientcert:depends({mode="sta", eap_type="tls", encryption="wpa2"})
  839. clientcert:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
  840. clientcert:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
  841. privkey = s:taboption("encryption", FileUpload, "priv_key", translate("Path to Private Key"))
  842. privkey:depends({mode="sta", eap_type="tls", encryption="wpa2"})
  843. privkey:depends({mode="sta", eap_type="tls", encryption="wpa"})
  844. privkey:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
  845. privkey:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
  846. privkeypwd = s:taboption("encryption", Value, "priv_key_pwd", translate("Password of Private Key"))
  847. privkeypwd:depends({mode="sta", eap_type="tls", encryption="wpa2"})
  848. privkeypwd:depends({mode="sta", eap_type="tls", encryption="wpa"})
  849. privkeypwd:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
  850. privkeypwd:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
  851. privkeypwd.rmempty = true
  852. privkeypwd.password = true
  853. auth = s:taboption("encryption", ListValue, "auth", translate("Authentication"))
  854. auth:value("PAP", "PAP", {eap_type="ttls"})
  855. auth:value("CHAP", "CHAP", {eap_type="ttls"})
  856. auth:value("MSCHAP", "MSCHAP", {eap_type="ttls"})
  857. auth:value("MSCHAPV2", "MSCHAPv2", {eap_type="ttls"})
  858. auth:value("EAP-GTC")
  859. auth:value("EAP-MD5")
  860. auth:value("EAP-MSCHAPV2")
  861. auth:value("EAP-TLS")
  862. auth:depends({mode="sta", eap_type="fast", encryption="wpa2"})
  863. auth:depends({mode="sta", eap_type="fast", encryption="wpa"})
  864. auth:depends({mode="sta", eap_type="peap", encryption="wpa2"})
  865. auth:depends({mode="sta", eap_type="peap", encryption="wpa"})
  866. auth:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
  867. auth:depends({mode="sta", eap_type="ttls", encryption="wpa"})
  868. auth:depends({mode="sta-wds", eap_type="fast", encryption="wpa2"})
  869. auth:depends({mode="sta-wds", eap_type="fast", encryption="wpa"})
  870. auth:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
  871. auth:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
  872. auth:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
  873. auth:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
  874. cacert2 = s:taboption("encryption", FileUpload, "ca_cert2", translate("Path to inner CA-Certificate"))
  875. cacert2:depends({mode="sta", auth="EAP-TLS", encryption="wpa"})
  876. cacert2:depends({mode="sta", auth="EAP-TLS", encryption="wpa2"})
  877. cacert2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa"})
  878. cacert2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa2"})
  879. clientcert2 = s:taboption("encryption", FileUpload, "client_cert2", translate("Path to inner Client-Certificate"))
  880. clientcert2:depends({mode="sta", auth="EAP-TLS", encryption="wpa"})
  881. clientcert2:depends({mode="sta", auth="EAP-TLS", encryption="wpa2"})
  882. clientcert2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa"})
  883. clientcert2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa2"})
  884. privkey2 = s:taboption("encryption", FileUpload, "priv_key2", translate("Path to inner Private Key"))
  885. privkey2:depends({mode="sta", auth="EAP-TLS", encryption="wpa"})
  886. privkey2:depends({mode="sta", auth="EAP-TLS", encryption="wpa2"})
  887. privkey2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa"})
  888. privkey2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa2"})
  889. privkeypwd2 = s:taboption("encryption", Value, "priv_key2_pwd", translate("Password of inner Private Key"))
  890. privkeypwd2:depends({mode="sta", auth="EAP-TLS", encryption="wpa"})
  891. privkeypwd2:depends({mode="sta", auth="EAP-TLS", encryption="wpa2"})
  892. privkeypwd2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa"})
  893. privkeypwd2:depends({mode="sta-wds", auth="EAP-TLS", encryption="wpa2"})
  894. privkeypwd2.rmempty = true
  895. privkeypwd2.password = true
  896. identity = s:taboption("encryption", Value, "identity", translate("Identity"))
  897. identity:depends({mode="sta", eap_type="fast", encryption="wpa2"})
  898. identity:depends({mode="sta", eap_type="fast", encryption="wpa"})
  899. identity:depends({mode="sta", eap_type="peap", encryption="wpa2"})
  900. identity:depends({mode="sta", eap_type="peap", encryption="wpa"})
  901. identity:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
  902. identity:depends({mode="sta", eap_type="ttls", encryption="wpa"})
  903. identity:depends({mode="sta-wds", eap_type="fast", encryption="wpa2"})
  904. identity:depends({mode="sta-wds", eap_type="fast", encryption="wpa"})
  905. identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
  906. identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
  907. identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
  908. identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
  909. identity:depends({mode="sta", eap_type="tls", encryption="wpa2"})
  910. identity:depends({mode="sta", eap_type="tls", encryption="wpa"})
  911. identity:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
  912. identity:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
  913. anonymous_identity = s:taboption("encryption", Value, "anonymous_identity", translate("Anonymous Identity"))
  914. anonymous_identity:depends({mode="sta", eap_type="fast", encryption="wpa2"})
  915. anonymous_identity:depends({mode="sta", eap_type="fast", encryption="wpa"})
  916. anonymous_identity:depends({mode="sta", eap_type="peap", encryption="wpa2"})
  917. anonymous_identity:depends({mode="sta", eap_type="peap", encryption="wpa"})
  918. anonymous_identity:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
  919. anonymous_identity:depends({mode="sta", eap_type="ttls", encryption="wpa"})
  920. anonymous_identity:depends({mode="sta-wds", eap_type="fast", encryption="wpa2"})
  921. anonymous_identity:depends({mode="sta-wds", eap_type="fast", encryption="wpa"})
  922. anonymous_identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
  923. anonymous_identity:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
  924. anonymous_identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
  925. anonymous_identity:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
  926. anonymous_identity:depends({mode="sta", eap_type="tls", encryption="wpa2"})
  927. anonymous_identity:depends({mode="sta", eap_type="tls", encryption="wpa"})
  928. anonymous_identity:depends({mode="sta-wds", eap_type="tls", encryption="wpa2"})
  929. anonymous_identity:depends({mode="sta-wds", eap_type="tls", encryption="wpa"})
  930. password = s:taboption("encryption", Value, "password", translate("Password"))
  931. password:depends({mode="sta", eap_type="fast", encryption="wpa2"})
  932. password:depends({mode="sta", eap_type="fast", encryption="wpa"})
  933. password:depends({mode="sta", eap_type="peap", encryption="wpa2"})
  934. password:depends({mode="sta", eap_type="peap", encryption="wpa"})
  935. password:depends({mode="sta", eap_type="ttls", encryption="wpa2"})
  936. password:depends({mode="sta", eap_type="ttls", encryption="wpa"})
  937. password:depends({mode="sta-wds", eap_type="fast", encryption="wpa2"})
  938. password:depends({mode="sta-wds", eap_type="fast", encryption="wpa"})
  939. password:depends({mode="sta-wds", eap_type="peap", encryption="wpa2"})
  940. password:depends({mode="sta-wds", eap_type="peap", encryption="wpa"})
  941. password:depends({mode="sta-wds", eap_type="ttls", encryption="wpa2"})
  942. password:depends({mode="sta-wds", eap_type="ttls", encryption="wpa"})
  943. password.rmempty = true
  944. password.password = true
  945. end
  946. -- ieee802.11w options
  947. if hwtype == "mac80211" then
  948. local has_80211w = (os.execute("hostapd -v11w 2>/dev/null || hostapd -veap 2>/dev/null") == 0)
  949. if has_80211w then
  950. ieee80211w = s:taboption("encryption", ListValue, "ieee80211w",
  951. translate("802.11w Management Frame Protection"),
  952. translate("Requires the 'full' version of wpad/hostapd " ..
  953. "and support from the wifi driver <br />(as of Feb 2017: " ..
  954. "ath9k and ath10k, in LEDE also mwlwifi and mt76)"))
  955. ieee80211w.default = ""
  956. ieee80211w.rmempty = true
  957. ieee80211w:value("", translate("Disabled (default)"))
  958. ieee80211w:value("1", translate("Optional"))
  959. ieee80211w:value("2", translate("Required"))
  960. ieee80211w:depends({mode="ap", encryption="wpa2"})
  961. ieee80211w:depends({mode="ap-wds", encryption="wpa2"})
  962. ieee80211w:depends({mode="ap", encryption="psk2"})
  963. ieee80211w:depends({mode="ap", encryption="psk-mixed"})
  964. ieee80211w:depends({mode="ap-wds", encryption="psk2"})
  965. ieee80211w:depends({mode="ap-wds", encryption="psk-mixed"})
  966. max_timeout = s:taboption("encryption", Value, "ieee80211w_max_timeout",
  967. translate("802.11w maximum timeout"),
  968. translate("802.11w Association SA Query maximum timeout"))
  969. max_timeout:depends({ieee80211w="1"})
  970. max_timeout:depends({ieee80211w="2"})
  971. max_timeout.datatype = "uinteger"
  972. max_timeout.placeholder = "1000"
  973. max_timeout.rmempty = true
  974. retry_timeout = s:taboption("encryption", Value, "ieee80211w_retry_timeout",
  975. translate("802.11w retry timeout"),
  976. translate("802.11w Association SA Query retry timeout"))
  977. retry_timeout:depends({ieee80211w="1"})
  978. retry_timeout:depends({ieee80211w="2"})
  979. retry_timeout.datatype = "uinteger"
  980. retry_timeout.placeholder = "201"
  981. retry_timeout.rmempty = true
  982. end
  983. end
  984. if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
  985. local wpasupplicant = fs.access("/usr/sbin/wpa_supplicant")
  986. local hostcli = fs.access("/usr/sbin/hostapd_cli")
  987. if hostcli and wpasupplicant then
  988. wps = s:taboption("encryption", Flag, "wps_pushbutton", translate("Enable WPS pushbutton, requires WPA(2)-PSK"))
  989. wps.enabled = "1"
  990. wps.disabled = "0"
  991. wps.rmempty = false
  992. wps:depends("encryption", "psk")
  993. wps:depends("encryption", "psk2")
  994. wps:depends("encryption", "psk-mixed")
  995. end
  996. end
  997. return m