modules/admin-full: allown symbolic hostnames for pptp server option
[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
26 local has_3g     = fs.access("/usr/bin/gcom")
27 local has_pptp   = fs.access("/usr/sbin/pptp")
28 local has_pppd   = fs.access("/usr/sbin/pppd")
29 local has_pppoe  = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
30 local has_pppoa  = fs.glob("/usr/lib/pppd/*/pppoatm.so")()
31 local has_ipv6   = fs.access("/proc/net/ipv6_route")
32 local has_6in4   = fs.access("/lib/network/6in4.sh")
33 local has_6to4   = fs.access("/lib/network/6to4.sh")
34
35 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>)."))
36 m:chain("wireless")
37
38 if has_firewall then
39         m:chain("firewall")
40 end
41
42 nw.init(m.uci)
43 fw.init(m.uci)
44
45
46 local net = nw:get_network(arg[1])
47
48 -- redirect to overview page if network does not exist anymore (e.g. after a revert)
49 if not net then
50         luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
51         return
52 end
53
54 local ifc = net:get_interfaces()[1]
55
56 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
57 s.addremove = false
58
59 s:tab("general", translate("General Setup"))
60 if has_ipv6  then s:tab("ipv6", translate("IPv6 Setup")) end
61 if has_pppd  then s:tab("ppp", translate("PPP Settings")) end
62 if has_pppoa then s:tab("atm", translate("ATM Settings")) end
63 if has_6in4 or has_6to4 then s:tab("tunnel", translate("Tunnel Settings")) end
64 s:tab("physical", translate("Physical Settings"))
65 if has_firewall then s:tab("firewall", translate("Firewall Settings")) end
66
67 st = s:taboption("general", DummyValue, "__status", translate("Status"))
68 st.template = "admin_network/iface_status"
69 st.network  = arg[1]
70
71 --[[
72 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
73 back.value = ""
74 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
75 ]]
76
77 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
78 p.override_scheme = true
79 p.default = "static"
80 p:value("static", translate("static"))
81 p:value("dhcp", "DHCP")
82 if has_pppd  then p:value("ppp",   "PPP")     end
83 if has_pppoe then p:value("pppoe", "PPPoE")   end
84 if has_pppoa then p:value("pppoa", "PPPoA")   end
85 if has_3g    then p:value("3g",    "UMTS/3G") end
86 if has_pptp  then p:value("pptp",  "PPTP")    end
87 if has_6in4  then p:value("6in4",  "6in4")    end
88 if has_6to4  then p:value("6to4",  "6to4")    end
89 p:value("none", translate("none"))
90
91 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
92         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")
93 end
94
95 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
96 br.enabled = "bridge"
97 br.rmempty = true
98 br:depends("proto", "static")
99 br:depends("proto", "dhcp")
100 br:depends("proto", "none")
101
102 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
103         translate("Enables the Spanning Tree Protocol on this bridge"))
104 stp:depends("type", "bridge")
105 stp.rmempty = true
106
107 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
108 ifname_single.template = "cbi/network_ifacelist"
109 ifname_single.widget = "radio"
110 ifname_single.nobridges = true
111 ifname_single.network = arg[1]
112 ifname_single.rmempty = true
113 ifname_single:depends({ type = "", proto = "static" })
114 ifname_single:depends({ type = "", proto = "dhcp"   })
115 ifname_single:depends({ type = "", proto = "pppoe"  })
116 ifname_single:depends({ type = "", proto = "pppoa"  })
117 ifname_single:depends({ type = "", proto = "none"   })
118
119 function ifname_single.cfgvalue(self, s)
120         return self.map.uci:get("network", s, "ifname")
121 end
122
123 function ifname_single.write(self, s, val)
124         local n = nw:get_network(s)
125         if n then
126                 local i
127                 for _, i in ipairs(n:get_interfaces()) do
128                         n:del_interface(i)
129                 end
130
131                 for i in ut.imatch(val) do
132                         n:add_interface(i)
133
134                         -- if this is not a bridge, only assign first interface
135                         if self.option == "ifname_single" then
136                                 break
137                         end
138                 end
139         end
140 end
141
142 ifname_multi = s:taboption("physical", Value, "ifname_multi", translate("Interface"))
143 ifname_multi.template = "cbi/network_ifacelist"
144 ifname_multi.nobridges = true
145 ifname_multi.network = arg[1]
146 ifname_multi.widget = "checkbox"
147 ifname_multi:depends("type", "bridge")
148 ifname_multi.cfgvalue = ifname_single.cfgvalue
149 ifname_multi.write = ifname_single.write
150
151
152 if has_firewall then
153         fwzone = s:taboption("firewall", Value, "_fwzone",
154                 translate("Create / Assign firewall-zone"),
155                 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."))
156
157         fwzone.template = "cbi/firewall_zonelist"
158         fwzone.network = arg[1]
159         fwzone.rmempty = false
160
161         function fwzone.cfgvalue(self, section)
162                 self.iface = section
163                 local z = fw:get_zone_by_network(section)
164                 return z and z:name()
165         end
166
167         function fwzone.write(self, section, value)
168                 local zone = fw:get_zone(value)
169
170                 if not zone and value == '-' then
171                         value = m:formvalue(self:cbid(section) .. ".newzone")
172                         if value and #value > 0 then
173                                 zone = fw:add_zone(value)
174                         else
175                                 fw:del_network(section)
176                         end
177                 end
178
179                 if zone then
180                         fw:del_network(section)
181                         zone:add_network(section)
182                 end
183         end
184 end
185
186 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
187 ipaddr.optional = true
188 ipaddr.datatype = "ip4addr"
189 ipaddr:depends("proto", "static")
190
191 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
192 nm.optional = true
193 nm.datatype = "ip4addr"
194 nm:depends("proto", "static")
195 nm:value("255.255.255.0")
196 nm:value("255.255.0.0")
197 nm:value("255.0.0.0")
198
199 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
200 gw.optional = true
201 gw.datatype = "ip4addr"
202 gw:depends("proto", "static")
203
204 bcast = s:taboption("general", Value, "broadcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
205 bcast.optional = true
206 bcast.datatype = "ip4addr"
207 bcast:depends("proto", "static")
208
209 if has_ipv6 then
210         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"))
211         ip6addr.optional = true
212         ip6addr.datatype = "ip6addr"
213         ip6addr:depends("proto", "static")
214         ip6addr:depends("proto", "6in4")
215
216         ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
217         ip6gw.optional = true
218         ip6gw.datatype = "ip6addr"
219         ip6gw:depends("proto", "static")
220 end
221
222 dns = s:taboption("general", DynamicList, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
223         translate("You can specify multiple DNS servers here, press enter to add a new entry. Servers entered here will override " ..
224                 "automatically assigned ones."))
225
226 dns.optional = true
227 dns.cast = "string"
228 dns.datatype = "ipaddr"
229 dns:depends({ peerdns = "", proto = "static" })
230 dns:depends({ peerdns = "", proto = "dhcp"   })
231 dns:depends({ peerdns = "", proto = "pppoe"  })
232 dns:depends({ peerdns = "", proto = "pppoa"  })
233 dns:depends({ peerdns = "", proto = "none"   })
234
235 mtu = s:taboption("physical", Value, "mtu", "MTU")
236 mtu.optional = true
237 mtu.datatype = "uinteger"
238 mtu.placeholder = 1500
239
240 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
241 srv:depends("proto", "pptp")
242 srv.optional = false
243 srv.datatype = "host"
244
245 if has_6in4 then
246         peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
247         peer.optional = false
248         peer.datatype = "ip4addr"
249         peer:depends("proto", "6in4")
250 end
251
252 if has_6in4 or has_6to4 then
253         ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
254         ttl.default = "64"
255         ttl.optional = true
256         ttl.datatype = "uinteger"
257         ttl:depends("proto", "6in4")
258         ttl:depends("proto", "6to4")
259 end
260
261 if has_6to4 then
262         advi = s:taboption("general", Value, "adv_interface", translate("Advertise IPv6 on network"))
263         advi.widget = "checkbox"
264         advi.exclude = arg[1]
265         advi.default = "lan"
266         advi.template = "cbi/network_netlist"
267         advi.nocreate = true
268         advi.nobridges = true
269         advi:depends("proto", "6to4")
270
271         advn = s:taboption("general", Value, "adv_subnet", translate("Advertised network ID"), translate("Allowed range is 1 to FFFF"))
272         advn.default = "1"
273         advn:depends("proto", "6to4")
274
275         function advn.write(self, section, value)
276                 value = tonumber(value, 16) or 1
277
278                 if value > 65535 then value = 65535
279                 elseif value < 1 then value = 1 end
280
281                 Value.write(self, section, "%X" % value)
282         end
283 end
284
285 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
286 mac:depends("proto", "none")
287 mac:depends("proto", "static")
288 mac:depends("proto", "dhcp")
289 mac.placeholder = ifc and ifc:mac():upper()
290
291 if has_3g then
292         service = s:taboption("general", ListValue, "service", translate("Service type"))
293         service:value("", translate("-- Please choose --"))
294         service:value("umts", "UMTS/GPRS")
295         service:value("cdma", "CDMA")
296         service:value("evdo", "EV-DO")
297         service:depends("proto", "3g")
298         service.rmempty = true
299
300         apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
301         apn:depends("proto", "3g")
302
303         pincode = s:taboption("general", Value, "pincode",
304          translate("PIN code"),
305          translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
306         )
307         pincode:depends("proto", "3g")
308 end
309
310 if has_6in4 then
311         tunid = s:taboption("general", Value, "tunnelid", translate("HE.net Tunnel ID"))
312         tunid.optional = true
313         tunid.datatype = "uinteger"
314         tunid:depends("proto", "6in4")
315 end
316
317 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
318         user = s:taboption("general", Value, "username", translate("Username"))
319         user.rmempty = true
320         user:depends("proto", "pptp")
321         user:depends("proto", "pppoe")
322         user:depends("proto", "pppoa")
323         user:depends("proto", "ppp")
324         user:depends("proto", "3g")
325         user:depends("proto", "6in4")
326
327         pass = s:taboption("general", Value, "password", translate("Password"))
328         pass.rmempty = true
329         pass.password = true
330         pass:depends("proto", "pptp")
331         pass:depends("proto", "pppoe")
332         pass:depends("proto", "pppoa")
333         pass:depends("proto", "ppp")
334         pass:depends("proto", "3g")
335         pass:depends("proto", "6in4")
336 end
337
338 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
339         ka = s:taboption("ppp", Value, "keepalive",
340          translate("Keep-Alive"),
341          translate("Number of failed connection tests to initiate automatic reconnect")
342         )
343         ka:depends("proto", "pptp")
344         ka:depends("proto", "pppoe")
345         ka:depends("proto", "pppoa")
346         ka:depends("proto", "ppp")
347         ka:depends("proto", "3g")
348
349         demand = s:taboption("ppp", Value, "demand",
350          translate("Automatic Disconnect"),
351          translate("Time (in seconds) after which an unused connection will be closed")
352         )
353         demand.optional = true
354         demand.datatype = "uinteger"
355         demand:depends("proto", "pptp")
356         demand:depends("proto", "pppoe")
357         demand:depends("proto", "pppoa")
358         demand:depends("proto", "ppp")
359         demand:depends("proto", "3g")
360 end
361
362 if has_pppoa then
363         encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
364         encaps:depends("proto", "pppoa")
365         encaps:value("vc", "VC-Mux")
366         encaps:value("llc", "LLC")
367
368         atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
369         atmdev:depends("proto", "pppoa")
370         atmdev.default = "0"
371         atmdev.datatype = "uinteger"
372
373         vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
374         vci:depends("proto", "pppoa")
375         vci.default = "35"
376         vci.datatype = "uinteger"
377
378         vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
379         vpi:depends("proto", "pppoa")
380         vpi.default = "8"
381         vpi.datatype = "uinteger"
382 end
383
384 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
385         device = s:taboption("general", Value, "device",
386          translate("Modem device"),
387          translate("The device node of your modem, e.g. /dev/ttyUSB0")
388         )
389         device:depends("proto", "ppp")
390         device:depends("proto", "3g")
391
392         defaultroute = s:taboption("ppp", Flag, "defaultroute",
393          translate("Replace default route"),
394          translate("Let pppd replace the current default route to use the PPP interface after successful connect")
395         )
396         defaultroute:depends("proto", "ppp")
397         defaultroute:depends("proto", "pppoa")
398         defaultroute:depends("proto", "pppoe")
399         defaultroute:depends("proto", "pptp")
400         defaultroute:depends("proto", "3g")
401         defaultroute.rmempty = false
402         function defaultroute.cfgvalue(...)
403                 return ( AbstractValue.cfgvalue(...) or '1' )
404         end
405
406         peerdns = s:taboption("ppp", Flag, "peerdns",
407          translate("Use peer DNS"),
408          translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
409         )
410         peerdns:depends("proto", "ppp")
411         peerdns:depends("proto", "pppoa")
412         peerdns:depends("proto", "pppoe")
413         peerdns:depends("proto", "pptp")
414         peerdns:depends("proto", "3g")
415         peerdns.rmempty = false
416         function peerdns.cfgvalue(...)
417                 return ( AbstractValue.cfgvalue(...) or '1' )
418         end
419
420         if has_ipv6 then
421                 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
422                 ipv6:depends("proto", "ppp")
423                 ipv6:depends("proto", "pppoa")
424                 ipv6:depends("proto", "pppoe")
425                 ipv6:depends("proto", "pptp")
426                 ipv6:depends("proto", "3g")
427         end
428
429         connect = s:taboption("ppp", Value, "connect",
430          translate("Connect script"),
431          translate("Let pppd run this script after establishing the PPP link")
432         )
433         connect:depends("proto", "ppp")
434         connect:depends("proto", "pppoe")
435         connect:depends("proto", "pppoa")
436         connect:depends("proto", "pptp")
437         connect:depends("proto", "3g")
438
439         disconnect = s:taboption("ppp", Value, "disconnect",
440          translate("Disconnect script"),
441          translate("Let pppd run this script before tearing down the PPP link")
442         )
443         disconnect:depends("proto", "ppp")
444         disconnect:depends("proto", "pppoe")
445         disconnect:depends("proto", "pppoa")
446         disconnect:depends("proto", "pptp")
447         disconnect:depends("proto", "3g")
448
449         pppd_options = s:taboption("ppp", Value, "pppd_options",
450          translate("Additional pppd options"),
451          translate("Specify additional command line arguments for pppd here")
452         )
453         pppd_options:depends("proto", "ppp")
454         pppd_options:depends("proto", "pppoa")
455         pppd_options:depends("proto", "pppoe")
456         pppd_options:depends("proto", "pptp")
457         pppd_options:depends("proto", "3g")
458
459         maxwait = s:taboption("ppp", Value, "maxwait",
460          translate("Setup wait time"),
461          translate("Seconds to wait for the modem to become ready before attempting to connect")
462         )
463         maxwait:depends("proto", "3g")
464         maxwait.default  = "0"
465         maxwait.optional = true
466         maxwait.datatype = "uinteger"
467 end
468
469 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
470 s2.addremove = true
471
472 s2:depends("interface", arg[1])
473 s2.defaults.interface = arg[1]
474
475 s2:tab("general", translate("General Setup"))
476 s2.defaults.proto = "static"
477
478 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
479 ip.optional = true
480 ip.datatype = "ip4addr"
481
482 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
483 nm.optional = true
484 nm.datatype = "ip4addr"
485 nm:value("255.255.255.0")
486 nm:value("255.255.0.0")
487 nm:value("255.0.0.0")
488
489 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
490 gw.optional = true
491 gw.datatype = "ip4addr"
492
493 if has_ipv6 then
494         s2:tab("ipv6", translate("IPv6 Setup"))
495
496         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"))
497         ip6.optional = true
498         ip6.datatype = "ip6addr"
499
500         gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
501         gw6.optional = true
502         gw6.datatype = "ip6addr"
503 end
504
505 s2:tab("advanced", translate("Advanced Settings"))
506
507 bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
508 bcast.optional = true
509 bcast.datatype = "ip4addr"
510
511 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
512 dns.optional = true
513 dns.datatype = "ip4addr"
514
515
516 --
517 -- Display DNS settings if dnsmasq is available
518 --
519
520 if has_dnsmasq then
521         m2 = Map("dhcp", "", "")
522         function m2.on_parse()
523                 local has_section = false
524
525                 m2.uci:foreach("dhcp", "dhcp", function(s)
526                         if s.interface == arg[1] then
527                                 has_section = true
528                                 return false
529                         end
530                 end)
531
532                 if not has_section then
533                         m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
534                         m2.uci:save("dhcp")
535                 end
536         end
537
538         s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
539         s.addremove = false
540         s.anonymous = true
541         s:tab("general",  translate("General Setup"))
542         s:tab("advanced", translate("Advanced Settings"))
543
544         function s.filter(self, section)
545                 return m2.uci:get("dhcp", section, "interface") == arg[1]
546         end
547
548         local ignore = s:taboption("general", Flag, "ignore",
549                 translate("Ignore interface"),
550                 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
551                         "this interface."))
552
553         ignore.rmempty = false
554
555         local start = s:taboption("general", Value, "start", translate("Start"),
556                 translate("Lowest leased address as offset from the network address."))
557         start.optional = true
558         start.datatype = "uinteger"
559         start.default = "100"
560
561         local limit = s:taboption("general", Value, "limit", translate("Limit"),
562                 translate("Maximum number of leased addresses."))
563         limit.optional = true
564         limit.datatype = "uinteger"
565         limit.default = "150"
566
567         local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
568                 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
569         ltime.rmempty = true
570         ltime.default = "12h"
571
572         local dd = s:taboption("advanced", Flag, "dynamicdhcp",
573                 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
574                 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
575                         "clients having static leases will be served."))
576
577         dd.rmempty = false
578         function dd.cfgvalue(self, section)
579                 return Flag.cfgvalue(self, section) or "1"
580         end
581
582         s:taboption("advanced", Flag, "force", translate("Force"),
583                 translate("Force DHCP on this network even if another server is detected."))
584
585         -- XXX: is this actually useful?
586         --s:taboption("advanced", Value, "name", translate("Name"),
587         --      translate("Define a name for this network."))
588
589         mask = s:taboption("advanced", Value, "netmask",
590                 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
591                 translate("Override the netmask sent to clients. Normally it is calculated " ..
592                         "from the subnet that is served."))
593
594         mask.optional = true
595         mask.datatype = "ip4addr"
596
597         s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
598                 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
599                         "192.168.2.2</code>\" which advertises different DNS servers to clients."))
600
601         for i, n in ipairs(s.children) do
602                 if n ~= ignore then
603                         n:depends("ignore", "")
604                 end
605         end
606 end
607
608 return m, m2