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 require = require
25 local nxo = require "nixio"
26 local nfs = require "nixio.fs"
27 local ipc = require "luci.ip"
28 local sys = require "luci.sys"
29 local utl = require "luci.util"
30 local dsp = require "luci.dispatcher"
31 local uci = require "luci.model.uci"
33 module "luci.model.network"
36 IFACE_PATTERNS_VIRTUAL = { }
37 IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^lo$" }
38 IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
41 protocol = utl.class()
43 local _protocols = { }
45 local _interfaces, _bridge, _switch, _tunnel
46 local _uci_real, _uci_state
48 function _filter(c, s, o, r)
49 local val = _uci_real:get(c, s, o)
52 if type(val) == "string" then
53 for val in val:gmatch("%S+") do
59 _uci_real:set(c, s, o, table.concat(l, " "))
61 _uci_real:delete(c, s, o)
63 elseif type(val) == "table" then
64 for _, val in ipairs(val) do
70 _uci_real:set(c, s, o, l)
72 _uci_real:delete(c, s, o)
78 function _append(c, s, o, a)
79 local val = _uci_real:get(c, s, o) or ""
80 if type(val) == "string" then
82 for val in val:gmatch("%S+") do
88 _uci_real:set(c, s, o, table.concat(l, " "))
89 elseif type(val) == "table" then
91 for _, val in ipairs(val) do
97 _uci_real:set(c, s, o, l)
101 function _stror(s1, s2)
102 if not s1 or #s1 == 0 then
103 return s2 and #s2 > 0 and s2
109 function _get(c, s, o)
110 return _uci_real:get(c, s, o)
113 function _set(c, s, o, v)
115 if type(v) == "boolean" then v = v and "1" or "0" end
116 return _uci_real:set(c, s, o, v)
118 return _uci_real:delete(c, s, o)
122 function _wifi_iface(x)
124 for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
132 function _wifi_lookup(ifn)
133 -- got a radio#.network# pseudo iface, locate the corresponding section
134 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
135 if radio and ifnidx then
139 ifnidx = tonumber(ifnidx)
140 _uci_real:foreach("wireless", "wifi-iface",
142 if s.device == radio then
144 if num == ifnidx then
153 -- looks like wifi, try to locate the section via state vars
154 elseif _wifi_iface(ifn) then
157 _uci_state:foreach("wireless", "wifi-iface",
159 if s.ifname == ifn then
169 function _iface_virtual(x)
171 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
179 function _iface_ignore(x)
181 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
186 return _iface_virtual(x)
190 function init(cursor)
191 _uci_real = cursor or _uci_real or uci.cursor()
192 _uci_state = _uci_real:substate()
199 -- read interface information
201 for n, i in ipairs(nxo.getifaddrs()) do
202 local name = i.name:match("[^:]+")
203 local prnt = name:match("^([^%.]+)%.")
205 if _iface_virtual(name) then
209 if _tunnel[name] or not _iface_ignore(name) then
210 _interfaces[name] = _interfaces[name] or {
211 idx = i.ifindex or n,
224 if i.family == "packet" then
225 _interfaces[name].flags = i.flags
226 _interfaces[name].stats = i.data
227 _interfaces[name].macaddr = i.addr
228 elseif i.family == "inet" then
229 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
230 elseif i.family == "inet6" then
231 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
236 -- read bridge informaton
238 for l in utl.execi("brctl show") do
239 if not l:match("STP") then
240 local r = utl.split(l, "%s+", nil, true)
246 ifnames = { _interfaces[r[4]] }
249 b.ifnames[1].bridge = b
253 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
254 b.ifnames[#b.ifnames].bridge = b
262 function save(self, ...)
267 function commit(self, ...)
268 _uci_real:commit(...)
272 function ifnameof(self, x)
273 if utl.instanceof(x, interface) then
275 elseif utl.instanceof(x, protocol) then
277 elseif type(x) == "string" then
278 return x:match("^[^:]+")
282 function get_protocol(self, protoname, netname)
283 local v = _protocols[protoname]
285 return v(netname or "__dummy__")
289 function get_protocols(self)
292 for _, v in ipairs(_protocols) do
293 p[#p+1] = v("__dummy__")
298 function register_protocol(self, protoname)
299 local proto = utl.class(protocol)
301 function proto.__init__(self, name)
305 function proto.proto(self)
309 _protocols[#_protocols+1] = proto
310 _protocols[protoname] = proto
315 function register_pattern_virtual(self, pat)
316 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
320 function has_ipv6(self)
321 return nfs.access("/proc/net/ipv6_route")
324 function add_network(self, n, options)
325 local oldnet = self:get_network(n)
326 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
327 if _uci_real:section("network", "interface", n, options) then
330 elseif oldnet and oldnet:is_empty() then
333 for k, v in pairs(options) do
341 function get_network(self, n)
342 if n and _uci_real:get("network", n) == "interface" then
347 function get_networks(self)
351 _uci_real:foreach("network", "interface",
353 nls[s['.name']] = network(s['.name'])
357 for n in utl.kspairs(nls) do
358 nets[#nets+1] = nls[n]
364 function del_network(self, n)
365 local r = _uci_real:delete("network", n)
367 _uci_real:delete_all("network", "alias",
368 function(s) return (s.interface == n) end)
370 _uci_real:delete_all("network", "route",
371 function(s) return (s.interface == n) end)
373 _uci_real:delete_all("network", "route6",
374 function(s) return (s.interface == n) end)
376 _uci_real:foreach("wireless", "wifi-iface",
378 if s.network == n then
379 _uci_real:delete("wireless", s['.name'], "network")
386 function rename_network(self, old, new)
388 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
389 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
392 _uci_real:foreach("network", "alias",
394 if s.interface == old then
395 _uci_real:set("network", s['.name'], "interface", new)
399 _uci_real:foreach("network", "route",
401 if s.interface == old then
402 _uci_real:set("network", s['.name'], "interface", new)
406 _uci_real:foreach("network", "route6",
408 if s.interface == old then
409 _uci_real:set("network", s['.name'], "interface", new)
413 _uci_real:foreach("wireless", "wifi-iface",
415 if s.network == old then
416 _uci_real:set("wireless", s['.name'], "network", new)
420 _uci_real:delete("network", old)
426 function get_interface(self, i)
427 if _interfaces[i] or _wifi_iface(i) then
432 _uci_real:foreach("wireless", "wifi-iface",
435 num[s.device] = num[s.device] and num[s.device] + 1 or 1
436 if s['.name'] == i then
438 "%s.network%d" %{s.device, num[s.device] })
447 function get_interfaces(self)
454 -- find normal interfaces
455 _uci_real:foreach("network", "interface",
457 for iface in utl.imatch(s.ifname) do
458 if not _iface_ignore(iface) and not _wifi_iface(iface) then
460 nfs[iface] = interface(iface)
465 for iface in utl.kspairs(_interfaces) do
466 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
467 nfs[iface] = interface(iface)
471 -- find vlan interfaces
472 _uci_real:foreach("network", "switch_vlan",
478 local base = baseof[s.device]
480 if not s.device:match("^eth%d") then
482 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
484 base = l:match("^%w+: (%w+)")
487 if not base or not base:match("^eth%d") then
493 baseof[s.device] = base
496 local vid = tonumber(s.vid or s.vlan)
497 if vid ~= nil and vid >= 0 and vid <= 4095 then
498 local iface = "%s.%d" %{ base, vid }
499 if not seen[iface] then
501 nfs[iface] = interface(iface)
506 for iface in utl.kspairs(nfs) do
507 ifaces[#ifaces+1] = nfs[iface]
510 -- find wifi interfaces
513 _uci_real:foreach("wireless", "wifi-iface",
516 num[s.device] = num[s.device] and num[s.device] + 1 or 1
517 local i = "%s.network%d" %{ s.device, num[s.device] }
518 wfs[i] = interface(i)
522 for iface in utl.kspairs(wfs) do
523 ifaces[#ifaces+1] = wfs[iface]
529 function ignore_interface(self, x)
530 return _iface_ignore(x)
533 function get_wifidev(self, dev)
534 if _uci_real:get("wireless", dev) == "wifi-device" then
539 function get_wifidevs(self)
543 _uci_real:foreach("wireless", "wifi-device",
544 function(s) wfd[#wfd+1] = s['.name'] end)
547 for _, dev in utl.vspairs(wfd) do
548 devs[#devs+1] = wifidev(dev)
554 function get_wifinet(self, net)
555 local wnet = _wifi_lookup(net)
561 function add_wifinet(self, net, options)
562 if type(options) == "table" and options.device and
563 _uci_real:get("wireless", options.device) == "wifi-device"
565 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
570 function del_wifinet(self, net)
571 local wnet = _wifi_lookup(net)
573 _uci_real:delete("wireless", wnet)
580 function network(name, proto)
582 local p = proto or _uci_real:get("network", name, "proto")
583 local c = p and _protocols[p] or protocol
588 function protocol.__init__(self, name)
592 function protocol._get(self, opt)
593 local v = _uci_real:get("network", self.sid, opt)
594 if type(v) == "table" then
595 return table.concat(v, " ")
600 function protocol._ip(self, opt, family, list)
601 local ip = _uci_state:get("network", self.sid, opt)
602 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
606 for ip in utl.imatch(ip) do
608 if ip then l[#l+1] = ip:string() end
613 return ip and ip:string()
618 function protocol.get(self, opt)
619 return _get("network", self.sid, opt)
622 function protocol.set(self, opt, val)
623 return _set("network", self.sid, opt, val)
626 function protocol.ifname(self)
627 local p = self:proto()
628 if self:is_bridge() then
629 return "br-" .. self.sid
630 elseif self:is_virtual() then
631 return p .. "-" .. self.sid
634 local dev = _uci_real:get("network", self.sid, "ifname") or
635 _uci_state:get("network", self.sid, "ifname")
637 dev = (type(dev) == "table") and dev[1] or dev
638 dev = (dev ~= nil) and dev:match("%S+")
641 _uci_real:foreach("wireless", "wifi-iface",
644 num[s.device] = num[s.device]
645 and num[s.device] + 1 or 1
647 if s.network == self.sid then
648 dev = "%s.network%d" %{ s.device, num[s.device] }
659 function protocol.proto(self)
663 function protocol.get_i18n(self)
664 local p = self:proto()
666 return i18n.translate("Unmanaged")
667 elseif p == "static" then
668 return i18n.translate("Static address")
669 elseif p == "dhcp" then
670 return i18n.translate("DHCP client")
672 return i18n.translate("Unknown")
676 function protocol.type(self)
677 return self:_get("type")
680 function protocol.name(self)
684 function protocol.uptime(self)
685 local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
687 return nxo.sysinfo().uptime - cnt
693 function protocol.expires(self)
694 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
695 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
697 l = l - (nxo.sysinfo().uptime - a)
698 return l > 0 and l or 0
703 function protocol.metric(self)
704 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
707 function protocol.ipaddr(self)
708 return self:_ip("ipaddr", 4)
711 function protocol.netmask(self)
712 return self:_ip("netmask", 4)
715 function protocol.gwaddr(self)
716 return self:_ip("gateway", 4)
719 function protocol.dnsaddrs(self)
720 return self:_ip("dns", 4, true)
723 function protocol.ip6addr(self)
724 local ip6 = self:_ip("ip6addr", 6)
726 local ifc = _interfaces[self:ifname()]
727 if ifc and ifc.ip6addrs then
729 for _, a in ipairs(ifc.ip6addrs) do
730 if not a:is6linklocal() then
740 function protocol.gw6addr(self)
741 local ip6 = self:_ip("ip6gw", 6)
743 local dr6 = sys.net.defaultroute6()
744 if dr6 and dr6.device == self:ifname() then
745 return dr6.nexthop:string()
751 function protocol.dns6addrs(self)
752 return self:_ip("dns", 6, true)
755 function protocol.is_bridge(self)
756 return (not self:is_virtual() and self:type() == "bridge")
759 function protocol.opkg_package(self)
763 function protocol.is_installed(self)
767 function protocol.is_virtual(self)
771 function protocol.is_floating(self)
775 function protocol.is_empty(self)
776 if self:is_floating() then
781 if (self:_get("ifname") or ""):match("%S+") then
785 _uci_real:foreach("wireless", "wifi-iface",
787 if s.network == self.sid then
797 function protocol.add_interface(self, ifname)
798 ifname = _M:ifnameof(ifname)
799 if ifname and not self:is_floating() then
800 -- remove the interface from all ifaces
801 _uci_real:foreach("network", "interface",
803 _filter("network", s['.name'], "ifname", ifname)
806 -- if its a wifi interface, change its network option
807 local wif = _wifi_lookup(ifname)
809 _uci_real:set("wireless", wif, "network", self.sid)
811 -- add iface to our iface list
813 _append("network", self.sid, "ifname", ifname)
818 function protocol.del_interface(self, ifname)
819 ifname = _M:ifnameof(ifname)
820 if ifname and not self:is_floating() then
821 -- if its a wireless interface, clear its network option
822 local wif = _wifi_lookup(ifname)
823 if wif then _uci_real:delete("wireless", wif, "network") end
825 -- remove the interface
826 _filter("network", self.sid, "ifname", ifname)
830 function protocol.get_interface(self)
831 if self:is_virtual() then
832 _tunnel[self:proto() .. "-" .. self.sid] = true
833 return interface(self:proto() .. "-" .. self.sid, self)
834 elseif self:is_bridge() then
835 _bridge["br-" .. self.sid] = true
836 return interface("br-" .. self.sid, self)
840 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
841 ifn = ifn:match("^[^:/]+")
842 return ifn and interface(ifn, self)
845 _uci_real:foreach("wireless", "wifi-iface",
848 num[s.device] = num[s.device] and num[s.device] + 1 or 1
849 if s.network == self.sid then
850 ifn = "%s.network%d" %{ s.device, num[s.device] }
855 return ifn and interface(ifn, self)
859 function protocol.get_interfaces(self)
860 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
865 for ifn in utl.imatch(self:get("ifname")) do
866 ifn = ifn:match("^[^:/]+")
867 nfs[ifn] = interface(ifn, self)
870 for ifn in utl.kspairs(nfs) do
871 ifaces[#ifaces+1] = nfs[ifn]
876 _uci_real:foreach("wireless", "wifi-iface",
879 num[s.device] = num[s.device] and num[s.device] + 1 or 1
880 if s.network == self.sid then
881 ifn = "%s.network%d" %{ s.device, num[s.device] }
882 wfs[ifn] = interface(ifn, self)
887 for ifn in utl.kspairs(wfs) do
888 ifaces[#ifaces+1] = wfs[ifn]
895 function protocol.contains_interface(self, ifname)
896 ifname = _M:ifnameof(ifname)
899 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
901 elseif self:is_bridge() and "br-" .. self.sid == ifname then
905 for ifn in utl.imatch(self:get("ifname")) do
906 ifn = ifn:match("[^:]+")
907 if ifn == ifname then
912 local wif = _wifi_lookup(ifname)
914 return (_uci_real:get("wireless", wif, "network") == self.sid)
921 function protocol.adminlink(self)
922 return dsp.build_url("admin", "network", "network", self.sid)
926 interface = utl.class()
928 function interface.__init__(self, ifname, network)
929 local wif = _wifi_lookup(ifname)
931 self.wif = wifinet(wif)
932 self.ifname = _uci_state:get("wireless", wif, "ifname")
935 self.ifname = self.ifname or ifname
936 self.dev = _interfaces[self.ifname]
937 self.network = network
940 function interface.name(self)
941 return self.wif and self.wif:ifname() or self.ifname
944 function interface.mac(self)
945 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
948 function interface.ipaddrs(self)
949 return self.dev and self.dev.ipaddrs or { }
952 function interface.ip6addrs(self)
953 return self.dev and self.dev.ip6addrs or { }
956 function interface.type(self)
957 if self.wif or _wifi_iface(self.ifname) then
959 elseif _bridge[self.ifname] then
961 elseif _tunnel[self.ifname] then
963 elseif self.ifname:match("%.") then
965 elseif _switch[self.ifname] then
972 function interface.shortname(self)
975 self.wif:active_mode(),
976 self.wif:active_ssid() or self.wif:active_bssid()
983 function interface.get_i18n(self)
985 return "%s: %s %q" %{
986 i18n.translate("Wireless Network"),
987 self.wif:active_mode(),
988 self.wif:active_ssid() or self.wif:active_bssid()
991 return "%s: %q" %{ self:get_type_i18n(), self:name() }
995 function interface.get_type_i18n(self)
996 local x = self:type()
998 return i18n.translate("Wireless Adapter")
999 elseif x == "bridge" then
1000 return i18n.translate("Bridge")
1001 elseif x == "switch" then
1002 return i18n.translate("Ethernet Switch")
1003 elseif x == "vlan" then
1004 return i18n.translate("VLAN Interface")
1005 elseif x == "tunnel" then
1006 return i18n.translate("Tunnel Interface")
1008 return i18n.translate("Ethernet Adapter")
1012 function interface.adminlink(self)
1014 return self.wif:adminlink()
1018 function interface.ports(self)
1022 for _, iface in ipairs(self.br.ifnames) do
1023 ifaces[#ifaces+1] = interface(iface.name)
1029 function interface.bridge_id(self)
1037 function interface.bridge_stp(self)
1045 function interface.is_up(self)
1047 return self.wif:is_up()
1049 return self.dev and self.dev.flags and self.dev.flags.up or false
1053 function interface.is_bridge(self)
1054 return (self:type() == "bridge")
1057 function interface.is_bridgeport(self)
1058 return self.dev and self.dev.bridge and true or false
1061 function interface.tx_bytes(self)
1062 return self.dev and self.dev.stats
1063 and self.dev.stats.tx_bytes or 0
1066 function interface.rx_bytes(self)
1067 return self.dev and self.dev.stats
1068 and self.dev.stats.rx_bytes or 0
1071 function interface.tx_packets(self)
1072 return self.dev and self.dev.stats
1073 and self.dev.stats.tx_packets or 0
1076 function interface.rx_packets(self)
1077 return self.dev and self.dev.stats
1078 and self.dev.stats.rx_packets or 0
1081 function interface.get_network(self)
1082 if not self.network then
1083 if self.dev and self.dev.network then
1084 self.network = _M:get_network(self.dev.network)
1088 if not self.network then
1090 for _, net in ipairs(_M:get_networks()) do
1091 if net:contains_interface(self.ifname) or
1092 net:ifname() == self.ifname
1103 function interface.get_wifinet(self)
1108 wifidev = utl.class()
1110 function wifidev.__init__(self, dev)
1112 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1115 function wifidev.get(self, opt)
1116 return _get("wireless", self.sid, opt)
1119 function wifidev.set(self, opt, val)
1120 return _set("wireless", self.sid, opt, val)
1123 function wifidev.name(self)
1127 function wifidev.hwmodes(self)
1128 local l = self.iwinfo.hwmodelist
1129 if l and next(l) then
1132 return { b = true, g = true }
1136 function wifidev.get_i18n(self)
1138 if self.iwinfo.type == "wl" then
1140 elseif self.iwinfo.type == "madwifi" then
1145 local l = self:hwmodes()
1146 if l.a then m = m .. "a" end
1147 if l.b then m = m .. "b" end
1148 if l.g then m = m .. "g" end
1149 if l.n then m = m .. "n" end
1151 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1154 function wifidev.is_up(self)
1157 _uci_state:foreach("wireless", "wifi-iface",
1159 if s.device == self.sid then
1170 function wifidev.get_wifinet(self, net)
1171 if _uci_real:get("wireless", net) == "wifi-iface" then
1174 local wnet = _wifi_lookup(net)
1176 return wifinet(wnet)
1181 function wifidev.get_wifinets(self)
1184 _uci_real:foreach("wireless", "wifi-iface",
1186 if s.device == self.sid then
1187 nets[#nets+1] = wifinet(s['.name'])
1194 function wifidev.add_wifinet(self, options)
1195 options = options or { }
1196 options.device = self.sid
1198 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1200 return wifinet(wnet, options)
1204 function wifidev.del_wifinet(self, net)
1205 if utl.instanceof(net, wifinet) then
1207 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1208 net = _wifi_lookup(net)
1211 if net and _uci_real:get("wireless", net, "device") == self.sid then
1212 _uci_real:delete("wireless", net)
1220 wifinet = utl.class()
1222 function wifinet.__init__(self, net, data)
1227 _uci_real:foreach("wireless", "wifi-iface",
1230 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1231 if s['.name'] == self.sid then
1232 netid = "%s.network%d" %{ s.device, num[s.device] }
1238 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1242 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1243 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1244 _uci_real:get_all("wireless", self.sid) or { }
1247 function wifinet.get(self, opt)
1248 return _get("wireless", self.sid, opt)
1251 function wifinet.set(self, opt, val)
1252 return _set("wireless", self.sid, opt, val)
1255 function wifinet.mode(self)
1256 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1259 function wifinet.ssid(self)
1260 return _uci_state:get("wireless", self.sid, "ssid")
1263 function wifinet.bssid(self)
1264 return _uci_state:get("wireless", self.sid, "bssid")
1267 function wifinet.network(self)
1268 return _uci_state:get("wifinet", self.sid, "network")
1271 function wifinet.id(self)
1275 function wifinet.name(self)
1279 function wifinet.ifname(self)
1280 local ifname = self.iwinfo.ifname
1281 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1287 function wifinet.get_device(self)
1288 if self.iwdata.device then
1289 return wifidev(self.iwdata.device)
1293 function wifinet.is_up(self)
1294 return (self.iwdata.up == "1")
1297 function wifinet.active_mode(self)
1298 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1300 if m == "ap" then m = "Master"
1301 elseif m == "sta" then m = "Client"
1302 elseif m == "adhoc" then m = "Ad-Hoc"
1303 elseif m == "mesh" then m = "Mesh"
1304 elseif m == "monitor" then m = "Monitor"
1310 function wifinet.active_mode_i18n(self)
1311 return i18n.translate(self:active_mode())
1314 function wifinet.active_ssid(self)
1315 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1318 function wifinet.active_bssid(self)
1319 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1322 function wifinet.active_encryption(self)
1323 local enc = self.iwinfo and self.iwinfo.encryption
1324 return enc and enc.description or "-"
1327 function wifinet.assoclist(self)
1328 return self.iwinfo.assoclist or { }
1331 function wifinet.frequency(self)
1332 local freq = self.iwinfo.frequency
1333 if freq and freq > 0 then
1334 return "%.03f" % (freq / 1000)
1338 function wifinet.bitrate(self)
1339 local rate = self.iwinfo.bitrate
1340 if rate and rate > 0 then
1341 return (rate / 1000)
1345 function wifinet.channel(self)
1346 return self.iwinfo.channel or
1347 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1350 function wifinet.signal(self)
1351 return self.iwinfo.signal or 0
1354 function wifinet.noise(self)
1355 return self.iwinfo.noise or 0
1358 function wifinet.country(self)
1359 return self.iwinfo.country or "00"
1362 function wifinet.txpower(self)
1363 local pwr = (self.iwinfo.txpower or 0)
1364 return pwr + self:txpower_offset()
1367 function wifinet.txpower_offset(self)
1368 return self.iwinfo.txpower_offset or 0
1371 function wifinet.signal_level(self, s, n)
1372 if self:active_bssid() ~= "00:00:00:00:00:00" then
1373 local signal = s or self:signal()
1374 local noise = n or self:noise()
1376 if signal < 0 and noise < 0 then
1377 local snr = -1 * (noise - signal)
1378 return math.floor(snr / 5)
1387 function wifinet.signal_percent(self)
1388 local qc = self.iwinfo.quality or 0
1389 local qm = self.iwinfo.quality_max or 0
1391 if qc > 0 and qm > 0 then
1392 return math.floor((100 / qm) * qc)
1398 function wifinet.shortname(self)
1400 i18n.translate(self:active_mode()),
1401 self:active_ssid() or self:active_bssid()
1405 function wifinet.get_i18n(self)
1406 return "%s: %s %q (%s)" %{
1407 i18n.translate("Wireless Network"),
1408 i18n.translate(self:active_mode()),
1409 self:active_ssid() or self:active_bssid(),
1414 function wifinet.adminlink(self)
1415 return dsp.build_url("admin", "network", "wireless", self.netid)
1418 function wifinet.get_network(self)
1419 local net = tostring(self.iwdata.network)
1420 if net and _uci_real:get("network", net) == "interface" then
1425 function wifinet.get_interface(self)
1426 return interface(self:ifname())
1430 -- setup base protocols
1431 _M:register_protocol("static")
1432 _M:register_protocol("dhcp")
1433 _M:register_protocol("none")
1435 -- load protocol extensions
1436 local exts = nfs.dir(utl.libpath() .. "/model/network")
1440 if ext:match("%.lua$") then
1441 require("luci.model.network." .. ext:gsub("%.lua$", ""))