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")
636 _uci_real:foreach("wireless", "wifi-iface",
639 num[s.device] = num[s.device]
640 and num[s.device] + 1 or 1
642 if s.network == self.sid then
643 ifname = "%s.network%d" %{ s.device, num[s.device] }
652 function protocol.proto(self)
656 function protocol.get_i18n(self)
657 local p = self:proto()
659 return i18n.translate("Unmanaged")
660 elseif p == "static" then
661 return i18n.translate("Static address")
662 elseif p == "dhcp" then
663 return i18n.translate("DHCP client")
665 return i18n.translate("Unknown")
669 function protocol.type(self)
670 return self:_get("type")
673 function protocol.name(self)
677 function protocol.uptime(self)
678 return self:_ubus("uptime") or 0
681 function protocol.expires(self)
682 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
683 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
685 l = l - (nxo.sysinfo().uptime - a)
686 return l > 0 and l or 0
691 function protocol.metric(self)
692 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
695 function protocol.ipaddr(self)
696 local addrs = self:_ubus("ipv4-address")
697 return addrs and #addrs > 0 and addrs[1].address
700 function protocol.netmask(self)
701 local addrs = self:_ubus("ipv4-address")
702 return addrs and #addrs > 0 and
703 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
706 function protocol.gwaddr(self)
708 for _, route in ipairs(self:_ubus("route") or { }) do
709 if route.target == "0.0.0.0" and route.mask == 0 then
715 function protocol.dnsaddrs(self)
718 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
719 if not addr:match(":") then
726 function protocol.ip6addr(self)
727 local addrs = self:_ubus("ipv6-address")
728 return addrs and #addrs > 0
729 and "%s/%d" %{ addrs[1].address, addrs[1].mask }
732 function protocol.gw6addr(self)
734 for _, route in ipairs(self:_ubus("route")) do
735 if route.target == "::" and route.mask == 0 then
736 return ipc.IPv6(route.nexthop):string()
741 function protocol.dns6addrs(self)
744 for _, addr in ipairs(self:_ubus("dns-server")) do
745 if addr:match(":") then
752 function protocol.is_bridge(self)
753 return (not self:is_virtual() and self:type() == "bridge")
756 function protocol.opkg_package(self)
760 function protocol.is_installed(self)
764 function protocol.is_virtual(self)
768 function protocol.is_floating(self)
772 function protocol.is_empty(self)
773 if self:is_floating() then
778 if (self:_get("ifname") or ""):match("%S+") then
782 _uci_real:foreach("wireless", "wifi-iface",
784 if s.network == self.sid then
794 function protocol.add_interface(self, ifname)
795 ifname = _M:ifnameof(ifname)
796 if ifname and not self:is_floating() then
797 -- remove the interface from all ifaces
798 _uci_real:foreach("network", "interface",
800 _filter("network", s['.name'], "ifname", ifname)
803 -- if its a wifi interface, change its network option
804 local wif = _wifi_lookup(ifname)
806 _uci_real:set("wireless", wif, "network", self.sid)
808 -- add iface to our iface list
810 _append("network", self.sid, "ifname", ifname)
815 function protocol.del_interface(self, ifname)
816 ifname = _M:ifnameof(ifname)
817 if ifname and not self:is_floating() then
818 -- if its a wireless interface, clear its network option
819 local wif = _wifi_lookup(ifname)
820 if wif then _uci_real:delete("wireless", wif, "network") end
822 -- remove the interface
823 _filter("network", self.sid, "ifname", ifname)
827 function protocol.get_interface(self)
828 if self:is_virtual() then
829 _tunnel[self:proto() .. "-" .. self.sid] = true
830 return interface(self:proto() .. "-" .. self.sid, self)
831 elseif self:is_bridge() then
832 _bridge["br-" .. self.sid] = true
833 return interface("br-" .. self.sid, self)
837 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
838 ifn = ifn:match("^[^:/]+")
839 return ifn and interface(ifn, self)
842 _uci_real:foreach("wireless", "wifi-iface",
845 num[s.device] = num[s.device] and num[s.device] + 1 or 1
846 if s.network == self.sid then
847 ifn = "%s.network%d" %{ s.device, num[s.device] }
852 return ifn and interface(ifn, self)
856 function protocol.get_interfaces(self)
857 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
862 for ifn in utl.imatch(self:get("ifname")) do
863 ifn = ifn:match("^[^:/]+")
864 nfs[ifn] = interface(ifn, self)
867 for ifn in utl.kspairs(nfs) do
868 ifaces[#ifaces+1] = nfs[ifn]
873 _uci_real:foreach("wireless", "wifi-iface",
876 num[s.device] = num[s.device] and num[s.device] + 1 or 1
877 if s.network == self.sid then
878 ifn = "%s.network%d" %{ s.device, num[s.device] }
879 wfs[ifn] = interface(ifn, self)
884 for ifn in utl.kspairs(wfs) do
885 ifaces[#ifaces+1] = wfs[ifn]
892 function protocol.contains_interface(self, ifname)
893 ifname = _M:ifnameof(ifname)
896 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
898 elseif self:is_bridge() and "br-" .. self.sid == ifname then
902 for ifn in utl.imatch(self:get("ifname")) do
903 ifn = ifn:match("[^:]+")
904 if ifn == ifname then
909 local wif = _wifi_lookup(ifname)
911 return (_uci_real:get("wireless", wif, "network") == self.sid)
918 function protocol.adminlink(self)
919 return dsp.build_url("admin", "network", "network", self.sid)
923 interface = utl.class()
925 function interface.__init__(self, ifname, network)
926 local wif = _wifi_lookup(ifname)
928 self.wif = wifinet(wif)
929 self.ifname = _uci_state:get("wireless", wif, "ifname")
932 self.ifname = self.ifname or ifname
933 self.dev = _interfaces[self.ifname]
934 self.network = network
937 function interface._ubus(self, field)
938 if not _ubusdevcache[self.ifname] then
939 _ubusdevcache[self.ifname] = _ubus:call("network.device", "status",
940 { name = self.ifname })
942 if _ubusdevcache[self.ifname] and field then
943 return _ubusdevcache[self.ifname][field]
945 return _ubusdevcache[self.ifname]
948 function interface.name(self)
949 return self.wif and self.wif:ifname() or self.ifname
952 function interface.mac(self)
953 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
956 function interface.ipaddrs(self)
957 return self.dev and self.dev.ipaddrs or { }
960 function interface.ip6addrs(self)
961 return self.dev and self.dev.ip6addrs or { }
964 function interface.type(self)
965 if self.wif or _wifi_iface(self.ifname) then
967 elseif _bridge[self.ifname] then
969 elseif _tunnel[self.ifname] then
971 elseif self.ifname:match("%.") then
973 elseif _switch[self.ifname] then
980 function interface.shortname(self)
983 self.wif:active_mode(),
984 self.wif:active_ssid() or self.wif:active_bssid()
991 function interface.get_i18n(self)
993 return "%s: %s %q" %{
994 i18n.translate("Wireless Network"),
995 self.wif:active_mode(),
996 self.wif:active_ssid() or self.wif:active_bssid()
999 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1003 function interface.get_type_i18n(self)
1004 local x = self:type()
1006 return i18n.translate("Wireless Adapter")
1007 elseif x == "bridge" then
1008 return i18n.translate("Bridge")
1009 elseif x == "switch" then
1010 return i18n.translate("Ethernet Switch")
1011 elseif x == "vlan" then
1012 return i18n.translate("VLAN Interface")
1013 elseif x == "tunnel" then
1014 return i18n.translate("Tunnel Interface")
1016 return i18n.translate("Ethernet Adapter")
1020 function interface.adminlink(self)
1022 return self.wif:adminlink()
1026 function interface.ports(self)
1027 local members = self:_ubus("bridge-members")
1031 for _, iface in ipairs(members) do
1032 ifaces[#ifaces+1] = interface(iface)
1037 function interface.bridge_id(self)
1045 function interface.bridge_stp(self)
1053 function interface.is_up(self)
1055 return self.wif:is_up()
1057 return self:_ubus("up") or false
1061 function interface.is_bridge(self)
1062 return (self:type() == "bridge")
1065 function interface.is_bridgeport(self)
1066 return self.dev and self.dev.bridge and true or false
1069 local function uint(x)
1071 return (x < 0) and ((2^32) + x) or x
1076 function interface.tx_bytes(self)
1077 local stat = self:_ubus("statistics")
1078 return stat and uint(stat.tx_bytes) or 0
1081 function interface.rx_bytes(self)
1082 local stat = self:_ubus("statistics")
1083 return stat and uint(stat.rx_bytes) or 0
1086 function interface.tx_packets(self)
1087 local stat = self:_ubus("statistics")
1088 return stat and uint(stat.tx_packets) or 0
1091 function interface.rx_packets(self)
1092 local stat = self:_ubus("statistics")
1093 return stat and uint(stat.rx_packets) or 0
1096 function interface.get_network(self)
1097 if not self.network then
1098 if self.dev and self.dev.network then
1099 self.network = _M:get_network(self.dev.network)
1103 if not self.network then
1105 for _, net in ipairs(_M:get_networks()) do
1106 if net:contains_interface(self.ifname) or
1107 net:ifname() == self.ifname
1118 function interface.get_wifinet(self)
1123 wifidev = utl.class()
1125 function wifidev.__init__(self, dev)
1127 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1130 function wifidev.get(self, opt)
1131 return _get("wireless", self.sid, opt)
1134 function wifidev.set(self, opt, val)
1135 return _set("wireless", self.sid, opt, val)
1138 function wifidev.name(self)
1142 function wifidev.hwmodes(self)
1143 local l = self.iwinfo.hwmodelist
1144 if l and next(l) then
1147 return { b = true, g = true }
1151 function wifidev.get_i18n(self)
1153 if self.iwinfo.type == "wl" then
1155 elseif self.iwinfo.type == "madwifi" then
1160 local l = self:hwmodes()
1161 if l.a then m = m .. "a" end
1162 if l.b then m = m .. "b" end
1163 if l.g then m = m .. "g" end
1164 if l.n then m = m .. "n" end
1166 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1169 function wifidev.is_up(self)
1172 _uci_state:foreach("wireless", "wifi-iface",
1174 if s.device == self.sid then
1185 function wifidev.get_wifinet(self, net)
1186 if _uci_real:get("wireless", net) == "wifi-iface" then
1189 local wnet = _wifi_lookup(net)
1191 return wifinet(wnet)
1196 function wifidev.get_wifinets(self)
1199 _uci_real:foreach("wireless", "wifi-iface",
1201 if s.device == self.sid then
1202 nets[#nets+1] = wifinet(s['.name'])
1209 function wifidev.add_wifinet(self, options)
1210 options = options or { }
1211 options.device = self.sid
1213 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1215 return wifinet(wnet, options)
1219 function wifidev.del_wifinet(self, net)
1220 if utl.instanceof(net, wifinet) then
1222 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1223 net = _wifi_lookup(net)
1226 if net and _uci_real:get("wireless", net, "device") == self.sid then
1227 _uci_real:delete("wireless", net)
1235 wifinet = utl.class()
1237 function wifinet.__init__(self, net, data)
1242 _uci_real:foreach("wireless", "wifi-iface",
1245 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1246 if s['.name'] == self.sid then
1247 netid = "%s.network%d" %{ s.device, num[s.device] }
1253 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1257 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1258 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1259 _uci_real:get_all("wireless", self.sid) or { }
1262 function wifinet.get(self, opt)
1263 return _get("wireless", self.sid, opt)
1266 function wifinet.set(self, opt, val)
1267 return _set("wireless", self.sid, opt, val)
1270 function wifinet.mode(self)
1271 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1274 function wifinet.ssid(self)
1275 return _uci_state:get("wireless", self.sid, "ssid")
1278 function wifinet.bssid(self)
1279 return _uci_state:get("wireless", self.sid, "bssid")
1282 function wifinet.network(self)
1283 return _uci_state:get("wifinet", self.sid, "network")
1286 function wifinet.id(self)
1290 function wifinet.name(self)
1294 function wifinet.ifname(self)
1295 local ifname = self.iwinfo.ifname
1296 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1302 function wifinet.get_device(self)
1303 if self.iwdata.device then
1304 return wifidev(self.iwdata.device)
1308 function wifinet.is_up(self)
1309 return (self.iwdata.up == "1")
1312 function wifinet.active_mode(self)
1313 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1315 if m == "ap" then m = "Master"
1316 elseif m == "sta" then m = "Client"
1317 elseif m == "adhoc" then m = "Ad-Hoc"
1318 elseif m == "mesh" then m = "Mesh"
1319 elseif m == "monitor" then m = "Monitor"
1325 function wifinet.active_mode_i18n(self)
1326 return i18n.translate(self:active_mode())
1329 function wifinet.active_ssid(self)
1330 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1333 function wifinet.active_bssid(self)
1334 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1337 function wifinet.active_encryption(self)
1338 local enc = self.iwinfo and self.iwinfo.encryption
1339 return enc and enc.description or "-"
1342 function wifinet.assoclist(self)
1343 return self.iwinfo.assoclist or { }
1346 function wifinet.frequency(self)
1347 local freq = self.iwinfo.frequency
1348 if freq and freq > 0 then
1349 return "%.03f" % (freq / 1000)
1353 function wifinet.bitrate(self)
1354 local rate = self.iwinfo.bitrate
1355 if rate and rate > 0 then
1356 return (rate / 1000)
1360 function wifinet.channel(self)
1361 return self.iwinfo.channel or
1362 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1365 function wifinet.signal(self)
1366 return self.iwinfo.signal or 0
1369 function wifinet.noise(self)
1370 return self.iwinfo.noise or 0
1373 function wifinet.country(self)
1374 return self.iwinfo.country or "00"
1377 function wifinet.txpower(self)
1378 local pwr = (self.iwinfo.txpower or 0)
1379 return pwr + self:txpower_offset()
1382 function wifinet.txpower_offset(self)
1383 return self.iwinfo.txpower_offset or 0
1386 function wifinet.signal_level(self, s, n)
1387 if self:active_bssid() ~= "00:00:00:00:00:00" then
1388 local signal = s or self:signal()
1389 local noise = n or self:noise()
1391 if signal < 0 and noise < 0 then
1392 local snr = -1 * (noise - signal)
1393 return math.floor(snr / 5)
1402 function wifinet.signal_percent(self)
1403 local qc = self.iwinfo.quality or 0
1404 local qm = self.iwinfo.quality_max or 0
1406 if qc > 0 and qm > 0 then
1407 return math.floor((100 / qm) * qc)
1413 function wifinet.shortname(self)
1415 i18n.translate(self:active_mode()),
1416 self:active_ssid() or self:active_bssid()
1420 function wifinet.get_i18n(self)
1421 return "%s: %s %q (%s)" %{
1422 i18n.translate("Wireless Network"),
1423 i18n.translate(self:active_mode()),
1424 self:active_ssid() or self:active_bssid(),
1429 function wifinet.adminlink(self)
1430 return dsp.build_url("admin", "network", "wireless", self.netid)
1433 function wifinet.get_network(self)
1434 local net = tostring(self.iwdata.network)
1435 if net and _uci_real:get("network", net) == "interface" then
1440 function wifinet.get_interface(self)
1441 return interface(self:ifname())
1445 -- setup base protocols
1446 _M:register_protocol("static")
1447 _M:register_protocol("dhcp")
1448 _M:register_protocol("none")
1450 -- load protocol extensions
1451 local exts = nfs.dir(utl.libpath() .. "/model/network")
1455 if ext:match("%.lua$") then
1456 require("luci.model.network." .. ext:gsub("%.lua$", ""))