rfc推荐的c语言中IPv6地址和inet_ntop的表示形式



阅读关于如何以最佳方式表示IPv6地址的RFC建议(RFC 5952),我尝试在c++中实现一个函数,将字节数组转换为适当的文本表示,即std::string

为了检查代码的正确性,我将结果与inet_ntop(#include <arpa/inet.h>)返回的结果进行比较。请注意,我实际上使用的是windows等效的#include <ws2tcpip.h>

在大多数情况下,我的函数具有相同的行为,并且我完全理解底层规则(省略前导零,通过将其替换为": "来压缩最长的零块,等等)。

但是有趣的部分是下面的:据我所知,对于一些特殊地址(IPv4映射、IPv4兼容和IPv4转换的IPv6地址,请参见RFC 2765),建议用IPv4地址常用的点分十进制表示最后4个字节的十六进制。

例如,::ffff:0:168.0.0.1,::ffff:168.0.0.1::168.0.0.1在其推荐的文本表示中都是有效的IPv6地址,inet_ntop也得出了这个结论。

现在是我的问题:根据inet_ntop, IPv6地址0:0:0:0:0:ffff:0.0.1.1被缩短为::ffff:0:101,再次选择十六进制表示。这种行为的原因是什么?我认为,因为我们在这里有一个特殊的地址前缀,无论最后4字节块的前两个字节是零,都将使用点分十进制表示法,因此将其写为::ffff:0.0.1.1。是我误解了RFC的建议,还是inet_ntop在这方面不一致?我观察到inet_ntop在我所有其他的测试用例中都非常符合rfc。

我希望你能帮助我。

编辑:经过更多的测试,inet_ntop似乎总是选择十六进制记数法而不是点分十进制,即使IPv6地址实际上只是一些特殊的嵌入式IPv4地址,如果最后4字节块的前两个字节为零。

在我的Ubuntu (glibc 2.31)上,我得到:

::ffff:0:168.0.0.1      -> ::ffff:0:a800:1      *
::ffff:168.0.0.1        -> ::ffff:168.0.0.1
::168.0.0.1             -> ::168.0.0.1
0:0:0:0:0:ffff:0.0.1.1  -> ::ffff:0.0.1.1       *

,其中两个标记的似乎与您的结果不同,表明此实现不识别::ffff:0前缀,但不太讨厌嵌入的0.0.1.1

然而,使用全零前缀,我得到了类似的结果:如果IPv4地址的前两个字节为零,输出格式改变:

::1.2.3.4           -> ::1.2.3.4
::0.2.3.4           -> ::0.2.3.4
::0.0.3.4           -> ::304
::0.0.0.4           -> ::4

这可能是因为::1不应该变成::0.0.0.1,但这意味着必须为混合表法中显示的IPv4地址画一条线,至少要用全零前缀。

那么,这可能只是你的库的一个错误或怪癖吗?如果它确实对全零前缀和其他前缀表现出类似的行为,也许他们只是决定采取简单的方式,平等对待所有前缀。据我所知,整个0/8块仍然保留给"本地识别",所以我想知道0.0.x.x这样的地址是否会嵌入到IPv6中。(虽然我不知道)

RFC还将混合表示法仅指定为"recommended &",因此我们不能真的说您的实现是错误的。

相关内容

  • 没有找到相关文章

最新更新