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_protocols(self)
285 for _, v in ipairs(_protocols) do
286 p[#p+1] = v("__dummy__")
291 function register_protocol(self, protoname)
292 local proto = utl.class(protocol)
294 function proto.__init__(self, name)
298 function proto.proto(self)
302 _protocols[#_protocols+1] = proto
303 _protocols[protoname] = proto
308 function register_pattern_virtual(self, pat)
309 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
313 function has_ipv6(self)
314 return nfs.access("/proc/net/ipv6_route")
317 function add_network(self, n, options)
318 local oldnet = self:get_network(n)
319 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
320 if _uci_real:section("network", "interface", n, options) then
323 elseif oldnet and oldnet:is_empty() then
326 for k, v in pairs(options) do
334 function get_network(self, n)
335 if n and _uci_real:get("network", n) == "interface" then
340 function get_networks(self)
344 _uci_real:foreach("network", "interface",
346 nls[s['.name']] = network(s['.name'])
350 for n in utl.kspairs(nls) do
351 nets[#nets+1] = nls[n]
357 function del_network(self, n)
358 local r = _uci_real:delete("network", n)
360 _uci_real:delete_all("network", "alias",
361 function(s) return (s.interface == n) end)
363 _uci_real:delete_all("network", "route",
364 function(s) return (s.interface == n) end)
366 _uci_real:delete_all("network", "route6",
367 function(s) return (s.interface == n) end)
369 _uci_real:foreach("wireless", "wifi-iface",
371 if s.network == n then
372 _uci_real:delete("wireless", s['.name'], "network")
379 function rename_network(self, old, new)
381 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
382 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
385 _uci_real:foreach("network", "alias",
387 if s.interface == old then
388 _uci_real:set("network", s['.name'], "interface", new)
392 _uci_real:foreach("network", "route",
394 if s.interface == old then
395 _uci_real:set("network", s['.name'], "interface", new)
399 _uci_real:foreach("network", "route6",
401 if s.interface == old then
402 _uci_real:set("network", s['.name'], "interface", new)
406 _uci_real:foreach("wireless", "wifi-iface",
408 if s.network == old then
409 _uci_real:set("wireless", s['.name'], "network", new)
413 _uci_real:delete("network", old)
419 function get_interface(self, i)
420 if _interfaces[i] or _wifi_iface(i) then
425 _uci_real:foreach("wireless", "wifi-iface",
428 num[s.device] = num[s.device] and num[s.device] + 1 or 1
429 if s['.name'] == i then
431 "%s.network%d" %{s.device, num[s.device] })
440 function get_interfaces(self)
446 -- find normal interfaces
447 _uci_real:foreach("network", "interface",
449 for iface in utl.imatch(s.ifname) do
450 if not _iface_ignore(iface) and not _wifi_iface(iface) then
452 nfs[iface] = interface(iface)
457 for iface in utl.kspairs(_interfaces) do
458 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
459 nfs[iface] = interface(iface)
463 -- find vlan interfaces
464 _uci_real:foreach("network", "switch_vlan",
466 local base = s.device or "-"
467 if not base:match("^eth%d") then
471 local vid = tonumber(s.vid or s.vlan)
472 if vid ~= nil and vid >= 0 and vid <= 4095 then
473 local iface = "%s.%d" %{ base, vid }
474 if not seen[iface] then
476 nfs[iface] = interface(iface)
481 for iface in utl.kspairs(nfs) do
482 ifaces[#ifaces+1] = nfs[iface]
485 -- find wifi interfaces
488 _uci_real:foreach("wireless", "wifi-iface",
491 num[s.device] = num[s.device] and num[s.device] + 1 or 1
492 local i = "%s.network%d" %{ s.device, num[s.device] }
493 wfs[i] = interface(i)
497 for iface in utl.kspairs(wfs) do
498 ifaces[#ifaces+1] = wfs[iface]
504 function ignore_interface(self, x)
505 return _iface_ignore(x)
508 function get_wifidev(self, dev)
509 if _uci_real:get("wireless", dev) == "wifi-device" then
514 function get_wifidevs(self)
518 _uci_real:foreach("wireless", "wifi-device",
519 function(s) wfd[#wfd+1] = s['.name'] end)
522 for _, dev in utl.vspairs(wfd) do
523 devs[#devs+1] = wifidev(dev)
529 function get_wifinet(self, net)
530 local wnet = _wifi_lookup(net)
536 function add_wifinet(self, net, options)
537 if type(options) == "table" and options.device and
538 _uci_real:get("wireless", options.device) == "wifi-device"
540 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
545 function del_wifinet(self, net)
546 local wnet = _wifi_lookup(net)
548 _uci_real:delete("wireless", wnet)
555 function network(name, proto)
557 local p = proto or _uci_real:get("network", name, "proto")
558 local c = p and _protocols[p] or protocol
563 function protocol.__init__(self, name)
567 function protocol._get(self, opt)
568 local v = _uci_real:get("network", self.sid, opt)
569 if type(v) == "table" then
570 return table.concat(v, " ")
575 function protocol._ip(self, opt, family, list)
576 local ip = _uci_state:get("network", self.sid, opt)
577 local fc = (family == 6) and ipc.IPv6 or ipc.IPv4
581 for ip in utl.imatch(ip) do
583 if ip then l[#l+1] = ip:string() end
588 return ip and ip:string()
593 function protocol.get(self, opt)
594 return _get("network", self.sid, opt)
597 function protocol.set(self, opt, val)
598 return _set("network", self.sid, opt, val)
601 function protocol.ifname(self)
602 local p = self:proto()
603 if self:is_bridge() then
604 return "br-" .. self.sid
605 elseif self:is_virtual() then
606 return p .. "-" .. self.sid
609 local dev = _uci_real:get("network", self.sid, "ifname") or
610 _uci_state:get("network", self.sid, "ifname")
612 dev = (type(dev) == "table") and dev[1] or dev
613 dev = (dev ~= nil) and dev:match("%S+")
616 _uci_real:foreach("wireless", "wifi-iface",
619 num[s.device] = num[s.device]
620 and num[s.device] + 1 or 1
622 if s.network == self.sid then
623 dev = "%s.network%d" %{ s.device, num[s.device] }
634 function protocol.proto(self)
638 function protocol.get_i18n(self)
639 local p = self:proto()
641 return i18n.translate("Unmanaged")
642 elseif p == "static" then
643 return i18n.translate("Static address")
644 elseif p == "dhcp" then
645 return i18n.translate("DHCP client")
647 return i18n.translate("Unknown")
651 function protocol.type(self)
652 return self:_get("type")
655 function protocol.name(self)
659 function protocol.uptime(self)
660 local cnt = tonumber(_uci_state:get("network", self.sid, "connect_time"))
662 return nxo.sysinfo().uptime - cnt
668 function protocol.expires(self)
669 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
670 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
672 l = l - (nxo.sysinfo().uptime - a)
673 return l > 0 and l or 0
678 function protocol.metric(self)
679 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
682 function protocol.ipaddr(self)
683 return self:_ip("ipaddr", 4)
686 function protocol.netmask(self)
687 return self:_ip("netmask", 4)
690 function protocol.gwaddr(self)
691 return self:_ip("gateway", 4)
694 function protocol.dnsaddrs(self)
695 return self:_ip("dns", 4, true)
698 function protocol.ip6addr(self)
699 local ip6 = self:_ip("ip6addr", 6)
701 local ifc = _interfaces[self:ifname()]
702 if ifc and ifc.ip6addrs then
704 for _, a in ipairs(ifc.ip6addrs) do
705 if not a:is6linklocal() then
715 function protocol.gw6addr(self)
716 local ip6 = self:_ip("ip6gw", 6)
718 local dr6 = sys.net.defaultroute6()
719 if dr6 and dr6.device == self:ifname() then
720 return dr6.nexthop:string()
726 function protocol.dns6addrs(self)
727 return self:_ip("dns", 6, true)
730 function protocol.is_bridge(self)
731 return (not self:is_virtual() and self:type() == "bridge")
734 function protocol.opkg_package(self)
738 function protocol.is_installed(self)
742 function protocol.is_virtual(self)
746 function protocol.is_floating(self)
750 function protocol.is_empty(self)
751 if self:is_virtual() then
756 if (self:_get("ifname") or ""):match("%S+") then
760 _uci_real:foreach("wireless", "wifi-iface",
762 if s.network == self.sid then
772 function protocol.add_interface(self, ifname)
773 ifname = _M:ifnameof(ifname)
774 if ifname and not self:is_floating() then
775 -- remove the interface from all ifaces
776 _uci_real:foreach("network", "interface",
778 _filter("network", s['.name'], "ifname", ifname)
781 -- if its a wifi interface, change its network option
782 local wif = _wifi_lookup(ifname)
784 _uci_real:set("wireless", wif, "network", self.sid)
786 -- add iface to our iface list
788 _append("network", self.sid, "ifname", ifname)
793 function protocol.del_interface(self, ifname)
794 ifname = _M:ifnameof(ifname)
795 if ifname and not self:is_floating() then
796 -- if its a wireless interface, clear its network option
797 local wif = _wifi_lookup(ifname)
798 if wif then _uci_real:delete("wireless", wif, "network") end
800 -- remove the interface
801 _filter("network", self.sid, "ifname", ifname)
805 function protocol.get_interface(self)
806 if self:is_virtual() then
807 _tunnel[self:proto() .. "-" .. self.sid] = true
808 return interface(self:proto() .. "-" .. self.sid, self)
809 elseif self:is_bridge() then
810 _bridge["br-" .. self.sid] = true
811 return interface("br-" .. self.sid, self)
815 for ifn in utl.imatch(_uci_state:get("network", self.sid, "ifname")) do
816 ifn = ifn:match("^[^:/]+")
817 return ifn and interface(ifn, self)
820 _uci_state:foreach("wireless", "wifi-iface",
823 num[s.device] = num[s.device] and num[s.device] + 1 or 1
824 if s.network == self.sid then
825 ifn = s.ifname or "%s.network%d" %{ s.device, num[s.device] }
830 return ifn and interface(ifn, self)
834 function protocol.get_interfaces(self)
835 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
840 for ifn in utl.imatch(self:get("ifname")) do
841 ifn = ifn:match("^[^:/]+")
842 nfs[ifn] = interface(ifn, self)
845 for ifn in utl.kspairs(nfs) do
846 ifaces[#ifaces+1] = nfs[ifn]
851 _uci_real:foreach("wireless", "wifi-iface",
854 num[s.device] = num[s.device] and num[s.device] + 1 or 1
855 if s.network == self.sid then
856 ifn = "%s.network%d" %{ s.device, num[s.device] }
857 wfs[ifn] = interface(ifn, self)
862 for ifn in utl.kspairs(wfs) do
863 ifaces[#ifaces+1] = wfs[ifn]
870 function protocol.contains_interface(self, ifname)
871 ifname = _M:ifnameof(ifname)
874 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
876 elseif self:is_bridge() and "br-" .. self.sid == ifname then
880 for ifn in utl.imatch(self:get("ifname")) do
881 ifn = ifn:match("[^:]+")
882 if ifn == ifname then
887 local wif = _wifi_lookup(ifname)
889 return (_uci_real:get("wireless", wif, "network") == self.sid)
896 function protocol.adminlink(self)
897 return dsp.build_url("admin", "network", "network", self.sid)
901 interface = utl.class()
903 function interface.__init__(self, ifname, network)
904 local wif = _wifi_lookup(ifname)
905 if wif then self.wif = wifinet(wif) end
907 self.ifname = self.ifname or ifname
908 self.dev = _interfaces[self.ifname]
909 self.network = network
912 function interface.name(self)
913 return self.wif and self.wif:ifname() or self.ifname
916 function interface.mac(self)
917 return (self.dev and self.dev.macaddr or "00:00:00:00:00:00"):upper()
920 function interface.ipaddrs(self)
921 return self.dev and self.dev.ipaddrs or { }
924 function interface.ip6addrs(self)
925 return self.dev and self.dev.ip6addrs or { }
928 function interface.type(self)
929 if self.wif or _wifi_iface(self.ifname) then
931 elseif _bridge[self.ifname] then
933 elseif _tunnel[self.ifname] then
935 elseif self.ifname:match("%.") then
937 elseif _switch[self.ifname] then
944 function interface.shortname(self)
947 self.wif:active_mode(),
948 self.wif:active_ssid() or self.wif:active_bssid()
955 function interface.get_i18n(self)
957 return "%s: %s %q" %{
958 i18n.translate("Wireless Network"),
959 self.wif:active_mode(),
960 self.wif:active_ssid() or self.wif:active_bssid()
963 return "%s: %q" %{ self:get_type_i18n(), self:name() }
967 function interface.get_type_i18n(self)
968 local x = self:type()
970 return i18n.translate("Wireless Adapter")
971 elseif x == "bridge" then
972 return i18n.translate("Bridge")
973 elseif x == "switch" then
974 return i18n.translate("Ethernet Switch")
975 elseif x == "vlan" then
976 return i18n.translate("VLAN Interface")
977 elseif x == "tunnel" then
978 return i18n.translate("Tunnel Interface")
980 return i18n.translate("Ethernet Adapter")
984 function interface.adminlink(self)
986 return self.wif:adminlink()
990 function interface.ports(self)
994 for _, iface in ipairs(self.br.ifnames) do
995 ifaces[#ifaces+1] = interface(iface.name)
1001 function interface.bridge_id(self)
1009 function interface.bridge_stp(self)
1017 function interface.is_up(self)
1019 return self.wif:is_up()
1021 return self.dev and self.dev.flags and self.dev.flags.up or false
1025 function interface.is_bridge(self)
1026 return (self:type() == "bridge")
1029 function interface.is_bridgeport(self)
1030 return self.dev and self.dev.bridge and true or false
1033 function interface.tx_bytes(self)
1034 return self.dev and self.dev.stats
1035 and self.dev.stats.tx_bytes or 0
1038 function interface.rx_bytes(self)
1039 return self.dev and self.dev.stats
1040 and self.dev.stats.rx_bytes or 0
1043 function interface.tx_packets(self)
1044 return self.dev and self.dev.stats
1045 and self.dev.stats.tx_packets or 0
1048 function interface.rx_packets(self)
1049 return self.dev and self.dev.stats
1050 and self.dev.stats.rx_packets or 0
1053 function interface.get_network(self)
1054 if not self.network then
1055 if self.dev and self.dev.network then
1056 self.network = _M:get_network(self.dev.network)
1060 if not self.network then
1062 for _, net in ipairs(_M:get_networks()) do
1063 if net:contains_interface(self.ifname) or
1064 net:ifname() == self.ifname
1075 function interface.get_wifinet(self)
1080 wifidev = utl.class()
1082 function wifidev.__init__(self, dev)
1084 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1087 function wifidev.get(self, opt)
1088 return _get("wireless", self.sid, opt)
1091 function wifidev.set(self, opt, val)
1092 return _set("wireless", self.sid, opt, val)
1095 function wifidev.name(self)
1099 function wifidev.hwmodes(self)
1100 local l = self.iwinfo.hwmodelist
1101 if l and next(l) then
1104 return { b = true, g = true }
1108 function wifidev.get_i18n(self)
1110 if self.iwinfo.type == "wl" then
1112 elseif self.iwinfo.type == "madwifi" then
1117 local l = self:hwmodes()
1118 if l.a then m = m .. "a" end
1119 if l.b then m = m .. "b" end
1120 if l.g then m = m .. "g" end
1121 if l.n then m = m .. "n" end
1123 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1126 function wifidev.is_up(self)
1129 _uci_state:foreach("wireless", "wifi-iface",
1131 if s.device == self.sid then
1142 function wifidev.get_wifinet(self, net)
1143 if _uci_real:get("wireless", net) == "wifi-iface" then
1146 local wnet = _wifi_lookup(net)
1148 return wifinet(wnet)
1153 function wifidev.get_wifinets(self)
1156 _uci_real:foreach("wireless", "wifi-iface",
1158 if s.device == self.sid then
1159 nets[#nets+1] = wifinet(s['.name'])
1166 function wifidev.add_wifinet(self, options)
1167 options = options or { }
1168 options.device = self.sid
1170 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1172 return wifinet(wnet, options)
1176 function wifidev.del_wifinet(self, net)
1177 if utl.instanceof(net, wifinet) then
1179 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1180 net = _wifi_lookup(net)
1183 if net and _uci_real:get("wireless", net, "device") == self.sid then
1184 _uci_real:delete("wireless", net)
1192 wifinet = utl.class()
1194 function wifinet.__init__(self, net, data)
1199 _uci_real:foreach("wireless", "wifi-iface",
1202 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1203 if s['.name'] == self.sid then
1204 netid = "%s.network%d" %{ s.device, num[s.device] }
1210 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1214 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1215 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1216 _uci_real:get_all("wireless", self.sid) or { }
1219 function wifinet.get(self, opt)
1220 return _get("wireless", self.sid, opt)
1223 function wifinet.set(self, opt, val)
1224 return _set("wireless", self.sid, opt, val)
1227 function wifinet.mode(self)
1228 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1231 function wifinet.ssid(self)
1232 return _uci_state:get("wireless", self.sid, "ssid")
1235 function wifinet.bssid(self)
1236 return _uci_state:get("wireless", self.sid, "bssid")
1239 function wifinet.network(self)
1240 return _uci_state:get("wifinet", self.sid, "network")
1243 function wifinet.id(self)
1247 function wifinet.name(self)
1251 function wifinet.ifname(self)
1252 local ifname = self.iwinfo.ifname
1253 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1259 function wifinet.get_device(self)
1260 if self.iwdata.device then
1261 return wifidev(self.iwdata.device)
1265 function wifinet.is_up(self)
1266 return (self.iwdata.up == "1")
1269 function wifinet.active_mode(self)
1270 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1272 if m == "ap" then m = "Master"
1273 elseif m == "sta" then m = "Client"
1274 elseif m == "adhoc" then m = "Ad-Hoc"
1275 elseif m == "mesh" then m = "Mesh"
1276 elseif m == "monitor" then m = "Monitor"
1282 function wifinet.active_mode_i18n(self)
1283 return i18n.translate(self:active_mode())
1286 function wifinet.active_ssid(self)
1287 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1290 function wifinet.active_bssid(self)
1291 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1294 function wifinet.active_encryption(self)
1295 local enc = self.iwinfo and self.iwinfo.encryption
1296 return enc and enc.description or "-"
1299 function wifinet.assoclist(self)
1300 return self.iwinfo.assoclist or { }
1303 function wifinet.frequency(self)
1304 local freq = self.iwinfo.frequency
1305 if freq and freq > 0 then
1306 return "%.03f" % (freq / 1000)
1310 function wifinet.bitrate(self)
1311 local rate = self.iwinfo.bitrate
1312 if rate and rate > 0 then
1313 return (rate / 1000)
1317 function wifinet.channel(self)
1318 return self.iwinfo.channel or
1319 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1322 function wifinet.signal(self)
1323 return self.iwinfo.signal or 0
1326 function wifinet.noise(self)
1327 return self.iwinfo.noise or 0
1330 function wifinet.country(self)
1331 return self.iwinfo.country or "00"
1334 function wifinet.txpower(self)
1335 return self.iwinfo.txpower or 0
1338 function wifinet.signal_level(self, s, n)
1339 if self:active_bssid() ~= "00:00:00:00:00:00" then
1340 local signal = s or self:signal()
1341 local noise = n or self:noise()
1343 if signal < 0 and noise < 0 then
1344 local snr = -1 * (noise - signal)
1345 return math.floor(snr / 5)
1354 function wifinet.signal_percent(self)
1355 local qc = self.iwinfo.quality or 0
1356 local qm = self.iwinfo.quality_max or 0
1358 if qc > 0 and qm > 0 then
1359 return math.floor((100 / qm) * qc)
1365 function wifinet.shortname(self)
1367 i18n.translate(self:active_mode()),
1368 self:active_ssid() or self:active_bssid()
1372 function wifinet.get_i18n(self)
1373 return "%s: %s %q (%s)" %{
1374 i18n.translate("Wireless Network"),
1375 i18n.translate(self:active_mode()),
1376 self:active_ssid() or self:active_bssid(),
1381 function wifinet.adminlink(self)
1382 return dsp.build_url("admin", "network", "wireless", self.netid)
1385 function wifinet.get_network(self)
1386 if _uci_real:get("network", self.iwdata.network) == "interface" then
1387 return network(self.iwdata.network)
1391 function wifinet.get_interface(self)
1392 return interface(self:ifname())
1396 -- setup base protocols
1397 _M:register_protocol("static")
1398 _M:register_protocol("dhcp")
1399 _M:register_protocol("none")
1401 -- load protocol extensions
1402 local exts = nfs.dir(utl.libpath() .. "/model/network")
1406 if ext:match("%.lua$") then
1407 require("luci.model.network." .. ext:gsub("%.lua$", ""))