applications/ffwizard: Rework wireless interface configuration
[project/luci.git] / applications / luci-ffwizard / luasrc / model / cbi / ffwizard.lua
index d2a051d..d37a55b 100644 (file)
@@ -24,7 +24,6 @@ local sys = require "luci.sys"
 local ip = require "luci.ip"
 local fs  = require "nixio.fs"
 
-
 local has_pptp  = fs.access("/usr/sbin/pptp")
 local has_pppoe = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
 local has_l2gvpn  = fs.access("/usr/sbin/node")
@@ -32,6 +31,8 @@ local has_radvd  = fs.access("/etc/config/radvd")
 local has_rom  = fs.access("/rom/etc")
 local has_autoipv6  = fs.access("/usr/bin/auto-ipv6")
 local has_qos  = fs.access("/etc/init.d/qos")
+local has_ipv6 = fs.access("/proc/sys/net/ipv6")
+local has_hb = fs.access("/sbin/heartbeat")
 
 luci.i18n.loadc("freifunk")
 
@@ -108,6 +109,7 @@ net_lat = f:field(ListValue, "net_lat", "", "")
 net_lat:depends("net", "0")
 net_lon = f:field(ListValue, "net_lon", "", "")
 net_lon:depends("net", "0")
+
 uci:foreach("freifunk", "community", function(s)
        if s.latitude then
                net_lat:value(s[".name"], "%s" % {s.latitude or "?"})
@@ -184,23 +186,22 @@ uci:foreach("wireless", "wifi-device",
                        function chan.cfgvalue(self, section)
                                return uci:get("freifunk", "wizard", "chan_" .. device)
                        end
+
                        chan:value('default')
-                       for i = 1, 14, 1 do
-                               chan:value(i)
-                       end
-                       for i = 36, 64, 4 do
-                               chan:value(i)
-                       end
-                       for i = 100, 140, 4 do
-                               chan:value(i)
+                       for _, f in ipairs(sys.wifi.channels(device)) do
+                               if not f.restricted then
+                                       chan:value(f.channel)
+                               end
                        end
+
                        function chan.write(self, sec, value)
                                if value then
                                        uci:set("freifunk", "wizard", "chan_" .. device, value)
                                        uci:save("freifunk")
                                end
                        end
-               local meship = f:field(Value, "meship_" .. device, device:upper() .. "  Mesh IP Adresse einrichten", "Ihre Mesh IP Adresse erhalten Sie von der Freifunk Gemeinschaft in Ihrer Nachbarschaft. Es ist eine netzweit eindeutige Identifikation, z.B. 104.1.1.1.")
+
+                       local meship = f:field(Value, "meship_" .. device, device:upper() .. "  Mesh IP Adresse einrichten", "Ihre Mesh IP Adresse erhalten Sie von der Freifunk Gemeinschaft in Ihrer Nachbarschaft. Es ist eine netzweit eindeutige Identifikation, z.B. 104.1.1.1.")
                        meship:depends("device_" .. device, "1")
                        meship.rmempty = true
                        function meship.cfgvalue(self, section)
@@ -219,12 +220,15 @@ uci:foreach("wireless", "wifi-device",
                                        uci:save("freifunk")
                                end
                        end
-               local meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
+               if has_ipv6 then
+                       local meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
                        meship6:depends("device_" .. device, "1")
                        meship6.rmempty = true
                        function meship6.cfgvalue(self, section)
                                return get_ula(get_mac(device))
                        end
+               end
+       
                local client = f:field(Flag, "client_" .. device, device:upper() .. "  DHCP anbieten", "DHCP weist verbundenen Benutzern automatisch eine Adresse zu. Diese Option sollten Sie unbedingt aktivieren, wenn Sie Nutzer an der drahtlosen Schnittstelle erwarten.")
                        client:depends("device_" .. device, "1")
                        client.rmempty = false
@@ -292,12 +296,15 @@ uci:foreach("network", "interface",
                                function meship.write(self, sec, value)
                                        uci:set("freifunk", "wizard", "meship_" .. device, value)
                                end
-                       meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
+                       if has_ipv6 then
+                               meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
                                meship6:depends("device_" .. device, "1")
                                meship6.rmempty = true
                                function meship6.cfgvalue(self, section)
                                        return get_ula(get_mac(ifname))
                                end
+                       end
+
                        client = f:field(Flag, "client_" .. device, device:upper() .. "  DHCP anbieten","DHCP weist verbundenen Benutzern automatisch eine Adresse zu. Diese Option sollten Sie unbedingt aktivieren, wenn Sie Nutzer an der drahtlosen Schnittstelle erwarten.")
                                client:depends("device_" .. device, "1")
                                client.rmempty = false
@@ -550,15 +557,17 @@ if has_l2gvpn then
        end
 end
 
-hb = f:field(Flag, "hb", "Heartbeat aktivieren","Dem Gerät erlauben anonyme Statistiken zu übertragen. (empfohlen)")
-hb.rmempty = false
-hb:depends("netconfig", "1")
-function hb.cfgvalue(self, section)
-       return uci:get("freifunk", "wizard", "hb")
-end
-function hb.write(self, section, value)
-       uci:set("freifunk", "wizard", "hb", value)
-       uci:save("freifunk")
+if has_hb then
+       hb = f:field(Flag, "hb", "Heartbeat aktivieren","Dem Gerät erlauben anonyme Statistiken zu übertragen. (empfohlen)")
+       hb.rmempty = false
+       hb:depends("netconfig", "1")
+       function hb.cfgvalue(self, section)
+               return uci:get("freifunk", "wizard", "hb")
+       end
+       function hb.write(self, section, value)
+               uci:set("freifunk", "wizard", "hb", value)
+               uci:save("freifunk")
+       end
 end
 
 -------------------- Control --------------------
@@ -609,7 +618,9 @@ function f.handle(self, state, data)
                        if has_radvd then
                                uci:commit("radvd")
                        end
-                       luci.http.redirect(luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path), "system", "reboot") .. "?reboot=1")
+-- the following line didn't work without admin-mini, for now i just replaced it with sys.exec... soma
+--                     luci.http.redirect(luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path), "system", "reboot") .. "?reboot=1")
+                       sys.exec("reboot")
                end
                return false
        elseif state == FORM_INVALID then
