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")
46 -- read interface information
48 for n, i in ipairs(nxo.getifaddrs()) do
49 local name = i.name:match("[^:]+")
51 if not _M:ignore_interface(name) then
52 ifs[name] = ifs[name] or {
61 if i.family == "packet" then
62 ifs[name].flags = i.flags
63 ifs[name].stats = i.data
64 ifs[name].macaddr = i.addr
65 elseif i.family == "inet" then
66 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
67 elseif i.family == "inet6" then
68 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
73 -- read bridge informaton
75 for l in utl.execi("brctl show") do
76 if not l:match("STP") then
77 local r = utl.split(l, "%s+", nil, true)
83 ifnames = { ifs[r[4]] }
86 b.ifnames[1].bridge = b
90 b.ifnames[#b.ifnames+1] = ifs[r[2]]
91 b.ifnames[#b.ifnames].bridge = b
98 function has_ipv6(self)
99 return nfs.access("/proc/net/ipv6_route")
102 function add_network(self, n, options)
103 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
104 if ub.uci:section("network", "interface", n, options) then
110 function get_network(self, n)
111 if n and ub.uci:get("network", n) == "interface" then
116 function get_networks(self)
118 ub.uci:foreach("network", "interface",
120 nets[#nets+1] = network(s['.name'])
125 function del_network(self, n)
126 local r = ub.uci:delete("network", n)
128 ub.uci:foreach("network", "alias",
130 if s.interface == n then
131 ub.uci:delete("network", s['.name'])
134 ub.uci:foreach("network", "route",
136 if s.interface == n then
137 ub.uci:delete("network", s['.name'])
140 ub.uci:foreach("network", "route6",
142 if s.interface == n then
143 ub.uci:delete("network", s['.name'])
150 function rename_network(self, old, new)
152 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
153 r = ub.uci:section("network", "interface", new,
154 ub.uci:get_all("network", old))
157 ub.uci:foreach("network", "alias",
159 if s.interface == old then
160 ub.uci:set("network", s['.name'], "interface", new)
163 ub.uci:foreach("network", "route",
165 if s.interface == old then
166 ub.uci:set("network", s['.name'], "interface", new)
169 ub.uci:foreach("network", "route6",
171 if s.interface == old then
172 ub.uci:set("network", s['.name'], "interface", new)
180 function get_interface(self, i)
181 return ifs[i] and interface(i)
184 function get_interfaces(self)
187 for iface, _ in pairs(ifs) do
188 ifaces[#ifaces+1] = interface(iface)
193 function ignore_interface(self, x)
194 return (x:match("^wmaster%d") or x:match("^wifi%d")
195 or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
199 network = ub:section("interface")
200 network:property("device")
201 network:property("ifname")
202 network:property("proto")
203 network:property("type")
205 function network.name(self)
209 function network.is_bridge(self)
210 return (self:type() == "bridge")
213 function network.add_interface(self, ifname)
214 if type(ifname) ~= "string" then
215 ifname = ifname:name()
218 self:ifname(ub:list((self:ifname() or ''), ifname))
222 function network.del_interface(self, ifname)
223 if type(ifname) ~= "string" then
224 ifname = ifname:name()
226 self:ifname(ub:list((self:ifname() or ''), nil, ifname))
229 function network.get_interfaces(self)
232 for _, iface in ub:list(
233 (self:ifname() or '') .. ' ' .. (self:device() or '')
235 iface = iface:match("[^:]+")
237 ifaces[#ifaces+1] = interface(iface)
243 function network.contains_interface(self, iface)
245 local ifaces = ub:list(
246 (self:ifname() or '') .. ' ' .. (self:device() or '')
249 if type(iface) ~= "string" then
253 for _, i in ipairs(ifaces) do
263 interface = utl.class()
264 function interface.__init__(self, ifname)
267 self.dev = ifs[ifname]
268 self.br = brs[ifname]
272 function interface.name(self)
276 function interface.mac(self)
277 return self.dev.macaddr or "00:00:00:00:00:00"
280 function interface.ipaddrs(self)
281 return self.dev.ipaddrs or { }
284 function interface.ip6addrs(self)
285 return self.dev.ip6addrs or { }
288 function interface.type(self)
289 if iwi.type(self.ifname) and iwi.type(self.ifname) ~= "dummy" then
291 elseif brs[self.ifname] then
293 elseif self.ifname:match("%.") then
300 function interface.get_type_i18n(self)
301 local x = self:type()
303 return i18n.translate("a_s_if_wifidev", "Wireless Adapter")
304 elseif x == "bridge" then
305 return i18n.translate("a_s_if_bridge", "Bridge")
306 elseif x == "switch" then
307 return i18n.translate("a_s_if_ethswitch", "Ethernet Switch")
309 return i18n.translate("a_s_if_ethdev", "Ethernet Adapter")
313 function interface.ports(self)
317 for _, iface in ipairs(self.br.ifnames) do
318 ifaces[#ifaces+1] = interface(iface.name)
324 function interface.bridge_id(self)
332 function interface.bridge_stp(self)
340 function interface.is_up(self)
341 return self.dev.flags and self.dev.flags.up
344 function interface.is_bridge(self)
345 return (self:type() == "bridge")
348 function interface.is_bridgeport(self)
349 return self.dev and self.dev.bridge and true or false
352 function interface.tx_bytes(self)
353 return self.dev and self.dev.stats
354 and self.dev.stats.tx_bytes or 0
357 function interface.rx_bytes(self)
358 return self.dev and self.dev.stats
359 and self.dev.stats.rx_bytes or 0
362 function interface.tx_packets(self)
363 return self.dev and self.dev.stats
364 and self.dev.stats.tx_packets or 0
367 function interface.rx_packets(self)
368 return self.dev and self.dev.stats
369 and self.dev.stats.rx_packets or 0
372 function interface.get_network(self)
373 if not self.network then
375 for _, net in ipairs(_M:get_networks()) do
376 if net:contains_interface(self.ifname) then