root/luci/trunk/libs/core/luasrc/model/network.lua @ 5448

Revision 5448, 10.0 KB (checked in by jow, 4 years ago)

all: change most translate statements to new format, some need manual cleanup

  • Property svn:keywords set to Id
Line 
1--[[
2LuCI - Network model
3
4Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18]]--
19
20local type, pairs, ipairs, loadfile, table, i18n
21    = type, pairs, ipairs, loadfile, table, luci.i18n
22
23local lmo = require "lmo"
24local nxo = require "nixio"
25local nfs = require "nixio.fs"
26local iwi = require "iwinfo"
27local ipc = require "luci.ip"
28local utl = require "luci.util"
29local uct = require "luci.model.uci.bind"
30
31module "luci.model.network"
32
33-- load extensions
34local ext
35local handler = { }
36
37for ext in nfs.glob(utl.libpath() .. "/model/network/*.lua") do
38    if nfs.access(ext) then
39        local m = loadfile(ext)
40        if m then
41            handler[#handler+1] = m()
42        end
43    end
44end
45
46function foreach_handler(code, ...)
47    local h
48    for _, h in ipairs(handler) do
49        if code(h, ...) then
50            return true
51        end
52    end
53    return false
54end
55
56local ub = uct.bind("network")
57local ifs, brs, sws
58
59function init(cursor)
60    if cursor then
61        cursor:unload("network")
62        cursor:load("network")
63        ub:init(cursor)
64
65        ifs = { }
66        brs = { }
67        sws = { }
68
69        -- init handler
70        foreach_handler(function(h)
71            h:init(cursor)
72            h:find_interfaces(ifs, brs)
73        end)
74
75        -- read interface information
76        local n, i
77        for n, i in ipairs(nxo.getifaddrs()) do
78            local name = i.name:match("[^:]+")
79            local prnt = name:match("^([^%.]+)%.")
80
81            if not _M:ignore_interface(name) then
82                ifs[name] = ifs[name] or {
83                    idx      = i.ifindex or n,
84                    name     = name,
85                    rawname  = i.name,
86                    flags    = { },
87                    ipaddrs  = { },
88                    ip6addrs = { }
89                }
90
91                if prnt then
92                    sws[name] = true
93                    sws[prnt] = true
94                end
95
96                if i.family == "packet" then
97                    ifs[name].flags   = i.flags
98                    ifs[name].stats   = i.data
99                    ifs[name].macaddr = i.addr
100                elseif i.family == "inet" then
101                    ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
102                elseif i.family == "inet6" then
103                    ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
104                end
105            end
106        end
107
108        -- read bridge informaton
109        local b, l
110        for l in utl.execi("brctl show") do
111            if not l:match("STP") then
112                local r = utl.split(l, "%s+", nil, true)
113                if #r == 4 then
114                    b = {
115                        name    = r[1],
116                        id      = r[2],
117                        stp     = r[3] == "yes",
118                        ifnames = { ifs[r[4]] }
119                    }
120                    if b.ifnames[1] then
121                        b.ifnames[1].bridge = b
122                    end
123                    brs[r[1]] = b
124                elseif b then
125                    b.ifnames[#b.ifnames+1] = ifs[r[2]]
126                    b.ifnames[#b.ifnames].bridge = b
127                end
128            end
129        end
130    end
131end
132
133function has_ipv6(self)
134    return nfs.access("/proc/net/ipv6_route")
135end
136
137function add_network(self, n, options)
138    if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
139        if ub.uci:section("network", "interface", n, options) then
140            return network(n)
141        end
142    end
143end
144
145function get_network(self, n)
146    if n and ub.uci:get("network", n) == "interface" then
147        return network(n)
148    end
149end
150
151function get_networks(self)
152    local nets = { }
153    ub.uci:foreach("network", "interface",
154        function(s)
155            nets[#nets+1] = network(s['.name'])
156        end)
157    return nets
158end
159
160function del_network(self, n)
161    local r = ub.uci:delete("network", n)
162    if r then
163        ub.uci:foreach("network", "alias",
164            function(s)
165                if s.interface == n then
166                    ub.uci:delete("network", s['.name'])
167                end
168            end)
169        ub.uci:foreach("network", "route",
170            function(s)
171                if s.interface == n then
172                    ub.uci:delete("network", s['.name'])
173                end
174            end)
175        ub.uci:foreach("network", "route6",
176            function(s)
177                if s.interface == n then
178                    ub.uci:delete("network", s['.name'])
179                end
180            end)
181
182        foreach_handler(function(h) h:del_network(n) end)
183    end
184    return r
185end
186
187function rename_network(self, old, new)
188    local r
189    if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
190        r = ub.uci:section("network", "interface", new,
191            ub.uci:get_all("network", old))
192
193        if r then
194            ub.uci:foreach("network", "alias",
195                function(s)
196                    if s.interface == old then
197                        ub.uci:set("network", s['.name'], "interface", new)
198                    end
199                end)
200            ub.uci:foreach("network", "route",
201                function(s)
202                    if s.interface == old then
203                        ub.uci:set("network", s['.name'], "interface", new)
204                    end
205                end)
206            ub.uci:foreach("network", "route6",
207                function(s)
208                    if s.interface == old then
209                        ub.uci:set("network", s['.name'], "interface", new)
210                    end
211                end)
212
213            foreach_handler(function(h) h:rename_network(old, new) end)
214        end
215    end
216    return r or false
217end
218
219function get_interface(self, i)
220    if ifs[i] then
221        return interface(i)
222    else
223        local j
224        for j, _ in pairs(ifs) do
225            if ifs[j].sid == i then
226                return interface(j)
227            end
228        end
229    end
230end
231
232function get_interfaces(self)
233    local ifaces = { }
234    local iface
235    for iface, _ in pairs(ifs) do
236        ifaces[#ifaces+1] = interface(iface)
237    end
238    return ifaces
239end
240
241function ignore_interface(self, x)
242    if foreach_handler(function(h) return h:ignore_interface(x) end) then
243        return true
244    else
245        return (x:match("^wmaster%d") or x:match("^wifi%d")
246            or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
247    end
248end
249
250
251network = ub:section("interface")
252network:property("device")
253network:property("ifname")
254network:property("proto")
255network:property("type")
256
257function network.name(self)
258    return self.sid
259end
260
261function network.is_bridge(self)
262    return (self:type() == "bridge")
263end
264
265function network.add_interface(self, ifname)
266    local ifaces, iface
267
268    if type(ifname) ~= "string" then
269        ifaces = { ifname:name() }
270    else
271        ifaces = ub:list(ifname)
272    end
273
274    for _, iface in ipairs(ifaces) do
275        if ifs[iface] then
276            -- make sure the interface is removed from all networks
277            local i = interface(iface)
278            local n = i:get_network()
279            if n then n:del_interface(iface) end
280
281            if ifs[iface].handler then
282                ifs[iface].handler:add_interface(self, iface, ifs[iface])
283            else
284                self:ifname(ub:list((self:ifname() or ''), iface))
285            end
286        end
287    end
288end
289
290function network.del_interface(self, ifname)
291    if type(ifname) ~= "string" then
292        ifname = ifname:name()
293    end
294
295    if ifs[ifname] and ifs[ifname].handler then
296        ifs[ifname].handler:del_interface(self, ifname, ifs[ifname])
297    else
298        self:ifname(ub:list((self:ifname() or ''), nil, ifname))
299    end
300end
301
302function network.get_interfaces(self)
303    local ifaces = { }
304    local iface
305    for _, iface in ipairs(ub:list(self:ifname())) do
306        iface = iface:match("[^:]+")
307        if ifs[iface] then
308            ifaces[#ifaces+1] = interface(iface)
309        end
310    end
311    for iface, _ in pairs(ifs) do
312        if ifs[iface].network == self:name() then
313            ifaces[#ifaces+1] = interface(iface)
314        end
315    end
316    return ifaces
317end
318
319function network.contains_interface(self, iface)
320    local i
321    local ifaces = ub:list(self:ifname())
322
323    if type(iface) ~= "string" then
324        iface = iface:name()
325    end
326
327    for _, i in ipairs(ifaces) do
328        if i == iface then
329            return true
330        end
331    end
332
333    for i, _ in pairs(ifs) do
334        if ifs[i].dev and ifs[i].dev.network == self:name() then
335            return true
336        end
337    end
338
339    return false
340end
341
342
343interface = utl.class()
344function interface.__init__(self, ifname)
345    if ifs[ifname] then
346        self.ifname = ifname
347        self.dev    = ifs[ifname]
348        self.br     = brs[ifname]
349    end
350end
351
352function interface.name(self)
353    return self.ifname
354end
355
356function interface.mac(self)
357    return self.dev.macaddr or "00:00:00:00:00:00"
358end
359
360function interface.ipaddrs(self)
361    return self.dev.ipaddrs or { }
362end
363
364function interface.ip6addrs(self)
365    return self.dev.ip6addrs or { }
366end
367
368function interface.type(self)
369    if self.dev and self.dev.type then
370        return self.dev.type
371    elseif brs[self.ifname] then
372        return "bridge"
373    elseif sws[self.ifname] or self.ifname:match("%.") then
374        return "switch"
375    else
376        return "ethernet"
377    end
378end
379
380function interface.shortname(self)
381    if self.dev and self.dev.handler then
382        return self.dev.handler:shortname(self)
383    else
384        return self.ifname
385    end
386end
387
388function interface.get_i18n(self)
389    if self.dev and self.dev.handler then
390        return self.dev.handler:get_i18n(self)
391    else
392        return "%s: %q" %{ self:get_type_i18n(), self:name() }
393    end
394end
395
396function interface.get_type_i18n(self)
397    local x = self:type()
398    if x == "wifi" then
399        return i18n.translate("Wireless Adapter")
400    elseif x == "bridge" then
401        return i18n.translate("Bridge")
402    elseif x == "switch" then
403        return i18n.translate("Ethernet Switch")
404    else
405        return i18n.translate("Ethernet Adapter")
406    end
407end
408
409function interface.ports(self)
410    if self.br then
411        local iface
412        local ifaces = { }
413        for _, iface in ipairs(self.br.ifnames) do
414            ifaces[#ifaces+1] = interface(iface.name)
415        end
416        return ifaces
417    end
418end
419
420function interface.bridge_id(self)
421    if self.br then
422        return self.br.id
423    else
424        return nil
425    end
426end
427
428function interface.bridge_stp(self)
429    if self.br then
430        return self.br.stp
431    else
432        return false
433    end
434end
435
436function interface.is_up(self)
437    return self.dev.flags and self.dev.flags.up
438end
439
440function interface.is_bridge(self)
441    return (self:type() == "bridge")
442end
443
444function interface.is_bridgeport(self)
445    return self.dev and self.dev.bridge and true or false
446end
447
448function interface.tx_bytes(self)
449    return self.dev and self.dev.stats
450        and self.dev.stats.tx_bytes or 0
451end
452
453function interface.rx_bytes(self)
454    return self.dev and self.dev.stats
455        and self.dev.stats.rx_bytes or 0
456end
457
458function interface.tx_packets(self)
459    return self.dev and self.dev.stats
460        and self.dev.stats.tx_packets or 0
461end
462
463function interface.rx_packets(self)
464    return self.dev and self.dev.stats
465        and self.dev.stats.rx_packets or 0
466end
467
468function interface.get_network(self)
469    if self.dev and self.dev.network then
470        self.network = _M:get_network(self.dev.network)
471    end
472
473    if not self.network then
474        local net
475        for _, net in ipairs(_M:get_networks()) do
476            if net:contains_interface(self.ifname) then
477                self.network = net
478                return net
479            end
480        end
481    else
482        return self.network
483    end
484end
485
Note: See TracBrowser for help on using the browser.