applications/luci-splash: Add limited IPv6 Support
authorManuel Munz <freifunk@somakoma.de>
Mon, 25 Mar 2013 16:31:34 +0000 (16:31 +0000)
committerManuel Munz <freifunk@somakoma.de>
Mon, 25 Mar 2013 16:31:34 +0000 (16:31 +0000)
applications/luci-splash/README [new file with mode: 0644]
applications/luci-splash/root/etc/init.d/luci_splash
applications/luci-splash/root/usr/sbin/luci-splash

diff --git a/applications/luci-splash/README b/applications/luci-splash/README
new file mode 100644 (file)
index 0000000..5a7af14
--- /dev/null
@@ -0,0 +1,5 @@
+
+* IPv6 support is only partial:
+  - will only work when used together with IPv4 (Dual stack)
+  - No bandwidth limiting
+
index 0d21bf5..a6c6366 100755 (executable)
@@ -8,6 +8,7 @@ LIMIT_UP=0
 
 IPT_REPLAY=/var/run/luci_splash.iptlog
 LOCK=/var/run/luci_splash.lock
+[ -x /usr/sbin/ip6tables ] && [ -f /proc/net/ipv6_route ] && HAS_IPV6=1
 
 silent() {
        "$@" 2>/dev/null
@@ -18,6 +19,13 @@ ipt_log() {
        echo iptables -D "$@" >> $IPT_REPLAY
 }
 
+ipt6_log() {
+       [ "$HAS_IPV6" = 1 ] || return
+       ip6tables -I "$@"
+       echo ip6tables -D "$@" >> $IPT_REPLAY
+}
+
+
 iface_add() {
        local cfg="$1"
 
@@ -33,6 +41,9 @@ iface_add() {
        config_get ipaddr "$net" ipaddr
        [ -n "$ipaddr" ] || return 0
 
+       config_get ip6addr "$net" ip6addr
+       #[ -n "$ipaddr" ] || return 0
+
        config_get netmask "$net" netmask
        [ -n "$netmask" ] || return 0
 
@@ -53,6 +64,10 @@ iface_add() {
        ipt_log "zone_${zone}_prerouting" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_prerouting -t nat
        ipt_log "zone_${zone}_forward"    -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_forwarding -t filter
 
+       if [ "$HAS_IPV6" = 1 ]; then
+               ipt6_log "zone_${zone}_forward"    -i "${ifname%:*}" -s "$ip6addr" -j luci_splash_forwarding -t filter
+       fi
+
        ### Allow traffic to the same subnet
        iptables -t nat    -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN
        iptables -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN
@@ -197,6 +212,11 @@ start() {
        iptables -t filter -N luci_splash_forwarding
        iptables -t filter -N luci_splash_filter
 
+       if [ "$HAS_IPV6" = 1 ]; then
+               ip6tables -t filter -N luci_splash_forwarding
+               ip6tables -t filter -N luci_splash_filter
+       fi
+
        ### Clear iptables replay log
        [ -s $IPT_REPLAY ] && . $IPT_REPLAY
        echo -n > $IPT_REPLAY
@@ -215,12 +235,24 @@ start() {
        iptables -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset
        iptables -t filter -A luci_splash_filter -j REJECT --reject-with icmp-net-prohibited
 
+       if [ "$HAS_IPV6" = 1 ]; then
+               ip6tables -t filter -A luci_splash_forwarding -j luci_splash_filter
+               ip6tables -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset
+               ip6tables -t filter -A luci_splash_filter -j REJECT --reject-with adm-prohibited
+       fi
+
        ### Add QoS chain
        [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && {
                iptables -t mangle -N luci_splash_mark_out
                iptables -t mangle -N luci_splash_mark_in
                iptables -t mangle -I PREROUTING  -j luci_splash_mark_out
                iptables -t mangle -I POSTROUTING -j luci_splash_mark_in
+               if [ "$HAS_IPV6" = 1 ]; then
+                       ip6tables -t mangle -N luci_splash_mark_out
+                       ip6tables -t mangle -N luci_splash_mark_in
+                       ip6tables -t mangle -I PREROUTING  -j luci_splash_mark_out
+                       ip6tables -t mangle -I POSTROUTING -j luci_splash_mark_in
+               fi
        }
 
        ### Find active mac addresses
@@ -254,6 +286,11 @@ stop() {
        silent iptables -t mangle -D PREROUTING  -j luci_splash_mark_out
        silent iptables -t mangle -D POSTROUTING -j luci_splash_mark_in
 
+       if [ "$HAS_IPV6" = 1 ]; then
+               silent ip6tables -t mangle -D PREROUTING  -j luci_splash_mark_out
+               silent ip6tables -t mangle -D POSTROUTING -j luci_splash_mark_in
+       fi
+
        ### Clear subchains
        silent iptables -t nat    -F luci_splash_prerouting
        silent iptables -t nat    -F luci_splash_leases
@@ -262,6 +299,13 @@ stop() {
        silent iptables -t mangle -F luci_splash_mark_out
        silent iptables -t mangle -F luci_splash_mark_in
 
+       if [ "$HAS_IPV6" = 1 ]; then
+               ip6tables -t filter -F luci_splash_forwarding
+               ip6tables -t filter -F luci_splash_filter
+               ip6tables -t mangle -F luci_splash_mark_out
+               ip6tables -t mangle -F luci_splash_mark_in
+       fi
+
        ### Delete subchains
        silent iptables -t nat    -X luci_splash_prerouting
        silent iptables -t nat    -X luci_splash_leases
@@ -269,7 +313,12 @@ stop() {
        silent iptables -t filter -X luci_splash_filter
        silent iptables -t mangle -X luci_splash_mark_out
        silent iptables -t mangle -X luci_splash_mark_in
-
+       if [ "$HAS_IPV6" = 1 ]; then
+               ip6tables -t filter -X luci_splash_forwarding
+               ip6tables -t filter -X luci_splash_filter
+               ip6tables -t mangle -X luci_splash_mark_out
+               ip6tables -t mangle -X luci_splash_mark_in
+       fi
        sed -ie '/\/usr\/sbin\/luci-splash sync/d' /var/spool/cron/crontabs/root
 
        lock -u $LOCK
index 4746173..bf32d63 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
@@ -191,6 +194,22 @@ 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, ":", "")
@@ -290,8 +309,12 @@ function add_lease_rule(mac, ipaddr)
                os.execute("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 80" % ipaddr)
        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
 
 
@@ -306,6 +329,9 @@ function remove_lease_rule(mac, ipaddr)
 
        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="filter", chain="luci_splash_filter",   options={"MAC", mac:upper()}})
+       end
 end
 
 
@@ -313,12 +339,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)
+       if has_ipv6 then
+               os.execute("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac)
+       end
 end
 
 
@@ -365,16 +397,22 @@ function sync()
 
        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 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)
+               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 ips[r.destination] end)
+       end
+
        unlock()
 end