【发布时间】:2015-12-30 04:58:51
【问题描述】:
我想使用规范化的 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 转换使其安全。真是浪费不过时间!)
【问题讨论】:
-
我不是在寻找 C++ 解决方案。只有一个 C 函数进行该转换,因此我的标记。现在只有对 C++ 感兴趣的人才会给我愚蠢的答案。也不好。
-
@ChronoKitsune,请注意,我明确表示我想将其用作数据库中的唯一键,而不是允许通过套接字进行事务的方式。话虽如此,了解 IPv6 的“缺点”是件好事。不过,据我了解,如果您正确设置了 IPv6 防火墙,则应该没问题。您只需要记住在执行该工作时阻止所有 IPv4(或大多数)。
-
由于 IPv4 映射地址 (
::ffff:0:0/96) 在 Internet 上不可路由,我不会花很多精力来阻止它们从 Internet 访问,当然也不会尝试使用他们上网。 -
在我看来,根据您的 cmets,您不会尝试使用这些地址发送数据,仅作为索引,您应该将 96 位
0附加到前面IPv4 地址,从而创建一个已弃用的与 IPv4 兼容的 IPv6 地址。这应该足够简单,无需查找库函数。生成的 IPv6 地址实际上不能用于任何东西,从数据库中读取它的任何东西都可以假定以 96 位0开头的地址是 IPv4 地址。
标签: network-programming posix ipv6 ipv4 sockaddr-in