Browse Source

Reorganize MAC addresses, always explicitly set address for private WLAN

Fixes #842
Matthias Schiffer 7 years ago
parent
commit
6cddaedfc7

+ 18 - 0
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

+ 1 - 0
docs/index.rst

@@ -43,6 +43,7 @@ Developer Documentation
    dev/configmode
    dev/wan
    dev/i18n
+   dev/mac_addresses
 
 Packages
 --------

+ 17 - 0
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)

+ 13 - 17
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

+ 12 - 15
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
 

+ 3 - 3
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')

+ 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 = 'gluon_mesh',
     transitive = 1,
     fixed_mtu = 1,
-    macaddr = util.get_mac(3),
+    macaddr = util.generate_mac(7),
   }
 )