@@ -636,6 +647,7 @@ function main.write(self, section, value)
        end
        -- Collect IP-Address
        local community = net:formvalue(section)
+       suffix = uci:get("freifunk", community, "suffix") or "olsr"
 
        -- Invalidate fields
        if not community then
@@ -684,14 +696,20 @@ function main.write(self, section, value)
                end)
        end
        uci:save("firewall")
-       uci:delete("manager", "heartbeat", "interface")
-       uci:save("manager")
+       if has_hb then
+               uci:delete("manager", "heartbeat", "interface")
+               uci:save("manager")
+       end
        -- Delete olsrdv4
        uci:delete_all("olsrd", "olsrd")
        local olsrbase
        olsrbase = uci:get_all("freifunk", "olsrd") or {}
        util.update(olsrbase, uci:get_all(external, "olsrd") or {})
-       olsrbase.IpVersion='6and4'
+       if has_ipv6 then
+               olsrbase.IpVersion='6and4'
+       else
+               olsrbase.IpVersion='4'
+       end
        uci:section("olsrd", "olsrd", nil, olsrbase)
        -- Delete olsrdv4 old p2pd settings
        uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_mdns.so.1.0.0"})
@@ -717,7 +735,9 @@ function main.write(self, section, value)
                        return
                end
                node_ip = luci.http.formvalue("cbid.ffwizward.1.meship_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.meship_" .. device))
-               node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
+               if has_ipv6 then
+                       node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
+               end
                if not node_ip or not network or not network:contains(node_ip) then
                        meship.tag_missing[section] = true
                        node_ip = nil
