来自Beej's Guide to Network programming
您可以强制它在ai_family字段中使用IPv4或IPv6,或将其保留为AF_UNSPEC以使用任何内容。这很酷,因为您的代码可以与IP版本无关。
正如标题所说 - 总是使用AF_UNSPEC
而不是指定IPv4或IPv6会有什么缺点(或风险,如果有的话)?
或者只是出于一个原因 - 如果指定了版本,这将保证只支持此版本吗?
一点背景 - 我考虑在客户端 - 服务器(C ++)应用程序中添加对IPv6的支持,并且应该支持这两个版本。所以我想知道使用AF_UNSPEC
是否合适,或者最好“识别”字符串中的地址并使用AF_INET6
或AF_INET
,具体取决于地址。
答案 0 :(得分:3)
应该是这样的:
应用程序应该是第3层不可知的。应该通过名称连接到另一个系统。该名称应解析为一个或多个地址,应用程序应连接到它们,而不查看正在使用的实际协议。这样,网络配置是网络和系统管理员的责任。如果在网络中引入了IPv6,那么应用程序将继续工作,甚至不会注意到差异。
一些现实问题:
有时IPv6配置错误,防火墙不知道如何处理IPv6,IPv6只在本地网络中使用而没有连接到互联网等。这应该不是问题,但有时你会遇到糟糕的实施或配置。为了解决这个问题,IETF正在制定一个名为happy-eyeballs的草案。它确保用户不会注意到这些问题。看看那个草案。使用该草案中指定的技术将确保您的应用程序适用于所有用户。
答案 1 :(得分:3)
您必须区分客户端和服务器应用程序。
在客户端上,这很简单:只需拨打getaddrinfo()
并按顺序尝试每个答案,直到获得连接为止。
在服务器上,事情有点困难:
即使在服务器上,也可以使用getaddrinfo()
。在那里你使用提示中的标志AI_PASSIVE
。然后你得到结果。在这些所有你必须听,也许启用IPV6_V6ONLY
标志。
accept()
应该是非阻止的,或者是select()
或poll()
(不确定后者是否可行)。
答案 2 :(得分:-1)
使用AF_UNSPEC的一个风险是您将客户端暴露给来自恶意DNS服务器的较大响应,恶意DNS服务器可能正在尝试使用CVE-2015-7547导致堆栈缓冲区溢出,并导致恶意代码被执行客户端。事实上,getaddrinfo中已知缺陷的一个建议解决方法是防止在错误报告中使用AF_UNSPEC作为详细的here。 DNS响应大于2K的溢出缺陷会影响glibc从2.9,并在2.23中修复。这会影响大多数当前安装的Linux发行版。