modules/admin-full: ... and another issue, also remove wifi up workaround, its done...
[project/luci.git] / modules / admin-full / luasrc / model / cbi / admin_network / ifaces.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008-2011 Jo-Philipp Wich <xm@subsignal.org>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11         http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14 ]]--
15
16 local fs = require "nixio.fs"
17 local ut = require "luci.util"
18 local nw = require "luci.model.network"
19 local fw = require "luci.model.firewall"
20
21 arg[1] = arg[1] or ""
22
23 local has_dnsmasq  = fs.access("/etc/config/dhcp")
24 local has_firewall = fs.access("/etc/config/firewall")
25 local has_radvd    = fs.access("/etc/config/radvd")
26
27 local has_3g     = fs.access("/usr/bin/gcom")
28 local has_pptp   = fs.access("/usr/sbin/pptp")
29 local has_pppd   = fs.access("/usr/sbin/pppd")
30 local has_pppoe  = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
31 local has_pppoa  = fs.glob("/usr/lib/pppd/*/pppoatm.so")()
32 local has_ipv6   = fs.access("/proc/net/ipv6_route")
33 local has_6in4   = fs.access("/lib/network/6in4.sh")
34 local has_6to4   = fs.access("/lib/network/6to4.sh")
35 local has_relay  = fs.access("/lib/network/relay.sh")
36 local has_ahcp   = fs.access("/lib/network/ahcp.sh")
37
38 m = Map("network", translate("Interfaces") .. " - " .. arg[1]:upper(), translate("On this page you can configure the network interfaces. You can bridge several interfaces by ticking the \"bridge interfaces\" field and enter the names of several network interfaces separated by spaces. You can also use <abbr title=\"Virtual Local Area Network\">VLAN</abbr> notation <samp>INTERFACE.VLANNR</samp> (<abbr title=\"for example\">e.g.</abbr>: <samp>eth0.1</samp>)."))
39 m:chain("wireless")
40
41 if has_firewall then
42         m:chain("firewall")
43 end
44
45 if has_radvd then
46         m:chain("radvd")
47 end
48
49 nw.init(m.uci)
50 fw.init(m.uci)
51
52
53 local net = nw:get_network(arg[1])
54
55 -- redirect to overview page if network does not exist anymore (e.g. after a revert)
56 if not net then
57         luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
58         return
59 end
60
61 -- dhcp setup was requested, create section and reload page
62 if m:formvalue("cbid.dhcp._enable._enable") then
63         m.uci:section("dhcp", "dhcp", nil, {
64                 interface = arg[1],
65                 start     = "100",
66                 limit     = "150",
67                 leasetime = "12h"
68         })
69
70         m.uci:save("dhcp")
71         luci.http.redirect(luci.dispatcher.build_url("admin/network/network", arg[1]))
72         return
73 end
74
75 local ifc = net:get_interface()
76
77 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
78 s.addremove = false
79
80 s:tab("general", translate("General Setup"))
81 if has_ipv6  then s:tab("ipv6", translate("IPv6 Setup")) end
82 if has_pppd  then s:tab("ppp", translate("PPP Settings")) end
83 if has_pppoa then s:tab("atm", translate("ATM Settings")) end
84 if has_6in4 or has_6to4 then s:tab("tunnel", translate("Tunnel Settings")) end
85 if has_relay then s:tab("relay", translate("Relay Settings")) end
86 if has_ahcp then s:tab("ahcp", translate("AHCP Settings")) end
87 s:tab("physical", translate("Physical Settings"))
88 if has_firewall then s:tab("firewall", translate("Firewall Settings")) end
89
90 st = s:taboption("general", DummyValue, "__status", translate("Status"))
91 st.template = "admin_network/iface_status"
92 st.network  = arg[1]
93
94 --[[
95 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
96 back.value = ""
97 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
98 ]]
99
100 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
101 p.override_scheme = true
102 p.default = "static"
103 p:value("static", translate("static"))
104 p:value("dhcp", "DHCP")
105 if has_pppd  then p:value("ppp",   "PPP")     end
106 if has_pppoe then p:value("pppoe", "PPPoE")   end
107 if has_pppoa then p:value("pppoa", "PPPoA")   end
108 if has_3g    then p:value("3g",    "UMTS/3G") end
109 if has_pptp  then p:value("pptp",  "PPTP")    end
110 if has_6in4  then p:value("6in4",  "6in4")    end
111 if has_6to4  then p:value("6to4",  "6to4")    end
112 if has_relay then p:value("relay", "Relay")   end
113 if has_ahcp  then p:value("ahcp",  "AHCP")    end
114 p:value("none", translate("none"))
115
116 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
117         p.description = translate("You need to install \"comgt\" for UMTS/GPRS, \"ppp-mod-pppoe\" for PPPoE, \"ppp-mod-pppoa\" for PPPoA or \"pptp\" for PPtP support")
118 end
119
120 auto = s:taboption("physical", Flag, "auto", translate("Bring up on boot"))
121 auto.default = (m.uci:get("network", arg[1], "proto") == "none") and auto.disabled or auto.enabled
122
123 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
124 br.enabled = "bridge"
125 br.rmempty = true
126 br:depends("proto", "static")
127 br:depends("proto", "dhcp")
128 br:depends("proto", "none")
129
130 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
131         translate("Enables the Spanning Tree Protocol on this bridge"))
132 stp:depends("type", "bridge")
133 stp.rmempty = true
134
135 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
136 ifname_single.template = "cbi/network_ifacelist"
137 ifname_single.widget = "radio"
138 ifname_single.nobridges = true
139 ifname_single.rmempty = false
140 ifname_single.network = arg[1]
141 ifname_single:depends({ type = "", proto = "static" })
142 ifname_single:depends({ type = "", proto = "dhcp"   })
143 ifname_single:depends({ type = "", proto = "pppoe"  })
144 ifname_single:depends({ type = "", proto = "pppoa"  })
145 ifname_single:depends({ type = "", proto = "ahcp"   })
146 ifname_single:depends({ type = "", proto = "none"   })
147
148 function ifname_single.cfgvalue(self, s)
149         -- let the template figure out the related ifaces through the network model
150         return nil
151 end
152
153 function ifname_single.write(self, s, val)
154         local n = nw:get_network(s)
155         if n then
156                 local i
157                 local new_ifs = { }
158                 local old_ifs = { }
159
160                 for _, i in ipairs(n:get_interfaces() or { n:get_interface() }) do
161                         old_ifs[#old_ifs+1] = i:name()
162                 end
163
164                 for i in ut.imatch(val) do
165                         new_ifs[#new_ifs+1] = i
166
167                         -- if this is not a bridge, only assign first interface
168                         if self.option == "ifname_single" then
169                                 break
170                         end
171                 end
172
173                 table.sort(old_ifs)
174                 table.sort(new_ifs)
175
176                 for i = 1, math.max(#old_ifs, #new_ifs) do
177                         if old_ifs[i] ~= new_ifs[i] then
178                                 for i = 1, #old_ifs do
179                                         n:del_interface(old_ifs[i])
180                                 end
181                                 for i = 1, #new_ifs do
182                                         n:add_interface(new_ifs[i])
183                                 end
184                                 break
185                         end
186                 end
187         end
188 end
189
190
191 ifname_multi = s:taboption("physical", Value, "ifname_multi", translate("Interface"))
192 ifname_multi.template = "cbi/network_ifacelist"
193 ifname_multi.nobridges = true
194 ifname_multi.rmempty = false
195 ifname_multi.network = arg[1]
196 ifname_multi.widget = "checkbox"
197 ifname_multi:depends("type", "bridge")
198 ifname_multi.cfgvalue = ifname_single.cfgvalue
199 ifname_multi.write = ifname_single.write
200
201
202 if has_firewall then
203         fwzone = s:taboption("firewall", Value, "_fwzone",
204                 translate("Create / Assign firewall-zone"),
205                 translate("Choose the firewall zone you want to assign to this interface. Select <em>unspecified</em> to remove the interface from the associated zone or fill out the <em>create</em> field to define a new zone and attach the interface to it."))
206
207         fwzone.template = "cbi/firewall_zonelist"
208         fwzone.network = arg[1]
209         fwzone.rmempty = false
210
211         function fwzone.cfgvalue(self, section)
212                 self.iface = section
213                 local z = fw:get_zone_by_network(section)
214                 return z and z:name()
215         end
216
217         function fwzone.write(self, section, value)
218                 local zone = fw:get_zone(value)
219
220                 if not zone and value == '-' then
221                         value = m:formvalue(self:cbid(section) .. ".newzone")
222                         if value and #value > 0 then
223                                 zone = fw:add_zone(value)
224                         else
225                                 fw:del_network(section)
226                         end
227                 end
228
229                 if zone then
230                         fw:del_network(section)
231                         zone:add_network(section)
232                 end
233         end
234 end
235
236 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
237 ipaddr.optional = true
238 ipaddr.datatype = "ip4addr"
239 ipaddr:depends("proto", "static")
240
241 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
242 nm.optional = true
243 nm.datatype = "ip4addr"
244 nm:depends("proto", "static")
245 nm:value("255.255.255.0")
246 nm:value("255.255.0.0")
247 nm:value("255.0.0.0")
248
249 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
250 gw.optional = true
251 gw.datatype = "ip4addr"
252 gw:depends("proto", "static")
253 gw:depends("proto", "dhcp")
254
255 bcast = s:taboption("general", Value, "broadcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
256 bcast.optional = true
257 bcast.datatype = "ip4addr"
258 bcast:depends("proto", "static")
259
260 if has_ipv6 then
261         ip6addr = s:taboption("ipv6", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
262         ip6addr.optional = true
263         ip6addr.datatype = "ip6addr"
264         ip6addr:depends("proto", "static")
265         ip6addr:depends("proto", "6in4")
266
267         ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
268         ip6gw.optional = true
269         ip6gw.datatype = "ip6addr"
270         ip6gw:depends("proto", "static")
271
272
273         ra = s:taboption("ipv6", Flag, "accept_ra", translate("Accept Router Advertisements"))
274         ra.default = m.uci:get("network", arg[1], "proto") == "dhcp" and ra.enabled or ra.disabled
275         ra:depends("proto", "static")
276         ra:depends("proto", "dhcp")
277         ra:depends("proto", "none")
278
279         rs = s:taboption("ipv6", Flag, "send_rs", translate("Send Router Solicitiations"))
280         rs.default = m.uci:get("network", arg[1], "proto") ~= "dhcp" and rs.enabled or rs.disabled
281         rs:depends("proto", "static")
282         rs:depends("proto", "dhcp")
283         rs:depends("proto", "none")
284 end
285
286 dns = s:taboption("general", DynamicList, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
287         translate("You can specify multiple DNS servers here, press enter to add a new entry. Servers entered here will override " ..
288                 "automatically assigned ones."))
289
290 dns.optional = true
291 dns.cast = "string"
292 dns.datatype = "ipaddr"
293 dns:depends({ peerdns = "", proto = "static" })
294 dns:depends({ peerdns = "", proto = "dhcp"   })
295 dns:depends({ peerdns = "", proto = "pppoe"  })
296 dns:depends({ peerdns = "", proto = "pppoa"  })
297 dns:depends({ peerdns = "", proto = "none"   })
298
299 mtu = s:taboption("physical", Value, "mtu", "MTU")
300 mtu.optional = true
301 mtu.datatype = "uinteger"
302 mtu.placeholder = 1500
303 mtu:depends("proto", "static")
304 mtu:depends("proto", "dhcp")
305 mtu:depends("proto", "pppoe")
306 mtu:depends("proto", "pppoa")
307 mtu:depends("proto", "6in4")
308 mtu:depends("proto", "6to4")
309 mtu:depends("proto", "none")
310
311 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
312 srv:depends("proto", "pptp")
313 srv.optional = false
314 srv.datatype = "host"
315
316 if has_6in4 then
317         peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
318         peer.optional = false
319         peer.datatype = "ip4addr"
320         peer:depends("proto", "6in4")
321 end
322
323 if has_6in4 or has_6to4 then
324         ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
325         ttl.default = "64"
326         ttl.optional = true
327         ttl.datatype = "uinteger"
328         ttl:depends("proto", "6in4")
329         ttl:depends("proto", "6to4")
330 end
331
332 if has_6to4 then
333         advi = s:taboption("general", Value, "adv_interface", translate("Advertise IPv6 on network"))
334         advi.widget = "checkbox"
335         advi.exclude = arg[1]
336         advi.default = "lan"
337         advi.template = "cbi/network_netlist"
338         advi.nocreate = true
339         advi.nobridges = true
340         advi:depends("proto", "6to4")
341
342         advn = s:taboption("general", Value, "adv_subnet", translate("Advertised network ID"), translate("Allowed range is 1 to FFFF"))
343         advn.default = "1"
344         advn:depends("proto", "6to4")
345
346         function advn.write(self, section, value)
347                 value = tonumber(value, 16) or 1
348
349                 if value > 65535 then value = 65535
350                 elseif value < 1 then value = 1 end
351
352                 Value.write(self, section, "%X" % value)
353         end
354 end
355
356 if has_relay then
357         rnet = s:taboption("general", Value, "network", translate("Relay between networks"))
358         rnet.widget = "checkbox"
359         rnet.exclude = arg[1]
360         rnet.template = "cbi/network_netlist"
361         rnet.nocreate = true
362         rnet.nobridges = true
363         rnet:depends("proto", "relay")
364 end
365
366 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
367 mac:depends("proto", "none")
368 mac:depends("proto", "static")
369 mac:depends("proto", "dhcp")
370 mac.placeholder = ifc and ifc:mac():upper()
371
372 if has_3g then
373         service = s:taboption("general", ListValue, "service", translate("Service type"))
374         service:value("", translate("-- Please choose --"))
375         service:value("umts", "UMTS/GPRS")
376         service:value("cdma", "CDMA")
377         service:value("evdo", "EV-DO")
378         service:depends("proto", "3g")
379         service.rmempty = true
380
381         apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
382         apn:depends("proto", "3g")
383
384         pincode = s:taboption("general", Value, "pincode",
385          translate("PIN code"),
386          translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
387         )
388         pincode:depends("proto", "3g")
389 end
390
391 if has_6in4 then
392         tunid = s:taboption("general", Value, "tunnelid", translate("HE.net Tunnel ID"))
393         tunid.optional = true
394         tunid.datatype = "uinteger"
395         tunid:depends("proto", "6in4")
396 end
397
398 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
399         user = s:taboption("general", Value, "username", translate("Username"))
400         user.rmempty = true
401         user:depends("proto", "pptp")
402         user:depends("proto", "pppoe")
403         user:depends("proto", "pppoa")
404         user:depends("proto", "ppp")
405         user:depends("proto", "3g")
406         user:depends("proto", "6in4")
407
408         pass = s:taboption("general", Value, "password", translate("Password"))
409         pass.rmempty = true
410         pass.password = true
411         pass:depends("proto", "pptp")
412         pass:depends("proto", "pppoe")
413         pass:depends("proto", "pppoa")
414         pass:depends("proto", "ppp")
415         pass:depends("proto", "3g")
416         pass:depends("proto", "6in4")
417 end
418
419 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
420         ka = s:taboption("ppp", Value, "keepalive",
421          translate("Keep-Alive"),
422          translate("Number of failed connection tests to initiate automatic reconnect")
423         )
424         ka:depends("proto", "pptp")
425         ka:depends("proto", "pppoe")
426         ka:depends("proto", "pppoa")
427         ka:depends("proto", "ppp")
428         ka:depends("proto", "3g")
429
430         demand = s:taboption("ppp", Value, "demand",
431          translate("Automatic Disconnect"),
432          translate("Time (in seconds) after which an unused connection will be closed")
433         )
434         demand.optional = true
435         demand.datatype = "uinteger"
436         demand:depends("proto", "pptp")
437         demand:depends("proto", "pppoe")
438         demand:depends("proto", "pppoa")
439         demand:depends("proto", "ppp")
440         demand:depends("proto", "3g")
441 end
442
443 if has_pppoa then
444         encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
445         encaps:depends("proto", "pppoa")
446         encaps:value("vc", "VC-Mux")
447         encaps:value("llc", "LLC")
448
449         atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
450         atmdev:depends("proto", "pppoa")
451         atmdev.default = "0"
452         atmdev.datatype = "uinteger"
453
454         vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
455         vci:depends("proto", "pppoa")
456         vci.default = "35"
457         vci.datatype = "uinteger"
458
459         vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
460         vpi:depends("proto", "pppoa")
461         vpi.default = "8"
462         vpi.datatype = "uinteger"
463 end
464
465 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
466         device = s:taboption("general", Value, "device",
467          translate("Modem device"),
468          translate("The device node of your modem, e.g. /dev/ttyUSB0")
469         )
470         device:depends("proto", "ppp")
471         device:depends("proto", "3g")
472
473         defaultroute = s:taboption("ppp", Flag, "defaultroute",
474          translate("Replace default route"),
475          translate("Let pppd replace the current default route to use the PPP interface after successful connect")
476         )
477         defaultroute:depends("proto", "ppp")
478         defaultroute:depends("proto", "pppoa")
479         defaultroute:depends("proto", "pppoe")
480         defaultroute:depends("proto", "pptp")
481         defaultroute:depends("proto", "3g")
482         defaultroute.default = defaultroute.enabled
483
484         peerdns = s:taboption("ppp", Flag, "peerdns",
485          translate("Use peer DNS"),
486          translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
487         )
488         peerdns:depends("proto", "ppp")
489         peerdns:depends("proto", "pppoa")
490         peerdns:depends("proto", "pppoe")
491         peerdns:depends("proto", "pptp")
492         peerdns:depends("proto", "3g")
493         peerdns.default = peerdns.enabled
494
495         if has_ipv6 then
496                 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
497                 ipv6:depends("proto", "ppp")
498                 ipv6:depends("proto", "pppoa")
499                 ipv6:depends("proto", "pppoe")
500                 ipv6:depends("proto", "pptp")
501                 ipv6:depends("proto", "3g")
502         end
503
504         connect = s:taboption("ppp", Value, "connect",
505          translate("Connect script"),
506          translate("Let pppd run this script after establishing the PPP link")
507         )
508         connect:depends("proto", "ppp")
509         connect:depends("proto", "pppoe")
510         connect:depends("proto", "pppoa")
511         connect:depends("proto", "pptp")
512         connect:depends("proto", "3g")
513
514         disconnect = s:taboption("ppp", Value, "disconnect",
515          translate("Disconnect script"),
516          translate("Let pppd run this script before tearing down the PPP link")
517         )
518         disconnect:depends("proto", "ppp")
519         disconnect:depends("proto", "pppoe")
520         disconnect:depends("proto", "pppoa")
521         disconnect:depends("proto", "pptp")
522         disconnect:depends("proto", "3g")
523
524         pppd_options = s:taboption("ppp", Value, "pppd_options",
525          translate("Additional pppd options"),
526          translate("Specify additional command line arguments for pppd here")
527         )
528         pppd_options:depends("proto", "ppp")
529         pppd_options:depends("proto", "pppoa")
530         pppd_options:depends("proto", "pppoe")
531         pppd_options:depends("proto", "pptp")
532         pppd_options:depends("proto", "3g")
533
534         maxwait = s:taboption("ppp", Value, "maxwait",
535          translate("Setup wait time"),
536          translate("Seconds to wait for the modem to become ready before attempting to connect")
537         )
538         maxwait:depends("proto", "3g")
539         maxwait.default  = "0"
540         maxwait.optional = true
541         maxwait.datatype = "uinteger"
542 end
543
544 if has_relay then
545         fb = s:taboption("relay", Flag, "forward_bcast", translate("Forward broadcasts"))
546         fb.default = fb.enabled
547         fb:depends("proto", "relay")
548
549         fd = s:taboption("relay", Flag, "forward_dhcp", translate("Forward DHCP"))
550         fd.default = fd.enabled
551         fd:depends("proto", "relay")
552
553         gw = s:taboption("relay", Value, "relay_gateway", translate("Override Gateway"))
554         gw.optional    = true
555         gw.placeholder = "0.0.0.0"
556         gw.datatype    = "ip4addr"
557         gw:depends("proto", "relay")
558         function gw.cfgvalue(self, section)
559                 return m.uci:get("network", section, "gateway")
560         end
561         function gw.write(self, section, value)
562                 return m.uci:set("network", section, "gateway", value)
563         end
564         function gw.delete(self, section)
565                 return m.uci:delete("network", section, "gateway")
566         end
567
568         expiry = s:taboption("relay", Value, "expiry", translate("Host expiry timeout"))
569         expiry.optional    = true
570         expiry.placeholder = 30
571         expiry.datatype    = "uinteger"
572         expiry:depends("proto", "relay")
573
574         retry = s:taboption("relay", Value, "retry", translate("ARP ping retries"))
575         retry.optional     = true
576         retry.placeholder  = 5
577         retry.datatype     = "uinteger"
578         retry:depends("proto", "relay")
579
580         table = s:taboption("relay", Value, "table", translate("Routing table ID"))
581         table.optional     = true
582         table.placeholder  = 16800
583         table.datatype     = "uinteger"
584         table:depends("proto", "relay")
585 end
586
587 if has_ahcp then
588         mca = s:taboption("ahcp", Value, "multicast_address", translate("Multicast address"))
589         mca.optional    = true
590         mca.placeholder = "ff02::cca6:c0f9:e182:5359"
591         mca.datatype    = "ip6addr"
592         mca:depends("proto", "ahcp")
593
594         port = s:taboption("ahcp", Value, "port", translate("Port"))
595         port.optional    = true
596         port.placeholder = 5359
597         port.datatype    = "port"
598         port:depends("proto", "ahcp")
599
600         fam = s:taboption("ahcp", ListValue, "_family", translate("Protocol family"))
601         fam:value("", translate("IPv4 and IPv6"))
602         fam:value("ipv4", translate("IPv4 only"))
603         fam:value("ipv6", translate("IPv6 only"))
604         fam:depends("proto", "ahcp")
605
606         function fam.cfgvalue(self, section)
607                 local v4 = m.uci:get_bool("network", section, "ipv4_only")
608                 local v6 = m.uci:get_bool("network", section, "ipv6_only")
609                 if v4 then
610                         return "ipv4"
611                 elseif v6 then
612                         return "ipv6"
613                 end
614                 return ""
615         end
616
617         function fam.write(self, section, value)
618                 if value == "ipv4" then
619                         m.uci:set("network", section, "ipv4_only", "true")
620                         m.uci:delete("network", section, "ipv6_only")
621                 elseif value == "ipv6" then
622                         m.uci:set("network", section, "ipv6_only", "true")
623                         m.uci:delete("network", section, "ipv4_only")
624                 end
625         end
626
627         function fam.remove(self, section)
628                 m.uci:delete("network", section, "ipv4_only")
629                 m.uci:delete("network", section, "ipv6_only")
630         end
631
632         nodns = s:taboption("ahcp", Flag, "no_dns", translate("Disable DNS setup"))
633         nodns.optional = true
634         nodns.enabled  = "true"
635         nodns.disabled = "false"
636         nodns.default  = nodns.disabled
637         nodns:depends("proto", "ahcp")
638
639         ltime = s:taboption("ahcp", Value, "lease_time", translate("Lease validity time"))
640         ltime.optional    = true
641         ltime.placeholder = 3666
642         ltime.datatype    = "uinteger"
643         ltime:depends("proto", "ahcp")
644 end
645
646 if net:proto() ~= "relay" then
647         s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
648         s2.addremove = true
649
650         s2:depends("interface", arg[1])
651         s2.defaults.interface = arg[1]
652
653         s2:tab("general", translate("General Setup"))
654         s2.defaults.proto = "static"
655
656         ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
657         ip.optional = true
658         ip.datatype = "ip4addr"
659
660         nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
661         nm.optional = true
662         nm.datatype = "ip4addr"
663         nm:value("255.255.255.0")
664         nm:value("255.255.0.0")
665         nm:value("255.0.0.0")
666
667         gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
668         gw.optional = true
669         gw.datatype = "ip4addr"
670
671         if has_ipv6 then
672                 s2:tab("ipv6", translate("IPv6 Setup"))
673
674                 ip6 = s2:taboption("ipv6", Value, "ip6addr", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Address"), translate("<abbr title=\"Classless Inter-Domain Routing\">CIDR</abbr>-Notation: address/prefix"))
675                 ip6.optional = true
676                 ip6.datatype = "ip6addr"
677
678                 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
679                 gw6.optional = true
680                 gw6.datatype = "ip6addr"
681         end
682
683         s2:tab("advanced", translate("Advanced Settings"))
684
685         bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
686         bcast.optional = true
687         bcast.datatype = "ip4addr"
688
689         dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
690         dns.optional = true
691         dns.datatype = "ip4addr"
692 end
693
694
695 --
696 -- Display DNS settings if dnsmasq is available
697 --
698
699 if has_dnsmasq and net:proto() == "static" then
700         m2 = Map("dhcp", "", "")
701
702         local has_section = false
703
704         m2.uci:foreach("dhcp", "dhcp", function(s)
705                 if s.interface == arg[1] then
706                         has_section = true
707                         return false
708                 end
709         end)
710
711         if not has_section then
712
713                 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
714                 s.anonymous   = true
715                 s.cfgsections = function() return { "_enable" } end
716
717                 x = s:option(Button, "_enable")
718                 x.title      = translate("No DHCP Server configured for this interface")
719                 x.inputtitle = translate("Setup DHCP Server")
720                 x.inputstyle = "apply"
721
722         else
723
724                 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
725                 s.addremove = false
726                 s.anonymous = true
727                 s:tab("general",  translate("General Setup"))
728                 s:tab("advanced", translate("Advanced Settings"))
729
730                 function s.filter(self, section)
731                         return m2.uci:get("dhcp", section, "interface") == arg[1]
732                 end
733
734                 local ignore = s:taboption("general", Flag, "ignore",
735                         translate("Ignore interface"),
736                         translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
737                                 "this interface."))
738
739                 local start = s:taboption("general", Value, "start", translate("Start"),
740                         translate("Lowest leased address as offset from the network address."))
741                 start.optional = true
742                 start.datatype = "uinteger"
743                 start.default = "100"
744
745                 local limit = s:taboption("general", Value, "limit", translate("Limit"),
746                         translate("Maximum number of leased addresses."))
747                 limit.optional = true
748                 limit.datatype = "uinteger"
749                 limit.default = "150"
750
751                 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
752                         translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
753                 ltime.rmempty = true
754                 ltime.default = "12h"
755
756                 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
757                         translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
758                         translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
759                                 "clients having static leases will be served."))
760                 dd.default = dd.enabled
761
762                 s:taboption("advanced", Flag, "force", translate("Force"),
763                         translate("Force DHCP on this network even if another server is detected."))
764
765                 -- XXX: is this actually useful?
766                 --s:taboption("advanced", Value, "name", translate("Name"),
767                 --      translate("Define a name for this network."))
768
769                 mask = s:taboption("advanced", Value, "netmask",
770                         translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
771                         translate("Override the netmask sent to clients. Normally it is calculated " ..
772                                 "from the subnet that is served."))
773
774                 mask.optional = true
775                 mask.datatype = "ip4addr"
776
777                 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
778                         translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
779                                 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
780
781                 for i, n in ipairs(s.children) do
782                         if n ~= ignore then
783                                 n:depends("ignore", "")
784                         end
785                 end
786
787         end
788 end
789
790 return m, m2