* Merged Luci to use native UCI-library
[project/luci.git] / applications / luci-splash / root / usr / sbin / luci-splash
1 #!/usr/bin/lua
2
3 require("luci.http")
4 require("luci.sys")
5 require("luci.model.uci")
6
7 -- Init state session
8 luci.model.uci.set_savedir(luci.model.uci.savedir_state)
9 local uci = luci.model.uci
10 local cfg = uci.config
11
12
13 function main(argv)
14 local cmd = argv[1]
15 local arg = argv[2]
16
17 if cmd == "status" then
18 if not arg then
19 os.exit(1)
20 end
21
22 if iswhitelisted(arg) then
23 print("whitelisted")
24 os.exit(0)
25 end
26
27 if haslease(arg) then
28 print("lease")
29 os.exit(0)
30 end
31
32 print("unknown")
33 os.exit(0)
34 elseif cmd == "add" then
35 if not arg then
36 os.exit(1)
37 end
38
39 if not haslease(arg) then
40 add_lease(arg)
41 else
42 print("already leased!")
43 os.exit(2)
44 end
45 os.exit(0)
46 elseif cmd == "remove" then
47 if not arg then
48 os.exit(1)
49 end
50
51 remove_lease(arg)
52 os.exit(0)
53 elseif cmd == "sync" then
54 sync()
55 os.exit(0)
56 else
57 print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
58 os.exit(1)
59 end
60 end
61
62 -- Add a lease to state and invoke add_rule
63 function add_lease(mac)
64 cfg.luci_splash[""] = "lease"
65 cfg.luci_splash[""].mac = mac
66 cfg.luci_splash[""].start = os.time()
67 add_rule(mac)
68
69 uci.save()
70 end
71
72
73 -- Remove a lease from state and invoke remove_rule
74 function remove_lease(mac)
75 mac = mac:lower()
76
77 uci.foreach("luci_splash", "lease",
78 function (section)
79 if section.mac:lower() == mac then
80 remove_rule(mac)
81 uci.delete("luci_splash", section[".name"])
82 end
83 end)
84
85 uci.save()
86 end
87
88
89 -- Add an iptables rule
90 function add_rule(mac)
91 return os.execute("iptables -t nat -I luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
92 end
93
94
95 -- Remove an iptables rule
96 function remove_rule(mac)
97 return os.execute("iptables -t nat -D luci_splash_leases -m mac --mac-source '"..mac.."' -j RETURN")
98 end
99
100
101 -- Check whether a MAC-Address is listed in the lease state list
102 function haslease(mac)
103 mac = mac:lower()
104 local stat = false
105
106 uci.foreach("luci_splash", "lease",
107 function (section)
108 if section.mac:lower() == mac then
109 stat = true
110 return
111 end
112 end)
113
114 return stat
115 end
116
117
118 -- Check whether a MAC-Address is whitelisted
119 function iswhitelisted(mac)
120 mac = mac:lower()
121
122 uci.foreach("luci_splash", "whitelist",
123 function (section)
124 if section.mac:lower() == mac then
125 stat = true
126 return
127 end
128 end)
129
130 return false
131 end
132
133
134 -- Returns a list of MAC-Addresses for which a rule is existing
135 function listrules()
136 local cmd = "iptables -t nat -L luci_splash_leases | grep RETURN |"
137 cmd = cmd .. "egrep -io [0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+:[0-9a-f]+"
138 return luci.util.split(luci.sys.exec(cmd))
139 end
140
141
142 -- Synchronise leases, remove abandoned rules
143 function sync()
144 local written = {}
145 local time = os.time()
146
147 -- Current leases in state files
148 local leases = uci.get_all("luci_splash")
149
150 -- Convert leasetime to seconds
151 local leasetime = tonumber(cfg.luci_splash.general.leasetime) * 3600
152
153 -- Clean state file
154 uci.revert("luci_splash")
155
156
157 -- For all leases
158 for k, v in pairs(leases) do
159 if v[".type"] == "lease" then
160 if os.difftime(time, tonumber(v.start)) > leasetime then
161 -- Remove expired
162 remove_rule(v.mac)
163 else
164 -- Rewrite state
165 cfg.luci_splash[""] = "lease"
166 cfg.luci_splash[""].mac = v.mac
167 cfg.luci_splash[""].start = v.start
168 written[v.mac:lower()] = 1
169 end
170 end
171 end
172
173
174 -- Delete rules without state
175 for i, r in ipairs(listrules()) do
176 if #r > 0 and not written[r:lower()] then
177 remove_rule(r)
178 end
179 end
180
181 uci.save("luci_splash")
182 end
183
184 main(arg)