Convert from MAC to IPv6

亡梦爱人 提交于 2020-01-13 03:38:16

问题


I would like to understand how to convert a MAC adress to IPv6. For example: 00:01:04:76:2A:5C Should become FE80::0201:04FF:FE76:2A5C

Could someone elaborate the conversion please ? We suppose an automatic configuration without random parameter for a local machin.


回答1:


Conversion step by step from a MAC address (48 bits) to a IPv6 address (128 bits):

  1. take the mac address: 52:74:f2:b1:a8:7f
  2. throw ff:fe in the middle: 52:74:f2:ff:fe:b1:a8:7f
  3. reformat to IPv6 notation 5274:f2ff:feb1:a87f
  4. convert the first octet from hexadecimal to binary: 52 -> 01010010
  5. invert the bit at index 6 (counting from 0): 01010010 -> 01010000
  6. convert octet back to hexadecimal: 01010000 -> 50
  7. replace first octet with newly calculated one: 5074:f2ff:feb1:a87f
  8. prepend the link-local prefix: fe80::5074:f2ff:feb1:a87f



回答2:


Bash/zsh function (now working without bc):

format_eui_64() {
    local macaddr="$1"
    printf "%02x%s" $(( 16#${macaddr:0:2} ^ 2#00000010 )) "${macaddr:2}" \
        | sed -E -e 's/([0-9a-zA-Z]{2})*/0x\0|/g' \
        | tr -d ':\n' \
        | xargs -d '|' \
        printf "%02x%02x:%02xff:fe%02x:%02x%02x"
}



回答3:


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;
}


来源:https://stackoverflow.com/questions/27693120/convert-from-mac-to-ipv6

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!