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)
453 -- find normal interfaces
454 _uci_real:foreach("network", "interface",
456 for iface in utl.imatch(s.ifname) do
457 if not _iface_ignore(iface) and not _wifi_iface(iface) then
459 nfs[iface] = interface(iface)
464 for iface in utl.kspairs(_interfaces) do
465 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
466 nfs[iface] = interface(iface)
470 -- find vlan interfaces
471 _uci_real:foreach("network", "switch_vlan",
473 local base = s.device or "-"
474 if not base:match("^eth%d") then
478 local vid = tonumber(s.vid or s.vlan)
479 if vid ~= nil and vid >= 0 and vid <= 4095 then
480 local iface = "%s.%d" %{ base, vid }
481 if not seen[iface] then
483 nfs[iface] = interface(iface)
488 for iface in utl.kspairs(nfs) do
489 ifaces[#ifaces+1] = nfs[iface]
492 -- find wifi interfaces
495 _uci_real:foreach("wireless", "wifi-iface",
498 num[s.device] = num[s.device] and num[s.device] + 1 or 1
499 local i = "%s.network%d" %{ s.device, num[s.device] }
500 wfs[i] = interface(i)
504 for iface in utl.kspairs(wfs) do
505 ifaces[#ifaces+1] = wfs[iface]
511 function ignore_interface(self, x)
512 return _iface_ignore(x)
515 function get_wifidev(self, dev)
516 if _uci_real:get("wireless", dev) == "wifi-device" then
521 function get_wifidevs(self)
525 _uci_real:foreach("wireless", "wifi-device",
526 function(s) wfd[#wfd+1] = s['.name'] end)
529 for _, dev in utl.vspairs(wfd) do
530 devs[#devs+1] = wifidev(dev)
536 function get_wifinet(self, net)
537 local wnet = _wifi_lookup(net)
543 function add_wifinet(self, net, options)
544 if type(options) == "table" and options.device and
545 _uci_real:get("wireless", options.device) == "wifi-device"
547 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
552 function del_wifinet(self, net)
553 local wnet = _wifi_lookup(net)
555 _uci_real:delete("wireless", wnet)
562 function network(name, proto)
564 local p = proto or _uci_real:get("network", name, "proto")
565 local c = p and _protocols[p] or protocol
570 function protocol.__init__(self, name)
574 function protocol._get(self, opt)
575 local v = _uci_real:get("network", self.sid, opt)
576 if type(v) == "table" then
577 return table.concat(v, " ")
582 function protocol._ip(self, opt, family, list)
583 local ip = _uci_state:get("network", self.sid, opt)
584 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
588 for ip in utl.imatch(ip) do
590 if ip then l[#l+1] = ip:string() end
595 return ip and ip:string()
600 function protocol.get(self, opt)
601 return _get("network", self.sid, opt)
604 function protocol.set(self, opt, val)
605 return _set("network", self.sid, opt, val)
608 function protocol.ifname(self)
609 local p = self:proto()
610 if self:is_bridge() then
611 return "br-" .. self.sid
612 elseif self:is_virtual() then
613 return p .. "-" .. self.sid
616 local dev = _uci_real:get("network", self.sid, "ifname") or
617 _uci_state:get("network", self.sid, "ifname")
619 dev = (type(dev) == "table") and dev[1] or dev
620 dev = (dev ~= nil) and dev:match("%S+")
623 _uci_real:foreach("wireless", "wifi-iface",
626 num[s.device] = num[s.device]
627 and num[s.device] + 1 or 1
629 if s.network == self.sid then
630 dev = "%s.network%d" %{ s.device, num[s.device] }
641 function protocol.proto(self)
645 function protocol.get_i18n(self)
646 local p = self:proto()
648 return i18n.translate("Unmanaged")
649 elseif p == "static" then
650 return i18n.translate("Static address")
651 elseif p == "dhcp" then
652 return i18n.translate("DHCP client")
654 return i18n.translate("Unknown")
658 function protocol.type(self)
659 return self:_get("type")
662 function protocol.name(self)
666 function protocol.uptime(self)
667 local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
669 return nxo.sysinfo().uptime - cnt
675 function protocol.expires(self)
676 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
677 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
679 l = l - (nxo.sysinfo().uptime - a)
680 return l > 0 and l or 0
685 function protocol.metric(self)
686 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
689 function protocol.ipaddr(self)
690 return self:_ip("ipaddr", 4)
693 function protocol.netmask(self)
694 return self:_ip("netmask", 4)
697 function protocol.gwaddr(self)
698 return self:_ip("gateway", 4)
701 function protocol.dnsaddrs(self)
702 return self:_ip("dns", 4, true)
705 function protocol.ip6addr(self)
706 local ip6 = self:_ip("ip6addr", 6)
708 local ifc = _interfaces[self:ifname()]
709 if ifc and ifc.ip6addrs then
711 for _, a in ipairs(ifc.ip6addrs) do
712 if not a:is6linklocal() then
722 function protocol.gw6addr(self)
723 local ip6 = self:_ip("ip6gw", 6)
725 local dr6 = sys.net.defaultroute6()
726 if dr6 and dr6.device == self:ifname() then
727 return dr6.nexthop:string()
733 function protocol.dns6addrs(self)
734 return self:_ip("dns", 6, true)
737 function protocol.is_bridge(self)
738 return (not self:is_virtual() and self:type() == "bridge")
741 function protocol.opkg_package(self)
745 function protocol.is_installed(self)
749 function protocol.is_virtual(self)
753 function protocol.is_floating(self)
757 function protocol.is_empty(self)
758 if self:is_virtual() then
763 if (self:_get("ifname") or ""):match("%S+") then
767 _uci_real:foreach("wireless", "wifi-iface",
769 if s.network == self.sid then
779 function protocol.add_interface(self, ifname)
780 ifname = _M:ifnameof(ifname)
781 if ifname and not self:is_floating() then
782 -- remove the interface from all ifaces
783 _uci_real:foreach("network", "interface",
785 _filter("network", s['.name'], "ifname", ifname)
788 -- if its a wifi interface, change its network option
789 local wif = _wifi_lookup(ifname)
791 _uci_real:set("wireless", wif, "network", self.sid)
793 -- add iface to our iface list
795 _append("network", self.sid, "ifname", ifname)
800 function protocol.del_interface(self, ifname)
801 ifname = _M:ifnameof(ifname)
802 if ifname and not self:is_floating() then
803 -- if its a wireless interface, clear its network option
804 local wif = _wifi_lookup(ifname)
805 if wif then _uci_real:delete("wireless", wif, "network") end
807 -- remove the interface
808 _filter("network", self.sid, "ifname", ifname)
812 function protocol.get_interface(self)
813 if self:is_virtual() then
814 _tunnel[self:proto() .. "-" .. self.sid] = true
815 return interface(self:proto() .. "-" .. self.sid, self)
816 elseif self:is_bridge() then
817 _bridge["br-" .. self.sid] = true
818 return interface("br-" .. self.sid, self)
822 for ifn in utl.imatch(_uci_state:get("network", self.sid, "ifname")) do
823 ifn = ifn:match("^[^:/]+")
824 return ifn and interface(ifn, self)
827 _uci_state:foreach("wireless", "wifi-iface",
830 num[s.device] = num[s.device] and num[s.device] + 1 or 1
831 if s.network == self.sid then
832 ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] }
837 return ifn and interface(ifn, self)
841 function protocol.get_interfaces(self)
842 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
847 for ifn in utl.imatch(self:get("ifname")) do
848 ifn = ifn:match("^[^:/]+")
849 nfs[ifn] = interface(ifn, self)
852 for ifn in utl.kspairs(nfs) do
853 ifaces[#ifaces+1] = nfs[ifn]
858 _uci_real:foreach("wireless", "wifi-iface",
861 num[s.device] = num[s.device] and num[s.device] + 1 or 1
862 if s.network == self.sid then
863 ifn = "%s.network%d" %{ s.device, num[s.device] }
864 wfs[ifn] = interface(ifn, self)
869 for ifn in utl.kspairs(wfs) do
870 ifaces[#ifaces+1] = wfs[ifn]
877 function protocol.contains_interface(self, ifname)
878 ifname = _M:ifnameof(ifname)
881 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
883 elseif self:is_bridge() and "br-" .. self.sid == ifname then
887 for ifn in utl.imatch(self:get("ifname")) do
888 ifn = ifn:match("[^:]+")
889 if ifn == ifname then
894 local wif = _wifi_lookup(ifname)
896 return (_uci_real:get("wireless", wif, "network") == self.sid)
903 function protocol.adminlink(self)
904 return dsp.build_url("admin", "network", "network", self.sid)
908 interface = utl.class()
910 function interface.__init__(self, ifname, network)
911 local wif = _wifi_lookup(ifname)
912 if wif then self.wif = wifinet(wif) end
914 self.ifname = self.ifname or ifname
915 self.dev = _interfaces[self.ifname]
916 self.network = network
919 function interface.name(self)
920 return self.wif and self.wif:ifname() or self.ifname
923 function interface.mac(self)
924 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
927 function interface.ipaddrs(self)
928 return self.dev and self.dev.ipaddrs or { }
931 function interface.ip6addrs(self)
932 return self.dev and self.dev.ip6addrs or { }
935 function interface.type(self)
936 if self.wif or _wifi_iface(self.ifname) then
938 elseif _bridge[self.ifname] then
940 elseif _tunnel[self.ifname] then
942 elseif self.ifname:match("%.") then
944 elseif _switch[self.ifname] then
951 function interface.shortname(self)
954 self.wif:active_mode(),
955 self.wif:active_ssid() or self.wif:active_bssid()
962 function interface.get_i18n(self)
964 return "%s: %s %q" %{
965 i18n.translate("Wireless Network"),
966 self.wif:active_mode(),
967 self.wif:active_ssid() or self.wif:active_bssid()
970 return "%s: %q" %{ self:get_type_i18n(), self:name() }
974 function interface.get_type_i18n(self)
975 local x = self:type()
977 return i18n.translate("Wireless Adapter")
978 elseif x == "bridge" then
979 return i18n.translate("Bridge")
980 elseif x == "switch" then
981 return i18n.translate("Ethernet Switch")
982 elseif x == "vlan" then
983 return i18n.translate("VLAN Interface")
984 elseif x == "tunnel" then
985 return i18n.translate("Tunnel Interface")
987 return i18n.translate("Ethernet Adapter")
991 function interface.adminlink(self)
993 return self.wif:adminlink()
997 function interface.ports(self)
1001 for _, iface in ipairs(self.br.ifnames) do
1002 ifaces[#ifaces+1] = interface(iface.name)
1008 function interface.bridge_id(self)
1016 function interface.bridge_stp(self)
1024 function interface.is_up(self)
1026 return self.wif:is_up()
1028 return self.dev and self.dev.flags and self.dev.flags.up or false
1032 function interface.is_bridge(self)
1033 return (self:type() == "bridge")
1036 function interface.is_bridgeport(self)
1037 return self.dev and self.dev.bridge and true or false
1040 function interface.tx_bytes(self)
1041 return self.dev and self.dev.stats
1042 and self.dev.stats.tx_bytes or 0
1045 function interface.rx_bytes(self)
1046 return self.dev and self.dev.stats
1047 and self.dev.stats.rx_bytes or 0
1050 function interface.tx_packets(self)
1051 return self.dev and self.dev.stats
1052 and self.dev.stats.tx_packets or 0
1055 function interface.rx_packets(self)
1056 return self.dev and self.dev.stats
1057 and self.dev.stats.rx_packets or 0
1060 function interface.get_network(self)
1061 if not self.network then
1062 if self.dev and self.dev.network then
1063 self.network = _M:get_network(self.dev.network)
1067 if not self.network then
1069 for _, net in ipairs(_M:get_networks()) do
1070 if net:contains_interface(self.ifname) or
1071 net:ifname() == self.ifname
1082 function interface.get_wifinet(self)
1087 wifidev = utl.class()
1089 function wifidev.__init__(self, dev)
1091 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1094 function wifidev.get(self, opt)
1095 return _get("wireless", self.sid, opt)
1098 function wifidev.set(self, opt, val)
1099 return _set("wireless", self.sid, opt, val)
1102 function wifidev.name(self)
1106 function wifidev.hwmodes(self)
1107 local l = self.iwinfo.hwmodelist
1108 if l and next(l) then
1111 return { b = true, g = true }
1115 function wifidev.get_i18n(self)
1117 if self.iwinfo.type == "wl" then
1119 elseif self.iwinfo.type == "madwifi" then
1124 local l = self:hwmodes()
1125 if l.a then m = m .. "a" end
1126 if l.b then m = m .. "b" end
1127 if l.g then m = m .. "g" end
1128 if l.n then m = m .. "n" end
1130 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1133 function wifidev.is_up(self)
1136 _uci_state:foreach("wireless", "wifi-iface",
1138 if s.device == self.sid then
1149 function wifidev.get_wifinet(self, net)
1150 if _uci_real:get("wireless", net) == "wifi-iface" then
1153 local wnet = _wifi_lookup(net)
1155 return wifinet(wnet)
1160 function wifidev.get_wifinets(self)
1163 _uci_real:foreach("wireless", "wifi-iface",
1165 if s.device == self.sid then
1166 nets[#nets+1] = wifinet(s['.name'])
1173 function wifidev.add_wifinet(self, options)
1174 options = options or { }
1175 options.device = self.sid
1177 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1179 return wifinet(wnet, options)
1183 function wifidev.del_wifinet(self, net)
1184 if utl.instanceof(net, wifinet) then
1186 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1187 net = _wifi_lookup(net)
1190 if net and _uci_real:get("wireless", net, "device") == self.sid then
1191 _uci_real:delete("wireless", net)
1199 wifinet = utl.class()
1201 function wifinet.__init__(self, net, data)
1206 _uci_real:foreach("wireless", "wifi-iface",
1209 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1210 if s['.name'] == self.sid then
1211 netid = "%s.network%d" %{ s.device, num[s.device] }
1217 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1221 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1222 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1223 _uci_real:get_all("wireless", self.sid) or { }
1226 function wifinet.get(self, opt)
1227 return _get("wireless", self.sid, opt)
1230 function wifinet.set(self, opt, val)
1231 return _set("wireless", self.sid, opt, val)
1234 function wifinet.mode(self)
1235 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1238 function wifinet.ssid(self)
1239 return _uci_state:get("wireless", self.sid, "ssid")
1242 function wifinet.bssid(self)
1243 return _uci_state:get("wireless", self.sid, "bssid")
1246 function wifinet.network(self)
1247 return _uci_state:get("wifinet", self.sid, "network")
1250 function wifinet.id(self)
1254 function wifinet.name(self)
1258 function wifinet.ifname(self)
1259 local ifname = self.iwinfo.ifname
1260 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1266 function wifinet.get_device(self)
1267 if self.iwdata.device then
1268 return wifidev(self.iwdata.device)
1272 function wifinet.is_up(self)
1273 return (self.iwdata.up == "1")
1276 function wifinet.active_mode(self)
1277 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1279 if m == "ap" then m = "Master"
1280 elseif m == "sta" then m = "Client"
1281 elseif m == "adhoc" then m = "Ad-Hoc"
1282 elseif m == "mesh" then m = "Mesh"
1283 elseif m == "monitor" then m = "Monitor"
1289 function wifinet.active_mode_i18n(self)
1290 return i18n.translate(self:active_mode())
1293 function wifinet.active_ssid(self)
1294 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1297 function wifinet.active_bssid(self)
1298 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1301 function wifinet.active_encryption(self)
1302 local enc = self.iwinfo and self.iwinfo.encryption
1303 return enc and enc.description or "-"
1306 function wifinet.assoclist(self)
1307 return self.iwinfo.assoclist or { }
1310 function wifinet.frequency(self)
1311 local freq = self.iwinfo.frequency
1312 if freq and freq > 0 then
1313 return "%.03f" % (freq / 1000)
1317 function wifinet.bitrate(self)
1318 local rate = self.iwinfo.bitrate
1319 if rate and rate > 0 then
1320 return (rate / 1000)
1324 function wifinet.channel(self)
1325 return self.iwinfo.channel or
1326 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1329 function wifinet.signal(self)
1330 return self.iwinfo.signal or 0
1333 function wifinet.noise(self)
1334 return self.iwinfo.noise or 0
1337 function wifinet.country(self)
1338 return self.iwinfo.country or "00"
1341 function wifinet.txpower(self)
1342 return self.iwinfo.txpower or 0
1345 function wifinet.signal_level(self, s, n)
1346 if self:active_bssid() ~= "00:00:00:00:00:00" then
1347 local signal = s or self:signal()
1348 local noise = n or self:noise()
1350 if signal < 0 and noise < 0 then
1351 local snr = -1 * (noise - signal)
1352 return math.floor(snr / 5)
1361 function wifinet.signal_percent(self)
1362 local qc = self.iwinfo.quality or 0
1363 local qm = self.iwinfo.quality_max or 0
1365 if qc > 0 and qm > 0 then
1366 return math.floor((100 / qm) * qc)
1372 function wifinet.shortname(self)
1374 i18n.translate(self:active_mode()),
1375 self:active_ssid() or self:active_bssid()
1379 function wifinet.get_i18n(self)
1380 return "%s: %s %q (%s)" %{
1381 i18n.translate("Wireless Network"),
1382 i18n.translate(self:active_mode()),
1383 self:active_ssid() or self:active_bssid(),
1388 function wifinet.adminlink(self)
1389 return dsp.build_url("admin", "network", "wireless", self.netid)
1392 function wifinet.get_network(self)
1393 if _uci_real:get("network", self.iwdata.network) == "interface" then
1394 return network(self.iwdata.network)
1398 function wifinet.get_interface(self)
1399 return interface(self:ifname())
1403 -- setup base protocols
1404 _M:register_protocol("static")
1405 _M:register_protocol("dhcp")
1406 _M:register_protocol("none")
1408 -- load protocol extensions
1409 local exts = nfs.dir(utl.libpath() .. "/model/network")
1413 if ext:match("%.lua$") then
1414 require("luci.model.network." .. ext:gsub("%.lua$", ""))