2 LuCI - Lua Configuration Interface
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008-2011 Jo-Philipp Wich <xm@subsignal.org>
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
11 http://www.apache.org/licenses/LICENSE-2.0
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"
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")
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")
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>)."))
53 local net = nw:get_network(arg[1])
55 -- redirect to overview page if network does not exist anymore (e.g. after a revert)
57 luci.http.redirect(luci.dispatcher.build_url("admin/network/network"))
61 local ifc = net:get_interfaces()[1]
63 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
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
76 st = s:taboption("general", DummyValue, "__status", translate("Status"))
77 st.template = "admin_network/iface_status"
81 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
83 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
86 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
87 p.override_scheme = true
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"))
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")
106 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
107 br.enabled = "bridge"
109 br:depends("proto", "static")
110 br:depends("proto", "dhcp")
111 br:depends("proto", "none")
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")
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" })
131 function ifname_single.cfgvalue(self, s)
132 return self.map.uci:get("network", s, "ifname")
135 function ifname_single.write(self, s, val)
136 local n = nw:get_network(s)
139 for _, i in ipairs(n:get_interfaces()) do
143 for i in ut.imatch(val) do
146 -- if this is not a bridge, only assign first interface
147 if self.option == "ifname_single" then
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
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."))
169 fwzone.template = "cbi/firewall_zonelist"
170 fwzone.network = arg[1]
171 fwzone.rmempty = false
173 function fwzone.cfgvalue(self, section)
175 local z = fw:get_zone_by_network(section)
176 return z and z:name()
179 function fwzone.write(self, section, value)
180 local zone = fw:get_zone(value)
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)
187 fw:del_network(section)
192 fw:del_network(section)
193 zone:add_network(section)
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")
203 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
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")
211 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
213 gw.datatype = "ip4addr"
214 gw:depends("proto", "static")
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")
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")
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")
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")
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")
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."))
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" })
260 mtu = s:taboption("physical", Value, "mtu", "MTU")
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")
272 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
273 srv:depends("proto", "pptp")
275 srv.datatype = "host"
278 peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
279 peer.optional = false
280 peer.datatype = "ip4addr"
281 peer:depends("proto", "6in4")
284 if has_6in4 or has_6to4 then
285 ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
288 ttl.datatype = "uinteger"
289 ttl:depends("proto", "6in4")
290 ttl:depends("proto", "6to4")
294 advi = s:taboption("general", Value, "adv_interface", translate("Advertise IPv6 on network"))
295 advi.widget = "checkbox"
296 advi.exclude = arg[1]
298 advi.template = "cbi/network_netlist"
300 advi.nobridges = true
301 advi:depends("proto", "6to4")
303 advn = s:taboption("general", Value, "adv_subnet", translate("Advertised network ID"), translate("Allowed range is 1 to FFFF"))
305 advn:depends("proto", "6to4")
307 function advn.write(self, section, value)
308 value = tonumber(value, 16) or 1
310 if value > 65535 then value = 65535
311 elseif value < 1 then value = 1 end
313 Value.write(self, section, "%X" % value)
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"
323 rnet.nobridges = true
324 rnet:depends("proto", "relay")
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()
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
342 apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
343 apn:depends("proto", "3g")
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!")
349 pincode:depends("proto", "3g")
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")
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"))
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")
369 pass = s:taboption("general", Value, "password", translate("Password"))
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")
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")
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")
391 demand = s:taboption("ppp", Value, "demand",
392 translate("Automatic Disconnect"),
393 translate("Time (in seconds) after which an unused connection will be closed")
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")
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")
410 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
411 atmdev:depends("proto", "pppoa")
413 atmdev.datatype = "uinteger"
415 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
416 vci:depends("proto", "pppoa")
418 vci.datatype = "uinteger"
420 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
421 vpi:depends("proto", "pppoa")
423 vpi.datatype = "uinteger"
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")
431 device:depends("proto", "ppp")
432 device:depends("proto", "3g")
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")
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
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")
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
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")
465 connect = s:taboption("ppp", Value, "connect",
466 translate("Connect script"),
467 translate("Let pppd run this script after establishing the PPP link")
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")
475 disconnect = s:taboption("ppp", Value, "disconnect",
476 translate("Disconnect script"),
477 translate("Let pppd run this script before tearing down the PPP link")
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")
485 pppd_options = s:taboption("ppp", Value, "pppd_options",
486 translate("Additional pppd options"),
487 translate("Specify additional command line arguments for pppd here")
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")
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")
499 maxwait:depends("proto", "3g")
500 maxwait.default = "0"
501 maxwait.optional = true
502 maxwait.datatype = "uinteger"
506 fb = s:taboption("relay", Flag, "forward_bcast", translate("Forward broadcasts"))
507 fb.default = fb.enabled
508 fb:depends("proto", "relay")
510 fd = s:taboption("relay", Flag, "forward_dhcp", translate("Forward DHCP"))
511 fd.default = fd.enabled
512 fd:depends("proto", "relay")
514 gw = s:taboption("relay", Value, "relay_gateway", translate("Override Gateway"))
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")
522 function gw.write(self, section, value)
523 return m.uci:set("network", section, "gateway", value)
525 function gw.delete(self, section)
526 return m.uci:delete("network", section, "gateway")
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")
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")
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")
549 mca = s:taboption("ahcp", Value, "multicast_address", translate("Multicast address"))
551 mca.placeholder = "ff02::cca6:c0f9:e182:5359"
552 mca.datatype = "ip6addr"
553 mca:depends("proto", "ahcp")
555 port = s:taboption("ahcp", Value, "port", translate("Port"))
557 port.placeholder = 5359
558 port.datatype = "port"
559 port:depends("proto", "ahcp")
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")
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")
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")
588 function fam.remove(self, section)
589 m.uci:delete("network", section, "ipv4_only")
590 m.uci:delete("network", section, "ipv6_only")
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")
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")
607 if net:proto() ~= "relay" then
608 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
611 s2:depends("interface", arg[1])
612 s2.defaults.interface = arg[1]
614 s2:tab("general", translate("General Setup"))
615 s2.defaults.proto = "static"
617 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
619 ip.datatype = "ip4addr"
621 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
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")
628 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
630 gw.datatype = "ip4addr"
633 s2:tab("ipv6", translate("IPv6 Setup"))
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"))
637 ip6.datatype = "ip6addr"
639 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
641 gw6.datatype = "ip6addr"
644 s2:tab("advanced", translate("Advanced Settings"))
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"
650 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
652 dns.datatype = "ip4addr"
657 -- Display DNS settings if dnsmasq is available
660 if has_dnsmasq and net:proto() == "static" then
661 m2 = Map("dhcp", "", "")
663 local section_id = "-"
665 function m2.on_parse()
666 m2.uci:foreach("dhcp", "dhcp", function(s)
667 if s.interface == arg[1] then
668 section_id = s['.name']
674 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
677 s:tab("general", translate("General Setup"))
678 s:tab("advanced", translate("Advanced Settings"))
680 function s.cfgsections(self)
681 return { section_id }
684 local ignore = s:taboption("general", Flag, "ignore",
685 translate("Ignore interface"),
686 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
689 ignore.rmempty = false
691 function ignore.cfgvalue(self, section)
692 return (section == "-") and self.enabled or Flag.cfgvalue(self, section)
695 function ignore.write(self, section, value)
696 section_id = m2.uci:section("dhcp", "dhcp", nil, {
703 local start = s:taboption("general", Value, "start", translate("Start"),
704 translate("Lowest leased address as offset from the network address."))
705 start.optional = true
706 start.datatype = "uinteger"
707 start.default = "100"
709 local limit = s:taboption("general", Value, "limit", translate("Limit"),
710 translate("Maximum number of leased addresses."))
711 limit.optional = true
712 limit.datatype = "uinteger"
713 limit.default = "150"
715 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
716 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
718 ltime.default = "12h"
720 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
721 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
722 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
723 "clients having static leases will be served."))
724 dd.default = dd.enabled
726 s:taboption("advanced", Flag, "force", translate("Force"),
727 translate("Force DHCP on this network even if another server is detected."))
729 -- XXX: is this actually useful?
730 --s:taboption("advanced", Value, "name", translate("Name"),
731 -- translate("Define a name for this network."))
733 mask = s:taboption("advanced", Value, "netmask",
734 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
735 translate("Override the netmask sent to clients. Normally it is calculated " ..
736 "from the subnet that is served."))
739 mask.datatype = "ip4addr"
741 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
742 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
743 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
746 local function write_opt(self, section, value)
747 return getmetatable(self).__index.write(self, section_id, value)
750 local function remove_opt(self, section, value)
751 return getmetatable(self).__index.remove(self, section_id, value)
754 for i, n in ipairs(s.children) do
756 n:depends("ignore", "")
758 n.remove = remove_opt