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

Revision 6373, 22.3 KB (checked in by jow, 3 years ago)

libs/core: support not-yet-existing interfaces in network model

  • 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
377    -- find normal interfaces
378    uci_r:foreach("network", "interface",
379        function(s)
380            for iface in utl.imatch(s.ifname) do
381                if not _iface_ignore(iface) and not _wifi_iface(iface) then
382                    seen[iface] = true
383                    ifaces[#ifaces+1] = interface(iface)
384                end
385            end
386        end)
387
388    for iface in utl.kspairs(ifs) do
389        if not (seen[iface] or _iface_ignore(iface) or _wifi_iface(iface)) then
390            ifaces[#ifaces+1] = interface(iface)
391        end
392    end
393
394    -- find wifi interfaces
395    local num = { }
396    local wfs = { }
397    uci_r:foreach("wireless", "wifi-iface",
398        function(s)
399            if s.device then
400                num[s.device] = num[s.device] and num[s.device] + 1 or 1
401                local i = "%s.network%d" %{ s.device, num[s.device] }
402                wfs[i] = interface(i)
403            end
404        end)
405
406    for iface in utl.kspairs(wfs) do
407        ifaces[#ifaces+1] = wfs[iface]
408    end
409
410    return ifaces
411end
412
413function ignore_interface(self, x)
414    return _iface_ignore(x)
415end
416
417function get_wifidev(self, dev)
418    if uci_r:get("wireless", dev) == "wifi-device" then
419        return wifidev(dev)
420    end
421end
422
423function get_wifidevs(self)
424    local devs = { }
425    local wfd  = { }
426
427    uci_r:foreach("wireless", "wifi-device",
428        function(s) wfd[#wfd+1] = s['.name'] end)
429
430    local dev
431    for _, dev in utl.vspairs(wfd) do
432        devs[#devs+1] = wifidev(dev)
433    end
434
435    return devs
436end
437
438function get_wifinet(self, net)
439    local wnet = _wifi_lookup(net)
440    if wnet then
441        return wifinet(wnet)
442    end
443end
444
445function add_wifinet(self, net, options)
446    if type(options) == "table" and options.device and
447        uci_r:get("wireless", options.device) == "wifi-device"
448    then
449        local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
450        return wifinet(wnet)
451    end
452end
453
454function del_wifinet(self, net)
455    local wnet = _wifi_lookup(net)
456    if wnet then
457        uci_r:delete("wireless", wnet)
458        return true
459    end
460    return false
461end
462
463
464network = utl.class()
465
466function network.__init__(self, name)
467    self.sid = name
468end
469
470function network._get(self, opt)
471    local v = uci_r:get("network", self.sid, opt)
472    if type(v) == "table" then
473        return table.concat(v, " ")
474    end
475    return v or ""
476end
477
478function network.get(self, opt)
479    return _get("network", self.sid, opt)
480end
481
482function network.set(self, opt, val)
483    return _set("network", self.sid, opt, val)
484end
485
486function network.ifname(self)
487    local p = self:proto()
488    if self:is_bridge() then
489        return "br-" .. self.sid
490    elseif self:is_virtual() then
491        return p .. "-" .. self.sid
492    else
493        local dev = self:_get("ifname") or
494            uci_r:get("network", self.sid, "ifname")
495
496        dev = dev and dev:match("%S+")
497
498        if not dev then
499            uci_r:foreach("wireless", "wifi-iface",
500                function(s)
501                    if s.device then
502                        num[s.device] = num[s.device]
503                            and num[s.device] + 1 or 1
504
505                        if s.network == self.sid then
506                            dev = "%s.network%d" %{ s.device, num[s.device] }
507                            return false
508                        end
509                    end
510                end)
511        end
512
513        return dev
514    end
515end
516
517function network.device(self)
518    local dev = self:_get("device")
519    if not dev or dev:match("[^%w%-%.%s]") then
520        dev = uci_r:get("network", self.sid, "ifname")
521    end
522    return dev
523end
524
525function network.proto(self)
526    return self:_get("proto") or "none"
527end
528
529function network.type(self)
530    return self:_get("type")
531end
532
533function network.name(self)
534    return self.sid
535end
536
537function network.is_bridge(self)
538    return (self:type() == "bridge")
539end
540
541function network.is_virtual(self)
542    local p = self:proto()
543    return (
544        p == "3g" or p == "6in4" or p == "ppp" or
545        p == "pppoe" or p == "pppoa"
546    )
547end
548
549function network.is_empty(self)
550    if self:is_virtual() then
551        return false
552    else
553        local rv = true
554
555        if (self:_get("ifname") or ""):match("%S+") then
556            rv = false
557        end
558
559        uci_r:foreach("wireless", "wifi-iface",
560            function(s)
561                if s.network == self.sid then
562                    rv = false
563                    return false
564                end
565            end)
566
567        return rv
568    end
569end
570
571function network.add_interface(self, ifname)
572    if not self:is_virtual() then
573        if type(ifname) ~= "string" then
574            ifname = ifname:name()
575        else
576            ifname = ifname:match("[^%s:]+")
577        end
578
579        -- remove the interface from all ifaces
580        uci_r:foreach("network", "interface",
581            function(s)
582                _list_del("network", s['.name'], "ifname", ifname)
583            end)
584
585        -- if its a wifi interface, change its network option
586        local wif = _wifi_lookup(ifname)
587        if wif then
588            uci_r:set("wireless", wif, "network", self.sid)
589
590        -- add iface to our iface list
591        else
592            _list_add("network", self.sid, "ifname", ifname)
593        end
594    end
595end
596
597function network.del_interface(self, ifname)
598    if not self:is_virtual() then
599        if utl.instanceof(ifname, interface) then
600            ifname = ifname:name()
601        else
602            ifname = ifname:match("[^%s:]+")
603        end
604
605        -- if its a wireless interface, clear its network option
606        local wif = _wifi_lookup(ifname)
607        if wif then uci_r:delete("wireless", wif, "network") end
608
609        -- remove the interface
610        _list_del("network", self.sid, "ifname", ifname)
611    end
612end
613
614function network.get_interfaces(self)
615    local ifaces = { }
616
617    local ifn
618    if self:is_virtual() then
619        ifn = self:proto() .. "-" .. self.sid
620        ifaces = { interface(ifn) }
621    else
622        local nfs = { }
623        for ifn in utl.imatch(self:get("ifname")) do
624            ifn = ifn:match("[^:]+")
625            nfs[ifn] = interface(ifn)
626        end
627
628        for ifn in utl.kspairs(nfs) do
629            ifaces[#ifaces+1] = nfs[ifn]
630        end
631
632        local num = { }
633        local wfs = { }
634        uci_r:foreach("wireless", "wifi-iface",
635            function(s)
636                if s.device then
637                    num[s.device] = num[s.device] and num[s.device] + 1 or 1
638                    if s.network == self.sid then
639                        ifn = "%s.network%d" %{ s.device, num[s.device] }
640                        wfs[ifn] = interface(ifn)
641                    end
642                end
643            end)
644
645        for ifn in utl.kspairs(wfs) do
646            ifaces[#ifaces+1] = wfs[ifn]
647        end
648    end
649
650    return ifaces
651end
652
653function network.contains_interface(self, ifname)
654    if type(ifname) ~= "string" then
655        ifname = ifname:name()
656    else
657        ifname = ifname:match("[^%s:]+")
658    end
659
660    local ifn
661    if self:is_virtual() then
662        ifn = self:proto() .. "-" .. self.sid
663        return ifname == ifn
664    else
665        for ifn in utl.imatch(self:get("ifname")) do
666            ifn = ifn:match("[^:]+")
667            if ifn == ifname then
668                return true
669            end
670        end
671
672        local wif = _wifi_lookup(ifname)
673        if wif then
674            return (uci_r:get("wireless", wif, "network") == self.sid)
675        end
676    end
677
678    return false
679end
680
681function network.adminlink(self)
682    return dsp.build_url("admin", "network", "network", self.sid)
683end
684
685
686interface = utl.class()
687function interface.__init__(self, ifname)
688    local wif = _wifi_lookup(ifname)
689    if wif then self.wif = wifinet(wif) end
690
691    self.ifname = self.ifname or ifname
692    self.dev    = ifs[self.ifname]
693end
694
695function interface.name(self)
696    return self.wif and self.wif:ifname() or self.ifname
697end
698
699function interface.mac(self)
700    return self.dev and self.dev.macaddr or "00:00:00:00:00:00"
701end
702
703function interface.ipaddrs(self)
704    return self.dev and self.dev.ipaddrs or { }
705end
706
707function interface.ip6addrs(self)
708    return self.dev and self.dev.ip6addrs or { }
709end
710
711function interface.type(self)
712    if self.wif or _wifi_iface(self.ifname) then
713        return "wifi"
714    elseif brs[self.ifname] then
715        return "bridge"
716    elseif sws[self.ifname] or self.ifname:match("%.") then
717        return "switch"
718    else
719        return "ethernet"
720    end
721end
722
723function interface.shortname(self)
724    if self.wif then
725        return "%s %q" %{
726            self.wif:active_mode(),
727            self.wif:active_ssid() or self.wif:active_bssid()
728        }
729    else
730        return self.ifname
731    end
732end
733
734function interface.get_i18n(self)
735    if self.wif then
736        return "%s: %s %q" %{
737            i18n.translate("Wireless Network"),
738            self.wif:active_mode(),
739            self.wif:active_ssid() or self.wif:active_bssid()
740        }
741    else
742        return "%s: %q" %{ self:get_type_i18n(), self:name() }
743    end
744end
745
746function interface.get_type_i18n(self)
747    local x = self:type()
748    if x == "wifi" then
749        return i18n.translate("Wireless Adapter")
750    elseif x == "bridge" then
751        return i18n.translate("Bridge")
752    elseif x == "switch" then
753        return i18n.translate("Ethernet Switch")
754    else
755        return i18n.translate("Ethernet Adapter")
756    end
757end
758
759function interface.adminlink(self)
760    if self.wif then
761        return self.wif:adminlink()
762    end
763end
764
765function interface.ports(self)
766    if self.br then
767        local iface
768        local ifaces = { }
769        for _, iface in ipairs(self.br.ifnames) do
770            ifaces[#ifaces+1] = interface(iface.name)
771        end
772        return ifaces
773    end
774end
775
776function interface.bridge_id(self)
777    if self.br then
778        return self.br.id
779    else
780        return nil
781    end
782end
783
784function interface.bridge_stp(self)
785    if self.br then
786        return self.br.stp
787    else
788        return false
789    end
790end
791
792function interface.is_up(self)
793    if self.wif then
794        return self.wif:is_up()
795    else
796        return self.dev and self.dev.flags and self.dev.flags.up or false
797    end
798end
799
800function interface.is_bridge(self)
801    return (self:type() == "bridge")
802end
803
804function interface.is_bridgeport(self)
805    return self.dev and self.dev.bridge and true or false
806end
807
808function interface.tx_bytes(self)
809    return self.dev and self.dev.stats
810        and self.dev.stats.tx_bytes or 0
811end
812
813function interface.rx_bytes(self)
814    return self.dev and self.dev.stats
815        and self.dev.stats.rx_bytes or 0
816end
817
818function interface.tx_packets(self)
819    return self.dev and self.dev.stats
820        and self.dev.stats.tx_packets or 0
821end
822
823function interface.rx_packets(self)
824    return self.dev and self.dev.stats
825        and self.dev.stats.rx_packets or 0
826end
827
828function interface.get_network(self)
829    if self.dev and self.dev.network then
830        self.network = _M:get_network(self.dev.network)
831    end
832
833    if not self.network then
834        local net
835        for _, net in ipairs(_M:get_networks()) do
836            if net:contains_interface(self.ifname) then
837                self.network = net
838                return net
839            end
840        end
841    else
842        return self.network
843    end
844end
845
846function interface.get_wifinet(self)
847    return self.wif
848end
849
850
851wifidev = utl.class()
852function wifidev.__init__(self, dev)
853    self.sid = dev
854end
855
856function wifidev.get(self, opt)
857    return _get("wireless", self.sid, opt)
858end
859
860function wifidev.set(self, opt, val)
861    return _set("wireless", self.sid, opt, val)
862end
863
864function wifidev.name(self)
865    return self.sid
866end
867
868function wifidev.is_up(self)
869    local up = false
870
871    uci_s:foreach("wireless", "wifi-iface",
872        function(s)
873            if s.device == self.sid then
874                if s.up == "1" then
875                    up = true
876                    return false
877                end
878            end
879        end)
880
881    return up
882end
883
884function wifidev.get_wifinet(self, net)
885    if uci_r:get("wireless", net) == "wifi-iface" then
886        return wifinet(net)
887    else
888        local wnet = _wifi_lookup(net)
889        if wnet then
890            return wifinet(wnet)
891        end
892    end
893end
894
895function wifidev.get_wifinets(self)
896    local nets = { }
897
898    uci_r:foreach("wireless", "wifi-iface",
899        function(s)
900            if s.device == self.sid then
901                nets[#nets+1] = wifinet(s['.name'])
902            end
903        end)
904
905    return nets
906end
907
908function wifidev.add_wifinet(self, options)
909    options = options or { }
910    options.device = self.sid
911
912    local wnet = uci_r:section("wireless", "wifi-iface", nil, options)
913    if wnet then
914        return wifinet(wnet, options)
915    end
916end
917
918function wifidev.del_wifinet(self, net)
919    if utl.instanceof(net, wifinet) then
920        net = net.sid
921    elseif uci_r:get("wireless", net) ~= "wifi-iface" then
922        net = _wifi_lookup(net)
923    end
924
925    if net and uci_r:get("wireless", net, "device") == self.sid then
926        uci_r:delete("wireless", net)
927        return true
928    end
929
930    return false
931end
932
933
934wifinet = utl.class()
935function wifinet.__init__(self, net, data)
936    self.sid = net
937
938    local dev = uci_s:get("wireless", self.sid, "ifname")
939    if not dev then
940        local num = { }
941        uci_r:foreach("wireless", "wifi-iface",
942            function(s)
943                if s.device then
944                    num[s.device] = num[s.device] and num[s.device] + 1 or 1
945                    if s['.name'] == self.sid then
946                        dev = "%s.network%d" %{ s.device, num[s.device] }
947                        return false
948                    end
949                end
950            end)
951    end
952
953    self.wdev   = dev
954    self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
955    self.iwdata = data or uci_s:get_all("wireless", self.sid) or
956        uci_r:get_all("wireless", self.sid) or { }
957end
958
959function wifinet.get(self, opt)
960    return _get("wireless", self.sid, opt)
961end
962
963function wifinet.set(self, opt, val)
964    return _set("wireless", self.sid, opt, val)
965end
966
967function wifinet.mode(self)
968    return uci_s:get("wireless", self.sid, "mode") or "ap"
969end
970
971function wifinet.ssid(self)
972    return uci_s:get("wireless", self.sid, "ssid")
973end
974
975function wifinet.bssid(self)
976    return uci_s:get("wireless", self.sid, "bssid")
977end
978
979function wifinet.network(self)
980    return uci_s:get("wifinet", self.sid, "network")
981end
982
983function wifinet.name(self)
984    return self.sid
985end
986
987function wifinet.ifname(self)
988    return self.iwinfo.ifname or self.wdev
989end
990
991function wifinet.get_device(self)
992    if self.iwdata.device then
993        return wifidev(self.iwdata.device)
994    end
995end
996
997function wifinet.is_up(self)
998    return (self.iwdata.up == "1")
999end
1000
1001function wifinet.active_mode(self)
1002    local m = _stror(self.iwinfo.mode, self.iwdata.mode) or "ap"
1003
1004    if     m == "ap"      then m = "AP"
1005    elseif m == "sta"     then m = "Client"
1006    elseif m == "adhoc"   then m = "Ad-Hoc"
1007    elseif m == "mesh"    then m = "Mesh"
1008    elseif m == "monitor" then m = "Monitor"
1009    end
1010
1011    return m
1012end
1013
1014function wifinet.active_mode_i18n(self)
1015    return i18n.translate(self:active_mode())
1016end
1017
1018function wifinet.active_ssid(self)
1019    return _stror(self.iwinfo.ssid, self.iwdata.ssid)
1020end
1021
1022function wifinet.active_bssid(self)
1023    return _stror(self.iwinfo.bssid, self.iwdata.bssid) or "00:00:00:00:00:00"
1024end
1025
1026function wifinet.active_encryption(self)
1027    local enc = self.iwinfo and self.iwinfo.encryption
1028    return enc and enc.description or "-"
1029end
1030
1031function wifinet.assoclist(self)
1032    return self.iwinfo.assoclist or { }
1033end
1034
1035function wifinet.frequency(self)
1036    local freq = self.iwinfo.frequency
1037    if freq and freq > 0 then
1038        return "%.03f" % (freq / 1000)
1039    end
1040end
1041
1042function wifinet.bitrate(self)
1043    local rate = self.iwinfo.bitrate
1044    if rate and rate > 0 then
1045        return (rate / 1000)
1046    end
1047end
1048
1049function wifinet.channel(self)
1050    return self.iwinfo.channel or
1051        tonumber(uci_s:get("wireless", self.iwdata.device, "channel"))
1052end
1053
1054function wifinet.signal(self)
1055    return self.iwinfo.signal or 0
1056end
1057
1058function wifinet.noise(self)
1059    return self.iwinfo.noise or 0
1060end
1061
1062function wifinet.signal_level(self, s, n)
1063    if self:active_bssid() ~= "00:00:00:00:00:00" then
1064        local signal = s or self:signal()
1065        local noise  = n or self:noise()
1066
1067        if signal < 0 and noise < 0 then
1068            local snr = -1 * (noise - signal)
1069            return math.floor(snr / 5)
1070        else
1071            return 0
1072        end
1073    else
1074        return -1
1075    end
1076end
1077
1078function wifinet.signal_percent(self)
1079    local qc = self.iwinfo.quality or 0
1080    local qm = self.iwinfo.quality_max or 0
1081
1082    if qc > 0 and qm > 0 then
1083        return math.floor((100 / qm) * qc)
1084    else
1085        return 0
1086    end
1087end
1088
1089function wifinet.shortname(self)
1090    return "%s %q" %{
1091        i18n.translate(self:active_mode()),
1092        self:active_ssid() or self:active_bssid()
1093    }
1094end
1095
1096function wifinet.get_i18n(self)
1097    return "%s: %s %q (%s)" %{
1098        i18n.translate("Wireless Network"),
1099        i18n.translate(self:active_mode()),
1100        self:active_ssid() or self:active_bssid(),
1101        self:ifname()
1102    }
1103end
1104
1105function wifinet.adminlink(self)
1106    return dsp.build_url("admin", "network", "wireless",
1107        self.iwdata.device, self.wdev)
1108end
1109
1110function wifinet.get_network(self)
1111    if uci_r:get("network", self.iwdata.network) == "interface" then
1112        return network(self.iwdata.network)
1113    end
1114end
1115
1116function wifinet.get_interface(self)
1117    return interface(self:ifname())
1118end
Note: See TracBrowser for help on using the browser.