libs/core: implement special treatment of wireless in network model
authorJo-Philipp Wich <jow@openwrt.org>
Thu, 15 Oct 2009 16:30:17 +0000 (16:30 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Thu, 15 Oct 2009 16:30:17 +0000 (16:30 +0000)
libs/core/luasrc/model/network.lua
libs/core/luasrc/model/network/wireless.lua [new file with mode: 0644]

index 718f07d..debf3db 100644 (file)
@@ -17,8 +17,8 @@ limitations under the License.
 
 ]]--
 
-local type, pairs, ipairs, table, i18n
-       = type, pairs, ipairs, table, luci.i18n
+local type, pairs, ipairs, loadfile, table, i18n
+       = type, pairs, ipairs, loadfile, table, luci.i18n
 
 local lmo = require "lmo"
 local nxo = require "nixio"
@@ -30,6 +30,28 @@ local uct = require "luci.model.uci.bind"
 
 module "luci.model.network"
 
+-- load extensions
+local ext
+local handler = { }
+
+for ext in nfs.glob(utl.libpath() .. "/model/network/*.lua") do
+       if nfs.access(ext) then
+               local m = loadfile(ext)
+               if m then
+                       handler[#handler+1] = m()
+               end
+       end
+end
+
+function foreach_handler(code, ...)
+       local h
+       for _, h in ipairs(handler) do
+               if code(h, ...) then
+                       return true
+               end
+       end
+       return false
+end
 
 local ub = uct.bind("network")
 local ifs, brs, sws
@@ -44,6 +66,12 @@ function init(cursor)
                brs = { }
                sws = { }
 
+               -- init handler
+               foreach_handler(function(h)
+                       h:init(cursor)
+                       h:find_interfaces(ifs, brs)
+               end)
+
                -- read interface information
                local n, i
                for n, i in ipairs(nxo.getifaddrs()) do
@@ -75,7 +103,7 @@ function init(cursor)
                                        ifs[name].ip6addrs[#ifs[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
                                end
                        end
-               end             
+               end
 
                -- read bridge informaton
                local b, l
@@ -150,6 +178,8 @@ function del_network(self, n)
                                        ub.uci:delete("network", s['.name'])
                                end
                        end)
+
+               foreach_handler(function(h) h:del_network(n) end)
        end
        return r
 end
@@ -179,6 +209,8 @@ function rename_network(self, old, new)
                                                ub.uci:set("network", s['.name'], "interface", new)
                                        end
                                end)
+
+                       foreach_handler(function(h) h:rename_network(old, new) end)
                end
        end
        return r or false
@@ -198,8 +230,12 @@ function get_interfaces(self)
 end
 
 function ignore_interface(self, x)