@@ -761,50 +781,37 @@ function main.write(self, section, value)
                end
                -- New Config
                -- Tune wifi device
-               local ssiduci = uci:get("freifunk", community, "ssid")
-               local ssiddot = string.find(ssiduci,'%..*')
-               local ssidshort
-               if ssiddot then
-                       ssidshort = string.sub(ssiduci,ssiddot)
-               else
-                       ssidshort = ssiduci
-               end
+               local ssid = uci:get("freifunk", community, "ssid") or "olsr.freifunk.net"
                local devconfig = uci:get_all("freifunk", "wifi_device")
                util.update(devconfig, uci:get_all(external, "wifi_device") or {})
-               local ssid = uci:get("freifunk", community, "ssid")
                local channel = luci.http.formvalue("cbid.ffwizward.1.chan_" .. device)
                local hwmode = "11bg"
-               local bssid = "02:CA:FF:EE:BA:BE"
+               local bssid = uci:get_all(external, "wifi_iface", "bssid") or "02:CA:FF:EE:BA:BE"
                local mrate = 5500
+               -- set bssid, see https://kifuse02.pberg.freifunk.net/moin/channel-bssid-essid for schema
                if channel and channel ~= "default" then
                        if devconfig.channel ~= channel then
                                devconfig.channel = channel
                                local chan = tonumber(channel)
                                if chan >= 0 and chan < 10 then
                                        bssid = channel .. "2:CA:FF:EE:BA:BE"
-                                       ssid = "ch" .. channel .. ssidshort
-                               elseif chan == 10 then
-                                       bssid = "02:CA:FF:EE:BA:BE"
-                                       ssid = "ch" .. channel .. ssidshort
                                elseif chan >= 11 and chan <= 14 then
                                        bssid = string.format("%X",channel) .. "2:CA:FF:EE:BA:BE"
-                                       ssid = "ch" .. channel .. ssidshort
                                elseif chan >= 36 and chan <= 64 then
                                        hwmode = "11a"
                                        mrate = ""
                                        outdoor = 0
                                        bssid = "00:" .. channel ..":CA:FF:EE:EE"
-                                       ssid = "ch" .. channel .. ssidshort
                                elseif chan >= 100 and chan <= 140 then
                                        hwmode = "11a"
                                        mrate = ""
                                        outdoor = 1
                                        bssid = "01:" .. string.sub(channel, 2) .. ":CA:FF:EE:EE"
-                                       ssid = "ch" .. channel .. ssidshort
                                end
                                devconfig.hwmode = hwmode
                                devconfig.outdoor = outdoor
                        end
+                       ssid = ssid .. " - ch" .. channel
                end
                uci:tset("wireless", device, devconfig)
                -- Create wifi iface
@@ -812,13 +819,7 @@ function main.write(self, section, value)
                util.update(ifconfig, uci:get_all(external, "wifi_iface") or {})
                ifconfig.device = device
                ifconfig.network = nif
-               if ssid then
-                       -- See Table https://kifuse02.pberg.freifunk.net/moin/channel-bssid-essid 
-                       ifconfig.ssid = ssid
-               else
-                       ifconfig.ssid = "olsr.freifunk.net"
-               end
-               -- See Table https://kifuse02.pberg.freifunk.net/moin/channel-bssid-essid       
+               ifconfig.ssid = ssid
                ifconfig.bssid = bssid
                ifconfig.encryption="none"
                -- Read Preset 
@@ -826,7 +827,9 @@ function main.write(self, section, value)
                util.update(netconfig, uci:get_all(external, "interface") or {})
                netconfig.proto = "static"
                netconfig.ipaddr = node_ip:string()
-               netconfig.ip6addr = node_ip6:string()
+               if has_ipv6 then
+                       netconfig.ip6addr = node_ip6:string()
+               end
                uci:section("network", "interface", nif, netconfig)
                if has_radvd then
                        uci:section("radvd", "interface", nil, {
@@ -860,10 +863,12 @@ function main.write(self, section, value)
                local client = luci.http.formvalue("cbid.ffwizward.1.client_" .. device)
                if client then
                        local dhcpmeshnet = luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device))
