freifunk-gwcheck: make it more readeable and make compat with smaler ip version witho...
[project/luci.git] / applications / luci-splash / root / usr / sbin / luci-splash
index 7738679..3f08f2c 100755 (executable)
@@ -9,10 +9,13 @@ require("luci.sys.iptparser")
 local uci = luci.model.uci.cursor_state()
 local ipt = luci.sys.iptparser.IptParser()
 local net = luci.sys.net
+local fs = require "luci.fs"
 
 local limit_up = 0
 local limit_down = 0
 
+local has_ipv6 = fs.access("/proc/net/ipv6_route") and fs.access("/usr/sbin/ip6tables")
+
 function lock()
        os.execute("lock /var/run/luci_splash.lock")
 end
@@ -146,7 +149,7 @@ function get_known_macs(list)
        local leased_macs = { }
 
        if not list or list == "lease" then
-               uci:foreach("luci_splash", "lease",
+               uci:foreach("luci_splash_leases", "lease",
                        function(s) leased_macs[s.mac:lower()] = true end)
        end
 
@@ -164,17 +167,6 @@ function get_known_macs(list)
 end
 
 
--- Get a list of known ip addresses
-function get_known_ips(macs, arp)
-       local leased_ips = { }
-       if not macs then macs = get_known_macs() end
-       for _, e in ipairs(arp or net.arptable()) do
-               if macs[e["HW address"]:lower()] then leased_ips[e["IP address"]] = true end
-       end
-       return leased_ips
-end
-
-
 -- Helper to delete iptables rules
 function ipt_delete_all(args, comp, off)
        off = off or { }
@@ -191,6 +183,26 @@ function ipt_delete_all(args, comp, off)
        end
 end
 
+function ipt6_delete_all(args, comp, off)
+       off = off or { }
+       for i, r in ipairs(ipt:find(args)) do
+               if comp == nil or comp(r) then
+                       off[r.table] = off[r.table] or { }
+                       off[r.table][r.chain] = off[r.table][r.chain] or 0
+
+                       os.execute("ip6tables -t %q -D %q %d 2>/dev/null"
+                               %{ r.table, r.chain, r.index - off[r.table][r.chain] })
+
+                       off[r.table][r.chain] = off[r.table][r.chain] + 1
+               end
+       end
+end
+
+
+-- Convert mac to uci-compatible section name
+function convert_mac_to_secname(mac)
+       return string.gsub(mac, ":", "")
+end
 
 -- Add a lease to state and invoke add_rule
 function add_lease(mac, arp, no_uci)
@@ -208,12 +220,12 @@ function add_lease(mac, arp, no_uci)
        -- Add lease if there is an ip addr
        if ipaddr then
                if not no_uci then
-                       uci:section("luci_splash", "lease", nil, {
+                       uci:section("luci_splash_leases", "lease", convert_mac_to_secname(mac), {
                                mac    = mac,
                                ipaddr = ipaddr,
                                start  = os.time()
                        })
-                       uci:save("luci_splash")
+                       uci:save("luci_splash_leases")
                end
                add_lease_rule(mac, ipaddr)
        else
@@ -226,7 +238,7 @@ end
 function remove_lease(mac)
        mac = mac:lower()
 
-       uci:delete_all("luci_splash", "lease",
+       uci:delete_all("luci_splash_leases", "lease",
                function(s)
                        if s.mac:lower() == mac then
                                remove_lease_rule(mac, s.ipaddr)
@@ -235,13 +247,13 @@ function remove_lease(mac)
                        return false
                end)
                
-       uci:save("luci_splash")
+       uci:save("luci_splash_leases")
 end
 
 
 -- Add a whitelist entry
 function add_whitelist(mac)
-       uci:section("luci_splash", "whitelist", nil, { mac = mac })
+       uci:section("luci_splash", "whitelist", convert_mac_to_secname(mac), { mac = mac })
        uci:save("luci_splash")
        uci:commit("luci_splash")
        add_whitelist_rule(mac)
@@ -250,7 +262,7 @@ end
 
 -- Add a blacklist entry
 function add_blacklist(mac)
-       uci:section("luci_splash", "blacklist", nil, { mac = mac })
+       uci:section("luci_splash", "blacklist", convert_mac_to_secname(mac), { mac = mac })
        uci:save("luci_splash")
        uci:commit("luci_splash")
        add_blacklist_rule(mac)
@@ -281,27 +293,36 @@ end
 
 -- Add an iptables rule
 function add_lease_rule(mac, ipaddr)
-       if limit_up > 0 and limit_down > 0 then
-               os.execute("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac)
-               os.execute("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80" % ipaddr)
+       os.execute("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac)
+       os.execute("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80 -m comment --comment %s" % {ipaddr, mac:upper()})
+
+       if has_ipv6 then
+               os.execute("ip6tables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac)
+               -- not working yet, needs the ip6addr
+               --os.execute("ip6tables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80 -m comment --comment %s" % {ipaddr, mac:upper()})
        end
 
+
        os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
        os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac)
+       if has_ipv6 then
+               os.execute("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
+       end
 end
 
 
 -- Remove lease, black- or whitelist rules
 function remove_lease_rule(mac, ipaddr)
        ipt:resync()
-
-       if ipaddr then
-               ipt_delete_all({table="mangle", chain="luci_splash_mark_in",  destination=ipaddr})
-               ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", mac:upper()}})
-       end
-
+       ipt_delete_all({table="mangle", chain="luci_splash_mark_in", options={"/*", mac:upper()}})
+       ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", mac:upper()}})
        ipt_delete_all({table="filter", chain="luci_splash_filter",   options={"MAC", mac:upper()}})
        ipt_delete_all({table="nat",    chain="luci_splash_leases",   options={"MAC", mac:upper()}})
+       if has_ipv6 then
+               --ipt6_delete_all({table="mangle", chain="luci_splash_mark_in", options={"/*", mac:upper()}})
+               ipt6_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", mac:upper()}})
+               ipt6_delete_all({table="filter", chain="luci_splash_filter",   options={"MAC", mac:upper()}})
+       end
 end
 
 
@@ -309,13 +330,18 @@ end
 function add_whitelist_rule(mac)
        os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
        os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac)
+       if has_ipv6 then
+               os.execute("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac)
+       end
 end
 
 
 -- Add blacklist rules
 function add_blacklist_rule(mac)
        os.execute("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac)
-       os.execute("iptables -t nat    -I luci_splash_leases -m mac --mac-source %q -j DROP" % mac)
+       if has_ipv6 then
+               os.execute("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac)
+       end
 end
 
 
@@ -326,14 +352,14 @@ function sync()
        local time = os.time()
 
        -- Current leases in state files
-       local leases = uci:get_all("luci_splash")
+       local leases = uci:get_all("luci_splash_leases")
        
        -- Convert leasetime to seconds
        local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600
        
        -- Clean state file
-       uci:load("luci_splash")
-       uci:revert("luci_splash")
+       uci:load("luci_splash_leases")
+       uci:revert("luci_splash_leases")
        
        -- For all leases
        for k, v in pairs(leases) do
@@ -343,7 +369,7 @@ function sync()
                                remove_lease_rule(v.mac, v.ipaddr)
                        else
                                -- Rewrite state
-                               uci:section("luci_splash", "lease", nil, {              
+                               uci:section("luci_splash_leases", "lease", convert_mac_to_secname(v.mac), {             
                                        mac    = v.mac,
                                        ipaddr = v.ipaddr,
                                        start  = v.start
@@ -352,25 +378,31 @@ function sync()
                end
        end
 
-       uci:save("luci_splash")
+       uci:save("luci_splash_leases")
 
-       -- Get current IPs and MAC addresses
+       -- Get the mac addresses of current leases
        local macs = get_known_macs()
-       local ips  = get_known_ips(macs)
 
        ipt:resync()
 
        ipt_delete_all({table="filter", chain="luci_splash_filter", options={"MAC"}},
                function(r) return not macs[r.options[2]:lower()] end)
-
        ipt_delete_all({table="nat", chain="luci_splash_leases", options={"MAC"}},
                function(r) return not macs[r.options[2]:lower()] end)
-
        ipt_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", "MARK", "set"}},
                function(r) return not macs[r.options[2]:lower()] end)
+       ipt_delete_all({table="mangle", chain="luci_splash_mark_in", options={"/*", "MARK", "set"}},
+               function(r) return not macs[r.options[2]:lower()] end)
 
-       ipt_delete_all({table="mangle", chain="luci_splash_mark_in", options={"MARK", "set"}},
-               function(r) return not ips[r.destination] end)
+
+       if has_ipv6 then
+               ipt6_delete_all({table="filter", chain="luci_splash_filter", options={"MAC"}},
+                       function(r) return not macs[r.options[2]:lower()] end)
+               ipt6_delete_all({table="mangle", chain="luci_splash_mark_out", options={"MAC", "MARK", "set"}},
+                       function(r) return not macs[r.options[2]:lower()] end)
+               --ipt6_delete_all({table="mangle", chain="luci_splash_mark_in", options={"/*", "MARK", "set"}},
+               --      function(r) return not macs[r.options[2]:lower()] end)
+       end
 
        unlock()
 end
@@ -398,7 +430,7 @@ function list()
        end
 
        -- Print listings
-       local leases = uci:get_all("luci_splash")
+       local leases = uci:get_all("luci_splash_leases")
 
        print(string.format(
                "%-17s  %-15s  %-9s  %-4s  %-7s  %20s",