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", "",
24 translate("The <em>Device Configuration</em> section covers physical settings of the radio " ..
25 "hardware such as channel, transmit power or antenna selection which is shared among all " ..
26 "defined wireless networks (if the radio hardware is multi-SSID capable). Per network settings " ..
27 "like encryption or operation mode are grouped in the <em>Interface Configuration</em>."))
33 function m.on_commit(map)
37 local wnet = ww:get_network(arg[2])
38 if ifsection and wnet then
39 ifsection.section = wnet.sid
46 local wnet = ww:get_network(arg[2])
48 -- redirect to overview page if network does not exist anymore (e.g. after a revert)
50 luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless"))
54 m.title = ww:get_i18n(wnet)
60 m.uci:foreach("wireless", "wifi-iface",
62 if s.device == arg[1] and not iw then
63 iw = luci.sys.wifi.getiwinfo(s.ifname or s.device)
64 tx_powers = iw.txpwrlist or { }
68 s = m:section(NamedSection, arg[1], "wifi-device", translate("Device Configuration"))
71 s:tab("general", translate("General Setup"))
72 s:tab("macfilter", translate("MAC-Filter"))
73 s:tab("advanced", translate("Advanced Settings"))
76 back = s:option(DummyValue, "_overview", translate("Overview"))
78 back.titleref = luci.dispatcher.build_url("admin", "network", "wireless")
81 en = s:taboption("general", Flag, "disabled", translate("enable"))
86 function en.cfgvalue(self, section)
87 return Flag.cfgvalue(self, section) or "0"
90 s:taboption("general", DummyValue, "type", translate("Type"))
92 local hwtype = m:get(arg[1], "type")
94 local nsantenna = m:get(arg[1], "antenna")
96 ch = s:taboption("general", Value, "channel", translate("Channel"))
97 ch:value("auto", translate("auto"))
98 for _, f in ipairs(luci.sys.wifi.channels()) do
99 ch:value(f.channel, "%i (%.3f GHz)" %{ f.channel, f.mhz / 1000 })
103 ------------------- MAC80211 Device ------------------
105 if hwtype == "mac80211" then
106 tp = s:taboption("general",
107 (tx_powers and #tx_powers > 0) and ListValue or Value,
108 "txpower", translate("Transmit Power"), "dBm")
111 for _, p in ipairs(iw and iw.txpwrlist or {}) do
112 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
117 ------------------- Madwifi Device ------------------
119 if hwtype == "atheros" then
120 tp = s:taboption("general",
121 (#tx_powers > 0) and ListValue or Value,
122 "txpower", translate("Transmit Power"), "dBm")
125 for _, p in ipairs(iw.txpwrlist) do
126 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
129 mode = s:taboption("advanced", ListValue, "hwmode", translate("Mode"))
130 mode:value("", translate("auto"))
131 mode:value("11b", "802.11b")
132 mode:value("11g", "802.11g")
133 mode:value("11a", "802.11a")
134 mode:value("11bg", "802.11b+g")
135 mode:value("11gst", "802.11g + Turbo")
136 mode:value("11ast", "802.11a + Turbo")
137 mode:value("fh", translate("Frequency Hopping"))
139 s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
141 if not nsantenna then
142 ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
143 ant1.widget = "radio"
144 ant1.orientation = "horizontal"
145 ant1:depends("diversity", "")
146 ant1:value("0", translate("auto"))
147 ant1:value("1", translate("Antenna 1"))
148 ant1:value("2", translate("Antenna 2"))
150 ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
151 ant2.widget = "radio"
152 ant2.orientation = "horizontal"
153 ant2:depends("diversity", "")
154 ant2:value("0", translate("auto"))
155 ant2:value("1", translate("Antenna 1"))
156 ant2:value("2", translate("Antenna 2"))
159 local ant = s:taboption("advanced", ListValue, "antenna", translate("Transmitter Antenna"))
161 ant:value("vertical")
162 ant:value("horizontal")
163 ant:value("external")
166 s:taboption("advanced", Value, "distance", translate("Distance Optimization"),
167 translate("Distance to farthest network member in meters."))
168 s:taboption("advanced", Value, "regdomain", translate("Regulatory Domain"))
169 s:taboption("advanced", Value, "country", translate("Country Code"))
170 s:taboption("advanced", Flag, "outdoor", translate("Outdoor Channels"))
172 --s:option(Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
177 ------------------- Broadcom Device ------------------
179 if hwtype == "broadcom" then
180 tp = s:taboption("general",
181 (#tx_powers > 0) and ListValue or Value,
182 "txpower", translate("Transmit Power"), "dBm")
185 for _, p in ipairs(iw.txpwrlist) do
186 tp:value(p.dbm, "%i dBm (%i mW)" %{ p.dbm, p.mw })
189 mp = s:taboption("macfilter", ListValue, "macfilter", translate("MAC-Address Filter"))
190 mp:value("", translate("disable"))
191 mp:value("allow", translate("Allow listed only"))
192 mp:value("deny", translate("Allow all except listed"))
193 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
194 ml:depends({macfilter="allow"})
195 ml:depends({macfilter="deny"})
197 ant1 = s:taboption("advanced", ListValue, "txantenna", translate("Transmitter Antenna"))
198 ant1.widget = "radio"
199 ant1:depends("diversity", "")
200 ant1:value("3", translate("auto"))
201 ant1:value("0", translate("Antenna 1"))
202 ant1:value("1", translate("Antenna 2"))
204 ant2 = s:taboption("advanced", ListValue, "rxantenna", translate("Receiver Antenna"))
205 ant2.widget = "radio"
206 ant2:depends("diversity", "")
207 ant2:value("3", translate("auto"))
208 ant2:value("0", translate("Antenna 1"))
209 ant2:value("1", translate("Antenna 2"))
211 s:taboption("advanced", Flag, "frameburst", translate("Frame Bursting"))
213 s:taboption("advanced", Value, "distance", translate("Distance Optimization"))
214 --s:option(Value, "slottime", translate("Slot time"))
216 s:taboption("advanced", Value, "country", translate("Country Code"))
217 s:taboption("advanced", Value, "maxassoc", translate("Connection Limit"))
221 --------------------- HostAP Device ---------------------
223 if hwtype == "prism2" then
224 s:taboption("advanced", Value, "txpower", translate("Transmit Power"), "att units").rmempty = true
226 s:taboption("advanced", Flag, "diversity", translate("Diversity")).rmempty = false
228 s:taboption("advanced", Value, "txantenna", translate("Transmitter Antenna"))
229 s:taboption("advanced", Value, "rxantenna", translate("Receiver Antenna"))
233 ----------------------- Interface -----------------------
235 local wnet = ww:get_network(arg[2])
238 s = m:section(NamedSection, wnet.sid, "wifi-iface", translate("Interface Configuration"))
242 s.defaults.device = arg[1]
244 s:tab("general", translate("General Setup"))
245 s:tab("encryption", translate("Wireless Security"))
246 s:tab("macfilter", translate("MAC-Filter"))
247 s:tab("advanced", translate("Advanced Settings"))
249 s:taboption("general", Value, "ssid", translate("<abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
251 mode = s:taboption("general", ListValue, "mode", translate("Mode"))
252 mode.override_values = true
253 mode:value("ap", translate("Access Point"))
254 mode:value("sta", translate("Client"))
255 mode:value("adhoc", translate("Ad-Hoc"))
257 bssid = s:taboption("general", Value, "bssid", translate("<abbr title=\"Basic Service Set Identifier\">BSSID</abbr>"))
259 network = s:taboption("general", Value, "network", translate("Network"),
260 translate("Choose the network you want to attach to this wireless interface. " ..
261 "Select <em>unspecified</em> to not attach any network or fill out the " ..
262 "<em>create</em> field to define a new network."))
264 network.rmempty = true
265 network.template = "cbi/network_netlist"
266 network.widget = "radio"
268 function network.write(self, section, value)
269 local i = nw:get_interface(section)
272 value = m:formvalue(self:cbid(section) .. ".newnet")
273 if value and #value > 0 then
274 local n = nw:add_network(value, {type="bridge", proto="none"})
275 if n then n:add_interface(i) end
277 local n = i:get_network()
278 if n then n:del_interface(i) end
281 local n = nw:get_network(value)
290 -------------------- MAC80211 Interface ----------------------
292 if hwtype == "mac80211" then
293 if fs.access("/usr/sbin/iw") then
294 mode:value("mesh", "802.11s")
297 mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
298 mode:value("monitor", translate("Monitor"))
299 bssid:depends({mode="adhoc"})
301 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
302 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
307 -------------------- Madwifi Interface ----------------------
309 if hwtype == "atheros" then
310 mode:value("ahdemo", translate("Pseudo Ad-Hoc (ahdemo)"))
311 mode:value("monitor", translate("Monitor"))
312 mode:value("ap-wds", "%s (%s)" % {translate("Access Point"), translate("WDS")})
313 mode:value("sta-wds", "%s (%s)" % {translate("Client"), translate("WDS")})
314 mode:value("wds", translate("Static WDS"))
316 function mode.write(self, section, value)
317 if value == "ap-wds" then
318 ListValue.write(self, section, "ap")
319 m.uci:set("wireless", section, "wds", 1)
320 elseif value == "sta-wds" then
321 ListValue.write(self, section, "sta")
322 m.uci:set("wireless", section, "wds", 1)
324 ListValue.write(self, section, value)
325 m.uci:delete("wireless", section, "wds")
329 function mode.cfgvalue(self, section)
330 local mode = ListValue.cfgvalue(self, section)
331 local wds = m.uci:get("wireless", section, "wds") == "1"
333 if mode == "ap" and wds then
335 elseif mode == "sta" and wds then
342 bssid:depends({mode="adhoc"})
343 bssid:depends({mode="ahdemo"})
344 bssid:depends({mode="wds"})
346 wdssep = s:taboption("advanced", Flag, "wdssep", translate("Separate WDS"))
347 wdssep:depends({mode="ap-wds"})
349 s:taboption("advanced", Flag, "doth", "802.11h")
350 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
351 hidden:depends({mode="ap"})
352 hidden:depends({mode="adhoc"})
353 hidden:depends({mode="ap-wds"})
354 hidden:depends({mode="sta-wds"})
355 isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
356 translate("Prevents client-to-client communication"))
357 isolate:depends({mode="ap"})
358 s:taboption("advanced", Flag, "bgscan", translate("Background Scan"))
360 mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
361 mp:value("", translate("disable"))
362 mp:value("deny", translate("Allow listed only"))
363 mp:value("allow", translate("Allow all except listed"))
364 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
365 ml:depends({macpolicy="allow"})
366 ml:depends({macpolicy="deny"})
368 s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
369 s:taboption("advanced", Value, "mcast_rate", translate("Multicast Rate"))
370 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
371 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
372 s:taboption("advanced", Value, "minrate", translate("Minimum Rate"))
373 s:taboption("advanced", Value, "maxrate", translate("Maximum Rate"))
374 s:taboption("advanced", Flag, "compression", translate("Compression"))
376 s:taboption("advanced", Flag, "bursting", translate("Frame Bursting"))
377 s:taboption("advanced", Flag, "turbo", translate("Turbo Mode"))
378 s:taboption("advanced", Flag, "ff", translate("Fast Frames"))
380 s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
381 s:taboption("advanced", Flag, "xr", translate("XR Support"))
382 s:taboption("advanced", Flag, "ar", translate("AR Support"))
384 local swm = s:taboption("advanced", Flag, "sw_merge", translate("Disable HW-Beacon timer"))
385 swm:depends({mode="adhoc"})
387 local nos = s:taboption("advanced", Flag, "nosbeacon", translate("Disable HW-Beacon timer"))
388 nos:depends({mode="sta"})
389 nos:depends({mode="sta-wds"})
391 local probereq = s:taboption("advanced", Flag, "probereq", translate("Do not send probe responses"))
392 probereq.enabled = "0"
393 probereq.disabled = "1"
397 -------------------- Broadcom Interface ----------------------
399 if hwtype == "broadcom" then
400 mode:value("wds", translate("WDS"))
401 mode:value("monitor", translate("Monitor"))
403 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
404 hidden:depends({mode="ap"})
405 hidden:depends({mode="adhoc"})
406 hidden:depends({mode="wds"})
408 isolate = s:taboption("advanced", Flag, "isolate", translate("Separate Clients"),
409 translate("Prevents client-to-client communication"))
410 isolate:depends({mode="ap"})
412 s:taboption("advanced", Flag, "doth", "802.11h")
413 s:taboption("advanced", Flag, "wmm", translate("WMM Mode"))
415 bssid:depends({mode="wds"})
416 bssid:depends({mode="adhoc"})
420 ----------------------- HostAP Interface ---------------------
422 if hwtype == "prism2" then
423 mode:value("wds", translate("WDS"))
424 mode:value("monitor", translate("Monitor"))
426 hidden = s:taboption("general", Flag, "hidden", translate("Hide <abbr title=\"Extended Service Set Identifier\">ESSID</abbr>"))
427 hidden:depends({mode="ap"})
428 hidden:depends({mode="adhoc"})
429 hidden:depends({mode="wds"})
431 bssid:depends({mode="sta"})
433 mp = s:taboption("macfilter", ListValue, "macpolicy", translate("MAC-Address Filter"))
434 mp:value("", translate("disable"))
435 mp:value("deny", translate("Allow listed only"))
436 mp:value("allow", translate("Allow all except listed"))
437 ml = s:taboption("macfilter", DynamicList, "maclist", translate("MAC-List"))
438 ml:depends({macpolicy="allow"})
439 ml:depends({macpolicy="deny"})
441 s:taboption("advanced", Value, "rate", translate("Transmission Rate"))
442 s:taboption("advanced", Value, "frag", translate("Fragmentation Threshold"))
443 s:taboption("advanced", Value, "rts", translate("RTS/CTS Threshold"))
447 ------------------- WiFI-Encryption -------------------
449 encr = s:taboption("encryption", ListValue, "encryption", translate("Encryption"))
450 encr.override_values = true
451 encr.override_depends = true
452 encr:depends({mode="ap"})
453 encr:depends({mode="sta"})
454 encr:depends({mode="adhoc"})
455 encr:depends({mode="ahdemo"})
456 encr:depends({mode="ap-wds"})
457 encr:depends({mode="sta-wds"})
458 encr:depends({mode="mesh"})
460 encr:value("none", "No Encryption")
461 encr:value("wep", "WEP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
463 if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
464 local supplicant = fs.access("/usr/sbin/wpa_supplicant")
465 local hostapd = fs.access("/usr/sbin/hostapd")
467 if hostapd and supplicant then
468 encr:value("psk", "WPA-PSK")
469 encr:value("psk2", "WPA2-PSK")
470 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode")
471 encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="sta"}, {mode="ap-wds"}, {mode="sta-wds"})
472 encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="sta"})
473 elseif hostapd and not supplicant then
474 encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
475 encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
476 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="ap-wds"}, {mode="adhoc"}, {mode="ahdemo"})
477 encr:value("wpa", "WPA-EAP", {mode="ap"}, {mode="ap-wds"})
478 encr:value("wpa2", "WPA2-EAP", {mode="ap"}, {mode="ap-wds"})
479 encr.description = translate(
480 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
481 "and ad-hoc mode) to be installed."
483 elseif not hostapd and supplicant then
484 encr:value("psk", "WPA-PSK", {mode="sta"}, {mode="sta-wds"})
485 encr:value("psk2", "WPA2-PSK", {mode="sta"}, {mode="sta-wds"})
486 encr:value("psk-mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="sta"}, {mode="sta-wds"})
487 encr:value("wpa", "WPA-EAP", {mode="sta"}, {mode="sta-wds"})
488 encr:value("wpa2", "WPA2-EAP", {mode="sta"}, {mode="sta-wds"})
489 encr.description = translate(
490 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
491 "and ad-hoc mode) to be installed."
494 encr.description = translate(
495 "WPA-Encryption requires wpa_supplicant (for client mode) or hostapd (for AP " ..
496 "and ad-hoc mode) to be installed."
499 elseif hwtype == "broadcom" then
500 encr:value("psk", "WPA-PSK")
501 encr:value("psk2", "WPA2-PSK")
502 encr:value("psk+psk2", "WPA-PSK/WPA2-PSK Mixed Mode")
505 encr:depends("mode", "ap")
506 encr:depends("mode", "sta")
507 encr:depends("mode", "ap-wds")
508 encr:depends("mode", "sta-wds")
509 encr:depends("mode", "wds")
511 server = s:taboption("encryption", Value, "server", translate("Radius-Server"))
512 server:depends({mode="ap", encryption="wpa"})
513 server:depends({mode="ap", encryption="wpa2"})
514 server:depends({mode="ap-wds", encryption="wpa"})
515 server:depends({mode="ap-wds", encryption="wpa2"})
516 server.rmempty = true
518 port = s:taboption("encryption", Value, "port", translate("Radius-Port"))
519 port:depends({mode="ap", encryption="wpa"})
520 port:depends({mode="ap", encryption="wpa2"})
521 port:depends({mode="ap-wds", encryption="wpa"})
522 port:depends({mode="ap-wds", encryption="wpa2"})
525 key = s:taboption("encryption", Value, "key", translate("Key"))
526 key:depends("encryption", "wep")
527 key:depends("encryption", "psk")
528 key:depends("encryption", "psk2")
529 key:depends("encryption", "psk+psk2")
530 key:depends("encryption", "psk-mixed")
531 key:depends({mode="ap", encryption="wpa"})
532 key:depends({mode="ap", encryption="wpa2"})
533 key:depends({mode="ap-wds", encryption="wpa"})
534 key:depends({mode="ap-wds", encryption="wpa2"})
538 if hwtype == "atheros" or hwtype == "mac80211" or hwtype == "prism2" then
539 nasid = s:taboption("encryption", Value, "nasid", translate("NAS ID"))
540 nasid:depends({mode="ap", encryption="wpa"})
541 nasid:depends({mode="ap", encryption="wpa2"})
542 nasid:depends({mode="ap-wds", encryption="wpa"})
543 nasid:depends({mode="ap-wds", encryption="wpa2"})
546 eaptype = s:taboption("encryption", ListValue, "eap_type", translate("EAP-Method"))
548 eaptype:value("TTLS")
549 eaptype:value("PEAP")
550 eaptype:depends({mode="sta", encryption="wpa"})
551 eaptype:depends({mode="sta", encryption="wpa2"})
553 cacert = s:taboption("encryption", FileUpload, "ca_cert", translate("Path to CA-Certificate"))
554 cacert:depends({mode="sta", encryption="wpa"})
555 cacert:depends({mode="sta", encryption="wpa2"})
557 privkey = s:taboption("encryption", FileUpload, "priv_key", translate("Path to Private Key"))
558 privkey:depends({mode="sta", eap_type="TLS", encryption="wpa2"})
559 privkey:depends({mode="sta", eap_type="TLS", encryption="wpa"})
561 privkeypwd = s:taboption("encryption", Value, "priv_key_pwd", translate("Password of Private Key"))
562 privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa2"})
563 privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa"})
566 auth = s:taboption("encryption", Value, "auth", translate("Authentication"))
570 auth:value("MSCHAPV2")
571 auth:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
572 auth:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
573 auth:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
574 auth:depends({mode="sta", eap_type="TTLS", encryption="wpa"})
577 identity = s:taboption("encryption", Value, "identity", translate("Identity"))
578 identity:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
579 identity:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
580 identity:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
581 identity:depends({mode="sta", eap_type="TTLS", encryption="wpa"})
583 password = s:taboption("encryption", Value, "password", translate("Password"))
584 password:depends({mode="sta", eap_type="PEAP", encryption="wpa2"})
585 password:depends({mode="sta", eap_type="PEAP", encryption="wpa"})
586 password:depends({mode="sta", eap_type="TTLS", encryption="wpa2"})
587 password:depends({mode="sta", eap_type="TTLS", encryption="wpa"})