all: change most translate statements to new format, some need manual cleanup
[project/luci.git] / libs / core / luasrc / model / network.lua
1 --[[
2 LuCI - Network model
3
4 Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
5
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
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
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.
17
18 ]]--
19
20 local type, pairs, ipairs, loadfile, table, i18n
21 = type, pairs, ipairs, loadfile, table, luci.i18n
22
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"
30
31 module "luci.model.network"
32
33 -- load extensions
34 local ext
35 local handler = { }
36
37 for 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
44 end
45
46 function 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
54 end
55
56 local ub = uct.bind("network")
57 local ifs, brs, sws
58
59 function 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
131 end
132
133 function has_ipv6(self)
134 return nfs.access("/proc/net/ipv6_route")
135 end
136
137 function 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
143 end
144
145 function get_network(self, n)
146 if n and ub.uci:get("network", n) == "interface" then
147 return network(n)
148 end
149 end
150
151 function 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
158 end
159
160 function 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
185 end
186
187 function 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
217 end
218
219 function 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
230 end
231
232 function 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
239 end
240
241 function 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
248 end
249
250
251 network = ub:section("interface")
252 network:property("device")
253 network:property("ifname")
254 network:property("proto")
255 network:property("type")
256
257 function network.name(self)
258 return self.sid
259 end
260
261 function network.is_bridge(self)
262 return (self:type() == "bridge")
263 end
264
265 function 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
288 end
289
290 function 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
300 end
301
302 function 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
317 end
318
319 function 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
340 end
341
342
343 interface = utl.class()
344 function 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
350 end
351
352 function interface.name(self)
353 return self.ifname
354 end
355
356 function interface.mac(self)
357 return self.dev.macaddr or "00:00:00:00:00:00"
358 end
359
360 function interface.ipaddrs(self)
361 return self.dev.ipaddrs or { }
362 end
363
364 function interface.ip6addrs(self)
365 return self.dev.ip6addrs or { }
366 end
367
368 function 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
378 end
379
380 function 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
386 end
387
388 function 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
394 end
395
396 function 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
407 end
408
409 function 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
418 end
419
420 function interface.bridge_id(self)
421 if self.br then
422 return self.br.id
423 else
424 return nil
425 end
426 end
427
428 function interface.bridge_stp(self)
429 if self.br then
430 return self.br.stp
431 else
432 return false
433 end
434 end
435
436 function interface.is_up(self)
437 return self.dev.flags and self.dev.flags.up
438 end
439
440 function interface.is_bridge(self)
441 return (self:type() == "bridge")
442 end
443
444 function interface.is_bridgeport(self)
445 return self.dev and self.dev.bridge and true or false
446 end
447
448 function interface.tx_bytes(self)
449 return self.dev and self.dev.stats
450 and self.dev.stats.tx_bytes or 0
451 end
452
453 function interface.rx_bytes(self)
454 return self.dev and self.dev.stats
455 and self.dev.stats.rx_bytes or 0
456 end
457
458 function interface.tx_packets(self)
459 return self.dev and self.dev.stats
460 and self.dev.stats.tx_packets or 0
461 end
462
463 function interface.rx_packets(self)
464 return self.dev and self.dev.stats
465 and self.dev.stats.rx_packets or 0
466 end
467
468 function 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
484 end
485