-                       local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
-                       table.insert(ifacelist,nif .. "dhcp")
-                       uci:set_list("manager", "heartbeat", "interface", ifacelist)
-                       uci:save("manager")
+                       if has_hb then
+                               local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
+                               table.insert(ifacelist,nif .. "dhcp")
+                               uci:set_list("manager", "heartbeat", "interface", ifacelist)
+                               uci:save("manager")
+                       end
                        if dhcpmeshnet then
                                if not dhcpmeshnet:minhost() or not dhcpmeshnet:mask() then
                                        dhcpmesh.tag_missing[section] = true
@@ -922,8 +927,8 @@ function main.write(self, section, value)
                                                device     =device,
                                                mode       ="ap",
                                                encryption ="none",
-                                               network    =nif.."dhcp",
-                                               ssid       ="AP"..ssidshort
+                                               network    =nif .. "dhcp",
+                                               ssid       ="AP-" .. ssid
                                        })
                                        if has_radvd then
                                                uci:section("radvd", "interface", nil, {
@@ -1021,7 +1026,9 @@ function main.write(self, section, value)
                if device ~= "loopback" and not string.find(device, "wifi") and not string.find(device, "wl") and not string.find(device, "wlan") and not string.find(device, "wireless") and not string.find(device, "radio") then
                        local node_ip
                        node_ip = luci.http.formvalue("cbid.ffwizward.1.meship_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.meship_" .. device))
-                       node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
+                       if has_ipv6 then
+                               node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
+                       end
                        if not node_ip or not network or not network:contains(node_ip) then
                                meship.tag_missing[section] = true
                                node_ip = nil
@@ -1049,7 +1056,9 @@ function main.write(self, section, value)
                        util.update(netconfig, uci:get_all(external, "interface") or {})
                        netconfig.proto = "static"
                        netconfig.ipaddr = node_ip:string()
-                       netconfig.ip6addr = node_ip6:string()
+                       if has_ipv6 then
+                               netconfig.ip6addr = node_ip6:string()
+                       end
                        uci:section("network", "interface", device, netconfig)
                        uci:save("network")
                        if has_radvd then
@@ -1085,10 +1094,12 @@ function main.write(self, section, value)
                        local client = luci.http.formvalue("cbid.ffwizward.1.client_" .. device)
                        if client then
                                local dhcpmeshnet = luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device))
-                               local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
-                               table.insert(ifacelist,device .. "dhcp")
-                               uci:set_list("manager", "heartbeat", "interface", ifacelist)
-                               uci:save("manager")
+                               if has_hb then
+                                       local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
+                                       table.insert(ifacelist,device .. "dhcp")
+                                       uci:set_list("manager", "heartbeat", "interface", ifacelist)
+                                       uci:save("manager")
+                               end
                                if dhcpmeshnet then
                                        if not dhcpmeshnet:minhost() or not dhcpmeshnet:mask() then
                                                dhcpmesh.tag_missing[section] = true
@@ -1232,18 +1243,19 @@ function main.write(self, section, value)
        local new_hostname = uci:get("freifunk", "wizard", "hostname")
        local old_hostname = sys.hostname()
 
-       local dhcphb = hb:formvalue(section)
-       if dhcphb then
-               uci:set("manager", "heartbeat", "enabled", "1")
-               -- Make sure that heartbeat is enabled
-               sys.init.enable("machash")
-
-       else
-               uci:set("manager", "heartbeat", "enabled", "0")
-               -- Make sure that heartbeat is enabled
-               sys.init.disable("machash")
+       if has_hb then
+               local dhcphb = hb:formvalue(section)
+               if dhcphb then
+                       uci:set("manager", "heartbeat", "enabled", "1")
+                       -- Make sure that heartbeat is enabled
+                       sys.init.enable("machash")
+               else
+                       uci:set("manager", "heartbeat", "enabled", "0")
+                       -- Make sure that heartbeat is enabled
+                       sys.init.disable("machash")
+               end
+               uci:save("manager")
        end
