You probably know that MAC address can be generated, for instance, in the following way:

macaddr=$(dd if=/dev/random bs=1024 count=1 2>/dev/null|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\)\(..\).*$/\1:\2:\3:\4:\5:\6/')
echo $macaddr

But this method can result in MAC address that looks like this one: 07:d4:51:9f:50:6c . You simply can't use the address . If you tried, you would get this error:

# ip link set dev wlan0 address $macaddr
RTNETLINK answers: Cannot assign requested address

So the line above should be rewritten. And the question is how it should look like so the MAC address always was valid?

  1. extract the first byte (e.g. 07 from your example)
  2. bitwise AND it with decimal 254 (11111110 - all bits except zeroth bit set)
  3. bitwise OR it with decimal 2 (00000010 - only 1st bit set)
  4. combine the first byte back with the last five bytes


#! /bin/sh


lastfive=$( echo "$mac" | cut -d: -f 2-6 )
firstbyte=$( echo "$mac" | cut -d: -f 1 )

# make sure bit 0 (broadcast) of $firstbyte is not set,
# and bit 1 (local) is set.
# i.e. via bitwise AND with 254 and bitwise OR with 2.

firstbyte=$( printf '%02x' $(( 0x$firstbyte & 254 | 2)) )


echo "$mac"



07 hex is 00000111 binary. bitwise AND-ing it with 254 (11111110 binary) results in 00000110 binary (6 decimal). bitwise OR-ing it with 2 (00000010 binary) results in no change because bit 1 is already set. Final result is 06 hex.

  • I just tested and it looks like that it works just fine. Apr 29 '16 at 4:52
  • thanks for the edit. i didn't even notice that i missed the last byte.
    – cas
    Apr 29 '16 at 4:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.