modules/admin-full: defer writing of interface related dhcp options until an actual...
[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 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
663 local section_id = "-"
664
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']
669 return false
670 end
671 end)
672 end
673
674 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
675 s.addremove = false
676 s.anonymous = true
677 s:tab("general", translate("General Setup"))
678 s:tab("advanced", translate("Advanced Settings"))
679
680 function s.cfgsections(self)
681 return { section_id }
682 end
683
684 local ignore = s:taboption("general", Flag, "ignore",
685 translate("Ignore interface"),
686 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
687 "this interface."))
688
689 ignore.rmempty = false
690
691 function ignore.cfgvalue(self, section)
692 return (section == "-") and self.enabled or Flag.cfgvalue(self, section)
693 end
694
695 function ignore.write(self, section, value)
696 section_id = m2.uci:section("dhcp", "dhcp", nil, {
697 ignore = value,
698 interface = arg[1]
699 })
700 end
701
702
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"
708
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"
714
715 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
716 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
717 ltime.rmempty = true
718 ltime.default = "12h"
719
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
725
726 s:taboption("advanced", Flag, "force", translate("Force"),
727 translate("Force DHCP on this network even if another server is detected."))
728
729 -- XXX: is this actually useful?
730 --s:taboption("advanced", Value, "name", translate("Name"),
731 -- translate("Define a name for this network."))
732
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."))
737
738 mask.optional = true
739 mask.datatype = "ip4addr"
740
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."))
744
745
746 local function write_opt(self, section, value)
747 return getmetatable(self).__index.write(self, section_id, value)
748 end
749
750 local function remove_opt(self, section, value)
751 return getmetatable(self).__index.remove(self, section_id, value)
752 end
753
754 for i, n in ipairs(s.children) do
755 if n ~= ignore then
756 n:depends("ignore", "")
757 n.write = write_opt
758 n.remove = remove_opt
759 end
760 end
761 end
762
763 return m, m2