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
24 local require = require
26 local nxo = require "nixio"
27 local nfs = require "nixio.fs"
28 local ipc = require "luci.ip"
29 local sys = require "luci.sys"
30 local utl = require "luci.util"
31 local dsp = require "luci.dispatcher"
32 local uci = require "luci.model.uci"
34 module "luci.model.network"
37 IFACE_PATTERNS_VIRTUAL = { }
38 IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^lo$" }
39 IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
42 protocol = utl.class()
44 local _protocols = { }
46 local _interfaces, _bridge, _switch, _tunnel
47 local _uci_real, _uci_state
49 function _filter(c, s, o, r)
50 local val = _uci_real:get(c, s, o)
53 if type(val) == "string" then
54 for val in val:gmatch("%S+") do
60 _uci_real:set(c, s, o, table.concat(l, " "))
62 _uci_real:delete(c, s, o)
64 elseif type(val) == "table" then
65 for _, val in ipairs(val) do
71 _uci_real:set(c, s, o, l)
73 _uci_real:delete(c, s, o)
79 function _append(c, s, o, a)
80 local val = _uci_real:get(c, s, o) or ""
81 if type(val) == "string" then
83 for val in val:gmatch("%S+") do
89 _uci_real:set(c, s, o, table.concat(l, " "))
90 elseif type(val) == "table" then
92 for _, val in ipairs(val) do
98 _uci_real:set(c, s, o, l)
102 function _stror(s1, s2)
103 if not s1 or #s1 == 0 then
104 return s2 and #s2 > 0 and s2
110 function _get(c, s, o)
111 return _uci_real:get(c, s, o)
114 function _set(c, s, o, v)
116 if type(v) == "boolean" then v = v and "1" or "0" end
117 return _uci_real:set(c, s, o, v)
119 return _uci_real:delete(c, s, o)
123 function _wifi_iface(x)
125 for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
133 function _wifi_lookup(ifn)
134 -- got a radio#.network# pseudo iface, locate the corresponding section
135 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
136 if radio and ifnidx then
140 ifnidx = tonumber(ifnidx)
141 _uci_real:foreach("wireless", "wifi-iface",
143 if s.device == radio then
145 if num == ifnidx then
154 -- looks like wifi, try to locate the section via state vars
155 elseif _wifi_iface(ifn) then
158 _uci_state:foreach("wireless", "wifi-iface",
160 if s.ifname == ifn then
170 function _iface_virtual(x)
172 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
180 function _iface_ignore(x)
182 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
187 return _iface_virtual(x)
191 function init(cursor)
192 _uci_real = cursor or _uci_real or uci.cursor()
193 _uci_state = _uci_real:substate()
200 -- read interface information
202 for n, i in ipairs(nxo.getifaddrs()) do
203 local name = i.name:match("[^:]+")
204 local prnt = name:match("^([^%.]+)%.")
206 if _iface_virtual(name) then
210 if _tunnel[name] or not _iface_ignore(name) then
211 _interfaces[name] = _interfaces[name] or {
212 idx = i.ifindex or n,
225 if i.family == "packet" then
226 _interfaces[name].flags = i.flags
227 _interfaces[name].stats = i.data
228 _interfaces[name].macaddr = i.addr
229 elseif i.family == "inet" then
230 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
231 elseif i.family == "inet6" then
232 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
237 -- read bridge informaton
239 for l in utl.execi("brctl show") do
240 if not l:match("STP") then
241 local r = utl.split(l, "%s+", nil, true)
247 ifnames = { _interfaces[r[4]] }
250 b.ifnames[1].bridge = b
254 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
255 b.ifnames[#b.ifnames].bridge = b
263 function save(self, ...)
268 function commit(self, ...)
269 _uci_real:commit(...)
273 function ifnameof(self, x)
274 if utl.instanceof(x, interface) then
276 elseif utl.instanceof(x, protocol) then
278 elseif type(x) == "string" then
279 return x:match("^[^:]+")
283 function get_protocol(self, protoname, netname)
284 local v = _protocols[protoname]
286 return v(netname or "__dummy__")
290 function get_protocols(self)
293 for _, v in ipairs(_protocols) do
294 p[#p+1] = v("__dummy__")
299 function register_protocol(self, protoname)
300 local proto = utl.class(protocol)
302 function proto.__init__(self, name)
306 function proto.proto(self)
310 _protocols[#_protocols+1] = proto
311 _protocols[protoname] = proto
316 function register_pattern_virtual(self, pat)
317 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
321 function has_ipv6(self)
322 return nfs.access("/proc/net/ipv6_route")
325 function add_network(self, n, options)
326 local oldnet = self:get_network(n)
327 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
328 if _uci_real:section("network", "interface", n, options) then
331 elseif oldnet and oldnet:is_empty() then
334 for k, v in pairs(options) do
342 function get_network(self, n)
343 if n and _uci_real:get("network", n) == "interface" then
348 function get_networks(self)
352 _uci_real:foreach("network", "interface",
354 nls[s['.name']] = network(s['.name'])
358 for n in utl.kspairs(nls) do
359 nets[#nets+1] = nls[n]
365 function del_network(self, n)
366 local r = _uci_real:delete("network", n)
368 _uci_real:delete_all("network", "alias",
369 function(s) return (s.interface == n) end)
371 _uci_real:delete_all("network", "route",
372 function(s) return (s.interface == n) end)
374 _uci_real:delete_all("network", "route6",
375 function(s) return (s.interface == n) end)
377 _uci_real:foreach("wireless", "wifi-iface",
379 if s.network == n then
380 _uci_real:delete("wireless", s['.name'], "network")
387 function rename_network(self, old, new)
389 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
390 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
393 _uci_real:foreach("network", "alias",
395 if s.interface == old then
396 _uci_real:set("network", s['.name'], "interface", new)
400 _uci_real:foreach("network", "route",
402 if s.interface == old then
403 _uci_real:set("network", s['.name'], "interface", new)
407 _uci_real:foreach("network", "route6",
409 if s.interface == old then
410 _uci_real:set("network", s['.name'], "interface", new)
414 _uci_real:foreach("wireless", "wifi-iface",
416 if s.network == old then
417 _uci_real:set("wireless", s['.name'], "network", new)
421 _uci_real:delete("network", old)
427 function get_interface(self, i)
428 if _interfaces[i] or _wifi_iface(i) then
433 _uci_real:foreach("wireless", "wifi-iface",
436 num[s.device] = num[s.device] and num[s.device] + 1 or 1
437 if s['.name'] == i then
439 "%s.network%d" %{s.device, num[s.device] })
448 function get_interfaces(self)
455 -- find normal interfaces
456 _uci_real:foreach("network", "interface",
458 for iface in utl.imatch(s.ifname) do
459 if not _iface_ignore(iface) and not _wifi_iface(iface) then
461 nfs[iface] = interface(iface)
466 for iface in utl.kspairs(_interfaces) do
467 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
468 nfs[iface] = interface(iface)
472 -- find vlan interfaces
473 _uci_real:foreach("network", "switch_vlan",
479 local base = baseof[s.device]
481 if not s.device:match("^eth%d") then
483 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
485 base = l:match("^%w+: (%w+)")
488 if not base or not base:match("^eth%d") then
494 baseof[s.device] = base
497 local vid = tonumber(s.vid or s.vlan)
498 if vid ~= nil and vid >= 0 and vid <= 4095 then
499 local iface = "%s.%d" %{ base, vid }
500 if not seen[iface] then
502 nfs[iface] = interface(iface)
507 for iface in utl.kspairs(nfs) do
508 ifaces[#ifaces+1] = nfs[iface]
511 -- find wifi interfaces
514 _uci_real:foreach("wireless", "wifi-iface",
517 num[s.device] = num[s.device] and num[s.device] + 1 or 1
518 local i = "%s.network%d" %{ s.device, num[s.device] }
519 wfs[i] = interface(i)
523 for iface in utl.kspairs(wfs) do
524 ifaces[#ifaces+1] = wfs[iface]
530 function ignore_interface(self, x)
531 return _iface_ignore(x)
534 function get_wifidev(self, dev)
535 if _uci_real:get("wireless", dev) == "wifi-device" then
540 function get_wifidevs(self)
544 _uci_real:foreach("wireless", "wifi-device",
545 function(s) wfd[#wfd+1] = s['.name'] end)
548 for _, dev in utl.vspairs(wfd) do
549 devs[#devs+1] = wifidev(dev)
555 function get_wifinet(self, net)
556 local wnet = _wifi_lookup(net)
562 function add_wifinet(self, net, options)
563 if type(options) == "table" and options.device and
564 _uci_real:get("wireless", options.device) == "wifi-device"
566 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
571 function del_wifinet(self, net)
572 local wnet = _wifi_lookup(net)
574 _uci_real:delete("wireless", wnet)
581 function network(name, proto)
583 local p = proto or _uci_real:get("network", name, "proto")
584 local c = p and _protocols[p] or protocol
589 function protocol.__init__(self, name)
593 function protocol._get(self, opt)
594 local v = _uci_real:get("network", self.sid, opt)
595 if type(v) == "table" then
596 return table.concat(v, " ")
601 function protocol._ip(self, opt, family, list)
602 local ip = _uci_state:get("network", self.sid, opt)
603 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
607 for ip in utl.imatch(ip) do
609 if ip then l[#l+1] = ip:string() end
614 return ip and ip:string()
619 function protocol.get(self, opt)
620 return _get("network", self.sid, opt)
623 function protocol.set(self, opt, val)
624 return _set("network", self.sid, opt, val)
627 function protocol.ifname(self)
628 local p = self:proto()
629 if self:is_bridge() then
630 return "br-" .. self.sid
631 elseif self:is_virtual() then
632 return p .. "-" .. self.sid
635 local dev = _uci_real:get("network", self.sid, "ifname") or
636 _uci_state:get("network", self.sid, "ifname")
638 dev = (type(dev) == "table") and dev[1] or dev
639 dev = (dev ~= nil) and dev:match("%S+")
642 _uci_real:foreach("wireless", "wifi-iface",
645 num[s.device] = num[s.device]
646 and num[s.device] + 1 or 1
648 if s.network == self.sid then
649 dev = "%s.network%d" %{ s.device, num[s.device] }
660 function protocol.proto(self)
664 function protocol.get_i18n(self)
665 local p = self:proto()
667 return i18n.translate("Unmanaged")
668 elseif p == "static" then
669 return i18n.translate("Static address")
670 elseif p == "dhcp" then
671 return i18n.translate("DHCP client")
673 return i18n.translate("Unknown")
677 function protocol.type(self)
678 return self:_get("type")
681 function protocol.name(self)
685 function protocol.uptime(self)
686 local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
688 return nxo.sysinfo().uptime - cnt
694 function protocol.expires(self)
695 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
696 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
698 l = l - (nxo.sysinfo().uptime - a)
699 return l > 0 and l or 0
704 function protocol.metric(self)
705 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
708 function protocol.ipaddr(self)
709 return self:_ip("ipaddr", 4)
712 function protocol.netmask(self)
713 return self:_ip("netmask", 4)
716 function protocol.gwaddr(self)
717 return self:_ip("gateway", 4)
720 function protocol.dnsaddrs(self)
721 return self:_ip("dns", 4, true)
724 function protocol.ip6addr(self)
725 local ip6 = self:_ip("ip6addr", 6)
727 local ifc = _interfaces[self:ifname()]
728 if ifc and ifc.ip6addrs then
730 for _, a in ipairs(ifc.ip6addrs) do
731 if not a:is6linklocal() then
741 function protocol.gw6addr(self)
742 local ip6 = self:_ip("ip6gw", 6)
744 local dr6 = sys.net.defaultroute6()
745 if dr6 and dr6.device == self:ifname() then
746 return dr6.nexthop:string()
752 function protocol.dns6addrs(self)
753 return self:_ip("dns", 6, true)
756 function protocol.is_bridge(self)
757 return (not self:is_virtual() and self:type() == "bridge")
760 function protocol.opkg_package(self)
764 function protocol.is_installed(self)
768 function protocol.is_virtual(self)
772 function protocol.is_floating(self)
776 function protocol.is_empty(self)
777 if self:is_virtual() then
782 if (self:_get("ifname") or ""):match("%S+") then
786 _uci_real:foreach("wireless", "wifi-iface",
788 if s.network == self.sid then
798 function protocol.add_interface(self, ifname)
799 ifname = _M:ifnameof(ifname)
800 if ifname and not self:is_floating() then
801 -- remove the interface from all ifaces
802 _uci_real:foreach("network", "interface",
804 _filter("network", s['.name'], "ifname", ifname)
807 -- if its a wifi interface, change its network option
808 local wif = _wifi_lookup(ifname)
810 _uci_real:set("wireless", wif, "network", self.sid)
812 -- add iface to our iface list
814 _append("network", self.sid, "ifname", ifname)
819 function protocol.del_interface(self, ifname)
820 ifname = _M:ifnameof(ifname)
821 if ifname and not self:is_floating() then
822 -- if its a wireless interface, clear its network option
823 local wif = _wifi_lookup(ifname)
824 if wif then _uci_real:delete("wireless", wif, "network") end
826 -- remove the interface
827 _filter("network", self.sid, "ifname", ifname)
831 function protocol.get_interface(self)
832 if self:is_virtual() then
833 _tunnel[self:proto() .. "-" .. self.sid] = true
834 return interface(self:proto() .. "-" .. self.sid, self)
835 elseif self:is_bridge() then
836 _bridge["br-" .. self.sid] = true
837 return interface("br-" .. self.sid, self)
841 for ifn in utl.imatch(_uci_state:get("network", self.sid, "ifname")) do
842 ifn = ifn:match("^[^:/]+")
843 return ifn and interface(ifn, self)
846 _uci_state:foreach("wireless", "wifi-iface",
849 num[s.device] = num[s.device] and num[s.device] + 1 or 1
850 if s.network == self.sid then
851 ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] }
856 return ifn and interface(ifn, self)
860 function protocol.get_interfaces(self)
861 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
866 for ifn in utl.imatch(self:get("ifname")) do
867 ifn = ifn:match("^[^:/]+")
868 nfs[ifn] = interface(ifn, self)
871 for ifn in utl.kspairs(nfs) do
872 ifaces[#ifaces+1] = nfs[ifn]
877 _uci_real:foreach("wireless", "wifi-iface",
880 num[s.device] = num[s.device] and num[s.device] + 1 or 1
881 if s.network == self.sid then
882 ifn = "%s.network%d" %{ s.device, num[s.device] }
883 wfs[ifn] = interface(ifn, self)
888 for ifn in utl.kspairs(wfs) do
889 ifaces[#ifaces+1] = wfs[ifn]
896 function protocol.contains_interface(self, ifname)
897 ifname = _M:ifnameof(ifname)
900 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
902 elseif self:is_bridge() and "br-" .. self.sid == ifname then
906 for ifn in utl.imatch(self:get("ifname")) do
907 ifn = ifn:match("[^:]+")
908 if ifn == ifname then
913 local wif = _wifi_lookup(ifname)
915 return (_uci_real:get("wireless", wif, "network") == self.sid)
922 function protocol.adminlink(self)
923 return dsp.build_url("admin", "network", "network", self.sid)
927 interface = utl.class()
929 function interface.__init__(self, ifname, network)
930 local wif = _wifi_lookup(ifname)
931 if wif then self.wif = wifinet(wif) end
933 self.ifname = self.ifname or ifname
934 self.dev = _interfaces[self.ifname]
935 self.network = network
938 function interface.name(self)
939 return self.wif and self.wif:ifname() or self.ifname
942 function interface.mac(self)
943 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
946 function interface.ipaddrs(self)
947 return self.dev and self.dev.ipaddrs or { }
950 function interface.ip6addrs(self)
951 return self.dev and self.dev.ip6addrs or { }
954 function interface.type(self)
955 if self.wif or _wifi_iface(self.ifname) then
957 elseif _bridge[self.ifname] then
959 elseif _tunnel[self.ifname] then
961 elseif self.ifname:match("%.") then
963 elseif _switch[self.ifname] then
970 function interface.shortname(self)
973 self.wif:active_mode(),
974 self.wif:active_ssid() or self.wif:active_bssid()
981 function interface.get_i18n(self)
983 return "%s: %s %q" %{
984 i18n.translate("Wireless Network"),
985 self.wif:active_mode(),
986 self.wif:active_ssid() or self.wif:active_bssid()
989 return "%s: %q" %{ self:get_type_i18n(), self:name() }
993 function interface.get_type_i18n(self)
994 local x = self:type()
996 return i18n.translate("Wireless Adapter")
997 elseif x == "bridge" then
998 return i18n.translate("Bridge")
999 elseif x == "switch" then
1000 return i18n.translate("Ethernet Switch")
1001 elseif x == "vlan" then
1002 return i18n.translate("VLAN Interface")
1003 elseif x == "tunnel" then
1004 return i18n.translate("Tunnel Interface")
1006 return i18n.translate("Ethernet Adapter")
1010 function interface.adminlink(self)
1012 return self.wif:adminlink()
1016 function interface.ports(self)
1020 for _, iface in ipairs(self.br.ifnames) do
1021 ifaces[#ifaces+1] = interface(iface.name)
1027 function interface.bridge_id(self)
1035 function interface.bridge_stp(self)
1043 function interface.is_up(self)
1045 return self.wif:is_up()
1047 return self.dev and self.dev.flags and self.dev.flags.up or false
1051 function interface.is_bridge(self)
1052 return (self:type() == "bridge")
1055 function interface.is_bridgeport(self)
1056 return self.dev and self.dev.bridge and true or false
1059 function interface.tx_bytes(self)
1060 return self.dev and self.dev.stats
1061 and self.dev.stats.tx_bytes or 0
1064 function interface.rx_bytes(self)
1065 return self.dev and self.dev.stats
1066 and self.dev.stats.rx_bytes or 0
1069 function interface.tx_packets(self)
1070 return self.dev and self.dev.stats
1071 and self.dev.stats.tx_packets or 0
1074 function interface.rx_packets(self)
1075 return self.dev and self.dev.stats
1076 and self.dev.stats.rx_packets or 0
1079 function interface.get_network(self)
1080 if not self.network then
1081 if self.dev and self.dev.network then
1082 self.network = _M:get_network(self.dev.network)
1086 if not self.network then
1088 for _, net in ipairs(_M:get_networks()) do
1089 if net:contains_interface(self.ifname) or
1090 net:ifname() == self.ifname
1101 function interface.get_wifinet(self)
1106 wifidev = utl.class()
1108 function wifidev.__init__(self, dev)
1110 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1113 function wifidev.get(self, opt)
1114 return _get("wireless", self.sid, opt)
1117 function wifidev.set(self, opt, val)
1118 return _set("wireless", self.sid, opt, val)
1121 function wifidev.name(self)
1125 function wifidev.hwmodes(self)
1126 local l = self.iwinfo.hwmodelist
1127 if l and next(l) then
1130 return { b = true, g = true }
1134 function wifidev.get_i18n(self)
1136 if self.iwinfo.type == "wl" then
1138 elseif self.iwinfo.type == "madwifi" then
1143 local l = self:hwmodes()
1144 if l.a then m = m .. "a" end
1145 if l.b then m = m .. "b" end
1146 if l.g then m = m .. "g" end
1147 if l.n then m = m .. "n" end
1149 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1152 function wifidev.is_up(self)
1155 _uci_state:foreach("wireless", "wifi-iface",
1157 if s.device == self.sid then
1168 function wifidev.get_wifinet(self, net)
1169 if _uci_real:get("wireless", net) == "wifi-iface" then
1172 local wnet = _wifi_lookup(net)
1174 return wifinet(wnet)
1179 function wifidev.get_wifinets(self)
1182 _uci_real:foreach("wireless", "wifi-iface",
1184 if s.device == self.sid then
1185 nets[#nets+1] = wifinet(s['.name'])
1192 function wifidev.add_wifinet(self, options)
1193 options = options or { }
1194 options.device = self.sid
1196 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1198 return wifinet(wnet, options)
1202 function wifidev.del_wifinet(self, net)
1203 if utl.instanceof(net, wifinet) then
1205 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1206 net = _wifi_lookup(net)
1209 if net and _uci_real:get("wireless", net, "device") == self.sid then
1210 _uci_real:delete("wireless", net)
1218 wifinet = utl.class()
1220 function wifinet.__init__(self, net, data)
1225 _uci_real:foreach("wireless", "wifi-iface",
1228 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1229 if s['.name'] == self.sid then
1230 netid = "%s.network%d" %{ s.device, num[s.device] }
1236 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1240 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1241 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1242 _uci_real:get_all("wireless", self.sid) or { }
1245 function wifinet.get(self, opt)
1246 return _get("wireless", self.sid, opt)
1249 function wifinet.set(self, opt, val)
1250 return _set("wireless", self.sid, opt, val)
1253 function wifinet.mode(self)
1254 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1257 function wifinet.ssid(self)
1258 return _uci_state:get("wireless", self.sid, "ssid")
1261 function wifinet.bssid(self)
1262 return _uci_state:get("wireless", self.sid, "bssid")
1265 function wifinet.network(self)
1266 return _uci_state:get("wifinet", self.sid, "network")
1269 function wifinet.id(self)
1273 function wifinet.name(self)
1277 function wifinet.ifname(self)
1278 local ifname = self.iwinfo.ifname
1279 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1285 function wifinet.get_device(self)
1286 if self.iwdata.device then
1287 return wifidev(self.iwdata.device)
1291 function wifinet.is_up(self)
1292 return (self.iwdata.up == "1")
1295 function wifinet.active_mode(self)
1296 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1298 if m == "ap" then m = "Master"
1299 elseif m == "sta" then m = "Client"
1300 elseif m == "adhoc" then m = "Ad-Hoc"
1301 elseif m == "mesh" then m = "Mesh"
1302 elseif m == "monitor" then m = "Monitor"
1308 function wifinet.active_mode_i18n(self)
1309 return i18n.translate(self:active_mode())
1312 function wifinet.active_ssid(self)
1313 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1316 function wifinet.active_bssid(self)
1317 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1320 function wifinet.active_encryption(self)
1321 local enc = self.iwinfo and self.iwinfo.encryption
1322 return enc and enc.description or "-"
1325 function wifinet.assoclist(self)
1326 return self.iwinfo.assoclist or { }
1329 function wifinet.frequency(self)
1330 local freq = self.iwinfo.frequency
1331 if freq and freq > 0 then
1332 return "%.03f" % (freq / 1000)
1336 function wifinet.bitrate(self)
1337 local rate = self.iwinfo.bitrate
1338 if rate and rate > 0 then
1339 return (rate / 1000)
1343 function wifinet.channel(self)
1344 return self.iwinfo.channel or
1345 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1348 function wifinet.signal(self)
1349 return self.iwinfo.signal or 0
1352 function wifinet.noise(self)
1353 return self.iwinfo.noise or 0
1356 function wifinet.country(self)
1357 return self.iwinfo.country or "00"
1360 function wifinet.txpower(self)
1361 return self.iwinfo.txpower or 0
1364 function wifinet.signal_level(self, s, n)
1365 if self:active_bssid() ~= "00:00:00:00:00:00" then
1366 local signal = s or self:signal()
1367 local noise = n or self:noise()
1369 if signal < 0 and noise < 0 then
1370 local snr = -1 * (noise - signal)
1371 return math.floor(snr / 5)
1380 function wifinet.signal_percent(self)
1381 local qc = self.iwinfo.quality or 0
1382 local qm = self.iwinfo.quality_max or 0
1384 if qc > 0 and qm > 0 then
1385 return math.floor((100 / qm) * qc)
1391 function wifinet.shortname(self)
1393 i18n.translate(self:active_mode()),
1394 self:active_ssid() or self:active_bssid()
1398 function wifinet.get_i18n(self)
1399 return "%s: %s %q (%s)" %{
1400 i18n.translate("Wireless Network"),
1401 i18n.translate(self:active_mode()),
1402 self:active_ssid() or self:active_bssid(),
1407 function wifinet.adminlink(self)
1408 return dsp.build_url("admin", "network", "wireless", self.netid)
1411 function wifinet.get_network(self)
1412 if _uci_real:get("network", self.iwdata.network) == "interface" then
1413 return network(self.iwdata.network)
1417 function wifinet.get_interface(self)
1418 return interface(self:ifname())
1422 -- setup base protocols
1423 _M:register_protocol("static")
1424 _M:register_protocol("dhcp")
1425 _M:register_protocol("none")
1427 -- load protocol extensions
1428 local exts = nfs.dir(utl.libpath() .. "/model/network")
1432 if ext:match("%.lua$") then
1433 require("luci.model.network." .. ext:gsub("%.lua$", ""))