modules: Make luci-base sufficient to use luci apps
[project/luci.git] / modules / luci-mod-admin-full / luasrc / model / cbi / admin_network / ifaces.lua
index 9be5ff1a7d178b26ffeb9d5e32461b25e36c8d49..8be354b448c17a4c2a943b86c8e0661ab43fea85 100644 (file)
@@ -1,17 +1,6 @@
---[[
-LuCI - Lua Configuration Interface
-
-Copyright 2008 Steven Barth <steven@midlink.org>
-Copyright 2008-2011 Jo-Philipp Wich <xm@subsignal.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-]]--
+-- Copyright 2008 Steven Barth <steven@midlink.org>
+-- Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
+-- Licensed to the public under the Apache License 2.0.
 
 local fs = require "nixio.fs"
 local ut = require "luci.util"
@@ -25,7 +14,9 @@ local has_dnsmasq  = fs.access("/etc/config/dhcp")
 local has_firewall = fs.access("/etc/config/firewall")
 
 m = Map("network", translate("Interfaces") .. " - " .. arg[1]:upper(), translate("On this page you can configure the network interfaces. You can bridge several interfaces by ticking the \"bridge interfaces\" field and enter the names of several network interfaces separated by spaces. You can also use <abbr title=\"Virtual Local Area Network\">VLAN</abbr> notation <samp>INTERFACE.VLANNR</samp> (<abbr title=\"for example\">e.g.</abbr>: <samp>eth0.1</samp>)."))
+m.redirect = luci.dispatcher.build_url("admin", "network", "network")
 m:chain("wireless")
+m:chain("luci")
 
 if has_firewall then
        m:chain("firewall")
@@ -37,18 +28,52 @@ fw.init(m.uci)
 
 local net = nw:get_network(arg[1])
 
+local function set_ifstate(name, option, value)
+       local found = false
+
+       m.uci:foreach("luci", "ifstate", function (s)
+               if s.interface == name then
+                       m.uci:set("luci", s[".name"], option, value)
+                       found = true
+                       return false
+               end
+       end)
+
+       if not found then
+               local sid = m.uci:add("luci", "ifstate")
+               m.uci:set("luci", sid, "interface", name)
+               m.uci:set("luci", sid, option, value)
+       end
+
+       m.uci:save("luci")
+end
+
+local function get_ifstate(name, option)
+       local val
+
+       m.uci:foreach("luci", "ifstate", function (s)
+               if s.interface == name then
+                       val = s[option]
+                       return false
+               end
+       end)
+
+       return val
+end
+
 local function backup_ifnames(is_bridge)
-       if not net:is_floating() and not m:get(net:name(), "_orig_ifname") then
+       if not net:is_floating() and not get_ifstate(net:name(), "ifname") then
                local ifcs = net:get_interfaces() or { net:get_interface() }
                if ifcs then
                        local _, ifn
                        local ifns = { }
                        for _, ifn in ipairs(ifcs) do