-       return (x:match("^wmaster%d") or x:match("^wifi%d")
-               or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
+       if foreach_handler(function(h) return h:ignore_interface(x) end) then
+               return true
+       else
+               return (x:match("^wmaster%d") or x:match("^wifi%d")
+                       or x:match("^hwsim%d") or x:match("^imq%d") or x == "lo")
+       end
 end
 
 
@@ -218,11 +254,27 @@ function network.is_bridge(self)
 end
 
 function network.add_interface(self, ifname)
+       local ifaces, iface
+
        if type(ifname) ~= "string" then
-               ifname = ifname:name()
+               ifaces = { ifname:name() }
+       else
+               ifaces = ub:list(ifname)
        end
-       if ifs[ifname] then
-               self:ifname(ub:list((self:ifname() or ''), ifname))
+
+       for _, iface in ipairs(ifaces) do
+               if ifs[iface] then
+                       -- make sure the interface is removed from all networks
+                       local i = interface(iface)
+                       local n = i:get_network()
+                       if n then n:del_interface(iface) end
+
+                       if ifs[iface].handler then
+                               ifs[iface].handler:add_interface(self, iface, ifs[iface])
+                       else
+                               self:ifname(ub:list((self:ifname() or ''), iface))
+                       end
+               end
        end
 end
 
@@ -230,7 +282,12 @@ function network.del_interface(self, ifname)
        if type(ifname) ~= "string" then
                ifname = ifname:name()
        end
-       self:ifname(ub:list((self:ifname() or ''), nil, ifname))
+
+       if ifs[ifname] and ifs[ifname].handler then
+               ifs[ifname].handler:del_interface(self, ifname, ifs[ifname])
+       else
+               self:ifname(ub:list((self:ifname() or ''), nil, ifname))
+       end
 end
 
 function network.get_interfaces(self)
@@ -242,6 +299,11 @@ function network.get_interfaces(self)
                        ifaces[#ifaces+1] = interface(iface)
                end
        end
+       for iface, _ in pairs(ifs) do
+               if ifs[iface].network == self:name() then
+                       ifaces[#ifaces+1] = interface(iface)
+               end
+       end
        return ifaces
 end
 
@@ -259,6 +321,12 @@ function network.contains_interface(self, iface)
                end
        end
 
+       for i, _ in pairs(ifs) do
+               if ifs[i].dev and ifs[i].dev.network == self:name() then
+                       return true
+               end
+       end
+
        return false
 end
 
@@ -289,8 +357,8 @@ function interface.ip6addrs(self)
 end
 
 function interface.type(self)
-       if iwi.type(self.ifname) and iwi.type(self.ifname) ~= "dummy" then
-               return "wifi"
+       if self.dev and self.dev.type then
+               return self.dev.type
        elseif brs[self.ifname] then
                return "bridge"
        elseif sws[self.ifname] or self.ifname:match("%.") then
@@ -300,6 +368,22 @@ function interface.type(self)
        end
 end
 
+function interface.shortname(self)
+       if self.dev and self.dev.handler then
+               return self.dev.handler:shortname(self)
+       else
+               return self.ifname
+       end
+end
+
+function interface.get_i18n(self)
+       if self.dev and self.dev.handler then
+               return self.dev.handler:get_i18n(self)
+       else
+               return "%s: %q" %{ self:get_type_i18n(), self:name() }
+       end
+end
+
 function interface.get_type_i18n(self)
        local x = self:type()
        if x == "wifi" then
@@ -373,6 +457,10 @@ function interface.rx_packets(self)
 end
 
 function interface.get_network(self)
+       if self.dev and self.dev.network then
+               self.network = _M:get_network(self.dev.network)
+       end
+
        if not self.network then
                local net
                for _, net in ipairs(_M:get_networks()) do
diff --git a/libs/core/luasrc/model/network/wireless.lua b/libs/core/luasrc/model/network/wireless.lua
new file mode 100644 (file)
index 0000000..ec4131b
--- /dev/null
@@ -0,0 +1,148 @@
+--[[
+LuCI - Network model - Wireless extension
+
+Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+]]--
+
+local pairs, i18n, uci = pairs, luci.i18n, luci.model.uci
+
+local iwi = require "iwinfo"
+local utl = require "luci.util"
+local uct = require "luci.model.uci.bind"
+
+module "luci.model.network.wireless"
+
+local ub = uct.bind("wireless")
+local st, ifs
+
+function init(self, cursor)
+       cursor:unload("wireless")
+       cursor:load("wireless")
+       ub:init(cursor)
+
+       st = uci.cursor_state()
+       ifs = { }
+
+       local count = 0
+               
+       ub.uci:foreach("wireless", "wifi-iface",
+               function(s)
+                       count = count + 1
+
+                       local device = s.device or "wlan0"
+                       local state = st:get_all("wireless", s['.name'])
+                       local name = state.ifname or device .. ".network" .. count
+                       
+                       ifs[state and state.ifname or name] = {
+                               idx      = count,
+                               name     = state and state.ifname or name,
+                               rawname  = state and state.ifname or name,
+                               flags    = { },
+                               ipaddrs  = { },
+                               ip6addrs = { },
+
+                               type     = "wifi",
+                               network  = s.network,
+                               handler  = self,
+                               wifi     = state or s,
+                               sid      = s['.name']
+                       }
+               end)
+end
+
+function shortname(self, iface)
+       if iface.dev and iface.dev.wifi then
+               return "%s %q" %{
+                       i18n.translate("a_s_if_iwmode_" .. (iface.dev.wifi.mode or "ap")), 
+                       iface.dev.wifi.ssid or iface.dev.wifi.bssid or "(hidden)"
+               }
+       else
+               return iface:name()
+       end
+end
+
+function get_i18n(self, iface)
+       if iface.dev and iface.dev.wifi then
+               return "%s: %s %q" %{
+                       i18n.translate("a_s_if_wifinet", "Wireless Network"),
+                       i18n.translate("a_s_if_iwmode_" .. (iface.dev.wifi.mode or "ap"), iface.dev.wifi.mode or "AP"),
+                       iface.dev.wifi.ssid or iface.dev.wifi.bssid or "(hidden)"
+               }
+       else
+               return "%s: %q" %{ i18n.translate("a_s_if_wifinet", "Wireless Network"), iface:name() }
+       end
+end
+
+function rename_network(self, old, new)
+       local i
+       for i, _ in pairs(ifs) do
+               if ifs[i].network == old then
+                       ifs[i].network = new
+               end
+       end
+
+       ub.uci:foreach("wireless", "wifi-iface",
+               function(s)
+                       if s.network == old then
+                               if new then 
+                                       ub.uci:set("wireless", s['.name'], "network", new)
+                               else
+                                       ub.uci:delete("wireless", s['.name'], "network")
+                               end
+                       end
+               end)
+end
+
+function del_network(self, old)
+       return self:rename_network(old, nil)
+end
+
+function find_interfaces(self, iflist, brlist)
+       local iface
+       for iface, _ in pairs(ifs) do
+               iflist[iface] = ifs[iface]
+       end
+end
+
+function ignore_interface(self, iface)
+       if ifs and ifs[iface] then
+               return false
+       else
+               return iwi.type(iface) and true or false
+       end
+end
+
+function add_interface(self, net, iface)
+       if ifs and ifs[iface] and ifs[iface].sid then
+               ub.uci:set("wireless", ifs[iface].sid, "network", net:name())
+               ifs[iface].network = net:name()
+               return true
+       end
+
+       return false
+end
+
+function del_interface(self, net, iface)
+       if ifs and ifs[iface] and ifs[iface].sid then
+               ub.uci:delete("wireless", ifs[iface].sid, "network")
+               --return true
+       end
+
+       return false
+end
+
+return _M
+