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
21 = type, next, pairs, ipairs, loadfile, table
23 local tonumber, tostring, math, i18n
24 = tonumber, tostring, math, luci.i18n
26 local require = require
28 local bus = require "ubus"
29 local nxo = require "nixio"
30 local nfs = require "nixio.fs"
31 local ipc = require "luci.ip"
32 local sys = require "luci.sys"
33 local utl = require "luci.util"
34 local dsp = require "luci.dispatcher"
35 local uci = require "luci.model.uci"
37 module "luci.model.network"
40 IFACE_PATTERNS_VIRTUAL = { }
41 IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^lo$" }
42 IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
45 protocol = utl.class()
47 local _protocols = { }
49 local _interfaces, _bridge, _switch, _tunnel
50 local _ubus, _ubusnetcache, _ubusdevcache
51 local _uci_real, _uci_state
53 function _filter(c, s, o, r)
54 local val = _uci_real:get(c, s, o)
57 if type(val) == "string" then
58 for val in val:gmatch("%S+") do
64 _uci_real:set(c, s, o, table.concat(l, " "))
66 _uci_real:delete(c, s, o)
68 elseif type(val) == "table" then
69 for _, val in ipairs(val) do
75 _uci_real:set(c, s, o, l)
77 _uci_real:delete(c, s, o)
83 function _append(c, s, o, a)
84 local val = _uci_real:get(c, s, o) or ""
85 if type(val) == "string" then
87 for val in val:gmatch("%S+") do
93 _uci_real:set(c, s, o, table.concat(l, " "))
94 elseif type(val) == "table" then
96 for _, val in ipairs(val) do
102 _uci_real:set(c, s, o, l)
106 function _stror(s1, s2)
107 if not s1 or #s1 == 0 then
108 return s2 and #s2 > 0 and s2
114 function _get(c, s, o)
115 return _uci_real:get(c, s, o)
118 function _set(c, s, o, v)
120 if type(v) == "boolean" then v = v and "1" or "0" end
121 return _uci_real:set(c, s, o, v)
123 return _uci_real:delete(c, s, o)
127 function _wifi_iface(x)
129 for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
137 function _wifi_lookup(ifn)
138 -- got a radio#.network# pseudo iface, locate the corresponding section
139 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
140 if radio and ifnidx then
144 ifnidx = tonumber(ifnidx)
145 _uci_real:foreach("wireless", "wifi-iface",
147 if s.device == radio then
149 if num == ifnidx then
158 -- looks like wifi, try to locate the section via state vars
159 elseif _wifi_iface(ifn) then
162 _uci_state:foreach("wireless", "wifi-iface",
164 if s.ifname == ifn then
174 function _iface_virtual(x)
176 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
184 function _iface_ignore(x)
186 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
191 return _iface_virtual(x)
195 function init(cursor)
196 _uci_real = cursor or _uci_real or uci.cursor()
197 _uci_state = _uci_real:substate()
204 _ubus = bus.connect()
208 -- read interface information
210 for n, i in ipairs(nxo.getifaddrs()) do
211 local name = i.name:match("[^:]+")
212 local prnt = name:match("^([^%.]+)%.")
214 if _iface_virtual(name) then
218 if _tunnel[name] or not _iface_ignore(name) then
219 _interfaces[name] = _interfaces[name] or {
220 idx = i.ifindex or n,
233 if i.family == "packet" then
234 _interfaces[name].flags = i.flags
235 _interfaces[name].stats = i.data
236 _interfaces[name].macaddr = i.addr
237 elseif i.family == "inet" then
238 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
239 elseif i.family == "inet6" then
240 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
245 -- read bridge informaton
247 for l in utl.execi("brctl show") do
248 if not l:match("STP") then
249 local r = utl.split(l, "%s+", nil, true)
255 ifnames = { _interfaces[r[4]] }
258 b.ifnames[1].bridge = b
262 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
263 b.ifnames[#b.ifnames].bridge = b
271 function save(self, ...)
276 function commit(self, ...)
277 _uci_real:commit(...)
281 function ifnameof(self, x)
282 if utl.instanceof(x, interface) then
284 elseif utl.instanceof(x, protocol) then
286 elseif type(x) == "string" then
287 return x:match("^[^:]+")
291 function get_protocol(self, protoname, netname)
292 local v = _protocols[protoname]
294 return v(netname or "__dummy__")
298 function get_protocols(self)
301 for _, v in ipairs(_protocols) do
302 p[#p+1] = v("__dummy__")
307 function register_protocol(self, protoname)
308 local proto = utl.class(protocol)
310 function proto.__init__(self, name)
314 function proto.proto(self)
318 _protocols[#_protocols+1] = proto
319 _protocols[protoname] = proto
324 function register_pattern_virtual(self, pat)
325 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
329 function has_ipv6(self)
330 return nfs.access("/proc/net/ipv6_route")
333 function add_network(self, n, options)
334 local oldnet = self:get_network(n)
335 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
336 if _uci_real:section("network", "interface", n, options) then
339 elseif oldnet and oldnet:is_empty() then
342 for k, v in pairs(options) do
350 function get_network(self, n)
351 if n and _uci_real:get("network", n) == "interface" then
356 function get_networks(self)
360 _uci_real:foreach("network", "interface",
362 nls[s['.name']] = network(s['.name'])
366 for n in utl.kspairs(nls) do
367 nets[#nets+1] = nls[n]
373 function del_network(self, n)
374 local r = _uci_real:delete("network", n)
376 _uci_real:delete_all("network", "alias",
377 function(s) return (s.interface == n) end)
379 _uci_real:delete_all("network", "route",
380 function(s) return (s.interface == n) end)
382 _uci_real:delete_all("network", "route6",
383 function(s) return (s.interface == n) end)
385 _uci_real:foreach("wireless", "wifi-iface",
387 if s.network == n then
388 _uci_real:delete("wireless", s['.name'], "network")
395 function rename_network(self, old, new)
397 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
398 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
401 _uci_real:foreach("network", "alias",
403 if s.interface == old then
404 _uci_real:set("network", s['.name'], "interface", new)
408 _uci_real:foreach("network", "route",
410 if s.interface == old then
411 _uci_real:set("network", s['.name'], "interface", new)
415 _uci_real:foreach("network", "route6",
417 if s.interface == old then
418 _uci_real:set("network", s['.name'], "interface", new)
422 _uci_real:foreach("wireless", "wifi-iface",
424 if s.network == old then
425 _uci_real:set("wireless", s['.name'], "network", new)
429 _uci_real:delete("network", old)
435 function get_interface(self, i)
436 if _interfaces[i] or _wifi_iface(i) then
441 _uci_real:foreach("wireless", "wifi-iface",
444 num[s.device] = num[s.device] and num[s.device] + 1 or 1
445 if s['.name'] == i then
447 "%s.network%d" %{s.device, num[s.device] })
456 function get_interfaces(self)
463 -- find normal interfaces
464 _uci_real:foreach("network", "interface",
466 for iface in utl.imatch(s.ifname) do
467 if not _iface_ignore(iface) and not _wifi_iface(iface) then
469 nfs[iface] = interface(iface)
474 for iface in utl.kspairs(_interfaces) do
475 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
476 nfs[iface] = interface(iface)
480 -- find vlan interfaces
481 _uci_real:foreach("network", "switch_vlan",
487 local base = baseof[s.device]
489 if not s.device:match("^eth%d") then
491 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
493 base = l:match("^%w+: (%w+)")
496 if not base or not base:match("^eth%d") then
502 baseof[s.device] = base
505 local vid = tonumber(s.vid or s.vlan)
506 if vid ~= nil and vid >= 0 and vid <= 4095 then
507 local iface = "%s.%d" %{ base, vid }
508 if not seen[iface] then
510 nfs[iface] = interface(iface)
515 for iface in utl.kspairs(nfs) do
516 ifaces[#ifaces+1] = nfs[iface]
519 -- find wifi interfaces
522 _uci_real:foreach("wireless", "wifi-iface",
525 num[s.device] = num[s.device] and num[s.device] + 1 or 1
526 local i = "%s.network%d" %{ s.device, num[s.device] }
527 wfs[i] = interface(i)
531 for iface in utl.kspairs(wfs) do
532 ifaces[#ifaces+1] = wfs[iface]
538 function ignore_interface(self, x)
539 return _iface_ignore(x)
542 function get_wifidev(self, dev)
543 if _uci_real:get("wireless", dev) == "wifi-device" then
548 function get_wifidevs(self)
552 _uci_real:foreach("wireless", "wifi-device",
553 function(s) wfd[#wfd+1] = s['.name'] end)
556 for _, dev in utl.vspairs(wfd) do
557 devs[#devs+1] = wifidev(dev)
563 function get_wifinet(self, net)
564 local wnet = _wifi_lookup(net)
570 function add_wifinet(self, net, options)
571 if type(options) == "table" and options.device and
572 _uci_real:get("wireless", options.device) == "wifi-device"
574 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
579 function del_wifinet(self, net)
580 local wnet = _wifi_lookup(net)
582 _uci_real:delete("wireless", wnet)
589 function network(name, proto)
591 local p = proto or _uci_real:get("network", name, "proto")
592 local c = p and _protocols[p] or protocol
597 function protocol.__init__(self, name)
601 function protocol._get(self, opt)
602 local v = _uci_real:get("network", self.sid, opt)
603 if type(v) == "table" then
604 return table.concat(v, " ")
609 function protocol._ubus(self, field)
610 if not _ubusnetcache[self.sid] then
611 _ubusnetcache[self.sid] = _ubus:call("network.interface.%s" % self.sid,
614 if _ubusnetcache[self.sid] and field then
615 return _ubusnetcache[self.sid][field]
617 return _ubusnetcache[self.sid]
620 function protocol.get(self, opt)
621 return _get("network", self.sid, opt)
624 function protocol.set(self, opt, val)
625 return _set("network", self.sid, opt, val)
628 function protocol.ifname(self)
630 if self:is_floating() then
631 ifname = self:_ubus("l3_device")
633 ifname = self:_ubus("device")
637 _uci_real:foreach("wireless", "wifi-iface",
640 num[s.device] = num[s.device]
641 and num[s.device] + 1 or 1
643 if s.network == self.sid then
644 ifname = "%s.network%d" %{ s.device, num[s.device] }
653 function protocol.proto(self)
657 function protocol.get_i18n(self)
658 local p = self:proto()
660 return i18n.translate("Unmanaged")
661 elseif p == "static" then
662 return i18n.translate("Static address")
663 elseif p == "dhcp" then
664 return i18n.translate("DHCP client")
666 return i18n.translate("Unknown")
670 function protocol.type(self)
671 return self:_get("type")
674 function protocol.name(self)
678 function protocol.uptime(self)
679 return self:_ubus("uptime") or 0
682 function protocol.expires(self)
683 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
684 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
686 l = l - (nxo.sysinfo().uptime - a)
687 return l > 0 and l or 0
692 function protocol.metric(self)
693 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
696 function protocol.ipaddr(self)
697 local addrs = self:_ubus("ipv4-address")
698 return addrs and #addrs > 0 and addrs[1].address
701 function protocol.netmask(self)
702 local addrs = self:_ubus("ipv4-address")
703 return addrs and #addrs > 0 and
704 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
707 function protocol.gwaddr(self)
709 for _, route in ipairs(self:_ubus("route") or { }) do
710 if route.target == "0.0.0.0" and route.mask == 0 then
716 function protocol.dnsaddrs(self)
719 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
720 if not addr:match(":") then
727 function protocol.ip6addr(self)
728 local addrs = self:_ubus("ipv6-address")
729 return addrs and #addrs > 0
730 and "%s/%d" %{ addrs[1].address, addrs[1].mask }
733 function protocol.gw6addr(self)
735 for _, route in ipairs(self:_ubus("route") or { }) do
736 if route.target == "::" and route.mask == 0 then
737 return ipc.IPv6(route.nexthop):string()
742 function protocol.dns6addrs(self)
745 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
746 if addr:match(":") then
753 function protocol.is_bridge(self)
754 return (not self:is_virtual() and self:type() == "bridge")
757 function protocol.opkg_package(self)
761 function protocol.is_installed(self)
765 function protocol.is_virtual(self)
769 function protocol.is_floating(self)
773 function protocol.is_empty(self)
774 if self:is_floating() then
779 if (self:_get("ifname") or ""):match("%S+") then
783 _uci_real:foreach("wireless", "wifi-iface",
785 if s.network == self.sid then
795 function protocol.add_interface(self, ifname)
796 ifname = _M:ifnameof(ifname)
797 if ifname and not self:is_floating() then
798 -- remove the interface from all ifaces
799 _uci_real:foreach("network", "interface",
801 _filter("network", s['.name'], "ifname", ifname)
804 -- if its a wifi interface, change its network option
805 local wif = _wifi_lookup(ifname)
807 _uci_real:set("wireless", wif, "network", self.sid)
809 -- add iface to our iface list
811 _append("network", self.sid, "ifname", ifname)
816 function protocol.del_interface(self, ifname)
817 ifname = _M:ifnameof(ifname)
818 if ifname and not self:is_floating() then
819 -- if its a wireless interface, clear its network option
820 local wif = _wifi_lookup(ifname)
821 if wif then _uci_real:delete("wireless", wif, "network") end
823 -- remove the interface
824 _filter("network", self.sid, "ifname", ifname)
828 function protocol.get_interface(self)
829 if self:is_virtual() then
830 _tunnel[self:proto() .. "-" .. self.sid] = true
831 return interface(self:proto() .. "-" .. self.sid, self)
832 elseif self:is_bridge() then
833 _bridge["br-" .. self.sid] = true
834 return interface("br-" .. self.sid, self)
838 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
839 ifn = ifn:match("^[^:/]+")
840 return ifn and interface(ifn, self)
843 _uci_real:foreach("wireless", "wifi-iface",
846 num[s.device] = num[s.device] and num[s.device] + 1 or 1
847 if s.network == self.sid then
848 ifn = "%s.network%d" %{ s.device, num[s.device] }
853 return ifn and interface(ifn, self)
857 function protocol.get_interfaces(self)
858 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
863 for ifn in utl.imatch(self:get("ifname")) do
864 ifn = ifn:match("^[^:/]+")
865 nfs[ifn] = interface(ifn, self)
868 for ifn in utl.kspairs(nfs) do
869 ifaces[#ifaces+1] = nfs[ifn]
874 _uci_real:foreach("wireless", "wifi-iface",
877 num[s.device] = num[s.device] and num[s.device] + 1 or 1
878 if s.network == self.sid then
879 ifn = "%s.network%d" %{ s.device, num[s.device] }
880 wfs[ifn] = interface(ifn, self)
885 for ifn in utl.kspairs(wfs) do
886 ifaces[#ifaces+1] = wfs[ifn]
893 function protocol.contains_interface(self, ifname)
894 ifname = _M:ifnameof(ifname)
897 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
899 elseif self:is_bridge() and "br-" .. self.sid == ifname then
903 for ifn in utl.imatch(self:get("ifname")) do
904 ifn = ifn:match("[^:]+")
905 if ifn == ifname then
910 local wif = _wifi_lookup(ifname)
912 return (_uci_real:get("wireless", wif, "network") == self.sid)
919 function protocol.adminlink(self)
920 return dsp.build_url("admin", "network", "network", self.sid)
924 interface = utl.class()
926 function interface.__init__(self, ifname, network)
927 local wif = _wifi_lookup(ifname)
929 self.wif = wifinet(wif)
930 self.ifname = _uci_state:get("wireless", wif, "ifname")
933 self.ifname = self.ifname or ifname
934 self.dev = _interfaces[self.ifname]
935 self.network = network
938 function interface._ubus(self, field)
939 if not _ubusdevcache[self.ifname] then
940 _ubusdevcache[self.ifname] = _ubus:call("network.device", "status",
941 { name = self.ifname })
943 if _ubusdevcache[self.ifname] and field then
944 return _ubusdevcache[self.ifname][field]
946 return _ubusdevcache[self.ifname]
949 function interface.name(self)
950 return self.wif and self.wif:ifname() or self.ifname
953 function interface.mac(self)
954 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
957 function interface.ipaddrs(self)
958 return self.dev and self.dev.ipaddrs or { }
961 function interface.ip6addrs(self)
962 return self.dev and self.dev.ip6addrs or { }
965 function interface.type(self)
966 if self.wif or _wifi_iface(self.ifname) then
968 elseif _bridge[self.ifname] then
970 elseif _tunnel[self.ifname] then
972 elseif self.ifname:match("%.") then
974 elseif _switch[self.ifname] then
981 function interface.shortname(self)
984 self.wif:active_mode(),
985 self.wif:active_ssid() or self.wif:active_bssid()
992 function interface.get_i18n(self)
994 return "%s: %s %q" %{
995 i18n.translate("Wireless Network"),
996 self.wif:active_mode(),
997 self.wif:active_ssid() or self.wif:active_bssid()
1000 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1004 function interface.get_type_i18n(self)
1005 local x = self:type()
1007 return i18n.translate("Wireless Adapter")
1008 elseif x == "bridge" then
1009 return i18n.translate("Bridge")
1010 elseif x == "switch" then
1011 return i18n.translate("Ethernet Switch")
1012 elseif x == "vlan" then
1013 return i18n.translate("VLAN Interface")
1014 elseif x == "tunnel" then
1015 return i18n.translate("Tunnel Interface")
1017 return i18n.translate("Ethernet Adapter")
1021 function interface.adminlink(self)
1023 return self.wif:adminlink()
1027 function interface.ports(self)
1028 local members = self:_ubus("bridge-members")
1032 for _, iface in ipairs(members) do
1033 ifaces[#ifaces+1] = interface(iface)
1039 function interface.bridge_id(self)
1047 function interface.bridge_stp(self)
1055 function interface.is_up(self)
1057 return self.wif:is_up()
1059 return self:_ubus("up") or false
1063 function interface.is_bridge(self)
1064 return (self:type() == "bridge")
1067 function interface.is_bridgeport(self)
1068 return self.dev and self.dev.bridge and true or false
1071 local function uint(x)
1073 return (x < 0) and ((2^32) + x) or x
1078 function interface.tx_bytes(self)
1079 local stat = self:_ubus("statistics")
1080 return stat and uint(stat.tx_bytes) or 0
1083 function interface.rx_bytes(self)
1084 local stat = self:_ubus("statistics")
1085 return stat and uint(stat.rx_bytes) or 0
1088 function interface.tx_packets(self)
1089 local stat = self:_ubus("statistics")
1090 return stat and uint(stat.tx_packets) or 0
1093 function interface.rx_packets(self)
1094 local stat = self:_ubus("statistics")
1095 return stat and uint(stat.rx_packets) or 0
1098 function interface.get_network(self)
1099 if not self.network then
1100 if self.dev and self.dev.network then
1101 self.network = _M:get_network(self.dev.network)
1105 if not self.network then
1107 for _, net in ipairs(_M:get_networks()) do
1108 if net:contains_interface(self.ifname) or
1109 net:ifname() == self.ifname
1120 function interface.get_wifinet(self)
1125 wifidev = utl.class()
1127 function wifidev.__init__(self, dev)
1129 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1132 function wifidev.get(self, opt)
1133 return _get("wireless", self.sid, opt)
1136 function wifidev.set(self, opt, val)
1137 return _set("wireless", self.sid, opt, val)
1140 function wifidev.name(self)
1144 function wifidev.hwmodes(self)
1145 local l = self.iwinfo.hwmodelist
1146 if l and next(l) then
1149 return { b = true, g = true }
1153 function wifidev.get_i18n(self)
1155 if self.iwinfo.type == "wl" then
1157 elseif self.iwinfo.type == "madwifi" then
1162 local l = self:hwmodes()
1163 if l.a then m = m .. "a" end
1164 if l.b then m = m .. "b" end
1165 if l.g then m = m .. "g" end
1166 if l.n then m = m .. "n" end
1168 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1171 function wifidev.is_up(self)
1174 _uci_state:foreach("wireless", "wifi-iface",
1176 if s.device == self.sid then
1187 function wifidev.get_wifinet(self, net)
1188 if _uci_real:get("wireless", net) == "wifi-iface" then
1191 local wnet = _wifi_lookup(net)
1193 return wifinet(wnet)
1198 function wifidev.get_wifinets(self)
1201 _uci_real:foreach("wireless", "wifi-iface",
1203 if s.device == self.sid then
1204 nets[#nets+1] = wifinet(s['.name'])
1211 function wifidev.add_wifinet(self, options)
1212 options = options or { }
1213 options.device = self.sid
1215 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1217 return wifinet(wnet, options)
1221 function wifidev.del_wifinet(self, net)
1222 if utl.instanceof(net, wifinet) then
1224 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1225 net = _wifi_lookup(net)
1228 if net and _uci_real:get("wireless", net, "device") == self.sid then
1229 _uci_real:delete("wireless", net)
1237 wifinet = utl.class()
1239 function wifinet.__init__(self, net, data)
1244 _uci_real:foreach("wireless", "wifi-iface",
1247 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1248 if s['.name'] == self.sid then
1249 netid = "%s.network%d" %{ s.device, num[s.device] }
1255 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1259 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1260 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1261 _uci_real:get_all("wireless", self.sid) or { }
1264 function wifinet.get(self, opt)
1265 return _get("wireless", self.sid, opt)
1268 function wifinet.set(self, opt, val)
1269 return _set("wireless", self.sid, opt, val)
1272 function wifinet.mode(self)
1273 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1276 function wifinet.ssid(self)
1277 return _uci_state:get("wireless", self.sid, "ssid")
1280 function wifinet.bssid(self)
1281 return _uci_state:get("wireless", self.sid, "bssid")
1284 function wifinet.network(self)
1285 return _uci_state:get("wifinet", self.sid, "network")
1288 function wifinet.id(self)
1292 function wifinet.name(self)
1296 function wifinet.ifname(self)
1297 local ifname = self.iwinfo.ifname
1298 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1304 function wifinet.get_device(self)
1305 if self.iwdata.device then
1306 return wifidev(self.iwdata.device)
1310 function wifinet.is_up(self)
1311 return (self.iwdata.up == "1")
1314 function wifinet.active_mode(self)
1315 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1317 if m == "ap" then m = "Master"
1318 elseif m == "sta" then m = "Client"
1319 elseif m == "adhoc" then m = "Ad-Hoc"
1320 elseif m == "mesh" then m = "Mesh"
1321 elseif m == "monitor" then m = "Monitor"
1327 function wifinet.active_mode_i18n(self)
1328 return i18n.translate(self:active_mode())
1331 function wifinet.active_ssid(self)
1332 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1335 function wifinet.active_bssid(self)
1336 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1339 function wifinet.active_encryption(self)
1340 local enc = self.iwinfo and self.iwinfo.encryption
1341 return enc and enc.description or "-"
1344 function wifinet.assoclist(self)
1345 return self.iwinfo.assoclist or { }
1348 function wifinet.frequency(self)
1349 local freq = self.iwinfo.frequency
1350 if freq and freq > 0 then
1351 return "%.03f" % (freq / 1000)
1355 function wifinet.bitrate(self)
1356 local rate = self.iwinfo.bitrate
1357 if rate and rate > 0 then
1358 return (rate / 1000)
1362 function wifinet.channel(self)
1363 return self.iwinfo.channel or
1364 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1367 function wifinet.signal(self)
1368 return self.iwinfo.signal or 0
1371 function wifinet.noise(self)
1372 return self.iwinfo.noise or 0
1375 function wifinet.country(self)
1376 return self.iwinfo.country or "00"
1379 function wifinet.txpower(self)
1380 local pwr = (self.iwinfo.txpower or 0)
1381 return pwr + self:txpower_offset()
1384 function wifinet.txpower_offset(self)
1385 return self.iwinfo.txpower_offset or 0
1388 function wifinet.signal_level(self, s, n)
1389 if self:active_bssid() ~= "00:00:00:00:00:00" then
1390 local signal = s or self:signal()
1391 local noise = n or self:noise()
1393 if signal < 0 and noise < 0 then
1394 local snr = -1 * (noise - signal)
1395 return math.floor(snr / 5)
1404 function wifinet.signal_percent(self)
1405 local qc = self.iwinfo.quality or 0
1406 local qm = self.iwinfo.quality_max or 0
1408 if qc > 0 and qm > 0 then
1409 return math.floor((100 / qm) * qc)
1415 function wifinet.shortname(self)
1417 i18n.translate(self:active_mode()),
1418 self:active_ssid() or self:active_bssid()
1422 function wifinet.get_i18n(self)
1423 return "%s: %s %q (%s)" %{
1424 i18n.translate("Wireless Network"),
1425 i18n.translate(self:active_mode()),
1426 self:active_ssid() or self:active_bssid(),
1431 function wifinet.adminlink(self)
1432 return dsp.build_url("admin", "network", "wireless", self.netid)
1435 function wifinet.get_network(self)
1436 local net = tostring(self.iwdata.network)
1437 if net and _uci_real:get("network", net) == "interface" then
1442 function wifinet.get_interface(self)
1443 return interface(self:ifname())
1447 -- setup base protocols
1448 _M:register_protocol("static")
1449 _M:register_protocol("dhcp")
1450 _M:register_protocol("none")
1452 -- load protocol extensions
1453 local exts = nfs.dir(utl.libpath() .. "/model/network")
1457 if ext:match("%.lua$") then
1458 require("luci.model.network." .. ext:gsub("%.lua$", ""))