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 s:tab("physical", translate("Physical Settings"))
45 s:tab("firewall", translate("Firewall Settings"))
48 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
50 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
53 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
54 p.override_scheme = true
56 p:value("static", translate("static"))
57 p:value("dhcp", "DHCP")
58 if has_pppd then p:value("ppp", "PPP") end
59 if has_pppoe then p:value("pppoe", "PPPoE") end
60 if has_pppoa then p:value("pppoa", "PPPoA") end
61 if has_3g then p:value("3g", "UMTS/3G") end
62 if has_pptp then p:value("pptp", "PPTP") end
63 p:value("none", translate("none"))
65 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
66 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")
69 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
73 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
74 translate("Enables the Spanning Tree Protocol on this bridge"))
75 stp:depends("type", "1")
78 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
79 ifname_single.template = "cbi/network_ifacelist"
80 ifname_single.widget = "radio"
81 ifname_single.nobridges = true
82 ifname_single.network = arg[1]
83 ifname_single.rmempty = true
84 ifname_single:depends("type", "")
86 function ifname_single.cfgvalue(self, s)
87 return self.map.uci:get("network", s, "ifname")
90 function ifname_single.write(self, s, val)
91 local n = nw:get_network(s)
94 for _, i in ipairs(n:get_interfaces()) do
102 ifname_multi = s:taboption("physical", MultiValue, "ifname_multi", translate("Interface"))
103 ifname_multi.template = "cbi/network_ifacelist"
104 ifname_multi.nobridges = true
105 ifname_multi.network = arg[1]
106 ifname_multi.widget = "checkbox"
107 ifname_multi:depends("type", "1")
108 ifname_multi.cfgvalue = ifname_single.cfgvalue
109 ifname_multi.write = ifname_single.write
112 for _, d in ipairs(nw:get_interfaces()) do
113 if not d:is_bridge() then
114 ifname_single:value(d:name())
115 ifname_multi:value(d:name())
120 local fwd_to, fwd_from
122 fwzone = s:taboption("firewall", Value, "_fwzone",
123 translate("Create / Assign firewall-zone"),
124 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."))
126 fwzone.template = "cbi/firewall_zonelist"
127 fwzone.network = arg[1]
128 fwzone.rmempty = false
130 function fwzone.cfgvalue(self, section)
132 local z = fw:get_zone_by_network(section)
133 return z and z:name()
136 function fwzone.write(self, section, value)
137 local zone = fw:get_zone(value)
139 if not zone and value == '-' then
140 value = m:formvalue(self:cbid(section) .. ".newzone")
141 if value and #value > 0 then
142 zone = fw:add_zone(value)
144 fw:del_network(section)
149 fw:del_network(section)
150 zone:add_network(section)
155 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
156 ipaddr.rmempty = true
157 ipaddr:depends("proto", "static")
159 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
161 nm:depends("proto", "static")
162 nm:value("255.255.255.0")
163 nm:value("255.255.0.0")
164 nm:value("255.0.0.0")
166 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
167 gw:depends("proto", "static")
170 bcast = s:taboption("general", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
171 bcast:depends("proto", "static")
174 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"))
175 ip6addr:depends("proto", "static")
177 ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
178 ip6gw:depends("proto", "static")
181 dns = s:taboption("general", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
182 translate("You can specify multiple DNS servers separated by space here. Servers entered here will override " ..
183 "automatically assigned ones."))
185 dns:depends("peerdns", "")
187 mtu = s:taboption("physical", Value, "mtu", "MTU")
190 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
193 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
194 srv:depends("proto", "pptp")
198 service = s:taboption("general", ListValue, "service", translate("Service type"))
199 service:value("", translate("-- Please choose --"))
200 service:value("umts", "UMTS/GPRS")
201 service:value("cdma", "CDMA")
202 service:value("evdo", "EV-DO")
203 service:depends("proto", "3g")
204 service.rmempty = true
206 apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
207 apn:depends("proto", "3g")
209 pincode = s:taboption("general", Value, "pincode",
210 translate("PIN code"),
211 translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
213 pincode:depends("proto", "3g")
216 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
217 user = s:taboption("general", Value, "username", translate("Username"))
219 user:depends("proto", "pptp")
220 user:depends("proto", "pppoe")
221 user:depends("proto", "pppoa")
222 user:depends("proto", "ppp")
223 user:depends("proto", "3g")
225 pass = s:taboption("general", Value, "password", translate("Password"))
228 pass:depends("proto", "pptp")
229 pass:depends("proto", "pppoe")
230 pass:depends("proto", "pppoa")
231 pass:depends("proto", "ppp")
232 pass:depends("proto", "3g")
234 ka = s:taboption("ppp", Value, "keepalive",
235 translate("Keep-Alive"),
236 translate("Number of failed connection tests to initiate automatic reconnect")
238 ka:depends("proto", "pptp")
239 ka:depends("proto", "pppoe")
240 ka:depends("proto", "pppoa")
241 ka:depends("proto", "ppp")
242 ka:depends("proto", "3g")
244 demand = s:taboption("ppp", Value, "demand",
245 translate("Automatic Disconnect"),
246 translate("Time (in seconds) after which an unused connection will be closed")
248 demand:depends("proto", "pptp")
249 demand:depends("proto", "pppoe")
250 demand:depends("proto", "pppoa")
251 demand:depends("proto", "ppp")
252 demand:depends("proto", "3g")
256 encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
257 encaps:depends("proto", "pppoa")
258 encaps:value("vc", "VC-Mux")
259 encaps:value("llc", "LLC")
261 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
262 atmdev:depends("proto", "pppoa")
265 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
266 vci:depends("proto", "pppoa")
269 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
270 vpi:depends("proto", "pppoa")
274 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
275 device = s:taboption("general", Value, "device",
276 translate("Modem device"),
277 translate("The device node of your modem, e.g. /dev/ttyUSB0")
279 device:depends("proto", "ppp")
280 device:depends("proto", "3g")
282 defaultroute = s:taboption("ppp", Flag, "defaultroute",
283 translate("Replace default route"),
284 translate("Let pppd replace the current default route to use the PPP interface after successful connect")
286 defaultroute:depends("proto", "ppp")
287 defaultroute:depends("proto", "pppoa")
288 defaultroute:depends("proto", "pppoe")
289 defaultroute:depends("proto", "pptp")
290 defaultroute:depends("proto", "3g")
291 defaultroute.rmempty = false
292 function defaultroute.cfgvalue(...)
293 return ( AbstractValue.cfgvalue(...) or '1' )
296 peerdns = s:taboption("ppp", Flag, "peerdns",
297 translate("Use peer DNS"),
298 translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
300 peerdns:depends("proto", "ppp")
301 peerdns:depends("proto", "pppoa")
302 peerdns:depends("proto", "pppoe")
303 peerdns:depends("proto", "pptp")
304 peerdns:depends("proto", "3g")
305 peerdns.rmempty = false
306 function peerdns.cfgvalue(...)
307 return ( AbstractValue.cfgvalue(...) or '1' )
311 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
312 ipv6:depends("proto", "ppp")
313 ipv6:depends("proto", "pppoa")
314 ipv6:depends("proto", "pppoe")
315 ipv6:depends("proto", "pptp")
316 ipv6:depends("proto", "3g")
319 connect = s:taboption("ppp", Value, "connect",
320 translate("Connect script"),
321 translate("Let pppd run this script after establishing the PPP link")
323 connect:depends("proto", "ppp")
324 connect:depends("proto", "pppoe")
325 connect:depends("proto", "pppoa")
326 connect:depends("proto", "pptp")
327 connect:depends("proto", "3g")
329 disconnect = s:taboption("ppp", Value, "disconnect",
330 translate("Disconnect script"),
331 translate("Let pppd run this script before tearing down the PPP link")
333 disconnect:depends("proto", "ppp")
334 disconnect:depends("proto", "pppoe")
335 disconnect:depends("proto", "pppoa")
336 disconnect:depends("proto", "pptp")
337 disconnect:depends("proto", "3g")
339 pppd_options = s:taboption("ppp", Value, "pppd_options",
340 translate("Additional pppd options"),
341 translate("Specify additional command line arguments for pppd here")
343 pppd_options:depends("proto", "ppp")
344 pppd_options:depends("proto", "pppoa")
345 pppd_options:depends("proto", "pppoe")
346 pppd_options:depends("proto", "pptp")
347 pppd_options:depends("proto", "3g")
349 maxwait = s:taboption("ppp", Value, "maxwait",
350 translate("Setup wait time"),
351 translate("Seconds to wait for the modem to become ready before attempting to connect")
353 maxwait:depends("proto", "3g")
356 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
359 s2:depends("interface", arg[1])
360 s2.defaults.interface = arg[1]
362 s2:tab("general", translate("General Setup"))
363 s2.defaults.proto = "static"
365 s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address")).rmempty = true
367 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
369 nm:value("255.255.255.0")
370 nm:value("255.255.0.0")
371 nm:value("255.0.0.0")
373 s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway")).rmempty = true
376 s2:tab("ipv6", translate("IPv6 Setup"))
377 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"))
378 s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
381 s2:tab("advanced", translate("Advanced Settings"))
382 s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
383 s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
386 m2 = Map("dhcp", "", "")
387 function m2.on_parse()
388 local has_section = false
390 m2.uci:foreach("dhcp", "dhcp", function(s)
391 if s.interface == arg[1] then
397 if not has_section then
398 m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
403 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
406 s:tab("general", translate("General Setup"))
407 s:tab("advanced", translate("Advanced Settings"))
409 function s.filter(self, section)
410 return m2.uci:get("dhcp", section, "interface") == arg[1]
413 local ignore = s:taboption("general", Flag, "ignore",
414 translate("Ignore interface"),
415 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
418 ignore.rmempty = false
420 local start = s:taboption("general", Value, "start", translate("Start"),
421 translate("Lowest leased address as offset from the network address."))
423 start.default = "100"
425 local limit = s:taboption("general", Value, "limit", translate("Limit"),
426 translate("Maximum number of leased addresses."))
428 limit.default = "150"
430 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
431 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
433 ltime.default = "12h"
435 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
436 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
437 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
438 "clients having static leases will be served."))
441 function dd.cfgvalue(self, section)
442 return Flag.cfgvalue(self, section) or "1"
445 s:taboption("advanced", Flag, "force", translate("Force"),
446 translate("Force DHCP on this network even if another server is detected."))
448 -- XXX: is this actually useful?
449 --s:taboption("advanced", Value, "name", translate("Name"),
450 -- translate("Define a name for this network."))
452 s:taboption("advanced", Value, "netmask",
453 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
454 translate("Override the netmask sent to clients. Normally it is calculated " ..
455 "from the subnet that is served."))
457 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
458 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
459 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
461 for i, n in ipairs(s.children) do
463 n:depends("ignore", "")