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 = type, pairs, ipairs, table
22 local lmo = require "lmo"
23 local nxo = require "nixio"
24 local iwi = require "iwinfo"
25 local ipc = require "luci.ip"
26 local utl = require "luci.util"
27 local uct = require "luci.model.uci.bind"
29 module "luci.model.network"
32 local ub = uct.bind("network")
37 cursor:unload("network")
38 cursor:load("network")
44 -- read interface information
46 for n, i in ipairs(nxo.getifaddrs()) do
47 local name = i.name:match("[^:]+")
49 if not _M:ignore_interface(name) then
50 ifs[name] = ifs[name] or {
59 if i.family == "packet" then
60 ifs[name].flags = i.flags
61 ifs[name].stats = i.data
62 ifs[name].macaddr = i.addr
63 elseif i.family == "inet" then
64 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
65 elseif i.family == "inet6" then
66 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
71 -- read bridge informaton
73 for l in utl.execi("brctl show") do
74 if not l:match("STP") then
75 local r = utl.split(l, "%s+", nil, true)
81 ifnames = { ifs[r[4]] }
84 b.ifnames[1].bridge = b
88 b.ifnames[#b.ifnames+1] = ifs[r[2]]
89 b.ifnames[#b.ifnames].bridge = b
96 function add_network(self, n, options)
97 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
98 if ub.uci:section("network", "interface", n, options) then
104 function get_network(self, n)
105 if n and ub.uci:get("network", n) == "interface" then
110 function get_networks(self)
112 ub.uci:foreach("network", "interface",
114 nets[#nets+1] = network(s['.name'])
119 function del_network(self, n)
120 local r = ub.uci:delete("network", n)
122 ub.uci:foreach("network", "alias",
124 if s.interface == n then
125 ub.uci:delete("network", s['.name'])
128 ub.uci:foreach("network", "route",
130 if s.interface == n then
131 ub.uci:delete("network", s['.name'])
134 ub.uci:foreach("network", "route6",
136 if s.interface == n then
137 ub.uci:delete("network", s['.name'])
144 function rename_network(self, old, new)
146 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
147 r = ub.uci:section("network", "interface", new,
148 ub.uci:get_all("network", old))
151 ub.uci:foreach("network", "alias",
153 if s.interface == old then
154 ub.uci:set("network", s['.name'], "interface", new)
157 ub.uci:foreach("network", "route",
159 if s.interface == old then
160 ub.uci:set("network", s['.name'], "interface", new)
163 ub.uci:foreach("network", "route6",
165 if s.interface == old then
166 ub.uci:set("network", s['.name'], "interface", new)
174 function get_interface(self, i)
175 return ifs[i] and interface(i)
178 function get_interfaces(self)
181 for iface, _ in pairs(ifs) do
182 ifaces[#ifaces+1] = interface(iface)
187 function ignore_interface(self, x)
188 return (x:match("^wmaster%d") or x:match("^wifi%d")
189 or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
193 network = ub:section("interface")
194 network:property("device")
195 network:property("ifname")
196 network:property("proto")
197 network:property("type")
199 function network.name(self)
203 function network.is_bridge(self)
204 return (self:type() == "bridge")
207 function network.add_interface(self, ifname)
208 if type(ifname) ~= "string" then
209 ifname = ifname:ifname()
212 self:ifname(ub:list((self:ifname() or ''), ifname))
216 function network.del_interface(self, ifname)
217 if type(ifname) ~= "string" then
218 ifname = ifname:ifname()
220 self:ifname(ub:list((self:ifname() or ''), nil, ifname))
223 function network.get_interfaces(self)
226 for _, iface in ub:list(
227 (self:ifname() or '') .. ' ' .. (self:device() or '')
229 iface = iface:match("[^:]+")
231 ifaces[#ifaces+1] = interface(iface)
237 function contains_interface(self, iface)
239 local ifaces = ub:list(
240 (self:ifname() or '') .. ' ' .. (self:device() or '')
243 if type(iface) ~= "string" then
244 iface = iface:ifname()
247 for _, i in ipairs(ifaces) do
257 interface = utl.class()
258 function interface.__init__(self, ifname)
261 self.dev = ifs[ifname]
262 self.br = brs[ifname]
266 function interface.name(self)
270 function interface.type(self)
271 if iwi.type(self.ifname) and iwi.type(self.ifname) ~= "dummy" then
273 elseif brs[self.ifname] then
275 elseif self.ifname:match("%.") then
282 function interface.ports(self)
286 for _, iface in ipairs(self.br.ifnames) do
287 ifaces[#ifaces+1] = interface(iface)
293 function interface.is_up(self)
294 return self.dev.flags and self.dev.flags.up
297 function interface.is_bridge(self)
298 return (self:type() == "bridge")
301 function interface.get_network(self)
303 for _, net in ipairs(_M:get_networks()) do
304 if net:contains_interface(self.ifname) then