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")
281 if has_pppd or has_pppoe or has_pppoa or has_3g or has_pptp then
282 ka = s:taboption("ppp", Value, "keepalive",
283 translate("Keep-Alive"),
284 translate("Number of failed connection tests to initiate automatic reconnect")
286 ka:depends("proto", "pptp")
287 ka:depends("proto", "pppoe")
288 ka:depends("proto", "pppoa")
289 ka:depends("proto", "ppp")
290 ka:depends("proto", "3g")
292 demand = s:taboption("ppp", Value, "demand",
293 translate("Automatic Disconnect"),
294 translate("Time (in seconds) after which an unused connection will be closed")
296 demand.optional = true
297 demand.datatype = "uinteger"
298 demand:depends("proto", "pptp")
299 demand:depends("proto", "pppoe")
300 demand:depends("proto", "pppoa")
301 demand:depends("proto", "ppp")
302 demand:depends("proto", "3g")
306 encaps = s:taboption("atm", ListValue, "encaps", translate("PPPoA Encapsulation"))
307 encaps:depends("proto", "pppoa")
308 encaps:value("vc", "VC-Mux")
309 encaps:value("llc", "LLC")
311 atmdev = s:taboption("atm", Value, "atmdev", translate("ATM device number"))
312 atmdev:depends("proto", "pppoa")
314 atmdev.datatype = "uinteger"
316 vci = s:taboption("atm", Value, "vci", translate("ATM Virtual Channel Identifier (VCI)"))
317 vci:depends("proto", "pppoa")
319 vci.datatype = "uinteger"
321 vpi = s:taboption("atm", Value, "vpi", translate("ATM Virtual Path Identifier (VPI)"))
322 vpi:depends("proto", "pppoa")
324 vpi.datatype = "uinteger"
327 if has_pptp or has_pppd or has_pppoe or has_pppoa or has_3g then
328 device = s:taboption("general", Value, "device",
329 translate("Modem device"),
330 translate("The device node of your modem, e.g. /dev/ttyUSB0")
332 device:depends("proto", "ppp")
333 device:depends("proto", "3g")
335 defaultroute = s:taboption("ppp", Flag, "defaultroute",
336 translate("Replace default route"),
337 translate("Let pppd replace the current default route to use the PPP interface after successful connect")
339 defaultroute:depends("proto", "ppp")
340 defaultroute:depends("proto", "pppoa")
341 defaultroute:depends("proto", "pppoe")
342 defaultroute:depends("proto", "pptp")
343 defaultroute:depends("proto", "3g")
344 defaultroute.rmempty = false
345 function defaultroute.cfgvalue(...)
346 return ( AbstractValue.cfgvalue(...) or '1' )
349 peerdns = s:taboption("ppp", Flag, "peerdns",
350 translate("Use peer DNS"),
351 translate("Configure the local DNS server to use the name servers adverticed by the PPP peer")
353 peerdns:depends("proto", "ppp")
354 peerdns:depends("proto", "pppoa")
355 peerdns:depends("proto", "pppoe")
356 peerdns:depends("proto", "pptp")
357 peerdns:depends("proto", "3g")
358 peerdns.rmempty = false
359 function peerdns.cfgvalue(...)
360 return ( AbstractValue.cfgvalue(...) or '1' )
364 ipv6 = s:taboption("ppp", Flag, "ipv6", translate("Enable IPv6 on PPP link") )
365 ipv6:depends("proto", "ppp")
366 ipv6:depends("proto", "pppoa")
367 ipv6:depends("proto", "pppoe")
368 ipv6:depends("proto", "pptp")
369 ipv6:depends("proto", "3g")
372 connect = s:taboption("ppp", Value, "connect",
373 translate("Connect script"),
374 translate("Let pppd run this script after establishing the PPP link")
376 connect:depends("proto", "ppp")
377 connect:depends("proto", "pppoe")
378 connect:depends("proto", "pppoa")
379 connect:depends("proto", "pptp")
380 connect:depends("proto", "3g")
382 disconnect = s:taboption("ppp", Value, "disconnect",
383 translate("Disconnect script"),
384 translate("Let pppd run this script before tearing down the PPP link")
386 disconnect:depends("proto", "ppp")
387 disconnect:depends("proto", "pppoe")
388 disconnect:depends("proto", "pppoa")
389 disconnect:depends("proto", "pptp")
390 disconnect:depends("proto", "3g")
392 pppd_options = s:taboption("ppp", Value, "pppd_options",
393 translate("Additional pppd options"),
394 translate("Specify additional command line arguments for pppd here")
396 pppd_options:depends("proto", "ppp")
397 pppd_options:depends("proto", "pppoa")
398 pppd_options:depends("proto", "pppoe")
399 pppd_options:depends("proto", "pptp")
400 pppd_options:depends("proto", "3g")
402 maxwait = s:taboption("ppp", Value, "maxwait",
403 translate("Setup wait time"),
404 translate("Seconds to wait for the modem to become ready before attempting to connect")
406 maxwait:depends("proto", "3g")
407 maxwait.default = "0"
408 maxwait.optional = true
409 maxwait.datatype = "uinteger"
412 s2 = m:section(TypedSection, "alias", translate("IP-Aliases"))
415 s2:depends("interface", arg[1])
416 s2.defaults.interface = arg[1]
418 s2:tab("general", translate("General Setup"))
419 s2.defaults.proto = "static"
421 ip = s2:taboption("general", Value, "ipaddr", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Address"))
423 ip.datatype = "ip4addr"
425 nm = s2:taboption("general", Value, "netmask", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"))
427 nm.datatype = "ip4addr"
428 nm:value("255.255.255.0")
429 nm:value("255.255.0.0")
430 nm:value("255.0.0.0")
432 gw = s2:taboption("general", Value, "gateway", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Gateway"))
434 gw.datatype = "ip4addr"
437 s2:tab("ipv6", translate("IPv6 Setup"))
439 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"))
441 ip6.datatype = "ip6addr"
443 gw6 = s2:taboption("ipv6", Value, "ip6gw", translate("<abbr title=\"Internet Protocol Version 6\">IPv6</abbr>-Gateway"))
445 gw6.datatype = "ip6addr"
448 s2:tab("advanced", translate("Advanced Settings"))
450 bcast = s2:taboption("advanced", Value, "bcast", translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Broadcast"))
451 bcast.optional = true
452 bcast.datatype = "ip4addr"
454 dns = s2:taboption("advanced", Value, "dns", translate("<abbr title=\"Domain Name System\">DNS</abbr>-Server"))
456 dns.datatype = "ip4addr"
459 m2 = Map("dhcp", "", "")
460 function m2.on_parse()
461 local has_section = false
463 m2.uci:foreach("dhcp", "dhcp", function(s)
464 if s.interface == arg[1] then
470 if not has_section then
471 m2.uci:section("dhcp", "dhcp", nil, { interface = arg[1], ignore = "1" })
476 s = m2:section(TypedSection, "dhcp", translate("DHCP Server"))
479 s:tab("general", translate("General Setup"))
480 s:tab("advanced", translate("Advanced Settings"))
482 function s.filter(self, section)
483 return m2.uci:get("dhcp", section, "interface") == arg[1]
486 local ignore = s:taboption("general", Flag, "ignore",
487 translate("Ignore interface"),
488 translate("Disable <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr> for " ..
491 ignore.rmempty = false
493 local start = s:taboption("general", Value, "start", translate("Start"),
494 translate("Lowest leased address as offset from the network address."))
495 start.optional = true
496 start.datatype = "uinteger"
497 start.default = "100"
499 local limit = s:taboption("general", Value, "limit", translate("Limit"),
500 translate("Maximum number of leased addresses."))
501 limit.optional = true
502 limit.datatype = "uinteger"
503 limit.default = "150"
505 local ltime = s:taboption("general", Value, "leasetime", translate("Leasetime"),
506 translate("Expiry time of leased addresses, minimum is 2 Minutes (<code>2m</code>)."))
508 ltime.default = "12h"
510 local dd = s:taboption("advanced", Flag, "dynamicdhcp",
511 translate("Dynamic <abbr title=\"Dynamic Host Configuration Protocol\">DHCP</abbr>"),
512 translate("Dynamically allocate DHCP addresses for clients. If disabled, only " ..
513 "clients having static leases will be served."))
516 function dd.cfgvalue(self, section)
517 return Flag.cfgvalue(self, section) or "1"
520 s:taboption("advanced", Flag, "force", translate("Force"),
521 translate("Force DHCP on this network even if another server is detected."))
523 -- XXX: is this actually useful?
524 --s:taboption("advanced", Value, "name", translate("Name"),
525 -- translate("Define a name for this network."))
527 mask = s:taboption("advanced", Value, "netmask",
528 translate("<abbr title=\"Internet Protocol Version 4\">IPv4</abbr>-Netmask"),
529 translate("Override the netmask sent to clients. Normally it is calculated " ..
530 "from the subnet that is served."))
533 mask.datatype = "ip4addr"
535 s:taboption("advanced", DynamicList, "dhcp_option", translate("DHCP-Options"),
536 translate("Define additional DHCP options, for example \"<code>6,192.168.2.1," ..
537 "192.168.2.2</code>\" which advertises different DNS servers to clients."))
539 for i, n in ipairs(s.children) do
541 n:depends("ignore", "")