4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
20 local type, pairs, ipairs, table, i18n
21 = type, pairs, ipairs, table, luci.i18n
23 local lmo = require "lmo"
24 local nxo = require "nixio"
25 local nfs = require "nixio.fs"
26 local iwi = require "iwinfo"
27 local ipc = require "luci.ip"
28 local utl = require "luci.util"
29 local uct = require "luci.model.uci.bind"
31 module "luci.model.network"
34 local ub = uct.bind("network")
39 cursor:unload("network")
40 cursor:load("network")
47 -- read interface information
49 for n, i in ipairs(nxo.getifaddrs()) do
50 local name = i.name:match("[^:]+")
51 local prnt = name:match("^([^%.]+)%.")
53 if not _M:ignore_interface(name) then
54 ifs[name] = ifs[name] or {
68 if i.family == "packet" then
69 ifs[name].flags = i.flags
70 ifs[name].stats = i.data
71 ifs[name].macaddr = i.addr
72 elseif i.family == "inet" then
73 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
74 elseif i.family == "inet6" then
75 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
80 -- read bridge informaton
82 for l in utl.execi("brctl show") do
83 if not l:match("STP") then
84 local r = utl.split(l, "%s+", nil, true)
90 ifnames = { ifs[r[4]] }
93 b.ifnames[1].bridge = b
97 b.ifnames[#b.ifnames+1] = ifs[r[2]]
98 b.ifnames[#b.ifnames].bridge = b
105 function has_ipv6(self)
106 return nfs.access("/proc/net/ipv6_route")
109 function add_network(self, n, options)
110 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
111 if ub.uci:section("network", "interface", n, options) then
117 function get_network(self, n)
118 if n and ub.uci:get("network", n) == "interface" then
123 function get_networks(self)
125 ub.uci:foreach("network", "interface",
127 nets[#nets+1] = network(s['.name'])
132 function del_network(self, n)
133 local r = ub.uci:delete("network", n)
135 ub.uci:foreach("network", "alias",
137 if s.interface == n then
138 ub.uci:delete("network", s['.name'])
141 ub.uci:foreach("network", "route",
143 if s.interface == n then
144 ub.uci:delete("network", s['.name'])
147 ub.uci:foreach("network", "route6",
149 if s.interface == n then
150 ub.uci:delete("network", s['.name'])
157 function rename_network(self, old, new)
159 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
160 r = ub.uci:section("network", "interface", new,
161 ub.uci:get_all("network", old))
164 ub.uci:foreach("network", "alias",
166 if s.interface == old then
167 ub.uci:set("network", s['.name'], "interface", new)
170 ub.uci:foreach("network", "route",
172 if s.interface == old then
173 ub.uci:set("network", s['.name'], "interface", new)
176 ub.uci:foreach("network", "route6",
178 if s.interface == old then
179 ub.uci:set("network", s['.name'], "interface", new)
187 function get_interface(self, i)
188 return ifs[i] and interface(i)
191 function get_interfaces(self)
194 for iface, _ in pairs(ifs) do
195 ifaces[#ifaces+1] = interface(iface)
200 function ignore_interface(self, x)
201 return (x:match("^wmaster%d") or x:match("^wifi%d")
202 or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
206 network = ub:section("interface")
207 network:property("device")
208 network:property("ifname")
209 network:property("proto")
210 network:property("type")
212 function network.name(self)
216 function network.is_bridge(self)
217 return (self:type() == "bridge")
220 function network.add_interface(self, ifname)
221 if type(ifname) ~= "string" then
222 ifname = ifname:name()
225 self:ifname(ub:list((self:ifname() or ''), ifname))
229 function network.del_interface(self, ifname)
230 if type(ifname) ~= "string" then
231 ifname = ifname:name()
233 self:ifname(ub:list((self:ifname() or ''), nil, ifname))
236 function network.get_interfaces(self)
239 for _, iface in ipairs(ub:list(self:ifname())) do
240 iface = iface:match("[^:]+")
242 ifaces[#ifaces+1] = interface(iface)
248 function network.contains_interface(self, iface)
250 local ifaces = ub:list(self:ifname())
252 if type(iface) ~= "string" then
256 for _, i in ipairs(ifaces) do
266 interface = utl.class()
267 function interface.__init__(self, ifname)
270 self.dev = ifs[ifname]
271 self.br = brs[ifname]
275 function interface.name(self)
279 function interface.mac(self)
280 return self.dev.macaddr or "00:00:00:00:00:00"
283 function interface.ipaddrs(self)
284 return self.dev.ipaddrs or { }
287 function interface.ip6addrs(self)
288 return self.dev.ip6addrs or { }
291 function interface.type(self)
292 if iwi.type(self.ifname) and iwi.type(self.ifname) ~= "dummy" then
294 elseif brs[self.ifname] then
296 elseif sws[self.ifname] or self.ifname:match("%.") then
303 function interface.get_type_i18n(self)
304 local x = self:type()
306 return i18n.translate("a_s_if_wifidev", "Wireless Adapter")
307 elseif x == "bridge" then
308 return i18n.translate("a_s_if_bridge", "Bridge")
309 elseif x == "switch" then
310 return i18n.translate("a_s_if_ethswitch", "Ethernet Switch")
312 return i18n.translate("a_s_if_ethdev", "Ethernet Adapter")
316 function interface.ports(self)
320 for _, iface in ipairs(self.br.ifnames) do
321 ifaces[#ifaces+1] = interface(iface.name)
327 function interface.bridge_id(self)
335 function interface.bridge_stp(self)
343 function interface.is_up(self)
344 return self.dev.flags and self.dev.flags.up
347 function interface.is_bridge(self)
348 return (self:type() == "bridge")
351 function interface.is_bridgeport(self)
352 return self.dev and self.dev.bridge and true or false
355 function interface.tx_bytes(self)
356 return self.dev and self.dev.stats
357 and self.dev.stats.tx_bytes or 0
360 function interface.rx_bytes(self)
361 return self.dev and self.dev.stats
362 and self.dev.stats.rx_bytes or 0
365 function interface.tx_packets(self)
366 return self.dev and self.dev.stats
367 and self.dev.stats.tx_packets or 0
370 function interface.rx_packets(self)
371 return self.dev and self.dev.stats
372 and self.dev.stats.rx_packets or 0
375 function interface.get_network(self)
376 if not self.network then
378 for _, net in ipairs(_M:get_networks()) do
379 if net:contains_interface(self.ifname) then