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"))
48 st = s:taboption("general", DummyValue, "__status", translate("Status"))
49 st.template = "admin_network/iface_status"
53 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
55 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
58 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
59 p.override_scheme = true
61 p:value("static", translate("static"))
62 p:value("dhcp", "DHCP")
63 if has_pppd then p:value("ppp", "PPP") end
64 if has_pppoe then p:value("pppoe", "PPPoE") end
65 if has_pppoa then p:value("pppoa", "PPPoA") end
66 if has_3g then p:value("3g", "UMTS/3G") end
67 if has_pptp then p:value("pptp", "PPTP") end
68 if has_6in4 then p:value("6in4", "6in4") end
69 p:value("none", translate("none"))
71 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
72 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")
75 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
78 br:depends("proto", "static")
79 br:depends("proto", "dhcp")
80 br:depends("proto", "none")
82 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
83 translate("Enables the Spanning Tree Protocol on this bridge"))
84 stp:depends("type", "1")
87 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
88 ifname_single.template = "cbi/network_ifacelist"
89 ifname_single.widget = "radio"
90 ifname_single.nobridges = true
91 ifname_single.network = arg[1]
92 ifname_single.rmempty = true
93 ifname_single:depends({ type = "", proto = "static" })
94 ifname_single:depends({ type = "", proto = "dhcp" })
95 ifname_single:depends({ type = "", proto = "pppoe" })
96 ifname_single:depends({ type = "", proto = "pppoa" })
97 ifname_single:depends({ type = "", proto = "none" })
99 function ifname_single.cfgvalue(self, s)
100 return self.map.uci:get("network", s, "ifname")
103 function ifname_single.write(self, s, val)
104 local n = nw:get_network(s)
107 for _, i in ipairs(n:get_interfaces()) do
115 ifname_multi = s:taboption("physical", MultiValue, "ifname_multi", translate("Interface"))
116 ifname_multi.template = "cbi/network_ifacelist"
117 ifname_multi.nobridges = true
118 ifname_multi.network = arg[1]
119 ifname_multi.widget = "checkbox"
120 ifname_multi:depends("type", "1")
121 ifname_multi.cfgvalue = ifname_single.cfgvalue
122 ifname_multi.write = ifname_single.write
125 for _, d in ipairs(nw:get_interfaces()) do
126 if not d:is_bridge() then
127 ifname_single:value(d:name())
128 ifname_multi:value(d:name())
133 local fwd_to, fwd_from
135 fwzone = s:taboption("firewall", Value, "_fwzone",
136 translate("Create / Assign firewall-zone"),
137 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."))
139 fwzone.template = "cbi/firewall_zonelist"
140 fwzone.network = arg[1]
141 fwzone.rmempty = false
143 function fwzone.cfgvalue(self, section)
145 local z = fw:get_zone_by_network(section)
146 return z and z:name()
149 function fwzone.write(self, section, value)
150 local zone = fw:get_zone(value)
152 if not zone and value == '-' then
153 value = m:formvalue(self:cbid(section) .. ".newzone")
154 if value and #value > 0 then
155 zone = fw:add_zone(value)
157 fw:del_network(section)
162 fw:del_network(section)
163 zone:add_network(section)
167 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
168 ipaddr.optional = true
169 ipaddr.datatype = "ip4addr"
170 ipaddr:depends("proto", "static")
172 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
174 nm.datatype = "ip4addr"
175 nm:depends("proto", "static")
176 nm:value("255.255.255.0")
177 nm:value("255.255.0.0")
178 nm:value("255.0.0.0")
180 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
182 gw.datatype = "ip4addr"
183 gw:depends("proto", "static")
185 bcast = s:taboption("general", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
186 bcast.optional = true
187 bcast.datatype = "ip4addr"
188 bcast:depends("proto", "static")
191 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"))
192 ip6addr.optional = true
193 ip6addr.datatype = "ip6addr"
194 ip6addr:depends("proto", "static")
195 ip6addr:depends("proto", "6in4")
197 ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
198 ip6gw.optional = true
199 ip6gw.datatype = "ip6addr"
200 ip6gw:depends("proto", "static")
203 dns = s:taboption("general", DynamicList, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
204 translate("You can specify multiple DNS servers here, press enter to add a new entry. Servers entered here will override " ..
205 "automatically assigned ones."))
209 dns.datatype = "ipaddr"
210 dns:depends("peerdns", "")
212 mtu = s:taboption("physical", Value, "mtu", "MTU")
214 mtu.datatype = "uinteger"
216 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
217 srv:depends("proto", "pptp")
219 srv.datatype = "ip4addr"
222 peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
223 peer.optional = false
224 peer.datatype = "ip4addr"
225 peer:depends("proto", "6in4")
227 ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
230 ttl.datatype = "uinteger"
231 ttl:depends("proto", "6in4")
234 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
235 mac:depends("proto", "none")
236 mac:depends("proto", "static")
237 mac:depends("proto", "dhcp")
240 service = s:taboption("general", ListValue, "service", translate("Service type"))
241 service:value("", translate("-- Please choose --"))
242 service:value("umts", "UMTS/GPRS")
243 service:value("cdma", "CDMA")
244 service:value("evdo", "EV-DO")
245 service:depends("proto", "3g")
246 service.rmempty = true
248 apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
249 apn:depends("proto", "3g")
251 pincode = s:taboption("general", Value, "pincode",
252 translate("PIN code"),
253 translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
255 pincode:depends("proto", "3g")
259 tunid = s:taboption("general", Value, "tunnelid", translate("HE.net Tunnel ID"))
260 tunid.optional = true
261 tunid.datatype = "uinteger"
262 tunid:depends("proto", "6in4")
265 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
266 user = s:taboption("general", Value, "username", translate("Username"))
268 user:depends("proto", "pptp")
269 user:depends("proto", "pppoe")
270 user:depends("proto", "pppoa")
271 user:depends("proto", "ppp")
272 user:depends("proto", "3g")
273 user:depends("proto", "6in4")
275 pass = s:taboption("general", Value, "password", translate("Password"))
278 pass:depends("proto", "pptp")
279 pass:depends("proto", "pppoe")
280 pass:depends("proto", "pppoa")
281 pass:depends("proto", "ppp")
282 pass:depends("proto", "3g")
283 pass:depends("proto", "6in4")
286 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
287 ka = s:taboption("ppp", Value, "keepalive",
288 translate("Keep-Alive"),
289 translate("Number of failed connection tests to initiate automatic reconnect")
291 ka:depends("proto", "pptp")
292 ka:depends("proto", "pppoe")
293 ka:depends("proto", "pppoa")
294 ka:depends("proto", "ppp")
295 ka:depends("proto", "3g")
297 demand = s:taboption("ppp", Value, "demand",
298 translate("Automatic Disconnect"),
299 translate("Time (in seconds) after which an unused connection will be closed")
301 demand.optional = true
302 demand.datatype = "uinteger"
303 demand:depends("proto", "pptp")
304 demand:depends("proto", "pppoe")
305 demand:depends("proto", "pppoa")
306 demand:depends("proto", "ppp")
307 demand:depends("proto", "3g")
311 encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
312 encaps:depends("proto", "pppoa")
313 encaps:value("vc", "VC-Mux")
314 encaps:value("llc", "LLC")
316 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
317 atmdev:depends("proto", "pppoa")
319 atmdev.datatype = "uinteger"
321 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
322 vci:depends("proto", "pppoa")
324 vci.datatype = "uinteger"
326 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
327 vpi:depends("proto", "pppoa")
329 vpi.datatype = "uinteger"
332 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
333 device = s:taboption("general", Value, "device",
334 translate("Modem device"),
335 translate("The device node of your modem, e.g. /dev/ttyUSB0")
337 device:depends("proto", "ppp")
338 device:depends("proto", "3g")
340 defaultroute = s:taboption("ppp", Flag, "defaultroute",
341 translate("Replace default route"),
342 translate("Let pppd replace the current default route to use the PPP interface after successful connect")
344 defaultroute:depends("proto", "ppp")
345 defaultroute:depends("proto", "pppoa")
346 defaultroute:depends("proto", "pppoe")
347 defaultroute:depends("proto", "pptp")
348 defaultroute:depends("proto", "3g")
349 defaultroute.rmempty = false
350 function defaultroute.cfgvalue(...)
351 return ( AbstractValue.cfgvalue(...) or '1' )
354 peerdns = s:taboption("ppp", Flag, "peerdns",
355 translate("Use peer DNS"),
356 translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
358 peerdns:depends("proto", "ppp")
359 peerdns:depends("proto", "pppoa")
360 peerdns:depends("proto", "pppoe")
361 peerdns:depends("proto", "pptp")
362 peerdns:depends("proto", "3g")
363 peerdns.rmempty = false
364 function peerdns.cfgvalue(...)
365 return ( AbstractValue.cfgvalue(...) or '1' )
369 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
370 ipv6:depends("proto", "ppp")
371 ipv6:depends("proto", "pppoa")
372 ipv6:depends("proto", "pppoe")
373 ipv6:depends("proto", "pptp")
374 ipv6:depends("proto", "3g")
377 connect = s:taboption("ppp", Value, "connect",
378 translate("Connect script"),
379 translate("Let pppd run this script after establishing the PPP link")
381 connect:depends("proto", "ppp")
382 connect:depends("proto", "pppoe")
383 connect:depends("proto", "pppoa")
384 connect:depends("proto", "pptp")
385 connect:depends("proto", "3g")
387 disconnect = s:taboption("ppp", Value, "disconnect",
388 translate("Disconnect script"),
389 translate("Let pppd run this script before tearing down the PPP link")
391 disconnect:depends("proto", "ppp")
392 disconnect:depends("proto", "pppoe")
393 disconnect:depends("proto", "pppoa")
394 disconnect:depends("proto", "pptp")
395 disconnect:depends("proto", "3g")
397 pppd_options = s:taboption("ppp", Value, "pppd_options",
398 translate("Additional pppd options"),
399 translate("Specify additional command line arguments for pppd here")
401 pppd_options:depends("proto", "ppp")
402 pppd_options:depends("proto", "pppoa")
403 pppd_options:depends("proto", "pppoe")
404 pppd_options:depends("proto", "pptp")
405 pppd_options:depends("proto", "3g")
407 maxwait = s:taboption("ppp", Value, "maxwait",
408 translate("Setup wait time"),
409 translate("Seconds to wait for the modem to become ready before attempting to connect")
411 maxwait:depends("proto", "3g")
412 maxwait.default = "0"
413 maxwait.optional = true
414 maxwait.datatype = "uinteger"
417 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
420 s2:depends("interface", arg[1])
421 s2.defaults.interface = arg[1]
423 s2:tab("general", translate("General Setup"))
424 s2.defaults.proto = "static"
426 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
428 ip.datatype = "ip4addr"
430 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
432 nm.datatype = "ip4addr"
433 nm:value("255.255.255.0")
434 nm:value("255.255.0.0")
435 nm:value("255.0.0.0")
437 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
439 gw.datatype = "ip4addr"
442 s2:tab("ipv6", translate("IPv6 Setup"))
444 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"))
446 ip6.datatype = "ip6addr"
448 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
450 gw6.datatype = "ip6addr"
453 s2:tab("advanced", translate("Advanced Settings"))
455 bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
456 bcast.optional = true
457 bcast.datatype = "ip4addr"
459 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
461 dns.datatype = "ip4addr"
464 m2 = Map("dhcp", "", "")
465 function m2.on_parse()
466 local has_section = false
468 m2.uci:foreach("dhcp", "dhcp", function(s)
469 if s.interface == arg[1] then
475 if not has_section then
476 m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
481 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
484 s:tab("general", translate("General Setup"))
485 s:tab("advanced", translate("Advanced Settings"))
487 function s.filter(self, section)
488 return m2.uci:get("dhcp", section, "interface") == arg[1]
491 local ignore = s:taboption("general", Flag, "ignore",
492 translate("Ignore interface"),
493 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
496 ignore.rmempty = false
498 local start = s:taboption("general", Value, "start", translate("Start"),
499 translate("Lowest leased address as offset from the network address."))
500 start.optional = true
501 start.datatype = "uinteger"
502 start.default = "100"
504 local limit = s:taboption("general", Value, "limit", translate("Limit"),
505 translate("Maximum number of leased addresses."))
506 limit.optional = true
507 limit.datatype = "uinteger"
508 limit.default = "150"
510 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
511 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
513 ltime.default = "12h"
515 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
516 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
517 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
518 "clients having static leases will be served."))
521 function dd.cfgvalue(self, section)
522 return Flag.cfgvalue(self, section) or "1"
525 s:taboption("advanced", Flag, "force", translate("Force"),
526 translate("Force DHCP on this network even if another server is detected."))
528 -- XXX: is this actually useful?
529 --s:taboption("advanced", Value, "name", translate("Name"),
530 -- translate("Define a name for this network."))
532 mask = s:taboption("advanced", Value, "netmask",
533 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
534 translate("Override the netmask sent to clients. Normally it is calculated " ..
535 "from the subnet that is served."))
538 mask.datatype = "ip4addr"
540 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
541 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
542 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
544 for i, n in ipairs(s.children) do
546 n:depends("ignore", "")