Search code examples
c++clinuxipv6ipv4

How to convert IPv4-mapped-IPv6 address to IPv4 (string format)?


I have a struct sockaddr structure containing an IPv4-mapped-IPv6 address like ::ffff:10.0.0.1. I want to obtain only the IPv4 version of it in a string (in this case, 10.0.0.1) in C programming language. How do I go about achieving it?


Solution

  • As your structure contains an IPV6 address, I'll assume your have a struct sockaddr * pointer (let's name it addrPtr) pointing to a struct sockaddr_in6 structure.

    You can get the address bytes easily.

    const uint8_t *bytes = ((const struct sockaddr_in6 *)addrPtr)->sin6_addr.s6_addr;
    

    Then add 12 to the pointer because the 12 first bytes are not interesting (10 0x00, then 2 0xff). Only the 4 last ones mater.

    bytes += 12;
    

    Now, we can use those four bytes to do whatever we want. For example, we might store them into a IPv4 struct in_addr address.

    struct in_addr addr = { *(const in_addr_t *)bytes };
    

    Then we can get a string using inet_ntop (declared in <arpa/inet.h>).

    char buffer[16]; // 16 characters at max: "xxx.xxx.xxx.xxx" + NULL terminator
    const char *string = inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));