2 LuCI - Lua Configuration Interface
4 Copyright 2008 Steven Barth <steven@midlink.org>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
15 local wa = require "luci.tools.webadmin"
16 local nw = require "luci.model.network"
17 local ww = require "luci.model.wireless"
18 local fs = require "nixio.fs"
23 m = Map("wireless", translate("Networks"), translate("You can run several wifi networks with one device. Be aware that there are certain hardware and driverspecific restrictions. Normally you can operate 1 Ad-Hoc or up to 3 Master-Mode and 1 Client-Mode network simultaneously."))
28 function m.on_commit(map)
32 local wnet = ww:get_network(arg[2])
33 if ifsection and wnet then
34 ifsection.section = wnet.sid
45 m.uci:foreach("wireless", "wifi-iface",
47 if s.device == arg[1] and not iw then
48 iw = luci.sys.wifi.getiwinfo(s.ifname or s.device)
49 tx_powers = iw.txpwrlist or { }
53 s = m:section(NamedSection, arg[1], "wifi-device", translate("Device") .. " " .. arg[1])
56 s:tab("general", translate("General Setup"))
57 s:tab("macfilter", translate("MAC-Filter"))
58 s:tab("advanced", translate("Advanced Settings"))
61 back = s:option(DummyValue, "_overview", translate("Overview"))
63 back.titleref = luci.dispatcher.build_url("admin", "network", "wireless")
66 en = s:taboption("general", Flag, "disabled", translate("enable"))
71 function en.cfgvalue(self, section)
72 return Flag.cfgvalue(self, section) or "0"
75 s:taboption("general", DummyValue, "type", translate("Type"))
77 local hwtype = m:get(arg[1], "type")
79 local nsantenna = m:get(arg[1], "antenna")
81 ch = s:taboption("general", Value, "channel", translate("Channel"))
82 ch:value("auto", translate("auto"))
83 for c, f in luci.util.kspairs(luci.sys.wifi.channels()) do
84 ch:value(c, "%i (%.3f GHz)" %{ c, f })
88 ------------------- MAC80211 Device ------------------
90 if hwtype == "mac80211" then
91 tp = s:taboption("general",
92 (tx_powers and #tx_powers > 0) and ListValue or Value,
93 "txpower", translate("Transmit Power"), "dBm")
96 for _, p in ipairs(iw and iw.txpwrlist or {}) do
97 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
102 ------------------- Madwifi Device ------------------
104 if hwtype == "atheros" then
105 tp = s:taboption("general",
106 (#tx_powers > 0) and ListValue or Value,
107 "txpower", translate("Transmit Power"), "dBm")
110 for _, p in ipairs(iw.txpwrlist) do
111 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
114 mode = s:taboption("advanced", ListValue, "hwmode", translate("Mode"))
115 mode:value("", translate("auto"))
116 mode:value("11b", "802.11b")
117 mode:value("11g", "802.11g")
118 mode:value("11a", "802.11a")
119 mode:value("11bg", "802.11b+g")
120 mode:value("11gst", "802.11g + Turbo")
121 mode:value("11ast", "802.11a + Turbo")
122 mode:value("fh", translate("Frequency Hopping"))
124 s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
126 if not nsantenna then
127 ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
128 ant1.widget = "radio"
129 ant1.orientation = "horizontal"
130 ant1:depends("diversity", "")
131 ant1:value("0", translate("auto"))
132 ant1:value("1", translate("Antenna 1"))
133 ant1:value("2", translate("Antenna 2"))
135 ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
136 ant2.widget = "radio"
137 ant2.orientation = "horizontal"
138 ant2:depends("diversity", "")
139 ant2:value("0", translate("auto"))
140 ant2:value("1", translate("Antenna 1"))
141 ant2:value("2", translate("Antenna 2"))
144 local ant = s:taboption("advanced", ListValue, "antenna", translate("Transmitter Antenna"))
146 ant:value("vertical")
147 ant:value("horizontal")
148 ant:value("external")
151 s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
152 translate("Distance to farthest network member in meters."))
153 s:taboption("advanced", Value, "regdomain", translate("Regulatory Domain"))
154 s:taboption("advanced", Value, "country", translate("Country Code"))
155 s:taboption("advanced", Flag, "outdoor", translate("Outdoor Channels"))
157 --s:option(Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
162 ------------------- Broadcom Device ------------------
164 if hwtype == "broadcom" then
165 tp = s:taboption("general",
166 (#tx_powers > 0) and ListValue or Value,
167 "txpower", translate("Transmit Power"), "dBm")
170 for _, p in ipairs(iw.txpwrlist) do
171 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
174 mp = s:taboption("macfilter", ListValue, "macfilter", translate("MAC-Address Filter"))
175 mp:value("", translate("disable"))
176 mp:value("allow", translate("Allow listed only"))
177 mp:value("deny", translate("Allow all except listed"))
178 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
179 ml:depends({macfilter="allow"})
180 ml:depends({macfilter="deny"})
182 ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
183 ant1.widget = "radio"
184 ant1:depends("diversity", "")
185 ant1:value("3", translate("auto"))
186 ant1:value("0", translate("Antenna 1"))
187 ant1:value("1", translate("Antenna 2"))
189 ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
190 ant2.widget = "radio"
191 ant2:depends("diversity", "")
192 ant2:value("3", translate("auto"))
193 ant2:value("0", translate("Antenna 1"))
194 ant2:value("1", translate("Antenna 2"))
196 s:taboption("advanced", Flag, "frameburst", translate("Frame Bursting"))
198 s:taboption("advanced", Value, "distance", translate("Distance Optimization"))
199 --s:option(Value, "slottime", translate("Slot time"))
201 s:taboption("advanced", Value, "country", translate("Country Code"))
202 s:taboption("advanced", Value, "maxassoc", translate("Connection Limit"))
206 --------------------- HostAP Device ---------------------
208 if hwtype == "prism2" then
209 s:taboption("advanced", Value, "txpower", translate("Transmit Power"), "att units").rmempty = true
211 s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
213 s:taboption("advanced", Value, "txantenna", translate("Transmitter Antenna"))
214 s:taboption("advanced", Value, "rxantenna", translate("Receiver Antenna"))
218 ----------------------- Interface -----------------------
220 local wnet = ww:get_network(arg[2])
223 s = m:section(NamedSection, wnet.sid, "wifi-iface", ww:get_i18n(wnet))
227 s.defaults.device = arg[1]
229 s:tab("general", translate("General Setup"))
230 s:tab("encryption", translate("Wireless Security"))
231 s:tab("macfilter", translate("MAC-Filter"))
232 s:tab("advanced", translate("Advanced Settings"))
234 s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
236 mode = s:taboption("general", ListValue, "mode", translate("Mode"))
237 mode.override_values = true
238 mode:value("ap", translate("Access Point"))
239 mode:value("sta", translate("Client"))
240 mode:value("adhoc", translate("Ad-Hoc"))
242 bssid = s:taboption("general", Value, "bssid", translate("<abbr title=\"Basic Service Set Identifier\">BSSID</abbr>"))
244 network = s:taboption("general", Value, "network", translate("Network"), translate("Add the Wifi network to physical network"))
245 network.rmempty = true
246 network.template = "cbi/network_netlist"
247 network.widget = "radio"
249 function network.write(self, section, value)
250 local i = nw:get_interface(section)
253 value = m:formvalue(self:cbid(section) .. ".newnet")
254 if value and #value > 0 then
255 local n = nw:add_network(value, {type="bridge", proto="none"})
256 if n then n:add_interface(i) end
258 local n = i:get_network()
259 if n then n:del_interface(i) end
262 local n = nw:get_network(value)
271 -------------------- MAC80211 Interface ----------------------
273 if hwtype == "mac80211" then
274 if fs.access("/usr/sbin/iw") then
275 mode:value("mesh", "802.11s")
278 mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
279 mode:value("monitor", translate("Monitor"))
280 bssid:depends({mode="adhoc"})
282 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
283 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
288 -------------------- Madwifi Interface ----------------------
290 if hwtype == "atheros" then
291 mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
292 mode:value("monitor", translate("Monitor"))
293 mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
294 mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
295 mode:value("wds", translate("Static WDS"))
297 function mode.write(self, section, value)
298 if value == "ap-wds" then
299 ListValue.write(self, section, "ap")
300 m.uci:set("wireless", section, "wds", 1)
301 elseif value == "sta-wds" then
302 ListValue.write(self, section, "sta")
303 m.uci:set("wireless", section, "wds", 1)
305 ListValue.write(self, section, value)
306 m.uci:delete("wireless", section, "wds")
310 function mode.cfgvalue(self, section)
311 local mode = ListValue.cfgvalue(self, section)
312 local wds = m.uci:get("wireless", section, "wds") == "1"
314 if mode == "ap" and wds then
316 elseif mode == "sta" and wds then
323 bssid:depends({mode="adhoc"})
324 bssid:depends({mode="ahdemo"})
325 bssid:depends({mode="wds"})
327 wdssep = s:taboption("advanced", Flag, "wdssep", translate("Separate WDS"))
328 wdssep:depends({mode="ap-wds"})
330 s:taboption("advanced", Flag, "doth", "802.11h")
331 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
332 hidden:depends({mode="ap"})
333 hidden:depends({mode="adhoc"})
334 hidden:depends({mode="ap-wds"})
335 hidden:depends({mode="sta-wds"})
336 isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
337 translate("Prevents client-to-client communication"))
338 isolate:depends({mode="ap"})
339 s:taboption("advanced", Flag, "bgscan", translate("Background Scan"))
341 mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
342 mp:value("", translate("disable"))
343 mp:value("deny", translate("Allow listed only"))
344 mp:value("allow", translate("Allow all except listed"))
345 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
346 ml:depends({macpolicy="allow"})
347 ml:depends({macpolicy="deny"})
349 s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
350 s:taboption("advanced", Value, "mcast_rate", translate("Multicast Rate"))
351 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
352 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
353 s:taboption("advanced", Value, "minrate", translate("Minimum Rate"))
354 s:taboption("advanced", Value, "maxrate", translate("Maximum Rate"))
355 s:taboption("advanced", Flag, "compression", translate("Compression"))
357 s:taboption("advanced", Flag, "bursting", translate("Frame Bursting"))
358 s:taboption("advanced", Flag, "turbo", translate("Turbo Mode"))
359 s:taboption("advanced", Flag, "ff", translate("Fast Frames"))
361 s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
362 s:taboption("advanced", Flag, "xr", translate("XR Support"))
363 s:taboption("advanced", Flag, "ar", translate("AR Support"))
365 local swm = s:taboption("advanced", Flag, "sw_merge", translate("Disable HW-Beacon timer"))
366 swm:depends({mode="adhoc"})
368 local nos = s:taboption("advanced", Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
369 nos:depends({mode="sta"})
370 nos:depends({mode="sta-wds"})
372 local probereq = s:taboption("advanced", Flag, "probereq", translate("Do not send probe responses"))
373 probereq.enabled = "0"
374 probereq.disabled = "1"
378 -------------------- Broadcom Interface ----------------------
380 if hwtype == "broadcom" then
381 mode:value("wds", translate("WDS"))
382 mode:value("monitor", translate("Monitor"))
384 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
385 hidden:depends({mode="ap"})
386 hidden:depends({mode="adhoc"})
387 hidden:depends({mode="wds"})
389 isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
390 translate("Prevents client-to-client communication"))
391 isolate:depends({mode="ap"})
393 s:taboption("advanced", Flag, "doth", "802.11h")
394 s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
396 bssid:depends({mode="wds"})
397 bssid:depends({mode="adhoc"})
401 ----------------------- HostAP Interface ---------------------
403 if hwtype == "prism2" then
404 mode:value("wds", translate("WDS"))
405 mode:value("monitor", translate("Monitor"))
407 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
408 hidden:depends({mode="ap"})
409 hidden:depends({mode="adhoc"})
410 hidden:depends({mode="wds"})
412 bssid:depends({mode="sta"})
414 mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
415 mp:value("", translate("disable"))
416 mp:value("deny", translate("Allow listed only"))
417 mp:value("allow", translate("Allow all except listed"))
418 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
419 ml:depends({macpolicy="allow"})
420 ml:depends({macpolicy="deny"})
422 s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
423 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
424 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
428 ------------------- WiFI-Encryption -------------------
430 encr = s:taboption("encryption", ListValue, "encryption", translate("Encryption"))
431 encr.override_values = true
432 encr.override_depends = true
433 encr:depends({mode="ap"})
434 encr:depends({mode="sta"})
435 encr:depends({mode="adhoc"})
436 encr:depends({mode="ahdemo"})
437 encr:depends({mode="ap-wds"})
438 encr:depends({mode="sta-wds"})
439 encr:depends({mode="mesh"})
441 encr:value("none", "No Encryption")
442 encr:value("wep", "WEP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
444 if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
445 local supplicant = fs.access("/usr/sbin/wpa_supplicant")
446 local hostapd = fs.access("/usr/sbin/hostapd")
448 if hostapd and supplicant then
449 encr:value("psk", "WPA-PSK")
450 encr:value("psk2", "WPA2-PSK")
451 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode")
452 encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
453 encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="sta"})
454 elseif hostapd and not supplicant then
455 encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
456 encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
457 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
458 encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="ap-wds"})
459 encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="ap-wds"})
460 encr.description = translate(
461 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
462 "and ad-hoc mode) to be installed."
464 elseif not hostapd and supplicant then
465 encr:value("psk", "WPA-PSK", {mode="sta"}, {mode="sta-wds"})
466 encr:value("psk2", "WPA2-PSK", {mode="sta"}, {mode="sta-wds"})
467 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="sta"}, {mode="sta-wds"})
468 encr:value("wpa", "WPA-EAP", {mode="sta"}, {mode="sta-wds"})
469 encr:value("wpa2", "WPA2-EAP", {mode="sta"}, {mode="sta-wds"})
470 encr.description = translate(
471 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
472 "and ad-hoc mode) to be installed."
475 encr.description = translate(
476 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
477 "and ad-hoc mode) to be installed."
480 elseif hwtype == "broadcom" then
481 encr:value("psk", "WPA-PSK")
482 encr:value("psk2", "WPA2-PSK")
483 encr:value("psk+psk2", "WPA-PSK/WPA2-PSK Mixed Mode")
486 encr:depends("mode", "ap")
487 encr:depends("mode", "sta")
488 encr:depends("mode", "ap-wds")
489 encr:depends("mode", "sta-wds")
490 encr:depends("mode", "wds")
492 server = s:taboption("encryption", Value, "server", translate("Radius-Server"))
493 server:depends({mode="ap", encryption="wpa"})
494 server:depends({mode="ap", encryption="wpa2"})
495 server.rmempty = true
497 port = s:taboption("encryption", Value, "port", translate("Radius-Port"))
498 port:depends({mode="ap", encryption="wpa"})
499 port:depends({mode="ap", encryption="wpa2"})
502 key = s:taboption("encryption", Value, "key", translate("Key"))
503 key:depends("encryption", "wep")
504 key:depends("encryption", "psk")
505 key:depends("encryption", "psk2")
506 key:depends("encryption", "psk+psk2")
507 key:depends("encryption", "psk-mixed")
508 key:depends({mode="ap", encryption="wpa"})
509 key:depends({mode="ap", encryption="wpa2"})
513 if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
514 nasid = s:taboption("encryption", Value, "nasid", translate("NAS ID"))
515 nasid:depends({mode="ap", encryption="wpa"})
516 nasid:depends({mode="ap", encryption="wpa2"})
519 eaptype = s:taboption("encryption", ListValue, "eap_type", translate("EAP-Method"))
521 eaptype:value("TTLS")
522 eaptype:value("PEAP")
523 eaptype:depends({mode="sta", encryption="wpa"})
524 eaptype:depends({mode="sta", encryption="wpa2"})
526 cacert = s:taboption("encryption", FileUpload, "ca_cert", translate("Path to CA-Certificate"))
527 cacert:depends({mode="sta", encryption="wpa"})
528 cacert:depends({mode="sta", encryption="wpa2"})
530 privkey = s:taboption("encryption", FileUpload, "priv_key", translate("Path to Private Key"))
531 privkey:depends({mode="sta", eap_type="TLS", encryption="wpa2"})
532 privkey:depends({mode="sta", eap_type="TLS", encryption="wpa"})
534 privkeypwd = s:taboption("encryption", Value, "priv_key_pwd", translate("Password of Private Key"))
535 privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa2"})
536 privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa"})
539 auth = s:taboption("encryption", Value, "auth", translate("Authentication"))
543 auth:value("MSCHAPV2")
544 auth:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
545 auth:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
546 auth:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
547 auth:depends({mode="sta", eap_type="TTLS", encryption="wpa"})
550 identity = s:taboption("encryption", Value, "identity", translate("Identity"))
551 identity:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
552 identity:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
553 identity:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
554 identity:depends({mode="sta", eap_type="TTLS", encryption="wpa"})
556 password = s:taboption("encryption", Value, "password", translate("Password"))
557 password:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
558 password:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
559 password:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
560 password:depends({mode="sta", eap_type="TTLS", encryption="wpa"})