Need static MAC-address as soon as possible after boot

Hey there community,

I have two modules in my little MiniAppliance, which get new MAC-addresses on every reboot.

One is a WWAN-module and I did some research, apparently it is pretty normal for those kind of modules.The other one is a WIFI7-module. Actually this one does have a fixed MAC-address but either IPFire cannot “read it out” or it just is too new and needs a different way of transmitting it or the manufacturer messed up or the board.bin is buggy, whatever.

Anyway, long story short: I need a way to set a static MAC-address for these two network devices as soon as possible after starting the IPFire.

I tried it with some classic commands (ip link, ifconfig, etc.) and put them in the firewall.local and rd.local but the moment when those commands are executed seem to late. For example the MAC-change of the WLAN-module has to take place before IPFire loads the zones (because the configuration of the blue zone depends on the MAC-address).

Any ideas?

Greetings

Alex

I know there are other peaple in the forum that have had similar problems.
Like this.

1 Like

Have you looked at IPF > Network> Assign MAC Address, but it looks like if is only for Red0.

Hmm… unfortunately there is no line with “RED_DEV” or in my case “BLUE_DEV” like Arne mentioned. Maybe they renewed the settings-file in the last years… but anyway, I will give it a try. Thanks for the hint! :slight_smile:

No it hasn’t been changed.

I have all four zones on my system and the settings file has RED_DEV, GREEN_DEV, BLUE_DEV and ORANGE_DEV.

I am not sure why you would not have a red or blue entry in your settings file.

Are there any RED_ or BLUE_ settings in the file.

In mine, which is dhcp based red connection there are:-

RED_DHCP_HOSTNAME=ipfire
RED_MACADDR=00:0b:e2:c7:46:8a
RED_NETMASK=0.0.0.0
RED_TYPE=DHCP
RED_ADDRESS=0.0.0.0
RED_NETADDRESS=0.0.0.0
RED_MODE=
RED_SLAVES=
RED_DESCRIPTION='"pci: Intel Corporation I211 Gigabit Network Connection (rev 03)"'
RED_DEV=red0
RED_DRIVER=igb
RED_STP=
RED_DHCP_FORCE_MTU=

and for blue

BLUE_DEV=blue0
BLUE_DRIVER=igb
BLUE_STP=
BLUE_ADDRESS=192.168.233.254
BLUE_NETADDRESS=192.168.233.0
BLUE_MODE=
BLUE_NETMASK=255.255.255.0
BLUE_DESCRIPTION='"pci: Intel Corporation I211 Gigabit Network Connection (rev 03)"'
BLUE_MACADDR=00:0b:e2:d8:57:9b
BLUE_SLAVES=

are you missing everything or just some of the entries?

The two wifi modules don’t give you any option to choose to fix the MAC Address at all?
Mobile phones also have the MAC addresses that are randomly provided but you can also choose to use the phone’s physical MAC address so that it is fixed.

1 Like

Hi Alex,

My suggestion would be to drop a script with your ‘ip link’ commands or whatever you need to change the mac address into /etc/rc.d/rcsysinit.d and name it with a ‘S09’ prefix so that it runs before ‘S10udev’.

My thought is that the interfaces get renamed by udev which runs in rcsysinit at ‘S10udev’ so if you can change the mac address before udev is started I think it might work.

When udev gets started it processes the net events with /lib/udev/rules.d/60-net which in turn calls /lib/udev/network-hotplug-rename to do the renames based on mac address matched from the /var/ipfire/ethernet/settings file. If you look at network-hotplug-rename you can see where it loads the /var/ipfire/ethernet/settings file and loops through the zone colors to do the assigns.

You would need the original adapter names assigned by the kernel, which you can get with ‘grep rename /var/log/bootlog’ to do the mac address assigns. The mac addresses you set with your ‘ip link’ commands would have to match the ones in the /var/ipfire/ethernet/settings file so that everything matches up for udev to find them and do the renames.

