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,
615 return _ubusnetcache[self.sid] and (field and _ubusnetcache[self.sid][field]
616 or _ubusnetcache[self.sid])
619 function protocol.get(self, opt)
620 return _get("network", self.sid, opt)
623 function protocol.set(self, opt, val)
624 return _set("network", self.sid, opt, val)
627 function protocol.ifname(self)
628 local p = self:proto()
629 if self:is_bridge() then
630 return "br-" .. self.sid
631 elseif self:is_virtual() then
632 return p .. "-" .. self.sid
635 local dev = _uci_real:get("network", self.sid, "ifname") or
636 _uci_state:get("network", self.sid, "ifname")
638 dev = (type(dev) == "table") and dev[1] or dev
639 dev = (dev ~= nil) and dev:match("%S+")
642 _uci_real:foreach("wireless", "wifi-iface",
645 num[s.device] = num[s.device]
646 and num[s.device] + 1 or 1
648 if s.network == self.sid then
649 dev = "%s.network%d" %{ s.device, num[s.device] }
660 function protocol.proto(self)
664 function protocol.get_i18n(self)
665 local p = self:proto()
667 return i18n.translate("Unmanaged")
668 elseif p == "static" then
669 return i18n.translate("Static address")
670 elseif p == "dhcp" then
671 return i18n.translate("DHCP client")
673 return i18n.translate("Unknown")
677 function protocol.type(self)
678 return self:_get("type")
681 function protocol.name(self)
685 function protocol.uptime(self)
686 return self:_ubus("uptime") or 0
689 function protocol.expires(self)
690 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
691 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
693 l = l - (nxo.sysinfo().uptime - a)
694 return l > 0 and l or 0
699 function protocol.metric(self)
700 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
703 function protocol.ipaddr(self)
704 local addrs = self:_ubus("ipv4-address")
705 return addrs and #addrs > 0 and addrs[1].address
708 function protocol.netmask(self)
709 local addrs = self:_ubus("ipv4-address")
710 return addrs and #addrs > 0 and
711 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
714 function protocol.gwaddr(self)
716 for _, route in ipairs(self:_ubus("route")) do
717 if route.target == "0.0.0.0" and route.mask == 0 then
723 function protocol.dnsaddrs(self)
726 for _, addr in ipairs(self:_ubus("dns-server")) do
727 if not addr:match(":") then
734 function protocol.ip6addr(self)
735 local addrs = self:_ubus("ipv6-address")
736 return addrs and #addrs > 0
737 and "%s/%d" %{ addrs[1].address, addrs[1].mask }
740 function protocol.gw6addr(self)
742 for _, route in ipairs(self:_ubus("route")) do
743 if route.target == "::" and route.mask == 0 then
744 return ipc.IPv6(route.nexthop):string()
749 function protocol.dns6addrs(self)
752 for _, addr in ipairs(self:_ubus("dns-server")) do
753 if addr:match(":") then
760 function protocol.is_bridge(self)
761 return (not self:is_virtual() and self:type() == "bridge")
764 function protocol.opkg_package(self)
768 function protocol.is_installed(self)
772 function protocol.is_virtual(self)
776 function protocol.is_floating(self)
780 function protocol.is_empty(self)
781 if self:is_floating() then
786 if (self:_get("ifname") or ""):match("%S+") then
790 _uci_real:foreach("wireless", "wifi-iface",
792 if s.network == self.sid then
802 function protocol.add_interface(self, ifname)
803 ifname = _M:ifnameof(ifname)
804 if ifname and not self:is_floating() then
805 -- remove the interface from all ifaces
806 _uci_real:foreach("network", "interface",
808 _filter("network", s['.name'], "ifname", ifname)
811 -- if its a wifi interface, change its network option
812 local wif = _wifi_lookup(ifname)
814 _uci_real:set("wireless", wif, "network", self.sid)
816 -- add iface to our iface list
818 _append("network", self.sid, "ifname", ifname)
823 function protocol.del_interface(self, ifname)
824 ifname = _M:ifnameof(ifname)
825 if ifname and not self:is_floating() then
826 -- if its a wireless interface, clear its network option
827 local wif = _wifi_lookup(ifname)
828 if wif then _uci_real:delete("wireless", wif, "network") end
830 -- remove the interface
831 _filter("network", self.sid, "ifname", ifname)
835 function protocol.get_interface(self)
836 if self:is_virtual() then
837 _tunnel[self:proto() .. "-" .. self.sid] = true
838 return interface(self:proto() .. "-" .. self.sid, self)
839 elseif self:is_bridge() then
840 _bridge["br-" .. self.sid] = true
841 return interface("br-" .. self.sid, self)
845 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
846 ifn = ifn:match("^[^:/]+")
847 return ifn and interface(ifn, self)
850 _uci_real:foreach("wireless", "wifi-iface",
853 num[s.device] = num[s.device] and num[s.device] + 1 or 1
854 if s.network == self.sid then
855 ifn = "%s.network%d" %{ s.device, num[s.device] }
860 return ifn and interface(ifn, self)
864 function protocol.get_interfaces(self)
865 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
870 for ifn in utl.imatch(self:get("ifname")) do
871 ifn = ifn:match("^[^:/]+")
872 nfs[ifn] = interface(ifn, self)
875 for ifn in utl.kspairs(nfs) do
876 ifaces[#ifaces+1] = nfs[ifn]
881 _uci_real:foreach("wireless", "wifi-iface",
884 num[s.device] = num[s.device] and num[s.device] + 1 or 1
885 if s.network == self.sid then
886 ifn = "%s.network%d" %{ s.device, num[s.device] }
887 wfs[ifn] = interface(ifn, self)
892 for ifn in utl.kspairs(wfs) do
893 ifaces[#ifaces+1] = wfs[ifn]
900 function protocol.contains_interface(self, ifname)
901 ifname = _M:ifnameof(ifname)
904 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
906 elseif self:is_bridge() and "br-" .. self.sid == ifname then
910 for ifn in utl.imatch(self:get("ifname")) do
911 ifn = ifn:match("[^:]+")
912 if ifn == ifname then
917 local wif = _wifi_lookup(ifname)
919 return (_uci_real:get("wireless", wif, "network") == self.sid)
926 function protocol.adminlink(self)
927 return dsp.build_url("admin", "network", "network", self.sid)
931 interface = utl.class()
933 function interface.__init__(self, ifname, network)
934 local wif = _wifi_lookup(ifname)
936 self.wif = wifinet(wif)
937 self.ifname = _uci_state:get("wireless", wif, "ifname")
940 self.ifname = self.ifname or ifname
941 self.dev = _interfaces[self.ifname]
942 self.network = network
945 function interface._ubus(self, field)
946 if not _ubusdevcache[self.ifname] then
947 _ubusdevcache[self.ifname] = _ubus:call("network.device", "status",
948 { name = self.ifname })
950 return _ubusdevcache[self.ifname] and
951 (field and _ubusdevcache[self.ifname][field] or
952 _ubusdevcache[self.ifname])
955 function interface.name(self)
956 return self.wif and self.wif:ifname() or self.ifname
959 function interface.mac(self)
960 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
963 function interface.ipaddrs(self)
964 return self.dev and self.dev.ipaddrs or { }
967 function interface.ip6addrs(self)
968 return self.dev and self.dev.ip6addrs or { }
971 function interface.type(self)
972 if self.wif or _wifi_iface(self.ifname) then
974 elseif _bridge[self.ifname] then
976 elseif _tunnel[self.ifname] then
978 elseif self.ifname:match("%.") then
980 elseif _switch[self.ifname] then
987 function interface.shortname(self)
990 self.wif:active_mode(),
991 self.wif:active_ssid() or self.wif:active_bssid()
998 function interface.get_i18n(self)
1000 return "%s: %s %q" %{
1001 i18n.translate("Wireless Network"),
1002 self.wif:active_mode(),
1003 self.wif:active_ssid() or self.wif:active_bssid()
1006 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1010 function interface.get_type_i18n(self)
1011 local x = self:type()
1013 return i18n.translate("Wireless Adapter")
1014 elseif x == "bridge" then
1015 return i18n.translate("Bridge")
1016 elseif x == "switch" then
1017 return i18n.translate("Ethernet Switch")
1018 elseif x == "vlan" then
1019 return i18n.translate("VLAN Interface")
1020 elseif x == "tunnel" then
1021 return i18n.translate("Tunnel Interface")
1023 return i18n.translate("Ethernet Adapter")
1027 function interface.adminlink(self)
1029 return self.wif:adminlink()
1033 function interface.ports(self)
1034 local members = self:_ubus("bridge-members")
1038 for _, iface in ipairs(members) do
1039 ifaces[#ifaces+1] = interface(iface)
1044 function interface.bridge_id(self)
1052 function interface.bridge_stp(self)
1060 function interface.is_up(self)
1062 return self.wif:is_up()
1064 return self:_ubus("up") or false
1068 function interface.is_bridge(self)
1069 return (self:type() == "bridge")
1072 function interface.is_bridgeport(self)
1073 return self.dev and self.dev.bridge and true or false
1076 local function uint(x)
1077 return (x < 0) and ((2^32) + x) or x
1080 function interface.tx_bytes(self)
1081 local stat = self:_ubus("statistics")
1082 return stat and uint(stat.tx_bytes) or 0
1085 function interface.rx_bytes(self)
1086 local stat = self:_ubus("statistics")
1087 return stat and uint(stat.rx_bytes) or 0
1090 function interface.tx_packets(self)
1091 local stat = self:_ubus("statistics")
1092 return stat and uint(stat.tx_packets) or 0
1095 function interface.rx_packets(self)
1096 local stat = self:_ubus("statistics")
1097 return stat and uint(stat.rx_packets) or 0
1100 function interface.get_network(self)
1101 if not self.network then
1102 if self.dev and self.dev.network then
1103 self.network = _M:get_network(self.dev.network)
1107 if not self.network then
1109 for _, net in ipairs(_M:get_networks()) do
1110 if net:contains_interface(self.ifname) or
1111 net:ifname() == self.ifname
1122 function interface.get_wifinet(self)
1127 wifidev = utl.class()
1129 function wifidev.__init__(self, dev)
1131 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1134 function wifidev.get(self, opt)
1135 return _get("wireless", self.sid, opt)
1138 function wifidev.set(self, opt, val)
1139 return _set("wireless", self.sid, opt, val)
1142 function wifidev.name(self)
1146 function wifidev.hwmodes(self)
1147 local l = self.iwinfo.hwmodelist
1148 if l and next(l) then
1151 return { b = true, g = true }
1155 function wifidev.get_i18n(self)
1157 if self.iwinfo.type == "wl" then
1159 elseif self.iwinfo.type == "madwifi" then
1164 local l = self:hwmodes()
1165 if l.a then m = m .. "a" end
1166 if l.b then m = m .. "b" end
1167 if l.g then m = m .. "g" end
1168 if l.n then m = m .. "n" end
1170 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1173 function wifidev.is_up(self)
1176 _uci_state:foreach("wireless", "wifi-iface",
1178 if s.device == self.sid then
1189 function wifidev.get_wifinet(self, net)
1190 if _uci_real:get("wireless", net) == "wifi-iface" then
1193 local wnet = _wifi_lookup(net)
1195 return wifinet(wnet)
1200 function wifidev.get_wifinets(self)
1203 _uci_real:foreach("wireless", "wifi-iface",
1205 if s.device == self.sid then
1206 nets[#nets+1] = wifinet(s['.name'])
1213 function wifidev.add_wifinet(self, options)
1214 options = options or { }
1215 options.device = self.sid
1217 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1219 return wifinet(wnet, options)
1223 function wifidev.del_wifinet(self, net)
1224 if utl.instanceof(net, wifinet) then
1226 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1227 net = _wifi_lookup(net)
1230 if net and _uci_real:get("wireless", net, "device") == self.sid then
1231 _uci_real:delete("wireless", net)
1239 wifinet = utl.class()
1241 function wifinet.__init__(self, net, data)
1246 _uci_real:foreach("wireless", "wifi-iface",
1249 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1250 if s['.name'] == self.sid then
1251 netid = "%s.network%d" %{ s.device, num[s.device] }
1257 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1261 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1262 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1263 _uci_real:get_all("wireless", self.sid) or { }
1266 function wifinet.get(self, opt)
1267 return _get("wireless", self.sid, opt)
1270 function wifinet.set(self, opt, val)
1271 return _set("wireless", self.sid, opt, val)
1274 function wifinet.mode(self)
1275 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1278 function wifinet.ssid(self)
1279 return _uci_state:get("wireless", self.sid, "ssid")
1282 function wifinet.bssid(self)
1283 return _uci_state:get("wireless", self.sid, "bssid")
1286 function wifinet.network(self)
1287 return _uci_state:get("wifinet", self.sid, "network")
1290 function wifinet.id(self)
1294 function wifinet.name(self)
1298 function wifinet.ifname(self)
1299 local ifname = self.iwinfo.ifname
1300 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1306 function wifinet.get_device(self)
1307 if self.iwdata.device then
1308 return wifidev(self.iwdata.device)
1312 function wifinet.is_up(self)
1313 return (self.iwdata.up == "1")
1316 function wifinet.active_mode(self)
1317 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1319 if m == "ap" then m = "Master"
1320 elseif m == "sta" then m = "Client"
1321 elseif m == "adhoc" then m = "Ad-Hoc"
1322 elseif m == "mesh" then m = "Mesh"
1323 elseif m == "monitor" then m = "Monitor"
1329 function wifinet.active_mode_i18n(self)
1330 return i18n.translate(self:active_mode())
1333 function wifinet.active_ssid(self)
1334 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1337 function wifinet.active_bssid(self)
1338 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1341 function wifinet.active_encryption(self)
1342 local enc = self.iwinfo and self.iwinfo.encryption
1343 return enc and enc.description or "-"
1346 function wifinet.assoclist(self)
1347 return self.iwinfo.assoclist or { }
1350 function wifinet.frequency(self)
1351 local freq = self.iwinfo.frequency
1352 if freq and freq > 0 then
1353 return "%.03f" % (freq / 1000)
1357 function wifinet.bitrate(self)
1358 local rate = self.iwinfo.bitrate
1359 if rate and rate > 0 then
1360 return (rate / 1000)
1364 function wifinet.channel(self)
1365 return self.iwinfo.channel or
1366 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1369 function wifinet.signal(self)
1370 return self.iwinfo.signal or 0
1373 function wifinet.noise(self)
1374 return self.iwinfo.noise or 0
1377 function wifinet.country(self)
1378 return self.iwinfo.country or "00"
1381 function wifinet.txpower(self)
1382 local pwr = (self.iwinfo.txpower or 0)
1383 return pwr + self:txpower_offset()
1386 function wifinet.txpower_offset(self)
1387 return self.iwinfo.txpower_offset or 0
1390 function wifinet.signal_level(self, s, n)
1391 if self:active_bssid() ~= "00:00:00:00:00:00" then
1392 local signal = s or self:signal()
1393 local noise = n or self:noise()
1395 if signal < 0 and noise < 0 then
1396 local snr = -1 * (noise - signal)
1397 return math.floor(snr / 5)
1406 function wifinet.signal_percent(self)
1407 local qc = self.iwinfo.quality or 0
1408 local qm = self.iwinfo.quality_max or 0
1410 if qc > 0 and qm > 0 then
1411 return math.floor((100 / qm) * qc)
1417 function wifinet.shortname(self)
1419 i18n.translate(self:active_mode()),
1420 self:active_ssid() or self:active_bssid()
1424 function wifinet.get_i18n(self)
1425 return "%s: %s %q (%s)" %{
1426 i18n.translate("Wireless Network"),
1427 i18n.translate(self:active_mode()),
1428 self:active_ssid() or self:active_bssid(),
1433 function wifinet.adminlink(self)
1434 return dsp.build_url("admin", "network", "wireless", self.netid)
1437 function wifinet.get_network(self)
1438 local net = tostring(self.iwdata.network)
1439 if net and _uci_real:get("network", net) == "interface" then
1444 function wifinet.get_interface(self)
1445 return interface(self:ifname())
1449 -- setup base protocols
1450 _M:register_protocol("static")
1451 _M:register_protocol("dhcp")
1452 _M:register_protocol("none")
1454 -- load protocol extensions
1455 local exts = nfs.dir(utl.libpath() .. "/model/network")
1459 if ext:match("%.lua$") then
1460 require("luci.model.network." .. ext:gsub("%.lua$", ""))