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