modules/admin-full: add 6to4 configuration support
[project/luci.git] / modules / admin-full / luasrc / model / cbi / admin_network / ifaces.lua
index 5598ed3..fd79d50 100644 (file)
@@ -14,6 +14,7 @@ $Id$
 ]]--
 
 local fs = require "nixio.fs"
+local ut = require "luci.util"
 local nw = require "luci.model.network"
 local fw = require "luci.model.firewall"
 
@@ -26,6 +27,7 @@ local has_pppoe  = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
 local has_pppoa  = fs.glob("/usr/lib/pppd/*/pppoatm.so")()
 local has_ipv6   = fs.access("/proc/net/ipv6_route")
 local has_6in4   = fs.access("/lib/network/6in4.sh")
+local has_6to4   = fs.access("/lib/network/6to4.sh")
 
 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:chain("firewall")
@@ -34,6 +36,17 @@ m:chain("wireless")
 nw.init(m.uci)
 fw.init(m.uci)
 
+
+local net = nw:get_network(arg[1])
+
+-- redirect to overview page if network does not exist anymore (e.g. after a revert)
+if not net then
+       luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
+       return
+end
+
+local ifc = net:get_interfaces()[1]
+
 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
 s.addremove = false
 
@@ -41,10 +54,14 @@ s:tab("general", translate("General Setup"))
 if has_ipv6  then s:tab("ipv6", translate("IPv6 Setup")) end
 if has_pppd  then s:tab("ppp", translate("PPP Settings")) end
 if has_pppoa then s:tab("atm", translate("ATM Settings")) end
-if has_6in4  then s:tab("tunnel", translate("Tunnel Settings")) end
+if has_6in4 or has_6to4 then s:tab("tunnel", translate("Tunnel Settings")) end
 s:tab("physical", translate("Physical Settings"))
 s:tab("firewall", translate("Firewall Settings"))
 
