'How does one calculate ones link-local ipv6 address?

So there are several sites that will calculate your link-local ipv6 address for you, like this one right here.

Nevertheless, it does not give any useful into as to how this address is calculated nor what the input parameters are. So what is the procedure(or algorithm)to compute a link local ipv6 address if one knows ones ipv4 address, subnet mask, and gateway address? I'm doing a project with SCTP sockets that uses ISATAP network tunneling and the LL ipv6 address is used in constructing the ISATAP address.



Solution 1:[1]

Appendix A of RFC 4291 describes the method for computing a modified EUI-64 from a MAC address. Once you have the modified EUI-64, you just put it in the lower 64 bits of the address and put fe80:: in the top 64 bits.

Basically you flip the 7th bit of the MAC address, and pack its first 24 bits (including the flipped bit), then fffe, then the lower 24 bits of the MAC address, resulting in 64 bits total.

That being said, your question is how to derive the link local address from the IPv4 address and subnet mask. That, you can't do. The IPv4 address and subnet mask (if indeed there is one – IPv6 does not require that IPv4 be running at all on the same interface) has nothing to do with the IPv6 address and the two aren't related in any way. The IPv4 gateway address (again, if there is one) is even less relevant.

Solution 2:[2]

The link-local address can be based on the MAC address per RFC 4862 or randomly generated as per RFC 4941.

Normally this should be limited to global scope, but some systems extend this privacy extension implementation to link-local scope. Follow this question on serverfault for discussion of the topic.

Solution 3:[3]

The previous answers failed to note that there is a defined procedure for generating a link local IPv6 address from an IPv4 address when using ISATAP, and there is a different process for generating a link local IPv6 address from a MAC address. The two things are unrelated.

For ISATAP, the 32-bit IPv4 address is prepended wit the 96 bits of either fe80::200:5efe or fe80::200:5efe to get the 128-bit IPv6 link-local address.

For MAC to IPv6, the 48-bit MAC address is split in half, 16 bits are inserted in the middle, those bits being ff:fe, then it is prepended by the 64-bit link-local prefix fe80::, and finally the 7th bit in the 5th IPv6 segment is flipped, to get the 128-bit IPv6 link-local address.

The following code provides examples showing how to use the The IPAddress library to do the conversions in either Java or Go. Disclaimer: I am the project manager of those libraries.

These examples also help to visualize the conversions described above.

Go:

func convertToIsatap(ipv4Str string, isGlobal bool) string {
    ipv4Address := ipaddr.NewIPAddressString(ipv4Str).GetAddress().ToIPv4()
    zero := &ipaddr.IPv6AddressSegment{}
    segments := make([]*ipaddr.IPv6AddressSegment, ipaddr.IPv6SegmentCount)
    segments[1], segments[2], segments[3], segments[4] = zero, zero, zero, zero
    segments[0] = ipaddr.NewIPv6Segment(0xfe80)
    segments[5] = ipaddr.NewIPv6Segment(0x5efe)
    if isGlobal {
        segments[4] = ipaddr.NewIPv6Segment(0x200)
    }
    ipv6Address, _ := ipv4Address.GetIPv6Address(ipaddr.NewIPv6Section(segments))
    return ipv6Address.String()
}

func convertToLinkLocalIPv6(macAddr string) string {
    macAddress := ipaddr.NewMACAddressString(macAddr).GetAddress()
    ipv6LinkLocal, _ := macAddress.ToLinkLocalIPv6()
    return ipv6LinkLocal.String()
}

fmt.Println("1.2.3.4 becomes ISATAP " + 
    convertToIsatap("1.2.3.4", true))
fmt.Println("aa:bb:cc:11:22:33 becomes " + 
    convertToLinkLocalIPv6("aa:bb:cc:11:22:33"))

Java:

static String convertToIsatap(String ipv4Str, boolean isGlobal) {
    IPv4Address ipv4Address = new IPAddressString(ipv4Str).getAddress().toIPv4();
    IPv6AddressSegment zeroSeg = new IPv6AddressSegment(0);
    IPv6AddressSegment segments[] = 
        new IPv6AddressSegment[IPv6Address.SEGMENT_COUNT - 2];
    segments[1] = segments[2] = segments[3] = segments[4] = zeroSeg;
    segments[0] = new IPv6AddressSegment(0xfe80);
    segments[5] = new IPv6AddressSegment(0x5efe);
    if(isGlobal) {
        segments[4] = new IPv6AddressSegment(0x200);
    }
    return ipv4Address.getIPv6Address(
        new IPv6AddressSection(segments)).toString();
}

static String convertToLinkLocalIPv6(String  macStr) {
    MACAddress macAddress = new MACAddressString(macStr).getAddress();
    return macAddress.toLinkLocalIPv6().toString();
}

System.out.println("1.2.3.4 becomes ISATAP " +
    convertToIsatap("1.2.3.4", true));
System.out.println("aa:bb:cc:11:22:33 becomes " +
    convertToLinkLocalIPv6("aa:bb:cc:11:22:33"));

The output is the same for both examples:

1.2.3.4 becomes ISATAP fe80::200:5efe:102:304
aa:bb:cc:11:22:33 becomes fe80::a8bb:ccff:fe11:2233

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community
Solution 2 Community
Solution 3