4 Copyright 2009-2010 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, next, pairs, ipairs, loadfile, table, tonumber, math, i18n
21 = type, next, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n
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"
30 module "luci.model.network"
33 local ifs, brs, sws, tns, uci_r, uci_s
35 function _list_del(c, s, o, r)
36 local val = uci_r:get(c, s, o)
39 if type(val) == "string" then
40 for val in val:gmatch("%S+") do
46 uci_r:set(c, s, o, table.concat(l, " "))
50 elseif type(val) == "table" then
51 for _, val in ipairs(val) do
65 function _list_add(c, s, o, a)
66 local val = uci_r:get(c, s, o) or ""
67 if type(val) == "string" then
69 for val in val:gmatch("%S+") do
75 uci_r:set(c, s, o, table.concat(l, " "))
76 elseif type(val) == "table" then
78 for _, val in ipairs(val) do
88 function _stror(s1, s2)
89 if not s1 or #s1 == 0 then
90 return s2 and #s2 > 0 and s2
96 function _get(c, s, o)
97 return uci_r:get(c, s, o)
100 function _set(c, s, o, v)
102 if type(v) == "boolean" then v = v and "1" or "0" end
103 return uci_r:set(c, s, o, v)
105 return uci_r:delete(c, s, o)
109 function _wifi_iface(x)
111 x:match("^wlan%d") or x:match("^wl%d") or x:match("^ath%d") or
112 x:match("^%w+%.network%d")
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
123 ifnidx = tonumber(ifnidx)
124 uci_r:foreach("wireless", "wifi-iface",
126 if s.device == radio then
128 if num == ifnidx then
137 -- looks like wifi, try to locate the section via state vars
138 elseif _wifi_iface(ifn) then
141 uci_s:foreach("wireless", "wifi-iface",
143 if s.ifname == ifn then
153 function _iface_virtual(x)
155 x:match("^6in4-%w") or x:match("^6to4-%w") or x:match("^3g-%w") or
156 x:match("^ppp-%w") or x:match("^pppoe-%w") or x:match("^pppoa-%w") or
161 function _iface_ignore(x)
163 x:match("^wmaster%d") or x:match("^wifi%d") or x:match("^hwsim%d") or
164 x:match("^imq%d") or x:match("^mon.wlan%d") or
165 x == "sit0" or x == "lo" or _iface_virtual(x)
170 function init(cursor)
171 uci_r = cursor or uci_r or uci.cursor()
172 uci_s = uci_r:substate()
179 -- read interface information
181 for n, i in ipairs(nxo.getifaddrs()) do
182 local name = i.name:match("[^:]+")
183 local prnt = name:match("^([^%.]+)%.")
185 if _iface_virtual(name) then
189 if tns[name] or not _iface_ignore(name) then
190 ifs[name] = ifs[name] or {
191 idx = i.ifindex or n,
204 if i.family == "packet" then
205 ifs[name].flags = i.flags
206 ifs[name].stats = i.data
207 ifs[name].macaddr = i.addr
208 elseif i.family == "inet" then
209 ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
210 elseif i.family == "inet6" then
211 ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
216 -- read bridge informaton
218 for l in utl.execi("brctl show") do
219 if not l:match("STP") then
220 local r = utl.split(l, "%s+", nil, true)
226 ifnames = { ifs[r[4]] }
229 b.ifnames[1].bridge = b
233 b.ifnames[#b.ifnames+1] = ifs[r[2]]
234 b.ifnames[#b.ifnames].bridge = b
242 function save(self, ...)
247 function commit(self, ...)
252 function has_ipv6(self)
253 return nfs.access("/proc/net/ipv6_route")
256 function add_network(self, n, options)
257 local oldnet = self:get_network(n)
258 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
259 if uci_r:section("network", "interface", n, options) then
262 elseif oldnet and oldnet:is_empty() then
265 for k, v in pairs(options) do
273 function get_network(self, n)
274 if n and uci_r:get("network", n) == "interface" then
279 function get_networks(self)
283 uci_r:foreach("network", "interface",
285 nls[s['.name']] = network(s['.name'])
289 for n in utl.kspairs(nls) do
290 nets[#nets+1] = nls[n]
296 function del_network(self, n)
297 local r = uci_r:delete("network", n)
299 uci_r:delete_all("network", "alias",
300 function(s) return (s.interface == n) end)
302 uci_r:delete_all("network", "route",
303 function(s) return (s.interface == n) end)
305 uci_r:delete_all("network", "route6",
306 function(s) return (s.interface == n) end)
308 uci_r:foreach("wireless", "wifi-iface",
310 if s.network == n then
311 uci_r:delete("wireless", s['.name'], "network")
318 function rename_network(self, old, new)
320 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
321 r = uci_r:section("network", "interface", new, uci_r:get_all("network", old))
324 uci_r:foreach("network", "alias",
326 if s.interface == old then
327 uci_r:set("network", s['.name'], "interface", new)
331 uci_r:foreach("network", "route",
333 if s.interface == old then
334 uci_r:set("network", s['.name'], "interface", new)
338 uci_r:foreach("network", "route6",
340 if s.interface == old then
341 uci_r:set("network", s['.name'], "interface", new)
345 uci_r:foreach("wireless", "wifi-iface",
347 if s.network == old then
348 uci_r:set("wireless", s['.name'], "network", new)
352 uci_r:delete("network", old)
358 function get_interface(self, i)
359 if ifs[i] or _wifi_iface(i) then
364 uci_r:foreach("wireless", "wifi-iface",
367 num[s.device] = num[s.device] and num[s.device] + 1 or 1
368 if s['.name'] == i then
370 "%s.network%d" %{s.device, num[s.device] })
379 function get_interfaces(self)
385 -- find normal interfaces
386 uci_r:foreach("network", "interface",
388 for iface in utl.imatch(s.ifname) do
389 if not _iface_ignore(iface) and not _wifi_iface(iface) then
391 nfs[iface] = interface(iface)
396 for iface in utl.kspairs(ifs) do
397 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
398 nfs[iface] = interface(iface)
402 -- find vlan interfaces
403 uci_r:foreach("network", "switch_vlan",
405 local base = s.device or "-"
406 if not base:match("^eth%d") then
410 local vid = tonumber(s.vid or s.vlan)
411 if vid ~= nil and vid >= 0 and vid <= 4095 then
412 local iface = "%s.%d" %{ base, vid }
413 if not seen[iface] then
415 nfs[iface] = interface(iface)
420 for iface in utl.kspairs(nfs) do
421 ifaces[#ifaces+1] = nfs[iface]
424 -- find wifi interfaces
427 uci_r:foreach("wireless", "wifi-iface",
430 num[s.device] = num[s.device] and num[s.device] + 1 or 1
431 local i = "%s.network%d" %{ s.device, num[s.device] }
432 wfs[i] = interface(i)
436 for iface in utl.kspairs(wfs) do
437 ifaces[#ifaces+1] = wfs[iface]
443 function ignore_interface(self, x)
444 return _iface_ignore(x)
447 function get_wifidev(self, dev)
448 if uci_r:get("wireless", dev) == "wifi-device" then
453 function get_wifidevs(self)
457 uci_r:foreach("wireless", "wifi-device",
458 function(s) wfd[#wfd+1] = s['.name'] end)
461 for _, dev in utl.vspairs(wfd) do
462 devs[#devs+1] = wifidev(dev)
468 function get_wifinet(self, net)
469 local wnet = _wifi_lookup(net)
475 function add_wifinet(self, net, options)
476 if type(options) == "table" and options.device and
477 uci_r:get("wireless", options.device) == "wifi-device"
479 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
484 function del_wifinet(self, net)
485 local wnet = _wifi_lookup(net)
487 uci_r:delete("wireless", wnet)
494 network = utl.class()
496 function network.__init__(self, name)
500 function network._get(self, opt)
501 local v = uci_r:get("network", self.sid, opt)
502 if type(v) == "table" then
503 return table.concat(v, " ")
508 function network._ip(self, opt, family, list)
509 local ip = uci_s:get("network", self.sid, opt)
510 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
514 for ip in utl.imatch(ip) do
516 if ip then l[#l+1] = ip:string() end
521 return ip and ip:string()
526 function network.get(self, opt)
527 return _get("network", self.sid, opt)
530 function network.set(self, opt, val)
531 return _set("network", self.sid, opt, val)
534 function network.ifname(self)
535 local p = self:proto()
536 if self:is_bridge() then
537 return "br-" .. self.sid
538 elseif self:proto() == "relay" then
539 return uci_s:get("network", self.sid, "up") == "1" and "lo" or nil
540 elseif self:is_virtual() then
541 return p .. "-" .. self.sid
544 local dev = uci_r:get("network", self.sid, "ifname") or
545 uci_s:get("network", self.sid, "ifname")
547 dev = (type(dev) == "table") and dev[1] or dev
548 dev = (dev ~= nil) and dev:match("%S+")
551 uci_r:foreach("wireless", "wifi-iface",
554 num[s.device] = num[s.device]
555 and num[s.device] + 1 or 1
557 if s.network == self.sid then
558 dev = "%s.network%d" %{ s.device, num[s.device] }
569 function network.device(self)
570 local dev = uci_r:get("network", self.sid, "device") or
571 uci_s:get("network", self.sid, "device")
573 dev = (type(dev) == "table") and dev[1] or dev
575 if not dev or dev:match("[^%w%-%.%s]") then
576 dev = uci_r:get("network", self.sid, "ifname") or
577 uci_s:get("network", self.sid, "ifname")
579 dev = (type(dev) == "table") and dev[1] or dev
582 for dev in utl.imatch(dev) do
587 function network.proto(self)
588 return self:_get("proto") or "none"
591 function network.type(self)
592 return self:_get("type")
595 function network.name(self)
599 function network.uptime(self)
600 local cnt = tonumber(uci_s:get("network", self.sid, "connect_time"))
602 return nxo.sysinfo().uptime - cnt
608 function network.expires(self)
609 local a = tonumber(uci_s:get("network", self.sid, "lease_acquired"))
610 local l = tonumber(uci_s:get("network", self.sid, "lease_lifetime"))
612 l = l - (nxo.sysinfo().uptime - a)
613 return l > 0 and l or 0
618 function network.metric(self)
619 return tonumber(uci_s:get("network", self.sid, "metric")) or 0
622 function network.ipaddr(self)
623 return self:_ip("ipaddr", 4)
626 function network.netmask(self)
627 return self:_ip("netmask", 4)
630 function network.gwaddr(self)
631 return self:_ip("gateway", 4)
634 function network.dnsaddrs(self)
635 return self:_ip("dns", 4, true)
638 function network.ip6addr(self)
639 local ip6 = self:_ip("ip6addr", 6)
641 local ifc = ifs[self:ifname()]
642 if ifc and ifc.ip6addrs then
644 for _, a in ipairs(ifc.ip6addrs) do
645 if not a:is6linklocal() then
655 function network.gw6addr(self)
656 local ip6 = self:_ip("ip6gw", 6)
658 local dr6 = sys.net.defaultroute6()
659 if dr6 and dr6.device == self:ifname() then
660 return dr6.nexthop:string()
666 function network.dns6addrs(self)
667 return self:_ip("dns", 6, true)
670 function network.is_bridge(self)
671 return (self:type() == "bridge")
674 function network.is_virtual(self)
675 local p = self:proto()
677 p == "3g" or p == "6in4" or p == "6to4" or p == "ppp" or
678 p == "pppoe" or p == "pppoa" or p == "relay"
682 function network.is_floating(self)
683 return (self:is_virtual() and self:proto() ~= "pppoe")
686 function network.is_empty(self)
687 if self:is_virtual() then
692 if (self:_get("ifname") or ""):match("%S+") then
696 uci_r:foreach("wireless", "wifi-iface",
698 if s.network == self.sid then
708 function network.add_interface(self, ifname)
709 if not self:is_floating() then
710 if type(ifname) ~= "string" then
711 ifname = ifname:name()
713 ifname = ifname:match("[^%s:]+")
716 -- remove the interface from all ifaces
717 uci_r:foreach("network", "interface",
719 _list_del("network", s['.name'], "ifname", ifname)
722 -- if its a wifi interface, change its network option
723 local wif = _wifi_lookup(ifname)
725 uci_r:set("wireless", wif, "network", self.sid)
727 -- add iface to our iface list
729 _list_add("network", self.sid, "ifname", ifname)
734 function network.del_interface(self, ifname)
735 if not self:is_floating() then
736 if utl.instanceof(ifname, interface) then
737 ifname = ifname:name()
739 ifname = ifname:match("[^%s:]+")
742 -- if its a wireless interface, clear its network option
743 local wif = _wifi_lookup(ifname)
744 if wif then uci_r:delete("wireless", wif, "network") end
746 -- remove the interface
747 _list_del("network", self.sid, "ifname", ifname)
751 function network.get_interface(self)
752 if self:is_virtual() then
753 tns[self:proto() .. "-" .. self.sid] = true
754 return interface(self:proto() .. "-" .. self.sid, self)
755 elseif self:is_bridge() then
756 brs["br-" .. self.sid] = true
757 return interface("br-" .. self.sid, self)
761 for ifn in utl.imatch(uci_s:get("network", self.sid, "ifname")) do
762 ifn = ifn:match("^[^:/]+")
763 return ifn and interface(ifn, self)
766 uci_s:foreach("wireless", "wifi-iface",
769 num[s.device] = num[s.device] and num[s.device] + 1 or 1
770 if s.network == self.sid then
771 ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] }
776 return ifn and interface(ifn, self)
780 function network.get_interfaces(self)
785 for ifn in utl.imatch(self:get("ifname")) do
786 ifn = ifn:match("^[^:/]+")
787 nfs[ifn] = interface(ifn, self)
790 for ifn in utl.kspairs(nfs) do
791 ifaces[#ifaces+1] = nfs[ifn]
794 if self:is_bridge() then
797 uci_r:foreach("wireless", "wifi-iface",
800 num[s.device] = num[s.device] and num[s.device] + 1 or 1
801 if s.network == self.sid then
802 ifn = "%s.network%d" %{ s.device, num[s.device] }
803 wfs[ifn] = interface(ifn, self)
808 for ifn in utl.kspairs(wfs) do
809 ifaces[#ifaces+1] = wfs[ifn]
816 function network.contains_interface(self, ifname)
817 if type(ifname) ~= "string" then
818 ifname = ifname:name()
820 ifname = ifname:match("[^%s:]+")
823 if self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
825 elseif self:is_bridge() and "br-" .. self.sid == ifname then
829 for ifn in utl.imatch(self:get("ifname")) do
830 ifn = ifn:match("[^:]+")
831 if ifn == ifname then
836 local wif = _wifi_lookup(ifname)
838 return (uci_r:get("wireless", wif, "network") == self.sid)
845 function network.adminlink(self)
846 return dsp.build_url("admin", "network", "network", self.sid)
850 interface = utl.class()
851 function interface.__init__(self, ifname, network)
852 local wif = _wifi_lookup(ifname)
853 if wif then self.wif = wifinet(wif) end
855 self.ifname = self.ifname or ifname
856 self.dev = ifs[self.ifname]
857 self.network = network
860 function interface.name(self)
861 return self.wif and self.wif:ifname() or self.ifname
864 function interface.mac(self)
865 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
868 function interface.ipaddrs(self)
869 return self.dev and self.dev.ipaddrs or { }
872 function interface.ip6addrs(self)
873 return self.dev and self.dev.ip6addrs or { }
876 function interface.type(self)
877 if self.wif or _wifi_iface(self.ifname) then
879 elseif brs[self.ifname] then
881 elseif tns[self.ifname] then
883 elseif self.ifname:match("%.") then
885 elseif sws[self.ifname] then
892 function interface.shortname(self)
895 self.wif:active_mode(),
896 self.wif:active_ssid() or self.wif:active_bssid()
903 function interface.get_i18n(self)
905 return "%s: %s %q" %{
906 i18n.translate("Wireless Network"),
907 self.wif:active_mode(),
908 self.wif:active_ssid() or self.wif:active_bssid()
911 return "%s: %q" %{ self:get_type_i18n(), self:name() }
915 function interface.get_type_i18n(self)
916 local x = self:type()
918 return i18n.translate("Wireless Adapter")
919 elseif x == "bridge" then
920 return i18n.translate("Bridge")
921 elseif x == "switch" then
922 return i18n.translate("Ethernet Switch")
923 elseif x == "vlan" then
924 return i18n.translate("VLAN Interface")
925 elseif x == "tunnel" then
926 return i18n.translate("Tunnel Interface")
928 return i18n.translate("Ethernet Adapter")
932 function interface.adminlink(self)
934 return self.wif:adminlink()
938 function interface.ports(self)
942 for _, iface in ipairs(self.br.ifnames) do
943 ifaces[#ifaces+1] = interface(iface.name)
949 function interface.bridge_id(self)
957 function interface.bridge_stp(self)
965 function interface.is_up(self)
967 return self.wif:is_up()
969 return self.dev and self.dev.flags and self.dev.flags.up or false
973 function interface.is_bridge(self)
974 return (self:type() == "bridge")
977 function interface.is_bridgeport(self)
978 return self.dev and self.dev.bridge and true or false
981 function interface.tx_bytes(self)
982 return self.dev and self.dev.stats
983 and self.dev.stats.tx_bytes or 0
986 function interface.rx_bytes(self)
987 return self.dev and self.dev.stats
988 and self.dev.stats.rx_bytes or 0
991 function interface.tx_packets(self)
992 return self.dev and self.dev.stats
993 and self.dev.stats.tx_packets or 0
996 function interface.rx_packets(self)
997 return self.dev and self.dev.stats
998 and self.dev.stats.rx_packets or 0
1001 function interface.get_network(self)
1002 if not self.network then
1003 if self.dev and self.dev.network then
1004 self.network = _M:get_network(self.dev.network)
1008 if not self.network then
1010 for _, net in ipairs(_M:get_networks()) do
1011 if net:contains_interface(self.ifname) or
1012 net:ifname() == self.ifname
1023 function interface.get_wifinet(self)
1028 wifidev = utl.class()
1029 function wifidev.__init__(self, dev)
1031 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1034 function wifidev.get(self, opt)
1035 return _get("wireless", self.sid, opt)
1038 function wifidev.set(self, opt, val)
1039 return _set("wireless", self.sid, opt, val)
1042 function wifidev.name(self)
1046 function wifidev.hwmodes(self)
1047 local l = self.iwinfo.hwmodelist
1048 if l and next(l) then
1051 return { b = true, g = true }
1055 function wifidev.get_i18n(self)
1057 if self.iwinfo.type == "wl" then
1059 elseif self.iwinfo.type == "madwifi" then
1064 local l = self:hwmodes()
1065 if l.a then m = m .. "a" end
1066 if l.b then m = m .. "b" end
1067 if l.g then m = m .. "g" end
1068 if l.n then m = m .. "n" end
1070 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1073 function wifidev.is_up(self)
1076 uci_s:foreach("wireless", "wifi-iface",
1078 if s.device == self.sid then
1089 function wifidev.get_wifinet(self, net)
1090 if uci_r:get("wireless", net) == "wifi-iface" then
1093 local wnet = _wifi_lookup(net)
1095 return wifinet(wnet)
1100 function wifidev.get_wifinets(self)
1103 uci_r:foreach("wireless", "wifi-iface",
1105 if s.device == self.sid then
1106 nets[#nets+1] = wifinet(s['.name'])
1113 function wifidev.add_wifinet(self, options)
1114 options = options or { }
1115 options.device = self.sid
1117 local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
1119 return wifinet(wnet, options)
1123 function wifidev.del_wifinet(self, net)
1124 if utl.instanceof(net, wifinet) then
1126 elseif uci_r:get("wireless", net) ~= "wifi-iface" then
1127 net = _wifi_lookup(net)
1130 if net and uci_r:get("wireless", net, "device") == self.sid then
1131 uci_r:delete("wireless", net)
1139 wifinet = utl.class()
1140 function wifinet.__init__(self, net, data)
1145 uci_r:foreach("wireless", "wifi-iface",
1148 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1149 if s['.name'] == self.sid then
1150 netid = "%s.network%d" %{ s.device, num[s.device] }
1156 local dev = uci_s:get("wireless", self.sid, "ifname") or netid
1160 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1161 self.iwdata = data or uci_s:get_all("wireless", self.sid) or
1162 uci_r:get_all("wireless", self.sid) or { }
1165 function wifinet.get(self, opt)
1166 return _get("wireless", self.sid, opt)
1169 function wifinet.set(self, opt, val)
1170 return _set("wireless", self.sid, opt, val)
1173 function wifinet.mode(self)
1174 return uci_s:get("wireless", self.sid, "mode") or "ap"
1177 function wifinet.ssid(self)
1178 return uci_s:get("wireless", self.sid, "ssid")
1181 function wifinet.bssid(self)
1182 return uci_s:get("wireless", self.sid, "bssid")
1185 function wifinet.network(self)
1186 return uci_s:get("wifinet", self.sid, "network")
1189 function wifinet.id(self)
1193 function wifinet.name(self)
1197 function wifinet.ifname(self)
1198 local ifname = self.iwinfo.ifname
1199 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1205 function wifinet.get_device(self)
1206 if self.iwdata.device then
1207 return wifidev(self.iwdata.device)
1211 function wifinet.is_up(self)
1212 return (self.iwdata.up == "1")
1215 function wifinet.active_mode(self)
1216 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1218 if m == "ap" then m = "Master"
1219 elseif m == "sta" then m = "Client"
1220 elseif m == "adhoc" then m = "Ad-Hoc"
1221 elseif m == "mesh" then m = "Mesh"
1222 elseif m == "monitor" then m = "Monitor"
1228 function wifinet.active_mode_i18n(self)
1229 return i18n.translate(self:active_mode())
1232 function wifinet.active_ssid(self)
1233 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1236 function wifinet.active_bssid(self)
1237 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1240 function wifinet.active_encryption(self)
1241 local enc = self.iwinfo and self.iwinfo.encryption
1242 return enc and enc.description or "-"
1245 function wifinet.assoclist(self)
1246 return self.iwinfo.assoclist or { }
1249 function wifinet.frequency(self)
1250 local freq = self.iwinfo.frequency
1251 if freq and freq > 0 then
1252 return "%.03f" % (freq / 1000)
1256 function wifinet.bitrate(self)
1257 local rate = self.iwinfo.bitrate
1258 if rate and rate > 0 then
1259 return (rate / 1000)
1263 function wifinet.channel(self)
1264 return self.iwinfo.channel or
1265 tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1268 function wifinet.signal(self)
1269 return self.iwinfo.signal or 0
1272 function wifinet.noise(self)
1273 return self.iwinfo.noise or 0
1276 function wifinet.country(self)
1277 return self.iwinfo.country or "00"
1280 function wifinet.txpower(self)
1281 return self.iwinfo.txpower or 0
1284 function wifinet.signal_level(self, s, n)
1285 if self:active_bssid() ~= "00:00:00:00:00:00" then
1286 local signal = s or self:signal()
1287 local noise = n or self:noise()
1289 if signal < 0 and noise < 0 then
1290 local snr = -1 * (noise - signal)
1291 return math.floor(snr / 5)
1300 function wifinet.signal_percent(self)
1301 local qc = self.iwinfo.quality or 0
1302 local qm = self.iwinfo.quality_max or 0
1304 if qc > 0 and qm > 0 then
1305 return math.floor((100 / qm) * qc)
1311 function wifinet.shortname(self)
1313 i18n.translate(self:active_mode()),
1314 self:active_ssid() or self:active_bssid()
1318 function wifinet.get_i18n(self)
1319 return "%s: %s %q (%s)" %{
1320 i18n.translate("Wireless Network"),
1321 i18n.translate(self:active_mode()),
1322 self:active_ssid() or self:active_bssid(),
1327 function wifinet.adminlink(self)
1328 return dsp.build_url("admin", "network", "wireless", self.netid)
1331 function wifinet.get_network(self)
1332 if uci_r:get("network", self.iwdata.network) == "interface" then
1333 return network(self.iwdata.network)
1337 function wifinet.get_interface(self)
1338 return interface(self:ifname())