47118d19b7a4a73a7c58d2ebb54839bb42bf267e
[project/luci.git] / applications / luci-ffwizard / luasrc / model / cbi / ffwizard.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 Copyright 2011 Patrick Grimm <patrick@pberg.freifunk.net>
7
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 $Id$
15
16 ]]--
17
18
19 local uci = require "luci.model.uci".cursor()
20 local uci_state = require "luci.model.uci".cursor_state()
21 local tools = require "luci.tools.ffwizard"
22 local util = require "luci.util"
23 local sys = require "luci.sys"
24 local ip = require "luci.ip"
25 local fs  = require "nixio.fs"
26
27 local has_pptp  = fs.access("/usr/sbin/pptp")
28 local has_pppoe = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
29 local has_l2gvpn  = fs.access("/usr/sbin/node")
30 local has_radvd  = fs.access("/etc/config/radvd")
31 local has_rom  = fs.access("/rom/etc")
32 local has_autoipv6  = fs.access("/usr/bin/auto-ipv6")
33 local has_qos  = fs.access("/etc/init.d/qos")
34 local has_ipv6 = fs.access("/proc/sys/net/ipv6")
35 local has_hb = fs.access("/sbin/heartbeat")
36
37 luci.i18n.loadc("freifunk")
38
39 function get_mac(ix)
40         if string.find(ix, "radio") then
41                 ix = string.gsub(ix,"radio", 'wlan')
42         end
43         local mac = fs.readfile("/sys/class/net/" .. ix .. "/address")
44         if not mac then
45                 mac = luci.util.exec("ifconfig " .. ix)
46                 mac = mac and mac:match(" ([A-F0-9:]+)%s*\n")
47         else
48                 mac = mac:sub(1,17)
49         end
50         if mac and #mac > 0 then
51                 return mac:lower()
52         end
53         return "?"
54 end
55 function get_ula(imac)
56         if string.len(imac) == 17 then
57                 local mac1 = string.sub(imac,4,8)
58                 local mac2 = string.sub(imac,10,14)
59                 local mac3 = string.sub(imac,16,17)
60                 return 'fdca:ffee:babe::02'..mac1..'ff:fe'..mac2..mac3..'/64'
61         end
62         return "?"
63 end
64
65
66 -------------------- View --------------------
67 f = SimpleForm("ffwizward", "Freifunkassistent",
68  "Dieser Assistent unterstützt Sie bei der Einrichtung des Routers für das Freifunknetz.")
69
70 -- if password is not set or default then force the user to set a new one
71 if sys.exec("diff /rom/etc/passwd /etc/passwd") == "" then
72         pw1 = f:field(Value, "pw1", translate("password"))
73         pw1.password = true
74         pw1.rmempty = false
75
76         pw2 = f:field(Value, "pw2", translate("confirmation"))
77         pw2.password = true
78         pw2.rmempty = false
79
80         function pw2.validate(self, value, section)
81                 return pw1:formvalue(section) == value and value
82         end
83 end
84
85 net = f:field(ListValue, "net", "Freifunk Community", "Nutzen Sie die Einstellungen der Freifunk Gemeinschaft in ihrer Nachbarschaft.")
86 net.rmempty = false
87 net.optional = false
88 uci:foreach("freifunk", "community", function(s)
89         net:value(s[".name"], "%s (%s)" % {s.name, s.mesh_network or "?"})
90 end)
91 function net.cfgvalue(self, section)
92         return uci:get("freifunk", "wizard", "net")
93 end
94 function net.write(self, section, value)
95         uci:set("freifunk", "wizard", "net", value)
96         uci:save("freifunk")
97 end
98 net_lat = f:field(ListValue, "net_lat", "", "")
99 net_lat:depends("net", "0")
100 net_lon = f:field(ListValue, "net_lon", "", "")
101 net_lon:depends("net", "0")
102
103 uci:foreach("freifunk", "community", function(s)
104         if s.latitude then
105                 net_lat:value(s[".name"], "%s" % {s.latitude or "?"})
106         end
107         if s.longitude then
108                 net_lon:value(s[".name"], "%s" % {s.longitude or "?"})
109         end
110 end)
111
112 -- hostname
113 hostname = f:field(Value, "hostname", "Knoten Name", "Geben Sie Ihrem Freifunk Router einen Namen. Wenn Sie dieses Feld leer lassen, wird der Name automatisch aus der Mesh IP generiert.")
114 hostname.rmempty = true
115 hostname.optional = false
116 function hostname.cfgvalue(self, section)
117         return sys.hostname()
118 end
119 function hostname.write(self, section, value)
120         uci:set("freifunk", "wizard", "hostname", value)
121         uci:save("freifunk")
122 end
123 function hostname.validate(self, value)
124         if (#value > 24) or string.find(value, "[^%w%.%-]") or string.find(string.sub(value, value:len()), "[%.%-]") or string.find(string.sub(value, 1), "[%.%-]") then
125                 return
126         else
127                 return value
128         end
129 end
130
131 -- location
132 location = f:field(Value, "location", "Standort", "Geben Sie den Standort ihres Gerätes an")
133 location.rmempty = false
134 location.optional = false
135 function location.cfgvalue(self, section)
136         return uci:get("freifunk", "contact", "location")
137 end
138 function location.write(self, section, value)
139         uci:set("freifunk", "contact", "location", value)
140         uci:save("freifunk")
141 end
142
143 -- mail
144 mail = f:field(Value, "mail", "E-Mail", "Bitte hinterlegen Sie eine Kontaktadresse.")
145 mail.rmempty = false
146 mail.optional = false
147 function mail.cfgvalue(self, section)
148         return uci:get("freifunk", "contact", "mail")
149 end
150 function mail.write(self, section, value)
151         uci:set("freifunk", "contact", "mail", value)
152         uci:save("freifunk")
153 end
154 -- main netconfig
155 main = f:field(Flag, "netconfig", "Netzwerk einrichten", "Setzen Sie den Haken, wenn Sie Ihr Freifunk Netzwerk einrichten wollen.")
156 uci:foreach("wireless", "wifi-device",
157         function(section)
158                 local device = section[".name"]
159                 local dev = f:field(Flag, "device_" .. device , "<b>Drahtloses Netzwerk \"" .. device:upper() .. "\"</b> ", "Konfigurieren Sie Ihre drahtlose " .. device:upper() .. "Schnittstelle (WLAN).")
160                         dev:depends("netconfig", "1")
161                         dev.rmempty = false
162                         function dev.cfgvalue(self, section)
163                                 return uci:get("freifunk", "wizard", "device_" .. device)
164                         end
165                         function dev.write(self, sec, value)
166                                 if value then
167                                         uci:set("freifunk", "wizard", "device_" .. device, value)
168                                         uci:save("freifunk")
169                                 end
170                         end
171                 local chan = f:field(ListValue, "chan_" .. device, device:upper() .. "  Freifunk Kanal einrichten", "Ihr Gerät und benachbarte Freifunk Knoten müssen auf demselben Kanal senden. Je nach Gerätetyp können Sie zwischen verschiedenen 2,4Ghz und 5Ghz Kanälen auswählen.")
172                         chan:depends("device_" .. device, "1")
173                         chan.rmempty = true
174                         function chan.cfgvalue(self, section)
175                                 return uci:get("freifunk", "wizard", "chan_" .. device)
176                         end
177
178                         chan:value('default')
179                         for _, f in ipairs(sys.wifi.channels(device)) do
180                                 if not f.restricted then
181                                         chan:value(f.channel)
182                                 end
183                         end
184
185                         function chan.write(self, sec, value)
186                                 if value then
187                                         uci:set("freifunk", "wizard", "chan_" .. device, value)
188                                         uci:save("freifunk")
189                                 end
190                         end
191
192                         local meship = f:field(Value, "meship_" .. device, device:upper() .. "  Mesh IP Adresse einrichten", "Ihre Mesh IP Adresse erhalten Sie von der Freifunk Gemeinschaft in Ihrer Nachbarschaft. Es ist eine netzweit eindeutige Identifikation, z.B. 104.1.1.1.")
193                         meship:depends("device_" .. device, "1")
194                         meship.rmempty = true
195                         function meship.cfgvalue(self, section)
196                                 return uci:get("freifunk", "wizard", "meship_" .. device)
197                         end
198                         function meship.validate(self, value)
199                                 local x = ip.IPv4(value)
200                                 return ( x and x:prefix() == 32 ) and x:string() or ""
201                         end
202                         function meship.write(self, sec, value)
203                                 uci:set("freifunk", "wizard", "meship_" .. device, value)
204                                 local new_ip = ip.IPv4(value)
205                                 if new_ip then
206                                         local new_hostname = new_ip:string():gsub("%.", "-")
207                                         uci:set("freifunk", "wizard", "hostname", new_hostname)
208                                         uci:save("freifunk")
209                                 end
210                         end
211                 if has_ipv6 then
212                         local meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
213                         meship6:depends("device_" .. device, "1")
214                         meship6.rmempty = true
215                         function meship6.cfgvalue(self, section)
216                                 return get_ula(get_mac(device))
217                         end
218                 end
219         
220                 local client = f:field(Flag, "client_" .. device, device:upper() .. "  DHCP anbieten", "DHCP weist verbundenen Benutzern automatisch eine Adresse zu. Diese Option sollten Sie unbedingt aktivieren, wenn Sie Nutzer an der drahtlosen Schnittstelle erwarten.")
221                         client:depends("device_" .. device, "1")
222                         client.rmempty = false
223                         function client.cfgvalue(self, section)
224                                 return uci:get("freifunk", "wizard", "client_" .. device)
225                         end
226                         function client.write(self, sec, value)
227                                 uci:set("freifunk", "wizard", "client_" .. device, value)
228                                 uci:save("freifunk")
229                         end
230                 local dhcpmesh = f:field(Value, "dhcpmesh_" .. device, device:upper() .. "  Mesh DHCP anbieten", "Bestimmen Sie den Adressbereich aus dem Ihre Nutzer IP Adressen erhalten. Es wird empfohlen einen Adressbereich aus Ihrer lokalen Freifunk Gemeinschaft zu nutzen. Der Adressbereich ist ein netzweit eindeutiger Netzbereich. z.B. 104.1.2.1/28")
231                         dhcpmesh:depends("client_" .. device, "1")
232                         dhcpmesh.rmempty = true
233                         function dhcpmesh.cfgvalue(self, section)
234                                 return uci:get("freifunk", "wizard", "dhcpmesh_" .. device)
235                         end
236                         function dhcpmesh.validate(self, value)
237                                 local x = ip.IPv4(value)
238                                 return ( x and x:minhost()) and x:string() or ""
239                         end
240                         function dhcpmesh.write(self, sec, value)
241                                 uci:set("freifunk", "wizard", "dhcpmesh_" .. device, value)
242                                 uci:save("freifunk")
243                         end
244                 local hwtype = section.type
245                 if hwtype == "atheros" then
246                         local vap = f:field(Flag, "vap_" .. device , "Virtueller Drahtloser Zugangspunkt", "Konfigurieren Sie Ihren Virtuellen AP")
247                         vap:depends("client_" .. device, "1")
248                         vap.rmempty = false
249                         function vap.cfgvalue(self, section)
250                                 return uci:get("freifunk", "wizard", "vap_" .. device)
251                         end
252                         function vap.write(self, sec, value)
253                                 uci:set("freifunk", "wizard", "vap_" .. device, value)
254                                 uci:save("freifunk")
255                         end
256                 end
257         end)
258
259 uci:foreach("network", "interface",
260         function(section)
261                 local device = section[".name"]
262                 local ifname = uci_state:get("network",device,"ifname")
263                 if device ~= "loopback" and not string.find(device, "gvpn")  and not string.find(device, "wifi") and not string.find(device, "wl") and not string.find(device, "wlan") and not string.find(device, "wireless") and not string.find(device, "radio") then
264                         dev = f:field(Flag, "device_" .. device , "<b>Drahtgebundenes Netzwerk \"" .. device:upper() .. "\"</b>", "Konfigurieren Sie Ihre drahtgebunde " .. device:upper() .. " Schnittstelle (LAN).")
265                                 dev:depends("netconfig", "1")
266                                 dev.rmempty = false
267                                 function dev.cfgvalue(self, section)
268                                         return uci:get("freifunk", "wizard", "device_" .. device)
269                                 end
270                                 function dev.write(self, sec, value)
271                                         uci:set("freifunk", "wizard", "device_" .. device, value)
272                                         uci:save("freifunk")
273                                 end
274                         meship = f:field(Value, "meship_" .. device, device:upper() .. "  Mesh IP Adresse einrichten", "Ihre Mesh IP Adresse erhalten Sie von der Freifunk Gemeinschaft in Ihrer Nachbarschaft. Es ist eine netzweit eindeutige Identifikation, z.B. 104.1.1.1.")
275                                 meship:depends("device_" .. device, "1")
276                                 meship.rmempty = true
277                                 function meship.cfgvalue(self, section)
278                                         return uci:get("freifunk", "wizard", "meship_" .. device)
279                                 end
280                                 function meship.validate(self, value)
281                                         local x = ip.IPv4(value)
282                                         return ( x and x:prefix() == 32 ) and x:string() or ""
283                                 end
284                                 function meship.write(self, sec, value)
285                                         uci:set("freifunk", "wizard", "meship_" .. device, value)
286                                 end
287                         if has_ipv6 then
288                                 meship6 = f:field(Value, "meship6_" .. device, device:upper() .. "  Mesh IPv6 Adresse einrichten", "Ihre Mesh IP Adresse wird automatisch berechnet")
289                                 meship6:depends("device_" .. device, "1")
290                                 meship6.rmempty = true
291                                 function meship6.cfgvalue(self, section)
292                                         return get_ula(get_mac(ifname))
293                                 end
294                         end
295
296                         client = f:field(Flag, "client_" .. device, device:upper() .. "  DHCP anbieten","DHCP weist verbundenen Benutzern automatisch eine Adresse zu. Diese Option sollten Sie unbedingt aktivieren, wenn Sie Nutzer an der drahtlosen Schnittstelle erwarten.")
297                                 client:depends("device_" .. device, "1")
298                                 client.rmempty = false
299                                 function client.cfgvalue(self, section)
300                                         return uci:get("freifunk", "wizard", "client_" .. device)
301                                 end
302                                 function client.write(self, sec, value)
303                                         uci:set("freifunk", "wizard", "client_" .. device, value)
304                                         uci:save("freifunk")
305                                 end
306                         dhcpmesh = f:field(Value, "dhcpmesh_" .. device, device:upper() .. "  Mesh DHCP anbieten ", "Bestimmen Sie den Adressbereich aus dem Ihre Nutzer IP Adressen erhalten. Es wird empfohlen einen Adressbereich aus Ihrer lokalen Freifunk Gemeinschaft zu nutzen. Der Adressbereich ist ein netzweit eindeutiger Netzbereich. z.B. 104.1.2.1/28")
307                                 dhcpmesh:depends("client_" .. device, "1")
308                                 dhcpmesh.rmempty = true
309                                 function dhcpmesh.cfgvalue(self, section)
310                                         return uci:get("freifunk", "wizard", "dhcpmesh_" .. device)
311                                 end
312                                 function dhcpmesh.validate(self, value)
313                                         local x = ip.IPv4(value)
314                                         return ( x and x:prefix() <= 30 and x:minhost()) and x:string() or ""
315                                 end
316                                 function dhcpmesh.write(self, sec, value)
317                                         uci:set("freifunk", "wizard", "dhcpmesh_" .. device, value)
318                                         uci:save("freifunk")
319                                 end
320                 end
321         end)
322
323
324 local syslat = uci:get("freifunk", "wizard", "latitude") or 52
325 local syslon = uci:get("freifunk", "wizard", "longitude") or 10
326 uci:foreach("system", "system", function(s)
327                 if s.latitude then
328                         syslat = s.latitude
329                 end
330                 if s.longitude then
331                         syslon = s.longitude
332                 end
333 end)
334 uci:foreach("olsrd", "LoadPlugin", function(s)
335         if s.library == "olsrd_nameservice.so.0.3" then
336                 if s.lat then
337                         syslat = s.lat
338                 end
339                 if s.lon then
340                         syslon = s.lon
341                 end
342         end
343 end)
344
345 lat = f:field(Value, "lat", "geographischer Breitengrad", "Setzen Sie den Breitengrad (Latitude) Ihres Geräts.")
346 lat:depends("netconfig", "1")
347 function lat.cfgvalue(self, section)
348         return syslat
349 end
350 function lat.write(self, section, value)
351         uci:set("freifunk", "wizard", "latitude", value)
352         uci:save("freifunk")
353 end
354
355 lon = f:field(Value, "lon", "geograpischer Längengrad", "Setzen Sie den Längengrad (Longitude) Ihres Geräts.")
356 lon:depends("netconfig", "1")
357 function lon.cfgvalue(self, section)
358         return syslon
359 end
360 function lon.write(self, section, value)
361         uci:set("freifunk", "wizard", "longitude", value)
362         uci:save("freifunk")
363 end
364
365 --[[
366 *Opens an OpenStreetMap iframe or popup
367 *Makes use of resources/OSMLatLon.htm and htdocs/resources/osm.js
368 (is that the right place for files like these?)
369 ]]--
370
371 local class = util.class
372
373 OpenStreetMapLonLat = class(AbstractValue)
374
375 function OpenStreetMapLonLat.__init__(self, ...)
376         AbstractValue.__init__(self, ...)
377         self.template = "cbi/osmll_value"
378         self.latfield = nil
379         self.lonfield = nil
380         self.centerlat = ""
381         self.centerlon = ""
382         self.zoom = "0"
383         self.width = "100%" --popups will ignore the %-symbol, "100%" is interpreted as "100"
384         self.height = "600"
385         self.popup = false
386         self.displaytext="OpenStreetMap" --text on button, that loads and displays the OSMap
387         self.hidetext="X" -- text on button, that hides OSMap
388 end
389
390 osm = f:field(OpenStreetMapLonLat, "latlon", "Geokoordinaten mit OpenStreetMap ermitteln:", "Klicken Sie auf Ihren Standort in der Karte. Diese Karte funktioniert nur, wenn das Gerät bereits eine Verbindung zum Internet hat.")
391 osm:depends("netconfig", "1")
392 osm.latfield = "lat"
393 osm.lonfield = "lon"
394 osm.centerlat = syslat
395 osm.centerlon = syslon
396 osm.width = "100%"
397 osm.height = "600"
398 osm.popup = false
399 syslatlengh = string.len(syslat)
400 if syslatlengh > 7 then
401         osm.zoom = "15"
402 elseif syslatlengh > 5 then
403         osm.zoom = "12"
404 else
405         osm.zoom = "6"
406 end
407 osm.displaytext="OpenStreetMap anzeigen"
408 osm.hidetext="OpenStreetMap verbergen"
409
410 share = f:field(Flag, "sharenet", "Eigenen Internetzugang freigeben", "Geben Sie Ihren Internetzugang im Freifunknetz frei.")
411 share.rmempty = false
412 share:depends("netconfig", "1")
413 function share.cfgvalue(self, section)
414         return uci:get("freifunk", "wizard", "share")
415 end
416 function share.write(self, section, value)
417         uci:set("freifunk", "wizard", "share", value)
418         uci:save("freifunk")
419 end
420
421 wanproto = f:field(ListValue, "wanproto", "Protokoll des Internetzugangs", "Geben Sie das Protokol an ueber das eine Internet verbindung hergestellt werden kann.")
422 wanproto:depends("sharenet", "1")
423 wanproto:value("static", translate("manual", "manual"))
424 wanproto:value("dhcp", translate("automatic", "automatic"))
425 if has_pppoe then wanproto:value("pppoe", "PPPoE") end
426 if has_pptp  then wanproto:value("pptp",  "PPTP")  end
427 function wanproto.cfgvalue(self, section)
428         return uci:get("network", "wan", "proto") or "dhcp"
429 end
430 function wanproto.write(self, section, value)
431         uci:set("network", "wan", "proto", value)
432         uci:save("network")
433 end
434 wanip = f:field(Value, "wanipaddr", translate("ipaddress"))
435 wanip:depends("wanproto", "static")
436 function wanip.cfgvalue(self, section)
437         return uci:get("network", "wan", "ipaddr")
438 end
439 function wanip.write(self, section, value)
440         uci:set("network", "wan", "ipaddr", value)
441         uci:save("network")
442 end
443 wannm = f:field(Value, "wannetmask", translate("netmask"))
444 wannm:depends("wanproto", "static")
445 function wannm.cfgvalue(self, section)
446         return uci:get("network", "wan", "netmask")
447 end
448 function wannm.write(self, section, value)
449         uci:set("network", "wan", "netmask", value)
450         uci:save("network")
451 end
452 wangw = f:field(Value, "wangateway", translate("gateway"))
453 wangw:depends("wanproto", "static")
454 wangw.rmempty = true
455 function wangw.cfgvalue(self, section)
456         return uci:get("network", "wan", "gateway")
457 end
458 function wangw.write(self, section, value)
459         uci:set("network", "wan", "gateway", value)
460         uci:save("network")
461 end
462 wandns = f:field(Value, "wandns", translate("dnsserver"))
463 wandns:depends("wanproto", "static")
464 wandns.rmempty = true
465 function wandns.cfgvalue(self, section)
466         return uci:get("network", "wan", "dns")
467 end
468 function wandns.write(self, section, value)
469         uci:set("network", "wan", "dns", value)
470         uci:save("network")
471 end
472 wanusr = f:field(Value, "wanusername", translate("username"))
473 wanusr:depends("wanproto", "pppoe")
474 wanusr:depends("wanproto", "pptp")
475 function wanusr.cfgvalue(self, section)
476         return uci:get("network", "wan", "username")
477 end
478 function wanusr.write(self, section, value)
479         uci:set("network", "wan", "username", value)
480         uci:save("network")
481 end
482 wanpwd = f:field(Value, "wanpassword", translate("password"))
483 wanpwd.password = true
484 wanpwd:depends("wanproto", "pppoe")
485 wanpwd:depends("wanproto", "pptp")
486 function wanpwd.cfgvalue(self, section)
487         return uci:get("network", "wan", "password")
488 end
489 function wanpwd.write(self, section, value)
490         uci:set("network", "wan", "password", value)
491         uci:save("network")
492 end
493
494 wansec = f:field(Flag, "wansec", "WAN-Zugriff auf Gateway beschränken", "Verbieten Sie Zugriffe auf Ihr lokales Netzwerk aus dem Freifunknetz.")
495 wansec.rmempty = false
496 wansec:depends("wanproto", "static")
497 wansec:depends("wanproto", "dhcp")
498 function wansec.cfgvalue(self, section)
499         return uci:get("freifunk", "wizard", "wan_security")
500 end
501 function wansec.write(self, section, value)
502         uci:set("freifunk", "wizard", "wan_security", value)
503         uci:save("freifunk")
504 end
505 if has_qos then
506         wanqosdown = f:field(Value, "wanqosdown", "Download Bandbreite begrenzen", "kb/s")
507         wanqosdown:depends("sharenet", "1")
508         function wanqosdown.cfgvalue(self, section)
509                 return uci:get("qos", "wan", "download")
510         end
511         function wanqosdown.write(self, section, value)
512                 uci:set("qos", "wan", "download", value)
513                 uci:save("qos")
514         end
515         wanqosup = f:field(Value, "wanqosup", "Upload Bandbreite begrenzen", "kb/s")
516         wanqosup:depends("sharenet", "1")
517         function wanqosup.cfgvalue(self, section)
518                 return uci:get("qos", "wan", "upload")
519         end
520         function wanqosup.write(self, section, value)
521                 uci:set("qos", "wan", "upload", value)
522                 uci:save("qos")
523         end
524 end
525
526 if has_l2gvpn then
527         gvpn = f:field(Flag, "gvpn", "Freifunk Internet Tunnel", "Verbinden Sie ihren Router ueber das Internet mit anderen Freifunknetzen.")
528         gvpn.rmempty = false
529         gvpn:depends("sharenet", "1")
530         function gvpn.cfgvalue(self, section)
531                 return uci:get("freifunk", "wizard", "gvpn")
532         end
533         function gvpn.write(self, section, value)
534                 uci:set("freifunk", "wizard", "gvpn", value)
535                 uci:save("freifunk")
536         end
537         gvpnip = f:field(Value, "gvpnipaddr", translate("ipaddress"))
538         gvpnip:depends("gvpn", "1")
539         function gvpnip.cfgvalue(self, section)
540                 return uci:get("l2gvpn", "bbb", "ip") or uci:get("network", "gvpn", "ipaddr")
541         end
542         function gvpnip.validate(self, value)
543                 local x = ip.IPv4(value)
544                 return ( x and x:prefix() == 32 ) and x:string() or ""
545         end
546 end
547
548 if has_hb then
549         hb = f:field(Flag, "hb", "Heartbeat aktivieren","Dem Gerät erlauben anonyme Statistiken zu übertragen. (empfohlen)")
550         hb.rmempty = false
551         hb:depends("netconfig", "1")
552         function hb.cfgvalue(self, section)
553                 return uci:get("freifunk", "wizard", "hb")
554         end
555         function hb.write(self, section, value)
556                 uci:set("freifunk", "wizard", "hb", value)
557                 uci:save("freifunk")
558         end
559 end
560
561 -------------------- Control --------------------
562 function f.handle(self, state, data)
563         if state == FORM_VALID then
564                 local debug = uci:get("freifunk", "wizard", "debug")
565                 if debug == "1" then
566                         if data.pw1 then
567                                 local stat = luci.sys.user.setpasswd("root", data.pw1) == 0
568                                 if stat then
569                                         f.message = translate("a_s_changepw_changed")
570                                 else
571                                         f.errmessage = translate("unknownerror")
572                                 end
573                         end
574                         data.pw1 = nil
575                         data.pw2 = nil
576                         luci.http.redirect(luci.dispatcher.build_url(unpack(luci.dispatcher.context.requested.path), "system", "system"))
577                 else
578                         if data.pw1 then
579                                 local stat = luci.sys.user.setpasswd("root", data.pw1) == 0
580                         end
581                         data.pw1 = nil
582                         data.pw2 = nil
583                         uci:commit("freifunk")
584                         uci:commit("wireless")
585                         uci:commit("network")
586                         uci:commit("dhcp")
587                         uci:commit("luci_splash")
588                         uci:commit("firewall")
589                         uci:commit("system")
590                         uci:commit("uhttpd")
591                         uci:commit("olsrd")
592                         uci:commit("manager")
593                         if has_autoipv6 then
594                                 uci:commit("autoipv6")
595                         end
596                         if has_qos then
597                                 uci:commit("qos")
598                         end
599                         if has_l2gvpn then
600                                 uci:commit("l2gvpn")
601                         end
602                         if has_radvd then
603                                 uci:commit("radvd")
604                         end
605
606                         sys.exec("for s in network dnsmasq luci_splash firewall uhttpd olsrd radvd l2gvpn; do [ -x /etc/init.d/$s ] && /etc/init.d/$s restart;done > /dev/null &")
607                         luci.http.redirect(luci.dispatcher.build_url(luci.dispatcher.context.path[1], "freifunk", "ffwizard"))
608                 end
609                 return false
610         elseif state == FORM_INVALID then
611                 self.errmessage = "Ungültige Eingabe: Bitte die Formularfelder auf Fehler prüfen."
612         end
613         return true
614 end
615
616 local function _strip_internals(tbl)
617         tbl = tbl or {}
618         for k, v in pairs(tbl) do
619                 if k:sub(1, 1) == "." then
620                         tbl[k] = nil
621                 end
622         end
623         return tbl
624 end
625 -- Configure Freifunk checked
626 function main.write(self, section, value)
627         if value == "0" then
628                 uci:set("freifunk", "wizard", "netconfig", "0")
629                 uci:save("freifunk")
630                 return
631         end
632         -- Collect IP-Address
633         local community = net:formvalue(section)
634         suffix = uci:get("freifunk", community, "suffix") or "olsr"
635
636         -- Invalidate fields
637         if not community then
638                 net.tag_missing[section] = true
639                 return
640         end
641
642         uci:set("freifunk", "wizard", "netconfig", "1")
643         uci:save("freifunk")
644
645         local external
646         external = uci:get("freifunk", community, "external") or ""
647
648         local netname = "wireless"
649         local network
650         network = ip.IPv4(uci:get("freifunk", community, "mesh_network") or "104.0.0.0/8")
651
652         -- Tune community settings
653         if community and uci:get("freifunk", community) then
654                 uci:tset("freifunk", "community", uci:get_all("freifunk", community))
655         end
656
657         -- Cleanup
658         uci:delete_all("firewall","zone", {name="freifunk"})
659         uci:delete_all("firewall","forwarding", {dest="freifunk"})
660         uci:delete_all("firewall","forwarding", {src="freifunk"})
661         uci:delete_all("firewall","rule", {dest="freifunk"})
662         uci:delete_all("firewall","rule", {src="freifunk"})
663         uci:save("firewall")
664         -- Create firewall zone and add default rules (first time)
665         --                    firewall_create_zone("name"    , "input" , "output", "forward ", Masqurade)
666         local newzone = tools.firewall_create_zone("freifunk", "ACCEPT", "ACCEPT", "REJECT"  , true)
667         if newzone then
668                 uci:foreach("freifunk", "fw_forwarding", function(section)
669                         uci:section("firewall", "forwarding", nil, section)
670                 end)
671                 uci:foreach(external, "fw_forwarding", function(section)
672                         uci:section("firewall", "forwarding", nil, section)
673                 end)
674
675                 uci:foreach("freifunk", "fw_rule", function(section)
676                         uci:section("firewall", "rule", nil, section)
677                 end)
678                 uci:foreach(external, "fw_rule", function(section)
679                         uci:section("firewall", "rule", nil, section)
680                 end)
681         end
682         uci:save("firewall")
683         if has_hb then
684                 uci:delete("manager", "heartbeat", "interface")
685                 uci:save("manager")
686         end
687         -- Delete olsrdv4
688         uci:delete_all("olsrd", "olsrd")
689         local olsrbase
690         olsrbase = uci:get_all("freifunk", "olsrd") or {}
691         util.update(olsrbase, uci:get_all(external, "olsrd") or {})
692         if has_ipv6 then
693                 olsrbase.IpVersion='6and4'
694         else
695                 olsrbase.IpVersion='4'
696         end
697         uci:section("olsrd", "olsrd", nil, olsrbase)
698         -- Delete olsrdv4 old p2pd settings
699         uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_mdns.so.1.0.0"})
700         uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_p2pd.so.0.1.0"})
701         -- Write olsrdv4 new p2pd settings
702         uci:section("olsrd", "LoadPlugin", nil, {
703                 library     = "olsrd_p2pd.so.0.1.0",
704                 P2pdTtl     = 10,
705                 UdpDestPort = "224.0.0.251 5353",
706                 ignore      = 1,
707         })
708         -- Delete http plugin
709         uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_httpinfo.so.0.1"})
710
711         -- Delete olsrdv4 old interface
712         uci:delete_all("olsrd", "Interface")
713         uci:delete_all("olsrd", "Hna4")
714         -- Create wireless ip4/ip6 and firewall config
715         uci:foreach("wireless", "wifi-device",
716         function(sec)
717                 local device = sec[".name"]
718                 if not luci.http.formvalue("cbid.ffwizward.1.device_" .. device) then
719                         return
720                 end
721                 node_ip = luci.http.formvalue("cbid.ffwizward.1.meship_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.meship_" .. device))
722                 if has_ipv6 then
723                         node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
724                 end
725                 if not node_ip or not network or not network:contains(node_ip) then
726                         meship.tag_missing[section] = true
727                         node_ip = nil
728                         return
729                 end
730                 -- rename the wireless interface s/wifi/wireless/
731                 local nif
732                 if string.find(device, "wifi") then
733                         nif = string.gsub(device,"wifi", netname)
734                 elseif string.find(device, "wl") then
735                         nif = string.gsub(device,"wl", netname)
736                 elseif string.find(device, "wlan") then
737                         nif = string.gsub(device,"wlan", netname)
738                 elseif string.find(device, "radio") then
739                         nif = string.gsub(device,"radio", netname)
740                 end
741                 -- Cleanup
742                 tools.wifi_delete_ifaces(device)
743                 -- tools.network_remove_interface(device)
744                 uci:delete("network", device .. "dhcp")
745                 uci:delete("network", device)
746                 tools.firewall_zone_remove_interface("freifunk", device)
747                 -- tools.network_remove_interface(nif)
748                 uci:delete("network", nif .. "dhcp")
749                 uci:delete("network", nif)
750                 tools.firewall_zone_remove_interface("freifunk", nif)
751                 -- Delete old dhcp
752                 uci:delete("dhcp", device)
753                 uci:delete("dhcp", device .. "dhcp")
754                 uci:delete("dhcp", nif)
755                 uci:delete("dhcp", nif .. "dhcp")
756                 -- Delete old splash
757                 uci:delete_all("luci_splash", "iface", {network=device.."dhcp", zone="freifunk"})
758                 uci:delete_all("luci_splash", "iface", {network=nif.."dhcp", zone="freifunk"})
759                 -- Delete old radvd
760                 if has_radvd then
761                         uci:delete_all("radvd", "interface", {interface=nif.."dhcp"})
762                         uci:delete_all("radvd", "interface", {interface=nif})
763                         uci:delete_all("radvd", "prefix", {interface=nif.."dhcp"})
764                         uci:delete_all("radvd", "prefix", {interface=nif})
765                 end
766                 -- New Config
767                 -- Tune wifi device
768                 local ssid = uci:get("freifunk", community, "ssid") or "olsr.freifunk.net"
769                 local devconfig = uci:get_all("freifunk", "wifi_device")
770                 util.update(devconfig, uci:get_all(external, "wifi_device") or {})
771                 local channel = luci.http.formvalue("cbid.ffwizward.1.chan_" .. device)
772                 local hwmode = "11bg"
773                 local bssid = uci:get_all(external, "wifi_iface", "bssid") or "02:CA:FF:EE:BA:BE"
774                 local mrate = 5500
775                 -- set bssid, see https://kifuse02.pberg.freifunk.net/moin/channel-bssid-essid for schema
776                 if channel and channel ~= "default" then
777                         if devconfig.channel ~= channel then
778                                 devconfig.channel = channel
779                                 local chan = tonumber(channel)
780                                 if chan >= 0 and chan < 10 then
781                                         bssid = channel .. "2:CA:FF:EE:BA:BE"
782                                 elseif chan == 10 then 
783                                         bssid = "02:CA:FF:EE:BA:BE" 
784                                 elseif chan >= 11 and chan <= 14 then
785                                         bssid = string.format("%X",channel) .. "2:CA:FF:EE:BA:BE"
786                                 elseif chan >= 36 and chan <= 64 then
787                                         hwmode = "11a"
788                                         mrate = ""
789                                         outdoor = 0
790                                         bssid = "00:" .. channel ..":CA:FF:EE:EE"
791                                 elseif chan >= 100 and chan <= 140 then
792                                         hwmode = "11a"
793                                         mrate = ""
794                                         outdoor = 1
795                                         bssid = "01:" .. string.sub(channel, 2) .. ":CA:FF:EE:EE"
796                                 end
797                                 devconfig.hwmode = hwmode
798                                 devconfig.outdoor = outdoor
799                         end
800                         ssid = ssid .. " - ch" .. channel
801                 end
802                 uci:tset("wireless", device, devconfig)
803                 -- Create wifi iface
804                 local ifconfig = uci:get_all("freifunk", "wifi_iface")
805                 util.update(ifconfig, uci:get_all(external, "wifi_iface") or {})
806                 ifconfig.device = device
807                 ifconfig.network = nif
808                 ifconfig.ssid = ssid
809                 ifconfig.bssid = bssid
810                 ifconfig.encryption="none"
811                 -- Read Preset 
812                 local netconfig = uci:get_all("freifunk", "interface")
813                 util.update(netconfig, uci:get_all(external, "interface") or {})
814                 netconfig.proto = "static"
815                 netconfig.ipaddr = node_ip:string()
816                 if has_ipv6 then
817                         netconfig.ip6addr = node_ip6:string()
818                 end
819                 uci:section("network", "interface", nif, netconfig)
820                 if has_radvd then
821                         uci:section("radvd", "interface", nil, {
822                                 interface          =nif,
823                                 AdvSendAdvert      =1,
824                                 AdvManagedFlag     =0,
825                                 AdvOtherConfigFlag =0,
826                                 ignore             =0
827                         })
828                         uci:section("radvd", "prefix", nil, {
829                                 interface          =nif,
830                                 AdvOnLink          =1,
831                                 AdvAutonomous      =1,
832                                 AdvRouterAddr      =0,
833                                 ignore             =0,
834                         })
835                         uci:save("radvd")
836                 end
837                 local new_hostname = node_ip:string():gsub("%.", "-")
838                 uci:set("freifunk", "wizard", "hostname", new_hostname)
839                 uci:save("freifunk")
840                 tools.firewall_zone_add_interface("freifunk", nif)
841                 uci:save("firewall")
842                 -- Write new olsrv4 interface
843                 local olsrifbase = uci:get_all("freifunk", "olsr_interface")
844                 util.update(olsrifbase, uci:get_all(external, "olsr_interface") or {})
845                 olsrifbase.interface = nif
846                 olsrifbase.ignore    = "0"
847                 uci:section("olsrd", "Interface", nil, olsrifbase)
848                 -- Collect MESH DHCP IP NET
849                 local client = luci.http.formvalue("cbid.ffwizward.1.client_" .. device)
850                 if client then
851                         local dhcpmeshnet = luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device))
852                         if has_hb then
853                                 local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
854                                 table.insert(ifacelist,nif .. "dhcp")
855                                 uci:set_list("manager", "heartbeat", "interface", ifacelist)
856                                 uci:save("manager")
857                         end
858                         if dhcpmeshnet then
859                                 if not dhcpmeshnet:minhost() or not dhcpmeshnet:mask() then
860                                         dhcpmesh.tag_missing[section] = true
861                                         dhcpmeshnet = nil
862                                         return
863                                 end
864                                 dhcp_ip = dhcpmeshnet:minhost():string()
865                                 dhcp_mask = dhcpmeshnet:mask():string()
866                                 dhcp_network = dhcpmeshnet:network():string()
867                                 uci:section("olsrd", "Hna4", nil, {
868                                         netmask  = dhcp_mask,
869                                         netaddr  = dhcp_network
870                                 })
871                                 uci:foreach("olsrd", "LoadPlugin",
872                                         function(s)             
873                                                 if s.library == "olsrd_p2pd.so.0.1.0" then
874                                                         uci:set("olsrd", s['.name'], "ignore", "0")
875                                                         local nonolsr = uci:get("olsrd", s['.name'], "NonOlsrIf") or ""
876                                                         vap = luci.http.formvalue("cbid.ffwizward.1.vap_" .. device)
877                                                         if vap then
878                                                                 nonolsr = nif.."dhcp "..nonolsr
879                                                         else
880                                                                 nonolsr = nif.." "..nonolsr
881                                                         end
882                                                         uci:set("olsrd", s['.name'], "NonOlsrIf", nonolsr)
883                                                 end
884                                         end)
885                         else
886                                 local subnet_prefix = tonumber(uci:get("freifunk", community, "splash_prefix")) or 27
887                                 local pool_network = uci:get("freifunk", community, "splash_network") or "10.104.0.0/16"
888                                 local pool = luci.ip.IPv4(pool_network)
889                                 local ip = tostring(node_ip)
890                                 if pool and ip then
891                                         local hosts_per_subnet = 2^(32 - subnet_prefix)
892                                         local number_of_subnets = (2^pool:prefix())/hosts_per_subnet
893                                         local seed1, seed2 = ip:match("(%d+)%.(%d+)$")
894                                         if seed1 and seed2 then
895                                                 math.randomseed(seed1 * seed2)
896                                         end
897                                         local subnet = pool:add(hosts_per_subnet * math.random(number_of_subnets))
898                                         dhcp_ip = subnet:network(subnet_prefix):add(1):string()
899                                         dhcp_mask = subnet:mask(subnet_prefix):string()
900                                 end
901                         end
902                         if dhcp_ip and dhcp_mask then
903                                 -- Create alias
904                                 local aliasbase = uci:get_all("freifunk", "alias")
905                                 util.update(aliasbase, uci:get_all(external, "alias") or {})
906                                 aliasbase.ipaddr = dhcp_ip
907                                 aliasbase.netmask = dhcp_mask
908                                 aliasbase.proto = "static"
909                                 vap = luci.http.formvalue("cbid.ffwizward.1.vap_" .. device)
910                                 if vap then
911                                         uci:section("network", "interface", nif .. "dhcp", aliasbase)
912                                         uci:section("wireless", "wifi-iface", nil, {
913                                                 device     =device,
914                                                 mode       ="ap",
915                                                 encryption ="none",
916                                                 network    =nif .. "dhcp",
917                                                 ssid       ="AP-" .. ssid
918                                         })
919                                         if has_radvd then
920                                                 uci:section("radvd", "interface", nil, {
921                                                         interface          =nif .. "dhcp",
922                                                         AdvSendAdvert      =1,
923                                                         AdvManagedFlag     =0,
924                                                         AdvOtherConfigFlag =0,
925                                                         ignore             =0
926                                                 })
927                                                 uci:section("radvd", "prefix", nil, {
928                                                         interface          =nif .. "dhcp",
929                                                         AdvOnLink          =1,
930                                                         AdvAutonomous      =1,
931                                                         AdvRouterAddr      =0,
932                                                         ignore             =0
933                                                 })
934                                                 uci:save("radvd")
935                                         end
936                                         tools.firewall_zone_add_interface("freifunk", nif .. "dhcp")
937                                         uci:save("wireless")
938                                         ifconfig.mcast_rate = nil
939                                         ifconfig.encryption="none"
940                                 else
941                                         aliasbase.interface = nif
942                                         uci:section("network", "alias", nif .. "dhcp", aliasbase)
943                                 end
944                                 -- Create dhcp
945                                 local dhcpbase = uci:get_all("freifunk", "dhcp")
946                                 util.update(dhcpbase, uci:get_all(external, "dhcp") or {})
947                                 dhcpbase.interface = nif .. "dhcp"
948                                 dhcpbase.force = 1
949                                 uci:section("dhcp", "dhcp", nif .. "dhcp", dhcpbase)
950                                 uci:set_list("dhcp", nif .. "dhcp", "dhcp_option", "119,olsr")
951                                 -- Create firewall settings
952                                 uci:delete_all("firewall", "rule", {
953                                         src="freifunk",
954                                         proto="udp",
955                                         dest_port="53"
956                                 })
957                                 uci:section("firewall", "rule", nil, {
958                                         src="freifunk",
959                                         proto="udp",
960                                         dest_port="53",
961                                         target="ACCEPT"
962                                 })
963                                 uci:delete_all("firewall", "rule", {
964                                         src="freifunk",
965                                         proto="udp",
966                                         src_port="68",
967                                         dest_port="67"
968                                 })
969                                 uci:section("firewall", "rule", nil, {
970                                         src="freifunk",
971                                         proto="udp",
972                                         src_port="68",
973                                         dest_port="67",
974                                         target="ACCEPT"
975                                 })
976                                 uci:delete_all("firewall", "rule", {
977                                         src="freifunk",
978                                         proto="tcp",
979                                         dest_port="8082",
980                                 })
981                                 uci:section("firewall", "rule", nil, {
982                                         src="freifunk",
983                                         proto="tcp",
984                                         dest_port="8082",
985                                         target="ACCEPT"
986                                 })
987                                 -- Register splash
988                                 uci:section("luci_splash", "iface", nil, {network=nif.."dhcp", zone="freifunk"})
989                                 uci:save("luci_splash")
990                                 -- Make sure that luci_splash is enabled
991                                 sys.init.enable("luci_splash")
992                         end
993                 else
994                         -- Delete old splash
995                         uci:delete_all("luci_splash", "iface", {network=device.."dhcp", zone="freifunk"})
996                 end
997                 --Write Ad-Hoc wifi section after AP wifi section
998                 uci:section("wireless", "wifi-iface", nil, ifconfig)
999                 uci:save("network")
1000                 uci:save("wireless")
1001                 uci:save("network")
1002                 uci:save("firewall")
1003                 uci:save("dhcp")
1004         end)
1005         -- Create wired ip and firewall config
1006         uci:foreach("network", "interface",
1007                 function(sec)
1008                 local device = sec[".name"]
1009                 if not luci.http.formvalue("cbid.ffwizward.1.device_" .. device) then
1010                         return
1011                 end
1012                 if device ~= "loopback" and not string.find(device, "wifi") and not string.find(device, "wl") and not string.find(device, "wlan") and not string.find(device, "wireless") and not string.find(device, "radio") then
1013                         local node_ip
1014                         node_ip = luci.http.formvalue("cbid.ffwizward.1.meship_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.meship_" .. device))
1015                         if has_ipv6 then
1016                                 node_ip6 = luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device) and ip.IPv6(luci.http.formvalue("cbid.ffwizward.1.meship6_" .. device))
1017                         end
1018                         if not node_ip or not network or not network:contains(node_ip) then
1019                                 meship.tag_missing[section] = true
1020                                 node_ip = nil
1021                                 return
1022                         end
1023                         -- Cleanup
1024                         tools.firewall_zone_remove_interface(device, device)
1025                         uci:delete_all("firewall","zone", {name=device})
1026                         uci:delete_all("firewall","forwarding", {src=device})
1027                         uci:delete_all("firewall","forwarding", {dest=device})
1028                         uci:delete("network", device .. "dhcp")
1029                         -- Delete old dhcp
1030                         uci:delete("dhcp", device)
1031                         uci:delete("dhcp", device .. "dhcp")
1032                         -- Delete old splash
1033                         uci:delete_all("luci_splash", "iface", {network=device.."dhcp", zone="freifunk"})
1034                         if has_radvd then
1035                                 uci:delete_all("radvd", "interface", {interface=device.."dhcp"})
1036                                 uci:delete_all("radvd", "interface", {interface=device})
1037                                 uci:delete_all("radvd", "prefix", {interface=device.."dhcp"})
1038                                 uci:delete_all("radvd", "prefix", {interface=device})
1039                         end
1040                         -- New Config
1041                         local netconfig = uci:get_all("freifunk", "interface")
1042                         util.update(netconfig, uci:get_all(external, "interface") or {})
1043                         netconfig.proto = "static"
1044                         netconfig.ipaddr = node_ip:string()
1045                         if has_ipv6 then
1046                                 netconfig.ip6addr = node_ip6:string()
1047                         end
1048                         uci:section("network", "interface", device, netconfig)
1049                         uci:save("network")
1050                         if has_radvd then
1051                                 uci:section("radvd", "interface", nil, {
1052                                         interface          =device,
1053                                         AdvSendAdvert      =1,
1054                                         AdvManagedFlag     =0,
1055                                         AdvOtherConfigFlag =0,
1056                                         ignore             =0
1057                                 })
1058                                 uci:section("radvd", "prefix", nil, {
1059                                         interface          =device,
1060                                         AdvOnLink          =1,
1061                                         AdvAutonomous      =1,
1062                                         AdvRouterAddr      =0,
1063                                         ignore             =0,
1064                                 })
1065                                 uci:save("radvd")
1066                         end
1067                         local new_hostname = node_ip:string():gsub("%.", "-")
1068                         uci:set("freifunk", "wizard", "hostname", new_hostname)
1069                         uci:save("freifunk")
1070                         tools.firewall_zone_add_interface("freifunk", device)
1071                         uci:save("firewall")
1072                         -- Write new olsrv4 interface
1073                         local olsrifbase = uci:get_all("freifunk", "olsr_interface")
1074                         util.update(olsrifbase, uci:get_all(external, "olsr_interface") or {})
1075                         olsrifbase.interface = device
1076                         olsrifbase.ignore    = "0"
1077                         uci:section("olsrd", "Interface", nil, olsrifbase)
1078                         olsrifbase.Mode = 'ether'
1079                         -- Collect MESH DHCP IP NET
1080                         local client = luci.http.formvalue("cbid.ffwizward.1.client_" .. device)
1081                         if client then
1082                                 local dhcpmeshnet = luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device) and ip.IPv4(luci.http.formvalue("cbid.ffwizward.1.dhcpmesh_" .. device))
1083                                 if has_hb then
1084                                         local ifacelist = uci:get_list("manager", "heartbeat", "interface") or {}
1085                                         table.insert(ifacelist,device .. "dhcp")
1086                                         uci:set_list("manager", "heartbeat", "interface", ifacelist)
1087                                         uci:save("manager")
1088                                 end
1089                                 if dhcpmeshnet then
1090                                         if not dhcpmeshnet:minhost() or not dhcpmeshnet:mask() then
1091                                                 dhcpmesh.tag_missing[section] = true
1092                                                 dhcpmeshnet = nil
1093                                                 return
1094                                         end
1095                                         dhcp_ip = dhcpmeshnet:minhost():string()
1096                                         dhcp_mask = dhcpmeshnet:mask():string()
1097                                         dhcp_network = dhcpmeshnet:network():string()
1098                                         uci:section("olsrd", "Hna4", nil, {
1099                                                 netmask  = dhcp_mask,
1100                                                 netaddr  = dhcp_network
1101                                         })
1102                                         uci:foreach("olsrd", "LoadPlugin",
1103                                                 function(s)             
1104                                                         if s.library == "olsrd_p2pd.so.0.1.0" then
1105                                                                 uci:set("olsrd", s['.name'], "ignore", "0")
1106                                                                 local nonolsr = uci:get("olsrd", s['.name'], "NonOlsrIf") or ""
1107                                                                 uci:set("olsrd", s['.name'], "NonOlsrIf", device .." ".. nonolsr)
1108                                                         end
1109                                                 end)
1110                                 else
1111                                         local subnet_prefix = tonumber(uci:get("freifunk", community, "splash_prefix")) or 27
1112                                         local pool_network = uci:get("freifunk", community, "splash_network") or "10.104.0.0/16"
1113                                         local pool = luci.ip.IPv4(pool_network)
1114                                         local ip = tostring(node_ip)
1115                                         if pool and ip then
1116                                                 local hosts_per_subnet = 2^(32 - subnet_prefix)
1117                                                 local number_of_subnets = (2^pool:prefix())/hosts_per_subnet
1118                                                 local seed1, seed2 = ip:match("(%d+)%.(%d+)$")
1119                                                 if seed1 and seed2 then
1120                                                         math.randomseed(seed1 * seed2)
1121                                                 end
1122                                                 local subnet = pool:add(hosts_per_subnet * math.random(number_of_subnets))
1123                                                 dhcp_ip = subnet:network(subnet_prefix):add(1):string()
1124                                                 dhcp_mask = subnet:mask(subnet_prefix):string()
1125                                         end
1126                                 end
1127                                 if dhcp_ip and dhcp_mask then
1128                                         -- Create alias
1129                                         local aliasbase = uci:get_all("freifunk", "alias")
1130                                         util.update(aliasbase, uci:get_all(external, "alias") or {})
1131                                         aliasbase.interface = device
1132                                         aliasbase.ipaddr = dhcp_ip
1133                                         aliasbase.netmask = dhcp_mask
1134                                         aliasbase.proto = "static"
1135                                         uci:section("network", "alias", device .. "dhcp", aliasbase)
1136                                         -- Create dhcp
1137                                         local dhcpbase = uci:get_all("freifunk", "dhcp")
1138                                         util.update(dhcpbase, uci:get_all(external, "dhcp") or {})
1139                                         dhcpbase.interface = device .. "dhcp"
1140                                         dhcpbase.force = 1
1141                                         uci:section("dhcp", "dhcp", device .. "dhcp", dhcpbase)
1142                                         uci:set_list("dhcp", device .. "dhcp", "dhcp_option", "119,olsr")
1143                                         -- Create firewall settings
1144                                         uci:delete_all("firewall", "rule", {
1145                                                 src="freifunk",
1146                                                 proto="udp",
1147                                                 dest_port="53"
1148                                         })
1149                                         uci:section("firewall", "rule", nil, {
1150                                                 src="freifunk",
1151                                                 proto="udp",
1152                                                 dest_port="53",
1153                                                 target="ACCEPT"
1154                                         })
1155                                         uci:delete_all("firewall", "rule", {
1156                                                 src="freifunk",
1157                                                 proto="udp",
1158                                                 src_port="68",
1159                                                 dest_port="67"
1160                                         })
1161                                         uci:section("firewall", "rule", nil, {
1162                                                 src="freifunk",
1163                                                 proto="udp",
1164                                                 src_port="68",
1165                                                 dest_port="67",
1166                                                 target="ACCEPT"
1167                                         })
1168                                         uci:delete_all("firewall", "rule", {
1169                                                 src="freifunk",
1170                                                 proto="tcp",
1171                                                 dest_port="8082",
1172                                         })
1173                                         uci:section("firewall", "rule", nil, {
1174                                                 src="freifunk",
1175                                                 proto="tcp",
1176                                                 dest_port="8082",
1177                                                 target="ACCEPT"
1178                                         })
1179                                         -- Register splash
1180                                         uci:section("luci_splash", "iface", nil, {network=device.."dhcp", zone="freifunk"})
1181                                         uci:save("luci_splash")
1182                                         -- Make sure that luci_splash is enabled
1183                                         sys.init.enable("luci_splash")
1184                                 end
1185                         end
1186                         uci:save("wireless")
1187                         uci:save("network")
1188                         uci:save("firewall")
1189                         uci:save("dhcp")
1190                 end
1191         end)
1192         --enable radvd
1193         if has_radvd then
1194                 sys.init.enable("radvd")
1195         end
1196         -- Enforce firewall include
1197         local has_include = false
1198         uci:foreach("firewall", "include",
1199                 function(section)
1200                         if section.path == "/etc/firewall.freifunk" then
1201                                 has_include = true
1202                         end
1203                 end)
1204
1205         if not has_include then
1206                 uci:section("firewall", "include", nil,
1207                         { path = "/etc/firewall.freifunk" })
1208         end
1209         -- Allow state: invalid packets
1210         uci:foreach("firewall", "defaults",
1211                 function(section)
1212                         uci:set("firewall", section[".name"], "drop_invalid", "0")
1213                 end)
1214
1215         -- Prepare advanced config
1216         local has_advanced = false
1217         uci:foreach("firewall", "advanced",
1218                 function(section) has_advanced = true end)
1219
1220         if not has_advanced then
1221                 uci:section("firewall", "advanced", nil,
1222                         { tcp_ecn = "0", ip_conntrack_max = "8192", tcp_westwood = "1" })
1223         end
1224         uci:save("wireless")
1225         uci:save("network")
1226         uci:save("firewall")
1227         uci:save("dhcp")
1228
1229         local new_hostname = uci:get("freifunk", "wizard", "hostname")
1230         local old_hostname = sys.hostname()
1231
1232         if has_hb then
1233                 local dhcphb = hb:formvalue(section)
1234                 if dhcphb then
1235                         uci:set("manager", "heartbeat", "enabled", "1")
1236                         -- Make sure that heartbeat is enabled
1237                         sys.init.enable("machash")
1238                 else
1239                         uci:set("manager", "heartbeat", "enabled", "0")
1240                         -- Make sure that heartbeat is enabled
1241                         sys.init.disable("machash")
1242                 end
1243                 uci:save("manager")
1244         end
1245
1246         local custom_hostname = hostname:formvalue(section)
1247         uci:foreach("system", "system",
1248                 function(s)
1249                         -- Make crond silent
1250                         uci:set("system", s['.name'], "cronloglevel", "10")
1251                         -- Make set timzone and zonename
1252                         uci:set("system", s['.name'], "zonename", "Europe/Berlin")
1253                         uci:set("system", s['.name'], "timezone", 'CET-1CEST,M3.5.0,M10.5.0/3')
1254                         -- Set hostname
1255                         if custom_hostname then
1256                                 uci:set("system", s['.name'], "hostname", custom_hostname)
1257                                 sys.hostname(custom_hostname)
1258                         else
1259                                 if new_hostname then
1260                                         if old_hostname == "OpenWrt" or old_hostname:match("^%d+-%d+-%d+-%d+$") then
1261                                                 uci:set("system", s['.name'], "hostname", new_hostname)
1262                                                 sys.hostname(new_hostname)
1263                                         end
1264                                 end
1265                         end
1266                 end)
1267
1268         -- Create time rdate_servers
1269         local rdate = uci:get_all("freifunk", "time")
1270         uci:delete_all("system", "time")
1271         uci:section("system", "time", "rdate_servers", rdate)
1272         rdate.server = rdate.rdate_servers
1273         rdate.rdate_servers = ""
1274         uci:delete_all("system", "rdate", nil)
1275         uci:section("system", "rdate", nil, rdate)
1276         uci:save("system")
1277
1278         -- Create http splash port 8082
1279         uci:set_list("uhttpd","main","listen_http",{"80"})
1280         uci:set_list("uhttpd","main","listen_https",{"443"})
1281         uci:save("uhttpd")
1282
1283         -- Read geos
1284         local latval = tonumber(lat:formvalue(section))
1285         local lonval = tonumber(lon:formvalue(section))
1286
1287         -- Save latlon to system too
1288         if latval and lonval then
1289                 uci:foreach("system", "system", function(s)
1290                         uci:set("system", s[".name"], "latlon",string.format("%.15f %.15f", latval, lonval))
1291                         uci:set("system", s[".name"], "latitude",string.format("%.15f", latval))
1292                         uci:set("system", s[".name"], "longitude",string.format("%.15f", lonval))
1293                 end)
1294         else
1295                 uci:foreach("system", "system", function(s)
1296                         uci:delete("system", s[".name"], "latlon")
1297                         uci:delete("system", s[".name"], "latitude")
1298                         uci:delete("system", s[".name"], "longitude")
1299                 end)
1300         end
1301         -- Delete old watchdog settings
1302         uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_watchdog.so.0.1"})
1303         -- Write new watchdog settings
1304         uci:section("olsrd", "LoadPlugin", nil, {
1305                 library  = "olsrd_watchdog.so.0.1",
1306                 file     = "/var/run/olsrd.watchdog",
1307                 interval = "30"
1308         })
1309
1310         -- Delete old nameservice settings
1311         uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_nameservice.so.0.3"})
1312         -- Write new nameservice settings
1313         uci:section("olsrd", "LoadPlugin", nil, {
1314                 library     = "olsrd_nameservice.so.0.3",
1315                 suffix      = "." .. suffix ,
1316                 hosts_file  = "/var/etc/hosts.olsr",
1317                 latlon_file = "/var/run/latlon.js",
1318                 lat         = latval and string.format("%.15f", latval) or "",
1319                 lon         = lonval and string.format("%.15f", lonval) or "",
1320                 services_file = "/var/etc/services.olsr"
1321         })
1322
1323         -- Import hosts and set domain
1324         uci:foreach("dhcp", "dnsmasq", function(s)
1325                 uci:set_list("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr")
1326                 uci:set("dhcp", s[".name"], "local", "/" .. suffix .. "/")
1327                 uci:set("dhcp", s[".name"], "domain", suffix)
1328         end)
1329
1330         -- Make sure that OLSR is enabled
1331         sys.init.enable("olsrd")
1332
1333         uci:save("olsrd")
1334         uci:save("dhcp")
1335         -- Import hosts and set domain
1336         if has_ipv6 then
1337                 uci:foreach("dhcp", "dnsmasq", function(s)
1338                         uci:set_list("dhcp", s[".name"], "addnhosts", {"/var/etc/hosts.olsr","/var/etc/hosts.olsr.ipv6"})
1339                 end)
1340         else
1341                 uci:foreach("dhcp", "dnsmasq", function(s)
1342                         uci:set_list("dhcp", s[".name"], "addnhosts", "/var/etc/hosts.olsr")
1343                 end)
1344         end
1345
1346         uci:save("dhcp")
1347
1348         -- Internet sharing
1349         local share_value = share:formvalue(section)
1350         if share_value == "1" then
1351                 uci:set("freifunk", "wizard", "netconfig", "1")
1352                 uci:section("firewall", "forwarding", nil, {src="freifunk", dest="wan"})
1353
1354                 if has_autoipv6 then
1355                         -- Set autoipv6 tunnel mode
1356                         uci:set("autoipv6", "olsr_node", "enable", "0")
1357                         uci:set("autoipv6", "tunnel", "enable", "1")
1358                         uci:save("autoipv6")
1359                 end
1360
1361                 -- Delete/Disable gateway plugin
1362                 uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw.so.0.5"})
1363                 uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"})
1364                 -- Enable gateway_plain plugin
1365                 uci:section("olsrd", "LoadPlugin", nil, {library="olsrd_dyn_gw_plain.so.0.4"})
1366                 sys.exec("chmod +x /etc/init.d/freifunk-p2pblock")
1367                 sys.init.enable("freifunk-p2pblock")
1368                 sys.init.enable("qos")
1369                 sys.exec('grep wan /etc/crontabs/root >/dev/null || echo "0 6 * * *     ifup wan" >> /etc/crontabs/root')
1370
1371                 if wansec:formvalue(section) == "1" then
1372                         uci:foreach("firewall", "zone",
1373                                 function(s)             
1374                                         if s.name == "wan" then
1375                                                 uci:set("firewall", s['.name'], "local_restrict", "1")
1376                                                 return false
1377                                         end
1378                                 end)
1379                 end
1380         else
1381                 uci:set("freifunk", "wizard", "netconfig", "0")
1382                 uci:save("freifunk")
1383                 if has_autoipv6 then
1384                         -- Set autoipv6 olsrd mode
1385                         uci:set("autoipv6", "olsr_node", "enable", "1")
1386                         uci:set("autoipv6", "tunnel", "enable", "0")
1387                         uci:save("autoipv6")
1388                 end
1389                 -- Delete gateway plugins
1390                 uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw.so.0.5"})
1391                 uci:delete_all("olsrd", "LoadPlugin", {library="olsrd_dyn_gw_plain.so.0.4"})
1392                 -- Disable gateway_plain plugin
1393                 uci:section("olsrd", "LoadPlugin", nil, {
1394                         library     = "olsrd_dyn_gw_plain.so.0.4",
1395                         ignore      = 1,
1396                 })
1397                 sys.init.disable("freifunk-p2pblock")
1398                 sys.init.disable("qos")
1399                 sys.exec("chmod -x /etc/init.d/freifunk-p2pblock")
1400                 uci:delete_all("firewall", "forwarding", {src="freifunk", dest="wan"})
1401                 uci:foreach("firewall", "zone",
1402                         function(s)             
1403                                 if s.name == "wan" then
1404                                         uci:delete("firewall", s['.name'], "local_restrict")
1405                                         return false
1406                                 end
1407                         end)
1408         end
1409         -- Write gvpn dummy interface
1410         if has_l2gvpn then
1411                 if gvpn then
1412                         local vpn = gvpn:formvalue(section)
1413                         if vpn then
1414                                 uci:delete_all("l2gvpn", "l2gvpn")
1415                                 uci:delete_all("l2gvpn", "node")
1416                                 uci:delete_all("l2gvpn", "supernode")
1417                                 -- Write olsr tunnel interface options
1418                                 local olsr_gvpnifbase = uci:get_all("freifunk", "olsr_gvpninterface")
1419                                 util.update(olsr_gvpnifbase, uci:get_all(external, "olsr_gvpninterface") or {})
1420                                 uci:section("olsrd", "Interface", nil, olsr_gvpnifbase)
1421                                 local vpnip = gvpnip:formvalue(section)
1422                                 local gvpnif = uci:get_all("freifunk", "gvpn_node")
1423                                 util.update(gvpnif, uci:get_all(external, "gvpn_node") or {})
1424                                 if gvpnif and gvpnif.tundev and vpnip then
1425                                         uci:section("network", "interface", gvpnif.tundev, {
1426                                                 ifname  =gvpnif.tundev ,
1427                                                 proto   ="static" ,
1428                                                 ipaddr  =vpnip ,
1429                                                 netmask =gvpnif.subnet or "255.255.255.192" ,
1430                                         })
1431                                         gvpnif.ip=""
1432                                         gvpnif.subnet=""
1433                                         gvpnif.up=""
1434                                         gvpnif.down=""
1435                                         gvpnif.mac="00:00:48:"..string.format("%X",string.gsub( vpnip, ".*%." , "" ))..":00:00"
1436                                         tools.firewall_zone_add_interface("freifunk", gvpnif.tundev)
1437                                         uci:section("l2gvpn", "node" , gvpnif.community , gvpnif)
1438                                         uci:save("network")
1439                                         uci:save("l2gvpn")
1440                                         uci:save("firewall")
1441                                         uci:save("olsrd")
1442                                         sys.init.enable("l2gvpn")
1443                                 end
1444                         else
1445                                 -- Disable l2gvpn
1446                                 sys.exec("/etc/init.d/l2gvpn stop")
1447                                 sys.init.disable("l2gvpn")
1448                         end
1449                 end
1450         end
1451
1452         uci:save("freifunk")
1453         uci:save("firewall")
1454         uci:save("olsrd")
1455         uci:save("system")
1456 end
1457
1458 return f
1459