network-programmingposixipv6ipv4sockaddr-in

Are there C functions to convert a sockaddr_in to a sockaddr_in6 structure?


I want to save data in a database using a canonicalized IP address.

The software, at this point, may get IPv4 or IPv6 addresses. I want to canonicalize by converting all addresses to an IPv6 address.

I know of inet_pton() to convert the string to a binary address. So I can try once with IPv6 and if that fails, try again with IPv4:

struct sockaddr_in6 sa;
int r = inet_pton(AF_INET6, input_addr, &sa.sin6_addr);
if(r != 1)
{
    // try again with IPv4
    struct sockaddr_in sa4;
    int r = inet_pton(AF_INET, input_addr, &sa4.sin_addr);

    // is there such a function?!
    inet_convert_ipv4_to_ipv6(&sa4, &sa);
}
char output_addr[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &sa, output_addr, sizeof(output_addr));

// in C++, I can do that if function returns std::string
// in C you cannot return a pointer on the stack, watch out!
return output_addr;

So, I am looking for a function such as inet_convert_ipv4_to_ipv6(&sa4, &sa); to convert the sockaddr_in to a sockaddr_in6. Do we have such in the C library?

If we do not have such a function, would a solution be to use the '::ffff:' introducer as in:

// try again with IPv4
std::string ipv4_to_ipv6("::ffff:");
ipv4_to_ipv6 += input_addr;
int r = inet_pton(AF_INET6, ipv4_to_ipv6.c_str(), &sa.sin_addr);

I would hope that we have a way to convert an IPv4 sockaddr_in to an IPv6 sockaddr_in6 function instead. I think it would be cleaner... I think that this last piece of code is not 100% secure (I guess I can test the IPv4 conversion first and if it succeeds, then use the IPv6 conversion to make it secure. What a waste of time though!)


Solution

  • You could keep using sockaddr_in6 in both calls to inet_pton. When you convert the IPv4 successfully, you could do a shift to the correct place. Here is a example of that in map4to6() method.

    EDIT: To fix the wrong method name mentioned.