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