applications/siitwizard:
[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("gateway", "Gateway")
25 mode:value("client", "Client")
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         end
172
173         -- siit0 interface
174         uci:delete_all("network", "interface",
175                 function(s) return ( s.ifname == "siit0" ) end)
176
177         uci:section("network", "interface", "siit0", {
178                 ifname  = "siit0",
179                 proto   = "static",
180                 ipaddr  = "169.254.42.42",
181                 netmask = "255.255.255.0"
182         })
183
184         -- siit0 route
185         uci:delete_all("network", "route6",
186                 function(s) return siit_route:contains(luci.ip.IPv6(s.target)) end)
187
188         uci:section("network", "route6", nil, {
189                 interface = "siit0",
190                 target    = siit_route:string()
191         })
192
193         -- create wifi network interface
194         uci:section("network", "interface", wifi_device, {
195                 proto   = "static",
196                 mtu     = 1400,
197                 ip6addr = ula:string()
198         })
199
200         -- nuke old olsrd interfaces
201         uci:delete_all("olsrd", "Interface",
202                 function(s) return s.interface == wifi_device end)
203
204         -- configure olsrd interface
205         uci:foreach("olsrd", "olsrd",
206                 function(s) uci:set("olsrd", s['.name'], "IpVersion", 6) end)
207
208         uci:section("olsrd", "Interface", nil, {
209                 ignore      = 0,
210                 interface   = wifi_device,
211                 Ip6AddrType = "global"
212         })
213
214         -- hna6
215         uci:delete_all("olsrd", "Hna6",
216                 function(s)
217                         if s.netaddr and s.prefix then
218                                 return siit_route:contains(luci.ip.IPv6(s.netaddr.."/"..s.prefix))
219                         end
220                 end)
221
222         uci:section("olsrd", "Hna6", nil, {
223                 netaddr = siit_route:host():string(),
224                 prefix  = siit_route:prefix()
225         })
226
227         uci:save("wireless")
228         uci:save("network")
229         uci:save("olsrd")
230 end
231
232 return f