+st = s:taboption("general", DummyValue, "__status", translate("Status"))
+st.template = "admin_network/iface_status"
+st.network  = arg[1]
+
 --[[
 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
 back.value = ""
@@ -62,6 +79,7 @@ if has_pppoa then p:value("pppoa", "PPPoA")   end
 if has_3g    then p:value("3g",    "UMTS/3G") end
 if has_pptp  then p:value("pptp",  "PPTP")    end
 if has_6in4  then p:value("6in4",  "6in4")    end
+if has_6to4  then p:value("6to4",  "6to4")    end
 p:value("none", translate("none"))
 
 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
@@ -77,7 +95,7 @@ br:depends("proto", "none")
 
 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
        translate("Enables the Spanning Tree Protocol on this bridge"))
-stp:depends("type", "1")
+stp:depends("type", "bridge")
 stp.rmempty = true
 
 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
@@ -103,29 +121,28 @@ function ifname_single.write(self, s, val)
                for _, i in ipairs(n:get_interfaces()) do
                        n:del_interface(i)
                end
-               n:add_interface(val)
+
+               for i in ut.imatch(val) do
+                       n:add_interface(i)
+
+                       -- if this is not a bridge, only assign first interface
+                       if self.option == "ifname_single" then
+                               break
+                       end
+               end
        end
 end
 
-
-ifname_multi = s:taboption("physical", MultiValue, "ifname_multi", translate("Interface"))
+ifname_multi = s:taboption("physical", Value, "ifname_multi", translate("Interface"))
 ifname_multi.template = "cbi/network_ifacelist"
 ifname_multi.nobridges = true
 ifname_multi.network = arg[1]
 ifname_multi.widget = "checkbox"
-ifname_multi:depends("type", "1")
+ifname_multi:depends("type", "bridge")
 ifname_multi.cfgvalue = ifname_single.cfgvalue
 ifname_multi.write = ifname_single.write
 
 
-for _, d in ipairs(nw:get_interfaces()) do
-       if not d:is_bridge() then
-               ifname_single:value(d:name())
-               ifname_multi:value(d:name())
-       end
-end
-
-
 local fwd_to, fwd_from
 
 fwzone = s:taboption("firewall", Value, "_fwzone",
@@ -161,12 +178,12 @@ function fwzone.write(self, section, value)
 end
 
 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
-ipaddr.rmempty = true
+ipaddr.optional = true
 ipaddr.datatype = "ip4addr"
 ipaddr:depends("proto", "static")
 
 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
-nm.rmempty = true
+nm.optional = true
 nm.datatype = "ip4addr"
 nm:depends("proto", "static")
 nm:value("255.255.255.0")
@@ -185,7 +202,7 @@ bcast:depends("proto", "static")
 
 if has_ipv6 then
        ip6addr = s:taboption("ipv6", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
-       ip6addr.rmempty = true
+       ip6addr.optional = true
        ip6addr.datatype = "ip6addr"
        ip6addr:depends("proto", "static")
        ip6addr:depends("proto", "6in4")
@@ -196,17 +213,23 @@ if has_ipv6 then
        ip6gw:depends("proto", "static")
 end
 
-dns = s:taboption("general", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
-       translate("You can specify multiple DNS servers separated by space here. Servers entered here will override " ..
+dns = s:taboption("general", DynamicList, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
+       translate("You can specify multiple DNS servers here, press enter to add a new entry. Servers entered here will override " ..
                "automatically assigned ones."))
 
 dns.optional = true
+dns.cast = "string"
 dns.datatype = "ipaddr"
-dns:depends("peerdns", "")
+dns:depends({ peerdns = "", proto = "static" })
+dns:depends({ peerdns = "", proto = "dhcp"   })
+dns:depends({ peerdns = "", proto = "pppoe"  })
+dns:depends({ peerdns = "", proto = "pppoa"  })
+dns:depends({ peerdns = "", proto = "none"   })
 
 mtu = s:taboption("physical", Value, "mtu", "MTU")
 mtu.optional = true
 mtu.datatype = "uinteger"
+mtu.placeholder = 1500
 
 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
 srv:depends("proto", "pptp")
@@ -218,18 +241,42 @@ if has_6in4 then
        peer.optional = false
        peer.datatype = "ip4addr"
        peer:depends("proto", "6in4")
+end
 
+if has_6in4 or has_6to4 then
        ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
        ttl.default = "64"
        ttl.optional = true
        ttl.datatype = "uinteger"
        ttl:depends("proto", "6in4")
+       ttl:depends("proto", "6to4")
+
+       advi = s:taboption("general", Value, "adv_interface", translate("Advertise IPv6 on network"))
+       advi.widget = "radio"
+       advi.exclude = arg[1]
+       advi.default = "lan"
+       advi.template = "cbi/network_netlist"
+       advi.nocreate = true
+       advi.nobridges = true
+
+       advn = s:taboption("general", Value, "adv_subnet", translate("Advertised network ID"), translate("Allowed range is 1 to FFFF"))
+       advn.default = "1"
+
+       function advn.write(self, section, value)
+               value = tonumber(value, 16) or 1
+
+               if value > 65535 then value = 65535
+               elseif value < 1 then value = 1 end
+
+               Value.write(self, section, "%X" % value)
+       end
 end
 
 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
 mac:depends("proto", "none")
 mac:depends("proto", "static")
 mac:depends("proto", "dhcp")
+mac.placeholder = ifc and ifc:mac():upper()
 
 if has_3g then
        service = s:taboption("general", ListValue, "service", translate("Service type"))
@@ -276,7 +323,9 @@ if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
        pass:depends("proto", "ppp")
        pass:depends("proto", "3g")
        pass:depends("proto", "6in4")
+end
 
+if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
        ka = s:taboption("ppp", Value, "keepalive",
         translate("Keep-Alive"),
         translate("Number of failed connection tests to initiate automatic reconnect")