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