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
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",
389 for net in utl.imatch(s.network) do
395 _uci_real:set("wireless", s['.name'], "network",
396 table.concat(rest, " "))
398 _uci_real:delete("wireless", s['.name'], "network")
405 function rename_network(self, old, new)
407 if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
408 r = _uci_real:section("network", "interface", new, _uci_real:get_all("network", old))
411 _uci_real:foreach("network", "alias",
413 if s.interface == old then
414 _uci_real:set("network", s['.name'], "interface", new)
418 _uci_real:foreach("network", "route",
420 if s.interface == old then
421 _uci_real:set("network", s['.name'], "interface", new)
425 _uci_real:foreach("network", "route6",
427 if s.interface == old then
428 _uci_real:set("network", s['.name'], "interface", new)
432 _uci_real:foreach("wireless", "wifi-iface",
436 for net in utl.imatch(s.network) do
444 _uci_real:set("wireless", s['.name'], "network",
445 table.concat(list, " "))
449 _uci_real:delete("network", old)
455 function get_interface(self, i)
456 if _interfaces[i] or _wifi_iface(i) then
461 _uci_real:foreach("wireless", "wifi-iface",
464 num[s.device] = num[s.device] and num[s.device] + 1 or 1
465 if s['.name'] == i then
467 "%s.network%d" %{s.device, num[s.device] })
476 function get_interfaces(self)
483 -- find normal interfaces
484 _uci_real:foreach("network", "interface",
486 for iface in utl.imatch(s.ifname) do
487 if not _iface_ignore(iface) and not _wifi_iface(iface) then
489 nfs[iface] = interface(iface)
494 for iface in utl.kspairs(_interfaces) do
495 if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
496 nfs[iface] = interface(iface)
500 -- find vlan interfaces
501 _uci_real:foreach("network", "switch_vlan",
507 local base = baseof[s.device]
509 if not s.device:match("^eth%d") then
511 for l in utl.execi("swconfig dev %q help 2>/dev/null" % s.device) do
513 base = l:match("^%w+: (%w+)")
516 if not base or not base:match("^eth%d") then
522 baseof[s.device] = base
525 local vid = tonumber(s.vid or s.vlan)
526 if vid ~= nil and vid >= 0 and vid <= 4095 then
527 local iface = "%s.%d" %{ base, vid }
528 if not seen[iface] then
530 nfs[iface] = interface(iface)
535 for iface in utl.kspairs(nfs) do
536 ifaces[#ifaces+1] = nfs[iface]
539 -- find wifi interfaces
542 _uci_real:foreach("wireless", "wifi-iface",
545 num[s.device] = num[s.device] and num[s.device] + 1 or 1
546 local i = "%s.network%d" %{ s.device, num[s.device] }
547 wfs[i] = interface(i)
551 for iface in utl.kspairs(wfs) do
552 ifaces[#ifaces+1] = wfs[iface]
558 function ignore_interface(self, x)
559 return _iface_ignore(x)
562 function get_wifidev(self, dev)
563 if _uci_real:get("wireless", dev) == "wifi-device" then
568 function get_wifidevs(self)
572 _uci_real:foreach("wireless", "wifi-device",
573 function(s) wfd[#wfd+1] = s['.name'] end)
576 for _, dev in utl.vspairs(wfd) do
577 devs[#devs+1] = wifidev(dev)
583 function get_wifinet(self, net)
584 local wnet = _wifi_lookup(net)
590 function add_wifinet(self, net, options)
591 if type(options) == "table" and options.device and
592 _uci_real:get("wireless", options.device) == "wifi-device"
594 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
599 function del_wifinet(self, net)
600 local wnet = _wifi_lookup(net)
602 _uci_real:delete("wireless", wnet)
608 function get_status_by_route(self, addr, mask)
610 for _, object in ipairs(_ubus:objects()) do
611 local net = object:match("^network%.interface%.(.+)")
613 local s = _ubus:call(object, "status", {})
614 if s and s.route then
616 for _, rt in ipairs(s.route) do
617 if rt.target == addr and rt.mask == mask then
626 function get_wannet(self)
627 local net = self:get_status_by_route("0.0.0.0", 0)
628 return net and network(net)
631 function get_wandev(self)
632 local _, stat = self:get_status_by_route("0.0.0.0", 0)
633 return stat and interface(stat.l3_device or stat.device)
636 function get_wan6net(self)
637 local net = self:get_status_by_route("::", 0)
638 return net and network(net)
641 function get_wan6dev(self)
642 local _, stat = self:get_status_by_route("::", 0)
643 return stat and interface(stat.l3_device or stat.device)
647 function network(name, proto)
649 local p = proto or _uci_real:get("network", name, "proto")
650 local c = p and _protocols[p] or protocol
655 function protocol.__init__(self, name)
659 function protocol._get(self, opt)
660 local v = _uci_real:get("network", self.sid, opt)
661 if type(v) == "table" then
662 return table.concat(v, " ")
667 function protocol._ubus(self, field)
668 if not _ubusnetcache[self.sid] then
669 _ubusnetcache[self.sid] = _ubus:call("network.interface.%s" % self.sid,
672 if _ubusnetcache[self.sid] and field then
673 return _ubusnetcache[self.sid][field]
675 return _ubusnetcache[self.sid]
678 function protocol.get(self, opt)
679 return _get("network", self.sid, opt)
682 function protocol.set(self, opt, val)
683 return _set("network", self.sid, opt, val)
686 function protocol.ifname(self)
688 if self:is_floating() then
689 ifname = self:_ubus("l3_device")
691 ifname = self:_ubus("device")
695 _uci_real:foreach("wireless", "wifi-iface",
698 num[s.device] = num[s.device]
699 and num[s.device] + 1 or 1
702 for net in utl.imatch(s.network) do
703 if net == self.sid then
704 ifname = "%s.network%d" %{ s.device, num[s.device] }
714 function protocol.proto(self)
718 function protocol.get_i18n(self)
719 local p = self:proto()
721 return lng.translate("Unmanaged")
722 elseif p == "static" then
723 return lng.translate("Static address")
724 elseif p == "dhcp" then
725 return lng.translate("DHCP client")
727 return lng.translate("Unknown")
731 function protocol.type(self)
732 return self:_get("type")
735 function protocol.name(self)
739 function protocol.uptime(self)
740 return self:_ubus("uptime") or 0
743 function protocol.expires(self)
744 local a = tonumber(_uci_state:get("network", self.sid, "lease_acquired"))
745 local l = tonumber(_uci_state:get("network", self.sid, "lease_lifetime"))
747 l = l - (nxo.sysinfo().uptime - a)
748 return l > 0 and l or 0
753 function protocol.metric(self)
754 return tonumber(_uci_state:get("network", self.sid, "metric")) or 0
757 function protocol.ipaddr(self)
758 local addrs = self:_ubus("ipv4-address")
759 return addrs and #addrs > 0 and addrs[1].address
762 function protocol.netmask(self)
763 local addrs = self:_ubus("ipv4-address")
764 return addrs and #addrs > 0 and
765 ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
768 function protocol.gwaddr(self)
770 for _, route in ipairs(self:_ubus("route") or { }) do
771 if route.target == "0.0.0.0" and route.mask == 0 then
777 function protocol.dnsaddrs(self)
780 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
781 if not addr:match(":") then
788 function protocol.ip6addr(self)
789 local addrs = self:_ubus("ipv6-address")
790 return addrs and #addrs > 0
791 and "%s/%d" %{ addrs[1].address, addrs[1].mask }
794 function protocol.gw6addr(self)
796 for _, route in ipairs(self:_ubus("route") or { }) do
797 if route.target == "::" and route.mask == 0 then
798 return ipc.IPv6(route.nexthop):string()
803 function protocol.dns6addrs(self)
806 for _, addr in ipairs(self:_ubus("dns-server") or { }) do
807 if addr:match(":") then
814 function protocol.is_bridge(self)
815 return (not self:is_virtual() and self:type() == "bridge")
818 function protocol.opkg_package(self)
822 function protocol.is_installed(self)
826 function protocol.is_virtual(self)
830 function protocol.is_floating(self)
834 function protocol.is_empty(self)
835 if self:is_floating() then
840 if (self:_get("ifname") or ""):match("%S+") then
844 _uci_real:foreach("wireless", "wifi-iface",
847 for n in utl.imatch(s.network) do
848 if n == self.sid then
859 function protocol.add_interface(self, ifname)
860 ifname = _M:ifnameof(ifname)
861 if ifname and not self:is_floating() then
862 -- if its a wifi interface, change its network option
863 local wif = _wifi_lookup(ifname)
865 _append("wireless", wif, "network", self.sid)
867 -- add iface to our iface list
869 _append("network", self.sid, "ifname", ifname)
874 function protocol.del_interface(self, ifname)
875 ifname = _M:ifnameof(ifname)
876 if ifname and not self:is_floating() then
877 -- if its a wireless interface, clear its network option
878 local wif = _wifi_lookup(ifname)
879 if wif then _filter("wireless", wif, "network", self.sid) end
881 -- remove the interface
882 _filter("network", self.sid, "ifname", ifname)
886 function protocol.get_interface(self)
887 if self:is_virtual() then
888 _tunnel[self:proto() .. "-" .. self.sid] = true
889 return interface(self:proto() .. "-" .. self.sid, self)
890 elseif self:is_bridge() then
891 _bridge["br-" .. self.sid] = true
892 return interface("br-" .. self.sid, self)
896 for ifn in utl.imatch(_uci_real:get("network", self.sid, "ifname")) do
897 ifn = ifn:match("^[^:/]+")
898 return ifn and interface(ifn, self)
901 _uci_real:foreach("wireless", "wifi-iface",
904 num[s.device] = num[s.device] and num[s.device] + 1 or 1
907 for net in utl.imatch(s.network) do
908 if net == self.sid then
909 ifn = "%s.network%d" %{ s.device, num[s.device] }
915 return ifn and interface(ifn, self)
919 function protocol.get_interfaces(self)
920 if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
925 for ifn in utl.imatch(self:get("ifname")) do
926 ifn = ifn:match("^[^:/]+")
927 nfs[ifn] = interface(ifn, self)
930 for ifn in utl.kspairs(nfs) do
931 ifaces[#ifaces+1] = nfs[ifn]
936 _uci_real:foreach("wireless", "wifi-iface",
939 num[s.device] = num[s.device] and num[s.device] + 1 or 1
942 for net in utl.imatch(s.network) do
943 if net == self.sid then
944 ifn = "%s.network%d" %{ s.device, num[s.device] }
945 wfs[ifn] = interface(ifn, self)
951 for ifn in utl.kspairs(wfs) do
952 ifaces[#ifaces+1] = wfs[ifn]
959 function protocol.contains_interface(self, ifname)
960 ifname = _M:ifnameof(ifname)
963 elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
965 elseif self:is_bridge() and "br-" .. self.sid == ifname then
969 for ifn in utl.imatch(self:get("ifname")) do
970 ifn = ifn:match("[^:]+")
971 if ifn == ifname then
976 local wif = _wifi_lookup(ifname)
979 for n in utl.imatch(_uci_real:get("wireless", wif, "network")) do
980 if n == self.sid then
990 function protocol.adminlink(self)
991 return dsp.build_url("admin", "network", "network", self.sid)
995 interface = utl.class()
997 function interface.__init__(self, ifname, network)
998 local wif = _wifi_lookup(ifname)
1000 self.wif = wifinet(wif)
1001 self.ifname = _uci_state:get("wireless", wif, "ifname")
1004 self.ifname = self.ifname or ifname
1005 self.dev = _interfaces[self.ifname]
1006 self.network = network
1009 function interface._ubus(self, field)
1010 if not _ubusdevcache[self.ifname] then
1011 _ubusdevcache[self.ifname] = _ubus:call("network.device", "status",
1012 { name = self.ifname })
1014 if _ubusdevcache[self.ifname] and field then
1015 return _ubusdevcache[self.ifname][field]
1017 return _ubusdevcache[self.ifname]
1020 function interface.name(self)
1021 return self.wif and self.wif:ifname() or self.ifname
1024 function interface.mac(self)
1025 return (self:_ubus("macaddr") or "00:00:00:00:00:00"):upper()
1028 function interface.ipaddrs(self)
1029 return self.dev and self.dev.ipaddrs or { }
1032 function interface.ip6addrs(self)
1033 return self.dev and self.dev.ip6addrs or { }
1036 function interface.type(self)
1037 if self.wif or _wifi_iface(self.ifname) then
1039 elseif _bridge[self.ifname] then
1041 elseif _tunnel[self.ifname] then
1043 elseif self.ifname:match("%.") then
1045 elseif _switch[self.ifname] then
1052 function interface.shortname(self)
1055 self.wif:active_mode(),
1056 self.wif:active_ssid() or self.wif:active_bssid()
1063 function interface.get_i18n(self)
1065 return "%s: %s %q" %{
1066 lng.translate("Wireless Network"),
1067 self.wif:active_mode(),
1068 self.wif:active_ssid() or self.wif:active_bssid()
1071 return "%s: %q" %{ self:get_type_i18n(), self:name() }
1075 function interface.get_type_i18n(self)
1076 local x = self:type()
1078 return lng.translate("Wireless Adapter")
1079 elseif x == "bridge" then
1080 return lng.translate("Bridge")
1081 elseif x == "switch" then
1082 return lng.translate("Ethernet Switch")
1083 elseif x == "vlan" then
1084 return lng.translate("VLAN Interface")
1085 elseif x == "tunnel" then
1086 return lng.translate("Tunnel Interface")
1088 return lng.translate("Ethernet Adapter")
1092 function interface.adminlink(self)
1094 return self.wif:adminlink()
1098 function interface.ports(self)
1099 local members = self:_ubus("bridge-members")
1103 for _, iface in ipairs(members) do
1104 ifaces[#ifaces+1] = interface(iface)
1109 function interface.bridge_id(self)
1117 function interface.bridge_stp(self)
1125 function interface.is_up(self)
1127 return self.wif:is_up()
1129 return self:_ubus("up") or false
1133 function interface.is_bridge(self)
1134 return (self:type() == "bridge")
1137 function interface.is_bridgeport(self)
1138 return self.dev and self.dev.bridge and true or false
1141 local function uint(x)
1143 return (x < 0) and ((2^32) + x) or x
1148 function interface.tx_bytes(self)
1149 local stat = self:_ubus("statistics")
1150 return stat and uint(stat.tx_bytes) or 0
1153 function interface.rx_bytes(self)
1154 local stat = self:_ubus("statistics")
1155 return stat and uint(stat.rx_bytes) or 0
1158 function interface.tx_packets(self)
1159 local stat = self:_ubus("statistics")
1160 return stat and uint(stat.tx_packets) or 0
1163 function interface.rx_packets(self)
1164 local stat = self:_ubus("statistics")
1165 return stat and uint(stat.rx_packets) or 0
1168 function interface.get_network(self)
1169 return self:get_networks()[1]
1172 function interface.get_networks(self)
1173 if not self.networks then
1176 for _, net in ipairs(_M:get_networks()) do
1177 if net:contains_interface(self.ifname) or
1178 net:ifname() == self.ifname
1183 table.sort(nets, function(a, b) return a.sid < b.sid end)
1184 self.networks = nets
1187 return self.networks
1191 function interface.get_wifinet(self)
1196 wifidev = utl.class()
1198 function wifidev.__init__(self, dev)
1200 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1203 function wifidev.get(self, opt)
1204 return _get("wireless", self.sid, opt)
1207 function wifidev.set(self, opt, val)
1208 return _set("wireless", self.sid, opt, val)
1211 function wifidev.name(self)
1215 function wifidev.hwmodes(self)
1216 local l = self.iwinfo.hwmodelist
1217 if l and next(l) then
1220 return { b = true, g = true }
1224 function wifidev.get_i18n(self)
1226 if self.iwinfo.type == "wl" then
1228 elseif self.iwinfo.type == "madwifi" then
1233 local l = self:hwmodes()
1234 if l.a then m = m .. "a" end
1235 if l.b then m = m .. "b" end
1236 if l.g then m = m .. "g" end
1237 if l.n then m = m .. "n" end
1239 return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
1242 function wifidev.is_up(self)
1245 _uci_state:foreach("wireless", "wifi-iface",
1247 if s.device == self.sid then
1258 function wifidev.get_wifinet(self, net)
1259 if _uci_real:get("wireless", net) == "wifi-iface" then
1262 local wnet = _wifi_lookup(net)
1264 return wifinet(wnet)
1269 function wifidev.get_wifinets(self)
1272 _uci_real:foreach("wireless", "wifi-iface",
1274 if s.device == self.sid then
1275 nets[#nets+1] = wifinet(s['.name'])
1282 function wifidev.add_wifinet(self, options)
1283 options = options or { }
1284 options.device = self.sid
1286 local wnet = _uci_real:section("wireless", "wifi-iface", nil, options)
1288 return wifinet(wnet, options)
1292 function wifidev.del_wifinet(self, net)
1293 if utl.instanceof(net, wifinet) then
1295 elseif _uci_real:get("wireless", net) ~= "wifi-iface" then
1296 net = _wifi_lookup(net)
1299 if net and _uci_real:get("wireless", net, "device") == self.sid then
1300 _uci_real:delete("wireless", net)
1308 wifinet = utl.class()
1310 function wifinet.__init__(self, net, data)
1315 _uci_real:foreach("wireless", "wifi-iface",
1318 num[s.device] = num[s.device] and num[s.device] + 1 or 1
1319 if s['.name'] == self.sid then
1320 netid = "%s.network%d" %{ s.device, num[s.device] }
1326 local dev = _uci_state:get("wireless", self.sid, "ifname") or netid
1330 self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
1331 self.iwdata = data or _uci_state:get_all("wireless", self.sid) or
1332 _uci_real:get_all("wireless", self.sid) or { }
1335 function wifinet.get(self, opt)
1336 return _get("wireless", self.sid, opt)
1339 function wifinet.set(self, opt, val)
1340 return _set("wireless", self.sid, opt, val)
1343 function wifinet.mode(self)
1344 return _uci_state:get("wireless", self.sid, "mode") or "ap"
1347 function wifinet.ssid(self)
1348 return _uci_state:get("wireless", self.sid, "ssid")
1351 function wifinet.bssid(self)
1352 return _uci_state:get("wireless", self.sid, "bssid")
1355 function wifinet.network(self)
1356 return _uci_state:get("wifinet", self.sid, "network")
1359 function wifinet.id(self)
1363 function wifinet.name(self)
1367 function wifinet.ifname(self)
1368 local ifname = self.iwinfo.ifname
1369 if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
1375 function wifinet.get_device(self)
1376 if self.iwdata.device then
1377 return wifidev(self.iwdata.device)
1381 function wifinet.is_up(self)
1382 return (self.iwdata.up == "1")
1385 function wifinet.active_mode(self)
1386 local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1388 if m == "ap" then m = "Master"
1389 elseif m == "sta" then m = "Client"
1390 elseif m == "adhoc" then m = "Ad-Hoc"
1391 elseif m == "mesh" then m = "Mesh"
1392 elseif m == "monitor" then m = "Monitor"
1398 function wifinet.active_mode_i18n(self)
1399 return lng.translate(self:active_mode())
1402 function wifinet.active_ssid(self)
1403 return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1406 function wifinet.active_bssid(self)
1407 return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1410 function wifinet.active_encryption(self)
1411 local enc = self.iwinfo and self.iwinfo.encryption
1412 return enc and enc.description or "-"
1415 function wifinet.assoclist(self)
1416 return self.iwinfo.assoclist or { }
1419 function wifinet.frequency(self)
1420 local freq = self.iwinfo.frequency
1421 if freq and freq > 0 then
1422 return "%.03f" % (freq / 1000)
1426 function wifinet.bitrate(self)
1427 local rate = self.iwinfo.bitrate
1428 if rate and rate > 0 then
1429 return (rate / 1000)
1433 function wifinet.channel(self)
1434 return self.iwinfo.channel or
1435 tonumber(_uci_state:get("wireless", self.iwdata.device, "channel"))
1438 function wifinet.signal(self)
1439 return self.iwinfo.signal or 0
1442 function wifinet.noise(self)
1443 return self.iwinfo.noise or 0
1446 function wifinet.country(self)
1447 return self.iwinfo.country or "00"
1450 function wifinet.txpower(self)
1451 local pwr = (self.iwinfo.txpower or 0)
1452 return pwr + self:txpower_offset()
1455 function wifinet.txpower_offset(self)
1456 return self.iwinfo.txpower_offset or 0
1459 function wifinet.signal_level(self, s, n)
1460 if self:active_bssid() ~= "00:00:00:00:00:00" then
1461 local signal = s or self:signal()
1462 local noise = n or self:noise()
1464 if signal < 0 and noise < 0 then
1465 local snr = -1 * (noise - signal)
1466 return math.floor(snr / 5)
1475 function wifinet.signal_percent(self)
1476 local qc = self.iwinfo.quality or 0
1477 local qm = self.iwinfo.quality_max or 0
1479 if qc > 0 and qm > 0 then
1480 return math.floor((100 / qm) * qc)
1486 function wifinet.shortname(self)
1488 lng.translate(self:active_mode()),
1489 self:active_ssid() or self:active_bssid()
1493 function wifinet.get_i18n(self)
1494 return "%s: %s %q (%s)" %{
1495 lng.translate("Wireless Network"),
1496 lng.translate(self:active_mode()),
1497 self:active_ssid() or self:active_bssid(),
1502 function wifinet.adminlink(self)
1503 return dsp.build_url("admin", "network", "wireless", self.netid)
1506 function wifinet.get_network(self)
1507 return self:get_networks()[1]
1510 function wifinet.get_networks(self)
1513 for net in utl.imatch(tostring(self.iwdata.network)) do
1514 if _uci_real:get("network", net) == "interface" then
1515 nets[#nets+1] = network(net)
1518 table.sort(nets, function(a, b) return a.sid < b.sid end)
1522 function wifinet.get_interface(self)
1523 return interface(self:ifname())
1527 -- setup base protocols
1528 _M:register_protocol("static")
1529 _M:register_protocol("dhcp")
1530 _M:register_protocol("none")
1532 -- load protocol extensions
1533 local exts = nfs.dir(utl.libpath() .. "/model/network")
1537 if ext:match("%.lua$") then
1538 require("luci.model.network." .. ext:gsub("%.lua$", ""))