My grep of bootlog looks like this:

grep renamed bootlog
[ 10.991608] bcmgenet fd580000.ethernet green0: renamed from eth0
[ 11.285374] r8152 2-2:1.0 red0: renamed from eth1

So if I were trying this for my system (which I haven’t btw) the link commands to run before udev starts would look something like:

ip link set dev eth0 address 12:34:56:78:9a:bc
ip link set dev eth1 address 12:34:56:78:9a:bd

and the 12:34:56:etcetra addresses would match those in /var/ipfire/ethernet/settings.

Hope that helps.

Stephen

Addendum: ‘ls /sys/class/net’ would also give you the network device names and may be a better option if the devices aren’t getting renamed to see in the bootlog.

2 Likes

Alex,

As a sidenote, what do you have in your ethernet/settings file? I was a little surprised that you don’t see RED_DEV and BLUE_DEV in there too.

Stephen

Hey there,

first of all: Thank you very much for your ideas / suggestions! :slight_smile:

second: Shame on me! Maybe because of the mixed up listing in the settings file (mine is not ordered by interface or alphabetically somehow) I missed the “DEV” entries. I just checked and there definitely ARE dev-entries for red, green and blue as well. Slightly embarassing… :woozy_face:

So I tried Arnes suggestion from the older post and changed the “BLUE_DEV=blue0” to “BLUE_DEV=wlan0” which fixed the issue that devices, connecting to blue, did not get an IP via dhcp despite the right MAC-address. Now this works…

But I guess this would not be enough and due to the MAC-address-randomizing I changed the configuration via “setup” after that, which obviously is cumbersome if you have to do it after every reboot.

Up until now I would not have known how to do this.

The WWAN-module does not have a MAC as far as I know and the WLAN-module has one printed on it’s label but apparently this information is not transmitted through the firmware or not read out by the driver or whatever.

Anyway, I switched back to the old Compex-module for now because I need a working WIFI for HomeOffice. :smiley:

But hopefully on the weekend (at the latest) I will try out @stephen’s suggestions and will do some digging into the udev-rules (just to understand the order and everything), as well as the bootlog and the sys/class/net to find a way to set the MAC as early as possible.

So again, thanks a lot to you guys, have a nice evening and I will keep you posted about my progress! :slight_smile:

Greetings

Alex

2 Likes

Hey there,

this idea was a really good call but sadly it didn’t work.

I tried it at multiple “places” of the initialization process (from S09 before udev up to S89 as the last but one before “firewall”) but at all those points it spits out the error “wlan0 cannot be found”, so I guess the “device-renaming-process” of IPFire (or more precisely linux itself I guess) takes place after this.

If I “execute” the renaming of the MAC-adress after “firewall” I have the problem, that the “rules” do not match the interfaces and the network has to be realoaded again.

So for now the only possibility I have, is to wait until IPFire boots the normal way (with the error that the interface with the MAC-adress XX:XX… cannot be found) then change the MAC-adress and then do a “/etc/init.d/network restart”.

This way everything works…

Any more ideas? There has to be a point where linux assigns random MACs to devices, which do not have one (I guess)… at this point it has to be possible to assign a specific address…

Already googled for this problem, but found no other solutions than “macchanger” which is unsuitable because I do not want to change the MAC-adress but want it to stay the same. :smiley:

Greetings

Alex

Hi Alex,

I set up a VM to test the ‘before udev’ approach with IPFire and was able to get it working. Details follow.

The test machine that I set up was a VM with 2 nics and IPFire installed, nothing special and no actual connections to the outside world.

So the first thing that I did was “Information Gathering”. I went to the “/etc/rc.d/rcsysinit.d” directory and installed some debug scripts. Note that in some of the screen shots I’m using “:” (colon) bash command for inline comments.

After the reboot, I get dropped to bash when rcsysinit is running.

So time to do some detective work. Let’s find out what the kernel assigned my nics to and the current mac addresses of the nics…

