root/luci/trunk/libs/core/luasrc/model/network.lua @ 6378

Revision 6378, 22.4 KB (checked in by jow, 3 years ago)

libs/core: return ordered list in luci.model.network.get_interfaces()

  • Property svn:keywords set to Id
Line 
1--[[
2LuCI - Network model
3
4Copyright 2009-2010 Jo-Philipp Wich <xm@subsignal.org>
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18]]--
19
20local type, pairs, ipairs, loadfile, table, tonumber, math, i18n
21    = type, pairs, ipairs, loadfile, table, tonumber, math, luci.i18n
22
23local nxo = require "nixio"
24local ipc = require "luci.ip"
25local sys = require "luci.sys"
26local utl = require "luci.util"
27local dsp = require "luci.dispatcher"
28local uci = require "luci.model.uci"
29
30module "luci.model.network"
31
32
33local ifs, brs, sws, uci_r, uci_s
34
35function _list_del(c, s, o, r)
36    local val = uci_r:get(c, s, o)
37    if val then
38        local l = { }
39        if type(val) == "string" then
40            for val in val:gmatch("%S+") do
41                if val ~= r then
42                    l[#l+1] = val
43                end
44            end
45            if #l > 0 then
46                uci_r:set(c, s, o, table.concat(l, " "))
47            else
48                uci_r:delete(c, s, o)
49            end
50        elseif type(val) == "table" then
51            for _, val in ipairs(val) do
52                if val ~= r then
53                    l[#l+1] = val
54                end
55            end
56            if #l > 0 then
57                uci_r:set(c, s, o, l)
58            else
59                uci_r:delete(c, s, o)
60            end
61        end
62    end
63end
64
65function _list_add(c, s, o, a)
66    local val = uci_r:get(c, s, o) or ""
67    if type(val) == "string" then
68        local l = { }
69        for val in val:gmatch("%S+") do
70            if val ~= a then
71                l[#l+1] = val
72            end
73        end
74        l[#l+1] = a
75        uci_r:set(c, s, o, table.concat(l, " "))
76    elseif type(val) == "table" then
77        local l = { }
78        for _, val in ipairs(val) do
79            if val ~= a then
80                l[#l+1] = val
81            end
82        end
83        l[#l+1] = a
84        uci_r:set(c, s, o, l)
85    end
86end
87
88function _stror(s1, s2)
89    if not s1 or #s1 == 0 then
90        return s2 and #s2 > 0 and s2
91    else
92        return s1
93    end
94end
95
96function _get(c, s, o)
97    return uci_r:get(c, s, o)
98end
99
100function _set(c, s, o, v)
101    if v ~= nil then
102        if type(v) == "boolean" then v = v and "1" or "0" end
103        return uci_r:set(c, s, o, v)
104    else
105        return uci_r:delete(c, s, o)
106    end
107end
108
109function _wifi_iface(x)
110    return (
111        x:match("^wlan%d") or x:match("^wl%d") or x:match("^ath%d") or
112        x:match("^%w+%.network%d")
113    )
114end
115
116function _wifi_lookup(ifn)
117    -- got a radio#.network# pseudo iface, locate the corresponding section
118    local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
119    if radio and ifnidx then
120        local sid = nil
121        local num = 0
122
123        ifnidx = tonumber(ifnidx)
124        uci_r:foreach("wireless", "wifi-iface",
125            function(s)
126                if s.device == radio then
127                    num = num + 1
128                    if num == ifnidx then
129                        sid = s['.name']
130                        return false
131                    end
132                end
133            end)
134
135        return sid
136
137    -- looks like wifi, try to locate the section via state vars
138    elseif _wifi_iface(ifn) then
139        local sid = nil
140
141        uci_s:foreach("wireless", "wifi-iface",
142            function(s)
143                if s.ifname == ifn then
144                    sid = s['.name']
145                    return false
146                end
147            end)
148
149        return sid
150    end
151end
152
153function _iface_ignore(x)
154    return (
155        x:match("^wmaster%d") or x:match("^wifi%d") or x:match("^hwsim%d") or
156        x:match("^imq%d") or x:match("^mon.wlan%d") or x:match("^6in4-%w") or
157        x:match("^3g-%w") or x:match("^ppp-%w") or x:match("^pppoe-%w") or
158        x:match("^pppoa-%w") or x == "lo"
159    )
160end
161
162
163function init(cursor)
164    uci_r = cursor or uci_r or uci.cursor()
165    uci_s = uci_r:substate()
166
167    ifs = { }
168    brs = { }
169    sws = { }
170
171    -- read interface information
172    local n, i
173    for n, i in ipairs(nxo.getifaddrs()) do
174        local name = i.name:match("[^:]+")
175        local prnt = name:match("^([^%.]+)%.")
176
177        if not _iface_ignore(name) then
178            ifs[name] = ifs[name] or {
179                idx      = i.ifindex or n,
180                name     = name,
181                rawname  = i.name,
182                flags    = { },
183                ipaddrs  = { },
184                ip6addrs = { }
185            }
186
187            if prnt then
188                sws[name] = true
189                sws[prnt] = true
190            end
191
192            if i.family == "packet" then
193                ifs[name].flags   = i.flags
194                ifs[name].stats   = i.data
195                ifs[name].macaddr = i.addr
196            elseif i.family == "inet" then
197                ifs[name].ipaddrs[#ifs[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
198            elseif i.family == "inet6" then
199                ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
200            end
201        end
202    end
203
204    -- read bridge informaton
205    local b, l
206    for l in utl.execi("brctl show") do
207        if not l:match("STP") then
208            local r = utl.split(l, "%s+", nil, true)
209            if #r == 4 then
210                b = {
211                    name    = r[1],
212                    id      = r[2],
213                    stp     = r[3] == "yes",
214                    ifnames = { ifs[r[4]] }
215                }
216                if b.ifnames[1] then
217                    b.ifnames[1].bridge = b
218                end
219                brs[r[1]] = b
220            elseif b then
221                b.ifnames[#b.ifnames+1] = ifs[r[2]]
222                b.ifnames[#b.ifnames].bridge = b
223            end
224        end
225    end
226
227    return _M
228end
229
230function save(self, ...)
231    uci_r:save(...)
232    uci_r:load(...)
233end
234
235function commit(self, ...)
236    uci_r:commit(...)
237    uci_r:load(...)
238end
239
240function has_ipv6(self)
241    return nfs.access("/proc/net/ipv6_route")
242end
243
244function add_network(self, n, options)
245    if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not self:get_network(n) then
246        if uci_r:section("network", "interface", n, options) then
247            return network(n)
248        end
249    end
250end
251
252function get_network(self, n)
253    if n and uci_r:get("network", n) == "interface" then
254        return network(n)
255    end
256end
257
258function get_networks(self)
259    local nets = { }
260    local nls = { }
261
262    uci_r:foreach("network", "interface",
263        function(s)
264            nls[s['.name']] = network(s['.name'])
265        end)
266
267    local n
268    for n in utl.kspairs(nls) do
269        nets[#nets+1] = nls[n]
270    end
271
272    return nets
273end
274
275function del_network(self, n)
276    local r = uci_r:delete("network", n)
277    if r then
278        uci_r:foreach("network", "alias",
279            function(s)
280                if s.interface == n then
281                    uci_r:delete("network", s['.name'])
282                end
283            end)
284
285        uci_r:foreach("network", "route",
286            function(s)
287                if s.interface == n then
288                    uci_r:delete("network", s['.name'])
289                end
290            end)
291
292        uci_r:foreach("network", "route6",
293            function(s)
294                if s.interface == n then
295                    uci_r:delete("network", s['.name'])
296                end
297            end)
298
299        uci_r:foreach("wireless", "wifi-iface",
300            function(s)
301                if s.network == n then
302                    uci_r:delete("wireless", s['.name'], "network")
303                end
304            end)
305
306        uci_r:delete("network", n)
307    end
308    return r
309end
310
311function rename_network(self, old, new)
312    local r
313    if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
314        r = uci_r:section("network", "interface", new, uci_r:get_all("network", old))
315
316        if r then
317            uci_r:foreach("network", "alias",
318                function(s)
319                    if s.interface == old then
320                        uci_r:set("network", s['.name'], "interface", new)
321                    end
322                end)
323
324            uci_r:foreach("network", "route",
325                function(s)
326                    if s.interface == old then
327                        uci_r:set("network", s['.name'], "interface", new)
328                    end
329                end)
330
331            uci_r:foreach("network", "route6",
332                function(s)
333                    if s.interface == old then
334                        uci_r:set("network", s['.name'], "interface", new)
335                    end
336                end)
337
338            uci_r:foreach("wireless", "wifi-iface",
339                function(s)
340                    if s.network == old then
341                        uci_r:set("wireless", s['.name'], "network", new)
342                    end
343                end)
344
345            uci_r:delete("network", old)
346        end
347    end
348    return r or false
349end
350
351function get_interface(self, i)
352    if ifs[i] or _wifi_iface(i) then
353        return interface(i)
354    else
355        local ifc
356        local num = { }
357        uci_r:foreach("wireless", "wifi-iface",
358            function(s)
359                if s.device then
360                    num[s.device] = num[s.device] and num[s.device] + 1 or 1
361                    if s['.name'] == i then
362                        ifc = interface(
363                            "%s.network%d" %{s.device, num[s.device] })
364                        return false
365                    end
366                end
367            end)
368        return ifc
369    end
370end
371
372function get_interfaces(self)
373    local iface
374    local ifaces = { }
375    local seen = { }
376    local nfs = { }
377
378    -- find normal interfaces
379    uci_r:foreach("network", "interface",
380        function(s)
381            for iface in utl.imatch(s.ifname) do
382                if not _iface_ignore(iface) and not _wifi_iface(iface) then
383                    seen[iface] = true
384                    nfs[iface] = interface(iface)
385                end
386            end
387        end)
388
389    for iface in utl.kspairs(ifs) do
390        if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
391            nfs[iface] = interface(iface)
392        end
393    end
394
395    for iface in utl.kspairs(nfs) do
396        ifaces[#ifaces+1] = nfs[iface]
397    end
398
399    -- find wifi interfaces
400    local num = { }
401    local wfs = { }
402    uci_r:foreach("wireless", "wifi-iface",
403        function(s)
404            if s.device then
405                num[s.device] = num[s.device] and num[s.device] + 1 or 1
406                local i = "%s.network%d" %{ s.device, num[s.device] }
407                wfs[i] = interface(i)
408            end
409        end)
410
411    for iface in utl.kspairs(wfs) do
412        ifaces[#ifaces+1] = wfs[iface]
413    end
414
415    return ifaces
416end
417
418function ignore_interface(self, x)
419    return _iface_ignore(x)
420end
421
422function get_wifidev(self, dev)
423    if uci_r:get("wireless", dev) == "wifi-device" then
424        return wifidev(dev)
425    end
426end
427
428function get_wifidevs(self)
429    local devs = { }
430    local wfd  = { }
431
432    uci_r:foreach("wireless", "wifi-device",
433        function(s) wfd[#wfd+1] = s['.name'] end)
434
435    local dev
436    for _, dev in utl.vspairs(wfd) do
437        devs[#devs+1] = wifidev(dev)
438    end
439
440    return devs
441end
442
443function get_wifinet(self, net)
444    local wnet = _wifi_lookup(net)
445    if wnet then
446        return wifinet(wnet)
447    end
448end
449
450function add_wifinet(self, net, options)
451    if type(options) == "table" and options.device and
452        uci_r:get("wireless", options.device) == "wifi-device"
453    then
454        local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
455        return wifinet(wnet)
456    end
457end
458
459function del_wifinet(self, net)
460    local wnet = _wifi_lookup(net)
461    if wnet then
462        uci_r:delete("wireless", wnet)
463        return true
464    end
465    return false
466end
467
468
469network = utl.class()
470
471function network.__init__(self, name)
472    self.sid = name
473end
474
475function network._get(self, opt)
476    local v = uci_r:get("network", self.sid, opt)
477    if type(v) == "table" then
478        return table.concat(v, " ")
479    end
480    return v or ""
481end
482
483function network.get(self, opt)
484    return _get("network", self.sid, opt)
485end
486
487function network.set(self, opt, val)
488    return _set("network", self.sid, opt, val)
489end
490
491function network.ifname(self)
492    local p = self:proto()
493    if self:is_bridge() then
494        return "br-" .. self.sid
495    elseif self:is_virtual() then
496        return p .. "-" .. self.sid
497    else
498        local dev = self:_get("ifname") or
499            uci_r:get("network", self.sid, "ifname")
500
501        dev = dev and dev:match("%S+")
502
503        if not dev then
504            uci_r:foreach("wireless", "wifi-iface",
505                function(s)
506                    if s.device then
507                        num[s.device] = num[s.device]
508                            and num[s.device] + 1 or 1
509
510                        if s.network == self.sid then
511                            dev = "%s.network%d" %{ s.device, num[s.device] }
512                            return false
513                        end
514                    end
515                end)
516        end
517
518        return dev
519    end
520end
521
522function network.device(self)
523    local dev = self:_get("device")
524    if not dev or dev:match("[^%w%-%.%s]") then
525        dev = uci_r:get("network", self.sid, "ifname")
526    end
527    return dev
528end
529
530function network.proto(self)
531    return self:_get("proto") or "none"
532end
533
534function network.type(self)
535    return self:_get("type")
536end
537
538function network.name(self)
539    return self.sid
540end
541
542function network.is_bridge(self)
543    return (self:type() == "bridge")
544end
545
546function network.is_virtual(self)
547    local p = self:proto()
548    return (
549        p == "3g" or p == "6in4" or p == "ppp" or
550        p == "pppoe" or p == "pppoa"
551    )
552end
553
554function network.is_empty(self)
555    if self:is_virtual() then
556        return false
557    else
558        local rv = true
559
560        if (self:_get("ifname") or ""):match("%S+") then
561            rv = false
562        end
563
564        uci_r:foreach("wireless", "wifi-iface",
565            function(s)
566                if s.network == self.sid then
567                    rv = false
568                    return false
569                end
570            end)
571
572        return rv
573    end
574end
575
576function network.add_interface(self, ifname)
577    if not self:is_virtual() then
578        if type(ifname) ~= "string" then
579            ifname = ifname:name()
580        else
581            ifname = ifname:match("[^%s:]+")
582        end
583
584        -- remove the interface from all ifaces
585        uci_r:foreach("network", "interface",
586            function(s)
587                _list_del("network", s['.name'], "ifname", ifname)
588            end)
589
590        -- if its a wifi interface, change its network option
591        local wif = _wifi_lookup(ifname)
592        if wif then
593            uci_r:set("wireless", wif, "network", self.sid)
594
595        -- add iface to our iface list
596        else
597            _list_add("network", self.sid, "ifname", ifname)
598        end
599    end
600end
601
602function network.del_interface(self, ifname)
603    if not self:is_virtual() then
604        if utl.instanceof(ifname, interface) then
605            ifname = ifname:name()
606        else
607            ifname = ifname:match("[^%s:]+")
608        end
609
610        -- if its a wireless interface, clear its network option
611        local wif = _wifi_lookup(ifname)
612        if wif then uci_r:delete("wireless", wif, "network") end
613
614        -- remove the interface
615        _list_del("network", self.sid, "ifname", ifname)
616    end
617end
618
619function network.get_interfaces(self)
620    local ifaces = { }
621
622    local ifn
623    if self:is_virtual() then
624        ifn = self:proto() .. "-" .. self.sid
625        ifaces = { interface(ifn) }
626    else
627        local nfs = { }
628        for ifn in utl.imatch(self:get("ifname")) do
629            ifn = ifn:match("[^:]+")
630            nfs[ifn] = interface(ifn)
631        end
632
633        for ifn in utl.kspairs(nfs) do
634            ifaces[#ifaces+1] = nfs[ifn]
635        end
636
637        local num = { }
638        local wfs = { }
639        uci_r:foreach("wireless", "wifi-iface",
640            function(s)
641                if s.device then
642                    num[s.device] = num[s.device] and num[s.device] + 1 or 1
643                    if s.network == self.sid then
644                        ifn = "%s.network%d" %{ s.device, num[s.device] }
645                        wfs[ifn] = interface(ifn)
646                    end
647                end
648            end)
649
650        for ifn in utl.kspairs(wfs) do
651            ifaces[#ifaces+1] = wfs[ifn]
652        end
653    end
654
655    return ifaces
656end
657
658function network.contains_interface(self, ifname)
659    if type(ifname) ~= "string" then
660        ifname = ifname:name()
661    else
662        ifname = ifname:match("[^%s:]+")
663    end
664
665    local ifn
666    if self:is_virtual() then
667        ifn = self:proto() .. "-" .. self.sid
668        return ifname == ifn
669    else
670        for ifn in utl.imatch(self:get("ifname")) do
671            ifn = ifn:match("[^:]+")
672            if ifn == ifname then
673                return true
674            end
675        end
676
677        local wif = _wifi_lookup(ifname)
678        if wif then
679            return (uci_r:get("wireless", wif, "network") == self.sid)
680        end
681    end
682
683    return false
684end
685
686function network.adminlink(self)
687    return dsp.build_url("admin", "network", "network", self.sid)
688end
689
690
691interface = utl.class()
692function interface.__init__(self, ifname)
693    local wif = _wifi_lookup(ifname)
694    if wif then self.wif = wifinet(wif) end
695
696    self.ifname = self.ifname or ifname
697    self.dev    = ifs[self.ifname]
698end
699
700function interface.name(self)
701    return self.wif and self.wif:ifname() or self.ifname
702end
703
704function interface.mac(self)
705    return self.dev and self.dev.macaddr or "00:00:00:00:00:00"
706end
707
708function interface.ipaddrs(self)
709    return self.dev and self.dev.ipaddrs or { }
710end
711
712function interface.ip6addrs(self)
713    return self.dev and self.dev.ip6addrs or { }
714end
715
716function interface.type(self)
717    if self.wif or _wifi_iface(self.ifname) then
718        return "wifi"
719    elseif brs[self.ifname] then
720        return "bridge"
721    elseif sws[self.ifname] or self.ifname:match("%.") then
722        return "switch"
723    else
724        return "ethernet"
725    end
726end
727
728function interface.shortname(self)
729    if self.wif then
730        return "%s %q" %{
731            self.wif:active_mode(),
732            self.wif:active_ssid() or self.wif:active_bssid()
733        }
734    else
735        return self.ifname
736    end
737end
738
739function interface.get_i18n(self)
740    if self.wif then
741        return "%s: %s %q" %{
742            i18n.translate("Wireless Network"),
743            self.wif:active_mode(),
744            self.wif:active_ssid() or self.wif:active_bssid()
745        }
746    else
747        return "%s: %q" %{ self:get_type_i18n(), self:name() }
748    end
749end
750
751function interface.get_type_i18n(self)
752    local x = self:type()
753    if x == "wifi" then
754        return i18n.translate("Wireless Adapter")
755    elseif x == "bridge" then
756        return i18n.translate("Bridge")
757    elseif x == "switch" then
758        return i18n.translate("Ethernet Switch")
759    else
760        return i18n.translate("Ethernet Adapter")
761    end
762end
763
764function interface.adminlink(self)
765    if self.wif then
766        return self.wif:adminlink()
767    end
768end
769
770function interface.ports(self)
771    if self.br then
772        local iface
773        local ifaces = { }
774        for _, iface in ipairs(self.br.ifnames) do
775            ifaces[#ifaces+1] = interface(iface.name)
776        end
777        return ifaces
778    end
779end
780
781function interface.bridge_id(self)
782    if self.br then
783        return self.br.id
784    else
785        return nil
786    end
787end
788
789function interface.bridge_stp(self)
790    if self.br then
791        return self.br.stp
792    else
793        return false
794    end
795end
796
797function interface.is_up(self)
798    if self.wif then
799        return self.wif:is_up()
800    else
801        return self.dev and self.dev.flags and self.dev.flags.up or false
802    end
803end
804
805function interface.is_bridge(self)
806    return (self:type() == "bridge")
807end
808
809function interface.is_bridgeport(self)
810    return self.dev and self.dev.bridge and true or false
811end
812
813function interface.tx_bytes(self)
814    return self.dev and self.dev.stats
815        and self.dev.stats.tx_bytes or 0
816end
817
818function interface.rx_bytes(self)
819    return self.dev and self.dev.stats
820        and self.dev.stats.rx_bytes or 0
821end
822
823function interface.tx_packets(self)
824    return self.dev and self.dev.stats
825        and self.dev.stats.tx_packets or 0
826end
827
828function interface.rx_packets(self)
829    return self.dev and self.dev.stats
830        and self.dev.stats.rx_packets or 0
831end
832
833function interface.get_network(self)
834    if self.dev and self.dev.network then
835        self.network = _M:get_network(self.dev.network)
836    end
837
838    if not self.network then
839        local net
840        for _, net in ipairs(_M:get_networks()) do
841            if net:contains_interface(self.ifname) then
842                self.network = net
843                return net
844            end
845        end
846    else
847        return self.network
848    end
849end
850
851function interface.get_wifinet(self)
852    return self.wif
853end
854
855
856wifidev = utl.class()
857function wifidev.__init__(self, dev)
858    self.sid = dev
859end
860
861function wifidev.get(self, opt)
862    return _get("wireless", self.sid, opt)
863end
864
865function wifidev.set(self, opt, val)
866    return _set("wireless", self.sid, opt, val)
867end
868
869function wifidev.name(self)
870    return self.sid
871end
872
873function wifidev.is_up(self)
874    local up = false
875
876    uci_s:foreach("wireless", "wifi-iface",
877        function(s)
878            if s.device == self.sid then
879                if s.up == "1" then
880                    up = true
881                    return false
882                end
883            end
884        end)
885
886    return up
887end
888
889function wifidev.get_wifinet(self, net)
890    if uci_r:get("wireless", net) == "wifi-iface" then
891        return wifinet(net)
892    else
893        local wnet = _wifi_lookup(net)
894        if wnet then
895            return wifinet(wnet)
896        end
897    end
898end
899
900function wifidev.get_wifinets(self)
901    local nets = { }
902
903    uci_r:foreach("wireless", "wifi-iface",
904        function(s)
905            if s.device == self.sid then
906                nets[#nets+1] = wifinet(s['.name'])
907            end
908        end)
909
910    return nets
911end
912
913function wifidev.add_wifinet(self, options)
914    options = options or { }
915    options.device = self.sid
916
917    local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
918    if wnet then
919        return wifinet(wnet, options)
920    end
921end
922
923function wifidev.del_wifinet(self, net)
924    if utl.instanceof(net, wifinet) then
925        net = net.sid
926    elseif uci_r:get("wireless", net) ~= "wifi-iface" then
927        net = _wifi_lookup(net)
928    end
929
930    if net and uci_r:get("wireless", net, "device") == self.sid then
931        uci_r:delete("wireless", net)
932        return true
933    end
934
935    return false
936end
937
938
939wifinet = utl.class()
940function wifinet.__init__(self, net, data)
941    self.sid = net
942
943    local dev = uci_s:get("wireless", self.sid, "ifname")
944    if not dev then
945        local num = { }
946        uci_r:foreach("wireless", "wifi-iface",
947            function(s)
948                if s.device then
949                    num[s.device] = num[s.device] and num[s.device] + 1 or 1
950                    if s['.name'] == self.sid then
951                        dev = "%s.network%d" %{ s.device, num[s.device] }
952                        return false
953                    end
954                end
955            end)
956    end
957
958    self.wdev   = dev
959    self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
960    self.iwdata = data or uci_s:get_all("wireless", self.sid) or
961        uci_r:get_all("wireless", self.sid) or { }
962end
963
964function wifinet.get(self, opt)
965    return _get("wireless", self.sid, opt)
966end
967
968function wifinet.set(self, opt, val)
969    return _set("wireless", self.sid, opt, val)
970end
971
972function wifinet.mode(self)
973    return uci_s:get("wireless", self.sid, "mode") or "ap"
974end
975
976function wifinet.ssid(self)
977    return uci_s:get("wireless", self.sid, "ssid")
978end
979
980function wifinet.bssid(self)
981    return uci_s:get("wireless", self.sid, "bssid")
982end
983
984function wifinet.network(self)
985    return uci_s:get("wifinet", self.sid, "network")
986end
987
988function wifinet.name(self)
989    return self.sid
990end
991
992function wifinet.ifname(self)
993    return self.iwinfo.ifname or self.wdev
994end
995
996function wifinet.get_device(self)
997    if self.iwdata.device then
998        return wifidev(self.iwdata.device)
999    end
1000end
1001
1002function wifinet.is_up(self)
1003    return (self.iwdata.up == "1")
1004end
1005
1006function wifinet.active_mode(self)
1007    local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1008
1009    if     m == "ap"      then m = "AP"
1010    elseif m == "sta"     then m = "Client"
1011    elseif m == "adhoc"   then m = "Ad-Hoc"
1012    elseif m == "mesh"    then m = "Mesh"
1013    elseif m == "monitor" then m = "Monitor"
1014    end
1015
1016    return m
1017end
1018
1019function wifinet.active_mode_i18n(self)
1020    return i18n.translate(self:active_mode())
1021end
1022
1023function wifinet.active_ssid(self)
1024    return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1025end
1026
1027function wifinet.active_bssid(self)
1028    return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1029end
1030
1031function wifinet.active_encryption(self)
1032    local enc = self.iwinfo and self.iwinfo.encryption
1033    return enc and enc.description or "-"
1034end
1035
1036function wifinet.assoclist(self)
1037    return self.iwinfo.assoclist or { }
1038end
1039
1040function wifinet.frequency(self)
1041    local freq = self.iwinfo.frequency
1042    if freq and freq > 0 then
1043        return "%.03f" % (freq / 1000)
1044    end
1045end
1046
1047function wifinet.bitrate(self)
1048    local rate = self.iwinfo.bitrate
1049    if rate and rate > 0 then
1050        return (rate / 1000)
1051    end
1052end
1053
1054function wifinet.channel(self)
1055    return self.iwinfo.channel or
1056        tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1057end
1058
1059function wifinet.signal(self)
1060    return self.iwinfo.signal or 0
1061end
1062
1063function wifinet.noise(self)
1064    return self.iwinfo.noise or 0
1065end
1066
1067function wifinet.signal_level(self, s, n)
1068    if self:active_bssid() ~= "00:00:00:00:00:00" then
1069        local signal = s or self:signal()
1070        local noise  = n or self:noise()
1071
1072        if signal < 0 and noise < 0 then
1073            local snr = -1 * (noise - signal)
1074            return math.floor(snr / 5)
1075        else
1076            return 0
1077        end
1078    else
1079        return -1
1080    end
1081end
1082
1083function wifinet.signal_percent(self)
1084    local qc = self.iwinfo.quality or 0
1085    local qm = self.iwinfo.quality_max or 0
1086
1087    if qc > 0 and qm > 0 then
1088        return math.floor((100 / qm) * qc)
1089    else
1090        return 0
1091    end
1092end
1093
1094function wifinet.shortname(self)
1095    return "%s %q" %{
1096        i18n.translate(self:active_mode()),
1097        self:active_ssid() or self:active_bssid()
1098    }
1099end
1100
1101function wifinet.get_i18n(self)
1102    return "%s: %s %q (%s)" %{
1103        i18n.translate("Wireless Network"),
1104        i18n.translate(self:active_mode()),
1105        self:active_ssid() or self:active_bssid(),
1106        self:ifname()
1107    }
1108end
1109
1110function wifinet.adminlink(self)
1111    return dsp.build_url("admin", "network", "wireless",
1112        self.iwdata.device, self.wdev)
1113end
1114
1115function wifinet.get_network(self)
1116    if uci_r:get("network", self.iwdata.network) == "interface" then
1117        return network(self.iwdata.network)
1118    end
1119end
1120
1121function wifinet.get_interface(self)
1122    return interface(self:ifname())
1123end
Note: See TracBrowser for help on using the browser.