applications/siitwizard: fix duplicate field name
[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
36 lanmsk = f:field(Value, "lanmask", "Lokale LAN Netzmaske")
37 lanmsk.value = "255.255.255.0"
38
39 gv4msk = f:field(Value, "gv4mask", "Globale LAN Netzmaske")
40 gv4msk.value = "255.255.0.0"
41
42
43 -------------------- Control --------------------
44 LL_PREFIX = luci.ip.IPv6("fe80::/64")
45
46 --
47 -- find link-local address
48 --
49 function find_ll()
50         for _, r in ipairs(luci.sys.net.routes6()) do
51                 if LL_PREFIX:contains(r.dest) and r.dest:higher(LL_PREFIX) then
52                         return r.dest:sub(LL_PREFIX)
53                 end
54         end
55         return luci.ip.IPv6("::")
56 end
57
58
59
60 function f.handle(self, state, data)
61         if state == FORM_VALID then
62                 luci.http.redirect(luci.dispatcher.build_url("admin", "uci", "changes"))
63                 return false
64         elseif state == FORM_INVALID then
65                 self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen."
66         end
67         return true
68 end
69
70 function mode.write(self, section, value)
71
72         -- lan interface
73         local lan_net = luci.ip.IPv4(
74                 lanip:formvalue(section) or "192.168.1.1",
75                 lanmsk:formvalue(section) or "255.255.255.0"
76         )
77
78         local gv4_net = luci.ip.IPv4(
79                 lanip:formvalue(section) or "192.168.1.1",
80                 gv4msk:formvalue(section) or "255.255.0.0"
81         )
82
83         --
84         -- Configure wifi device
85         --
86         local wifi_device  = dev:formvalue(section)
87         local wifi_essid   = uci:get("siit", "wifi", "essid")   or "6mesh.freifunk.net"
88         local wifi_bssid   = uci:get("siit", "wifi", "bssid")   or "02:ca:ff:ee:ba:be"
89         local wifi_channel = uci:get("siit", "wifi", "channel") or "1"
90
91         -- nuke old device definition
92         uci:delete_all("wireless", "wifi-iface",
93                 function(s) return s.device == wifi_device end )
94
95         uci:delete_all("network", "interface",
96                 function(s) return s['.name'] == wifi_device end )
97
98         -- create wifi device definition
99         uci:tset("wireless", wifi_device, {
100                 disabled  = 0,
101                 channel   = wifi_channel,
102 --              txantenna = 1,
103 --              rxantenna = 1,
104 --              diversity = 0
105         })
106
107         uci:section("wireless", "wifi-iface", nil, {
108                 encryption = "none",
109                 mode       = "adhoc",
110                 network    = wifi_device,
111                 device     = wifi_device,
112                 ssid       = wifi_essid,
113                 bssid      = wifi_bssid,
114         })
115
116
117         --
118         -- Determine defaults
119         --
120         local ula_prefix  = uci:get("siit", "ipv6", "ula_prefix")  or "fd00::"
121         local ula_global  = uci:get("siit", "ipv6", "ula_global")  or "00ca:ffee:babe::"                -- = Freifunk
122         local ula_subnet  = uci:get("siit", "ipv6", "ula_subnet")  or "0000:0000:0000:4223::"   -- = Berlin
123         local siit_prefix = uci:get("siit", "ipv6", "siit_prefix") or "::ffff:0000:0000"
124
125         -- Find wifi interface
126         local device = dev:formvalue(section)
127
128         --
129         -- Generate ULA
130         --
131         local ula = luci.ip.IPv6("::/64")
132
133         for _, prefix in ipairs({ ula_prefix, ula_global, ula_subnet }) do
134                 ula = ula:add(luci.ip.IPv6(prefix))
135         end
136
137         ula = ula:add(find_ll())
138
139
140         --
141         -- Gateway mode
142         --
143         --      * wan port is dhcp, lan port is 172.23.1.1/24
144         --      * siit0 gets a dummy address: 169.254.42.42
145         --      * wl0 gets an ipv6 address, in this case the fdca:ffee:babe::1:1/64
146         --      * we do a ::ffff:ffff:0/96 route into siit0, so everything from 6mesh goes into translation.
147         --      * an HNA6 of ::ffff:ffff:0:0/96 announces the mapped 0.0.0.0/0 ipv4 space.
148         --      * MTU on WAN, LAN down to 1400, ipv6 headers are slighly larger.
149
150         if value == "gateway" then
151
152
153                 -- wan mtu
154                 uci:set("network", "wan", "mtu", 1400)
155
156                 -- lan settings
157                 uci:tset("network", "lan", {
158                         mtu     = 1400,
159                         ipaddr  = lan_net:host():string(),
160                         netmask = lan_net:mask():string()
161                 })
162
163                 -- use full siit subnet
164                 siit_route = luci.ip.IPv6(siit_prefix .. "/96")
165
166                 -- v4 <-> siit route
167                 uci:delete_all("network", "route",
168                         function(s) return s.interface == "siit0" end)
169
170                 uci:section("network", "route", nil, {
171                         interface = "siit0",
172                         target    = gv4_net:host():string(),
173                         netmask   = gv4_net:mask():string()
174                 })
175
176         --
177         -- Client mode
178         --
179         --      * 172.23.2.1/24 on its lan, fdca:ffee:babe::1:2 on wl0 and the usual dummy address on siit0.
180         --      * 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.
181         --      * same route as HNA6 announcement to catch the traffic out of the mesh.
182         --      * Also, MTU on LAN reduced to 1400.
183
184         else
185
186                 -- lan settings
187                 uci:tset("network", "lan", {
188                         mtu     = 1400,
189                         ipaddr  = lan_net:host():string(),
190                         netmask = lan_net:mask():string()
191                 })
192
193                 -- derive siit subnet from lan config
194                 siit_route = luci.ip.IPv6(
195                         siit_prefix .. "/" .. (96 + lan_net:prefix())
196                 ):add(lan_net[2])
197
198                 -- ipv4 <-> siit route
199                 uci:delete_all("network", "route",
200                         function(s) return s.interface == "siit0" end)
201
202                 -- XXX: kind of a catch all, gv4_net would be better
203                 --      but does not cover non-local v4 space
204                 uci:section("network", "route", nil, {
205                         interface = "siit0",
206                         target    = "0.0.0.0",
207                         netmask   = "0.0.0.0"
208                 })
209         end
210
211         -- setup the firewall
212         uci:delete_all("firewall", "zone",
213                 function(s) return (
214                         s['.name'] == "siit0" or s.name == "siit0" or
215                         s.network == "siit0" or s['.name'] == wifi_device or
216                         s.name == wifi_device or s.network == wifi_device
217                 ) end)
218
219         uci:delete_all("firewall", "forwarding",
220                 function(s) return (
221                         s.src == wifi_device and s.dest == "siit0" or
222                         s.dest == wifi_device and s.src == "siit0" or
223                         s.src == "lan" and s.dest == "siit0" or
224                         s.dest == "lan" and s.src == "siit0"
225                 ) end)
226
227         uci:section("firewall", "zone", "siit0", {
228                 name    = "siit0",
229                 network = "siit0",
230                 input   = "ACCEPT",
231                 output  = "ACCEPT",
232                 forward = "ACCEPT"
233         })
234
235         uci:section("firewall", "zone", wifi_device, {
236                 name    = wifi_device,
237                 network = wifi_device,
238                 input   = "ACCEPT",
239                 output  = "ACCEPT",
240                 forward = "ACCEPT"
241         })
242
243         uci:section("firewall", "forwarding", nil, {
244                 src  = wifi_device,
245                 dest = "siit0"
246         })
247
248         uci:section("firewall", "forwarding", nil, {
249                 src  = "siit0",
250                 dest = wifi_device
251         })
252
253         uci:section("firewall", "forwarding", nil, {
254                 src  = "lan",
255                 dest = "siit0"
256         })
257
258         uci:section("firewall", "forwarding", nil, {
259                 src  = "siit0",
260                 dest = "lan"
261         })
262
263         -- siit0 interface
264         uci:delete_all("network", "interface",
265                 function(s) return ( s.ifname == "siit0" ) end)
266
267         uci:section("network", "interface", "siit0", {
268                 ifname  = "siit0",
269                 proto   = "static",
270                 ipaddr  = "169.254.42.42",
271                 netmask = "255.255.255.0"
272         })
273
274         -- siit0 route
275         uci:delete_all("network", "route6",
276                 function(s) return siit_route:contains(luci.ip.IPv6(s.target)) end)
277
278         uci:section("network", "route6", nil, {
279                 interface = "siit0",
280                 target    = siit_route:string()
281         })
282
283         -- create wifi network interface
284         uci:section("network", "interface", wifi_device, {
285                 proto   = "static",
286                 mtu     = 1400,
287                 ip6addr = ula:string()
288         })
289
290         -- nuke old olsrd interfaces
291         uci:delete_all("olsrd", "Interface",
292                 function(s) return s.interface == wifi_device end)
293
294         -- configure olsrd interface
295         uci:foreach("olsrd", "olsrd",
296                 function(s) uci:set("olsrd", s['.name'], "IpVersion", 6) end)
297
298         uci:section("olsrd", "Interface", nil, {
299                 ignore      = 0,
300                 interface   = wifi_device,
301                 Ip6AddrType = "global"
302         })
303
304         -- hna6
305         uci:delete_all("olsrd", "Hna6",
306                 function(s)
307                         if s.netaddr and s.prefix then
308                                 return siit_route:contains(luci.ip.IPv6(s.netaddr.."/"..s.prefix))
309                         end
310                 end)
311
312         uci:section("olsrd", "Hna6", nil, {
313                 netaddr = siit_route:host():string(),
314                 prefix  = siit_route:prefix()
315         })
316
317         uci:save("wireless")
318         uci:save("firewall")
319         uci:save("network")
320         uci:save("olsrd")
321 end
322
323 return f