2 package.path = "/usr/lib/lua/?.lua;/usr/lib/lua/?/init.lua;" .. package.path
3 package.cpath = "/usr/lib/lua/?.so;" .. package.cpath
7 require("ffluci.model.uci")
10 uci = ffluci.model.uci.Session("/var/state")
18 print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
20 elseif cmd == "status" then
25 if iswhitelisted(arg) then
37 elseif cmd == "add" then
42 if not haslease(arg) then
45 print("already leased!")
49 elseif cmd == "remove" then
56 elseif cmd == "sync" then
62 -- Add a lease to state and invoke add_rule
63 function add_lease(mac)
64 local key = uci:add("luci_splash", "lease")
65 uci:set("luci_splash", key, "mac", mac)
66 uci:set("luci_splash", key, "start", os.time())
71 -- Remove a lease from state and invoke remove_rule
72 function remove_lease(mac)
75 for k, v in pairs(uci:show("luci_splash").luci_splash) do
76 if v.mac:lower() == mac then
78 uci:del("luci_splash", k)
84 -- Add an iptables rule
85 function add_rule(mac)
86 return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
90 -- Remove an iptables rule
91 function remove_rule(mac)
92 return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
96 -- Check whether a MAC-Address is listed in the lease state list
97 function haslease(mac)
100 for k, v in pairs(uci:show("luci_splash").luci_splash) do
101 if v[".type"] == "lease" and v.mac and v.mac:lower() == mac then
110 -- Check whether a MAC-Address is whitelisted
111 function iswhitelisted(mac)
114 for k, v in pairs(uci:show("luci_splash").luci_splash) do
115 if v[".type"] == "whitelist" and v.mac and v.mac:lower() == mac then
124 -- Returns a list of MAC-Addresses for which a rule is existing
126 local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |"
127 cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+"
128 return ffluci.util.split(ffluci.sys.exec(cmd))
132 -- Synchronise leases, remove abandoned rules
135 local time = os.time()
137 -- Current leases in state files
138 local leases = uci:show("luci_splash").luci_splash
140 -- Convert leasetime to seconds
141 local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600
144 uci:revert("luci_splash")
148 for k, v in pairs(uci:show("luci_splash")) do
149 if v[".type"] == "lease" then
150 if os.difftime(time, tonumber(v.start)) > leasetime then
155 local n = uci:add("luci_splash", "lease")
156 uci:set("luci_splash", n, "mac", v.mac)
157 uci:set("luci_splash", n, "start", v.start)
158 written[v.mac:lower()] = 1
164 -- Delete rules without state
165 for i, r in ipairs(listrules()) do
166 if #r > 0 and not written[r:lower()] then