From e795f61252b4836b3d948ed21996e435ce995c04 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 31 Aug 2016 00:37:59 +0200 Subject: [PATCH] Reorganize MAC addresses, always explicitly set address for private WLAN Fixes #842 --- docs/dev/mac_addresses.rst | 18 +++++++++++ docs/index.rst | 1 + .../luasrc/lib/gluon/upgrade/200-wireless | 17 +++++++++++ .../luasrc/usr/lib/lua/gluon/util.lua | 30 ++++++++----------- .../lua/luci/model/cbi/admin/privatewifi.lua | 27 ++++++++--------- ...0-gluon-mesh-batman-adv-core-mac-addresses | 6 ++-- .../lib/gluon/upgrade/400-mesh-vpn-fastd | 2 +- 7 files changed, 65 insertions(+), 36 deletions(-) create mode 100644 docs/dev/mac_addresses.rst diff --git a/docs/dev/mac_addresses.rst b/docs/dev/mac_addresses.rst new file mode 100644 index 00000000..b221a302 --- /dev/null +++ b/docs/dev/mac_addresses.rst @@ -0,0 +1,18 @@ +MAC addresses +============= + +Many devices don't have enough unique MAC addresses assigned by the vendor +(in batman-adv, each mesh interface needs an own MAC address that must be unique +mesh-wide). + +Gluon tries to solve this issue by using a hash of the primary MAC address as a +45 bit MAC address prefix. The resulting 8 addresses are used as follows: + +* 0: client0; WAN +* 1: mesh0 +* 2: ibss0 +* 3: wan_radio0 (private WLAN); batman-adv primary address +* 4: client1; LAN +* 5: mesh1 +* 6: ibss1 +* 7: wan_radio1 (private WLAN); mesh VPN diff --git a/docs/index.rst b/docs/index.rst index 769f6e8c..8c12b40d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -43,6 +43,7 @@ Developer Documentation dev/configmode dev/wan dev/i18n + dev/mac_addresses Packages -------- diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless index ae23427f..6e809572 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless @@ -127,6 +127,21 @@ local function configure_mesh(config, radio, index, suffix, disabled) ) end +local function fixup_wan(radio, index) + local name = 'wan_' .. radio + + if not uci:get('wireless', name) then + return + end + + local macaddr = util.get_wlan_mac(radio, index, 4) + if not macaddr then + return + end + + uci:set('wireless', name, 'macaddr', macaddr) +end + local function configure_radio(radio, index, config) if not config then return @@ -177,6 +192,8 @@ local function configure_radio(radio, index, config) false ) ) + + fixup_wan(radio, index) end util.iterate_radios(configure_radio) diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua index 677cfc52..0ae50b4d 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -114,18 +114,18 @@ local function get_addresses(radio) end -- Generates a (hopefully) unique MAC address --- The parameter defines the ID to add to the mac addr +-- The parameter defines the ID to add to the MAC address -- -- IDs defined so far: --- 0: client0; mesh-vpn +-- 0: client0; WAN -- 1: mesh0 -- 2: ibss0 --- 3: client1; mesh-on-wan --- 4: mesh1 --- 5: ibss1 --- 6: mesh-on-lan --- 7: unused -local function generate_mac(i) +-- 3: wan_radio0 (private WLAN); batman-adv primary address +-- 4: client1; LAN +-- 5: mesh1 +-- 6: ibss1 +-- 7: wan_radio1 (private WLAN); mesh VPN +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) @@ -137,9 +137,9 @@ local function generate_mac(i) 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') + -- It's necessary that the first 45 bits of the MAC address don't + -- vary on a single hardware interface, since some chips are using + -- a hardware MAC filter. (e.g 'rt305x') m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) m6 = m6 + i -- add virtual interface id @@ -147,11 +147,7 @@ local 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_from_driver(radio, vif) +local function get_wlan_mac_from_driver(radio, vif) local primary = sysconfig.primary_mac:lower() local i = 1 @@ -172,7 +168,7 @@ function get_wlan_mac(radio, index, vif) return addr end - return generate_mac(3*(index-1) + (vif-1)) + return generate_mac(4*(index-1) + (vif-1)) end -- Iterate over all radios defined in UCI calling diff --git a/package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua b/package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua index f05eaa47..46a1a9d7 100644 --- a/package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua +++ b/package/gluon-luci-private-wifi/luasrc/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua @@ -2,11 +2,10 @@ local uci = luci.model.uci.cursor() local util = require 'gluon.util' local f, s, o, ssid -local config = 'wireless' -- where to read the configuration from local primary_iface = 'wan_radio0' -local ssid = uci:get(config, primary_iface, "ssid") +local ssid = uci:get('wireless', primary_iface, "ssid") f = SimpleForm("wifi", translate("Private WLAN")) f.template = "admin/expertmode" @@ -19,7 +18,7 @@ s = f:section(SimpleSection, nil, translate( )) o = s:option(Flag, "enabled", translate("Enabled")) -o.default = (ssid and not uci:get_bool(config, primary_iface, "disabled")) and o.enabled or o.disabled +o.default = (ssid and not uci:get_bool('wireless', primary_iface, "disabled")) and o.enabled or o.disabled o.rmempty = false o = s:option(Value, "ssid", translate("Name (SSID)")) @@ -30,22 +29,19 @@ o.default = ssid o = s:option(Value, "key", translate("Key"), translate("8-63 characters")) o:depends("enabled", '1') o.datatype = "wpakey" -o.default = uci:get(config, primary_iface, "key") +o.default = uci:get('wireless', primary_iface, "key") function f.handle(self, state, data) if state == FORM_VALID then - uci:foreach(config, "wifi-device", - function(s) - local radio = s['.name'] + util.iterate_radios( + function(radio, index) local name = "wan_" .. radio if data.enabled == '1' then - -- get_wlan_mac_from_driver will return nil (and thus leave the - -- MAC address unset) if the driver doesn't provide enough addresses - local macaddr = util.get_wlan_mac_from_driver(radio, 4) + local macaddr = util.get_wlan_mac(radio, index, 4) -- set up WAN wifi-iface - uci:section(config, "wifi-iface", name, + uci:section('wireless', "wifi-iface", name, { device = radio, network = "wan", @@ -59,12 +55,13 @@ function f.handle(self, state, data) ) else -- disable WAN wifi-iface - uci:set(config, name, "disabled", 1) + uci:set('wireless', name, "disabled", 1) end - end) + end + ) - uci:save(config) - uci:commit(config) + uci:save('wireless') + uci:commit('wireless') end end diff --git a/package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-mac-addresses b/package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-mac-addresses index ca4f1474..38011107 100755 --- a/package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-mac-addresses +++ b/package/gluon-mesh-batman-adv-core/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-mac-addresses @@ -4,7 +4,7 @@ local util = require 'gluon.util' local uci = require('luci.model.uci').cursor() --- fix up duplicate mac addresses (for meshing) -uci:set('network', 'wan', 'macaddr', util.get_mac(1)) -uci:set('network', 'mesh_lan', 'macaddr', util.get_mac(2)) +-- fix up potentially duplicate MAC addresses (for meshing) +uci:set('network', 'wan', 'macaddr', util.generate_mac(0)) +uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(4)) uci:save('network') diff --git a/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd index 2fd35a1f..74ab4a41 100755 --- a/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd +++ b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd @@ -127,7 +127,7 @@ uci:section('network', 'interface', 'mesh_vpn', proto = 'gluon_mesh', transitive = 1, fixed_mtu = 1, - macaddr = util.get_mac(3), + macaddr = util.generate_mac(7), } )