4 Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.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 = tonumber, tostring, math
25 local require = require
27 local nxo = require "nixio"
28 local nfs = require "nixio.fs"
29 local ipc = require "luci.ip"
30 local sys = require "luci.sys"
31 local utl = require "luci.util"
32 local dsp = require "luci.dispatcher"
33 local uci = require "luci.model.uci"
34 local lng = require "luci.i18n"
36 module "luci.model.network"
39 IFACE_PATTERNS_VIRTUAL = { }
40 IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^gre%d", "^lo$" }
41 IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
44 protocol = utl.class()
46 local _protocols = { }
48 local _interfaces, _bridge, _switch, _tunnel
49 local _ubusnetcache, _ubusdevcache, _ubuswificache
50 local _uci_real, _uci_state
52 function _filter(c, s, o, r)
53 local val = _uci_real:get(c, s, o)
56 if type(val) == "string" then
57 for val in val:gmatch("%S+") do
63 _uci_real:set(c, s, o, table.concat(l, " "))
65 _uci_real:delete(c, s, o)
67 elseif type(val) == "table" then
68 for _, val in ipairs(val) do
74 _uci_real:set(c, s, o, l)
76 _uci_real:delete(c, s, o)
82 function _append(c, s, o, a)
83 local val = _uci_real:get(c, s, o) or ""
84 if type(val) == "string" then
86 for val in val:gmatch("%S+") do
92 _uci_real:set(c, s, o, table.concat(l, " "))
93 elseif type(val) == "table" then
95 for _, val in ipairs(val) do
101 _uci_real:set(c, s, o, l)
105 function _stror(s1, s2)
106 if not s1 or #s1 == 0 then
107 return s2 and #s2 > 0 and s2
113 function _get(c, s, o)
114 return _uci_real:get(c, s, o)
117 function _set(c, s, o, v)
119 if type(v) == "boolean" then v = v and "1" or "0" end
120 return _uci_real:set(c, s, o, v)
122 return _uci_real:delete(c, s, o)
126 function _wifi_iface(x)
128 for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
136 function _wifi_state(key, val, field)
137 local radio, radiostate, ifc, ifcstate
139 if not next(_ubuswificache) then
140 _ubuswificache = utl.ubus("network.wireless", "status", {}) or {}
142 -- workaround extended section format
143 for radio, radiostate in pairs(_ubuswificache) do
144 for ifc, ifcstate in pairs(radiostate.interfaces) do
145 if ifcstate.section and ifcstate.section:sub(1, 1) == '@' then
146 local s = _uci_real:get_all('wireless.%s' % ifcstate.section)
148 ifcstate.section = s['.name']
155 for radio, radiostate in pairs(_ubuswificache) do
156 for ifc, ifcstate in pairs(radiostate.interfaces) do
157 if ifcstate[key] == val then
158 return ifcstate[field]
164 function _wifi_lookup(ifn)
165 -- got a radio#.network# pseudo iface, locate the corresponding section
166 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
167 if radio and ifnidx then
171 ifnidx = tonumber(ifnidx)
172 _uci_real:foreach("wireless", "wifi-iface",
174 if s.device == radio then
176 if num == ifnidx then
185 -- looks like wifi, try to locate the section via state vars
186 elseif _wifi_iface(ifn) then
187 local sid = _wifi_state("ifname", ifn, "section")
189 _uci_state:foreach("wireless", "wifi-iface",
191 if s.ifname == ifn then
202 function _iface_virtual(x)
204 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
212 function _iface_ignore(x)
214 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
219 return _iface_virtual(x)
223 function init(cursor)
224 _uci_real = cursor or _uci_real or uci.cursor()
225 _uci_state = _uci_real:substate()
236 -- read interface information
238 for n, i in ipairs(nxo.getifaddrs()) do
239 local name = i.name:match("[^:]+")
240 local prnt = name:match("^([^%.]+)%.")
242 if _iface_virtual(name) then
246 if _tunnel[name] or not _iface_ignore(name) then
247 _interfaces[name] = _interfaces[name] or {
248 idx = i.ifindex or n,
261 if i.family == "packet" then
262 _interfaces[name].flags = i.flags
263 _interfaces[name].stats = i.data
264 _interfaces[name].macaddr = i.addr
265 elseif i.family == "inet" then
266 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
267 elseif i.family == "inet6" then
268 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
273 -- read bridge informaton
275 for l in utl.execi("brctl show") do
276 if not l:match("STP") then
277 local r = utl.split(l, "%s+", nil, true)
283 ifnames = { _interfaces[r[4]] }
286 b.ifnames[1].bridge = b
290 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
291 b.ifnames[#b.ifnames].bridge = b
299 function save(self, ...)
304 function commit(self, ...)
305 _uci_real:commit(...)
309 function ifnameof(self, x)
310 if utl.instanceof(x, interface) then
312 elseif utl.instanceof(x, protocol) then
314 elseif type(x) == "string" then
315 return x:match("^[^:]+")
319 function get_protocol(self, protoname, netname)
320 local v = _protocols[protoname]
322 return v(netname or "__dummy__")
326 function get_protocols(self)
329 for _, v in ipairs(_protocols) do
330 p[#p+1] = v("__dummy__")
335 function register_protocol(self, protoname)
336 local proto = utl.class(protocol)
338 function proto.__init__(self, name)
342 function proto.proto(self)
346 _protocols[#_protocols+1] = proto
347 _protocols[protoname] = proto
352 function register_pattern_virtual(self, pat)
353 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
357 function has_ipv6(self)
358 return nfs.access("/proc/net/ipv6_route")
361 function add_network(self, n, options)
362 local oldnet = self:get_network(n)
363 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
364 if _uci_real:section("network", "interface", n, options) then
367 elseif oldnet and oldnet:is_empty() then
370 for k, v in pairs(options) do
378 function get_network(self, n)
379 if n and _uci_real:get("network", n) == "interface" then
384 function get_networks(self)
388 _uci_real:foreach("network", "interface",
390 nls[s['.name']] = network(s['.name'])
394 for n in utl.kspairs(nls) do
395 nets[#nets+1] = nls[n]
401 function del_network(self, n)
402 local r = _uci_real:delete("network", n)
404 _uci_real:delete_all("network", "alias",
405 function(s) return (s.interface == n) end)
407 _uci_real:delete_all("network", "route",
408 function(s) return (s.interface == n) end)
410 _uci_real:delete_all("network", "route6",
411 function(s) return (s.interface == n) end)
413 _uci_real:foreach("wireless", "wifi-iface",
417 for net in utl.imatch(s.network) do
423 _uci_real:set("wireless", s['.name'], "network",
424 table.concat(rest, " "))
426 _uci_real:delete("wireless", s['.name'], "network")
433 function rename_network(self, old, new)
435 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
436 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
439 _uci_real:foreach("network", "alias",
441 if s.interface == old then
442 _uci_real:set("network", s['.name'], "interface", new)
446 _uci_real:foreach("network", "route",
448 if s.interface == old then
449 _uci_real:set("network", s['.name'], "interface", new)
453 _uci_real:foreach("network", "route6",
455 if s.interface == old then
456 _uci_real:set("network", s['.name'], "interface", new)
460 _uci_real:foreach("wireless", "wifi-iface",
464 for net in utl.imatch(s.network) do
472 _uci_real:set("wireless", s['.name'], "network",
473 table.concat(list, " "))
477 _uci_real:delete("network", old)
483 function get_interface(self, i)
484 if _interfaces[i] or _wifi_iface(i) then
489 _uci_real:foreach("wireless", "wifi-iface",
492 num[s.device] = num[s.device] and num[s.device] + 1 or 1
493 if s['.name'] == i then
495 "%s.network%d" %{s.device, num[s.device] })
504 function get_interfaces(self)
511 -- find normal interfaces
512 _uci_real:foreach("network", "interface",
514 for iface in utl.imatch(s.ifname) do
515 if not _iface_ignore(iface) and not _wifi_iface(iface) then
517 nfs[iface] = interface(iface)
522 for iface in utl.kspairs(_interfaces) do
523 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
524 nfs[iface] = interface(iface)
528 -- find vlan interfaces
529 _uci_real:foreach("network", "switch_vlan",
535 local base = baseof[s.device]
537 if not s.device:match("^eth%d") then
539 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
541 base = l:match("^%w+: (%w+)")
544 if not base or not base:match("^eth%d") then
550 baseof[s.device] = base
553 local vid = tonumber(s.vid or s.vlan)
554 if vid ~= nil and vid >= 0 and vid <= 4095 then
555 local iface = "%s.%d" %{ base, vid }
556 if not seen[iface] then
558 nfs[iface] = interface(iface)
563 for iface in utl.kspairs(nfs) do
564 ifaces[#ifaces+1] = nfs[iface]
567 -- find wifi interfaces
570 _uci_real:foreach("wireless", "wifi-iface",
573 num[s.device] = num[s.device] and num[s.device] + 1 or 1
574 local i = "%s.network%d" %{ s.device, num[s.device] }
575 wfs[i] = interface(i)
579 for iface in utl.kspairs(wfs) do
580 ifaces[#ifaces+1] = wfs[iface]
586 function ignore_interface(self, x)
587 return _iface_ignore(x)
590 function get_wifidev(self, dev)
591 if _uci_real:get("wireless", dev) == "wifi-device" then
596 function get_wifidevs(self)
600 _uci_real:foreach("wireless", "wifi-device",
601 function(s) wfd[#wfd+1] = s['.name'] end)
604 for _, dev in utl.vspairs(wfd) do
605 devs[#devs+1] = wifidev(dev)
611 function get_wifinet(self, net)
612 local wnet = _wifi_lookup(net)
618 function add_wifinet(self, net, options)
619 if type(options) == "table" and options.device and
620 _uci_real:get("wireless", options.device) == "wifi-device"
622 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
627 function del_wifinet(self, net)
628 local wnet = _wifi_lookup(net)
630 _uci_real:delete("wireless", wnet)
636 function get_status_by_route(self, addr, mask)
638 for _, object in ipairs(utl.ubus()) do
639 local net = object:match("^network%.interface%.(.+)")
641 local s = utl.ubus(object, "status", {})
642 if s and s.route then
644 for _, rt in ipairs(s.route) do
645 if not rt.table and rt.target == addr and rt.mask == mask then
654 function get_status_by_address(self, addr)
656 for _, object in ipairs(utl.ubus()) do
657 local net = object:match("^network%.interface%.(.+)")
659 local s = utl.ubus(object, "status", {})
660 if s and s['ipv4-address'] then
662 for _, a in ipairs(s['ipv4-address']) do
663 if a.address == addr then
668 if s and s['ipv6-address'] then
670 for _, a in ipairs(s['ipv6-address']) do
671 if a.address == addr then
680 function get_wannet(self)
681 local net = self:get_status_by_route("0.0.0.0", 0)
682 return net and network(net)
685 function get_wandev(self)
686 local _, stat = self:get_status_by_route("0.0.0.0", 0)
687 return stat and interface(stat.l3_device or stat.device)
690 function get_wan6net(self)
691 local net = self:get_status_by_route("::", 0)
692 return net and network(net)
695 function get_wan6dev(self)
696 local _, stat = self:get_status_by_route("::", 0)
697 return stat and interface(stat.l3_device or stat.device)
701 function network(name, proto)
703 local p = proto or _uci_real:get("network", name, "proto")
704 local c = p and _protocols[p] or protocol
709 function protocol.__init__(self, name)
713 function protocol._get(self, opt)
714 local v = _uci_real:get("network", self.sid, opt)
715 if type(v) == "table" then
716 return table.concat(v, " ")
721 function protocol._ubus(self, field)
722 if not _ubusnetcache[self.sid] then
723 _ubusnetcache[self.sid] = utl.ubus("network.interface.%s" % self.sid,
726 if _ubusnetcache[self.sid] and field then
727 return _ubusnetcache[self.sid][field]
729 return _ubusnetcache[self.sid]
732 function protocol.get(self, opt)
733 return _get("network", self.sid, opt)
736 function protocol.set(self, opt, val)
737 return _set("network", self.sid, opt, val)
740 function protocol.ifname(self)
742 if self:is_floating() then
743 ifname = self:_ubus("l3_device")
745 ifname = self:_ubus("device")
749 _uci_real:foreach("wireless", "wifi-iface",
752 num[s.device] = num[s.device]
753 and num[s.device] + 1 or 1
756 for net in utl.imatch(s.network) do
757 if net == self.sid then
758 ifname = "%s.network%d" %{ s.device, num[s.device] }
768 function protocol.proto(self)
772 function protocol.get_i18n(self)
773 local p = self:proto()
775 return lng.translate("Unmanaged")
776 elseif p == "static" then
777 return lng.translate("Static address")
778 elseif p == "dhcp" then
779 return lng.translate("DHCP client")
781 return lng.translate("Unknown")
785 function protocol.type(self)
786 return self:_get("type")
789 function protocol.name(self)
793 function protocol.uptime(self)
794 return self:_ubus("uptime") or 0
797 function protocol.expires(self)
798 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
799 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
801 l = l - (nxo.sysinfo().uptime - a)
802 return l > 0 and l or 0
807 function protocol.metric(self)
808 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
811 function protocol.ipaddr(self)
812 local addrs = self:_ubus("ipv4-address")
813 return addrs and #addrs > 0 and addrs[1].address
816 function protocol.netmask(self)
817 local addrs = self:_ubus("ipv4-address")
818 return addrs and #addrs > 0 and
819 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
822 function protocol.gwaddr(self)
824 for _, route in ipairs(self:_ubus("route") or { }) do
825 if route.target == "0.0.0.0" and route.mask == 0 then
831 function protocol.dnsaddrs(self)
834 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
835 if not addr:match(":") then
842 function protocol.ip6addr(self)
843 local addrs = self:_ubus("ipv6-address")
844 if addrs and #addrs > 0 then
845 return "%s/%d" %{ addrs[1].address, addrs[1].mask }
847 addrs = self:_ubus("ipv6-prefix-assignment")
848 if addrs and #addrs > 0 then
849 return "%s/%d" %{ addrs[1].address, addrs[1].mask }
854 function protocol.gw6addr(self)
856 for _, route in ipairs(self:_ubus("route") or { }) do
857 if route.target == "::" and route.mask == 0 then
858 return ipc.IPv6(route.nexthop):string()
863 function protocol.dns6addrs(self)
866 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
867 if addr:match(":") then
874 function protocol.is_bridge(self)
875 return (not self:is_virtual() and self:type() == "bridge")
878 function protocol.opkg_package(self)
882 function protocol.is_installed(self)
886 function protocol.is_virtual(self)
890 function protocol.is_floating(self)
894 function protocol.is_empty(self)
895 if self:is_floating() then
900 if (self:_get("ifname") or ""):match("%S+") then
904 _uci_real:foreach("wireless", "wifi-iface",
907 for n in utl.imatch(s.network) do
908 if n == self.sid then
919 function protocol.add_interface(self, ifname)
920 ifname = _M:ifnameof(ifname)
921 if ifname and not self:is_floating() then
922 -- if its a wifi interface, change its network option
923 local wif = _wifi_lookup(ifname)
925 _append("wireless", wif, "network", self.sid)
927 -- add iface to our iface list
929 _append("network", self.sid, "ifname", ifname)
934 function protocol.del_interface(self, ifname)
935 ifname = _M:ifnameof(ifname)
936 if ifname and not self:is_floating() then
937 -- if its a wireless interface, clear its network option
938 local wif = _wifi_lookup(ifname)
939 if wif then _filter("wireless", wif, "network", self.sid) end
941 -- remove the interface
942 _filter("network", self.sid, "ifname", ifname)
946 function protocol.get_interface(self)
947 if self:is_virtual() then
948 _tunnel[self:proto() .. "-" .. self.sid] = true
949 return interface(self:proto() .. "-" .. self.sid, self)
950 elseif self:is_bridge() then
951 _bridge["br-" .. self.sid] = true
952 return interface("br-" .. self.sid, self)
956 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
957 ifn = ifn:match("^[^:/]+")
958 return ifn and interface(ifn, self)
961 _uci_real:foreach("wireless", "wifi-iface",
964 num[s.device] = num[s.device] and num[s.device] + 1 or 1
967 for net in utl.imatch(s.network) do
968 if net == self.sid then
969 ifn = "%s.network%d" %{ s.device, num[s.device] }
975 return ifn and interface(ifn, self)
979 function protocol.get_interfaces(self)
980 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
985 for ifn in utl.imatch(self:get("ifname")) do
986 ifn = ifn:match("^[^:/]+")
987 nfs[ifn] = interface(ifn, self)
990 for ifn in utl.kspairs(nfs) do
991 ifaces[#ifaces+1] = nfs[ifn]
996 _uci_real:foreach("wireless", "wifi-iface",
999 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1002 for net in utl.imatch(s.network) do
1003 if net == self.sid then
1004 ifn = "%s.network%d" %{ s.device, num[s.device] }
1005 wfs[ifn] = interface(ifn, self)
1011 for ifn in utl.kspairs(wfs) do
1012 ifaces[#ifaces+1] = wfs[ifn]
1019 function protocol.contains_interface(self, ifname)
1020 ifname = _M:ifnameof(ifname)
1023 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
1025 elseif self:is_bridge() and "br-" .. self.sid == ifname then
1029 for ifn in utl.imatch(self:get("ifname")) do
1030 ifn = ifn:match("[^:]+")
1031 if ifn == ifname then
1036 local wif = _wifi_lookup(ifname)
1039 for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do
1040 if n == self.sid then
1050 function protocol.adminlink(self)
1051 return dsp.build_url("admin", "network", "network", self.sid)
1055 interface = utl.class()
1057 function interface.__init__(self, ifname, network)
1058 local wif = _wifi_lookup(ifname)
1060 self.wif = wifinet(wif)
1061 self.ifname = _wifi_state("section", wif, "ifname")
1064 self.ifname = self.ifname or ifname
1065 self.dev = _interfaces[self.ifname]
1066 self.network = network
1069 function interface._ubus(self, field)
1070 if not _ubusdevcache[self.ifname] then
1071 _ubusdevcache[self.ifname] = utl.ubus("network.device", "status",
1072 { name = self.ifname })
1074 if _ubusdevcache[self.ifname] and field then
1075 return _ubusdevcache[self.ifname][field]
1077 return _ubusdevcache[self.ifname]
1080 function interface.name(self)
1081 return self.wif and self.wif:ifname() or self.ifname
1084 function interface.mac(self)
1085 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
1088 function interface.ipaddrs(self)
1089 return self.dev and self.dev.ipaddrs or { }
1092 function interface.ip6addrs(self)
1093 return self.dev and self.dev.ip6addrs or { }
1096 function interface.type(self)
1097 if self.wif or _wifi_iface(self.ifname) then
1099 elseif _bridge[self.ifname] then
1101 elseif _tunnel[self.ifname] then
1103 elseif self.ifname:match("%.") then
1105 elseif _switch[self.ifname] then
1112 function interface.shortname(self)
1115 self.wif:active_mode(),
1116 self.wif:active_ssid() or self.wif:active_bssid()
1123 function interface.get_i18n(self)
1125 return "%s: %s %q" %{
1126 lng.translate("Wireless Network"),
1127 self.wif:active_mode(),
1128 self.wif:active_ssid() or self.wif:active_bssid()
1131 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1135 function interface.get_type_i18n(self)
1136 local x = self:type()
1138 return lng.translate("Wireless Adapter")
1139 elseif x == "bridge" then
1140 return lng.translate("Bridge")
1141 elseif x == "switch" then
1142 return lng.translate("Ethernet Switch")
1143 elseif x == "vlan" then
1144 return lng.translate("VLAN Interface")
1145 elseif x == "tunnel" then
1146 return lng.translate("Tunnel Interface")
1148 return lng.translate("Ethernet Adapter")
1152 function interface.adminlink(self)
1154 return self.wif:adminlink()
1158 function interface.ports(self)
1159 local members = self:_ubus("bridge-members")
1163 for _, iface in ipairs(members) do
1164 ifaces[#ifaces+1] = interface(iface)
1169 function interface.bridge_id(self)
1177 function interface.bridge_stp(self)
1185 function interface.is_up(self)
1186 return self:_ubus("up") or false
1189 function interface.is_bridge(self)
1190 return (self:type() == "bridge")
1193 function interface.is_bridgeport(self)
1194 return self.dev and self.dev.bridge and true or false
1197 function interface.tx_bytes(self)
1198 local stat = self:_ubus("statistics")
1199 return stat and stat.tx_bytes or 0
1202 function interface.rx_bytes(self)
1203 local stat = self:_ubus("statistics")
1204 return stat and stat.rx_bytes or 0
1207 function interface.tx_packets(self)
1208 local stat = self:_ubus("statistics")
1209 return stat and stat.tx_packets or 0
1212 function interface.rx_packets(self)
1213 local stat = self:_ubus("statistics")
1214 return stat and stat.rx_packets or 0
1217 function interface.get_network(self)
1218 return self:get_networks()[1]
1221 function interface.get_networks(self)
1222 if not self.networks then
1225 for _, net in ipairs(_M:get_networks()) do
1226 if net:contains_interface(self.ifname) or
1227 net:ifname() == self.ifname
1232 table.sort(nets, function(a, b) return a.sid < b.sid end)
1233 self.networks = nets
1236 return self.networks
1240 function interface.get_wifinet(self)
1245 wifidev = utl.class()
1247 function wifidev.__init__(self, dev)
1249 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1252 function wifidev.get(self, opt)
1253 return _get("wireless", self.sid, opt)
1256 function wifidev.set(self, opt, val)
1257 return _set("wireless", self.sid, opt, val)
1260 function wifidev.name(self)
1264 function wifidev.hwmodes(self)
1265 local l = self.iwinfo.hwmodelist
1266 if l and next(l) then
1269 return { b = true, g = true }
1273 function wifidev.get_i18n(self)
1275 if self.iwinfo.type == "wl" then
1277 elseif self.iwinfo.type == "madwifi" then
1282 local l = self:hwmodes()
1283 if l.a then m = m .. "a" end
1284 if l.b then m = m .. "b" end
1285 if l.g then m = m .. "g" end
1286 if l.n then m = m .. "n" end
1287 if l.ac then m = "ac" end
1289 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1292 function wifidev.is_up(self)
1293 if _ubuswificache[self.sid] then
1294 return (_ubuswificache[self.sid].up == true)
1298 _uci_state:foreach("wireless", "wifi-iface",
1300 if s.device == self.sid then
1311 function wifidev.get_wifinet(self, net)
1312 if _uci_real:get("wireless", net) == "wifi-iface" then
1315 local wnet = _wifi_lookup(net)
1317 return wifinet(wnet)
1322 function wifidev.get_wifinets(self)
1325 _uci_real:foreach("wireless", "wifi-iface",
1327 if s.device == self.sid then
1328 nets[#nets+1] = wifinet(s['.name'])
1335 function wifidev.add_wifinet(self, options)
1336 options = options or { }
1337 options.device = self.sid
1339 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1341 return wifinet(wnet, options)
1345 function wifidev.del_wifinet(self, net)
1346 if utl.instanceof(net, wifinet) then
1348 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1349 net = _wifi_lookup(net)
1352 if net and _uci_real:get("wireless", net, "device") == self.sid then
1353 _uci_real:delete("wireless", net)
1361 wifinet = utl.class()
1363 function wifinet.__init__(self, net, data)
1368 _uci_real:foreach("wireless", "wifi-iface",
1371 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1372 if s['.name'] == self.sid then
1373 netid = "%s.network%d" %{ s.device, num[s.device] }
1379 local dev = _wifi_state("section", self.sid, "ifname") or netid
1383 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1384 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1385 _uci_real:get_all("wireless", self.sid) or { }
1388 function wifinet.get(self, opt)
1389 return _get("wireless", self.sid, opt)
1392 function wifinet.set(self, opt, val)
1393 return _set("wireless", self.sid, opt, val)
1396 function wifinet.mode(self)
1397 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1400 function wifinet.ssid(self)
1401 return _uci_state:get("wireless", self.sid, "ssid")
1404 function wifinet.bssid(self)
1405 return _uci_state:get("wireless", self.sid, "bssid")
1408 function wifinet.network(self)
1409 return _uci_state:get("wifinet", self.sid, "network")
1412 function wifinet.id(self)
1416 function wifinet.name(self)
1420 function wifinet.ifname(self)
1421 local ifname = self.iwinfo.ifname
1422 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1428 function wifinet.get_device(self)
1429 if self.iwdata.device then
1430 return wifidev(self.iwdata.device)
1434 function wifinet.is_up(self)
1435 local ifc = self:get_interface()
1436 return (ifc and ifc:is_up() or false)
1439 function wifinet.active_mode(self)
1440 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1442 if m == "ap" then m = "Master"
1443 elseif m == "sta" then m = "Client"
1444 elseif m == "adhoc" then m = "Ad-Hoc"
1445 elseif m == "mesh" then m = "Mesh"
1446 elseif m == "monitor" then m = "Monitor"
1452 function wifinet.active_mode_i18n(self)
1453 return lng.translate(self:active_mode())
1456 function wifinet.active_ssid(self)
1457 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1460 function wifinet.active_bssid(self)
1461 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1464 function wifinet.active_encryption(self)
1465 local enc = self.iwinfo and self.iwinfo.encryption
1466 return enc and enc.description or "-"
1469 function wifinet.assoclist(self)
1470 return self.iwinfo.assoclist or { }
1473 function wifinet.frequency(self)
1474 local freq = self.iwinfo.frequency
1475 if freq and freq > 0 then
1476 return "%.03f" % (freq / 1000)
1480 function wifinet.bitrate(self)
1481 local rate = self.iwinfo.bitrate
1482 if rate and rate > 0 then
1483 return (rate / 1000)
1487 function wifinet.channel(self)
1488 return self.iwinfo.channel or
1489 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1492 function wifinet.signal(self)
1493 return self.iwinfo.signal or 0
1496 function wifinet.noise(self)
1497 return self.iwinfo.noise or 0
1500 function wifinet.country(self)
1501 return self.iwinfo.country or "00"
1504 function wifinet.txpower(self)
1505 local pwr = (self.iwinfo.txpower or 0)
1506 return pwr + self:txpower_offset()
1509 function wifinet.txpower_offset(self)
1510 return self.iwinfo.txpower_offset or 0
1513 function wifinet.signal_level(self, s, n)
1514 if self:active_bssid() ~= "00:00:00:00:00:00" then
1515 local signal = s or self:signal()
1516 local noise = n or self:noise()
1518 if signal < 0 and noise < 0 then
1519 local snr = -1 * (noise - signal)
1520 return math.floor(snr / 5)
1529 function wifinet.signal_percent(self)
1530 local qc = self.iwinfo.quality or 0
1531 local qm = self.iwinfo.quality_max or 0
1533 if qc > 0 and qm > 0 then
1534 return math.floor((100 / qm) * qc)
1540 function wifinet.shortname(self)
1542 lng.translate(self:active_mode()),
1543 self:active_ssid() or self:active_bssid()
1547 function wifinet.get_i18n(self)
1548 return "%s: %s %q (%s)" %{
1549 lng.translate("Wireless Network"),
1550 lng.translate(self:active_mode()),
1551 self:active_ssid() or self:active_bssid(),
1556 function wifinet.adminlink(self)
1557 return dsp.build_url("admin", "network", "wireless", self.netid)
1560 function wifinet.get_network(self)
1561 return self:get_networks()[1]
1564 function wifinet.get_networks(self)
1567 for net in utl.imatch(tostring(self.iwdata.network)) do
1568 if _uci_real:get("network", net) == "interface" then
1569 nets[#nets+1] = network(net)
1572 table.sort(nets, function(a, b) return a.sid < b.sid end)
1576 function wifinet.get_interface(self)
1577 return interface(self:ifname())
1581 -- setup base protocols
1582 _M:register_protocol("static")
1583 _M:register_protocol("dhcp")
1584 _M:register_protocol("none")
1586 -- load protocol extensions
1587 local exts = nfs.dir(utl.libpath() .. "/model/network")
1591 if ext:match("%.lua$") then
1592 require("luci.model.network." .. ext:gsub("%.lua$", ""))