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
21 = type, next, pairs, ipairs, loadfile, table
23 local tonumber, tostring, math, i18n
24 = tonumber, tostring, math, luci.i18n
26 local require = require
28 local nxo = require "nixio"
29 local nfs = require "nixio.fs"
30 local ipc = require "luci.ip"
31 local sys = require "luci.sys"
32 local utl = require "luci.util"
33 local dsp = require "luci.dispatcher"
34 local uci = require "luci.model.uci"
36 module "luci.model.network"
39 IFACE_PATTERNS_VIRTUAL = { }
40 IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^lo$" }
41 IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
44 protocol = utl.class()
46 local _protocols = { }
48 local _interfaces, _bridge, _switch, _tunnel
49 local _uci_real, _uci_state
51 function _filter(c, s, o, r)
52 local val = _uci_real:get(c, s, o)
55 if type(val) == "string" then
56 for val in val:gmatch("%S+") do
62 _uci_real:set(c, s, o, table.concat(l, " "))
64 _uci_real:delete(c, s, o)
66 elseif type(val) == "table" then
67 for _, val in ipairs(val) do
73 _uci_real:set(c, s, o, l)
75 _uci_real:delete(c, s, o)
81 function _append(c, s, o, a)
82 local val = _uci_real:get(c, s, o) or ""
83 if type(val) == "string" then
85 for val in val:gmatch("%S+") do
91 _uci_real:set(c, s, o, table.concat(l, " "))
92 elseif type(val) == "table" then
94 for _, val in ipairs(val) do
100 _uci_real:set(c, s, o, l)
104 function _stror(s1, s2)
105 if not s1 or #s1 == 0 then
106 return s2 and #s2 > 0 and s2
112 function _get(c, s, o)
113 return _uci_real:get(c, s, o)
116 function _set(c, s, o, v)
118 if type(v) == "boolean" then v = v and "1" or "0" end
119 return _uci_real:set(c, s, o, v)
121 return _uci_real:delete(c, s, o)
125 function _wifi_iface(x)
127 for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
135 function _wifi_lookup(ifn)
136 -- got a radio#.network# pseudo iface, locate the corresponding section
137 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
138 if radio and ifnidx then
142 ifnidx = tonumber(ifnidx)
143 _uci_real:foreach("wireless", "wifi-iface",
145 if s.device == radio then
147 if num == ifnidx then
156 -- looks like wifi, try to locate the section via state vars
157 elseif _wifi_iface(ifn) then
160 _uci_state:foreach("wireless", "wifi-iface",
162 if s.ifname == ifn then
172 function _iface_virtual(x)
174 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
182 function _iface_ignore(x)
184 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
189 return _iface_virtual(x)
193 function init(cursor)
194 _uci_real = cursor or _uci_real or uci.cursor()
195 _uci_state = _uci_real:substate()
202 -- read interface information
204 for n, i in ipairs(nxo.getifaddrs()) do
205 local name = i.name:match("[^:]+")
206 local prnt = name:match("^([^%.]+)%.")
208 if _iface_virtual(name) then
212 if _tunnel[name] or not _iface_ignore(name) then
213 _interfaces[name] = _interfaces[name] or {
214 idx = i.ifindex or n,
227 if i.family == "packet" then
228 _interfaces[name].flags = i.flags
229 _interfaces[name].stats = i.data
230 _interfaces[name].macaddr = i.addr
231 elseif i.family == "inet" then
232 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
233 elseif i.family == "inet6" then
234 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
239 -- read bridge informaton
241 for l in utl.execi("brctl show") do
242 if not l:match("STP") then
243 local r = utl.split(l, "%s+", nil, true)
249 ifnames = { _interfaces[r[4]] }
252 b.ifnames[1].bridge = b
256 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
257 b.ifnames[#b.ifnames].bridge = b
265 function save(self, ...)
270 function commit(self, ...)
271 _uci_real:commit(...)
275 function ifnameof(self, x)
276 if utl.instanceof(x, interface) then
278 elseif utl.instanceof(x, protocol) then
280 elseif type(x) == "string" then
281 return x:match("^[^:]+")
285 function get_protocol(self, protoname, netname)
286 local v = _protocols[protoname]
288 return v(netname or "__dummy__")
292 function get_protocols(self)
295 for _, v in ipairs(_protocols) do
296 p[#p+1] = v("__dummy__")
301 function register_protocol(self, protoname)
302 local proto = utl.class(protocol)
304 function proto.__init__(self, name)
308 function proto.proto(self)
312 _protocols[#_protocols+1] = proto
313 _protocols[protoname] = proto
318 function register_pattern_virtual(self, pat)
319 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
323 function has_ipv6(self)
324 return nfs.access("/proc/net/ipv6_route")
327 function add_network(self, n, options)
328 local oldnet = self:get_network(n)
329 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
330 if _uci_real:section("network", "interface", n, options) then
333 elseif oldnet and oldnet:is_empty() then
336 for k, v in pairs(options) do
344 function get_network(self, n)
345 if n and _uci_real:get("network", n) == "interface" then
350 function get_networks(self)
354 _uci_real:foreach("network", "interface",
356 nls[s['.name']] = network(s['.name'])
360 for n in utl.kspairs(nls) do
361 nets[#nets+1] = nls[n]
367 function del_network(self, n)
368 local r = _uci_real:delete("network", n)
370 _uci_real:delete_all("network", "alias",
371 function(s) return (s.interface == n) end)
373 _uci_real:delete_all("network", "route",
374 function(s) return (s.interface == n) end)
376 _uci_real:delete_all("network", "route6",
377 function(s) return (s.interface == n) end)
379 _uci_real:foreach("wireless", "wifi-iface",
381 if s.network == n then
382 _uci_real:delete("wireless", s['.name'], "network")
389 function rename_network(self, old, new)
391 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
392 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
395 _uci_real:foreach("network", "alias",
397 if s.interface == old then
398 _uci_real:set("network", s['.name'], "interface", new)
402 _uci_real:foreach("network", "route",
404 if s.interface == old then
405 _uci_real:set("network", s['.name'], "interface", new)
409 _uci_real:foreach("network", "route6",
411 if s.interface == old then
412 _uci_real:set("network", s['.name'], "interface", new)
416 _uci_real:foreach("wireless", "wifi-iface",
418 if s.network == old then
419 _uci_real:set("wireless", s['.name'], "network", new)
423 _uci_real:delete("network", old)
429 function get_interface(self, i)
430 if _interfaces[i] or _wifi_iface(i) then
435 _uci_real:foreach("wireless", "wifi-iface",
438 num[s.device] = num[s.device] and num[s.device] + 1 or 1
439 if s['.name'] == i then
441 "%s.network%d" %{s.device, num[s.device] })
450 function get_interfaces(self)
457 -- find normal interfaces
458 _uci_real:foreach("network", "interface",
460 for iface in utl.imatch(s.ifname) do
461 if not _iface_ignore(iface) and not _wifi_iface(iface) then
463 nfs[iface] = interface(iface)
468 for iface in utl.kspairs(_interfaces) do
469 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
470 nfs[iface] = interface(iface)
474 -- find vlan interfaces
475 _uci_real:foreach("network", "switch_vlan",
481 local base = baseof[s.device]
483 if not s.device:match("^eth%d") then
485 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
487 base = l:match("^%w+: (%w+)")
490 if not base or not base:match("^eth%d") then
496 baseof[s.device] = base
499 local vid = tonumber(s.vid or s.vlan)
500 if vid ~= nil and vid >= 0 and vid <= 4095 then
501 local iface = "%s.%d" %{ base, vid }
502 if not seen[iface] then
504 nfs[iface] = interface(iface)
509 for iface in utl.kspairs(nfs) do
510 ifaces[#ifaces+1] = nfs[iface]
513 -- find wifi interfaces
516 _uci_real:foreach("wireless", "wifi-iface",
519 num[s.device] = num[s.device] and num[s.device] + 1 or 1
520 local i = "%s.network%d" %{ s.device, num[s.device] }
521 wfs[i] = interface(i)
525 for iface in utl.kspairs(wfs) do
526 ifaces[#ifaces+1] = wfs[iface]
532 function ignore_interface(self, x)
533 return _iface_ignore(x)
536 function get_wifidev(self, dev)
537 if _uci_real:get("wireless", dev) == "wifi-device" then
542 function get_wifidevs(self)
546 _uci_real:foreach("wireless", "wifi-device",
547 function(s) wfd[#wfd+1] = s['.name'] end)
550 for _, dev in utl.vspairs(wfd) do
551 devs[#devs+1] = wifidev(dev)
557 function get_wifinet(self, net)
558 local wnet = _wifi_lookup(net)
564 function add_wifinet(self, net, options)
565 if type(options) == "table" and options.device and
566 _uci_real:get("wireless", options.device) == "wifi-device"
568 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
573 function del_wifinet(self, net)
574 local wnet = _wifi_lookup(net)
576 _uci_real:delete("wireless", wnet)
583 function network(name, proto)
585 local p = proto or _uci_real:get("network", name, "proto")
586 local c = p and _protocols[p] or protocol
591 function protocol.__init__(self, name)
595 function protocol._get(self, opt)
596 local v = _uci_real:get("network", self.sid, opt)
597 if type(v) == "table" then
598 return table.concat(v, " ")
603 function protocol._ip(self, opt, family, list)
604 local ip = _uci_state:get("network", self.sid, opt)
605 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
609 for ip in utl.imatch(ip) do
611 if ip then l[#l+1] = ip:string() end
616 return ip and ip:string()
621 function protocol.get(self, opt)
622 return _get("network", self.sid, opt)
625 function protocol.set(self, opt, val)
626 return _set("network", self.sid, opt, val)
629 function protocol.ifname(self)
630 local p = self:proto()
631 if self:is_bridge() then
632 return "br-" .. self.sid
633 elseif self:is_virtual() then
634 return p .. "-" .. self.sid
637 local dev = _uci_real:get("network", self.sid, "ifname") or
638 _uci_state:get("network", self.sid, "ifname")
640 dev = (type(dev) == "table") and dev[1] or dev
641 dev = (dev ~= nil) and dev:match("%S+")
644 _uci_real:foreach("wireless", "wifi-iface",
647 num[s.device] = num[s.device]
648 and num[s.device] + 1 or 1
650 if s.network == self.sid then
651 dev = "%s.network%d" %{ s.device, num[s.device] }
662 function protocol.proto(self)
666 function protocol.get_i18n(self)
667 local p = self:proto()
669 return i18n.translate("Unmanaged")
670 elseif p == "static" then
671 return i18n.translate("Static address")
672 elseif p == "dhcp" then
673 return i18n.translate("DHCP client")
675 return i18n.translate("Unknown")
679 function protocol.type(self)
680 return self:_get("type")
683 function protocol.name(self)
687 function protocol.uptime(self)
688 local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
690 return nxo.sysinfo().uptime - cnt
696 function protocol.expires(self)
697 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
698 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
700 l = l - (nxo.sysinfo().uptime - a)
701 return l > 0 and l or 0
706 function protocol.metric(self)
707 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
710 function protocol.ipaddr(self)
711 return self:_ip("ipaddr", 4)
714 function protocol.netmask(self)
715 return self:_ip("netmask", 4)
718 function protocol.gwaddr(self)
719 return self:_ip("gateway", 4)
722 function protocol.dnsaddrs(self)
723 return self:_ip("dns", 4, true)
726 function protocol.ip6addr(self)
727 local ip6 = self:_ip("ip6addr", 6)
729 local ifc = _interfaces[self:ifname()]
730 if ifc and ifc.ip6addrs then
732 for _, a in ipairs(ifc.ip6addrs) do
733 if not a:is6linklocal() then
743 function protocol.gw6addr(self)
744 local ip6 = self:_ip("ip6gw", 6)
746 local dr6 = sys.net.defaultroute6()
747 if dr6 and dr6.device == self:ifname() then
748 return dr6.nexthop:string()
754 function protocol.dns6addrs(self)
755 return self:_ip("dns", 6, true)
758 function protocol.is_bridge(self)
759 return (not self:is_virtual() and self:type() == "bridge")
762 function protocol.opkg_package(self)
766 function protocol.is_installed(self)
770 function protocol.is_virtual(self)
774 function protocol.is_floating(self)
778 function protocol.is_empty(self)
779 if self:is_floating() then
784 if (self:_get("ifname") or ""):match("%S+") then
788 _uci_real:foreach("wireless", "wifi-iface",
790 if s.network == self.sid then
800 function protocol.add_interface(self, ifname)
801 ifname = _M:ifnameof(ifname)
802 if ifname and not self:is_floating() then
803 -- remove the interface from all ifaces
804 _uci_real:foreach("network", "interface",
806 _filter("network", s['.name'], "ifname", ifname)
809 -- if its a wifi interface, change its network option
810 local wif = _wifi_lookup(ifname)
812 _uci_real:set("wireless", wif, "network", self.sid)
814 -- add iface to our iface list
816 _append("network", self.sid, "ifname", ifname)
821 function protocol.del_interface(self, ifname)
822 ifname = _M:ifnameof(ifname)
823 if ifname and not self:is_floating() then
824 -- if its a wireless interface, clear its network option
825 local wif = _wifi_lookup(ifname)
826 if wif then _uci_real:delete("wireless", wif, "network") end
828 -- remove the interface
829 _filter("network", self.sid, "ifname", ifname)
833 function protocol.get_interface(self)
834 if self:is_virtual() then
835 _tunnel[self:proto() .. "-" .. self.sid] = true
836 return interface(self:proto() .. "-" .. self.sid, self)
837 elseif self:is_bridge() then
838 _bridge["br-" .. self.sid] = true
839 return interface("br-" .. self.sid, self)
843 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
844 ifn = ifn:match("^[^:/]+")
845 return ifn and interface(ifn, self)
848 _uci_real:foreach("wireless", "wifi-iface",
851 num[s.device] = num[s.device] and num[s.device] + 1 or 1
852 if s.network == self.sid then
853 ifn = "%s.network%d" %{ s.device, num[s.device] }
858 return ifn and interface(ifn, self)
862 function protocol.get_interfaces(self)
863 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
868 for ifn in utl.imatch(self:get("ifname")) do
869 ifn = ifn:match("^[^:/]+")
870 nfs[ifn] = interface(ifn, self)
873 for ifn in utl.kspairs(nfs) do
874 ifaces[#ifaces+1] = nfs[ifn]
879 _uci_real:foreach("wireless", "wifi-iface",
882 num[s.device] = num[s.device] and num[s.device] + 1 or 1
883 if s.network == self.sid then
884 ifn = "%s.network%d" %{ s.device, num[s.device] }
885 wfs[ifn] = interface(ifn, self)
890 for ifn in utl.kspairs(wfs) do
891 ifaces[#ifaces+1] = wfs[ifn]
898 function protocol.contains_interface(self, ifname)
899 ifname = _M:ifnameof(ifname)
902 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
904 elseif self:is_bridge() and "br-" .. self.sid == ifname then
908 for ifn in utl.imatch(self:get("ifname")) do
909 ifn = ifn:match("[^:]+")
910 if ifn == ifname then
915 local wif = _wifi_lookup(ifname)
917 return (_uci_real:get("wireless", wif, "network") == self.sid)
924 function protocol.adminlink(self)
925 return dsp.build_url("admin", "network", "network", self.sid)
929 interface = utl.class()
931 function interface.__init__(self, ifname, network)
932 local wif = _wifi_lookup(ifname)
934 self.wif = wifinet(wif)
935 self.ifname = _uci_state:get("wireless", wif, "ifname")
938 self.ifname = self.ifname or ifname
939 self.dev = _interfaces[self.ifname]
940 self.network = network
943 function interface.name(self)
944 return self.wif and self.wif:ifname() or self.ifname
947 function interface.mac(self)
948 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
951 function interface.ipaddrs(self)
952 return self.dev and self.dev.ipaddrs or { }
955 function interface.ip6addrs(self)
956 return self.dev and self.dev.ip6addrs or { }
959 function interface.type(self)
960 if self.wif or _wifi_iface(self.ifname) then
962 elseif _bridge[self.ifname] then
964 elseif _tunnel[self.ifname] then
966 elseif self.ifname:match("%.") then
968 elseif _switch[self.ifname] then
975 function interface.shortname(self)
978 self.wif:active_mode(),
979 self.wif:active_ssid() or self.wif:active_bssid()
986 function interface.get_i18n(self)
988 return "%s: %s %q" %{
989 i18n.translate("Wireless Network"),
990 self.wif:active_mode(),
991 self.wif:active_ssid() or self.wif:active_bssid()
994 return "%s: %q" %{ self:get_type_i18n(), self:name() }
998 function interface.get_type_i18n(self)
999 local x = self:type()
1001 return i18n.translate("Wireless Adapter")
1002 elseif x == "bridge" then
1003 return i18n.translate("Bridge")
1004 elseif x == "switch" then
1005 return i18n.translate("Ethernet Switch")
1006 elseif x == "vlan" then
1007 return i18n.translate("VLAN Interface")
1008 elseif x == "tunnel" then
1009 return i18n.translate("Tunnel Interface")
1011 return i18n.translate("Ethernet Adapter")
1015 function interface.adminlink(self)
1017 return self.wif:adminlink()
1021 function interface.ports(self)
1025 for _, iface in ipairs(self.br.ifnames) do
1026 ifaces[#ifaces+1] = interface(iface.name)
1032 function interface.bridge_id(self)
1040 function interface.bridge_stp(self)
1048 function interface.is_up(self)
1050 return self.wif:is_up()
1052 return self.dev and self.dev.flags and self.dev.flags.up or false
1056 function interface.is_bridge(self)
1057 return (self:type() == "bridge")
1060 function interface.is_bridgeport(self)
1061 return self.dev and self.dev.bridge and true or false
1064 function interface.tx_bytes(self)
1065 return self.dev and self.dev.stats
1066 and self.dev.stats.tx_bytes or 0
1069 function interface.rx_bytes(self)
1070 return self.dev and self.dev.stats
1071 and self.dev.stats.rx_bytes or 0
1074 function interface.tx_packets(self)
1075 return self.dev and self.dev.stats
1076 and self.dev.stats.tx_packets or 0
1079 function interface.rx_packets(self)
1080 return self.dev and self.dev.stats
1081 and self.dev.stats.rx_packets or 0
1084 function interface.get_network(self)
1085 if not self.network then
1086 if self.dev and self.dev.network then
1087 self.network = _M:get_network(self.dev.network)
1091 if not self.network then
1093 for _, net in ipairs(_M:get_networks()) do
1094 if net:contains_interface(self.ifname) or
1095 net:ifname() == self.ifname
1106 function interface.get_wifinet(self)
1111 wifidev = utl.class()
1113 function wifidev.__init__(self, dev)
1115 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1118 function wifidev.get(self, opt)
1119 return _get("wireless", self.sid, opt)
1122 function wifidev.set(self, opt, val)
1123 return _set("wireless", self.sid, opt, val)
1126 function wifidev.name(self)
1130 function wifidev.hwmodes(self)
1131 local l = self.iwinfo.hwmodelist
1132 if l and next(l) then
1135 return { b = true, g = true }
1139 function wifidev.get_i18n(self)
1141 if self.iwinfo.type == "wl" then
1143 elseif self.iwinfo.type == "madwifi" then
1148 local l = self:hwmodes()
1149 if l.a then m = m .. "a" end
1150 if l.b then m = m .. "b" end
1151 if l.g then m = m .. "g" end
1152 if l.n then m = m .. "n" end
1154 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1157 function wifidev.is_up(self)
1160 _uci_state:foreach("wireless", "wifi-iface",
1162 if s.device == self.sid then
1173 function wifidev.get_wifinet(self, net)
1174 if _uci_real:get("wireless", net) == "wifi-iface" then
1177 local wnet = _wifi_lookup(net)
1179 return wifinet(wnet)
1184 function wifidev.get_wifinets(self)
1187 _uci_real:foreach("wireless", "wifi-iface",
1189 if s.device == self.sid then
1190 nets[#nets+1] = wifinet(s['.name'])
1197 function wifidev.add_wifinet(self, options)
1198 options = options or { }
1199 options.device = self.sid
1201 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1203 return wifinet(wnet, options)
1207 function wifidev.del_wifinet(self, net)
1208 if utl.instanceof(net, wifinet) then
1210 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1211 net = _wifi_lookup(net)
1214 if net and _uci_real:get("wireless", net, "device") == self.sid then
1215 _uci_real:delete("wireless", net)
1223 wifinet = utl.class()
1225 function wifinet.__init__(self, net, data)
1230 _uci_real:foreach("wireless", "wifi-iface",
1233 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1234 if s['.name'] == self.sid then
1235 netid = "%s.network%d" %{ s.device, num[s.device] }
1241 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1245 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1246 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1247 _uci_real:get_all("wireless", self.sid) or { }
1250 function wifinet.get(self, opt)
1251 return _get("wireless", self.sid, opt)
1254 function wifinet.set(self, opt, val)
1255 return _set("wireless", self.sid, opt, val)
1258 function wifinet.mode(self)
1259 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1262 function wifinet.ssid(self)
1263 return _uci_state:get("wireless", self.sid, "ssid")
1266 function wifinet.bssid(self)
1267 return _uci_state:get("wireless", self.sid, "bssid")
1270 function wifinet.network(self)
1271 return _uci_state:get("wifinet", self.sid, "network")
1274 function wifinet.id(self)
1278 function wifinet.name(self)
1282 function wifinet.ifname(self)
1283 local ifname = self.iwinfo.ifname
1284 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1290 function wifinet.get_device(self)
1291 if self.iwdata.device then
1292 return wifidev(self.iwdata.device)
1296 function wifinet.is_up(self)
1297 return (self.iwdata.up == "1")
1300 function wifinet.active_mode(self)
1301 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1303 if m == "ap" then m = "Master"
1304 elseif m == "sta" then m = "Client"
1305 elseif m == "adhoc" then m = "Ad-Hoc"
1306 elseif m == "mesh" then m = "Mesh"
1307 elseif m == "monitor" then m = "Monitor"
1313 function wifinet.active_mode_i18n(self)
1314 return i18n.translate(self:active_mode())
1317 function wifinet.active_ssid(self)
1318 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1321 function wifinet.active_bssid(self)
1322 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1325 function wifinet.active_encryption(self)
1326 local enc = self.iwinfo and self.iwinfo.encryption
1327 return enc and enc.description or "-"
1330 function wifinet.assoclist(self)
1331 return self.iwinfo.assoclist or { }
1334 function wifinet.frequency(self)
1335 local freq = self.iwinfo.frequency
1336 if freq and freq > 0 then
1337 return "%.03f" % (freq / 1000)
1341 function wifinet.bitrate(self)
1342 local rate = self.iwinfo.bitrate
1343 if rate and rate > 0 then
1344 return (rate / 1000)
1348 function wifinet.channel(self)
1349 return self.iwinfo.channel or
1350 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1353 function wifinet.signal(self)
1354 return self.iwinfo.signal or 0
1357 function wifinet.noise(self)
1358 return self.iwinfo.noise or 0
1361 function wifinet.country(self)
1362 return self.iwinfo.country or "00"
1365 function wifinet.txpower(self)
1366 local pwr = (self.iwinfo.txpower or 0)
1367 return pwr + self:txpower_offset()
1370 function wifinet.txpower_offset(self)
1371 return self.iwinfo.txpower_offset or 0
1374 function wifinet.signal_level(self, s, n)
1375 if self:active_bssid() ~= "00:00:00:00:00:00" then
1376 local signal = s or self:signal()
1377 local noise = n or self:noise()
1379 if signal < 0 and noise < 0 then
1380 local snr = -1 * (noise - signal)
1381 return math.floor(snr / 5)
1390 function wifinet.signal_percent(self)
1391 local qc = self.iwinfo.quality or 0
1392 local qm = self.iwinfo.quality_max or 0
1394 if qc > 0 and qm > 0 then
1395 return math.floor((100 / qm) * qc)
1401 function wifinet.shortname(self)
1403 i18n.translate(self:active_mode()),
1404 self:active_ssid() or self:active_bssid()
1408 function wifinet.get_i18n(self)
1409 return "%s: %s %q (%s)" %{
1410 i18n.translate("Wireless Network"),
1411 i18n.translate(self:active_mode()),
1412 self:active_ssid() or self:active_bssid(),
1417 function wifinet.adminlink(self)
1418 return dsp.build_url("admin", "network", "wireless", self.netid)
1421 function wifinet.get_network(self)
1422 local net = tostring(self.iwdata.network)
1423 if net and _uci_real:get("network", net) == "interface" then
1428 function wifinet.get_interface(self)
1429 return interface(self:ifname())
1433 -- setup base protocols
1434 _M:register_protocol("static")
1435 _M:register_protocol("dhcp")
1436 _M:register_protocol("none")
1438 -- load protocol extensions
1439 local exts = nfs.dir(utl.libpath() .. "/model/network")
1443 if ext:match("%.lua$") then
1444 require("luci.model.network." .. ext:gsub("%.lua$", ""))