2 LuCI - Lua Configuration Interface
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2008 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 nw = require "luci.model.network"
18 local fw = require "luci.model.firewall"
22 local has_3g = fs.access("/usr/bin/gcom")
23 local has_pptp = fs.access("/usr/sbin/pptp")
24 local has_pppd = fs.access("/usr/sbin/pppd")
25 local has_pppoe = fs.glob("/usr/lib/pppd/*/rp-pppoe.so")()
26 local has_pppoa = fs.glob("/usr/lib/pppd/*/pppoatm.so")()
27 local has_ipv6 = fs.access("/proc/net/ipv6_route")
28 local has_6in4 = fs.access("/lib/network/6in4.sh")
30 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>)."))
37 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
40 s:tab("general", translate("General Setup"))
41 if has_ipv6 then s:tab("ipv6", translate("IPv6 Setup")) end
42 if has_pppd then s:tab("ppp", translate("PPP Settings")) end
43 if has_pppoa then s:tab("atm", translate("ATM Settings")) end
44 if has_6in4 then s:tab("tunnel", translate("Tunnel Settings")) end
45 s:tab("physical", translate("Physical Settings"))
46 s:tab("firewall", translate("Firewall Settings"))
49 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
51 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
54 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
55 p.override_scheme = true
57 p:value("static", translate("static"))
58 p:value("dhcp", "DHCP")
59 if has_pppd then p:value("ppp", "PPP") end
60 if has_pppoe then p:value("pppoe", "PPPoE") end
61 if has_pppoa then p:value("pppoa", "PPPoA") end
62 if has_3g then p:value("3g", "UMTS/3G") end
63 if has_pptp then p:value("pptp", "PPTP") end
64 if has_6in4 then p:value("6in4", "6in4") end
65 p:value("none", translate("none"))
67 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
68 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")
71 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
74 br:depends("proto", "static")
75 br:depends("proto", "dhcp")
76 br:depends("proto", "none")
78 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
79 translate("Enables the Spanning Tree Protocol on this bridge"))
80 stp:depends("type", "1")
83 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
84 ifname_single.template = "cbi/network_ifacelist"
85 ifname_single.widget = "radio"
86 ifname_single.nobridges = true
87 ifname_single.network = arg[1]
88 ifname_single.rmempty = true
89 ifname_single:depends({ type = "", proto = "static" })
90 ifname_single:depends({ type = "", proto = "dhcp" })
91 ifname_single:depends({ type = "", proto = "pppoe" })
92 ifname_single:depends({ type = "", proto = "pppoa" })
93 ifname_single:depends({ type = "", proto = "none" })
95 function ifname_single.cfgvalue(self, s)
96 return self.map.uci:get("network", s, "ifname")
99 function ifname_single.write(self, s, val)
100 local n = nw:get_network(s)
103 for _, i in ipairs(n:get_interfaces()) do
111 ifname_multi = s:taboption("physical", MultiValue, "ifname_multi", translate("Interface"))
112 ifname_multi.template = "cbi/network_ifacelist"
113 ifname_multi.nobridges = true
114 ifname_multi.network = arg[1]
115 ifname_multi.widget = "checkbox"
116 ifname_multi:depends("type", "1")
117 ifname_multi.cfgvalue = ifname_single.cfgvalue
118 ifname_multi.write = ifname_single.write
121 for _, d in ipairs(nw:get_interfaces()) do
122 if not d:is_bridge() then
123 ifname_single:value(d:name())
124 ifname_multi:value(d:name())
129 local fwd_to, fwd_from
131 fwzone = s:taboption("firewall", Value, "_fwzone",
132 translate("Create / Assign firewall-zone"),
133 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."))
135 fwzone.template = "cbi/firewall_zonelist"
136 fwzone.network = arg[1]
137 fwzone.rmempty = false
139 function fwzone.cfgvalue(self, section)
141 local z = fw:get_zone_by_network(section)
142 return z and z:name()
145 function fwzone.write(self, section, value)
146 local zone = fw:get_zone(value)
148 if not zone and value == '-' then
149 value = m:formvalue(self:cbid(section) .. ".newzone")
150 if value and #value > 0 then
151 zone = fw:add_zone(value)
153 fw:del_network(section)
158 fw:del_network(section)
159 zone:add_network(section)
163 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
164 ipaddr.rmempty = true
165 ipaddr.datatype = "ip4addr"
166 ipaddr:depends("proto", "static")
168 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
170 nm.datatype = "ip4addr"
171 nm:depends("proto", "static")
172 nm:value("255.255.255.0")
173 nm:value("255.255.0.0")
174 nm:value("255.0.0.0")
176 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
178 gw.datatype = "ip4addr"
179 gw:depends("proto", "static")
181 bcast = s:taboption("general", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
182 bcast.optional = true
183 bcast.datatype = "ip4addr"
184 bcast:depends("proto", "static")
187 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"))
188 ip6addr.rmempty = true
189 ip6addr.datatype = "ip6addr"
190 ip6addr:depends("proto", "static")
191 ip6addr:depends("proto", "6in4")
193 ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
194 ip6gw.optional = true
195 ip6gw.datatype = "ip6addr"
196 ip6gw:depends("proto", "static")
199 dns = s:taboption("general", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
200 translate("You can specify multiple DNS servers separated by space here. Servers entered here will override " ..
201 "automatically assigned ones."))
204 dns.datatype = "ipaddr"
205 dns:depends("peerdns", "")
207 mtu = s:taboption("physical", Value, "mtu", "MTU")
209 mtu.datatype = "uinteger"
211 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
212 srv:depends("proto", "pptp")
214 srv.datatype = "ip4addr"
217 peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
218 peer.optional = false
219 peer.datatype = "ip4addr"
220 peer:depends("proto", "6in4")
222 ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
225 ttl.datatype = "uinteger"
226 ttl:depends("proto", "6in4")
229 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
230 mac:depends("proto", "none")
231 mac:depends("proto", "static")
232 mac:depends("proto", "dhcp")
235 service = s:taboption("general", ListValue, "service", translate("Service type"))
236 service:value("", translate("-- Please choose --"))
237 service:value("umts", "UMTS/GPRS")
238 service:value("cdma", "CDMA")
239 service:value("evdo", "EV-DO")
240 service:depends("proto", "3g")
241 service.rmempty = true
243 apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
244 apn:depends("proto", "3g")
246 pincode = s:taboption("general", Value, "pincode",
247 translate("PIN code"),
248 translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
250 pincode:depends("proto", "3g")
254 tunid = s:taboption("general", Value, "tunnelid", translate("HE.net Tunnel ID"))
255 tunid.optional = true
256 tunid.datatype = "uinteger"
257 tunid:depends("proto", "6in4")
260 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
261 user = s:taboption("general", Value, "username", translate("Username"))
263 user:depends("proto", "pptp")
264 user:depends("proto", "pppoe")
265 user:depends("proto", "pppoa")
266 user:depends("proto", "ppp")
267 user:depends("proto", "3g")
268 user:depends("proto", "6in4")
270 pass = s:taboption("general", Value, "password", translate("Password"))
273 pass:depends("proto", "pptp")
274 pass:depends("proto", "pppoe")
275 pass:depends("proto", "pppoa")
276 pass:depends("proto", "ppp")
277 pass:depends("proto", "3g")
278 pass:depends("proto", "6in4")
280 ka = s:taboption("ppp", Value, "keepalive",
281 translate("Keep-Alive"),
282 translate("Number of failed connection tests to initiate automatic reconnect")
284 ka:depends("proto", "pptp")
285 ka:depends("proto", "pppoe")
286 ka:depends("proto", "pppoa")
287 ka:depends("proto", "ppp")
288 ka:depends("proto", "3g")
290 demand = s:taboption("ppp", Value, "demand",
291 translate("Automatic Disconnect"),
292 translate("Time (in seconds) after which an unused connection will be closed")
294 demand.optional = true
295 demand.datatype = "uinteger"
296 demand:depends("proto", "pptp")
297 demand:depends("proto", "pppoe")
298 demand:depends("proto", "pppoa")
299 demand:depends("proto", "ppp")
300 demand:depends("proto", "3g")
304 encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
305 encaps:depends("proto", "pppoa")
306 encaps:value("vc", "VC-Mux")
307 encaps:value("llc", "LLC")
309 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
310 atmdev:depends("proto", "pppoa")
312 atmdev.datatype = "uinteger"
314 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
315 vci:depends("proto", "pppoa")
317 vci.datatype = "uinteger"
319 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
320 vpi:depends("proto", "pppoa")
322 vpi.datatype = "uinteger"
325 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
326 device = s:taboption("general", Value, "device",
327 translate("Modem device"),
328 translate("The device node of your modem, e.g. /dev/ttyUSB0")
330 device:depends("proto", "ppp")
331 device:depends("proto", "3g")
333 defaultroute = s:taboption("ppp", Flag, "defaultroute",
334 translate("Replace default route"),
335 translate("Let pppd replace the current default route to use the PPP interface after successful connect")
337 defaultroute:depends("proto", "ppp")
338 defaultroute:depends("proto", "pppoa")
339 defaultroute:depends("proto", "pppoe")
340 defaultroute:depends("proto", "pptp")
341 defaultroute:depends("proto", "3g")
342 defaultroute.rmempty = false
343 function defaultroute.cfgvalue(...)
344 return ( AbstractValue.cfgvalue(...) or '1' )
347 peerdns = s:taboption("ppp", Flag, "peerdns",
348 translate("Use peer DNS"),
349 translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
351 peerdns:depends("proto", "ppp")
352 peerdns:depends("proto", "pppoa")
353 peerdns:depends("proto", "pppoe")
354 peerdns:depends("proto", "pptp")
355 peerdns:depends("proto", "3g")
356 peerdns.rmempty = false
357 function peerdns.cfgvalue(...)
358 return ( AbstractValue.cfgvalue(...) or '1' )
362 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
363 ipv6:depends("proto", "ppp")
364 ipv6:depends("proto", "pppoa")
365 ipv6:depends("proto", "pppoe")
366 ipv6:depends("proto", "pptp")
367 ipv6:depends("proto", "3g")
370 connect = s:taboption("ppp", Value, "connect",
371 translate("Connect script"),
372 translate("Let pppd run this script after establishing the PPP link")
374 connect:depends("proto", "ppp")
375 connect:depends("proto", "pppoe")
376 connect:depends("proto", "pppoa")
377 connect:depends("proto", "pptp")
378 connect:depends("proto", "3g")
380 disconnect = s:taboption("ppp", Value, "disconnect",
381 translate("Disconnect script"),
382 translate("Let pppd run this script before tearing down the PPP link")
384 disconnect:depends("proto", "ppp")
385 disconnect:depends("proto", "pppoe")
386 disconnect:depends("proto", "pppoa")
387 disconnect:depends("proto", "pptp")
388 disconnect:depends("proto", "3g")
390 pppd_options = s:taboption("ppp", Value, "pppd_options",
391 translate("Additional pppd options"),
392 translate("Specify additional command line arguments for pppd here")
394 pppd_options:depends("proto", "ppp")
395 pppd_options:depends("proto", "pppoa")
396 pppd_options:depends("proto", "pppoe")
397 pppd_options:depends("proto", "pptp")
398 pppd_options:depends("proto", "3g")
400 maxwait = s:taboption("ppp", Value, "maxwait",
401 translate("Setup wait time"),
402 translate("Seconds to wait for the modem to become ready before attempting to connect")
404 maxwait:depends("proto", "3g")
405 maxwait.default = "0"
406 maxwait.optional = true
407 maxwait.datatype = "uinteger"
410 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
413 s2:depends("interface", arg[1])
414 s2.defaults.interface = arg[1]
416 s2:tab("general", translate("General Setup"))
417 s2.defaults.proto = "static"
419 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
421 ip.datatype = "ip4addr"
423 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
425 nm.datatype = "ip4addr"
426 nm:value("255.255.255.0")
427 nm:value("255.255.0.0")
428 nm:value("255.0.0.0")
430 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
432 gw.datatype = "ip4addr"
435 s2:tab("ipv6", translate("IPv6 Setup"))
437 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"))
439 ip6.datatype = "ip6addr"
441 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
443 gw6.datatype = "ip6addr"
446 s2:tab("advanced", translate("Advanced Settings"))
448 bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
449 bcast.optional = true
450 bcast.datatype = "ip4addr"
452 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
454 dns.datatype = "ip4addr"
457 m2 = Map("dhcp", "", "")
458 function m2.on_parse()
459 local has_section = false
461 m2.uci:foreach("dhcp", "dhcp", function(s)
462 if s.interface == arg[1] then
468 if not has_section then
469 m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
474 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
477 s:tab("general", translate("General Setup"))
478 s:tab("advanced", translate("Advanced Settings"))
480 function s.filter(self, section)
481 return m2.uci:get("dhcp", section, "interface") == arg[1]
484 local ignore = s:taboption("general", Flag, "ignore",
485 translate("Ignore interface"),
486 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
489 ignore.rmempty = false
491 local start = s:taboption("general", Value, "start", translate("Start"),
492 translate("Lowest leased address as offset from the network address."))
493 start.optional = true
494 start.datatype = "uinteger"
495 start.default = "100"
497 local limit = s:taboption("general", Value, "limit", translate("Limit"),
498 translate("Maximum number of leased addresses."))
499 limit.optional = true
500 limit.datatype = "uinteger"
501 limit.default = "150"
503 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
504 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
506 ltime.default = "12h"
508 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
509 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
510 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
511 "clients having static leases will be served."))
514 function dd.cfgvalue(self, section)
515 return Flag.cfgvalue(self, section) or "1"
518 s:taboption("advanced", Flag, "force", translate("Force"),
519 translate("Force DHCP on this network even if another server is detected."))
521 -- XXX: is this actually useful?
522 --s:taboption("advanced", Value, "name", translate("Name"),
523 -- translate("Define a name for this network."))
525 mask = s:taboption("advanced", Value, "netmask",
526 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
527 translate("Override the netmask sent to clients. Normally it is calculated " ..
528 "from the subnet that is served."))
531 mask.datatype = "ip4addr"
533 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
534 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
535 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
537 for i, n in ipairs(s.children) do
539 n:depends("ignore", "")