Right now, my nics are eth0 and eth1 with mac addresses 08:00:27:6b:36:a9 and 08:00:27:cd:49:0a. And those are the same mac addresses that I set for red0 and green0 when I did the command line setup installing IPFire.

So let’s change those to 08:00:27:aa:aa:aa for eth0 and 08:00:27:bb:bb:bb for eth1.

And check the changes.

Now the mac addresses are the ones that we want, let’s exit bash and continue to boot.

S10udev just ran and we got dropped back into bash by the S11bashdebug, so let’s see what we have.

The mac addresses are changed, but red0 and green0 did not get assigned. That’s because ‘/var/ipfire/ethernet/settings’ don’t match the new IP addresses of the adapters. We’ll need to fix that but can’t here because we are in the middle of a boot and the root partition is mounted read-only. So let’s ‘exit’ bash to continue the boot and get back to the console.

Back at the console we can see that the mac addresses are what we want, but red0 and green0 are not assigned the way that we want them to be.

So first, let’s persist the mac address changes that we made by putting those changes in a script for rcsysinit. I created a file ‘S09macchange’ with the ‘ip link’ commands in ‘/etc/rc.d/rcsysinit’ and made it executable. I used ‘echo’ commands to create the file here for display purposes.

And now I have to change ‘/var/ipfire/ethernet/settings’ to match the IP addresses that I want. Here are the results of that.

Before I reboot and see if this all works, I want to add another bashdebug checkpoint so that I can check before and after the ‘ip link’ commands run. So I copy the S09bashdebug file to S09zbashdebug.

Since the scripts get run in name order, when I reboot, they will get run in this order.

So ready to reboot, let’s see what happens.

On reboot, I get dropped to the first bash checkpoint as expected and do some checking.

Mac changes worked, next udev has to pick those changes up when assigning red0 and green0 so let’s exit this checkpoint and see what happens when udev runs.

Now after udev runs we have red0 and green0 interfaces so this worked for the test VM. For cleanup, delete the ‘S*bashdebug’ files from ‘/etc/rc.d/rcsysinit’ so that boot flows cleanly.

Gotta have a direct console to do this, can’t do it all over ssh, but maybe would work for you.

Stephen

2 Likes

Hey @stephen,

first of all: You sir, are a gentleman! So much effort, thanks a lot for this! My problem is not yet solved but it helped me a big step further.

Here are my results:

First, I adopted your idea with the debug scripts to check the status after every step. It turns out that there is no wlan0 before udev:

01

(I have five eth-interfaces because of an additional USB-dongle, the wwan0-interface is an LTE-modul). wlan0 is definitely not there yet, also not showing up in ifconfig (I know it’s obsolete, but just for showing):

But right after executing udev, wlan0 is suddenly there:

03

Also in ifconfig:

So I figured, I must have done something wrong in the past, when the script for changing the mac-address did not work at different points of rcsysinit…

But now comes the really weird part:

When I stop the booting-process to open a bash (after udev)… then change the mac-adress by hand, then exit the bash to continue the booting-process of IPFire, everything works fine:

(Don’t mind the hostapd error-messages, that’s another construction site :smiley:)

But when I try to automate this part via script, then I get the same error like before.

I tried it with

ifconfig wlan0 down
ifconfig wlan0 hw ether XX:XX:XX:XX:XX:XX
ifconfig wlan0 up)

which leads to

06

And I tried

ip link set dev wlan0 down
ip link set dev wlan0 address XX:XX:XX:XX:XX:XX
ip link set dev wlan0 up

which leads to

07

No success at all…

Again: When I stop the booting to open “bash” and then execute the mac-change by hand, everything works fine. So as a workaround I thought of opening a bash and running the mac-change within it and closing it again, but I had to realize I’m not able of doing this yet, since I need pipes for this and I haven’t read into it yet. :nerd_face:

