Convert from MAC to IPv6
3 answers
Conversion step by step from MAC address (48 bit) to IPv6 address (128 bit):
- take MAC address: 52: 74: f2: b1: a8: 7f
- throw ff: fe in the middle: 52: 74: f2: ff: fe: b1: a8: 7f
- reformat to IPv6 notation 5274: f2ff: feb1: a87f
- convert first octet from hexadecimal to binary: 52 -> 01010010
- invert bit to index 6 (counting from 0): 01010010 → 01010000
- convert octet back to hex: 01010000 → 50
- replace the first octet with the newly computed one: 5074: f2ff: feb1: a87f
- add local link prefix: fe80 :: 5074: f2ff: feb1: a87f
+16
source to share
I got it working in C. Suggestions are welcome.
#include <stdio.h>
#include <string.h>
int toogle_kth_bit(unsigned int n, int k) {
return (n ^ (1 << (k-1)));
}
/*
- take the mac address: 52:74:f2:b1:a8:7f
- throw ff:fe in the middle: 52:74:f2:ff:fe:b1:a8:7f
- reformat to IPv6 notation 5274:f2ff:feb1:a87f
- convert the first octet from hexadecimal to binary: 52 -> 01010010
- invert the bit at index 6 (counting from 0): 01010010 -> 01010000
- convert octet back to hexadecimal: 01010000 -> 50
- replace first octet with newly calculated one: 5074:f2ff:feb1:a87f
- prepend the link-local prefix: fe80::5074:f2ff:feb1:a87f
*/
void mac_to_ipv6_link_local(char* mac) {
char mac_c[128];
char mac_c_exp[128];
char ipv6[128];
char ipv6_link_local[128];
char delim[] = ":";
int count = 0;
// throw ff:fe in the middle
snprintf(mac_c, sizeof(mac_c), "%s", mac);
char *ptr = strtok(mac_c, delim);
while (ptr != NULL) {
count++;
if (count > 1) {
snprintf(mac_c_exp, sizeof(mac_c_exp), "%s:%s", mac_c_exp, ptr);
} else {
snprintf(mac_c_exp, sizeof(mac_c_exp), "%s%s", mac_c_exp, ptr);
}
if (count == 3) {
snprintf(mac_c_exp, sizeof(mac_c_exp), "%s:%s", mac_c_exp, "ff:fe");
}
ptr = strtok(NULL, delim);
}
// reformat to IPv6 notation
ptr = strtok(mac_c_exp, delim);
count = 0;
while (ptr != NULL) {
count++;
if (count % 2 != 0 && count > 1) {
snprintf(ipv6, sizeof(ipv6), "%s:%s", ipv6, ptr);
} else {
snprintf(ipv6, sizeof(ipv6), "%s%s", ipv6, ptr);
}
ptr = strtok(NULL, delim);
}
// convert the first octet from hexadecimal to binary
char hex[2] = {ipv6[0], ipv6[1]};
char inverted_hex[3];
unsigned int number = (unsigned int)strtol(hex, NULL, 16);
// invert the bit at index 6 (counting from 0)
unsigned int new_num = toogle_kth_bit(number, 2);
sprintf(inverted_hex, "%x", new_num);
// replace first octet with newly calculated one
ipv6[0] = inverted_hex[0];
ipv6[1] = inverted_hex[1];
// prepend the link-local prefix
sprintf(ipv6_link_local, "%s%s", "fe80::", ipv6);
printf("%s\n", ipv6_link_local);
}
int main() {
mac_to_ipv6_link_local("52:74:f2:b1:a8:7f");
return 0;
}
0
source to share