858753f7fcf4df1028ce01426ba565ef07b83274
[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:del(c, s, o, v)
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 luci.model.uci.cursor()
165 uci_s = cursor: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
376 -- find normal interfaces
377 for iface in utl.kspairs(ifs) do
378 if not _iface_ignore(iface) and not _wifi_iface(iface) then
379 ifaces[#ifaces+1] = interface(iface)
380 end
381 end
382
383 -- find wifi interfaces
384 local num = { }
385 local wfs = { }
386 uci_r:foreach("wireless", "wifi-iface",
387 function(s)
388 if s.device then
389 num[s.device] = num[s.device] and num[s.device] + 1 or 1
390 local i = "%s.network%d" %{ s.device, num[s.device] }
391 wfs[i] = interface(i)
392 end
393 end)
394
395 for iface in utl.kspairs(wfs) do
396 ifaces[#ifaces+1] = wfs[iface]
397 end
398
399 return ifaces
400 end
401
402 function ignore_interface(self, x)
403 return _iface_ignore(x)
404 end
405
406 function get_wifidev(self, dev)
407 if uci_r:get("wireless", dev) == "wifi-device" then
408 return wifidev(dev)
409 end
410 end
411
412 function get_wifidevs(self)
413 local devs = { }
414 local wfd = { }
415
416 uci_r:foreach("wireless", "wifi-device",
417 function(s) wfd[#wfd+1] = s['.name'] end)
418
419 local dev
420 for _, dev in utl.vspairs(wfd) do
421 devs[#devs+1] = wifidev(dev)
422 end
423
424 return devs
425 end
426
427 function get_wifinet(self, net)
428 local wnet = _wifi_lookup(net)
429 if wnet then
430 return wifinet(wnet)
431 end
432 end
433
434 function add_wifinet(self, net, options)
435 if type(options) == "table" and options.device and
436 uci_r:get("wireless", options.device) == "wifi-device"
437 then
438 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
439 return wifinet(wnet)
440 end
441 end
442
443 function del_wifinet(self, net)
444 local wnet = _wifi_lookup(net)
445 if wnet then
446 uci_r:delete("wireless", wnet)
447 return true
448 end
449 return false
450 end
451
452
453 network = utl.class()
454
455 function network.__init__(self, name)
456 self.sid = name
457 end
458
459 function network._get(self, opt)
460 local v = uci_r:get("network", self.sid, opt)
461 if type(v) == "table" then
462 return table.concat(v, " ")
463 end
464 return v or ""
465 end
466
467 function network.get(self, opt)
468 return _get("network", self.sid, opt)
469 end
470
471 function network.set(self, opt, val)
472 return _set("network", self.sid, opt, val)
473 end
474
475 function network.ifname(self)
476 local p = self:proto()
477 if self:is_bridge() then
478 return "br-" .. self.sid
479 elseif self:is_virtual() then
480 return p .. "-" .. self.sid
481 else
482 local dev = self:_get("ifname") or
483 uci_r:get("network", self.sid, "ifname")
484
485 dev = dev and dev:match("%S+")
486
487 if not dev then
488 uci_r:foreach("wireless", "wifi-iface",
489 function(s)
490 if s.device then
491 num[s.device] = num[s.device]
492 and num[s.device] + 1 or 1
493
494 if s.network == self.sid then
495 dev = "%s.network%d" %{ s.device, num[s.device] }
496 return false
497 end
498 end
499 end)
500 end
501
502 return dev
503 end
504 end
505
506 function network.device(self)
507 local dev = self:_get("device")
508 if not dev or dev:match("[^%w%-%.%s]") then
509 dev = uci_r:get("network", self.sid, "ifname")
510 end
511 return dev
512 end
513
514 function network.proto(self)
515 return self:_get("proto") or "none"
516 end
517
518 function network.type(self)
519 return self:_get("type")
520 end
521
522 function network.name(self)
523 return self.sid
524 end
525
526 function network.is_bridge(self)
527 return (self:type() == "bridge")
528 end
529
530 function network.is_virtual(self)
531 local p = self:proto()
532 return (
533 p == "3g" or p == "6in4" or p == "ppp" or
534 p == "pppoe" or p == "pppoa"
535 )
536 end
537
538 function network.is_empty(self)
539 if self:is_virtual() then
540 return false
541 else
542 local rv = true
543
544 if (self:_get("ifname") or ""):match("%S+") then
545 rv = false
546 end
547
548 uci_r:foreach("wireless", "wifi-iface",
549 function(s)
550 if s.network == self.sid then
551 rv = false
552 return false
553 end
554 end)
555
556 return rv
557 end
558 end
559
560 function network.add_interface(self, ifname)
561 if not self:is_virtual() then
562 if type(ifname) ~= "string" then
563 ifname = ifname:name()
564 else
565 ifname = ifname:match("[^%s:]+")
566 end
567
568 -- remove the interface from all ifaces
569 uci_r:foreach("network", "interface",
570 function(s)
571 _list_del("network", s['.name'], "ifname", ifname)
572 end)
573
574 -- if its a wifi interface, change its network option
575 local wif = _wifi_lookup(ifname)
576 if wif then
577 uci_r:set("wireless", wif, "network", self.sid)
578
579 -- add iface to our iface list
580 else
581 _list_add("network", self.sid, "ifname", ifname)
582 end
583 end
584 end
585
586 function network.del_interface(self, ifname)
587 if not self:is_virtual() then
588 if utl.instanceof(ifname, interface) then
589 ifname = ifname:name()
590 else
591 ifname = ifname:match("[^%s:]+")
592 end
593
594 -- if its a wireless interface, clear its network option
595 local wif = _wifi_lookup(ifname)
596 if wif then uci_r:delete("wireless", wif, "network") end
597
598 -- remove the interface
599 _list_del("network", self.sid, "ifname", ifname)
600 end
601 end
602
603 function network.get_interfaces(self)
604 local ifaces = { }
605
606 local ifn
607 if self:is_virtual() then
608 ifn = self:proto() .. "-" .. self.sid
609 ifaces = { interface(ifn) }
610 else
611 local nfs = { }
612 for ifn in self:_get("ifname"):gmatch("%S+") do
613 ifn = ifn:match("[^:]+")
614 nfs[ifn] = interface(ifn)
615 end
616
617 for ifn in utl.kspairs(nfs) do
618 ifaces[#ifaces+1] = nfs[ifn]
619 end
620
621 local num = { }
622 local wfs = { }
623 uci_r:foreach("wireless", "wifi-iface",
624 function(s)
625 if s.device then
626 num[s.device] = num[s.device] and num[s.device] + 1 or 1
627 if s.network == self.sid then
628 ifn = "%s.network%d" %{ s.device, num[s.device] }
629 wfs[ifn] = interface(ifn)
630 end
631 end
632 end)
633
634 for ifn in utl.kspairs(wfs) do
635 ifaces[#ifaces+1] = wfs[ifn]
636 end
637 end
638
639 return ifaces
640 end
641
642 function network.contains_interface(self, ifname)
643 if type(ifname) ~= "string" then
644 ifname = ifname:name()
645 else
646 ifname = ifname:match("[^%s:]+")
647 end
648
649 local ifn
650 if self:is_virtual() then
651 ifn = self:proto() .. "-" .. self.sid
652 return ifname == ifn
653 else
654 for ifn in self:_get("ifname"):gmatch("%S+") do
655 ifn = ifn:match("[^:]+")
656 if ifn == ifname then
657 return true
658 end
659 end
660
661 local wif = _wifi_lookup(ifname)
662 if wif then
663 return (uci_r:get("wireless", wif, "network") == self.sid)
664 end
665 end
666
667 return false
668 end
669
670 function network.adminlink(self)
671 return dsp.build_url("admin", "network", "network", self.sid)
672 end
673
674
675 interface = utl.class()
676 function interface.__init__(self, ifname)
677 local wif = _wifi_lookup(ifname)
678 if wif then self.wif = wifinet(wif) end
679
680 self.ifname = self.ifname or ifname
681 self.dev = ifs[self.ifname]
682 end
683
684 function interface.name(self)
685 return self.wif and self.wif:ifname() or self.ifname
686 end
687
688 function interface.mac(self)
689 return self.dev and self.dev or "00:00:00:00:00:00"
690 end
691
692 function interface.ipaddrs(self)
693 return self.dev and self.dev.ipaddrs or { }
694 end
695
696 function interface.ip6addrs(self)
697 return self.dev and self.dev.ip6addrs or { }
698 end
699
700 function interface.type(self)
701 if self.wif or _wifi_iface(self.ifname) then
702 return "wifi"
703 elseif brs[self.ifname] then
704 return "bridge"
705 elseif sws[self.ifname] or self.ifname:match("%.") then
706 return "switch"
707 else
708 return "ethernet"
709 end
710 end
711
712 function interface.shortname(self)
713 if self.wif then
714 return "%s %q" %{
715 self.wif:active_mode(),
716 self.wif:active_ssid() or self.wif:active_bssid()
717 }
718 else
719 return self.ifname
720 end
721 end
722
723 function interface.get_i18n(self)
724 if self.wif then
725 return "%s: %s %q" %{
726 i18n.translate("Wireless Network"),
727 self.wif:active_mode(),
728 self.wif:active_ssid() or self.wif:active_bssid()
729 }
730 else
731 return "%s: %q" %{ self:get_type_i18n(), self:name() }
732 end
733 end
734
735 function interface.get_type_i18n(self)
736 local x = self:type()
737 if x == "wifi" then
738 return i18n.translate("Wireless Adapter")
739 elseif x == "bridge" then
740 return i18n.translate("Bridge")
741 elseif x == "switch" then
742 return i18n.translate("Ethernet Switch")
743 else
744 return i18n.translate("Ethernet Adapter")
745 end
746 end
747
748 function interface.adminlink(self)
749 if self.wif then
750 return self.wif:adminlink()
751 end
752 end
753
754 function interface.ports(self)
755 if self.br then
756 local iface
757 local ifaces = { }
758 for _, iface in ipairs(self.br.ifnames) do
759 ifaces[#ifaces+1] = interface(iface.name)
760 end
761 return ifaces
762 end
763 end
764
765 function interface.bridge_id(self)
766 if self.br then
767 return self.br.id
768 else
769 return nil
770 end
771 end
772
773 function interface.bridge_stp(self)
774 if self.br then
775 return self.br.stp
776 else
777 return false
778 end
779 end
780
781 function interface.is_up(self)
782 if self.wif then
783 return self.wif:is_up()
784 else
785 return self.dev and self.dev.flags and self.dev.flags.up or false
786 end
787 end
788
789 function interface.is_bridge(self)
790 return (self:type() == "bridge")
791 end
792
793 function interface.is_bridgeport(self)
794 return self.dev and self.dev.bridge and true or false
795 end
796
797 function interface.tx_bytes(self)
798 return self.dev and self.dev.stats
799 and self.dev.stats.tx_bytes or 0
800 end
801
802 function interface.rx_bytes(self)
803 return self.dev and self.dev.stats
804 and self.dev.stats.rx_bytes or 0
805 end
806
807 function interface.tx_packets(self)
808 return self.dev and self.dev.stats
809 and self.dev.stats.tx_packets or 0
810 end
811
812 function interface.rx_packets(self)
813 return self.dev and self.dev.stats
814 and self.dev.stats.rx_packets or 0
815 end
816
817 function interface.get_network(self)
818 if self.dev and self.dev.network then
819 self.network = _M:get_network(self.dev.network)
820 end
821
822 if not self.network then
823 local net
824 for _, net in ipairs(_M:get_networks()) do
825 if net:contains_interface(self.ifname) then
826 self.network = net
827 return net
828 end
829 end
830 else
831 return self.network
832 end
833 end
834
835 function interface.get_wifinet(self)
836 return self.wif
837 end
838
839
840 wifidev = utl.class()
841 function wifidev.__init__(self, dev)
842 self.sid = dev
843 end
844
845 function wifidev.get(self, opt)
846 return _get("wireless", self.sid, opt)
847 end
848
849 function wifidev.set(self, opt, val)
850 return _set("wireless", self.sid, opt, val)
851 end
852
853 function wifidev.name(self)
854 return self.sid
855 end
856
857 function wifidev.is_up(self)
858 local up = false
859
860 uci_s:foreach("wireless", "wifi-iface",
861 function(s)
862 if s.device == self.sid then
863 if s.up == "1" then
864 up = true
865 return false
866 end
867 end
868 end)
869
870 return up
871 end
872
873 function wifidev.get_wifinet(self, net)
874 if uci_r:get("wireless", net) == "wifi-iface" then
875 return wifinet(net)
876 else
877 local wnet = _wifi_lookup(net)
878 if wnet then
879 return wifinet(wnet)
880 end
881 end
882 end
883
884 function wifidev.get_wifinets(self)
885 local nets = { }
886
887 uci_r:foreach("wireless", "wifi-iface",
888 function(s)
889 if s.device == self.sid then
890 nets[#nets+1] = wifinet(s['.name'])
891 end
892 end)
893
894 return nets
895 end
896
897 function wifidev.add_wifinet(self, options)
898 options = options or { }
899 options.device = self.sid
900
901 local wnet = uci_r:section("wifidev", "wifi-iface", nil, options)
902 if wnet then
903 return wifinet(wnet)
904 end
905 end
906
907 function wifidev.del_wifinet(self, net)
908 if utl.instanceof(net, wifinet) then
909 net = net.sid
910 elseif uci_r:get("wireless", net) ~= "wifi-iface" then
911 net = _wifi_lookup(net)
912 end
913
914 if net and uci_r:get("wireless", net, "device") == self.sid then
915 uci_r:delete("wireless", net)
916 return true
917 end
918
919 return false
920 end
921
922
923 wifinet = utl.class()
924 function wifinet.__init__(self, net)
925 self.sid = net
926
927 local dev = uci_s:get("wireless", self.sid, "ifname")
928 if not dev then
929 local num = { }
930 uci_r:foreach("wireless", "wifi-iface",
931 function(s)
932 if s.device then
933 num[s.device] = num[s.device] and num[s.device] + 1 or 1
934 if s['.name'] == self.sid then
935 dev = "%s.network%d" %{ s.device, num[s.device] }
936 return false
937 end
938 end
939 end)
940 end
941
942 self.wdev = dev
943 self.iwdata = uci_s:get_all("wireless", self.sid) or { }
944 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
945 end
946
947 function wifinet.get(self, opt)
948 return _get("wireless", self.sid, opt)
949 end
950
951 function wifinet.set(self, opt, val)
952 return _set("wireless", self.sid, opt, val)
953 end
954
955 function wifinet.mode(self)
956 return uci_s:get("wireless", self.sid, "mode") or "ap"
957 end
958
959 function wifinet.ssid(self)
960 return uci_s:get("wireless", self.sid, "ssid")
961 end
962
963 function wifinet.bssid(self)
964 return uci_s:get("wireless", self.sid, "bssid")
965 end
966
967 function wifinet.network(self)
968 return uci_s:get("wifinet", self.sid, "network")
969 end
970
971 function wifinet.name(self)
972 return self.sid
973 end
974
975 function wifinet.ifname(self)
976 return self.iwinfo.ifname or self.wdev
977 end
978
979 function wifinet.get_device(self)
980 if self.iwdata.device then
981 return wifidev(self.iwdata.device)
982 end
983 end
984
985 function wifinet.is_up(self)
986 return (self.iwdata.up == "1")
987 end
988
989 function wifinet.active_mode(self)
990 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
991
992 if m == "ap" then m = "AP"
993 elseif m == "sta" then m = "Client"
994 elseif m == "adhoc" then m = "Ad-Hoc"
995 elseif m == "mesh" then m = "Mesh"
996 elseif m == "monitor" then m = "Monitor"
997 end
998
999 return m
1000 end
1001
1002 function wifinet.active_mode_i18n(self)
1003 return i18n.translate(self:active_mode())
1004 end
1005
1006 function wifinet.active_ssid(self)
1007 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1008 end
1009
1010 function wifinet.active_bssid(self)
1011 return _stror(self.iwinfo.bssid, self.iwinfo.bssid) or "00:00:00:00:00:00"
1012 end
1013
1014 function wifinet.active_encryption(self)
1015 local enc = self.iwinfo and self.iwinfo.encryption
1016 return enc and enc.description or "-"
1017 end
1018
1019 function wifinet.assoclist(self)
1020 return self.iwinfo.assoclist or { }
1021 end
1022
1023 function wifinet.frequency(self)
1024 local freq = self.iwinfo.frequency
1025 if freq and freq > 0 then
1026 return "%.03f" % (freq / 1000)
1027 end
1028 end
1029
1030 function wifinet.bitrate(self)
1031 local rate = self.iwinfo.bitrate
1032 if rate and rate > 0 then
1033 return (rate / 1000)
1034 end
1035 end
1036
1037 function wifinet.channel(self)
1038 return self.iwinfo.channel or
1039 tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1040 end
1041
1042 function wifinet.signal(self)
1043 return self.iwinfo.signal or 0
1044 end
1045
1046 function wifinet.noise(self)
1047 return self.iwinfo.noise or 0
1048 end
1049
1050 function wifinet.signal_level(self, s, n)
1051 if self:active_bssid() ~= "00:00:00:00:00:00" then
1052 local signal = s or self:signal()
1053 local noise = n or self:noise()
1054
1055 if signal < 0 and noise < 0 then
1056 local snr = -1 * (noise - signal)
1057 return math.floor(snr / 5)
1058 else
1059 return 0
1060 end
1061 else
1062 return -1
1063 end
1064 end
1065
1066 function wifinet.signal_percent(self)
1067 local qc = self.iwinfo.quality or 0
1068 local qm = self.iwinfo.quality_max or 0
1069
1070 if qc > 0 and qm > 0 then
1071 return math.floor((100 / qm) * qc)
1072 else
1073 return 0
1074 end
1075 end
1076
1077 function wifinet.shortname(self)
1078 return "%s %q" %{
1079 i18n.translate(self:active_mode()),
1080 self:active_ssid() or self:active_bssid()
1081 }
1082 end
1083
1084 function wifinet.get_i18n(self)
1085 return "%s: %s %q (%s)" %{
1086 i18n.translate("Wireless Network"),
1087 i18n.translate(self:active_mode()),
1088 self:active_ssid() or self:active_bssid(),
1089 self:ifname()
1090 }
1091 end
1092
1093 function wifinet.adminlink(self)
1094 return dsp.build_url("admin", "network", "wireless",
1095 self.iwdata.device, self.wdev)
1096 end
1097
1098 function wifinet.get_network(self)
1099 if uci_r:get("network", self.iwdata.network) == "interface" then
1100 return network(self.iwdata.network)
1101 end
1102 end
1103
1104 function wifinet.get_interface(self)
1105 return interface(self:ifname())
1106 end