-                               ifns[#ifns+1] = ifn:name()
+                               local wif = ifn:get_wifinet()
+                               ifns[#ifns+1] = wif and wif:id() or ifn:name()
                        end
                        if #ifns > 0 then
-                               m:set(net:name(), "_orig_ifname", table.concat(ifns, " "))
-                               m:set(net:name(), "_orig_bridge", tostring(net:is_bridge()))
+                               set_ifstate(net:name(), "ifname", table.concat(ifns, " "))
+                               set_ifstate(net:name(), "bridge", tostring(net:is_bridge()))
                        end
                end
        end
@@ -94,10 +119,10 @@ if m:formvalue("cbid.network.%s._switch" % net:name()) then
                elseif net:is_floating() and not proto:is_floating() then
                        -- if we have backup data, then re-add all orphaned interfaces
                        -- from it and restore the bridge choice
-                       local br = (m:get(net:name(), "_orig_bridge") == "true")
+                       local br = (get_ifstate(net:name(), "bridge") == "true")
                        local ifn
                        local ifns = { }
-                       for ifn in ut.imatch(m:get(net:name(), "_orig_ifname")) do
+                       for ifn in ut.imatch(get_ifstate(net:name(), "ifname")) do
                                ifn = nw:get_interface(ifn)
                                if ifn and not ifn:get_network() then
                                        proto:add_interface(ifn)
@@ -124,9 +149,7 @@ if m:formvalue("cbid.network.%s._switch" % net:name()) then
                for k, v in pairs(m:get(net:name())) do
                        if k:sub(1,1) ~= "." and
                           k ~= "type" and
-                          k ~= "ifname" and
-                          k ~= "_orig_ifname" and
-                          k ~= "_orig_bridge"
+                          k ~= "ifname"
                        then
                                m:del(net:name(), k)
                        end
@@ -145,7 +168,7 @@ end
 
 -- dhcp setup was requested, create section and reload page
 if m:formvalue("cbid.dhcp._enable._enable") then
-       m.uci:section("dhcp", "dhcp", nil, {
+       m.uci:section("dhcp", "dhcp", arg[1], {
                interface = arg[1],
                start     = "100",
                limit     = "150",
@@ -230,6 +253,12 @@ auto.default = (net:proto() == "none") and auto.disabled or auto.enabled
 delegate = s:taboption("advanced", Flag, "delegate", translate("Use builtin IPv6-management"))
 delegate.default = delegate.enabled
 
+force_link = s:taboption("advanced", Flag, "force_link",
+       translate("Force link"),
+       translate("Set interface properties regardless of the link carrier (If set, carrier sense events do not invoke hotplug handlers)."))
+
+force_link.default = (net:proto() == "static") and force_link.enabled or force_link.disabled
+
 
 if not net:is_virtual() then
        br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
@@ -243,6 +272,11 @@ if not net:is_virtual() then
                translate("Enables the Spanning Tree Protocol on this bridge"))
        stp:depends("type", "bridge")
        stp.rmempty = true
+
+       igmp = s:taboption("physical", Flag, "igmp_snooping", translate("Enable <abbr title=\"Internet Group Management Protocol\">IGMP</abbr> snooping"),
+               translate("Enables IGMP snooping on this bridge"))
+       igmp:depends("type", "bridge")
+       igmp.rmempty = true
 end
 
 
@@ -251,6 +285,7 @@ if not net:is_floating() then
        ifname_single.template = "cbi/network_ifacelist"
        ifname_single.widget = "radio"
        ifname_single.nobridges = true
+       ifname_single.noaliases = false
        ifname_single.rmempty = false
        ifname_single.network = arg[1]
        ifname_single:depends("type", "")
@@ -261,12 +296,18 @@ if not net:is_floating() then
        end
 
        function ifname_single.write(self, s, val)
-               local i
+               local _, i
                local new_ifs = { }
                local old_ifs = { }
 
-               for _, i in ipairs(net:get_interfaces() or { net:get_interface() }) do
-                       old_ifs[#old_ifs+1] = i:name()
+               local alias = net:is_alias()
+
+               if alias then
+                       old_ifs[1] = '@' .. alias
+               else
+                       for _, i in ipairs(net:get_interfaces() or { net:get_interface() }) do
+                               old_ifs[#old_ifs+1] = i:name()
+                       end
                end
 
                for i in ut.imatch(val) do
@@ -301,6 +342,7 @@ if not net:is_virtual() then
        ifname_multi = s:taboption("physical", Value, "ifname_multi", translate("Interface"))
        ifname_multi.template = "cbi/network_ifacelist"
        ifname_multi.nobridges = true
+       ifname_multi.noaliases = true
        ifname_multi.rmempty = false
        ifname_multi.network = arg[1]
        ifname_multi.widget = "checkbox"
@@ -317,7 +359,6 @@ if has_firewall then
 
        fwzone.template = "cbi/firewall_zonelist"
        fwzone.network = arg[1]
-       fwzone.rmempty = false
 
        function fwzone.cfgvalue(self, section)
                self.iface = section
@@ -326,22 +367,16 @@ if has_firewall then
        end
 
        function fwzone.write(self, section, value)
-               local zone = fw:get_zone(value)
-
-               if not zone and value == '-' then
-                       value = m:formvalue(self:cbid(section) .. ".newzone")
-                       if value and #value > 0 then
-                               zone = fw:add_zone(value)
-                       else
-                               fw:del_network(section)
-                       end
-               end
-
+               local zone = fw:get_zone(value) or fw:add_zone(value)
                if zone then
                        fw:del_network(section)
                        zone:add_network(section)
                end
        end
+
+       function fwzone.remove(self, section)
+               fw:del_network(section)
+       end
 end
 
 
@@ -383,7 +418,7 @@ for _, field in ipairs(s.children) do
                if next(field.deps) then
                        local _, dep
                        for _, dep in ipairs(field.deps) do
-                               dep.deps.proto = net:proto()
+                               dep.proto = net:proto()
                        end
                else
                        field:depends("proto", net:proto())
@@ -449,7 +484,7 @@ if has_dnsmasq and net:proto() == "static" then
                limit.datatype = "uinteger"
                limit.default = "150"
 
-               local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
+               local ltime = s:taboption("general", Value, "leasetime", translate("Lease time"),
                        translate("Expiry time of leased addresses, minimum is 2 minutes (<code>2m</code>)."))
                ltime.rmempty = true
                ltime.default = "12h"
@@ -502,8 +537,9 @@ if has_dnsmasq and net:proto() == "static" then
                o:value("relay", translate("relay mode"))
                o:value("hybrid", translate("hybrid mode"))
 
-               o = s:taboption("ipv6", ListValue, "ra_management", translate("DHCPv6-Mode"))
-               o:value("", translate("stateless"))
+               o = s:taboption("ipv6", ListValue, "ra_management", translate("DHCPv6-Mode"),
+                       translate("Default is stateless + stateful"))
+               o:value("0", translate("stateless"))
                o:value("1", translate("stateless + stateful"))
                o:value("2", translate("stateful-only"))
                o:depends("dhcpv6", "server")