Explorar o código

Use MAC addresses provided by WLAN drivers by default

Some drivers (mt76) don't support arbitrary MAC addresses. Use the
addresses provided by the driver (avoiding the primary address) by default,
but fall back to our has-based scheme when the driver doesn't provide
(enough) addresses.
Matthias Schiffer %!s(int64=7) %!d(string=hai) anos
pai
achega
2afe34efec

+ 1 - 1
package/gluon-client-bridge/luasrc/lib/gluon/upgrade/320-gluon-client-bridge-wireless

@@ -25,7 +25,7 @@ local function configure_client(config, radio, index, suffix)
     return
   end
 
-  macaddr = util.generate_mac(3*(index-1))
+  macaddr = util.get_wlan_mac(radio, index, 1)
   if not macaddr then
     return
   end

+ 64 - 1
package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua

@@ -23,6 +23,7 @@ local function escape_args(ret, arg0, ...)
 end
 
 
+local io = io
 local os = os
 local string = string
 local tonumber = tonumber
@@ -34,6 +35,8 @@ local hash = require 'hash'
 local sysconfig = require 'gluon.sysconfig'
 local site = require 'gluon.site_config'
 local uci = require('luci.model.uci').cursor()
+local lutil = require 'luci.util'
+local fs = require 'nixio.fs'
 
 
 module 'gluon.util'
@@ -71,6 +74,45 @@ function node_id()
   return string.gsub(sysconfig.primary_mac, ':', '')
 end
 
+
+local function find_phy_by_path(path)
+  for phy in fs.glob('/sys/devices/' .. path .. '/ieee80211/phy*') do
+    return phy:match('([^/]+)$')
+  end
+end
+
+local function find_phy_by_macaddr(macaddr)
+  local addr = macaddr:lower()
+  for file in fs.glob('/sys/class/ieee80211/*/macaddress') do
+    if lutil.trim(fs.readfile(file)) == addr then
+      return file:match('([^/]+)/macaddress$')
+    end
+  end
+end
+
+local function find_phy(radio)
+  local config = uci:get_all('wireless', radio)
+
+  if not config or config.type ~= 'mac80211' then
+    return nil
+  elseif config.path then
+    return find_phy_by_path(config.path)
+  elseif config.macaddr then
+    return find_phy_by_macaddr(config.macaddr)
+  else
+    return nil
+  end
+end
+
+local function get_addresses(radio)
+  local phy = find_phy(radio)
+  if not phy then
+    return function() end
+  end
+
+  return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses')
+end
+
 -- Generates a (hopefully) unique MAC address
 -- The parameter defines the ID to add to the mac addr
 --
@@ -83,7 +125,7 @@ end
 -- 5: ibss1
 -- 6: mesh-on-lan
 -- 7: unused
-function generate_mac(i)
+local function generate_mac(i)
   if i > 7 or i < 0 then return nil end -- max allowed id (0b111)
 
   local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12)
@@ -105,6 +147,27 @@ function generate_mac(i)
   return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6)
 end
 
+function get_mac(index)
+  return generate_mac(3*(index-1))
+end
+
+function get_wlan_mac(radio, index, vif)
+  local primary = sysconfig.primary_mac:lower()
+
+  local i = 1
+  for addr in get_addresses(radio) do
+    if addr:lower() ~= primary then
+      if i == vif then
+        return addr
+      end
+
+      i = i + 1
+    end
+  end
+
+  return generate_mac(3*(index-1) + (vif-1))
+end
+
 -- Iterate over all radios defined in UCI calling
 -- f(radio, index, site.wifiX) for each radio found while passing
 --  site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones.

+ 1 - 2
package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan

@@ -5,6 +5,5 @@ local uci = require('luci.model.uci').cursor()
 
 
 -- fix up duplicate mac addresses (for mesh-on-WAN)
-uci:set('network', 'wan', 'macaddr', util.generate_mac(3))
+uci:set('network', 'wan', 'macaddr', util.get_mac(2))
 uci:save('network')
-

+ 2 - 2
package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless

@@ -33,7 +33,7 @@ local function configure_ibss(config, radio, index, suffix, disabled)
     return
   end
 
-  macaddr = util.generate_mac(3*(index-1)+2)
+  macaddr = util.get_wlan_mac(radio, index, 3)
   if not macaddr then
     return
   end
@@ -88,7 +88,7 @@ local function configure_mesh(config, radio, index, suffix, disabled)
     return
   end
 
-  macaddr = util.generate_mac(3*(index-1)+1)
+  macaddr = util.get_wlan_mac(radio, index, 2)
   if not macaddr then
     return
   end

+ 1 - 1
package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan

@@ -18,7 +18,7 @@ uci:section('network', 'interface', 'mesh_lan', {
   proto   = 'batadv',
   mesh    = 'bat0',
   mesh_no_rebroadcast = '1',
-  macaddr = util.generate_mac(6),
+  macaddr = util.get_mac(3),
 })
 
 if uci:get('network', 'mesh_lan', 'auto') == nil then

+ 1 - 1
package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd

@@ -127,7 +127,7 @@ uci:section('network', 'interface', 'mesh_vpn',
 		  proto = 'batadv',
 		  mesh = 'bat0',
 		  mesh_no_rebroadcast = 1,
-		  macaddr = util.generate_mac(0),
+		  macaddr = util.get_mac(1),
 	  }
 )