libs/core: return ordered list in luci.model.network.get_interfaces()
[project/luci.git] / libs / core / luasrc / model / network.lua
1 --[[
2 LuCI - Network model
3
4 Copyright 2009-2010 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, tonumber, math, i18n
21 = type, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n
22
23 local nxo = require "nixio"
24 local ipc = require "luci.ip"
25 local sys = require "luci.sys"
26 local utl = require "luci.util"
27 local dsp = require "luci.dispatcher"
28 local uci = require "luci.model.uci"
29
30 module "luci.model.network"
31
32
33 local ifs, brs, sws, uci_r, uci_s
34
35 function _list_del(c, s, o, r)
36 local val = uci_r:get(c, s, o)
37 if val then
38 local l = { }
39 if type(val) == "string" then
40 for val in val:gmatch("%S+") do
41 if val ~= r then
42 l[#l+1] = val
43 end
44 end
45 if #l > 0 then
46 uci_r:set(c, s, o, table.concat(l, " "))
47 else
48 uci_r:delete(c, s, o)
49 end
50 elseif type(val) == "table" then
51 for _, val in ipairs(val) do
52 if val ~= r then
53 l[#l+1] = val
54 end
55 end
56 if #l > 0 then
57 uci_r:set(c, s, o, l)
58 else
59 uci_r:delete(c, s, o)
60 end
61 end
62 end
63 end
64
65 function _list_add(c, s, o, a)
66 local val = uci_r:get(c, s, o) or ""
67 if type(val) == "string" then
68 local l = { }
69 for val in val:gmatch("%S+") do
70 if val ~= a then
71 l[#l+1] = val
72 end
73 end
74 l[#l+1] = a
75 uci_r:set(c, s, o, table.concat(l, " "))
76 elseif type(val) == "table" then
77 local l = { }
78 for _, val in ipairs(val) do
79 if val ~= a then
80 l[#l+1] = val
81 end
82 end
83 l[#l+1] = a
84 uci_r:set(c, s, o, l)
85 end
86 end
87
88 function _stror(s1, s2)
89 if not s1 or #s1 == 0 then
90 return s2 and #s2 > 0 and s2
91 else
92 return s1
93 end
94 end
95
96 function _get(c, s, o)
97 return uci_r:get(c, s, o)
98 end
99
100 function _set(c, s, o, v)
101 if v ~= nil then
102 if type(v) == "boolean" then v = v and "1" or "0" end
103 return uci_r:set(c, s, o, v)
104 else
105 return uci_r:delete(c, s, o)
106 end
107 end
108
109 function _wifi_iface(x)
110 return (
111 x:match("^wlan%d") or x:match("^wl%d") or x:match("^ath%d") or
112 x:match("^%w+%.network%d")
113 )
114 end
115
116 function _wifi_lookup(ifn)
117 -- got a radio#.network# pseudo iface, locate the corresponding section
118 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
119 if radio and ifnidx then
120 local sid = nil
121 local num = 0
122
123 ifnidx = tonumber(ifnidx)
124 uci_r:foreach("wireless", "wifi-iface",
125 function(s)
126 if s.device == radio then
127 num = num + 1
128 if num == ifnidx then
129 sid = s['.name']
130 return false
131 end
132 end
133 end)
134
135 return sid
136
137 -- looks like wifi, try to locate the section via state vars
138 elseif _wifi_iface(ifn) then
139 local sid = nil
140
141 uci_s:foreach("wireless", "wifi-iface",
142 function(s)
143 if s.ifname == ifn then
144 sid = s['.name']
145 return false
146 end
147 end)
148
149 return sid
150 end
151 end
152
153 function _iface_ignore(x)
154 return (
155 x:match("^wmaster%d") or x:match("^wifi%d") or x:match("^hwsim%d") or
156 x:match("^imq%d") or x:match("^mon.wlan%d") or x:match("^6in4-%w") or
157 x:match("^3g-%w") or x:match("^ppp-%w") or x:match("^pppoe-%w") or
158 x:match("^pppoa-%w") or x == "lo"
159 )
160 end
161
162
163 function init(cursor)
164 uci_r = cursor or uci_r or uci.cursor()
165 uci_s = uci_r:substate()
166
167 ifs = { }
168 brs = { }
169 sws = { }
170
171 -- read interface information
172 local n, i
173 for n, i in ipairs(nxo.getifaddrs()) do
174 local name = i.name:match("[^:]+")
175 local prnt = name:match("^([^%.]+)%.")
176
177 if not _iface_ignore(name) then
178 ifs[name] = ifs[name] or {
179 idx = i.ifindex or n,
180 name = name,
181 rawname = i.name,
182 flags = { },
183 ipaddrs = { },
184 ip6addrs = { }
185 }
186
187 if prnt then
188 sws[name] = true
189 sws[prnt] = true
190 end
191
192 if i.family == "packet" then
193 ifs[name].flags = i.flags
194 ifs[name].stats = i.data
195 ifs[name].macaddr = i.addr
196 elseif i.family == "inet" then
197 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
198 elseif i.family == "inet6" then
199 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
200 end
201 end
202 end
203
204 -- read bridge informaton
205 local b, l
206 for l in utl.execi("brctl show") do
207 if not l:match("STP") then
208 local r = utl.split(l, "%s+", nil, true)
209 if #r == 4 then
210 b = {
211 name = r[1],
212 id = r[2],
213 stp = r[3] == "yes",
214 ifnames = { ifs[r[4]] }
215 }
216 if b.ifnames[1] then
217 b.ifnames[1].bridge = b
218 end
219 brs[r[1]] = b
220 elseif b then
221 b.ifnames[#b.ifnames+1] = ifs[r[2]]
222 b.ifnames[#b.ifnames].bridge = b
223 end
224 end
225 end
226
227 return _M
228 end
229
230 function save(self, ...)
231 uci_r:save(...)
232 uci_r:load(...)
233 end
234
235 function commit(self, ...)
236 uci_r:commit(...)
237 uci_r:load(...)
238 end
239
240 function has_ipv6(self)
241 return nfs.access("/proc/net/ipv6_route")
242 end
243
244 function add_network(self, n, options)
245 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
246 if uci_r:section("network", "interface", n, options) then
247 return network(n)
248 end
249 end
250 end
251
252 function get_network(self, n)
253 if n and uci_r:get("network", n) == "interface" then
254 return network(n)
255 end
256 end
257
258 function get_networks(self)
259 local nets = { }
260 local nls = { }
261
262 uci_r:foreach("network", "interface",
263 function(s)
264 nls[s['.name']] = network(s['.name'])
265 end)
266
267 local n
268 for n in utl.kspairs(nls) do
269 nets[#nets+1] = nls[n]
270 end
271
272 return nets
273 end
274
275 function del_network(self, n)
276 local r = uci_r:delete("network", n)
277 if r then
278 uci_r:foreach("network", "alias",
279 function(s)
280 if s.interface == n then
281 uci_r:delete("network", s['.name'])
282 end
283 end)
284
285 uci_r:foreach("network", "route",
286 function(s)
287 if s.interface == n then
288 uci_r:delete("network", s['.name'])
289 end
290 end)
291
292 uci_r:foreach("network", "route6",
293 function(s)
294 if s.interface == n then
295 uci_r:delete("network", s['.name'])
296 end
297 end)
298
299 uci_r:foreach("wireless", "wifi-iface",
300 function(s)
301 if s.network == n then
302 uci_r:delete("wireless", s['.name'], "network")
303 end
304 end)
305
306 uci_r:delete("network", n)
307 end
308 return r
309 end
310
311 function rename_network(self, old, new)
312 local r
313 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
314 r = uci_r:section("network", "interface", new, uci_r:get_all("network", old))
315
316 if r then
317 uci_r:foreach("network", "alias",
318 function(s)
319 if s.interface == old then
320 uci_r:set("network", s['.name'], "interface", new)
321 end
322 end)
323
324 uci_r:foreach("network", "route",
325 function(s)
326 if s.interface == old then
327 uci_r:set("network", s['.name'], "interface", new)
328 end
329 end)
330
331 uci_r:foreach("network", "route6",
332 function(s)
333 if s.interface == old then
334 uci_r:set("network", s['.name'], "interface", new)
335 end
336 end)
337
338 uci_r:foreach("wireless", "wifi-iface",
339 function(s)
340 if s.network == old then
341 uci_r:set("wireless", s['.name'], "network", new)
342 end
343 end)
344
345 uci_r:delete("network", old)
346 end
347 end
348 return r or false
349 end
350
351 function get_interface(self, i)
352 if ifs[i] or _wifi_iface(i) then
353 return interface(i)
354 else
355 local ifc
356 local num = { }
357 uci_r:foreach("wireless", "wifi-iface",
358 function(s)
359 if s.device then
360 num[s.device] = num[s.device] and num[s.device] + 1 or 1
361 if s['.name'] == i then
362 ifc = interface(
363 "%s.network%d" %{s.device, num[s.device] })
364 return false
365 end
366 end
367 end)
368 return ifc
369 end
370 end
371
372 function get_interfaces(self)
373 local iface
374 local ifaces = { }
375 local seen = { }
376 local nfs = { }
377
378 -- find normal interfaces
379 uci_r:foreach("network", "interface",
380 function(s)
381 for iface in utl.imatch(s.ifname) do
382 if not _iface_ignore(iface) and not _wifi_iface(iface) then
383 seen[iface] = true
384 nfs[iface] = interface(iface)
385 end
386 end
387 end)
388
389 for iface in utl.kspairs(ifs) do
390 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
391 nfs[iface] = interface(iface)
392 end
393 end
394
395 for iface in utl.kspairs(nfs) do
396 ifaces[#ifaces+1] = nfs[iface]
397 end
398
399 -- find wifi interfaces
400 local num = { }
401 local wfs = { }
402 uci_r:foreach("wireless", "wifi-iface",
403 function(s)
404 if s.device then
405 num[s.device] = num[s.device] and num[s.device] + 1 or 1
406 local i = "%s.network%d" %{ s.device, num[s.device] }
407 wfs[i] = interface(i)
408 end
409 end)
410
411 for iface in utl.kspairs(wfs) do
412 ifaces[#ifaces+1] = wfs[iface]
413 end
414
415 return ifaces
416 end
417
418 function ignore_interface(self, x)
419 return _iface_ignore(x)
420 end
421
422 function get_wifidev(self, dev)
423 if uci_r:get("wireless", dev) == "wifi-device" then
424 return wifidev(dev)
425 end
426 end
427
428 function get_wifidevs(self)
429 local devs = { }
430 local wfd = { }
431
432 uci_r:foreach("wireless", "wifi-device",
433 function(s) wfd[#wfd+1] = s['.name'] end)
434
435 local dev
436 for _, dev in utl.vspairs(wfd) do
437 devs[#devs+1] = wifidev(dev)
438 end
439
440 return devs
441 end
442
443 function get_wifinet(self, net)
444 local wnet = _wifi_lookup(net)
445 if wnet then
446 return wifinet(wnet)
447 end
448 end
449
450 function add_wifinet(self, net, options)
451 if type(options) == "table" and options.device and
452 uci_r:get("wireless", options.device) == "wifi-device"
453 then
454 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
455 return wifinet(wnet)
456 end
457 end
458
459 function del_wifinet(self, net)
460 local wnet = _wifi_lookup(net)
461 if wnet then
462 uci_r:delete("wireless", wnet)
463 return true
464 end
465 return false
466 end
467
468
469 network = utl.class()
470
471 function network.__init__(self, name)
472 self.sid = name
473 end
474
475 function network._get(self, opt)
476 local v = uci_r:get("network", self.sid, opt)
477 if type(v) == "table" then
478 return table.concat(v, " ")
479 end
480 return v or ""
481 end
482
483 function network.get(self, opt)
484 return _get("network", self.sid, opt)
485 end
486
487 function network.set(self, opt, val)
488 return _set("network", self.sid, opt, val)
489 end
490
491 function network.ifname(self)
492 local p = self:proto()
493 if self:is_bridge() then
494 return "br-" .. self.sid
495 elseif self:is_virtual() then
496 return p .. "-" .. self.sid
497 else
498 local dev = self:_get("ifname") or
499 uci_r:get("network", self.sid, "ifname")
500
501 dev = dev and dev:match("%S+")
502
503 if not dev then
504 uci_r:foreach("wireless", "wifi-iface",
505 function(s)
506 if s.device then
507 num[s.device] = num[s.device]
508 and num[s.device] + 1 or 1
509
510 if s.network == self.sid then
511 dev = "%s.network%d" %{ s.device, num[s.device] }
512 return false
513 end
514 end
515 end)
516 end
517
518 return dev
519 end
520 end
521
522 function network.device(self)
523 local dev = self:_get("device")
524 if not dev or dev:match("[^%w%-%.%s]") then
525 dev = uci_r:get("network", self.sid, "ifname")
526 end
527 return dev
528 end
529
530 function network.proto(self)
531 return self:_get("proto") or "none"
532 end
533
534 function network.type(self)
535 return self:_get("type")
536 end
537
538 function network.name(self)
539 return self.sid
540 end
541
542 function network.is_bridge(self)
543 return (self:type() == "bridge")
544 end
545
546 function network.is_virtual(self)
547 local p = self:proto()
548 return (
549 p == "3g" or p == "6in4" or p == "ppp" or
550 p == "pppoe" or p == "pppoa"
551 )
552 end
553
554 function network.is_empty(self)
555 if self:is_virtual() then
556 return false
557 else
558 local rv = true
559
560 if (self:_get("ifname") or ""):match("%S+") then
561 rv = false
562 end
563
564 uci_r:foreach("wireless", "wifi-iface",
565 function(s)
566 if s.network == self.sid then
567 rv = false
568 return false
569 end
570 end)
571
572 return rv
573 end
574 end
575
576 function network.add_interface(self, ifname)
577 if not self:is_virtual() then
578 if type(ifname) ~= "string" then
579 ifname = ifname:name()
580 else
581 ifname = ifname:match("[^%s:]+")
582 end
583
584 -- remove the interface from all ifaces
585 uci_r:foreach("network", "interface",
586 function(s)
587 _list_del("network", s['.name'], "ifname", ifname)
588 end)
589
590 -- if its a wifi interface, change its network option
591 local wif = _wifi_lookup(ifname)
592 if wif then
593 uci_r:set("wireless", wif, "network", self.sid)
594
595 -- add iface to our iface list
596 else
597 _list_add("network", self.sid, "ifname", ifname)
598 end
599 end
600 end
601
602 function network.del_interface(self, ifname)
603 if not self:is_virtual() then
604 if utl.instanceof(ifname, interface) then
605 ifname = ifname:name()
606 else
607 ifname = ifname:match("[^%s:]+")
608 end
609
610 -- if its a wireless interface, clear its network option
611 local wif = _wifi_lookup(ifname)
612 if wif then uci_r:delete("wireless", wif, "network") end
613
614 -- remove the interface
615 _list_del("network", self.sid, "ifname", ifname)
616 end
617 end
618
619 function network.get_interfaces(self)
620 local ifaces = { }
621
622 local ifn
623 if self:is_virtual() then
624 ifn = self:proto() .. "-" .. self.sid
625 ifaces = { interface(ifn) }
626 else
627 local nfs = { }
628 for ifn in utl.imatch(self:get("ifname")) do
629 ifn = ifn:match("[^:]+")
630 nfs[ifn] = interface(ifn)
631 end
632
633 for ifn in utl.kspairs(nfs) do
634 ifaces[#ifaces+1] = nfs[ifn]
635 end
636
637 local num = { }
638 local wfs = { }
639 uci_r:foreach("wireless", "wifi-iface",
640 function(s)
641 if s.device then
642 num[s.device] = num[s.device] and num[s.device] + 1 or 1
643 if s.network == self.sid then
644 ifn = "%s.network%d" %{ s.device, num[s.device] }
645 wfs[ifn] = interface(ifn)
646 end
647 end
648 end)
649
650 for ifn in utl.kspairs(wfs) do
651 ifaces[#ifaces+1] = wfs[ifn]
652 end
653 end
654
655 return ifaces
656 end
657
658 function network.contains_interface(self, ifname)
659 if type(ifname) ~= "string" then
660 ifname = ifname:name()
661 else
662 ifname = ifname:match("[^%s:]+")
663 end
664
665 local ifn
666 if self:is_virtual() then
667 ifn = self:proto() .. "-" .. self.sid
668 return ifname == ifn
669 else
670 for ifn in utl.imatch(self:get("ifname")) do
671 ifn = ifn:match("[^:]+")
672 if ifn == ifname then
673 return true
674 end
675 end
676
677 local wif = _wifi_lookup(ifname)
678 if wif then
679 return (uci_r:get("wireless", wif, "network") == self.sid)
680 end
681 end
682
683 return false
684 end
685
686 function network.adminlink(self)
687 return dsp.build_url("admin", "network", "network", self.sid)
688 end
689
690
691 interface = utl.class()
692 function interface.__init__(self, ifname)
693 local wif = _wifi_lookup(ifname)
694 if wif then self.wif = wifinet(wif) end
695
696 self.ifname = self.ifname or ifname
697 self.dev = ifs[self.ifname]
698 end
699
700 function interface.name(self)
701 return self.wif and self.wif:ifname() or self.ifname
702 end
703
704 function interface.mac(self)
705 return self.dev and self.dev.macaddr or "00:00:00:00:00:00"
706 end
707
708 function interface.ipaddrs(self)
709 return self.dev and self.dev.ipaddrs or { }
710 end
711
712 function interface.ip6addrs(self)
713 return self.dev and self.dev.ip6addrs or { }
714 end
715
716 function interface.type(self)
717 if self.wif or _wifi_iface(self.ifname) then
718 return "wifi"
719 elseif brs[self.ifname] then
720 return "bridge"
721 elseif sws[self.ifname] or self.ifname:match("%.") then
722 return "switch"
723 else
724 return "ethernet"
725 end
726 end
727
728 function interface.shortname(self)
729 if self.wif then
730 return "%s %q" %{
731 self.wif:active_mode(),
732 self.wif:active_ssid() or self.wif:active_bssid()
733 }
734 else
735 return self.ifname
736 end
737 end
738
739 function interface.get_i18n(self)
740 if self.wif then
741 return "%s: %s %q" %{
742 i18n.translate("Wireless Network"),
743 self.wif:active_mode(),
744 self.wif:active_ssid() or self.wif:active_bssid()
745 }
746 else
747 return "%s: %q" %{ self:get_type_i18n(), self:name() }
748 end
749 end
750
751 function interface.get_type_i18n(self)
752 local x = self:type()
753 if x == "wifi" then
754 return i18n.translate("Wireless Adapter")
755 elseif x == "bridge" then
756 return i18n.translate("Bridge")
757 elseif x == "switch" then
758 return i18n.translate("Ethernet Switch")
759 else
760 return i18n.translate("Ethernet Adapter")
761 end
762 end
763
764 function interface.adminlink(self)
765 if self.wif then
766 return self.wif:adminlink()
767 end
768 end
769
770 function interface.ports(self)
771 if self.br then
772 local iface
773 local ifaces = { }
774 for _, iface in ipairs(self.br.ifnames) do
775 ifaces[#ifaces+1] = interface(iface.name)
776 end
777 return ifaces
778 end
779 end
780
781 function interface.bridge_id(self)
782 if self.br then
783 return self.br.id
784 else
785 return nil
786 end
787 end
788
789 function interface.bridge_stp(self)
790 if self.br then
791 return self.br.stp
792 else
793 return false
794 end
795 end
796
797 function interface.is_up(self)
798 if self.wif then
799 return self.wif:is_up()
800 else
801 return self.dev and self.dev.flags and self.dev.flags.up or false
802 end
803 end
804
805 function interface.is_bridge(self)
806 return (self:type() == "bridge")
807 end
808
809 function interface.is_bridgeport(self)
810 return self.dev and self.dev.bridge and true or false
811 end
812
813 function interface.tx_bytes(self)
814 return self.dev and self.dev.stats
815 and self.dev.stats.tx_bytes or 0
816 end
817
818 function interface.rx_bytes(self)
819 return self.dev and self.dev.stats
820 and self.dev.stats.rx_bytes or 0
821 end
822
823 function interface.tx_packets(self)
824 return self.dev and self.dev.stats
825 and self.dev.stats.tx_packets or 0
826 end
827
828 function interface.rx_packets(self)
829 return self.dev and self.dev.stats
830 and self.dev.stats.rx_packets or 0
831 end
832
833 function interface.get_network(self)
834 if self.dev and self.dev.network then
835 self.network = _M:get_network(self.dev.network)
836 end
837
838 if not self.network then
839 local net
840 for _, net in ipairs(_M:get_networks()) do
841 if net:contains_interface(self.ifname) then
842 self.network = net
843 return net
844 end
845 end
846 else
847 return self.network
848 end
849 end
850
851 function interface.get_wifinet(self)
852 return self.wif
853 end
854
855
856 wifidev = utl.class()
857 function wifidev.__init__(self, dev)
858 self.sid = dev
859 end
860
861 function wifidev.get(self, opt)
862 return _get("wireless", self.sid, opt)
863 end
864
865 function wifidev.set(self, opt, val)
866 return _set("wireless", self.sid, opt, val)
867 end
868
869 function wifidev.name(self)
870 return self.sid
871 end
872
873 function wifidev.is_up(self)
874 local up = false
875
876 uci_s:foreach("wireless", "wifi-iface",
877 function(s)
878 if s.device == self.sid then
879 if s.up == "1" then
880 up = true
881 return false
882 end
883 end
884 end)
885
886 return up
887 end
888
889 function wifidev.get_wifinet(self, net)
890 if uci_r:get("wireless", net) == "wifi-iface" then
891 return wifinet(net)
892 else
893 local wnet = _wifi_lookup(net)
894 if wnet then
895 return wifinet(wnet)
896 end
897 end
898 end
899
900 function wifidev.get_wifinets(self)
901 local nets = { }
902
903 uci_r:foreach("wireless", "wifi-iface",
904 function(s)
905 if s.device == self.sid then
906 nets[#nets+1] = wifinet(s['.name'])
907 end
908 end)
909
910 return nets
911 end
912
913 function wifidev.add_wifinet(self, options)
914 options = options or { }
915 options.device = self.sid
916
917 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
918 if wnet then
919 return wifinet(wnet, options)
920 end
921 end
922
923 function wifidev.del_wifinet(self, net)
924 if utl.instanceof(net, wifinet) then
925 net = net.sid
926 elseif uci_r:get("wireless", net) ~= "wifi-iface" then
927 net = _wifi_lookup(net)
928 end
929
930 if net and uci_r:get("wireless", net, "device") == self.sid then
931 uci_r:delete("wireless", net)
932 return true
933 end
934
935 return false
936 end
937
938
939 wifinet = utl.class()
940 function wifinet.__init__(self, net, data)
941 self.sid = net
942
943 local dev = uci_s:get("wireless", self.sid, "ifname")
944 if not dev then
945 local num = { }
946 uci_r:foreach("wireless", "wifi-iface",
947 function(s)
948 if s.device then
949 num[s.device] = num[s.device] and num[s.device] + 1 or 1
950 if s['.name'] == self.sid then
951 dev = "%s.network%d" %{ s.device, num[s.device] }
952 return false
953 end
954 end
955 end)
956 end
957
958 self.wdev = dev
959 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
960 self.iwdata = data or uci_s:get_all("wireless", self.sid) or
961 uci_r:get_all("wireless", self.sid) or { }
962 end
963
964 function wifinet.get(self, opt)
965 return _get("wireless", self.sid, opt)
966 end
967
968 function wifinet.set(self, opt, val)
969 return _set("wireless", self.sid, opt, val)
970 end
971
972 function wifinet.mode(self)
973 return uci_s:get("wireless", self.sid, "mode") or "ap"
974 end
975
976 function wifinet.ssid(self)
977 return uci_s:get("wireless", self.sid, "ssid")
978 end
979
980 function wifinet.bssid(self)
981 return uci_s:get("wireless", self.sid, "bssid")
982 end
983
984 function wifinet.network(self)
985 return uci_s:get("wifinet", self.sid, "network")
986 end
987
988 function wifinet.name(self)
989 return self.sid
990 end
991
992 function wifinet.ifname(self)
993 return self.iwinfo.ifname or self.wdev
994 end
995
996 function wifinet.get_device(self)
997 if self.iwdata.device then
998 return wifidev(self.iwdata.device)
999 end
1000 end
1001
1002 function wifinet.is_up(self)
1003 return (self.iwdata.up == "1")
1004 end
1005
1006 function wifinet.active_mode(self)
1007 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1008
1009 if m == "ap" then m = "AP"
1010 elseif m == "sta" then m = "Client"
1011 elseif m == "adhoc" then m = "Ad-Hoc"
1012 elseif m == "mesh" then m = "Mesh"
1013 elseif m == "monitor" then m = "Monitor"
1014 end
1015
1016 return m
1017 end
1018
1019 function wifinet.active_mode_i18n(self)
1020 return i18n.translate(self:active_mode())
1021 end
1022
1023 function wifinet.active_ssid(self)
1024 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1025 end
1026
1027 function wifinet.active_bssid(self)
1028 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1029 end
1030
1031 function wifinet.active_encryption(self)
1032 local enc = self.iwinfo and self.iwinfo.encryption
1033 return enc and enc.description or "-"
1034 end
1035
1036 function wifinet.assoclist(self)
1037 return self.iwinfo.assoclist or { }
1038 end
1039
1040 function wifinet.frequency(self)
1041 local freq = self.iwinfo.frequency
1042 if freq and freq > 0 then
1043 return "%.03f" % (freq / 1000)
1044 end
1045 end
1046
1047 function wifinet.bitrate(self)
1048 local rate = self.iwinfo.bitrate
1049 if rate and rate > 0 then
1050 return (rate / 1000)
1051 end
1052 end
1053
1054 function wifinet.channel(self)
1055 return self.iwinfo.channel or
1056 tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1057 end
1058
1059 function wifinet.signal(self)
1060 return self.iwinfo.signal or 0
1061 end
1062
1063 function wifinet.noise(self)
1064 return self.iwinfo.noise or 0
1065 end
1066
1067 function wifinet.signal_level(self, s, n)
1068 if self:active_bssid() ~= "00:00:00:00:00:00" then
1069 local signal = s or self:signal()
1070 local noise = n or self:noise()
1071
1072 if signal < 0 and noise < 0 then
1073 local snr = -1 * (noise - signal)
1074 return math.floor(snr / 5)
1075 else
1076 return 0
1077 end
1078 else
1079 return -1
1080 end
1081 end
1082
1083 function wifinet.signal_percent(self)
1084 local qc = self.iwinfo.quality or 0
1085 local qm = self.iwinfo.quality_max or 0
1086
1087 if qc > 0 and qm > 0 then
1088 return math.floor((100 / qm) * qc)
1089 else
1090 return 0
1091 end
1092 end
1093
1094 function wifinet.shortname(self)
1095 return "%s %q" %{
1096 i18n.translate(self:active_mode()),
1097 self:active_ssid() or self:active_bssid()
1098 }
1099 end
1100
1101 function wifinet.get_i18n(self)
1102 return "%s: %s %q (%s)" %{
1103 i18n.translate("Wireless Network"),
1104 i18n.translate(self:active_mode()),
1105 self:active_ssid() or self:active_bssid(),
1106 self:ifname()
1107 }
1108 end
1109
1110 function wifinet.adminlink(self)
1111 return dsp.build_url("admin", "network", "wireless",
1112 self.iwdata.device, self.wdev)
1113 end
1114
1115 function wifinet.get_network(self)
1116 if uci_r:get("network", self.iwdata.network) == "interface" then
1117 return network(self.iwdata.network)
1118 end
1119 end
1120
1121 function wifinet.get_interface(self)
1122 return interface(self:ifname())
1123 end