From c73a12e0ea9fd6bb48927f0a03367354b5897ddc Mon Sep 17 00:00:00 2001 From: lemoer <git@irrelefant.net> Date: Wed, 27 Apr 2016 12:16:39 +0200 Subject: [PATCH] Change MAC schema generation (#715) While ath9k/ath10k devices can supprt VIFs with any combination of MAC addresses, there are also adapters which have a hardware MAC filter which only allows a few bits to differ. This commit changes the addresses of all VIFs to ony differ in the last 3 bits, which is required to support many Ralink/Mediatek based WLAN adapters. Technically, the new addresses are generated by calculating an MD5 hash of the primary MAC address and using a part of this hash as a prefix for the MAC addresses. The addresses (BSSIDs) of the AP VIFs are also reused for the LAN and WAN interfaces in mesh-on-LAN/WAN mode to reduce the number of needed addresses, and thus reduce the chance of collisions. This is not a problem as the MAC addresses of the AP VIFs are never used except as BSSID, and thus not seen by routing protocols like batman-adv. Fixes #648 [Matthias Schiffer: rewrote commit message] --- .../upgrade/320-gluon-client-bridge-wireless | 6 ++- package/gluon-core/Makefile | 2 +- .../files/usr/lib/lua/gluon/util.lua | 48 ++++++++++++------- .../300-gluon-mesh-batman-adv-core-wan | 2 +- .../320-gluon-mesh-batman-adv-core-wireless | 12 +++-- ...340-gluon-mesh-batman-adv-core-mesh-on-lan | 2 +- .../lib/gluon/upgrade/400-mesh-vpn-fastd | 2 +- 7 files changed, 48 insertions(+), 26 deletions(-) diff --git a/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless b/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless index 8d5c7181f..6fc8a72a5 100755 --- a/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless +++ b/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless @@ -21,14 +21,16 @@ local function configure_client(config, radio, index, suffix) uci:delete('wireless', name) - if config then + macaddr = util.generate_mac(3*index) + + if config and macaddr then uci:section('wireless', 'wifi-iface', name, { device = radio, network = 'client', mode = 'ap', ssid = config.ssid, - macaddr = util.generate_mac(2, index), + macaddr = macaddr, ifname = suffix and 'client' .. suffix, disabled = disabled, } diff --git a/package/gluon-core/Makefile b/package/gluon-core/Makefile index de54283ba..725fb7375 100644 --- a/package/gluon-core/Makefile +++ b/package/gluon-core/Makefile @@ -12,7 +12,7 @@ define Package/gluon-core SECTION:=gluon CATEGORY:=Gluon TITLE:=Base files of Gluon - DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +luci-base +luci-lib-jsonc +odhcp6c +firewall + DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +lua-hash +luci-base +luci-lib-jsonc +odhcp6c +firewall endef diff --git a/package/gluon-core/files/usr/lib/lua/gluon/util.lua b/package/gluon-core/files/usr/lib/lua/gluon/util.lua index d9df636f5..72b6220d8 100644 --- a/package/gluon-core/files/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/files/usr/lib/lua/gluon/util.lua @@ -30,6 +30,7 @@ local ipairs = ipairs local table = table local nixio = require 'nixio' +local hash = require 'hash' local sysconfig = require 'gluon.sysconfig' local site = require 'gluon.site_config' local uci = require('luci.model.uci').cursor() @@ -71,22 +72,37 @@ function node_id() end -- Generates a (hopefully) unique MAC address --- The first parameter defines the function and the second --- parameter an ID to add to the MAC address --- Functions and IDs defined so far: --- (1, 0): WAN (for mesh-on-WAN) --- (1, 1): LAN (for mesh-on-LAN) --- (2, n): client interface for the n'th radio --- (3, n): adhoc interface for n'th radio --- (4, 0): mesh VPN --- (5, n): mesh interface for n'th radio (802.11s) -function generate_mac(f, i) - local m1, m2, m3, m4, m5, m6 = string.match(sysconfig.primary_mac, '(%x%x):(%x%x):(%x%x):(%x%x):(%x%x):(%x%x)') - m1 = nixio.bit.bor(tonumber(m1, 16), 0x02) - m2 = (tonumber(m2, 16)+f) % 0x100 - m3 = (tonumber(m3, 16)+i) % 0x100 - - return string.format('%02x:%02x:%02x:%s:%s:%s', m1, m2, m3, m4, m5, m6) +-- The parameter defines the ID to add to the mac addr +-- +-- IDs defined so far: +-- 0: client0; mesh-vpn +-- 1: mesh0 +-- 2: ibss0 +-- 3: client1; mesh-on-wan +-- 4: mesh1 +-- 5: ibss1 +-- 6: mesh-on-lan +-- 7: unused +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) + local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)') + + m1 = tonumber(m1, 16) + m6 = tonumber(m6, 16) + + m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit + m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit + + -- It's necessary that the first 45 bits of the mac do + -- not vary on a single hardware interface, since some chips are using + -- a hardware mac filter. (e.g 'ramips-rt305x') + + m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) + m6 = m6 + i -- add virtual interface id + + return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) end -- Iterate over all radios defined in UCI calling diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan index 00b164147..be96c012b 100755 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan +++ b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan @@ -5,6 +5,6 @@ local uci = require('luci.model.uci').cursor() -- fix up duplicate mac addresses (for mesh-on-WAN) -uci:set('network', 'wan', 'macaddr', util.generate_mac(1, 0)) +uci:set('network', 'wan', 'macaddr', util.generate_mac(3)) uci:save('network') diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless index a73912b86..05462c6fe 100755 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless +++ b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless @@ -29,7 +29,9 @@ local function configure_ibss(config, radio, index, suffix, disabled) uci:delete('network', name .. '_vlan') uci:delete('wireless', name) - if config then + macaddr = util.generate_mac(3*index+2) + + if config and macaddr then if config.vlan then uci:section('network', 'interface', name, { @@ -60,7 +62,7 @@ local function configure_ibss(config, radio, index, suffix, disabled) mode = 'adhoc', ssid = config.ssid, bssid = config.bssid, - macaddr = util.generate_mac(3, index), + macaddr = macaddr, mcast_rate = config.mcast_rate, ifname = suffix and 'ibss' .. suffix, disabled = disabled and 1 or 0, @@ -77,7 +79,9 @@ local function configure_mesh(config, radio, index, suffix, disabled) uci:delete('network', name) uci:delete('wireless', name) - if config then + macaddr = util.generate_mac(3*index+1) + + if config and macaddr then uci:section('network', 'interface', name, { proto = 'batadv', @@ -92,7 +96,7 @@ local function configure_mesh(config, radio, index, suffix, disabled) mode = 'mesh', mesh_id = config.id, mesh_fwding = 0, - macaddr = util.generate_mac(5, index), + macaddr = macaddr, mcast_rate = config.mcast_rate, ifname = suffix and 'mesh' .. suffix, disabled = disabled and 1 or 0, diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan index 27c1935bb..cbc9cd947 100755 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan +++ b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan @@ -28,7 +28,7 @@ if sysconfig.lan_ifname and not uci:get('network', 'mesh_lan') then , proto = 'batadv' , mesh = 'bat0' , mesh_no_rebroadcast = '1' - , macaddr = util.generate_mac(1, 1) + , macaddr = util.generate_mac(6) , auto = enable and 1 or 0 }) diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd b/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd index 902f1ccd2..77f2e6f29 100755 --- a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd +++ b/package/gluon-mesh-vpn-fastd/files/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(4, 0), + macaddr = util.generate_mac(0), } ) -- GitLab