* Reworked Luci-Splash
authorSteven Barth <steven@midlink.org>
Sun, 27 Apr 2008 11:04:48 +0000 (11:04 +0000)
committerSteven Barth <steven@midlink.org>
Sun, 27 Apr 2008 11:04:48 +0000 (11:04 +0000)
* Created ffluci-system-addons package for Kamikaze addons

18 files changed:
contrib/package/ffluci-splash/Makefile [new file with mode: 0644]
contrib/package/ffluci-splash/ipkg/conffiles [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci-splash.lua [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci_splash.cron [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci_splash.init [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci_splash.uci [new file with mode: 0644]
contrib/package/ffluci-splash/src/luci_splash_httpd.conf [new file with mode: 0644]
contrib/package/ffluci-system-addons/Makefile [new file with mode: 0644]
contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases [new file with mode: 0644]
contrib/package/ffluci-system-addons/src/root.crontab [new file with mode: 0644]
contrib/package/ffluci-system-addons/src/run-parts [new file with mode: 0644]
contrib/package/ffluci/Makefile
core/contrib/hotplug.d-20-aliases [deleted file]
core/contrib/uci/luci
core/src/ffluci/sys.lua
module/admin-core/contrib/luci-splash

diff --git a/contrib/package/ffluci-splash/Makefile b/contrib/package/ffluci-splash/Makefile
new file mode 100644 (file)
index 0000000..d3e98af
--- /dev/null
@@ -0,0 +1,43 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffluci-splash
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+PKG_BUILD_DEPENDS:=lua-luci
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffluci-splash
+  SECTION:=admin
+  CATEGORY:=Administration
+  SUBMENU:=FFLuCI
+  DEPENDS:=+ffluci +iptables-mod-nat +lua-luci
+  TITLE:=FFLuCI DHCP-Splash
+endef
+
+define Build/Compile
+endef
+
+define Package/ffluci-splash/install
+       $(INSTALL_DIR) $(1)/usr/lib/luci-splash/htdocs/cgi-bin
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_DIR) $(1)/etc/cron.minutely
+       $(INSTALL_DIR) $(1)/etc/init.d
+       $(INSTALL_DIR) $(1)/usr/sbin
+       
+       $(CP) -a ./src/luci-splash/* $(1)/usr/lib/luci-splash/ -R
+       $(INSTALL_BIN) ./src/luci-splash/htdocs/cgi-bin/index.cgi $(1)/usr/lib/luci-splash/htdocs/cgi-bin
+       $(INSTALL_BIN) ./src/luci_splash.init $(1)/etc/init.d/luci_splash
+       $(INSTALL_BIN) ./src/luci-splash.lua $(1)/usr/sbin/luci-splash
+       
+       $(INSTALL_BIN) -a ./src/luci_splash.cron $(1)/etc/cron.minutely/luci_splash
+       $(CP) -a ./src/luci_splash.uci $(1)/etc/config/luci_splash
+       $(CP) -a ./src/luci_splash_httpd.conf $(1)/etc/
+       
+       $(CP) -a ./ipkg/conffiles $(1)/CONTROL/conffiles
+endef
+
+$(eval $(call BuildPackage,ffluci-splash))
diff --git a/contrib/package/ffluci-splash/ipkg/conffiles b/contrib/package/ffluci-splash/ipkg/conffiles
new file mode 100644 (file)
index 0000000..dcbe1ad
--- /dev/null
@@ -0,0 +1 @@
+/etc/config/luci_splash
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash.lua b/contrib/package/ffluci-splash/src/luci-splash.lua
new file mode 100644 (file)
index 0000000..54c32ad
--- /dev/null
@@ -0,0 +1,173 @@
+#!/usr/bin/lua
+package.path  = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
+
+require("ffluci.http")
+require("ffluci.sys")
+require("ffluci.model.uci")
+
+-- Init state session
+uci = ffluci.model.uci.Session("/var/state")
+
+
+-- Parse stdin and do something
+function main(argv)
+       local cmd = argv[1]
+       local arg = argv[2]
+       
+       if not cmd then
+               print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
+               os.exit(1)
+       elseif cmd == "status" then
+               if not arg then
+                       os.exit(1)
+               end
+               
+               if iswhitelisted(arg) then
+                       print("whitelisted")
+                       os.exit(0)
+               end
+               
+               if haslease(arg) then
+                       print("lease")
+                       os.exit(0)
+               end             
+               
+               print("unknown")
+               os.exit(0)
+       elseif cmd == "add" then
+               if not arg then
+                       os.exit(1)
+               end
+               
+               if not haslease(arg) then
+                       add_lease(arg)
+               else
+                       print("already leased!")
+                       os.exit(2)
+               end
+               os.exit(0)
+       elseif cmd == "remove" then
+               if not cmd[2] then
+                       os.exit(1)
+               end
+               
+               remove_lease(arg)
+               os.exit(0)              
+       elseif cmd == "sync" then
+               sync()
+               os.exit(0)
+       end
+end
+
+-- Add a lease to state and invoke add_rule
+function add_lease(mac)
+       local key = uci:add("luci_splash", "lease")
+       uci:set("luci_splash", key, "mac", mac)
+       uci:set("luci_splash", key, "start", os.time())
+       add_rule(mac)
+end
+
+
+-- Remove a lease from state and invoke remove_rule
+function remove_lease(mac)
+       mac = mac:lower()
+
+       for k, v in pairs(uci:show("luci_splash").luci_splash) do
+               if v.mac:lower() == mac then
+                       remove_rule(mac)
+                       uci:del("luci_splash", k)
+               end
+       end
+end
+
+
+-- Add an iptables rule
+function add_rule(mac)
+       return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Remove an iptables rule
+function remove_rule(mac)
+       return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
+end
+
+
+-- Check whether a MAC-Address is listed in the lease state list
+function haslease(mac)
+       mac = mac:lower()
+       
+       for k, v in pairs(uci:show("luci_splash").luci_splash) do
+               if v[".type"] == "lease" and v.mac and v.mac:lower() == mac then
+                       return true
+               end
+       end
+       
+       return false
+end
+
+
+-- Check whether a MAC-Address is whitelisted
+function iswhitelisted(mac)
+       mac = mac:lower()
+       
+       for k, v in pairs(uci:show("luci_splash").luci_splash) do
+               if v[".type"] == "whitelist" and v.mac and v.mac:lower() == mac then
+                       return true
+               end
+       end
+       
+       return false
+end
+
+
+-- Returns a list of MAC-Addresses for which a rule is existing
+function listrules()
+       local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |"
+       cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+"
+       return ffluci.util.split(ffluci.sys.exec(cmd))
+end
+
+
+-- Synchronise leases, remove abandoned rules
+function sync()
+       local written = {}
+       local time = os.time()
+       
+       -- Current leases in state files
+       local leases = uci:show("luci_splash").luci_splash
+       
+       -- Convert leasetime to seconds
+       local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600
+       
+       -- Clean state file
+       uci:revert("luci_splash")
+       
+       
+       -- For all leases
+       for k, v in pairs(uci:show("luci_splash")) do
+               if v[".type"] == "lease" then
+                       if os.difftime(time, tonumber(v.start)) > leasetime then
+                               -- Remove expired
+                               remove_rule(v.mac)
+                       else
+                               -- Rewrite state
+                               local n = uci:add("luci_splash", "lease")
+                               uci:set("luci_splash", n, "mac", v.mac)
+                               uci:set("luci_splash", n, "start", v.start)
+                               written[v.mac] = 1
+                       end
+               end
+       end
+       
+       
+       -- Delete rules without state
+       for i, r in ipairs(listrules()) do
+               if #r > 0 and not written[r] then
+                       remove_rule(r)
+               end
+       end
+end
+
+main(arg)
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi b/contrib/package/ffluci-splash/src/luci-splash/htdocs/cgi-bin/index.cgi
new file mode 100644 (file)
index 0000000..4cbddc0
--- /dev/null
@@ -0,0 +1,39 @@
+#!/usr/bin/haserl --shell=luac
+package.path  = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
+package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
+
+require("ffluci.http")
+require("ffluci.sys")
+require("ffluci.model.uci")
+
+local srv
+local ip = ffluci.http.remote_addr()
+for k, v in pairs(ffluci.model.uci.show("network").network) do
+       if v[".type"] == "interface" and v.ipaddr then
+               local p = ffluci.sys.net.mask4prefix(v.netmask)
+               if ffluci.sys.net.belongs(ip, v.ipaddr, p) then
+                       srv = v.ipaddr
+                       break
+               end
+       end
+end
+
+if not srv then
+       ffluci.http.textheader()
+       return print("Unable to detect network settings!")
+end
+
+local action = "splash"
+
+local mac = ffluci.sys.net.ip4mac(ip)
+if not mac then
+       action = "unknown"
+end
+
+local status = ffluci.sys.exec("luci-splash status "..mac)
+
+if status == "whitelisted" or status == "lease" then
+       action = "allowed"
+end
+
+ffluci.http.redirect("http://" .. srv .. "/cgi-bin/luci-splash/" .. action)
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html b/contrib/package/ffluci-splash/src/luci-splash/htdocs/index.html
new file mode 100644 (file)
index 0000000..58387a5
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="refresh" content="0; URL=/cgi-bin/index.cgi" />
+</head>
+<body style="background-color: black">
+<a style="color: white; text-decoration: none" href="/cgi-bin/index.cgi">FFLuCI - Freifunk Lua Configuration Interface</a>
+</body>
+</html>
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash.cron b/contrib/package/ffluci-splash/src/luci_splash.cron
new file mode 100644 (file)
index 0000000..eae4294
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ "$(date +%M | cut -c2)" == "5" ] && luci-splash sync
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash.init b/contrib/package/ffluci-splash/src/luci_splash.init
new file mode 100644 (file)
index 0000000..a7bb4ab
--- /dev/null
@@ -0,0 +1,88 @@
+#!/bin/sh /etc/rc.common
+START=70
+
+iface_add() {
+       local cfg="$1"
+       
+       config_get net "$cfg" network
+       [ -n "$net" ] || return 0
+       
+       config_get iface "$net" ifname
+       [ -n "$iface" ] || return 0
+       iface="${iface%%:*}"
+       
+       config_get ipaddr "$net" ipaddr
+       [ -n "$ipaddr" ] || return 0
+       
+       config_get netmask "$net" netmask
+       [ -n "$netmask" ] || return 0
+       
+       eval "$(ipcalc.sh $ipaddr $netmask)"
+       
+       iptables -t nat -A luci_splash -i "$iface" -s "$IP/$PREFIX" -j luci_splash_portal
+       iptables -t nat -A luci_splash_portal -i "$iface" -s "$IP/$PREFIX" -d "$ipaddr" -p tcp --dport 80 -j RETURN  
+}
+
+blacklist_add() {
+       local cfg="$1"
+       
+       config_get mac "$cfg" mac
+       [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j DROP
+}
+
+whitelist_add() {
+       local cfg="$1"
+       
+       config_get mac "$cfg" mac
+       [ -n "$mac" ] && iptables -t nat -A luci_splash_portal -m mac --mac-source "$mac" -j RETURN
+}
+
+start() {
+       ### Read chains from config
+       include /lib/network
+       scan_interfaces
+       config_load luci_splash
+       
+       ### Create subchains
+       iptables -t nat -N luci_splash
+       iptables -t nat -N luci_splash_portal
+       iptables -t nat -N luci_splash_leases
+       
+       ### Build the main and portal rule
+       config_foreach blacklist_add blacklist
+       config_foreach whitelist_add whitelist
+       config_foreach iface_add iface
+       
+       ### Build the portal rule
+       iptables -t nat -A luci_splash_portal -p udp --dport 53 -j RETURN
+       iptables -t nat -A luci_splash_portal -j luci_splash_leases
+       
+       ### Build the leases rule
+       iptables -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082
+       iptables -t nat -A luci_splash_leases -j DROP
+       
+       ### Start the splash httpd
+       httpd -c /etc/luci_splash_httpd.conf -p 8082 -h /usr/lib/luci-splash/htdocs
+       
+       ### Sync leases
+       /usr/lib/luci-splash/sync.lua
+       
+       ### Hook in the chain
+       iptables -t nat -A prerouting_rule -j luci_splash
+}
+
+stop() {
+       ### Hook out the chain
+       iptables -t nat -D prerouting_rule -j luci_splash
+       
+       ### Clear subchains
+       iptables -t nat -F luci_splash_leases
+       iptables -t nat -F luci_splash_portal
+       iptables -t nat -F luci_splash  
+       
+       ### Delete subchains
+       iptables -t nat -X luci_splash_leases
+       iptables -t nat -X luci_splash_portal
+       iptables -t nat -X luci_splash
+}
+
diff --git a/contrib/package/ffluci-splash/src/luci_splash.uci b/contrib/package/ffluci-splash/src/luci_splash.uci
new file mode 100644 (file)
index 0000000..c4cfef5
--- /dev/null
@@ -0,0 +1,2 @@
+config core general
+       option leasetime 1
\ No newline at end of file
diff --git a/contrib/package/ffluci-splash/src/luci_splash_httpd.conf b/contrib/package/ffluci-splash/src/luci_splash_httpd.conf
new file mode 100644 (file)
index 0000000..6007e80
--- /dev/null
@@ -0,0 +1 @@
+E404:index.html
\ No newline at end of file
diff --git a/contrib/package/ffluci-system-addons/Makefile b/contrib/package/ffluci-system-addons/Makefile
new file mode 100644 (file)
index 0000000..3d38bd3
--- /dev/null
@@ -0,0 +1,32 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ffluci-system-addons
+PKG_VERSION:=0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+PKG_INSTALL_DIR:=$(PKG_BUILD_DIR)/ipkg-install
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ffluci-splash
+  SECTION:=admin
+  CATEGORY:=Administration
+  SUBMENU:=FFLuCI
+  TITLE:=FFLuCI System Addons for Kamikaze
+endef
+
+define Build/Compile
+endef
+
+define Package/ffluci-system-addons/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       $(INSTALL_DIR) $(1)/etc/crontabs
+       $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
+
+       $(INSTALL_BIN) ./src/run-parts $(1)/usr/bin
+       $(CP) ./src/root.crontab $(1)/etc/crontabs/root
+       $(CP) ./src/hotplug.d-20-aliases $(1)/etc/hotplug.d/iface/20-aliases
+endef
+
+$(eval $(call BuildPackage,ffluci-system-addons))
diff --git a/contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases b/contrib/package/ffluci-system-addons/src/hotplug.d-20-aliases
new file mode 100644 (file)
index 0000000..b9986e3
--- /dev/null
@@ -0,0 +1,24 @@
+add_aliases() {
+        local config="$1"
+
+        config_get base "$INTERFACE" ifname
+        config_get iface "$config" ifname
+        config_get ipaddr "$config" ipaddr
+        config_get auto "$config" auto
+
+        [ "${iface%%:*}" == "$base" -a "$iface" != "$base" ] && {
+                case "$auto" in
+                        1|on|enabled) setup_interface "$iface" "$config";;
+                        *) return 1;;
+                esac
+        }
+}
+
+
+case "$ACTION" in
+        ifup)
+                include /lib/network
+                scan_interfaces
+                config_foreach "add_aliases" interface
+        ;;
+esac
diff --git a/contrib/package/ffluci-system-addons/src/root.crontab b/contrib/package/ffluci-system-addons/src/root.crontab
new file mode 100644 (file)
index 0000000..6e2e417
--- /dev/null
@@ -0,0 +1,3 @@
+0-59/1 * * * *  /usr/bin/run-parts /etc/cron.minutely
+0 * * * *       /usr/bin/run-parts /etc/cron.hourly
+0 0 * * *       /usr/bin/run-parts /etc/cron.daily
diff --git a/contrib/package/ffluci-system-addons/src/run-parts b/contrib/package/ffluci-system-addons/src/run-parts
new file mode 100644 (file)
index 0000000..0f0cbbd
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+set +e
+
+if [ $# -lt 1 ]; then
+        echo "Usage: run-parts <dir>"
+        exit 1
+fi
+
+if [ ! -d $1 ]; then
+        echo "Not a directory: $1"
+        exit 1
+fi
+
+for i in $1/*; do
+       [ -x $i ] && $i
+done
+       
+exit 0
\ No newline at end of file
index aa6050d..1c45695 100644 (file)
@@ -26,7 +26,7 @@ define Package/ffluci
   CATEGORY:=Administration
   TITLE:=FFLuCI
   SUBMENU:=FFLuCI
-  DEPENDS:=+luaposix +haserl-lua
+  DEPENDS:=+luaposix +haserl-lua +ffluci-system-addons
   MAINTAINER:=Steven Barth <steven-at-midlink-dot-org>
 endef
 
@@ -50,7 +50,6 @@ define Package/ffluci/install
        
        $(CP) $(PKG_BUILD_DIR)/core/dist/* $(1)/usr/lib/lua/ -R
        $(CP) $(PKG_BUILD_DIR)/core/contrib/uci/* $(1)/etc/config/
-       $(CP) $(PKG_BUILD_DIR)/core/contrib/hotplug.d-20-aliases $(1)/etc/hotplug.d/iface/20-aliases -R
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci $(1)/www/cgi-bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/ffluci-upload $(1)/www/cgi-bin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/core/contrib/index.cgi $(1)/www/cgi-bin
diff --git a/core/contrib/hotplug.d-20-aliases b/core/contrib/hotplug.d-20-aliases
deleted file mode 100644 (file)
index b9986e3..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-add_aliases() {
-        local config="$1"
-
-        config_get base "$INTERFACE" ifname
-        config_get iface "$config" ifname
-        config_get ipaddr "$config" ipaddr
-        config_get auto "$config" auto
-
-        [ "${iface%%:*}" == "$base" -a "$iface" != "$base" ] && {
-                case "$auto" in
-                        1|on|enabled) setup_interface "$iface" "$config";;
-                        *) return 1;;
-                esac
-        }
-}
-
-
-case "$ACTION" in
-        ifup)
-                include /lib/network
-                scan_interfaces
-                config_foreach "add_aliases" interface
-        ;;
-esac
index a3603d7..292e8f2 100644 (file)
@@ -17,7 +17,7 @@ config extern flash_keep
 config event uci_oncommit
         option network "/etc/init.d/network restart"
         option wireless        "/etc/init.d/network restart"
-        option olsr            "/etc/init.d/olsrd restart"
+        option olsr            "reboot"
         option dhcp            "/etc/init.d/dnsmasq restart"
         option luci_fw  "/etc/init.d/luci_fw restart"
         option dropbear "/etc/init.d/dropbear restart"
index cde1877..8aa77cf 100644 (file)
@@ -134,6 +134,19 @@ function net.devices()
        return devices
 end
 
+-- Returns the MAC-Address belonging to the given IP-Address
+function net.ip4mac(ip)
+       local mac = nil
+       
+       for i, l in ipairs(net.arptable()) do
+               if l["IP address"] == ip then
+                       mac = l["HW address"]
+               end
+       end
+       
+       return mac
+end
+
 -- Returns the prefix to a given netmask
 function net.mask4prefix(mask)
        local bin = net.ip4bin(mask)
index 57fa4b6..188ad7a 100644 (file)
@@ -1,4 +1,4 @@
 #!/bin/sh
 echo "Status: 302 Found"
-echo "Location: ffluci/public/splash$PATH_INFO"
+echo "Location: /cgi-bin/ffluci/splash/splash$PATH_INFO"
 echo
\ No newline at end of file