| 1 | --[[ |
|---|
| 2 | LuCI - Lua Configuration Interface |
|---|
| 3 | |
|---|
| 4 | Copyright 2008 Steven Barth <steven@midlink.org> |
|---|
| 5 | Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net> |
|---|
| 6 | |
|---|
| 7 | Licensed under the Apache License, Version 2.0 (the "License"); |
|---|
| 8 | you may not use this file except in compliance with the License. |
|---|
| 9 | You may obtain a copy of the License at |
|---|
| 10 | |
|---|
| 11 | http://www.apache.org/licenses/LICENSE-2.0 |
|---|
| 12 | |
|---|
| 13 | $Id$ |
|---|
| 14 | ]]-- |
|---|
| 15 | |
|---|
| 16 | -- Data init -- |
|---|
| 17 | |
|---|
| 18 | local uci = luci.model.uci.cursor() |
|---|
| 19 | if not uci:get("network", "wan") then |
|---|
| 20 | uci:section("network", "interface", "wan", {proto="none", ifname=" "}) |
|---|
| 21 | uci:save("network") |
|---|
| 22 | uci:commit("network") |
|---|
| 23 | end |
|---|
| 24 | |
|---|
| 25 | local wlcursor = luci.model.uci.cursor_state() |
|---|
| 26 | local wireless = wlcursor:get_all("wireless") |
|---|
| 27 | local wifidata = luci.sys.wifi.getiwconfig() |
|---|
| 28 | local wifidevs = {} |
|---|
| 29 | local ifaces = {} |
|---|
| 30 | |
|---|
| 31 | for k, v in pairs(wireless) do |
|---|
| 32 | if v[".type"] == "wifi-iface" then |
|---|
| 33 | table.insert(ifaces, v) |
|---|
| 34 | end |
|---|
| 35 | end |
|---|
| 36 | |
|---|
| 37 | wlcursor:foreach("wireless", "wifi-device", |
|---|
| 38 | function(section) |
|---|
| 39 | table.insert(wifidevs, section[".name"]) |
|---|
| 40 | end) |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | -- Main Map -- |
|---|
| 44 | |
|---|
| 45 | m = Map("wireless", translate("wifi"), translate("a_w_devices1")) |
|---|
| 46 | m:chain("network") |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | -- Status Table -- |
|---|
| 50 | s = m:section(Table, ifaces, translate("networks")) |
|---|
| 51 | |
|---|
| 52 | link = s:option(DummyValue, "_link", translate("link")) |
|---|
| 53 | function link.cfgvalue(self, section) |
|---|
| 54 | local ifname = self.map:get(section, "ifname") |
|---|
| 55 | return wifidata[ifname] and wifidata[ifname]["Link Quality"] or "-" |
|---|
| 56 | end |
|---|
| 57 | |
|---|
| 58 | essid = s:option(DummyValue, "ssid", "ESSID") |
|---|
| 59 | |
|---|
| 60 | bssid = s:option(DummyValue, "_bsiid", "BSSID") |
|---|
| 61 | function bssid.cfgvalue(self, section) |
|---|
| 62 | local ifname = self.map:get(section, "ifname") |
|---|
| 63 | return (wifidata[ifname] and (wifidata[ifname].Cell |
|---|
| 64 | or wifidata[ifname]["Access Point"])) or "-" |
|---|
| 65 | end |
|---|
| 66 | |
|---|
| 67 | channel = s:option(DummyValue, "channel", translate("channel")) |
|---|
| 68 | function channel.cfgvalue(self, section) |
|---|
| 69 | return wireless[self.map:get(section, "device")].channel |
|---|
| 70 | end |
|---|
| 71 | |
|---|
| 72 | protocol = s:option(DummyValue, "_mode", translate("protocol")) |
|---|
| 73 | function protocol.cfgvalue(self, section) |
|---|
| 74 | local mode = wireless[self.map:get(section, "device")].mode |
|---|
| 75 | return mode and "802." .. mode |
|---|
| 76 | end |
|---|
| 77 | |
|---|
| 78 | mode = s:option(DummyValue, "mode", translate("mode")) |
|---|
| 79 | encryption = s:option(DummyValue, "encryption", translate("iwscan_encr")) |
|---|
| 80 | |
|---|
| 81 | power = s:option(DummyValue, "_power", translate("power")) |
|---|
| 82 | function power.cfgvalue(self, section) |
|---|
| 83 | local ifname = self.map:get(section, "ifname") |
|---|
| 84 | return wifidata[ifname] and wifidata[ifname]["Tx-Power"] or "-" |
|---|
| 85 | end |
|---|
| 86 | |
|---|
| 87 | scan = s:option(Button, "_scan", translate("scan")) |
|---|
| 88 | scan.inputstyle = "find" |
|---|
| 89 | |
|---|
| 90 | function scan.cfgvalue(self, section) |
|---|
| 91 | return self.map:get(section, "ifname") or false |
|---|
| 92 | end |
|---|
| 93 | |
|---|
| 94 | -- WLAN-Scan-Table -- |
|---|
| 95 | |
|---|
| 96 | t2 = m:section(Table, {}, translate("iwscan"), translate("iwscan1")) |
|---|
| 97 | |
|---|
| 98 | function scan.write(self, section) |
|---|
| 99 | m.autoapply = false |
|---|
| 100 | t2.render = t2._render |
|---|
| 101 | local ifname = self.map:get(section, "ifname") |
|---|
| 102 | luci.util.update(t2.data, luci.sys.wifi.iwscan(ifname)) |
|---|
| 103 | end |
|---|
| 104 | |
|---|
| 105 | t2._render = t2.render |
|---|
| 106 | t2.render = function() end |
|---|
| 107 | |
|---|
| 108 | t2:option(DummyValue, "Quality", translate("iwscan_link")) |
|---|
| 109 | essid = t2:option(DummyValue, "ESSID", "ESSID") |
|---|
| 110 | function essid.cfgvalue(self, section) |
|---|
| 111 | return self.map:get(section, "ESSID") |
|---|
| 112 | end |
|---|
| 113 | |
|---|
| 114 | t2:option(DummyValue, "Address", "BSSID") |
|---|
| 115 | t2:option(DummyValue, "Mode", translate("mode")) |
|---|
| 116 | chan = t2:option(DummyValue, "channel", translate("channel")) |
|---|
| 117 | function chan.cfgvalue(self, section) |
|---|
| 118 | return self.map:get(section, "Channel") |
|---|
| 119 | or self.map:get(section, "Frequency") |
|---|
| 120 | or "-" |
|---|
| 121 | end |
|---|
| 122 | |
|---|
| 123 | t2:option(DummyValue, "Encryption key", translate("iwscan_encr")) |
|---|
| 124 | |
|---|
| 125 | t2:option(DummyValue, "Signal level", translate("iwscan_signal")) |
|---|
| 126 | |
|---|
| 127 | t2:option(DummyValue, "Noise level", translate("iwscan_noise")) |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | |
|---|
| 131 | if #wifidevs < 1 then |
|---|
| 132 | return m |
|---|
| 133 | end |
|---|
| 134 | |
|---|
| 135 | -- Config Section -- |
|---|
| 136 | |
|---|
| 137 | s = m:section(NamedSection, wifidevs[1], "wifi-device", translate("devices")) |
|---|
| 138 | s.addremove = false |
|---|
| 139 | |
|---|
| 140 | en = s:option(Flag, "disabled", translate("enable")) |
|---|
| 141 | en.rmempty = false |
|---|
| 142 | en.enabled = "0" |
|---|
| 143 | en.disabled = "1" |
|---|
| 144 | |
|---|
| 145 | function en.cfgvalue(self, section) |
|---|
| 146 | return Flag.cfgvalue(self, section) or "0" |
|---|
| 147 | end |
|---|
| 148 | |
|---|
| 149 | |
|---|
| 150 | local hwtype = m:get(wifidevs[1], "type") |
|---|
| 151 | |
|---|
| 152 | if hwtype == "atheros" then |
|---|
| 153 | mode = s:option(ListValue, "mode", translate("mode")) |
|---|
| 154 | mode.override_values = true |
|---|
| 155 | mode:value("", "auto") |
|---|
| 156 | mode:value("11b", "802.11b") |
|---|
| 157 | mode:value("11g", "802.11g") |
|---|
| 158 | mode:value("11a", "802.11a") |
|---|
| 159 | mode:value("11bg", "802.11b+g") |
|---|
| 160 | mode.rmempty = true |
|---|
| 161 | end |
|---|
| 162 | |
|---|
| 163 | |
|---|
| 164 | ch = s:option(Value, "channel", translate("a_w_channel")) |
|---|
| 165 | for i=1, 14 do |
|---|
| 166 | ch:value(i, i .. " (2.4 GHz)") |
|---|
| 167 | end |
|---|
| 168 | |
|---|
| 169 | |
|---|
| 170 | s = m:section(TypedSection, "wifi-iface", translate("m_n_local")) |
|---|
| 171 | s.anonymous = true |
|---|
| 172 | s.addremove = false |
|---|
| 173 | |
|---|
| 174 | s:option(Value, "ssid", translate("a_w_netid")) |
|---|
| 175 | |
|---|
| 176 | bssid = s:option(Value, "bssid", translate("wifi_bssid")) |
|---|
| 177 | |
|---|
| 178 | local devs = {} |
|---|
| 179 | luci.model.uci.cursor():foreach("wireless", "wifi-device", |
|---|
| 180 | function (section) |
|---|
| 181 | table.insert(devs, section[".name"]) |
|---|
| 182 | end) |
|---|
| 183 | |
|---|
| 184 | if #devs > 1 then |
|---|
| 185 | device = s:option(DummyValue, "device", translate("device")) |
|---|
| 186 | else |
|---|
| 187 | s.defaults.device = devs[1] |
|---|
| 188 | end |
|---|
| 189 | |
|---|
| 190 | mode = s:option(ListValue, "mode", translate("mode")) |
|---|
| 191 | mode.override_values = true |
|---|
| 192 | mode:value("ap", translate("m_w_ap")) |
|---|
| 193 | mode:value("adhoc", translate("m_w_adhoc")) |
|---|
| 194 | mode:value("sta", translate("m_w_client")) |
|---|
| 195 | |
|---|
| 196 | function mode.write(self, section, value) |
|---|
| 197 | if value == "sta" then |
|---|
| 198 | local oldif = m.uci:get("network", "wan", "ifname") |
|---|
| 199 | if oldif and oldif ~= " " then |
|---|
| 200 | m.uci:set("network", "wan", "_ifname", oldif) |
|---|
| 201 | end |
|---|
| 202 | m.uci:set("network", "wan", "ifname", " ") |
|---|
| 203 | |
|---|
| 204 | self.map:set(section, "network", "wan") |
|---|
| 205 | else |
|---|
| 206 | if m.uci:get("network", "wan", "_ifname") then |
|---|
| 207 | m.uci:set("network", "wan", "ifname", m.uci:get("network", "wan", "_ifname")) |
|---|
| 208 | end |
|---|
| 209 | self.map:set(section, "network", "lan") |
|---|
| 210 | end |
|---|
| 211 | |
|---|
| 212 | return ListValue.write(self, section, value) |
|---|
| 213 | end |
|---|
| 214 | |
|---|
| 215 | encr = s:option(ListValue, "encryption", translate("encryption")) |
|---|
| 216 | encr.override_values = true |
|---|
| 217 | encr:value("none", "No Encryption") |
|---|
| 218 | encr:value("wep", "WEP") |
|---|
| 219 | |
|---|
| 220 | if hwtype == "atheros" or hwtype == "mac80211" then |
|---|
| 221 | local supplicant = luci.fs.mtime("/usr/sbin/wpa_supplicant") |
|---|
| 222 | local hostapd = luci.fs.mtime("/usr/sbin/hostapd") |
|---|
| 223 | |
|---|
| 224 | if hostapd and supplicant then |
|---|
| 225 | encr:value("psk", "WPA-PSK") |
|---|
| 226 | encr:value("psk2", "WPA2-PSK") |
|---|
| 227 | encr:value("mixed", "WPA-PSK/WPA2-PSK Mixed Mode") |
|---|
| 228 | encr:value("wpa", "WPA-Radius", {mode="ap"}, {mode="sta"}) |
|---|
| 229 | encr:value("wpa2", "WPA2-Radius", {mode="ap"}, {mode="sta"}) |
|---|
| 230 | elseif hostapd and not supplicant then |
|---|
| 231 | encr:value("psk", "WPA-PSK", {mode="ap"}, {mode="adhoc"}) |
|---|
| 232 | encr:value("psk2", "WPA2-PSK", {mode="ap"}, {mode="adhoc"}) |
|---|
| 233 | encr:value("mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="ap"}, {mode="adhoc"}) |
|---|
| 234 | encr:value("wpa", "WPA-Radius", {mode="ap"}) |
|---|
| 235 | encr:value("wpa2", "WPA2-Radius", {mode="ap"}) |
|---|
| 236 | encr.description = translate("wifi_wpareq") |
|---|
| 237 | elseif not hostapd and supplicant then |
|---|
| 238 | encr:value("psk", "WPA-PSK", {mode="sta"}) |
|---|
| 239 | encr:value("psk2", "WPA2-PSK", {mode="sta"}) |
|---|
| 240 | encr:value("mixed", "WPA-PSK/WPA2-PSK Mixed Mode", {mode="sta"}) |
|---|
| 241 | encr:value("wpa", "WPA-EAP", {mode="sta"}) |
|---|
| 242 | encr:value("wpa2", "WPA2-EAP", {mode="sta"}) |
|---|
| 243 | encr.description = translate("wifi_wpareq") |
|---|
| 244 | else |
|---|
| 245 | encr.description = translate("wifi_wpareq") |
|---|
| 246 | end |
|---|
| 247 | elseif hwtype == "broadcom" then |
|---|
| 248 | encr:value("psk", "WPA-PSK") |
|---|
| 249 | encr:value("psk2", "WPA2-PSK") |
|---|
| 250 | encr:value("psk+psk2", "WPA-PSK/WPA2-PSK Mixed Mode") |
|---|
| 251 | end |
|---|
| 252 | |
|---|
| 253 | key = s:option(Value, "key", translate("key")) |
|---|
| 254 | key:depends("encryption", "wep") |
|---|
| 255 | key:depends("encryption", "psk") |
|---|
| 256 | key:depends("encryption", "psk2") |
|---|
| 257 | key:depends("encryption", "psk+psk2") |
|---|
| 258 | key:depends("encryption", "mixed") |
|---|
| 259 | key:depends({mode="ap", encryption="wpa"}) |
|---|
| 260 | key:depends({mode="ap", encryption="wpa2"}) |
|---|
| 261 | key.rmempty = true |
|---|
| 262 | key.password = true |
|---|
| 263 | |
|---|
| 264 | server = s:option(Value, "server", translate("a_w_radiussrv")) |
|---|
| 265 | server:depends({mode="ap", encryption="wpa"}) |
|---|
| 266 | server:depends({mode="ap", encryption="wpa2"}) |
|---|
| 267 | server.rmempty = true |
|---|
| 268 | |
|---|
| 269 | port = s:option(Value, "port", translate("a_w_radiusport")) |
|---|
| 270 | port:depends({mode="ap", encryption="wpa"}) |
|---|
| 271 | port:depends({mode="ap", encryption="wpa2"}) |
|---|
| 272 | port.rmempty = true |
|---|
| 273 | |
|---|
| 274 | |
|---|
| 275 | if hwtype == "atheros" or hwtype == "mac80211" then |
|---|
| 276 | nasid = s:option(Value, "nasid", translate("a_w_nasid")) |
|---|
| 277 | nasid:depends({mode="ap", encryption="wpa"}) |
|---|
| 278 | nasid:depends({mode="ap", encryption="wpa2"}) |
|---|
| 279 | nasid.rmempty = true |
|---|
| 280 | |
|---|
| 281 | eaptype = s:option(ListValue, "eap_type", translate("a_w_eaptype")) |
|---|
| 282 | eaptype:value("TLS") |
|---|
| 283 | eaptype:value("TTLS") |
|---|
| 284 | eaptype:value("PEAP") |
|---|
| 285 | eaptype:depends({mode="sta", encryption="wpa"}) |
|---|
| 286 | eaptype:depends({mode="sta", encryption="wpa2"}) |
|---|
| 287 | |
|---|
| 288 | cacert = s:option(FileUpload, "ca_cert", translate("a_w_cacert")) |
|---|
| 289 | cacert:depends({mode="sta", encryption="wpa"}) |
|---|
| 290 | cacert:depends({mode="sta", encryption="wpa2"}) |
|---|
| 291 | |
|---|
| 292 | privkey = s:option(FileUpload, "priv_key", translate("a_w_tlsprivkey")) |
|---|
| 293 | privkey:depends({mode="sta", eap_type="TLS", encryption="wpa2"}) |
|---|
| 294 | privkey:depends({mode="sta", eap_type="TLS", encryption="wpa"}) |
|---|
| 295 | |
|---|
| 296 | privkeypwd = s:option(Value, "priv_key_pwd", translate("a_w_tlsprivkeypwd")) |
|---|
| 297 | privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa2"}) |
|---|
| 298 | privkeypwd:depends({mode="sta", eap_type="TLS", encryption="wpa"}) |
|---|
| 299 | |
|---|
| 300 | |
|---|
| 301 | auth = s:option(Value, "auth", translate("a_w_peapauth")) |
|---|
| 302 | auth:value("PAP") |
|---|
| 303 | auth:value("CHAP") |
|---|
| 304 | auth:value("MSCHAP") |
|---|
| 305 | auth:value("MSCHAPV2") |
|---|
| 306 | auth:depends({mode="sta", eap_type="PEAP", encryption="wpa2"}) |
|---|
| 307 | auth:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) |
|---|
| 308 | auth:depends({mode="sta", eap_type="TTLS", encryption="wpa2"}) |
|---|
| 309 | auth:depends({mode="sta", eap_type="TTLS", encryption="wpa"}) |
|---|
| 310 | |
|---|
| 311 | |
|---|
| 312 | identity = s:option(Value, "identity", translate("a_w_peapidentity")) |
|---|
| 313 | identity:depends({mode="sta", eap_type="PEAP", encryption="wpa2"}) |
|---|
| 314 | identity:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) |
|---|
| 315 | identity:depends({mode="sta", eap_type="TTLS", encryption="wpa2"}) |
|---|
| 316 | identity:depends({mode="sta", eap_type="TTLS", encryption="wpa"}) |
|---|
| 317 | |
|---|
| 318 | password = s:option(Value, "password", translate("a_w_peappassword")) |
|---|
| 319 | password:depends({mode="sta", eap_type="PEAP", encryption="wpa2"}) |
|---|
| 320 | password:depends({mode="sta", eap_type="PEAP", encryption="wpa"}) |
|---|
| 321 | password:depends({mode="sta", eap_type="TTLS", encryption="wpa2"}) |
|---|
| 322 | password:depends({mode="sta", eap_type="TTLS", encryption="wpa"}) |
|---|
| 323 | end |
|---|
| 324 | |
|---|
| 325 | |
|---|
| 326 | if hwtype == "atheros" or hwtype == "broadcom" then |
|---|
| 327 | iso = s:option(Flag, "isolate", translate("a_w_apisolation"), translate("a_w_apisolation1")) |
|---|
| 328 | iso.rmempty = true |
|---|
| 329 | iso:depends("mode", "ap") |
|---|
| 330 | |
|---|
| 331 | hide = s:option(Flag, "hidden", translate("a_w_hideessid")) |
|---|
| 332 | hide.rmempty = true |
|---|
| 333 | hide:depends("mode", "ap") |
|---|
| 334 | end |
|---|
| 335 | |
|---|
| 336 | if hwtype == "mac80211" or hwtype == "atheros" then |
|---|
| 337 | bssid:depends({mode="adhoc"}) |
|---|
| 338 | end |
|---|
| 339 | |
|---|
| 340 | if hwtype == "broadcom" then |
|---|
| 341 | bssid:depends({mode="wds"}) |
|---|
| 342 | bssid:depends({mode="adhoc"}) |
|---|
| 343 | end |
|---|
| 344 | |
|---|
| 345 | |
|---|
| 346 | return m |
|---|