We know that we can use the MAC address to create an interface identifier, e.g. for a link-local IPv6 address which should be unique in the Network.

The image shows the way to do this:

Create interface identifier from MAC address

My questions are:

  • How can I create an IPv6 address from a MAC using awk or sed?
  • OR is there any command that gives me the link-local IPv6 address for a specific MAC (something like that createIPv6 myMAC)?
  • I rephrased your question a bit (pending review). IPv6 addresses are not extracted from MAC addresses, but created. And here you deal only with the interface identifier part (the last 64 bit) of an IPv6 address. But I'm not sure: Do you only want the interface identifier or a whole IPv6 address? Please re-edit, if I did not understand you correctly.
    – Dubu
    Jun 12, 2014 at 7:34
  • @Dubu, Thanks for editing, I want the whole IPv6 address.
    – Nidal
    Jun 12, 2014 at 11:13

5 Answers 5


If you want to create a whole IPv6 address from a MAC (and a given prefix), you could use the excellent ipv6calc tool by Peter Bieringer.

The following command creates a link-local IPv6 address (fe80:: prefix) from a MAC address:

$ ipv6calc --action prefixmac2ipv6 --in prefix+mac --out ipv6addr fe80:: 00:21:5b:f7:25:1b

You can leave most of the options away and let the command guess what to do:

$ ipv6calc --in prefix+mac fe80:: 00:21:5b:f7:25:1b
No action type specified, try autodetection...found type: prefixmac2ipv6

For Debian distros, ipv6calc is in the main repository.


From the IPv6 Wikipedia entry a more textual description:

A 64-bit interface identifier is most commonly derived from its 48-bit MAC address.

A MAC address 00:0C:29:0C:47:D5 is turned into a 64-bit EUI-64 by inserting FF:FE in the middle: 00:0C:29:FF:FE:0C:47:D5.

So replacing the third : with :FF:FE: should do the trick:

echo  00:0C:29:0C:47:D5 | sed s/:/:FF:FE:/3

No idea if that syntax is specific to GNU sed.

Work in progress:

Convert that to bits:

for HEX in $(tr ":" " " <<< 00:0C:29:FF:FE:0C:47:D5) 
    printf "%08d " $(bc <<< "ibase=16;obase=2;$HEX") 

should result in the bits 00000000 00001100 00101001 11111111 11111110 00001100 01000111 11010101 leaving only the flipping of bit number 7.

  • 1
    what about reverse the 7-th bit !
    – Nidal
    Jun 11, 2014 at 22:52
  • Ah the U/L bit, good point!
    – HBruijn
    Jun 11, 2014 at 23:04
#! /usr/bin/env python
import sys
n=[int(x, 16) for x in sys.argv[1].split(":")]
print "fe80::%02x%02x:%02xff:fe%02x:%02x%02x" % tuple([n[0]^2]+n[1:])

You can create a bash function (and place it in your ~/.bashrc) that uses IFS to split the MAC address into 6 colon-separated groups and assembles them. You'll also need to flip the 7th most significant bit, i.e. bit 1 of the first byte:

mac_to_ipv6_ll() {
    IFS=':'; set $1; unset IFS
    echo "fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6"

Usage example:

$ mac_to_ipv6_ll 12:34:56:78:90:12

I must give kudos to @rubo77 above for a pure-shell (unless you count printf) answer above, which I was seeking.

This adds a bit of sed to:

(a) elide any leading zeroes in each 16-bit chunk; and

(b) elide any further all-zero chunks at the start of the IID

...as per common conventions for address brevity.

mac_to_eui64() {
 IFS=':'; set $1; unset IFS
 echo "fe80::$(printf %x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6" |
  sed -E 's/:0+/:/g; s/:{3,}/::/; s/:$/:0/'

Note that if you wished to repurpose this for other (arbitrary) prefixes, which you might since EUI-64 can be used in any scope (although it's advised not to use it for global addresses for privacy reasons), you'd need a slightly more convoluted sed script. That's because the fe80:: prefix already contains three zero-chunks (elided to the double-colon) adjacent to the start of the IID. Thus even if the IID's first chunk is all-zeroes (that is, if the MAC started with 02:00), it would be elided too. The EUI-64 format only leaves one further chunk that could be all-zero -- the last one -- which the script above adds back in as a single zero. Other prefixes might require one to leave a single zero between two colons.

  • You're right, thanks - I went back and left @rubo77's fine printf alone and did the additional stuff in sed instead.
    – Headbank
    Dec 15, 2019 at 1:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .