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 --function m.on_commit(map)
42 s = m:section(NamedSection, arg[1], "interface", translate("Common Configuration"))
45 s:tab("general", translate("General Setup"))
46 if has_ipv6 then s:tab("ipv6", translate("IPv6 Setup")) end
47 if has_pppd then s:tab("ppp", translate("PPP Settings")) end
48 if has_pppoa then s:tab("atm", translate("ATM Settings")) end
49 if has_6in4 then s:tab("tunnel", translate("Tunnel Settings")) end
50 s:tab("physical", translate("Physical Settings"))
51 s:tab("firewall", translate("Firewall Settings"))
53 st = s:taboption("general", DummyValue, "__status", translate("Status"))
54 st.template = "admin_network/iface_status"
58 back = s:taboption("general", DummyValue, "_overview", translate("Overview"))
60 back.titleref = luci.dispatcher.build_url("admin", "network", "network")
63 p = s:taboption("general", ListValue, "proto", translate("Protocol"))
64 p.override_scheme = true
66 p:value("static", translate("static"))
67 p:value("dhcp", "DHCP")
68 if has_pppd then p:value("ppp", "PPP") end
69 if has_pppoe then p:value("pppoe", "PPPoE") end
70 if has_pppoa then p:value("pppoa", "PPPoA") end
71 if has_3g then p:value("3g", "UMTS/3G") end
72 if has_pptp then p:value("pptp", "PPTP") end
73 if has_6in4 then p:value("6in4", "6in4") end
74 p:value("none", translate("none"))
76 if not ( has_pppd and has_pppoe and has_pppoa and has_3g and has_pptp ) then
77 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")
80 br = s:taboption("physical", Flag, "type", translate("Bridge interfaces"), translate("creates a bridge over specified interface(s)"))
83 br:depends("proto", "static")
84 br:depends("proto", "dhcp")
85 br:depends("proto", "none")
87 stp = s:taboption("physical", Flag, "stp", translate("Enable <abbr title=\"Spanning Tree Protocol\">STP</abbr>"),
88 translate("Enables the Spanning Tree Protocol on this bridge"))
89 stp:depends("type", "1")
92 ifname_single = s:taboption("physical", Value, "ifname_single", translate("Interface"))
93 ifname_single.template = "cbi/network_ifacelist"
94 ifname_single.widget = "radio"
95 ifname_single.nobridges = true
96 ifname_single.network = arg[1]
97 ifname_single.rmempty = true
98 ifname_single:depends({ type = "", proto = "static" })
99 ifname_single:depends({ type = "", proto = "dhcp" })
100 ifname_single:depends({ type = "", proto = "pppoe" })
101 ifname_single:depends({ type = "", proto = "pppoa" })
102 ifname_single:depends({ type = "", proto = "none" })
104 function ifname_single.cfgvalue(self, s)
105 return self.map.uci:get("network", s, "ifname")
108 function ifname_single.write(self, s, val)
109 local n = nw:get_network(s)
112 for _, i in ipairs(n:get_interfaces()) do
116 for i in val:gmatch("%S+") do
119 -- if this is not a bridge, only assign first interface
120 if self.option == "ifname_single" then
128 ifname_multi = s:taboption("physical", MultiValue, "ifname_multi", translate("Interface"))
129 ifname_multi.template = "cbi/network_ifacelist"
130 ifname_multi.nobridges = true
131 ifname_multi.network = arg[1]
132 ifname_multi.widget = "checkbox"
133 ifname_multi:depends("type", "1")
134 ifname_multi.cfgvalue = ifname_single.cfgvalue
135 ifname_multi.write = ifname_single.write
138 for _, d in ipairs(nw:get_interfaces()) do
139 if not d:is_bridge() then
140 ifname_single:value(d:name())
141 ifname_multi:value(d:name())
146 local fwd_to, fwd_from
148 fwzone = s:taboption("firewall", Value, "_fwzone",
149 translate("Create / Assign firewall-zone"),
150 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."))
152 fwzone.template = "cbi/firewall_zonelist"
153 fwzone.network = arg[1]
154 fwzone.rmempty = false
156 function fwzone.cfgvalue(self, section)
158 local z = fw:get_zone_by_network(section)
159 return z and z:name()
162 function fwzone.write(self, section, value)
163 local zone = fw:get_zone(value)
165 if not zone and value == '-' then
166 value = m:formvalue(self:cbid(section) .. ".newzone")
167 if value and #value > 0 then
168 zone = fw:add_zone(value)
170 fw:del_network(section)
175 fw:del_network(section)
176 zone:add_network(section)
180 ipaddr = s:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
181 ipaddr.optional = true
182 ipaddr.datatype = "ip4addr"
183 ipaddr:depends("proto", "static")
185 nm = s:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
187 nm.datatype = "ip4addr"
188 nm:depends("proto", "static")
189 nm:value("255.255.255.0")
190 nm:value("255.255.0.0")
191 nm:value("255.0.0.0")
193 gw = s:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
195 gw.datatype = "ip4addr"
196 gw:depends("proto", "static")
198 bcast = s:taboption("general", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
199 bcast.optional = true
200 bcast.datatype = "ip4addr"
201 bcast:depends("proto", "static")
204 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"))
205 ip6addr.optional = true
206 ip6addr.datatype = "ip6addr"
207 ip6addr:depends("proto", "static")
208 ip6addr:depends("proto", "6in4")
210 ip6gw = s:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
211 ip6gw.optional = true
212 ip6gw.datatype = "ip6addr"
213 ip6gw:depends("proto", "static")
216 dns = s:taboption("general", DynamicList, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"),
217 translate("You can specify multiple DNS servers here, press enter to add a new entry. Servers entered here will override " ..
218 "automatically assigned ones."))
222 dns.datatype = "ipaddr"
223 dns:depends("peerdns", "")
225 mtu = s:taboption("physical", Value, "mtu", "MTU")
227 mtu.datatype = "uinteger"
229 srv = s:taboption("general", Value, "server", translate("<abbr title=\"Point-to-Point Tunneling Protocol\">PPTP</abbr>-Server"))
230 srv:depends("proto", "pptp")
232 srv.datatype = "ip4addr"
235 peer = s:taboption("general", Value, "peeraddr", translate("Server IPv4-Address"))
236 peer.optional = false
237 peer.datatype = "ip4addr"
238 peer:depends("proto", "6in4")
240 ttl = s:taboption("physical", Value, "ttl", translate("TTL"))
243 ttl.datatype = "uinteger"
244 ttl:depends("proto", "6in4")
247 mac = s:taboption("physical", Value, "macaddr", translate("<abbr title=\"Media Access Control\">MAC</abbr>-Address"))
248 mac:depends("proto", "none")
249 mac:depends("proto", "static")
250 mac:depends("proto", "dhcp")
253 service = s:taboption("general", ListValue, "service", translate("Service type"))
254 service:value("", translate("-- Please choose --"))
255 service:value("umts", "UMTS/GPRS")
256 service:value("cdma", "CDMA")
257 service:value("evdo", "EV-DO")
258 service:depends("proto", "3g")
259 service.rmempty = true
261 apn = s:taboption("general", Value, "apn", translate("Access point (APN)"))
262 apn:depends("proto", "3g")
264 pincode = s:taboption("general", Value, "pincode",
265 translate("PIN code"),
266 translate("Make sure that you provide the correct pin code here or you might lock your sim card!")
268 pincode:depends("proto", "3g")
272 tunid = s:taboption("general", Value, "tunnelid", translate("HE.net Tunnel ID"))
273 tunid.optional = true
274 tunid.datatype = "uinteger"
275 tunid:depends("proto", "6in4")
278 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp or has_6in4 then
279 user = s:taboption("general", Value, "username", translate("Username"))
281 user:depends("proto", "pptp")
282 user:depends("proto", "pppoe")
283 user:depends("proto", "pppoa")
284 user:depends("proto", "ppp")
285 user:depends("proto", "3g")
286 user:depends("proto", "6in4")
288 pass = s:taboption("general", Value, "password", translate("Password"))
291 pass:depends("proto", "pptp")
292 pass:depends("proto", "pppoe")
293 pass:depends("proto", "pppoa")
294 pass:depends("proto", "ppp")
295 pass:depends("proto", "3g")
296 pass:depends("proto", "6in4")
299 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
300 ka = s:taboption("ppp", Value, "keepalive",
301 translate("Keep-Alive"),
302 translate("Number of failed connection tests to initiate automatic reconnect")
304 ka:depends("proto", "pptp")
305 ka:depends("proto", "pppoe")
306 ka:depends("proto", "pppoa")
307 ka:depends("proto", "ppp")
308 ka:depends("proto", "3g")
310 demand = s:taboption("ppp", Value, "demand",
311 translate("Automatic Disconnect"),
312 translate("Time (in seconds) after which an unused connection will be closed")
314 demand.optional = true
315 demand.datatype = "uinteger"
316 demand:depends("proto", "pptp")
317 demand:depends("proto", "pppoe")
318 demand:depends("proto", "pppoa")
319 demand:depends("proto", "ppp")
320 demand:depends("proto", "3g")
324 encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
325 encaps:depends("proto", "pppoa")
326 encaps:value("vc", "VC-Mux")
327 encaps:value("llc", "LLC")
329 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
330 atmdev:depends("proto", "pppoa")
332 atmdev.datatype = "uinteger"
334 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
335 vci:depends("proto", "pppoa")
337 vci.datatype = "uinteger"
339 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
340 vpi:depends("proto", "pppoa")
342 vpi.datatype = "uinteger"
345 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
346 device = s:taboption("general", Value, "device",
347 translate("Modem device"),
348 translate("The device node of your modem, e.g. /dev/ttyUSB0")
350 device:depends("proto", "ppp")
351 device:depends("proto", "3g")
353 defaultroute = s:taboption("ppp", Flag, "defaultroute",
354 translate("Replace default route"),
355 translate("Let pppd replace the current default route to use the PPP interface after successful connect")
357 defaultroute:depends("proto", "ppp")
358 defaultroute:depends("proto", "pppoa")
359 defaultroute:depends("proto", "pppoe")
360 defaultroute:depends("proto", "pptp")
361 defaultroute:depends("proto", "3g")
362 defaultroute.rmempty = false
363 function defaultroute.cfgvalue(...)
364 return ( AbstractValue.cfgvalue(...) or '1' )
367 peerdns = s:taboption("ppp", Flag, "peerdns",
368 translate("Use peer DNS"),
369 translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
371 peerdns:depends("proto", "ppp")
372 peerdns:depends("proto", "pppoa")
373 peerdns:depends("proto", "pppoe")
374 peerdns:depends("proto", "pptp")
375 peerdns:depends("proto", "3g")
376 peerdns.rmempty = false
377 function peerdns.cfgvalue(...)
378 return ( AbstractValue.cfgvalue(...) or '1' )
382 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
383 ipv6:depends("proto", "ppp")
384 ipv6:depends("proto", "pppoa")
385 ipv6:depends("proto", "pppoe")
386 ipv6:depends("proto", "pptp")
387 ipv6:depends("proto", "3g")
390 connect = s:taboption("ppp", Value, "connect",
391 translate("Connect script"),
392 translate("Let pppd run this script after establishing the PPP link")
394 connect:depends("proto", "ppp")
395 connect:depends("proto", "pppoe")
396 connect:depends("proto", "pppoa")
397 connect:depends("proto", "pptp")
398 connect:depends("proto", "3g")
400 disconnect = s:taboption("ppp", Value, "disconnect",
401 translate("Disconnect script"),
402 translate("Let pppd run this script before tearing down the PPP link")
404 disconnect:depends("proto", "ppp")
405 disconnect:depends("proto", "pppoe")
406 disconnect:depends("proto", "pppoa")
407 disconnect:depends("proto", "pptp")
408 disconnect:depends("proto", "3g")
410 pppd_options = s:taboption("ppp", Value, "pppd_options",
411 translate("Additional pppd options"),
412 translate("Specify additional command line arguments for pppd here")
414 pppd_options:depends("proto", "ppp")
415 pppd_options:depends("proto", "pppoa")
416 pppd_options:depends("proto", "pppoe")
417 pppd_options:depends("proto", "pptp")
418 pppd_options:depends("proto", "3g")
420 maxwait = s:taboption("ppp", Value, "maxwait",
421 translate("Setup wait time"),
422 translate("Seconds to wait for the modem to become ready before attempting to connect")
424 maxwait:depends("proto", "3g")
425 maxwait.default = "0"
426 maxwait.optional = true
427 maxwait.datatype = "uinteger"
430 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
433 s2:depends("interface", arg[1])
434 s2.defaults.interface = arg[1]
436 s2:tab("general", translate("General Setup"))
437 s2.defaults.proto = "static"
439 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
441 ip.datatype = "ip4addr"
443 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
445 nm.datatype = "ip4addr"
446 nm:value("255.255.255.0")
447 nm:value("255.255.0.0")
448 nm:value("255.0.0.0")
450 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
452 gw.datatype = "ip4addr"
455 s2:tab("ipv6", translate("IPv6 Setup"))
457 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"))
459 ip6.datatype = "ip6addr"
461 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
463 gw6.datatype = "ip6addr"
466 s2:tab("advanced", translate("Advanced Settings"))
468 bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
469 bcast.optional = true
470 bcast.datatype = "ip4addr"
472 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
474 dns.datatype = "ip4addr"
477 m2 = Map("dhcp", "", "")
478 function m2.on_parse()
479 local has_section = false
481 m2.uci:foreach("dhcp", "dhcp", function(s)
482 if s.interface == arg[1] then
488 if not has_section then
489 m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
494 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
497 s:tab("general", translate("General Setup"))
498 s:tab("advanced", translate("Advanced Settings"))
500 function s.filter(self, section)
501 return m2.uci:get("dhcp", section, "interface") == arg[1]
504 local ignore = s:taboption("general", Flag, "ignore",
505 translate("Ignore interface"),
506 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
509 ignore.rmempty = false
511 local start = s:taboption("general", Value, "start", translate("Start"),
512 translate("Lowest leased address as offset from the network address."))
513 start.optional = true
514 start.datatype = "uinteger"
515 start.default = "100"
517 local limit = s:taboption("general", Value, "limit", translate("Limit"),
518 translate("Maximum number of leased addresses."))
519 limit.optional = true
520 limit.datatype = "uinteger"
521 limit.default = "150"
523 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
524 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
526 ltime.default = "12h"
528 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
529 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
530 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
531 "clients having static leases will be served."))
534 function dd.cfgvalue(self, section)
535 return Flag.cfgvalue(self, section) or "1"
538 s:taboption("advanced", Flag, "force", translate("Force"),
539 translate("Force DHCP on this network even if another server is detected."))
541 -- XXX: is this actually useful?
542 --s:taboption("advanced", Value, "name", translate("Name"),
543 -- translate("Define a name for this network."))
545 mask = s:taboption("advanced", Value, "netmask",
546 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
547 translate("Override the netmask sent to clients. Normally it is calculated " ..
548 "from the subnet that is served."))
551 mask.datatype = "ip4addr"
553 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
554 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
555 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
557 for i, n in ipairs(s.children) do
559 n:depends("ignore", "")