-       uci:save("manager")
 
        local custom_hostname = hostname:formvalue(section)
        uci:foreach("system", "system",
@@ -1314,7 +1326,7 @@ function main.write(self, section, value)
        -- Write new nameservice settings
        uci:section("olsrd", "LoadPlugin", nil, {
                library     = "olsrd_nameservice.so.0.3",
-               suffix      = ".olsr",
+               suffix      = "." .. suffix ,
                hosts_file  = "/var/etc/hosts.olsr",
                latlon_file = "/var/run/latlon.js",
                lat         = latval and string.format("%.15f", latval) or "",
@@ -1325,8 +1337,8 @@ function main.write(self, section, value)
        -- Import hosts and set domain
        uci:foreach("dhcp", "dnsmasq", function(s)
                uci:set_list("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr")
-               uci:set("dhcp", s[".name"], "local", "/olsr/")
-               uci:set("dhcp", s[".name"], "domain", "olsr")
+               uci:set("dhcp", s[".name"], "local", "/" .. suffix .. "/")
+               uci:set("dhcp", s[".name"], "domain", suffix)
        end)
 
        -- Make sure that OLSR is enabled
@@ -1335,9 +1347,15 @@ function main.write(self, section, value)
        uci:save("olsrd")
        uci:save("dhcp")
        -- Import hosts and set domain
-       uci:foreach("dhcp", "dnsmasq", function(s)
-               uci:set_list("dhcp", s[".name"], "addnhosts", {"/var/etc/hosts.olsr","/var/etc/hosts.olsr.ipv6"})
-       end)
+       if has_ipv6 then
+               uci:foreach("dhcp", "dnsmasq", function(s)
+                       uci:set_list("dhcp", s[".name"], "addnhosts", {"/var/etc/hosts.olsr","/var/etc/hosts.olsr.ipv6"})
+               end)
+       else
+               uci:foreach("dhcp", "dnsmasq", function(s)
+                       uci:set_list("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr")
+               end)
+       end
 
        uci:save("dhcp")
 
@@ -1346,10 +1364,14 @@ function main.write(self, section, value)
        if share_value == "1" then
                uci:set("freifunk", "wizard", "netconfig", "1")
                uci:section("firewall", "forwarding", nil, {src="freifunk", dest="wan"})
-               -- Set autoipv6 tunnel mode
-               uci:set("autoipv6", "olsr_node", "enable", "0")
-               uci:set("autoipv6", "tunnel", "enable", "1")
-               uci:save("autoipv6")
+
+               if has_autoipv6 then
+                       -- Set autoipv6 tunnel mode
+                       uci:set("autoipv6", "olsr_node", "enable", "0")
+                       uci:set("autoipv6", "tunnel", "enable", "1")
+                       uci:save("autoipv6")
+               end
+
                -- Delete/Disable gateway plugin
                uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw.so.0.5"})
                uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"})
@@ -1372,10 +1394,12 @@ function main.write(self, section, value)
        else
                uci:set("freifunk", "wizard", "netconfig", "0")
                uci:save("freifunk")
-               -- Set autoipv6 olsrd mode
-               uci:set("autoipv6", "olsr_node", "enable", "1")
-               uci:set("autoipv6", "tunnel", "enable", "0")
-               uci:save("autoipv6")
+               if has_autoipv6 then
+                       -- Set autoipv6 olsrd mode
+                       uci:set("autoipv6", "olsr_node", "enable", "1")
+                       uci:set("autoipv6", "tunnel", "enable", "0")
+                       uci:save("autoipv6")
+               end
                -- Delete gateway plugins
                uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw.so.0.5"})
                uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"})