Anyway, thank you very much again for all your effort, I’ll keep you posted as soon as I tinkered a solution. :slight_smile:

1 Like

Hi Alex,

Glad that you found the troubleshooting approach helpful. :wink:

I read through your post and I agree, it’s really, really weird…

So this may sound crazy, but what if it’s a race condition?

I’m not a kernel expert by any means, but pretty sure that the kernel creates the device name after it loads the driver and performs at least some type of low level initialization to make sure that it can talk to the device. So if the device name isn’t there, then the kernel hasn’t put it there yet, right?

Your manual configuration maybe works because sufficient time has passed for the wlan0 device to be ready, but when you automate it the device isn’t ready in time and the boot process just blows past the mac-change script producing the errors that you’re seeing.

Easy to test at your first breakpoint. Do the ‘ls /sys/class/net’ and then wait a minute or two and run it again to see if ‘wlan0’ shows up after a period of time.

Stephen

2 Likes

Hey there,

I did some more digging and “detective work” :wink: and found something interesting and a workaround.

The interesting thingy:

Before udev is executed, the interface, or more specific the device itself is missing the “net-folder” (I guess it’s not really a folder but on this level of linux it is over my head for now… and possibly will be forever :smiley:). I opened a bash before udev and waited for minutes, nothing changed. After udev, it shows up (after about 4 seconds).

Explanation:

I checked with “ls -lash” before and after udev. After udev the interface is named “wlan0”, which is also the “subfolder” under the “net-folder” (bear with me here) in the device itself (like with all the other interfaces / devices).

Before udev is executed the wlan0-interface is missing (as we already know)

So I went to the “device-path” itself and found that there is no “net-folder”

I did the same check after udev again and there it is

Since the “names” of the interfaces are within those “net-folders” (sorry again for calling them folders but as I said, this is way beyond my understanding) it cannot be renamed by IPFire because it has not gotten it’s original name in the first place.

It must have something to do with the driver or the firmware of this module, since the link to the ath12k driver and some other driver-related folders like “ieee80211” and “mhi0” are also missing. And so it is not fully loaded until something is done, which is coincidentally done by udev.

After udev it works BUT it takes some time. I did multiple restarts for testing and found out, that the net folder and therefor the naming wlan0 shows up after about 4 seconds. So @stephen you were right again :+1:, it is a race condition.

The workaround:

I wrote a small script, which is executed directly after udev (named it S11wlan0) and which starts with a “sleep 5”. Now everything works as it should. It’s not the best solution, I would prefer the standard IPFire naming convention “blue0” but this would mean executing udev (or parts of it) again and this might mess things up. And for a partial rewrite I’m definitely not skilled enough. So for now I’m going to rename “blue0” to “wlan0” in the ethernet/settings and wlanap/settings and it works.

Anyway, I will mark you first response as solution because it kind of is. Thank you very much again! :slight_smile:

Greetings and have a nice weekend!

Hi Alex,

I think if you restart udev after making the mac address change it may complete your solution with wlan0 renamed to blue0. Restarting udev shouldn’t cause any problems.

Try adding ‘/etc/init.d/udev restart’ to the end of your S11wlan0 script and see if that works to get the blue0.

Stephen

1 Like

Hey Stephen,

I tried that but sadly it did not work. The only way to change wlan0 to blue0 is to do a “setup” on the CLI, modify something (does not have to be the interface-config; IP or Subnet is enough) and save it… then blue0 is suddenly there.

Maybe I can find out which part of udev makes wlan0 appear in the first place and I could execute this before the whole hotplug-renaming script.

Hey @stephen,

just wanted to let you know that I must have done something wrong at a specific point because NOW it works. :slight_smile: I rename wlan0 to blue0 right after udev and then, even without running udev again, everything works fine because it matches the configuration I made before via “setup”.

So just wanted to say thank you again, you helped me a lot. :slight_smile:

Greetings and a nice weekend

Alex

1 Like