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 iwi = require "iwinfo"
26 local ipc = require "luci.ip"
27 local utl = require "luci.util"
28 local uct = require "luci.model.uci.bind"
30 module "luci.model.network"
33 local ub = uct.bind("network")
38 cursor:unload("network")
39 cursor:load("network")
45 -- read interface information
47 for n, i in ipairs(nxo.getifaddrs()) do
48 local name = i.name:match("[^:]+")
50 if not _M:ignore_interface(name) then
51 ifs[name] = ifs[name] or {
60 if i.family == "packet" then
61 ifs[name].flags = i.flags
62 ifs[name].stats = i.data
63 ifs[name].macaddr = i.addr
64 elseif i.family == "inet" then
65 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
66 elseif i.family == "inet6" then
67 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
72 -- read bridge informaton
74 for l in utl.execi("brctl show") do
75 if not l:match("STP") then
76 local r = utl.split(l, "%s+", nil, true)
82 ifnames = { ifs[r[4]] }
85 b.ifnames[1].bridge = b
89 b.ifnames[#b.ifnames+1] = ifs[r[2]]
90 b.ifnames[#b.ifnames].bridge = b
97 function add_network(self, n, options)
98 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
99 if ub.uci:section("network", "interface", n, options) then
105 function get_network(self, n)
106 if n and ub.uci:get("network", n) == "interface" then
111 function get_networks(self)
113 ub.uci:foreach("network", "interface",
115 nets[#nets+1] = network(s['.name'])
120 function del_network(self, n)
121 local r = ub.uci:delete("network", n)
123 ub.uci:foreach("network", "alias",
125 if s.interface == n then
126 ub.uci:delete("network", s['.name'])
129 ub.uci:foreach("network", "route",
131 if s.interface == n then
132 ub.uci:delete("network", s['.name'])
135 ub.uci:foreach("network", "route6",
137 if s.interface == n then
138 ub.uci:delete("network", s['.name'])
145 function rename_network(self, old, new)
147 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
148 r = ub.uci:section("network", "interface", new,
149 ub.uci:get_all("network", old))
152 ub.uci:foreach("network", "alias",
154 if s.interface == old then
155 ub.uci:set("network", s['.name'], "interface", new)
158 ub.uci:foreach("network", "route",
160 if s.interface == old then
161 ub.uci:set("network", s['.name'], "interface", new)
164 ub.uci:foreach("network", "route6",
166 if s.interface == old then
167 ub.uci:set("network", s['.name'], "interface", new)
175 function get_interface(self, i)
176 return ifs[i] and interface(i)
179 function get_interfaces(self)
182 for iface, _ in pairs(ifs) do
183 ifaces[#ifaces+1] = interface(iface)
188 function ignore_interface(self, x)
189 return (x:match("^wmaster%d") or x:match("^wifi%d")
190 or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
194 network = ub:section("interface")
195 network:property("device")
196 network:property("ifname")
197 network:property("proto")
198 network:property("type")
200 function network.name(self)
204 function network.is_bridge(self)
205 return (self:type() == "bridge")
208 function network.add_interface(self, ifname)
209 if type(ifname) ~= "string" then
210 ifname = ifname:name()
213 self:ifname(ub:list((self:ifname() or ''), ifname))
217 function network.del_interface(self, ifname)
218 if type(ifname) ~= "string" then
219 ifname = ifname:name()
221 self:ifname(ub:list((self:ifname() or ''), nil, ifname))
224 function network.get_interfaces(self)
227 for _, iface in ub:list(
228 (self:ifname() or '') .. ' ' .. (self:device() or '')
230 iface = iface:match("[^:]+")
232 ifaces[#ifaces+1] = interface(iface)
238 function network.contains_interface(self, iface)
240 local ifaces = ub:list(
241 (self:ifname() or '') .. ' ' .. (self:device() or '')
244 if type(iface) ~= "string" then
248 for _, i in ipairs(ifaces) do
258 interface = utl.class()
259 function interface.__init__(self, ifname)
262 self.dev = ifs[ifname]
263 self.br = brs[ifname]
267 function interface.name(self)
271 function interface.type(self)
272 if iwi.type(self.ifname) and iwi.type(self.ifname) ~= "dummy" then
274 elseif brs[self.ifname] then
276 elseif self.ifname:match("%.") then
283 function interface.get_type_i18n(self)
284 local x = self:type()
286 return i18n.translate("a_s_if_wifidev", "Wireless Adapter")
287 elseif x == "bridge" then
288 return i18n.translate("a_s_if_bridge", "Bridge")
289 elseif x == "switch" then
290 return i18n.translate("a_s_if_ethswitch", "Ethernet Switch")
292 return i18n.translate("a_s_if_ethdev", "Ethernet Adapter")
296 function interface.ports(self)
300 for _, iface in ipairs(self.br.ifnames) do
301 ifaces[#ifaces+1] = interface(iface)
307 function interface.is_up(self)
308 return self.dev.flags and self.dev.flags.up
311 function interface.is_bridge(self)
312 return (self:type() == "bridge")
315 function interface.get_network(self)
317 for _, net in ipairs(_M:get_networks()) do
318 if net:contains_interface(self.ifname) then