applications/siitwizard: also setup v4 routes and firewall
[project/luci.git] / applications / luci-siitwizard / luasrc / model / cbi / siitwizard.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14
15 ]]--
16
17 local uci = require "luci.model.uci".cursor()
18
19 -------------------- View --------------------
20 f = SimpleForm("siitwizward", "4over6-Assistent",
21 "Dieser Assistent unterstüzt bei der Einrichtung von IPv4-over-IPv6 Translation.")
22
23 mode = f:field(ListValue, "mode", "Betriebsmodus")
24 mode:value("client", "Client")
25 mode:value("gateway", "Gateway")
26
27 dev = f:field(ListValue, "device", "WLAN-Gerät")
28 uci:foreach("wireless", "wifi-device",
29 function(section)
30 dev:value(section[".name"])
31 end)
32
33 lanip = f:field(Value, "ipaddr", "LAN IP Adresse")
34 lanip.value = "172.23.1.1"
35 lanip:depends("mode", "client")
36
37 lanmsk = f:field(Value, "netmask", "LAN Netzmaske")
38 lanmsk.value = "255.255.0.0"
39 lanmsk:depends("mode", "client")
40
41
42 -------------------- Control --------------------
43 LL_PREFIX = luci.ip.IPv6("fe80::/64")
44
45 --
46 -- find link-local address
47 --
48 function find_ll()
49 for _, r in ipairs(luci.sys.net.routes6()) do
50 if LL_PREFIX:contains(r.dest) and r.dest:higher(LL_PREFIX) then
51 return r.dest:sub(LL_PREFIX)
52 end
53 end
54 return luci.ip.IPv6("::")
55 end
56
57
58
59 function f.handle(self, state, data)
60 if state == FORM_VALID then
61 luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes"))
62 return false
63 elseif state == FORM_INVALID then
64 self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen."
65 end
66 return true
67 end
68
69 function mode.write(self, section, value)
70
71 --
72 -- Configure wifi device
73 --
74 local wifi_device = dev:formvalue(section)
75 local wifi_essid = uci:get("siit", "wifi", "essid") or "6mesh.freifunk.net"
76 local wifi_bssid = uci:get("siit", "wifi", "bssid") or "02:ca:ff:ee:ba:be"
77 local wifi_channel = uci:get("siit", "wifi", "channel") or "1"
78
79 -- nuke old device definition
80 uci:delete_all("wireless", "wifi-iface",
81 function(s) return s.device == wifi_device end )
82
83 uci:delete_all("network", "interface",
84 function(s) return s['.name'] == wifi_device end )
85
86 -- create wifi device definition
87 uci:tset("wireless", wifi_device, {
88 disabled = 0,
89 channel = wifi_channel,
90 -- txantenna = 1,
91 -- rxantenna = 1,
92 -- diversity = 0
93 })
94
95 uci:section("wireless", "wifi-iface", nil, {
96 encryption = "none",
97 mode = "adhoc",
98 network = wifi_device,
99 device = wifi_device,
100 ssid = wifi_essid,
101 bssid = wifi_bssid,
102 })
103
104
105 --
106 -- Determine defaults
107 --
108 local ula_prefix = uci:get("siit", "ipv6", "ula_prefix") or "fd00::"
109 local ula_global = uci:get("siit", "ipv6", "ula_global") or "00ca:ffee:babe::" -- = Freifunk
110 local ula_subnet = uci:get("siit", "ipv6", "ula_subnet") or "0000:0000:0000:4223::" -- = Berlin
111 local siit_prefix = uci:get("siit", "ipv6", "siit_prefix") or "::ffff:0000:0000"
112
113 -- Find wifi interface
114 local device = dev:formvalue(section)
115
116 --
117 -- Generate ULA
118 --
119 local ula = luci.ip.IPv6("::/64")
120
121 for _, prefix in ipairs({ ula_prefix, ula_global, ula_subnet }) do
122 ula = ula:add(luci.ip.IPv6(prefix))
123 end
124
125 ula = ula:add(find_ll())
126
127
128 --
129 -- Gateway mode
130 --
131 -- * wan port is dhcp, lan port is 172.23.1.1/24
132 -- * siit0 gets a dummy address: 169.254.42.42
133 -- * wl0 gets an ipv6 address, in this case the fdca:ffee:babe::1:1/64
134 -- * we do a ::ffff:ffff:0/96 route into siit0, so everything from 6mesh goes into translation.
135 -- * an HNA6 of ::ffff:ffff:0:0/96 announces the mapped 0.0.0.0/0 ipv4 space.
136 -- * MTU on WAN, LAN down to 1400, ipv6 headers are slighly larger.
137
138 if value == "gateway" then
139
140 uci:set("network", "wan", "mtu", 1400)
141
142 -- use full siit subnet
143 siit_route = luci.ip.IPv6(siit_prefix .. "/96")
144
145 --
146 -- Client mode
147 --
148 -- * 172.23.2.1/24 on its lan, fdca:ffee:babe::1:2 on wl0 and the usual dummy address on siit0.
149 -- * we do a ::ffff:ffff:172.13.2.0/120 to siit0, because in this case, only traffic directed to clients needs to go into translation.
150 -- * same route as HNA6 announcement to catch the traffic out of the mesh.
151 -- * Also, MTU on LAN reduced to 1400.
152
153 else
154 -- lan interface
155 local lan_net = luci.ip.IPv4(
156 lanip:formvalue(section) or "192.168.1.1",
157 lanmsk:formvalue(section) or "255.255.255.0"
158 )
159
160 uci:tset("network", "lan", {
161 mtu = 1400,
162 ipaddr = lan_net:host():string(),
163 netmask = lan_net:mask():string()
164 })
165
166 -- derive siit subnet from lan config
167 siit_route = luci.ip.IPv6(
168 siit_prefix .. "/" .. (96 + lan_net:prefix())
169 ):add(lan_net[2])
170
171 -- ipv4 <-> siit route
172 uci:delete_all("network", "route",
173 function(s) return s.interface == "siit0" end)
174
175 uci:section("network", "route", nil, {
176 interface = "siit0",
177 target = "0.0.0.0",
178 netmask = "0.0.0.0"
179 })
180 end
181
182 -- setup the firewall
183 uci:delete_all("firewall", "zone",
184 function(s) return (
185 s['.name'] == "siit0" or s.name == "siit0" or
186 s.network == "siit0" or s['.name'] == wifi_device or
187 s.name == wifi_device or s.network == wifi_device
188 ) end)
189
190 uci:delete_all("firewall", "forwarding",
191 function(s) return (
192 s.src == wifi_device and s.dest == "siit0" or
193 s.dest == wifi_device and s.src == "siit0"
194 ) end)
195
196 uci:section("firewall", "zone", "siit0", {
197 name = "siit0",
198 network = "siit0",
199 input = "ACCEPT",
200 output = "ACCEPT",
201 forward = "ACCEPT"
202 })
203
204 uci:section("firewall", "zone", wifi_device, {
205 name = wifi_device,
206 network = wifi_device,
207 input = "ACCEPT",
208 output = "ACCEPT",
209 forward = "ACCEPT"
210 })
211
212 uci:section("firewall", "forwarding", nil, {
213 src = wifi_device,
214 dest = "siit0"
215 })
216
217 uci:section("firewall", "forwarding", nil, {
218 src = "siit0",
219 dest = wifi_device
220 })
221
222 -- siit0 interface
223 uci:delete_all("network", "interface",
224 function(s) return ( s.ifname == "siit0" ) end)
225
226 uci:section("network", "interface", "siit0", {
227 ifname = "siit0",
228 proto = "static",
229 ipaddr = "169.254.42.42",
230 netmask = "255.255.255.0"
231 })
232
233 -- siit0 route
234 uci:delete_all("network", "route6",
235 function(s) return siit_route:contains(luci.ip.IPv6(s.target)) end)
236
237 uci:section("network", "route6", nil, {
238 interface = "siit0",
239 target = siit_route:string()
240 })
241
242 -- create wifi network interface
243 uci:section("network", "interface", wifi_device, {
244 proto = "static",
245 mtu = 1400,
246 ip6addr = ula:string()
247 })
248
249 -- nuke old olsrd interfaces
250 uci:delete_all("olsrd", "Interface",
251 function(s) return s.interface == wifi_device end)
252
253 -- configure olsrd interface
254 uci:foreach("olsrd", "olsrd",
255 function(s) uci:set("olsrd", s['.name'], "IpVersion", 6) end)
256
257 uci:section("olsrd", "Interface", nil, {
258 ignore = 0,
259 interface = wifi_device,
260 Ip6AddrType = "global"
261 })
262
263 -- hna6
264 uci:delete_all("olsrd", "Hna6",
265 function(s)
266 if s.netaddr and s.prefix then
267 return siit_route:contains(luci.ip.IPv6(s.netaddr.."/"..s.prefix))
268 end
269 end)
270
271 uci:section("olsrd", "Hna6", nil, {
272 netaddr = siit_route:host():string(),
273 prefix = siit_route:prefix()
274 })
275
276 uci:save("wireless")
277 uci:save("firewall")
278 uci:save("network")
279 uci:save("olsrd")
280 end
281
282 return f