fc3a0c8da50933443cf56b192a44c466d778843c
[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
11
12 function main(argv)
13 local cmd = argv[1]
14 local arg = argv[2]
15
16 if cmd == "status" then
17 if not arg then
18 os.exit(1)
19 end
20
21 if iswhitelisted(arg) then
22 print("whitelisted")
23 os.exit(0)
24 end
25
26 if haslease(arg) then
27 print("lease")
28 os.exit(0)
29 end
30
31 print("unknown")
32 os.exit(0)
33 elseif cmd == "add" then
34 if not arg then
35 os.exit(1)
36 end
37
38 if not haslease(arg) then
39 add_lease(arg)
40 else
41 print("already leased!")
42 os.exit(2)
43 end
44 os.exit(0)
45 elseif cmd == "remove" then
46 if not arg then
47 os.exit(1)
48 end
49
50 remove_lease(arg)
51 os.exit(0)
52 elseif cmd == "sync" then
53 sync()
54 os.exit(0)
55 else
56 print("Usage: " .. argv[0] .. " <status|add|remove|sync> [MAC]")
57 os.exit(1)
58 end
59 end
60
61 -- Add a lease to state and invoke add_rule
62 function add_lease(mac)
63 uci.section("luci_splash", "lease", nil, {
64 mac = mac,
65 start = os.time()
66 })
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(uci.get("luci_splash", "general", "leasetime")) * 3600
152
153 -- Clean state file
154 uci.load("luci_splash")
155 uci.revert("luci_splash")
156
157
158 -- For all leases
159 for k, v in pairs(leases) do
160 if v[".type"] == "lease" then
161 if os.difftime(time, tonumber(v.start)) > leasetime then
162 -- Remove expired
163 remove_rule(v.mac)
164 else
165 -- Rewrite state
166 uci.section("luci_splash", "lease", nil, {
167 mac = v.mac,
168 start = v.start
169 })
170 written[v.mac:lower()] = 1
171 end
172 end
173 end
174
175
176 -- Delete rules without state
177 for i, r in ipairs(listrules()) do
178 if #r > 0 and not written[r:lower()] then
179 remove_rule(r)
180 end
181 end
182
183 uci.save("luci_splash")
184 end
185
186 main(arg)