是否有 C 函数可以将 sockaddr_in 转换为 sockaddr_in6 结构?

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

我想使用规范化的 IP 地址将数据保存在数据库中。

此时,软件可能会获得 IPv4 或 IPv6 地址。我想通过将所有地址转换为 IPv6 地址来规范化。

我知道 inet_pton() 可以将字符串转换为二进制地址。所以我可以使用 IPv6 尝试一次,如果失败,请使用 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;

所以,我正在寻找 inet_convert_ipv4_to_ipv6(&sa4, &sa); 之类的函数来将 sockaddr_in 转换为 sockaddr_in6。我们在 C 库中有这样的东西吗?

如果我们没有这样的功能,解决方案是使用 '::ffff:' 引入器,如:

// 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);

我希望我们有办法将 IPv4 sockaddr_in 转换为 IPv6 sockaddr_in6 函数。我认为它会更干净......我认为这最后一段代码不是 100% 安全的(我想我可以先测试 IPv4 转换,如果成功,然后使用 IPv6 转换来确保它安全。多么浪费不过时间!)

您可以在对 inet_pton 的两次调用中继续使用 sockaddr_in6。成功转换 IPv4 后,您可以转移到正确的位置。 Here 是 map4to6() 方法中的一个示例。

编辑:修复提到的错误方法名称。

unsigned char *ip = in6_addr.s6_addr;
((uint64*)ip)[0] = 0;
((uint16*)ip)[4] = 0;
ip[10] = 0xFF;
ip[11] = 0xFF;
((in_addr_t*)(ip + 12))[0] = in_addr.s_addr