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