Reorganize MAC addresses, always explicitly set address for private WLAN
Fixes #842
This commit is contained in:
		
							parent
							
								
									4f39be09c9
								
							
						
					
					
						commit
						6cddaedfc7
					
				
							
								
								
									
										18
									
								
								docs/dev/mac_addresses.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								docs/dev/mac_addresses.rst
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
| @ -43,6 +43,7 @@ Developer Documentation | ||||
|    dev/configmode | ||||
|    dev/wan | ||||
|    dev/i18n | ||||
|    dev/mac_addresses | ||||
| 
 | ||||
| Packages | ||||
| -------- | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -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') | ||||
|  | ||||
| @ -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), | ||||
|   } | ||||
| ) | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user