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.ifname or "%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)
930 if wif then self.wif = wifinet(wif) end
932 self.ifname = self.ifname or ifname
933 self.dev = _interfaces[self.ifname]
934 self.network = network
937 function interface.name(self)
938 return self.wif and self.wif:ifname() or self.ifname
941 function interface.mac(self)
942 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
945 function interface.ipaddrs(self)
946 return self.dev and self.dev.ipaddrs or { }
949 function interface.ip6addrs(self)
950 return self.dev and self.dev.ip6addrs or { }
953 function interface.type(self)
954 if self.wif or _wifi_iface(self.ifname) then
956 elseif _bridge[self.ifname] then
958 elseif _tunnel[self.ifname] then
960 elseif self.ifname:match("%.") then
962 elseif _switch[self.ifname] then
969 function interface.shortname(self)
972 self.wif:active_mode(),
973 self.wif:active_ssid() or self.wif:active_bssid()
980 function interface.get_i18n(self)
982 return "%s: %s %q" %{
983 i18n.translate("Wireless Network"),
984 self.wif:active_mode(),
985 self.wif:active_ssid() or self.wif:active_bssid()
988 return "%s: %q" %{ self:get_type_i18n(), self:name() }
992 function interface.get_type_i18n(self)
993 local x = self:type()
995 return i18n.translate("Wireless Adapter")
996 elseif x == "bridge" then
997 return i18n.translate("Bridge")
998 elseif x == "switch" then
999 return i18n.translate("Ethernet Switch")
1000 elseif x == "vlan" then
1001 return i18n.translate("VLAN Interface")
1002 elseif x == "tunnel" then
1003 return i18n.translate("Tunnel Interface")
1005 return i18n.translate("Ethernet Adapter")
1009 function interface.adminlink(self)
1011 return self.wif:adminlink()
1015 function interface.ports(self)
1019 for _, iface in ipairs(self.br.ifnames) do
1020 ifaces[#ifaces+1] = interface(iface.name)
1026 function interface.bridge_id(self)
1034 function interface.bridge_stp(self)
1042 function interface.is_up(self)
1044 return self.wif:is_up()
1046 return self.dev and self.dev.flags and self.dev.flags.up or false
1050 function interface.is_bridge(self)
1051 return (self:type() == "bridge")
1054 function interface.is_bridgeport(self)
1055 return self.dev and self.dev.bridge and true or false
1058 function interface.tx_bytes(self)
1059 return self.dev and self.dev.stats
1060 and self.dev.stats.tx_bytes or 0
1063 function interface.rx_bytes(self)
1064 return self.dev and self.dev.stats
1065 and self.dev.stats.rx_bytes or 0
1068 function interface.tx_packets(self)
1069 return self.dev and self.dev.stats
1070 and self.dev.stats.tx_packets or 0
1073 function interface.rx_packets(self)
1074 return self.dev and self.dev.stats
1075 and self.dev.stats.rx_packets or 0
1078 function interface.get_network(self)
1079 if not self.network then
1080 if self.dev and self.dev.network then
1081 self.network = _M:get_network(self.dev.network)
1085 if not self.network then
1087 for _, net in ipairs(_M:get_networks()) do
1088 if net:contains_interface(self.ifname) or
1089 net:ifname() == self.ifname
1100 function interface.get_wifinet(self)
1105 wifidev = utl.class()
1107 function wifidev.__init__(self, dev)
1109 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1112 function wifidev.get(self, opt)
1113 return _get("wireless", self.sid, opt)
1116 function wifidev.set(self, opt, val)
1117 return _set("wireless", self.sid, opt, val)
1120 function wifidev.name(self)
1124 function wifidev.hwmodes(self)
1125 local l = self.iwinfo.hwmodelist
1126 if l and next(l) then
1129 return { b = true, g = true }
1133 function wifidev.get_i18n(self)
1135 if self.iwinfo.type == "wl" then
1137 elseif self.iwinfo.type == "madwifi" then
1142 local l = self:hwmodes()
1143 if l.a then m = m .. "a" end
1144 if l.b then m = m .. "b" end
1145 if l.g then m = m .. "g" end
1146 if l.n then m = m .. "n" end
1148 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1151 function wifidev.is_up(self)
1154 _uci_state:foreach("wireless", "wifi-iface",
1156 if s.device == self.sid then
1167 function wifidev.get_wifinet(self, net)
1168 if _uci_real:get("wireless", net) == "wifi-iface" then
1171 local wnet = _wifi_lookup(net)
1173 return wifinet(wnet)
1178 function wifidev.get_wifinets(self)
1181 _uci_real:foreach("wireless", "wifi-iface",
1183 if s.device == self.sid then
1184 nets[#nets+1] = wifinet(s['.name'])
1191 function wifidev.add_wifinet(self, options)
1192 options = options or { }
1193 options.device = self.sid
1195 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1197 return wifinet(wnet, options)
1201 function wifidev.del_wifinet(self, net)
1202 if utl.instanceof(net, wifinet) then
1204 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1205 net = _wifi_lookup(net)
1208 if net and _uci_real:get("wireless", net, "device") == self.sid then
1209 _uci_real:delete("wireless", net)
1217 wifinet = utl.class()
1219 function wifinet.__init__(self, net, data)
1224 _uci_real:foreach("wireless", "wifi-iface",
1227 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1228 if s['.name'] == self.sid then
1229 netid = "%s.network%d" %{ s.device, num[s.device] }
1235 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1239 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1240 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1241 _uci_real:get_all("wireless", self.sid) or { }
1244 function wifinet.get(self, opt)
1245 return _get("wireless", self.sid, opt)
1248 function wifinet.set(self, opt, val)
1249 return _set("wireless", self.sid, opt, val)
1252 function wifinet.mode(self)
1253 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1256 function wifinet.ssid(self)
1257 return _uci_state:get("wireless", self.sid, "ssid")
1260 function wifinet.bssid(self)
1261 return _uci_state:get("wireless", self.sid, "bssid")
1264 function wifinet.network(self)
1265 return _uci_state:get("wifinet", self.sid, "network")
1268 function wifinet.id(self)
1272 function wifinet.name(self)
1276 function wifinet.ifname(self)
1277 local ifname = self.iwinfo.ifname
1278 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1284 function wifinet.get_device(self)
1285 if self.iwdata.device then
1286 return wifidev(self.iwdata.device)
1290 function wifinet.is_up(self)
1291 return (self.iwdata.up == "1")
1294 function wifinet.active_mode(self)
1295 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1297 if m == "ap" then m = "Master"
1298 elseif m == "sta" then m = "Client"
1299 elseif m == "adhoc" then m = "Ad-Hoc"
1300 elseif m == "mesh" then m = "Mesh"
1301 elseif m == "monitor" then m = "Monitor"
1307 function wifinet.active_mode_i18n(self)
1308 return i18n.translate(self:active_mode())
1311 function wifinet.active_ssid(self)
1312 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1315 function wifinet.active_bssid(self)
1316 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1319 function wifinet.active_encryption(self)
1320 local enc = self.iwinfo and self.iwinfo.encryption
1321 return enc and enc.description or "-"
1324 function wifinet.assoclist(self)
1325 return self.iwinfo.assoclist or { }
1328 function wifinet.frequency(self)
1329 local freq = self.iwinfo.frequency
1330 if freq and freq > 0 then
1331 return "%.03f" % (freq / 1000)
1335 function wifinet.bitrate(self)
1336 local rate = self.iwinfo.bitrate
1337 if rate and rate > 0 then
1338 return (rate / 1000)
1342 function wifinet.channel(self)
1343 return self.iwinfo.channel or
1344 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1347 function wifinet.signal(self)
1348 return self.iwinfo.signal or 0
1351 function wifinet.noise(self)
1352 return self.iwinfo.noise or 0
1355 function wifinet.country(self)
1356 return self.iwinfo.country or "00"
1359 function wifinet.txpower(self)
1360 return self.iwinfo.txpower or 0
1363 function wifinet.signal_level(self, s, n)
1364 if self:active_bssid() ~= "00:00:00:00:00:00" then
1365 local signal = s or self:signal()
1366 local noise = n or self:noise()
1368 if signal < 0 and noise < 0 then
1369 local snr = -1 * (noise - signal)
1370 return math.floor(snr / 5)
1379 function wifinet.signal_percent(self)
1380 local qc = self.iwinfo.quality or 0
1381 local qm = self.iwinfo.quality_max or 0
1383 if qc > 0 and qm > 0 then
1384 return math.floor((100 / qm) * qc)
1390 function wifinet.shortname(self)
1392 i18n.translate(self:active_mode()),
1393 self:active_ssid() or self:active_bssid()
1397 function wifinet.get_i18n(self)
1398 return "%s: %s %q (%s)" %{
1399 i18n.translate("Wireless Network"),
1400 i18n.translate(self:active_mode()),
1401 self:active_ssid() or self:active_bssid(),
1406 function wifinet.adminlink(self)
1407 return dsp.build_url("admin", "network", "wireless", self.netid)
1410 function wifinet.get_network(self)
1411 if _uci_real:get("network", self.iwdata.network) == "interface" then
1412 return network(self.iwdata.network)
1416 function wifinet.get_interface(self)
1417 return interface(self:ifname())
1421 -- setup base protocols
1422 _M:register_protocol("static")
1423 _M:register_protocol("dhcp")
1424 _M:register_protocol("none")
1426 -- load protocol extensions
1427 local exts = nfs.dir(utl.libpath() .. "/model/network")
1431 if ext:match("%.lua$") then
1432 require("luci.model.network." .. ext:gsub("%.lua$", ""))