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