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 = tonumber, tostring, math
25 local require = require
27 local bus = require "ubus"
28 local nxo = require "nixio"
29 local nfs = require "nixio.fs"
30 local ipc = require "luci.ip"
31 local sys = require "luci.sys"
32 local utl = require "luci.util"
33 local dsp = require "luci.dispatcher"
34 local uci = require "luci.model.uci"
35 local lng = require "luci.i18n"
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", "^gre%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, _ubuswificache
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_state(key, val, field)
138 if not next(_ubuswificache) then
139 _ubuswificache = _ubus:call("network.wireless", "status", {}) or {}
142 local radio, radiostate
143 for radio, radiostate in pairs(_ubuswificache) do
145 for ifc, ifcstate in pairs(radiostate.interfaces) do
146 if ifcstate[key] == val then
147 return ifcstate[field]
153 function _wifi_lookup(ifn)
154 -- got a radio#.network# pseudo iface, locate the corresponding section
155 local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
156 if radio and ifnidx then
160 ifnidx = tonumber(ifnidx)
161 _uci_real:foreach("wireless", "wifi-iface",
163 if s.device == radio then
165 if num == ifnidx then
174 -- looks like wifi, try to locate the section via state vars
175 elseif _wifi_iface(ifn) then
176 local sid = _wifi_state("ifname", ifn, "section")
178 _uci_state:foreach("wireless", "wifi-iface",
180 if s.ifname == ifn then
191 function _iface_virtual(x)
193 for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
201 function _iface_ignore(x)
203 for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
208 return _iface_virtual(x)
212 function init(cursor)
213 _uci_real = cursor or _uci_real or uci.cursor()
214 _uci_state = _uci_real:substate()
221 _ubus = bus.connect()
226 -- read interface information
228 for n, i in ipairs(nxo.getifaddrs()) do
229 local name = i.name:match("[^:]+")
230 local prnt = name:match("^([^%.]+)%.")
232 if _iface_virtual(name) then
236 if _tunnel[name] or not _iface_ignore(name) then
237 _interfaces[name] = _interfaces[name] or {
238 idx = i.ifindex or n,
251 if i.family == "packet" then
252 _interfaces[name].flags = i.flags
253 _interfaces[name].stats = i.data
254 _interfaces[name].macaddr = i.addr
255 elseif i.family == "inet" then
256 _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
257 elseif i.family == "inet6" then
258 _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
263 -- read bridge informaton
265 for l in utl.execi("brctl show") do
266 if not l:match("STP") then
267 local r = utl.split(l, "%s+", nil, true)
273 ifnames = { _interfaces[r[4]] }
276 b.ifnames[1].bridge = b
280 b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
281 b.ifnames[#b.ifnames].bridge = b
289 function save(self, ...)
294 function commit(self, ...)
295 _uci_real:commit(...)
299 function ifnameof(self, x)
300 if utl.instanceof(x, interface) then
302 elseif utl.instanceof(x, protocol) then
304 elseif type(x) == "string" then
305 return x:match("^[^:]+")
309 function get_protocol(self, protoname, netname)
310 local v = _protocols[protoname]
312 return v(netname or "__dummy__")
316 function get_protocols(self)
319 for _, v in ipairs(_protocols) do
320 p[#p+1] = v("__dummy__")
325 function register_protocol(self, protoname)
326 local proto = utl.class(protocol)
328 function proto.__init__(self, name)
332 function proto.proto(self)
336 _protocols[#_protocols+1] = proto
337 _protocols[protoname] = proto
342 function register_pattern_virtual(self, pat)
343 IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
347 function has_ipv6(self)
348 return nfs.access("/proc/net/ipv6_route")
351 function add_network(self, n, options)
352 local oldnet = self:get_network(n)
353 if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
354 if _uci_real:section("network", "interface", n, options) then
357 elseif oldnet and oldnet:is_empty() then
360 for k, v in pairs(options) do
368 function get_network(self, n)
369 if n and _uci_real:get("network", n) == "interface" then
374 function get_networks(self)
378 _uci_real:foreach("network", "interface",
380 nls[s['.name']] = network(s['.name'])
384 for n in utl.kspairs(nls) do
385 nets[#nets+1] = nls[n]
391 function del_network(self, n)
392 local r = _uci_real:delete("network", n)
394 _uci_real:delete_all("network", "alias",
395 function(s) return (s.interface == n) end)
397 _uci_real:delete_all("network", "route",
398 function(s) return (s.interface == n) end)
400 _uci_real:delete_all("network", "route6",
401 function(s) return (s.interface == n) end)
403 _uci_real:foreach("wireless", "wifi-iface",
407 for net in utl.imatch(s.network) do
413 _uci_real:set("wireless", s['.name'], "network",
414 table.concat(rest, " "))
416 _uci_real:delete("wireless", s['.name'], "network")
423 function rename_network(self, old, new)
425 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
426 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
429 _uci_real:foreach("network", "alias",
431 if s.interface == old then
432 _uci_real:set("network", s['.name'], "interface", new)
436 _uci_real:foreach("network", "route",
438 if s.interface == old then
439 _uci_real:set("network", s['.name'], "interface", new)
443 _uci_real:foreach("network", "route6",
445 if s.interface == old then
446 _uci_real:set("network", s['.name'], "interface", new)
450 _uci_real:foreach("wireless", "wifi-iface",
454 for net in utl.imatch(s.network) do
462 _uci_real:set("wireless", s['.name'], "network",
463 table.concat(list, " "))
467 _uci_real:delete("network", old)
473 function get_interface(self, i)
474 if _interfaces[i] or _wifi_iface(i) then
479 _uci_real:foreach("wireless", "wifi-iface",
482 num[s.device] = num[s.device] and num[s.device] + 1 or 1
483 if s['.name'] == i then
485 "%s.network%d" %{s.device, num[s.device] })
494 function get_interfaces(self)
501 -- find normal interfaces
502 _uci_real:foreach("network", "interface",
504 for iface in utl.imatch(s.ifname) do
505 if not _iface_ignore(iface) and not _wifi_iface(iface) then
507 nfs[iface] = interface(iface)
512 for iface in utl.kspairs(_interfaces) do
513 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
514 nfs[iface] = interface(iface)
518 -- find vlan interfaces
519 _uci_real:foreach("network", "switch_vlan",
525 local base = baseof[s.device]
527 if not s.device:match("^eth%d") then
529 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
531 base = l:match("^%w+: (%w+)")
534 if not base or not base:match("^eth%d") then
540 baseof[s.device] = base
543 local vid = tonumber(s.vid or s.vlan)
544 if vid ~= nil and vid >= 0 and vid <= 4095 then
545 local iface = "%s.%d" %{ base, vid }
546 if not seen[iface] then
548 nfs[iface] = interface(iface)
553 for iface in utl.kspairs(nfs) do
554 ifaces[#ifaces+1] = nfs[iface]
557 -- find wifi interfaces
560 _uci_real:foreach("wireless", "wifi-iface",
563 num[s.device] = num[s.device] and num[s.device] + 1 or 1
564 local i = "%s.network%d" %{ s.device, num[s.device] }
565 wfs[i] = interface(i)
569 for iface in utl.kspairs(wfs) do
570 ifaces[#ifaces+1] = wfs[iface]
576 function ignore_interface(self, x)
577 return _iface_ignore(x)
580 function get_wifidev(self, dev)
581 if _uci_real:get("wireless", dev) == "wifi-device" then
586 function get_wifidevs(self)
590 _uci_real:foreach("wireless", "wifi-device",
591 function(s) wfd[#wfd+1] = s['.name'] end)
594 for _, dev in utl.vspairs(wfd) do
595 devs[#devs+1] = wifidev(dev)
601 function get_wifinet(self, net)
602 local wnet = _wifi_lookup(net)
608 function add_wifinet(self, net, options)
609 if type(options) == "table" and options.device and
610 _uci_real:get("wireless", options.device) == "wifi-device"
612 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
617 function del_wifinet(self, net)
618 local wnet = _wifi_lookup(net)
620 _uci_real:delete("wireless", wnet)
626 function get_status_by_route(self, addr, mask)
628 for _, object in ipairs(_ubus:objects()) do
629 local net = object:match("^network%.interface%.(.+)")
631 local s = _ubus:call(object, "status", {})
632 if s and s.route then
634 for _, rt in ipairs(s.route) do
635 if not rt.table and rt.target == addr and rt.mask == mask then
644 function get_status_by_address(self, addr)
646 for _, object in ipairs(_ubus:objects()) do
647 local net = object:match("^network%.interface%.(.+)")
649 local s = _ubus:call(object, "status", {})
650 if s and s['ipv4-address'] then
652 for _, a in ipairs(s['ipv4-address']) do
653 if a.address == addr then
658 if s and s['ipv6-address'] then
660 for _, a in ipairs(s['ipv6-address']) do
661 if a.address == addr then
670 function get_wannet(self)
671 local net = self:get_status_by_route("0.0.0.0", 0)
672 return net and network(net)
675 function get_wandev(self)
676 local _, stat = self:get_status_by_route("0.0.0.0", 0)
677 return stat and interface(stat.l3_device or stat.device)
680 function get_wan6net(self)
681 local net = self:get_status_by_route("::", 0)
682 return net and network(net)
685 function get_wan6dev(self)
686 local _, stat = self:get_status_by_route("::", 0)
687 return stat and interface(stat.l3_device or stat.device)
691 function network(name, proto)
693 local p = proto or _uci_real:get("network", name, "proto")
694 local c = p and _protocols[p] or protocol
699 function protocol.__init__(self, name)
703 function protocol._get(self, opt)
704 local v = _uci_real:get("network", self.sid, opt)
705 if type(v) == "table" then
706 return table.concat(v, " ")
711 function protocol._ubus(self, field)
712 if not _ubusnetcache[self.sid] then
713 _ubusnetcache[self.sid] = _ubus:call("network.interface.%s" % self.sid,
716 if _ubusnetcache[self.sid] and field then
717 return _ubusnetcache[self.sid][field]
719 return _ubusnetcache[self.sid]
722 function protocol.get(self, opt)
723 return _get("network", self.sid, opt)
726 function protocol.set(self, opt, val)
727 return _set("network", self.sid, opt, val)
730 function protocol.ifname(self)
732 if self:is_floating() then
733 ifname = self:_ubus("l3_device")
735 ifname = self:_ubus("device")
739 _uci_real:foreach("wireless", "wifi-iface",
742 num[s.device] = num[s.device]
743 and num[s.device] + 1 or 1
746 for net in utl.imatch(s.network) do
747 if net == self.sid then
748 ifname = "%s.network%d" %{ s.device, num[s.device] }
758 function protocol.proto(self)
762 function protocol.get_i18n(self)
763 local p = self:proto()
765 return lng.translate("Unmanaged")
766 elseif p == "static" then
767 return lng.translate("Static address")
768 elseif p == "dhcp" then
769 return lng.translate("DHCP client")
771 return lng.translate("Unknown")
775 function protocol.type(self)
776 return self:_get("type")
779 function protocol.name(self)
783 function protocol.uptime(self)
784 return self:_ubus("uptime") or 0
787 function protocol.expires(self)
788 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
789 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
791 l = l - (nxo.sysinfo().uptime - a)
792 return l > 0 and l or 0
797 function protocol.metric(self)
798 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
801 function protocol.ipaddr(self)
802 local addrs = self:_ubus("ipv4-address")
803 return addrs and #addrs > 0 and addrs[1].address
806 function protocol.netmask(self)
807 local addrs = self:_ubus("ipv4-address")
808 return addrs and #addrs > 0 and
809 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
812 function protocol.gwaddr(self)
814 for _, route in ipairs(self:_ubus("route") or { }) do
815 if route.target == "0.0.0.0" and route.mask == 0 then
821 function protocol.dnsaddrs(self)
824 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
825 if not addr:match(":") then
832 function protocol.ip6addr(self)
833 local addrs = self:_ubus("ipv6-address")
834 if addrs and #addrs > 0 then
835 return "%s/%d" %{ addrs[1].address, addrs[1].mask }
837 addrs = self:_ubus("ipv6-prefix-assignment")
838 if addrs and #addrs > 0 then
839 return "%s/%d" %{ addrs[1].address, addrs[1].mask }
844 function protocol.gw6addr(self)
846 for _, route in ipairs(self:_ubus("route") or { }) do
847 if route.target == "::" and route.mask == 0 then
848 return ipc.IPv6(route.nexthop):string()
853 function protocol.dns6addrs(self)
856 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
857 if addr:match(":") then
864 function protocol.is_bridge(self)
865 return (not self:is_virtual() and self:type() == "bridge")
868 function protocol.opkg_package(self)
872 function protocol.is_installed(self)
876 function protocol.is_virtual(self)
880 function protocol.is_floating(self)
884 function protocol.is_empty(self)
885 if self:is_floating() then
890 if (self:_get("ifname") or ""):match("%S+") then
894 _uci_real:foreach("wireless", "wifi-iface",
897 for n in utl.imatch(s.network) do
898 if n == self.sid then
909 function protocol.add_interface(self, ifname)
910 ifname = _M:ifnameof(ifname)
911 if ifname and not self:is_floating() then
912 -- if its a wifi interface, change its network option
913 local wif = _wifi_lookup(ifname)
915 _append("wireless", wif, "network", self.sid)
917 -- add iface to our iface list
919 _append("network", self.sid, "ifname", ifname)
924 function protocol.del_interface(self, ifname)
925 ifname = _M:ifnameof(ifname)
926 if ifname and not self:is_floating() then
927 -- if its a wireless interface, clear its network option
928 local wif = _wifi_lookup(ifname)
929 if wif then _filter("wireless", wif, "network", self.sid) end
931 -- remove the interface
932 _filter("network", self.sid, "ifname", ifname)
936 function protocol.get_interface(self)
937 if self:is_virtual() then
938 _tunnel[self:proto() .. "-" .. self.sid] = true
939 return interface(self:proto() .. "-" .. self.sid, self)
940 elseif self:is_bridge() then
941 _bridge["br-" .. self.sid] = true
942 return interface("br-" .. self.sid, self)
946 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
947 ifn = ifn:match("^[^:/]+")
948 return ifn and interface(ifn, self)
951 _uci_real:foreach("wireless", "wifi-iface",
954 num[s.device] = num[s.device] and num[s.device] + 1 or 1
957 for net in utl.imatch(s.network) do
958 if net == self.sid then
959 ifn = "%s.network%d" %{ s.device, num[s.device] }
965 return ifn and interface(ifn, self)
969 function protocol.get_interfaces(self)
970 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
975 for ifn in utl.imatch(self:get("ifname")) do
976 ifn = ifn:match("^[^:/]+")
977 nfs[ifn] = interface(ifn, self)
980 for ifn in utl.kspairs(nfs) do
981 ifaces[#ifaces+1] = nfs[ifn]
986 _uci_real:foreach("wireless", "wifi-iface",
989 num[s.device] = num[s.device] and num[s.device] + 1 or 1
992 for net in utl.imatch(s.network) do
993 if net == self.sid then
994 ifn = "%s.network%d" %{ s.device, num[s.device] }
995 wfs[ifn] = interface(ifn, self)
1001 for ifn in utl.kspairs(wfs) do
1002 ifaces[#ifaces+1] = wfs[ifn]
1009 function protocol.contains_interface(self, ifname)
1010 ifname = _M:ifnameof(ifname)
1013 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
1015 elseif self:is_bridge() and "br-" .. self.sid == ifname then
1019 for ifn in utl.imatch(self:get("ifname")) do
1020 ifn = ifn:match("[^:]+")
1021 if ifn == ifname then
1026 local wif = _wifi_lookup(ifname)
1029 for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do
1030 if n == self.sid then
1040 function protocol.adminlink(self)
1041 return dsp.build_url("admin", "network", "network", self.sid)
1045 interface = utl.class()
1047 function interface.__init__(self, ifname, network)
1048 local wif = _wifi_lookup(ifname)
1050 self.wif = wifinet(wif)
1051 self.ifname = _wifi_state("section", wif, "ifname")
1054 self.ifname = self.ifname or ifname
1055 self.dev = _interfaces[self.ifname]
1056 self.network = network
1059 function interface._ubus(self, field)
1060 if not _ubusdevcache[self.ifname] then
1061 _ubusdevcache[self.ifname] = _ubus:call("network.device", "status",
1062 { name = self.ifname })
1064 if _ubusdevcache[self.ifname] and field then
1065 return _ubusdevcache[self.ifname][field]
1067 return _ubusdevcache[self.ifname]
1070 function interface.name(self)
1071 return self.wif and self.wif:ifname() or self.ifname
1074 function interface.mac(self)
1075 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
1078 function interface.ipaddrs(self)
1079 return self.dev and self.dev.ipaddrs or { }
1082 function interface.ip6addrs(self)
1083 return self.dev and self.dev.ip6addrs or { }
1086 function interface.type(self)
1087 if self.wif or _wifi_iface(self.ifname) then
1089 elseif _bridge[self.ifname] then
1091 elseif _tunnel[self.ifname] then
1093 elseif self.ifname:match("%.") then
1095 elseif _switch[self.ifname] then
1102 function interface.shortname(self)
1105 self.wif:active_mode(),
1106 self.wif:active_ssid() or self.wif:active_bssid()
1113 function interface.get_i18n(self)
1115 return "%s: %s %q" %{
1116 lng.translate("Wireless Network"),
1117 self.wif:active_mode(),
1118 self.wif:active_ssid() or self.wif:active_bssid()
1121 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1125 function interface.get_type_i18n(self)
1126 local x = self:type()
1128 return lng.translate("Wireless Adapter")
1129 elseif x == "bridge" then
1130 return lng.translate("Bridge")
1131 elseif x == "switch" then
1132 return lng.translate("Ethernet Switch")
1133 elseif x == "vlan" then
1134 return lng.translate("VLAN Interface")
1135 elseif x == "tunnel" then
1136 return lng.translate("Tunnel Interface")
1138 return lng.translate("Ethernet Adapter")
1142 function interface.adminlink(self)
1144 return self.wif:adminlink()
1148 function interface.ports(self)
1149 local members = self:_ubus("bridge-members")
1153 for _, iface in ipairs(members) do
1154 ifaces[#ifaces+1] = interface(iface)
1159 function interface.bridge_id(self)
1167 function interface.bridge_stp(self)
1175 function interface.is_up(self)
1176 return self:_ubus("up") or false
1179 function interface.is_bridge(self)
1180 return (self:type() == "bridge")
1183 function interface.is_bridgeport(self)
1184 return self.dev and self.dev.bridge and true or false
1187 function interface.tx_bytes(self)
1188 local stat = self:_ubus("statistics")
1189 return stat and stat.tx_bytes or 0
1192 function interface.rx_bytes(self)
1193 local stat = self:_ubus("statistics")
1194 return stat and stat.rx_bytes or 0
1197 function interface.tx_packets(self)
1198 local stat = self:_ubus("statistics")
1199 return stat and stat.tx_packets or 0
1202 function interface.rx_packets(self)
1203 local stat = self:_ubus("statistics")
1204 return stat and stat.rx_packets or 0
1207 function interface.get_network(self)
1208 return self:get_networks()[1]
1211 function interface.get_networks(self)
1212 if not self.networks then
1215 for _, net in ipairs(_M:get_networks()) do
1216 if net:contains_interface(self.ifname) or
1217 net:ifname() == self.ifname
1222 table.sort(nets, function(a, b) return a.sid < b.sid end)
1223 self.networks = nets
1226 return self.networks
1230 function interface.get_wifinet(self)
1235 wifidev = utl.class()
1237 function wifidev.__init__(self, dev)
1239 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1242 function wifidev.get(self, opt)
1243 return _get("wireless", self.sid, opt)
1246 function wifidev.set(self, opt, val)
1247 return _set("wireless", self.sid, opt, val)
1250 function wifidev.name(self)
1254 function wifidev.hwmodes(self)
1255 local l = self.iwinfo.hwmodelist
1256 if l and next(l) then
1259 return { b = true, g = true }
1263 function wifidev.get_i18n(self)
1265 if self.iwinfo.type == "wl" then
1267 elseif self.iwinfo.type == "madwifi" then
1272 local l = self:hwmodes()
1273 if l.a then m = m .. "a" end
1274 if l.b then m = m .. "b" end
1275 if l.g then m = m .. "g" end
1276 if l.n then m = m .. "n" end
1278 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1281 function wifidev.is_up(self)
1282 if _ubuswificache[self.sid] then
1283 return (_ubuswificache[self.sid].up == true)
1287 _uci_state:foreach("wireless", "wifi-iface",
1289 if s.device == self.sid then
1300 function wifidev.get_wifinet(self, net)
1301 if _uci_real:get("wireless", net) == "wifi-iface" then
1304 local wnet = _wifi_lookup(net)
1306 return wifinet(wnet)
1311 function wifidev.get_wifinets(self)
1314 _uci_real:foreach("wireless", "wifi-iface",
1316 if s.device == self.sid then
1317 nets[#nets+1] = wifinet(s['.name'])
1324 function wifidev.add_wifinet(self, options)
1325 options = options or { }
1326 options.device = self.sid
1328 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1330 return wifinet(wnet, options)
1334 function wifidev.del_wifinet(self, net)
1335 if utl.instanceof(net, wifinet) then
1337 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1338 net = _wifi_lookup(net)
1341 if net and _uci_real:get("wireless", net, "device") == self.sid then
1342 _uci_real:delete("wireless", net)
1350 wifinet = utl.class()
1352 function wifinet.__init__(self, net, data)
1357 _uci_real:foreach("wireless", "wifi-iface",
1360 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1361 if s['.name'] == self.sid then
1362 netid = "%s.network%d" %{ s.device, num[s.device] }
1368 local dev = _wifi_state("section", self.sid, "ifname") or netid
1372 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1373 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1374 _uci_real:get_all("wireless", self.sid) or { }
1377 function wifinet.get(self, opt)
1378 return _get("wireless", self.sid, opt)
1381 function wifinet.set(self, opt, val)
1382 return _set("wireless", self.sid, opt, val)
1385 function wifinet.mode(self)
1386 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1389 function wifinet.ssid(self)
1390 return _uci_state:get("wireless", self.sid, "ssid")
1393 function wifinet.bssid(self)
1394 return _uci_state:get("wireless", self.sid, "bssid")
1397 function wifinet.network(self)
1398 return _uci_state:get("wifinet", self.sid, "network")
1401 function wifinet.id(self)
1405 function wifinet.name(self)
1409 function wifinet.ifname(self)
1410 local ifname = self.iwinfo.ifname
1411 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1417 function wifinet.get_device(self)
1418 if self.iwdata.device then
1419 return wifidev(self.iwdata.device)
1423 function wifinet.is_up(self)
1424 local ifc = self:get_interface()
1425 return (ifc and ifc:is_up() or false)
1428 function wifinet.active_mode(self)
1429 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1431 if m == "ap" then m = "Master"
1432 elseif m == "sta" then m = "Client"
1433 elseif m == "adhoc" then m = "Ad-Hoc"
1434 elseif m == "mesh" then m = "Mesh"
1435 elseif m == "monitor" then m = "Monitor"
1441 function wifinet.active_mode_i18n(self)
1442 return lng.translate(self:active_mode())
1445 function wifinet.active_ssid(self)
1446 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1449 function wifinet.active_bssid(self)
1450 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1453 function wifinet.active_encryption(self)
1454 local enc = self.iwinfo and self.iwinfo.encryption
1455 return enc and enc.description or "-"
1458 function wifinet.assoclist(self)
1459 return self.iwinfo.assoclist or { }
1462 function wifinet.frequency(self)
1463 local freq = self.iwinfo.frequency
1464 if freq and freq > 0 then
1465 return "%.03f" % (freq / 1000)
1469 function wifinet.bitrate(self)
1470 local rate = self.iwinfo.bitrate
1471 if rate and rate > 0 then
1472 return (rate / 1000)
1476 function wifinet.channel(self)
1477 return self.iwinfo.channel or
1478 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1481 function wifinet.signal(self)
1482 return self.iwinfo.signal or 0
1485 function wifinet.noise(self)
1486 return self.iwinfo.noise or 0
1489 function wifinet.country(self)
1490 return self.iwinfo.country or "00"
1493 function wifinet.txpower(self)
1494 local pwr = (self.iwinfo.txpower or 0)
1495 return pwr + self:txpower_offset()
1498 function wifinet.txpower_offset(self)
1499 return self.iwinfo.txpower_offset or 0
1502 function wifinet.signal_level(self, s, n)
1503 if self:active_bssid() ~= "00:00:00:00:00:00" then
1504 local signal = s or self:signal()
1505 local noise = n or self:noise()
1507 if signal < 0 and noise < 0 then
1508 local snr = -1 * (noise - signal)
1509 return math.floor(snr / 5)
1518 function wifinet.signal_percent(self)
1519 local qc = self.iwinfo.quality or 0
1520 local qm = self.iwinfo.quality_max or 0
1522 if qc > 0 and qm > 0 then
1523 return math.floor((100 / qm) * qc)
1529 function wifinet.shortname(self)
1531 lng.translate(self:active_mode()),
1532 self:active_ssid() or self:active_bssid()
1536 function wifinet.get_i18n(self)
1537 return "%s: %s %q (%s)" %{
1538 lng.translate("Wireless Network"),
1539 lng.translate(self:active_mode()),
1540 self:active_ssid() or self:active_bssid(),
1545 function wifinet.adminlink(self)
1546 return dsp.build_url("admin", "network", "wireless", self.netid)
1549 function wifinet.get_network(self)
1550 return self:get_networks()[1]
1553 function wifinet.get_networks(self)
1556 for net in utl.imatch(tostring(self.iwdata.network)) do
1557 if _uci_real:get("network", net) == "interface" then
1558 nets[#nets+1] = network(net)
1561 table.sort(nets, function(a, b) return a.sid < b.sid end)
1565 function wifinet.get_interface(self)
1566 return interface(self:ifname())
1570 -- setup base protocols
1571 _M:register_protocol("static")
1572 _M:register_protocol("dhcp")
1573 _M:register_protocol("none")
1575 -- load protocol extensions
1576 local exts = nfs.dir(utl.libpath() .. "/model/network")
1580 if ext:match("%.lua$") then
1581 require("luci.model.network." .. ext:gsub("%.lua$", ""))