Network Working Group M-K. Shin, Ed. Request for Comments: 4038 ETRI/NIST Category: Informational Y-G. Hong ETRI J. Hagino IIJ P. Savola CSC/FUNET E. M. Castro GSYC/URJC March 2005
Network Working Group M-K. Shin, Ed. Request for Comments: 4038 ETRI/NIST Category: Informational Y-G. Hong ETRI J. Hagino IIJ P. Savola CSC/FUNET E. M. Castro GSYC/URJC March 2005
Application Aspects of IPv6 Transition
IPv6过渡的应用方面
Status of This Memo
关于下段备忘
This memo provides information for the Internet community. It does not specify an Internet standard of any kind. Distribution of this memo is unlimited.
本备忘录为互联网社区提供信息。它没有规定任何类型的互联网标准。本备忘录的分发不受限制。
Copyright Notice
版权公告
Copyright (C) The Internet Society (2005).
版权所有(C)互联网协会(2005年)。
Abstract
摘要
As IPv6 networks are deployed and the network transition is discussed, one should also consider how to enable IPv6 support in applications running on IPv6 hosts, and the best strategy to develop IP protocol support in applications. This document specifies scenarios and aspects of application transition. It also proposes guidelines on how to develop IP version-independent applications during the transition period.
在部署IPv6网络和讨论网络过渡的同时,还应该考虑如何在IPv6主机上运行的应用程序中启用IPv6支持,以及在应用程序中开发IP协议支持的最佳策略。本文档指定了应用程序转换的场景和方面。它还就如何在过渡期间开发与IP版本无关的应用程序提出了指导方针。
Table of Contents
目录
1. Introduction ................................................. 3 2. Overview of IPv6 Application Transition ...................... 3 3. Problems with IPv6 Application Transition .................... 5 3.1. IPv6 Support in the OS and Applications Are Unrelated... 5 3.2. DNS Does Not Indicate Which IP Version Will Be Used .... 6 3.3. Supporting Many Versions of an Application Is Difficult. 6 4. Description of Transition Scenarios and Guidelines ........... 7 4.1. IPv4 Applications in a Dual-Stack Node ................. 7 4.2. IPv6 Applications in a Dual-Stack Node ................. 8 4.3. IPv4/IPv6 Applications in a Dual-Stack Node ............ 11 4.4. IPv4/IPv6 Applications in an IPv4-only Node ............ 12 5. Application Porting Considerations ........................... 12 5.1. Presentation Format for an IP Address .................. 13 5.2. Transport Layer API .................................... 14 5.3. Name and Address Resolution ............................ 15 5.4. Specific IP Dependencies ............................... 16 5.4.1. IP Address Selection ........................... 16 5.4.2. Application Framing ............................ 16 5.4.3. Storage of IP addresses ........................ 17 5.5. Multicast Applications ................................. 17 6. Developing IP Version - Independent Applications ............. 18 6.1. IP Version - Independent Structures..................... 18 6.2. IP Version - Independent APIs........................... 19 6.2.1. Example of Overly Simplistic TCP Server Application .................................... 20 6.2.2. Example of Overly Simplistic TCP Client Application .................................... 21 6.2.3. Binary/Presentation Format Conversion .......... 22 6.3. Iterated Jobs for Finding the Working Address .......... 23 6.3.1. Example of TCP Server Application .............. 23 6.3.2. Example of TCP Client Application .............. 25 7. Transition Mechanism Considerations .......................... 26 8. Security Considerations ...................................... 26 9. Acknowledgments .............................................. 27 10. References ................................................... 27 Appendix A. Other Binary/Presentation Format Conversions ........ 30 A.1. Binary to Presentation Using inet_ntop() ............... 30 A.2. Presentation to Binary Using inet_pton() ............... 31 Authors' Addresses ............................................... 32 Full Copyright Statement ......................................... 33
1. Introduction ................................................. 3 2. Overview of IPv6 Application Transition ...................... 3 3. Problems with IPv6 Application Transition .................... 5 3.1. IPv6 Support in the OS and Applications Are Unrelated... 5 3.2. DNS Does Not Indicate Which IP Version Will Be Used .... 6 3.3. Supporting Many Versions of an Application Is Difficult. 6 4. Description of Transition Scenarios and Guidelines ........... 7 4.1. IPv4 Applications in a Dual-Stack Node ................. 7 4.2. IPv6 Applications in a Dual-Stack Node ................. 8 4.3. IPv4/IPv6 Applications in a Dual-Stack Node ............ 11 4.4. IPv4/IPv6 Applications in an IPv4-only Node ............ 12 5. Application Porting Considerations ........................... 12 5.1. Presentation Format for an IP Address .................. 13 5.2. Transport Layer API .................................... 14 5.3. Name and Address Resolution ............................ 15 5.4. Specific IP Dependencies ............................... 16 5.4.1. IP Address Selection ........................... 16 5.4.2. Application Framing ............................ 16 5.4.3. Storage of IP addresses ........................ 17 5.5. Multicast Applications ................................. 17 6. Developing IP Version - Independent Applications ............. 18 6.1. IP Version - Independent Structures..................... 18 6.2. IP Version - Independent APIs........................... 19 6.2.1. Example of Overly Simplistic TCP Server Application .................................... 20 6.2.2. Example of Overly Simplistic TCP Client Application .................................... 21 6.2.3. Binary/Presentation Format Conversion .......... 22 6.3. Iterated Jobs for Finding the Working Address .......... 23 6.3.1. Example of TCP Server Application .............. 23 6.3.2. Example of TCP Client Application .............. 25 7. Transition Mechanism Considerations .......................... 26 8. Security Considerations ...................................... 26 9. Acknowledgments .............................................. 27 10. References ................................................... 27 Appendix A. Other Binary/Presentation Format Conversions ........ 30 A.1. Binary to Presentation Using inet_ntop() ............... 30 A.2. Presentation to Binary Using inet_pton() ............... 31 Authors' Addresses ............................................... 32 Full Copyright Statement ......................................... 33
As IPv6 is introduced in the IPv4-based Internet, several general issues will arise, such as routing, addressing, DNS, and scenarios.
随着IPv6在基于IPv4的Internet中的引入,会出现一些一般性问题,例如路由、寻址、DNS和场景。
An important key to a successful IPv6 transition is compatibility with the large installed base of IPv4 hosts and routers. This issue has already been extensively studied, and work is still in progress. [2893BIS] describes the basic transition mechanisms: dual-stack deployment and tunneling. Various other kinds of mechanisms have been developed for the transition to an IPv6 network. However, these transition mechanisms take no stance on whether applications support IPv6.
成功过渡IPv6的一个重要关键是与大量IPv4主机和路由器的兼容性。这一问题已经得到广泛研究,工作仍在进行中。[2893BIS]描述了基本的转换机制:双堆栈部署和隧道。为过渡到IPv6网络,已经开发了各种其他类型的机制。然而,这些转换机制对于应用程序是否支持IPv6没有任何立场。
This document specifies application aspects of IPv6 transition. Two inter-related topics are covered:
本文档指定了IPv6转换的应用程序方面。涵盖两个相互关联的主题:
1. How different network transition techniques affect applications, and strategies for applications to support IPv6 and IPv4.
1. 不同的网络转换技术如何影响应用程序,以及应用程序支持IPv6和IPv4的策略。
2. How to develop IPv6-capable or protocol-independent applications ("application porting guidelines") using standard APIs [RFC3493][RFC3542].
2. 如何使用标准API[RFC3493][RFC3542]开发支持IPv6或独立于协议的应用程序(“应用程序移植指南”)。
In the context of this document, the term "application" covers all kinds of applications, but the focus is on those network applications which have been developed using relatively low-level APIs (such as the "C" language, using standard libraries). Many such applications could be command-line driven, but that is not a requirement.
在本文档的上下文中,“应用程序”一词涵盖了所有类型的应用程序,但重点是那些使用相对低级的API(例如使用标准库的“C”语言)开发的网络应用程序。许多这样的应用程序可以是命令行驱动的,但这不是一个要求。
Applications will have to be modified to support IPv6 (and IPv4) by using one of a number of techniques described in sections 2 - 4. Guidelines for developing such applications are presented in sections 5 and 6.
必须使用第2-4节中描述的多种技术之一修改应用程序以支持IPv6(和IPv4)。第5节和第6节介绍了开发此类应用程序的指南。
The transition of an application can be classified by using four different cases (excluding the first case when there is no IPv6 support in either the application or the operating system):
应用程序的转换可以使用四种不同的情况进行分类(不包括应用程序或操作系统中不支持IPv6的第一种情况):
+-------------------+ | appv4 | (appv4 - IPv4-only applications) +-------------------+ | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
+-------------------+ | appv4 | (appv4 - IPv4-only applications) +-------------------+ | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
Case 1. IPv4 applications in a dual-stack node.
案例1。双堆栈节点中的IPv4应用程序。
+-------------------+ (appv4 - IPv4-only applications) | appv4 | appv6 | (appv6 - IPv6-only applications) +-------------------+ | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
+-------------------+ (appv4 - IPv4-only applications) | appv4 | appv6 | (appv6 - IPv6-only applications) +-------------------+ | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
Case 2. IPv4-only applications and IPv6-only applications in a dual-stack node.
案例2。双堆栈节点中的仅IPv4应用程序和仅IPv6应用程序。
+-------------------+ | appv4/v6 | (appv4/v6 - applications supporting +-------------------+ both IPv4 and IPv6) | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
+-------------------+ | appv4/v6 | (appv4/v6 - applications supporting +-------------------+ both IPv4 and IPv6) | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | IPv6 | (IP protocols supported/enabled in the OS) +-------------------+
Case 3. Applications supporting both IPv4 and IPv6 in a dual-stack node.
案例3。在双堆栈节点中同时支持IPv4和IPv6的应用程序。
+-------------------+ | appv4/v6 | (appv4/v6 - applications supporting +-------------------+ both IPv4 and IPv6) | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | (IP protocols supported/enabled in the OS) +-------------------+
+-------------------+ | appv4/v6 | (appv4/v6 - applications supporting +-------------------+ both IPv4 and IPv6) | TCP / UDP / others| (transport protocols - TCP, UDP, +-------------------+ SCTP, DCCP, etc.) | IPv4 | (IP protocols supported/enabled in the OS) +-------------------+
Case 4. Applications supporting both IPv4 and IPv6 in an IPv4-only node.
案例4。仅在IPv4节点中同时支持IPv4和IPv6的应用程序。
Figure 1. Overview of Application Transition
图1。应用程序转换概述
Figure 1 shows the cases of application transition.
图1显示了应用程序转换的情况。
Case 1: IPv4-only applications in a dual-stack node. IPv6 protocol is introduced in a node, but applications are not yet ported to support IPv6.
案例1:双堆栈节点中仅IPv4应用程序。IPv6协议是在节点中引入的,但应用程序尚未移植以支持IPv6。
Case 2: IPv4-only applications and IPv6-only applications in a dual-stack node. Applications are ported for IPv6-only. Therefore there are two similar applications, one for each protocol version (e.g., ping and ping6).
案例2:双堆栈节点中的仅IPv4应用程序和仅IPv6应用程序。应用程序仅针对IPv6进行移植。因此,有两个类似的应用程序,每个协议版本一个(例如,ping和ping6)。
Case 3: Applications supporting both IPv4 and IPv6 in a dual stack node. Applications are ported for both IPv4 and IPv6 support. Therefore, the existing IPv4 applications can be removed.
案例3:在双堆栈节点中同时支持IPv4和IPv6的应用程序。对应用程序进行了移植,以支持IPv4和IPv6。因此,可以删除现有的IPv4应用程序。
Case 4: Applications supporting both IPv4 and IPv6 in an IPv4-only node. Applications are ported for both IPv4 and IPv6 support, but the same applications may also have to work when IPv6 is not being used (e.g., disabled from the OS).
案例4:仅IPv4节点中同时支持IPv4和IPv6的应用程序。为支持IPv4和IPv6而对应用程序进行了移植,但在未使用IPv6时(例如,从操作系统禁用),也可能需要使用相同的应用程序。
The first two cases are not interesting in the longer term; only few applications are inherently IPv4- or IPv6-specific, and should work with both protocols without having to care about which one is being used.
从长远来看,前两种情况并不令人感兴趣;只有少数应用程序本质上特定于IPv4或IPv6,并且应该使用这两种协议,而不必关心使用哪一种协议。
There are several reasons why the transition period between IPv4 and IPv6 applications may not be straightforward. These issues are described in this section.
IPv4和IPv6应用程序之间的过渡期可能并不简单,原因有几个。本节将介绍这些问题。
Considering the cases described in the previous section, IPv4 and IPv6 protocol stacks are likely to co-exist in a node for a long time.
考虑到上一节中描述的情况,IPv4和IPv6协议栈可能在节点中长期共存。
Similarly, most applications are expected to be able to handle both IPv4 and IPv6 during another long period. A dual-stack operating system is not intended to have both IPv4 and IPv6 applications. Therefore, IPv6-capable application transition may be independent of protocol stacks in a node.
类似地,大多数应用程序预计将能够在另一个较长时期内同时处理IPv4和IPv6。双栈操作系统不打算同时具有IPv4和IPv6应用程序。因此,支持IPv6的应用程序转换可能独立于节点中的协议栈。
Applications capable of both IPv4 and IPv6 will probably have to work properly in IPv4-only nodes (whether the IPv6 protocol is completely disabled or there is no IPv6 connectivity at all).
能够同时使用IPv4和IPv6的应用程序可能必须在仅使用IPv4的节点中正常工作(无论IPv6协议是完全禁用还是根本没有IPv6连接)。
In a node, the DNS name resolver gathers the list of destination addresses. DNS queries and responses are sent by using either IPv4 or IPv6 to carry the queries, regardless of the protocol version of the data records [DNSTRANS].
在节点中,DNS名称解析程序收集目标地址列表。DNS查询和响应通过使用IPv4或IPv6承载查询来发送,而不管数据记录的协议版本如何[DNSTRANS]。
The DNS name resolution issue related to application transition is that by only doing a DNS name lookup a client application can not be certain of the version of the peer application. For example, if a server application does not support IPv6 yet but runs on a dual-stack machine for other IPv6 services, and this host is listed with an AAAA record in the DNS, the client application will fail to connect to the server application. This is caused by a mismatch between the DNS query result (i.e., IPv6 addresses) and a server application version (i.e., IPv4).
与应用程序转换相关的DNS名称解析问题是,仅通过进行DNS名称查找,客户端应用程序无法确定对等应用程序的版本。例如,如果服务器应用程序尚不支持IPv6,但在用于其他IPv6服务的双堆栈计算机上运行,并且此主机在DNS中列出了AAAA记录,则客户端应用程序将无法连接到服务器应用程序。这是由于DNS查询结果(即IPv6地址)与服务器应用程序版本(即IPv4)不匹配造成的。
Using SRV records would avoid these problems. Unfortunately, they are not used widely enough to be applicable in most cases. Hence an operational solution is to use "service names" in the DNS. If a node offers multiple services, but only some of them over IPv6, a DNS name may be added for each of these services or group of services (with the associated A/AAAA records), not just a single name for the physical machine, also including the AAAA records. However, the applications cannot depend on this operational practice.
使用SRV记录可以避免这些问题。不幸的是,它们的应用还不够广泛,无法在大多数情况下适用。因此,一个可操作的解决方案是在DNS中使用“服务名称”。如果一个节点提供多个服务,但只有其中一些服务是通过IPv6提供的,则可以为这些服务或服务组(带有关联的a/AAAA记录)中的每一个添加DNS名称,而不仅仅是物理机器的单个名称,还包括AAAA记录。但是,应用程序不能依赖于此操作实践。
The application should request all IP addresses without address family constraints and try all the records returned from the DNS, in some order, until a working address is found. In particular, the application has to be able to handle all IP versions returned from the DNS. This issue is discussed in more detail in [DNSOPV6].
应用程序应该请求没有地址族约束的所有IP地址,并按一定顺序尝试从DNS返回的所有记录,直到找到工作地址。特别是,应用程序必须能够处理从DNS返回的所有IP版本。[DNSOPV6]中详细讨论了此问题。
During the application transition period, system administrators may have various versions of the same application (an IPv4-only application, an IPv6-only application, or an application supporting both IPv4 and IPv6).
在应用程序转换期间,系统管理员可能拥有同一应用程序的各种版本(仅IPv4应用程序、仅IPv6应用程序或同时支持IPv4和IPv6的应用程序)。
Typically one cannot know which IP versions must be supported prior to doing a DNS lookup *and* trying (see section 3.2) the addresses returned. Therefore if multiple versions of the same application are available, the local users have difficulty selecting the right version supporting the exact IP version required.
通常,在进行DNS查找*和*尝试(参见第3.2节)返回的地址之前,无法知道必须支持哪些IP版本。因此,如果同一应用程序有多个版本可用,本地用户很难选择支持所需确切IP版本的正确版本。
To avoid problems with one application not supporting the specified protocol version, it is desirable to have hybrid applications supporting both.
为了避免一个应用程序不支持指定的协议版本的问题,最好让混合应用程序同时支持这两个版本。
An alternative approach for local client applications could be to have a "wrapper application" that performs certain tasks (such as figuring out which protocol version will be used) and calls the IPv4/IPv6-only applications as necessary. This application would perform connection establishment (or similar tasks) and pass the opened socket to another application. However, as applications such as this would have to do more than just perform a DNS lookup or determine the literal IP address given, they will become complex -- likely much more so than a hybrid application. Furthermore, writing "wrapping" applications that perform complex operations with IP addresses (such as FTP clients) might be even more challenging or even impossible. In short, wrapper applications do not look like a robust approach for application transition.
本地客户端应用程序的另一种方法是使用“包装器应用程序”执行某些任务(例如确定将使用哪个协议版本),并在必要时仅调用IPv4/IPv6应用程序。此应用程序将执行连接建立(或类似任务),并将打开的套接字传递给另一个应用程序。然而,由于像这样的应用程序需要做的不仅仅是执行DNS查找或确定给定的文字IP地址,它们将变得复杂——可能比混合应用程序复杂得多。此外,编写使用IP地址执行复杂操作的“包装”应用程序(如FTP客户端)可能更具挑战性,甚至是不可能的。简而言之,包装器应用程序看起来不像是应用程序转换的健壮方法。
Once the IPv6 network is deployed, applications supporting IPv6 can use IPv6 network services to establish IPv6 connections. However, upgrading every node to IPv6 at the same time is not feasible, and transition from IPv4 to IPv6 will be a gradual process.
部署IPv6网络后,支持IPv6的应用程序可以使用IPv6网络服务建立IPv6连接。但是,同时将每个节点升级到IPv6是不可行的,从IPv4到IPv6的过渡将是一个渐进的过程。
Dual-stack nodes provide one solution to maintaining IPv4 compatibility in unicast communications. In this section we will analyze different application transition scenarios (as introduced in section 2) and guidelines for maintaining interoperability between applications running in different types of nodes.
双栈节点为单播通信中保持IPv4兼容性提供了一种解决方案。在本节中,我们将分析不同的应用程序转换场景(如第2节中介绍的)以及维护在不同类型节点上运行的应用程序之间互操作性的指导原则。
Note that the first two cases, IPv4-only and IPv6-only applications, are not interesting in the longer term; only few applications are inherently IPv4- or IPv6-specific, and should work with both protocols without having to care about which one is being used.
请注意,前两种情况,即仅IPv4和仅IPv6应用程序,从长远来看并不令人感兴趣;只有少数应用程序本质上特定于IPv4或IPv6,并且应该使用这两种协议,而不必关心使用哪一种协议。
In this scenario, the IPv6 protocol is added in a node, but IPv6- capable applications aren't yet available or installed. Although the node implements the dual stack, IPv4 applications can only manage IPv4 communications and accept/establish connections from/to nodes that implement an IPv4 stack.
在这种情况下,IPv6协议添加到节点中,但支持IPv6的应用程序尚未可用或安装。尽管节点实现了双堆栈,但IPv4应用程序只能管理IPv4通信并接受/建立与实现IPv4堆栈的节点之间的连接。
To allow an application to communicate with other nodes using IPv6, the first priority is to port applications to IPv6.
要允许应用程序使用IPv6与其他节点通信,首要任务是将应用程序移植到IPv6。
In some cases (e.g., when no source code is available), existing IPv4 applications can work if the Bump-in-the-Stack [BIS] or Bump-in-the-API [BIA] mechanism is installed in the node. We strongly recommend that application developers not use these mechanisms when application source code is available. Also, they should not be used as an excuse not to port software or to delay porting.
在某些情况下(例如,当没有可用的源代码时),如果在节点中安装了堆栈中的Bump[BIS]或API中的Bump[BIA]机制,则现有IPv4应用程序可以工作。我们强烈建议应用程序开发人员在应用程序源代码可用时不要使用这些机制。此外,它们不应被用作不移植软件或延迟移植的借口。
When [BIA] or [BIS] is used, the problem described in section 3.2 arises - (the IPv4 client in a [BIS]/[BIA] node tries to connect to an IPv4 server in a dual stack system). However, one can rely on the [BIA]/[BIS] mechanism, which should cycle through all the addresses instead of applications.
使用[BIA]或[BIS]时,会出现第3.2节中描述的问题—[BIS]/[BIA]节点中的IPv4客户端尝试连接到双堆栈系统中的IPv4服务器。但是,可以依赖[BIA]/[BIS]机制,该机制应该循环遍历所有地址,而不是应用程序。
[BIS] and [BIA] do not work with all kinds of applications - in particular, with applications that exchange IP addresses as application data (e.g., FTP). These mechanisms provide IPv4 temporary addresses to the applications and locally make a translation between IPv4 and IPv6 communication. Therefore, these IPv4 temporary addresses are only valid in the node scope.
[BIS]和[BIA]不适用于所有类型的应用程序,尤其是将IP地址交换为应用程序数据的应用程序(例如FTP)。这些机制为应用程序提供IPv4临时地址,并在IPv4和IPv6通信之间进行本地转换。因此,这些IPv4临时地址仅在节点范围内有效。
As we have seen in the previous section, applications should be ported to IPv6. The easiest way to port an IPv4 application is to substitute the old IPv4 API references with the new IPv6 APIs with one-to-one mapping. This way the application will be IPv6-only. This IPv6-only source code cannot work in IPv4-only nodes, so the old IPv4 application should be maintained in these nodes. This necessitates having two similar applications working with different protocol versions, depending on the node they are running (e.g., telnet and telnet6). This case is undesirable, as maintaining two versions of the same source code per application could be difficult. This approach would also cause problems for users having to select which version of the application to use, as described in section 3.3.
正如我们在上一节中所看到的,应用程序应该移植到IPv6。移植IPv4应用程序的最简单方法是用具有一对一映射的新IPv6 API替换旧的IPv4 API引用。这样,应用程序将仅限于IPv6。此仅限IPv6的源代码无法在仅限IPv4的节点中工作,因此应在这些节点中维护旧的IPv4应用程序。这需要两个类似的应用程序使用不同的协议版本,具体取决于它们运行的节点(例如telnet和telnet6)。这种情况是不可取的,因为在每个应用程序中维护相同源代码的两个版本可能很困难。如第3.3节所述,这种方法也会给用户带来问题,用户必须选择要使用的应用程序版本。
Most implementations of dual stack allow IPv6-only applications to interoperate with both IPv4 and IPv6 nodes. IPv4 packets going to IPv6 applications on a dual-stack node reach their destination because their addresses are mapped by using IPv4-mapped IPv6 addresses: the IPv6 address ::FFFF:x.y.z.w represents the IPv4 address x.y.z.w.
大多数双栈实现允许仅限IPv6的应用程序与IPv4和IPv6节点进行互操作。前往双堆栈节点上IPv6应用程序的IPv4数据包到达其目标,因为它们的地址通过使用IPv4映射的IPv6地址进行映射:IPv6地址::FFFF:x.y.z.w表示IPv4地址x.y.z.w。
+----------------------------------------------+ | +------------------------------------------+ | | | | | | | IPv6-only applications | | | | | | | +------------------------------------------+ | | | | | +------------------------------------------+ | | | | | | | TCP / UDP / others (SCTP, DCCP, etc.) | | | | | | | +------------------------------------------+ | | IPv4-mapped | | IPv6 | | IPv6 addresses | | addresses | | +--------------------+ +-------------------+ | | | IPv4 | | IPv6 | | | +--------------------+ +-------------------+ | | IPv4 | | | | addresses | | | +--------------|-----------------|-------------+ | | IPv4 packets IPv6 packets
+----------------------------------------------+ | +------------------------------------------+ | | | | | | | IPv6-only applications | | | | | | | +------------------------------------------+ | | | | | +------------------------------------------+ | | | | | | | TCP / UDP / others (SCTP, DCCP, etc.) | | | | | | | +------------------------------------------+ | | IPv4-mapped | | IPv6 | | IPv6 addresses | | addresses | | +--------------------+ +-------------------+ | | | IPv4 | | IPv6 | | | +--------------------+ +-------------------+ | | IPv4 | | | | addresses | | | +--------------|-----------------|-------------+ | | IPv4 packets IPv6 packets
We will analyze the behaviour of IPv6-applications that exchange IPv4 packets with IPv4 applications by using the client/server model. We consider the default case to be when the IPV6_V6ONLY socket option has not been set. In these dual-stack nodes, this default behavior allows a limited amount of IPv4 communication using the IPv4-mapped IPv6 addresses.
我们将使用客户机/服务器模型分析与IPv4应用程序交换IPv4数据包的IPv6应用程序的行为。我们认为默认情况是当没有设置IPv6V6V6套接字选项时。在这些双堆栈节点中,此默认行为允许使用IPv4映射的IPv6地址进行有限数量的IPv4通信。
IPv6-only server: When an IPv4 client application sends data to an IPv6-only server application running on a dual-stack node by using the wildcard address, the IPv4 client address is interpreted as the IPv4-mapped IPv6 address in the dual-stack node. This allows the IPv6 application to manage the communication. The IPv6 server will use this mapped address as if it were a regular IPv6 address, and a usual IPv6 connection. However, IPv4 packets will be exchanged between the nodes. Kernels with dual stack properly interpret IPv4-mapped IPv6 addresses as IPv4 ones, and vice versa.
仅限IPv6服务器:当IPv4客户端应用程序使用通配符地址向双堆栈节点上运行的仅限IPv6服务器应用程序发送数据时,IPv4客户端地址将被解释为双堆栈节点中的IPv4映射IPv6地址。这允许IPv6应用程序管理通信。IPv6服务器将使用此映射地址,就像它是常规IPv6地址和常规IPv6连接一样。但是,IPv4数据包将在节点之间交换。具有双堆栈的内核正确地将IPv4映射的IPv6地址解释为IPv4地址,反之亦然。
IPv6-only client: IPv6-only client applications in a dual-stack node will not receive IPv4-mapped addresses from the hostname resolution API functions unless a special hint, AI_V4MAPPED, is given. If it
仅限IPv6客户端:双堆栈节点中仅限IPv6的客户端应用程序将不会从主机名解析API函数接收IPv4映射地址,除非给出特殊提示AI_V4MAPPED。如果是
is, the IPv6 client will use the returned mapped address as if it were a regular IPv6 address, and a usual IPv6 connection. However, IPv4 packets will be exchanged between applications.
是,IPv6客户端将使用返回的映射地址,就像它是常规IPv6地址和常规IPv6连接一样。但是,IPv4数据包将在应用程序之间交换。
Respectively, with IPV6_V6ONLY set, an IPv6-only server application will only communicate with IPv6 nodes, and an IPv6-only client only with IPv6 servers, as the mapped addresses have been disabled. This option could be useful if applications use new IPv6 features such as Flow Label. If communication with IPv4 is needed, either IPV6_V6ONLY must not be used, or dual-stack applications must be used, as described in section 4.3.
分别设置了IPV6_V6ONLY后,仅IPV6服务器应用程序将仅与IPV6节点通信,仅IPV6客户端仅与IPV6服务器通信,因为映射的地址已被禁用。如果应用程序使用新的IPv6功能(如流标签),此选项可能很有用。如果需要与IPv4通信,则不得使用IPV6_V6ONLY,或必须使用双堆栈应用程序,如第4.3节所述。
Some implementations of dual-stack do not allow IPv4-mapped IPv6 addresses to be used for interoperability between IPv4 and IPv6 applications. In these cases, there are two ways to handle the problem:
某些双栈实现不允许将IPv4映射的IPv6地址用于IPv4和IPv6应用程序之间的互操作性。在这些情况下,有两种方法来处理问题:
1. Deploy two different versions of the application (possibly attached with '6' in the name).
1. 部署应用程序的两个不同版本(名称中可能附加了“6”)。
2. Deploy just one application supporting both protocol versions as described in the next section.
2. 只部署一个支持两个协议版本的应用程序,如下一节所述。
The first method is not recommended because of a significant number of problems associated with selecting the right applications. These problems are described in sections 3.2 and 3.3.
不推荐使用第一种方法,因为在选择正确的应用程序时存在大量问题。第3.2节和第3.3节描述了这些问题。
Therefore, there are two distinct cases to consider when writing one application to support both protocols:
因此,当编写一个应用程序来支持两个协议时,有两个不同的情况需要考虑:
1. Whether the application can (or should) support both IPv4 and IPv6 through IPv4-mapped IPv6 addresses or the applications should support both explicitly (see section 4.3), and
1. 应用程序是否可以(或应该)通过IPv4映射的IPv6地址同时支持IPv4和IPv6,或者应用程序是否应该明确支持两者(请参见第4.3节),以及
2. Whether the systems in which the applications are used support IPv6 (see section 4.4).
2. 使用应用程序的系统是否支持IPv6(参见第4.4节)。
Note that some systems will disable (by default) support for internal IPv4-mapped IPv6 addresses. The security concerns regarding these are legitimate, but disabling them internally breaks one transition mechanism for server applications originally written to bind() and listen() to a single socket by using a wildcard address. This forces the software developer to rewrite the daemon to create two separate sockets, one for IPv4 only and the other for IPv6 only, and then to use select(). However, mapping-enabling of IPv4 addresses on any particular system is controlled by the OS owner and not necessarily
请注意,某些系统将禁用(默认情况下)对内部IPv4映射IPv6地址的支持。有关这些的安全问题是合理的,但在内部禁用它们会破坏服务器应用程序的一种转换机制,这种转换机制最初是通过使用通配符地址将bind()和listen()写入单个套接字的。这迫使软件开发人员重写守护进程以创建两个单独的套接字,一个仅用于IPv4,另一个仅用于IPv6,然后使用select()。但是,在任何特定系统上启用IPv4地址的映射都是由操作系统所有者控制的,不一定是这样
by a developer. This complicates developers' work, as they now have to rewrite the daemon network code to handle both environments, even for the same OS.
由一个开发者开发。这使开发人员的工作复杂化,因为他们现在必须重写守护程序网络代码来处理这两种环境,即使是对于同一个操作系统。
Applications should be ported to support both IPv4 and IPv6. Over time, the existing IPv4-only applications could be removed. As we have only one version of each application, the source code will typically be easy to maintain and to modify, and there are no problems managing which application to select for which communication.
应用程序应进行移植,以支持IPv4和IPv6。随着时间的推移,现有的仅IPv4应用程序可能会被删除。由于每个应用程序只有一个版本,因此源代码通常很容易维护和修改,并且在管理为哪个通信选择哪个应用程序时没有问题。
This transition case is the most advisable. During the IPv6 transition period, applications supporting both IPv4 and IPv6 should be able to communicate with other applications, irrespective of the version of the protocol stack or the application in the node. Dual applications allow more interoperability between heterogeneous applications and nodes.
这种过渡情况是最可取的。在IPv6过渡期间,支持IPv4和IPv6的应用程序应该能够与其他应用程序通信,而不管协议栈的版本或节点中的应用程序如何。双应用程序允许异构应用程序和节点之间实现更多互操作性。
If the source code is written in a protocol-independent way, without dependencies on either IPv4 or IPv6, applications will be able to communicate with any combination of applications and types of nodes.
如果源代码以独立于协议的方式编写,而不依赖于IPv4或IPv6,则应用程序将能够与应用程序和节点类型的任何组合进行通信。
Implementations typically prefer IPv6 by default if the remote node and application support it. However, if IPv6 connections fail, version-independent applications will automatically try IPv4 ones. The resolver returns a list of valid addresses for the remote node, and applications can iterate through all of them until connection succeeds.
如果远程节点和应用程序支持IPv6,则默认情况下实现通常更喜欢IPv6。但是,如果IPv6连接失败,独立于版本的应用程序将自动尝试IPv4连接。解析器返回远程节点的有效地址列表,应用程序可以遍历所有这些地址,直到连接成功。
Application writers should be aware of this protocol ordering, which is typically the default, but the applications themselves usually need not be [RFC3484].
应用程序编写者应该知道这种协议顺序,这通常是默认的,但应用程序本身通常不需要[RFC3484]。
If the source code is written in a protocol-dependent way, the application will support IPv4 and IPv6 explicitly by using two separate sockets. Note that there are some differences in bind() implementation - that is, in whether one can first bind to IPv6 wildcard addresses, and then to those for IPv4. Writing applications that cope with this can be a pain. Implementing IPV6_V6ONLY simplifies this. The IPv4 wildcard bind fails on some systems because the IPv4 address space is embedded into IPv6 address space when IPv4-mapped IPv6 addresses are used.
如果源代码以协议相关的方式编写,则应用程序将通过使用两个单独的套接字显式支持IPv4和IPv6。请注意,bind()实现中存在一些差异,即是否可以先绑定到IPv6通配符地址,然后再绑定到IPv4的通配符地址。编写能够处理这一问题的应用程序可能是一件痛苦的事情。实现IPV6_v6只会简化这一点。IPv4通配符绑定在某些系统上失败,因为在使用IPv4映射的IPv6地址时,IPv4地址空间嵌入到IPv6地址空间中。
A more detailed porting guideline is described in section 6.
第6节描述了更详细的移植指南。
As the transition is likely to take place over a longer time frame, applications already ported to support both IPv4 and IPv6 may be run on IPv4-only nodes. This would typically be done to avoid supporting two application versions for older and newer operating systems, or to support a case in which the user wants to disable IPv6 for some reason.
由于转换可能会在较长的时间内进行,因此已移植以支持IPv4和IPv6的应用程序可能会在仅IPv4的节点上运行。这样做通常是为了避免为较旧和较新的操作系统支持两个应用程序版本,或者是为了支持用户出于某种原因想要禁用IPv6的情况。
The most important case is the application support on systems where IPv6 support can be dynamically enabled or disabled by the users. Applications on such a system should be able to handle a situation IPv6 would not be enabled. Another scenario is when an application is deployed on older systems that do not support IPv6 at all (even the basic APIs such as getaddrinfo). In this case, the application designer has to make a case-by-case judgment call as to whether it makes sense to have compile-time toggle between an older and a newer API (having to support both in the code), or whether to provide getaddrinfo etc. function support on older platforms as part of the application libraries.
最重要的情况是用户可以动态启用或禁用IPv6支持的系统上的应用程序支持。这种系统上的应用程序应该能够处理无法启用IPv6的情况。另一种情况是,应用程序部署在完全不支持IPv6的较旧系统上(即使是基本API,如getaddrinfo)。在这种情况下,应用程序设计人员必须进行逐案判断调用,以确定在旧API和新API之间进行编译时切换是否有意义(必须在代码中同时支持这两种API),或者是否在旧平台上作为应用程序库的一部分提供getaddrinfo等函数支持。
Depending on application/operating system support, some may want to ignore this case, but usually no assumptions can be made, and applications should also work in this scenario.
根据应用程序/操作系统支持的不同,有些人可能希望忽略这种情况,但通常无法做出任何假设,应用程序也应该在这种情况下工作。
An example is an application that issues a socket() command, first trying AF_INET6 and then AF_INET. However, if the kernel does not have IPv6 support, the call will result in an EPROTONOSUPPORT or EAFNOSUPPORT error. Typically, errors like these lead to exiting the socket loop, and AF_INET will not even be tried. The application will need to handle this case or build the loop so that errors are ignored until the last address family.
例如,一个应用程序发出socket()命令,首先尝试AF_INET6,然后尝试AF_INET。但是,如果内核不支持IPv6,则调用将导致EPROTONOSUPPORT或EAFNOSUPPORT错误。通常,此类错误会导致退出套接字循环,甚至不会尝试AF_INET。应用程序将需要处理这种情况或构建循环,以便在最后一个地址族之前忽略错误。
This case is just an extension of the IPv4/IPv6 support in the previous case, covering one relatively common but often-ignored case.
本案例只是前一案例中IPv4/IPv6支持的扩展,涵盖了一个相对常见但常常被忽略的案例。
The minimum changes for IPv4 applications to work with IPv6 are based on the different size and format of IPv4 and IPv6 addresses.
IPv4应用程序与IPv6配合使用的最小更改基于IPv4和IPv6地址的不同大小和格式。
Applications have been developed with IPv4 network protocol in mind. This assumption has resulted in many IP dependencies through source code.
开发应用程序时考虑了IPv4网络协议。这种假设通过源代码导致了许多IP依赖关系。
The following list summarizes the more common IP version dependencies in applications:
以下列表总结了应用程序中更常见的IP版本依赖关系:
a) Presentation format for an IP address: An ASCII string that represents the IP address, a dotted-decimal string for IPv4, and a hexadecimal string for IPv6.
a) IP地址的表示格式:表示IP地址的ASCII字符串、表示IPv4的点十进制字符串和表示IPv6的十六进制字符串。
b) Transport layer API: Functions to establish communications and to exchange information.
b) 传输层API:用于建立通信和交换信息的函数。
c) Name and address resolution: Conversion functions between hostnames and IP addresses.
c) 名称和地址解析:主机名和IP地址之间的转换函数。
d) Specific IP dependencies: More specific IP version dependencies, such as IP address selection, application framing, and storage of IP addresses.
d) 特定IP依赖项:更特定的IP版本依赖项,如IP地址选择、应用程序框架和IP地址存储。
e) Multicast applications: One must find the IPv6 equivalents to the IPv4 multicast addresses and use the right socket configuration options.
e) 多播应用程序:必须找到与IPv4多播地址等价的IPv6,并使用正确的套接字配置选项。
The following subsections describe the problems with the aforementioned IP version dependencies. Although application source code can be ported to IPv6 with minimum changes related to IP addresses, some recommendations are given to modify the source code in a protocol-independent way, which will allow applications to work with both IPv4 and IPv6.
以下小节描述了上述IP版本依赖关系的问题。虽然可以将应用程序源代码移植到IPv6,但只需对IP地址进行最小的更改,但仍提供了一些建议,以独立于协议的方式修改源代码,这将允许应用程序同时使用IPv4和IPv6。
Many applications use IP addresses to identify network nodes and to establish connections to destination addresses. For instance, using the client/server model, clients usually need an IP address as an application parameter to connect to a server. This IP address is usually provided in the presentation format, as a string. There are two problems when porting the presentation format for an IP address: the allocated memory and the management of the presentation format.
许多应用程序使用IP地址来标识网络节点并建立到目标地址的连接。例如,使用客户机/服务器模型,客户机通常需要一个IP地址作为连接到服务器的应用程序参数。此IP地址通常以表示格式作为字符串提供。移植IP地址的表示格式时有两个问题:分配的内存和表示格式的管理。
Usually, the memory allocated to contain an IPv4 address representation as a string is unable to contain an IPv6 address. Applications should be modified to prevent buffer overflows made possible by the larger IPv6 address.
通常,分配给以字符串形式包含IPv4地址表示的内存无法包含IPv6地址。应修改应用程序,以防止较大的IPv6地址造成缓冲区溢出。
IPv4 and IPv6 do not use the same presentation format. IPv4 uses a dot (.) to separate the four octets written in decimal notation, and IPv6 uses a colon (:) to separate each pair of octets written in hexadecimal notation [RFC3513]. In cases where one must be able to specify, for example, port numbers with the address (see below), it may be desirable to require placing the address inside the square brackets [TextRep].
IPv4和IPv6不使用相同的表示格式。IPv4使用点(.)分隔以十进制表示的四个八位字节,IPv6使用冒号(:)分隔以十六进制表示的每对八位字节[RFC3513]。例如,在必须能够指定端口号和地址的情况下(见下文),可能需要将地址放在方括号内[TextRep]。
A particular problem with IP address parsers comes when the input is actually a combination of IP address and port number. With IPv4 these are often coupled with a colon; for example, "192.0.2.1:80". However, this approach would be ambiguous with IPv6, as colons are already used to structure the address.
当输入实际上是IP地址和端口号的组合时,IP地址解析器会出现一个特殊的问题。对于IPv4,它们通常与冒号连接;例如,“192.0.2.1:80”。然而,这种方法对于IPv6来说是不明确的,因为冒号已经被用来构造地址。
Therefore, the IP address parsers that take the port number separated with a colon should distinguish IPv6 addresses somehow. One way is to enclose the address in brackets, as is done with Uniform Resource Locators (URLs) [RFC2732]; for example, http://[2001:db8::1]:80.
因此,采用冒号分隔的端口号的IP地址解析器应该以某种方式区分IPv6地址。一种方法是将地址括在括号中,就像使用统一资源定位器(URL)[RFC2732]一样;例如,http://[2001:db8::1]:80。
Some applications also need to specify IPv6 prefixes and lengths: The prefix length should be inserted outside of the square brackets, if used; for example, [2001:db8::]/64 or 2001:db8::/64 and not [2001:db8::/64]. Note that prefix/length notation is syntactically indistinguishable from a legal URI; therefore, the prefix/length notation must not be used when it isn't clear from the context that it's used to specify the prefix and length and not, for example, a URI.
一些应用程序还需要指定IPv6前缀和长度:如果使用,前缀长度应插入方括号之外;例如,[2001:db8::]/64或2001:db8::/64而不是[2001:db8::/64]。注意,前缀/长度表示法在语法上与合法URI无法区分;因此,当上下文中不清楚前缀/长度表示法用于指定前缀和长度而不是URI时,不得使用前缀/长度表示法。
In some specific cases, it may be necessary to give a zone identifier as part of the address; for example, fe80::1%eth0. In general, applications should not need to parse these identifiers.
在某些特定情况下,可能需要提供区域标识符作为地址的一部分;例如,fe80::1%eth0。一般来说,应用程序不需要解析这些标识符。
The IP address parsers should support enclosing the IPv6 address in brackets, even when the address is not used in conjunction with a port number. Requiring that the user always give a literal IP address enclosed in brackets is not recommended.
IP地址解析器应支持将IPv6地址括在括号中,即使该地址未与端口号一起使用。不建议要求用户始终提供括号内的文字IP地址。
Note that some applications may also represent IPv6 address literals differently; for example, SMTP [RFC2821] uses [IPv6:2001:db8::1].
请注意,某些应用程序也可能以不同的方式表示IPv6地址文本;例如,SMTP[RFC2821]使用[IPv6:2001:db8::1]。
Note that the use of address literals is strongly discouraged for general-purpose direct input to the applications. Host names and DNS should be used instead.
请注意,对于应用程序的通用直接输入,强烈建议不要使用地址文本。应改用主机名和DNS。
Communication applications often include a transport module that establishes communications. Usually this module manages everything related to communications and uses a transport-layer API, typically as a network library. When an application is ported to IPv6, most changes should be made in this application transport module in order to be adapted to the new IPv6 API.
通信应用程序通常包括建立通信的传输模块。通常,该模块管理与通信相关的一切,并使用传输层API,通常作为网络库。将应用程序移植到IPv6时,应在此应用程序传输模块中进行大多数更改,以适应新的IPv6 API。
In the general case, porting an existing application to IPv6 requires an examination of the following issues related to the API:
在一般情况下,将现有应用程序移植到IPv6需要检查与API相关的以下问题:
- Network Information Storage: IP address Data Structures The new structures must contain 128-bit IP addresses. The use of generic address structures, which can store any address family, is recommended.
- 网络信息存储:IP地址数据结构新结构必须包含128位IP地址。建议使用可存储任何地址族的通用地址结构。
Sometimes special addresses are hard-coded in the application source code. Developers should pay attention to these in order to use the new address format. Some of these special IP addresses are wildcard local, loopback, and broadcast. IPv6 does not have the broadcast addresses, so applications can use multicast instead.
有时在应用程序源代码中硬编码特殊地址。开发人员应该注意这些,以便使用新的地址格式。其中一些特殊IP地址是通配符本地、环回和广播。IPv6没有广播地址,因此应用程序可以使用多播。
- Address Conversion Functions The address conversion functions convert the binary address representation to the presentation format and vice versa. The new conversion functions are specified to the IPv6 address format.
- 地址转换函数地址转换函数将二进制地址表示转换为表示格式,反之亦然。新的转换函数指定为IPv6地址格式。
- Communication API Functions These functions manage communications. Their signatures are defined based on a generic socket address structure. The same functions are valid for IPv6; however, the IP address data structures used when calling these functions require the updates.
- 通信API函数这些函数管理通信。它们的签名是基于通用套接字地址结构定义的。相同的功能对IPv6有效;但是,调用这些函数时使用的IP地址数据结构需要更新。
- Network Configuration Options These are used when different communication models are configured for Input/Output (I/O) operations (blocking/nonblocking, I/O multiplexing, etc.) and should be translated for IPv6.
- 网络配置选项—当为输入/输出(I/O)操作(阻塞/非阻塞、I/O多路复用等)配置不同的通信模型时,将使用这些选项,并应转换为IPv6。
From the application point of view, the name and address resolution is a system-independent process. An application calls functions in a system library, the resolver, which is linked into the application when it is built. However, these functions use IP address structures, that are protocol dependent and must be reviewed to support the new IPv6 resolution calls.
从应用程序的角度来看,名称和地址解析是一个独立于系统的过程。应用程序调用系统库(解析器)中的函数,解析器在构建时链接到应用程序中。但是,这些功能使用IP地址结构,这些结构依赖于协议,必须进行检查以支持新的IPv6解析调用。
With IPv6, there are two new basic resolution functions, getaddrinfo() and getnameinfo(). The first returns a list of all configured IP addresses for a hostname. These queries can be constrained to one protocol family; for instance, only IPv4 or only
在IPv6中,有两个新的基本解析函数,getaddrinfo()和getnameinfo()。第一个返回主机名的所有已配置IP地址的列表。这些查询可以限制为一个协议族;例如,仅IPv4或仅IPv4
IPv6 addresses. However, it is recommended that all configured IP addresses be obtained to allow applications to work with every kind of node. The second function returns the hostname associated to an IP address.
IPv6地址。但是,建议获取所有配置的IP地址,以允许应用程序与每种节点一起工作。第二个函数返回与IP地址关联的主机名。
Unlike the IPv4 model, IPv6 promotes the configuration of multiple IP addresses per node, however, applications only use a destination/source pair for a communication. Choosing the right IP source and destination addresses is a key factor that may determine the route of IP datagrams.
与IPv4模式不同,IPv6促进了每个节点多个IP地址的配置,但是,应用程序仅使用目的地/源对进行通信。选择正确的IP源地址和目标地址是决定IP数据报路由的关键因素。
Typically, nodes, not applications, automatically solve the source address selection. A node will choose the source address for a communication following some rules of best choice, per [RFC3484], but will also allow applications to make changes in the ordering rules.
通常,节点(而不是应用程序)会自动解决源地址选择问题。根据[RFC3484],节点将根据一些最佳选择规则选择通信的源地址,但也允许应用程序更改排序规则。
When selecting the destination address, applications usually ask a resolver for the destination IP address. The resolver returns a set of valid IP addresses from a hostname. Unless applications have a specific reason to select any particular destination address, they should try each element in the list until the communication succeeds.
当选择目标地址时,应用程序通常向解析器请求目标IP地址。解析程序从主机名返回一组有效的IP地址。除非应用程序有特定的理由选择任何特定的目标地址,否则它们应该尝试列表中的每个元素,直到通信成功。
In some cases, the application may need to specify its source address. The destination address selection process picks the best destination for the source address (instead of picking the best source address for the chosen destination address). Note that if it is not yet known which protocol will be used for communication there may be an increase in complexity for IP version - independent applications that have to specify the source address (especially for client applications. Fortunately, specifying the source address is not typically required).
在某些情况下,应用程序可能需要指定其源地址。目标地址选择过程为源地址选择最佳目标(而不是为所选目标地址选择最佳源地址)。请注意,如果还不知道将使用哪个协议进行通信,则必须指定源地址的IP版本无关应用程序(尤其是客户端应用程序)的复杂性可能会增加。幸运的是,通常不需要指定源地址。
The Application Level Framing (ALF) architecture controls mechanisms that traditionally fall within the transport layer. Applications implementing ALF are often responsible for packetizing data into Application Data Units (ADUs). The application problem with ALF arrives from the ADU size selection to obtain better performance.
应用程序级框架(ALF)体系结构控制传统上属于传输层的机制。实现ALF的应用程序通常负责将数据打包到应用程序数据单元(ADU)中。ALF的应用问题来自ADU尺寸选择,以获得更好的性能。
Applications using connectionless protocols (such as UDP) typically need application framing. These applications have three choices: (1) to use packet sizes no larger than the IPv6 minimum Maximum Transmission Unit (MTU) of 1280 bytes [RFC2460], (2) to use any
使用无连接协议(如UDP)的应用程序通常需要应用程序框架。这些应用程序有三种选择:(1)使用不大于1280字节的IPv6最小最大传输单元(MTU)[RFC2460],(2)使用任何
packet sizes, but to force IPv6 fragmentation/reassembly when necessary, or (3) to optimize the packet size and avoid unnecessary fragmentation/reassembly, and to guess or find out the optimal packet sizes that can be sent and received, end-to-end, on the network. This memo takes no stance on that approach is best.
数据包大小,但在必要时强制IPv6分段/重新组装,或(3)优化数据包大小,避免不必要的分段/重新组装,并猜测或找出网络上可以端到端发送和接收的最佳数据包大小。这份备忘录没有表明这种做法是最好的。
Note that the most optimal ALF depends on dynamic factors such as Path MTU or whether IPv4 or IPv6 is being used (due to different header sizes, possible IPv6-in-IPv4 tunneling overhead, etc.). These factors have to be taken into consideration when application framing is implemented.
请注意,最佳ALF取决于动态因素,如路径MTU或是否使用IPv4或IPv6(由于不同的报头大小、可能的IPv6-in-IPv4隧道开销等)。在实现应用程序框架时,必须考虑这些因素。
Some applications store IP addresses as remote peer information. For instance, one of the most popular ways to register remote nodes in collaborative applications uses IP addresses as registry keys.
某些应用程序将IP地址存储为远程对等信息。例如,在协作应用程序中注册远程节点的最流行的方法之一就是使用IP地址作为注册表项。
Although the source code that stores IP addresses can be modified to IPv6 by following the previous basic porting recommendations, applications should not store IP addresses for the following reasons:
虽然存储IP地址的源代码可以按照前面的基本移植建议修改为IPv6,但应用程序不应存储IP地址,原因如下:
- IP addresses can change throughout time; for instance, after a renumbering process.
- IP地址可以随时间变化;例如,在重新编号过程之后。
- The same node can reach a destination host using different IP addresses, possibly with a different protocol version.
- 同一节点可以使用不同的IP地址(可能使用不同的协议版本)到达目标主机。
When possible, applications should store names such as FQDNs or other protocol-independent identities instead of addresses. In this case applications are only bound to specific addresses at run time, or for the duration of a cache lifetime. Other types of applications, such as massive peer-to-peer systems with their own rendezvous and discovery mechanisms, may need to cache addresses for performance reasons, but cached addresses should not be treated as permanent, reliable information. In highly dynamic networks, any form of name resolution may be impossible, and here again addresses must be cached.
如果可能,应用程序应该存储名称,例如FQDN或其他与协议无关的标识,而不是地址。在这种情况下,应用程序仅在运行时绑定到特定地址,或在缓存生存期内绑定到特定地址。其他类型的应用程序,例如具有自身集合和发现机制的大规模对等系统,出于性能原因可能需要缓存地址,但缓存地址不应被视为永久、可靠的信息。在高度动态的网络中,任何形式的名称解析都是不可能的,在这里地址必须被缓存。
There is an additional problem in porting multicast applications. When multicast facilities are used some changes must be carried out to support IPv6. First, applications must change the IPv4 multicast addresses to IPv6 ones, and second, the socket configuration options must be changed.
在移植多播应用程序时还有一个问题。当使用多播设施时,必须进行一些更改以支持IPv6。首先,应用程序必须将IPv4多播地址更改为IPv6地址,其次,必须更改套接字配置选项。
All IPv6 multicast addresses encode scope; the scope was only implicit in IPv4 (with multicast groups in 239/8). Also, although a large number of application-specific multicast addresses have been assigned with IPv4, this has been (luckily enough) avoided with IPv6. So there are no direct equivalents for all the multicast addresses. For link-local multicast, it's possible to pick almost anything within the link-local scope. The global groups could use unicast prefix - based addresses [RFC3306]. All in all, this may force the application developers to write more protocol-dependent code.
所有IPv6多播地址编码范围;作用域仅在IPv4中是隐式的(在239/8中有多播组)。此外,尽管IPv4分配了大量特定于应用程序的多播地址,但IPv6(幸运的是)避免了这一点。因此,所有多播地址都没有直接等价物。对于链路本地多播,几乎可以拾取链路本地范围内的任何内容。全局组可以使用基于前缀的单播地址[RFC3306]。总之,这可能会迫使应用程序开发人员编写更多依赖于协议的代码。
Another problem is that IPv6 multicast does not yet have a standardized mechanism for traditional Any Source Multicast for Interdomain multicast. The models for Any Source Multicast (ASM) or Source-Specific Multicast (SSM) are generally similar between IPv4 and IPv6, but it is possible that PIM-SSM will become more widely deployed in IPv6 due to its simpler architecture.
另一个问题是IPv6多播还没有一个标准化的机制,用于域间多播的传统任何源多播。IPv4和IPv6之间任何源多播(ASM)或源特定多播(SSM)的模型通常相似,但PIM-SSM可能由于其更简单的体系结构而在IPv6中得到更广泛的部署。
It might be beneficial to port the applications to use SSM semantics, requiring off-band source discovery mechanisms and a different API [RFC3678]. Inter-domain ASM service is available only through a method embedding the Rendezvous Point address in the multicast address [Embed-RP].
将应用程序移植到使用SSM语义的端口可能是有益的,这需要带外源发现机制和不同的API[RFC3678]。域间ASM服务仅通过在多播地址[Embed RP]中嵌入集合点地址的方法可用。
Another generic problem with multiparty conferencing applications, similar to the issues with peer-to-peer applications, is that all users of the session must use the same protocol version (IPv4 or IPv6), or some form of proxy or translator (e.g., [MUL-GW]).
与对等应用程序的问题类似,多方会议应用程序的另一个常见问题是,会话的所有用户必须使用相同的协议版本(IPv4或IPv6),或某种形式的代理或转换器(例如,[MUL-GW])。
As stated, dual applications working with both IPv4 and IPv6 are recommended. These applications should avoid IP dependencies in the source code. However, if IP dependencies are required, one of the better solutions would be to build a communication library that provides an IP version - independent API to applications and that hides all dependencies.
如上所述,建议同时使用IPv4和IPv6的双应用程序。这些应用程序应该避免源代码中的IP依赖关系。但是,如果需要IP依赖关系,更好的解决方案之一是构建一个通信库,为应用程序提供一个与IP版本无关的API,并隐藏所有依赖关系。
To develop IP version - independent applications, the following guidelines should be considered.
要开发与IP版本无关的应用程序,应考虑以下准则。
All memory structures and APIs should be IP version-independent. One should avoid structs in_addr, in6_addr, sockaddr_in, and sockaddr_in6.
所有内存结构和API都应该是独立于IP版本的。我们应该避免在_addr、in 6 addr、sockaddr_in和sockaddr_in 6中使用结构。
Suppose a network address is passed to some function, foo(). If one uses struct in_addr or struct in6_addr, results an extra parameter to indicate address family, as below:
假设将网络地址传递给某个函数foo()。如果在_addr中使用struct或在6 _addr中使用struct,则会产生一个额外的参数来指示地址族,如下所示:
struct in_addr in4addr; struct in6_addr in6addr; /* IPv4 case */ foo(&in4addr, AF_INET); /* IPv6 case */ foo(&in6addr, AF_INET6);
struct in_addr in4addr; struct in6_addr in6addr; /* IPv4 case */ foo(&in4addr, AF_INET); /* IPv6 case */ foo(&in6addr, AF_INET6);
This leads to duplicated code and having to consider each scenario from both perspectives independently, which is difficult to maintain. So we should use struct sockaddr_storage, as below:
这导致重复的代码,并且必须从两个角度独立地考虑每个场景,这是难以维护的。因此,我们应该使用struct sockaddr_存储,如下所示:
struct sockaddr_storage ss; int sslen; /* AF independent! - use sockaddr when passing a pointer */ /* note: it's typically necessary to also pass the length explicitly */ foo((struct sockaddr *)&ss, sslen);
struct sockaddr_storage ss; int sslen; /* AF independent! - use sockaddr when passing a pointer */ /* note: it's typically necessary to also pass the length explicitly */ foo((struct sockaddr *)&ss, sslen);
The new address independent variants getaddrinfo() and getnameinfo() hide the gory details of name-to-address and address-to-name translations. They implement functionalities of the following functions:
新的独立于地址的变量getaddrinfo()和getnameinfo()隐藏了名称到地址和地址到名称转换的详细信息。它们实现以下功能的功能:
gethostbyname() gethostbyaddr() getservbyname() getservbyport()
gethostbyname()gethostbyaddr()getservbyname()getservbyport()
They also obsolete the functionality of gethostbyname2(), defined in [RFC2133].
它们还废弃了[RFC2133]中定义的gethostbyname2()的功能。
The new variants can perform hostname/address and service name/port lookups, though the features can be turned off, if desired. Getaddrinfo() can return multiple addresses, as below:
新的变体可以执行主机名/地址和服务名/端口查找,但如果需要,可以关闭这些功能。Getaddrinfo()可以返回多个地址,如下所示:
localhost. IN A 127.0.0.1 IN A 127.0.0.2 IN AAAA ::1
本地主机。在AAAA中的127.0.0.1和127.0.0.2中::1
In this example, if IPv6 is preferred, getaddrinfo first returns ::1; then both 127.0.0.1 and 127.0.0.2 are in a random order.
在本例中,如果首选IPv6,则getaddrinfo首先返回::1;那么127.0.0.1和127.0.0.2都是随机顺序。
Getaddrinfo() and getnameinfo() can query hostname and service name/port at once.
Getaddrinfo()和getnameinfo()可以同时查询主机名和服务名称/端口。
Hardcoding AF-dependent knowledge is not preferred in the program. Constructs such as that below should be avoided:
程序中不首选硬编码AF相关知识。应避免以下构造:
/* BAD EXAMPLE */ switch (sa->sa_family) { case AF_INET: salen = sizeof(struct sockaddr_in); break; }
/* BAD EXAMPLE */ switch (sa->sa_family) { case AF_INET: salen = sizeof(struct sockaddr_in); break; }
Instead, we should use the ai_addrlen member of the addrinfo structure, as returned by getaddrinfo().
相反,我们应该使用addrinfo结构的ai_addrlen成员,如getaddrinfo()返回的。
The gethostbyname(), gethostbyaddr(), getservbyname(), and getservbyport() are mainly used to get server and client sockets. In the following sections, we will see simple examples creating these sockets by using the new IPv6 resolution functions.
gethostbyname()、gethostbyaddr()、getservbyname()和getservbyport()主要用于获取服务器和客户端套接字。在以下部分中,我们将看到使用新的IPv6解析函数创建这些套接字的简单示例。
A simple TCP server socket at service name (or port number string) SERVICE:
服务名称(或端口号字符串)服务处的简单TCP服务器套接字:
/* * BAD EXAMPLE: does not implement the getaddrinfo loop as * specified in 6.3. This may result in one of the following: * - an IPv6 server, listening at the wildcard address, * allowing IPv4 addresses through IPv4-mapped IPv6 addresses. * - an IPv4 server, if IPv6 is not enabled, * - an IPv6-only server, if IPv6 is enabled but IPv4-mapped IPv6 * addresses are not used by default, or * - no server at all, if getaddrinfo supports IPv6, but the * system doesn't, and socket(AF_INET6, ...) exits with an * error. */ struct addrinfo hints, *res; int error, sockfd;
/* * BAD EXAMPLE: does not implement the getaddrinfo loop as * specified in 6.3. This may result in one of the following: * - an IPv6 server, listening at the wildcard address, * allowing IPv4 addresses through IPv4-mapped IPv6 addresses. * - an IPv4 server, if IPv6 is not enabled, * - an IPv6-only server, if IPv6 is enabled but IPv4-mapped IPv6 * addresses are not used by default, or * - no server at all, if getaddrinfo supports IPv6, but the * system doesn't, and socket(AF_INET6, ...) exits with an * error. */ struct addrinfo hints, *res; int error, sockfd;
memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(NULL, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */
memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(NULL, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */
}
}
sockfd = socket(res->family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { /* handle socket error */ }
sockfd = socket(res->family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { /* handle socket error */ }
if (bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) { /* handle bind error */ }
if (bind(sockfd, res->ai_addr, res->ai_addrlen) < 0) { /* handle bind error */ }
/* ... */
/* ... */
freeaddrinfo(res);
freeaddrinfo(res);
A simple TCP client socket connecting to a server running at node name (or IP address presentation format) SERVER_NODE and service name (or port number string) SERVICE follows:
连接到以节点名称(或IP地址表示格式)服务器\节点和服务名称(或端口号字符串)服务运行的服务器的简单TCP客户端套接字如下所示:
/* * BAD EXAMPLE: does not implement the getaddrinfo loop as * specified in 6.3. This may result in one of the following: * - an IPv4 connection to an IPv4 destination, * - an IPv6 connection to an IPv6 destination, * - an attempt to try to reach an IPv6 destination (if AAAA * record found), but failing -- without fallbacks -- because: * o getaddrinfo supports IPv6 but the system does not * o IPv6 routing doesn't exist, so falling back to e.g., TCP * timeouts * o IPv6 server reached, but service not IPv6-enabled or * firewalled away * - if the first destination is not reached, there is no * fallback to the next records */ struct addrinfo hints, *res; int error, sockfd;
/* * BAD EXAMPLE: does not implement the getaddrinfo loop as * specified in 6.3. This may result in one of the following: * - an IPv4 connection to an IPv4 destination, * - an IPv6 connection to an IPv6 destination, * - an attempt to try to reach an IPv6 destination (if AAAA * record found), but failing -- without fallbacks -- because: * o getaddrinfo supports IPv6 but the system does not * o IPv6 routing doesn't exist, so falling back to e.g., TCP * timeouts * o IPv6 server reached, but service not IPv6-enabled or * firewalled away * - if the first destination is not reached, there is no * fallback to the next records */ struct addrinfo hints, *res; int error, sockfd;
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM;
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
sockfd = socket(res->family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { /* handle socket error */ }
sockfd = socket(res->family, res->ai_socktype, res->ai_protocol); if (sockfd < 0) { /* handle socket error */ }
if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 ) { /* handle connect error */ }
if (connect(sockfd, res->ai_addr, res->ai_addrlen) < 0 ) { /* handle connect error */ }
/* ... */
/* ... */
freeaddrinfo(res);
freeaddrinfo(res);
We should consider the binary and presentation address format conversion APIs. The following functions convert network address structure in its presentation address format and vice versa:
我们应该考虑二进制和呈现地址格式转换API。以下函数将网络地址结构转换为表示地址格式,反之亦然:
inet_ntop() inet_pton()
inet_ntop()inet_pton()
Both are from the basic socket extensions for IPv6. However, these conversion functions are protocol-dependent. It is better to use getnameinfo()/getaddrinfo() (inet_pton and inet_ntop equivalents are described in Appendix A).
两者都来自IPv6的基本套接字扩展。但是,这些转换函数依赖于协议。最好使用getnameinfo()/getaddrinfo()(附录A中描述了inet\u pton和inet\u ntop等价物)。
Conversion from network address structure to presentation format can be written as follows:
从网络地址结构到表示格式的转换可以编写如下:
struct sockaddr_storage ss; char addrStr[INET6_ADDRSTRLEN]; char servStr[NI_MAXSERV]; int error;
struct sockaddr_storage ss; char addrStr[INET6_ADDRSTRLEN]; char servStr[NI_MAXSERV]; int error;
/* fill ss structure */
/* fill ss structure */
error = getnameinfo((struct sockaddr *)&ss, sizeof(ss), addrStr, sizeof(addrStr), servStr, sizeof(servStr), NI_NUMERICHOST);
error = getnameinfo((struct sockaddr *)&ss, sizeof(ss), addrStr, sizeof(addrStr), servStr, sizeof(servStr), NI_NUMERICHOST);
Conversions from presentation format to network address structure can be written as follows:
从表示格式到网络地址结构的转换可以编写如下:
struct addrinfo hints, *res; char addrStr[INET6_ADDRSTRLEN]; int error;
struct addrinfo hints, *res; char addrStr[INET6_ADDRSTRLEN]; int error;
/* fill addrStr buffer */
/* fill addrStr buffer */
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC;
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC;
error = getaddrinfo(addrStr, NULL, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
error = getaddrinfo(addrStr, NULL, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
/* res->ai_addr contains the network address structure */ /* ... */ freeaddrinfo(res);
/* res->ai_addr contains the network address structure */ /* ... */ freeaddrinfo(res);
In a client code, when multiple addresses are returned from getaddrinfo(), we should try all of them until connection succeeds. When a failure occurs with socket(), connect(), bind(), or some other function, the code should go on to try the next address.
在客户端代码中,当从getaddrinfo()返回多个地址时,我们应该尝试所有地址,直到连接成功。当socket()、connect()、bind()或其他函数出现故障时,代码应继续尝试下一个地址。
In addition, if something is wrong with the socket call because the address family is not supported (i.e., in case of section 4.4), applications should try the next address structure.
此外,如果由于不支持地址族(即,在第4.4节的情况下),套接字调用出现问题,应用程序应尝试下一个地址结构。
Note: In the following examples, the socket() return value error handling could be simplified by always continuing on with the socket loop instead of performing special checking of specific error numbers.
注意:在下面的示例中,socket()返回值错误处理可以通过始终继续套接字循环而不是执行特定错误号的特殊检查来简化。
The previous TCP server example should be written as follows:
前面的TCP服务器示例应编写如下:
#define MAXSOCK 2 struct addrinfo hints, *res; int error, sockfd[MAXSOCK], nsock=0;
#define MAXSOCK 2 struct addrinfo hints, *res; int error, sockfd[MAXSOCK], nsock=0;
memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC;
memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hits.ai_socktype=SOCK_流;
error = getaddrinfo(NULL, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
error = getaddrinfo(NULL, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
for (aip=res; aip && nsock < MAXSOCK; aip=aip->ai_next) { sockfd[nsock] = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
for (aip=res; aip && nsock < MAXSOCK; aip=aip->ai_next) { sockfd[nsock] = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
if (sockfd[nsock] < 0) { switch errno { case EAFNOSUPPORT: case EPROTONOSUPPORT: /* * e.g., skip the errors until * the last address family, * see section 4.4. */ if (aip->ai_next) continue;
if (sockfd[nsock] < 0) { switch errno { case EAFNOSUPPORT: case EPROTONOSUPPORT: /* * e.g., skip the errors until * the last address family, * see section 4.4. */ if (aip->ai_next) continue;
else { /* handle unknown protocol errors */ break; } default: /* handle other socket errors */ ; }
else { /* handle unknown protocol errors */ break; } default: /* handle other socket errors */ ; }
} else { int on = 1; /* optional: works better if dual-binding to wildcard address */ if (aip->ai_family == AF_INET6) { setsockopt(sockfd[nsock], IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); /* errors are ignored */ } if (bind(sockfd[nsock], aip->ai_addr, aip->ai_addrlen) < 0 ) { /* handle bind error */ close(sockfd[nsock]); continue; }
} else { int on = 1; /* optional: works better if dual-binding to wildcard address */ if (aip->ai_family == AF_INET6) { setsockopt(sockfd[nsock], IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); /* errors are ignored */ } if (bind(sockfd[nsock], aip->ai_addr, aip->ai_addrlen) < 0 ) { /* handle bind error */ close(sockfd[nsock]); continue; }
if (listen(sockfd[nsock], SOMAXCONN) < 0) { /* handle listen errors */ close(sockfd[nsock]); continue; } } nsock++; } freeaddrinfo(res);
if (listen(sockfd[nsock], SOMAXCONN) < 0) { /* handle listen errors */ close(sockfd[nsock]); continue; } } nsock++; } freeaddrinfo(res);
/* check that we were able to obtain the sockets */
/* check that we were able to obtain the sockets */
The previous TCP client example should be written as follows:
前面的TCP客户端示例应编写如下:
struct addrinfo hints, *res, *aip; int sockfd, error;
struct addrinfo hints, *res, *aip; int sockfd, error;
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM;
memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
error = getaddrinfo(SERVER_NODE, SERVICE, &hints, &res); if (error != 0) { /* handle getaddrinfo error */ }
for (aip=res; aip; aip=aip->ai_next) {
for (aip=res; aip; aip=aip->ai_next) {
sockfd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
sockfd = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
if (sockfd < 0) { switch errno { case EAFNOSUPPORT: case EPROTONOSUPPORT: /* * e.g., skip the errors until * the last address family, * see section 4.4. */ if (aip->ai_next) continue; else { /* handle unknown protocol errors */ break;
if (sockfd < 0) { switch errno { case EAFNOSUPPORT: case EPROTONOSUPPORT: /* * e.g., skip the errors until * the last address family, * see section 4.4. */ if (aip->ai_next) continue; else { /* handle unknown protocol errors */ break;
}
}
default: /* handle other socket errors */ ; }
default: /* handle other socket errors */ ; }
} else { if (connect(sockfd, aip->ai_addr, aip->ai_addrlen) == 0) break;
} else { if (connect(sockfd, aip->ai_addr, aip->ai_addrlen) == 0) break;
/* handle connect errors */ close(sockfd); sockfd=-1; } }
/* handle connect errors */ close(sockfd); sockfd=-1; } }
if (sockfd > 0) { /* socket connected to server address */
if (sockfd > 0) { /* socket connected to server address */
/* ... */ }
/* ... */ }
freeaddrinfo(res);
freeaddrinfo(res);
The mechanism [NAT-PT] introduces a special set of addresses, formed of an NAT-PT prefix and an IPv4 address these refer to IPv4 addresses translated by NAT-PT DNS-ALG. In some cases, one might be tempted to handle these differently.
机制[NAT-PT]引入了一组特殊的地址,由NAT-PT前缀和IPv4地址组成。这些地址指NAT-PT DNS-ALG转换的IPv4地址。在某些情况下,人们可能会试图以不同的方式处理这些问题。
However, IPv6 applications must not be required to distinguish "normal" and "NAT-PT translated" addresses (or any other kind of special addresses, including the IPv4-mapped IPv6 addresses): This would be completely impractical, and if the distinction must be made, it must be done elsewhere (e.g., kernel, system libraries).
但是,不得要求IPv6应用程序区分“正常”和“NAT-PT转换”地址(或任何其他类型的特殊地址,包括IPv4映射的IPv6地址):这将完全不切实际,如果必须进行区分,则必须在其他地方进行(例如,内核、系统库)。
There are a number of security considerations for IPv6 transition, but those are outside the scope of this memo.
IPv6转换有许多安全注意事项,但这些不在本备忘录的范围之内。
To ensure the availability and robustness of the service even when transitioning to IPv6, this memo describes a number of ways to make applications more resistant to failures by cycling through addresses until a working one is found. Doing this properly is critical to maintain availability and to avoid loss of service.
为了确保服务的可用性和健壮性(即使在过渡到IPv6时),本备忘录介绍了通过在地址间循环直到找到可用地址,使应用程序更能抵抗故障的多种方法。正确地执行此操作对于保持可用性和避免服务丢失至关重要。
A special consideration about application transition is how IPv4- mapped IPv6 addresses are handled. The use in the API can be seen both as a merit (easier application transition) and as a burden (difficulty in ensuring whether the use was legitimate). Note that some systems will disable (by default) support for internal IPv4- mapped IPv6 addresses. The security concerns regarding these on the wire are legitimate, but disabling it internally breaks one transition mechanism for server applications originally written to bind() and listen() to a single socket by using a wildcard address [V6MAPPED]. This should be considered in more detail when applications are designed.
关于应用程序转换的一个特殊考虑是如何处理IPv4映射的IPv6地址。API中的使用可以被视为优点(更容易的应用程序转换)和负担(难以确保使用是否合法)。请注意,某些系统将禁用(默认情况下)对内部IPv4映射IPv6地址的支持。关于这些连接的安全问题是合理的,但在内部禁用它会破坏服务器应用程序的一种转换机制,这些应用程序最初是使用通配符地址[V6MAPPED]将bind()和listen()写入单个套接字的。在设计应用程序时,应更详细地考虑这一点。
Some of guidelines for development of IP version-independent applications (section 6) were first brought up by [AF-APP]. Other work to document application porting guidelines has also been in progress; for example, [IP-GGF] and [PRT]. We would like to thank the members of the v6ops working group and the application area for helpful comments. Special thanks are due to Brian E. Carpenter, Antonio Querubin, Stig Venaas, Chirayu Patel, Jordi Palet, and Jason Lin for extensive review of this document. We acknowledge Ron Pike for proofreading the document.
[AF-APP]首先提出了一些与IP版本无关的应用程序开发指南(第6节)。记录应用程序移植指南的其他工作也在进行中;例如,[IP-GGF]和[PRT]。我们要感谢v6ops工作组和应用领域的成员提供的有用意见。特别感谢Brian E.Carpenter、Antonio Querubin、Stig Venaas、Chirayu Patel、Jordi Palet和Jason Lin对本文件的广泛审阅。我们感谢罗恩·派克校对这份文件。
[RFC3493] Gilligan, R., Thomson, S., Bound, J., McCann, J., and W. Stevens, "Basic Socket Interface Extensions for IPv6", RFC 3493, February 2003.
[RFC3493]Gilligan,R.,Thomson,S.,Bound,J.,McCann,J.,和W.Stevens,“IPv6的基本套接字接口扩展”,RFC 3493,2003年2月。
[RFC3542] Stevens, W., Thomas, M., Nordmark, E., and T. Jinmei, "Advanced Sockets Application Program Interface (API) for IPv6", RFC 3542, May 2003.
[RFC3542]Stevens,W.,Thomas,M.,Nordmark,E.,和T.Jinmei,“IPv6的高级套接字应用程序接口(API)”,RFC 3542,2003年5月。
[BIS] Tsuchiya, K., Higuchi, H., and Y. Atarashi, "Dual Stack Hosts using the "Bump-In-the-Stack" Technique (BIS)", RFC 2767, February 2000.
[BIS]Tsuchiya,K.,Higuchi,H.,和Y.Atarashi,“使用“堆栈中的凹凸”技术(BIS)的双堆栈主机”,RFC 2767,2000年2月。
[BIA] Lee, S., Shin, M-K., Kim, Y-J., Nordmark, E., and A. Durand, "Dual Stack Hosts Using "Bump-in-the-API" (BIA)", RFC 3338, October 2002.
[BIA]Lee,S.,Shin,M-K.,Kim,Y-J.,Nordmark,E.,和A.Durand,“使用“API中的凹凸”的双堆栈主机”(BIA),RFC 3338,2002年10月。
[RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, December 1998.
[RFC2460]Deering,S.和R.Hinden,“互联网协议,第6版(IPv6)规范”,RFC 2460,1998年12月。
[RFC3484] Draves, R., "Default Address Selection for Internet Protocol version 6 (IPv6)", RFC 3484, February 2003.
[RFC3484]Draves,R.,“互联网协议版本6(IPv6)的默认地址选择”,RFC 3484,2003年2月。
[RFC3513] Hinden, R. and S. Deering, "Internet Protocol Version 6 (IPv6) Addressing Architecture", RFC 3513, April 2003.
[RFC3513]Hinden,R.和S.Deering,“互联网协议版本6(IPv6)寻址体系结构”,RFC 3513,2003年4月。
[2893BIS] Nordmark, E. and R. E. Gilligan, "Basic Transition Mechanisms for IPv6 Hosts and Routers", Work in Progress, June 2004.
[2893之二]Nordmark,E.和R.E.Gilligan,“IPv6主机和路由器的基本转换机制”,正在进行的工作,2004年6月。
[RFC2133] Gilligan, R., Thomson, S., Bound, J., and W. Stevens, "Basic Socket Interface Extensions for IPv6", RFC 2133, April 1997.
[RFC2133]Gilligan,R.,Thomson,S.,Bound,J.,和W.Stevens,“IPv6的基本套接字接口扩展”,RFC 21331997年4月。
[RFC2732] Hinden, R., Carpenter, B., and L. Masinter, "Format for Literal IPv6 Addresses in URL's", RFC 2732, December 1999.
[RFC2732]Hinden,R.,Carpenter,B.,和L.Masinter,“URL中文字IPv6地址的格式”,RFC 2732,1999年12月。
[RFC2821] Klensin, J., "Simple Mail Transfer Protocol", RFC 2821, April 2001.
[RFC2821]Klensin,J.,“简单邮件传输协议”,RFC 28212001年4月。
[TextRep] Main, A., "Textual Representation of IPv4 and IPv6 Addresses", Work in Progress, October 2003.
[TextRep]Main,A.,“IPv4和IPv6地址的文本表示”,正在进行的工作,2003年10月。
[NAT-PT] Tsirtsis, G. and P. Srisuresh, "Network Address Translation - Protocol Translation (NAT-PT)", RFC 2766, February 2000.
[NAT-PT]Tsirtsis,G.和P.Srisuresh,“网络地址转换-协议转换(NAT-PT)”,RFC 2766,2000年2月。
[DNSTRANS] Durand, A. and J. Ihren, "DNS IPv6 Transport Operational Guidelines", BCP 91, RFC 3901, September 2004.
[DNSTRANS]Durand,A.和J.Ihren,“DNS IPv6传输操作指南”,BCP 91,RFC 3901,2004年9月。
[DNSOPV6] Durand, A., Ihren, J. and P. Savola, "Operational Considerations and Issues with IPv6 DNS", Work in Progress, May 2004.
[DNSOPV6]Durand,A.,Ihren,J.和P.Savola,“IPv6 DNS的操作注意事项和问题”,正在进行的工作,2004年5月。
[AF-APP] Hagino, J., "Implementing AF-independent application", http://www.kame.net/newsletter/19980604/, 2001.
[AF-APP]Hagino,J.,“实现AF独立应用程序”,http://www.kame.net/newsletter/19980604/, 2001.
[V6MAPPED] Hagino, J., "IPv4 mapped address considered harmful", Work in Progress, April 2002.
[V6MAPPED]Hagino,J.,“被认为有害的IPv4映射地址”,正在进行的工作,2002年4月。
[IP-GGF] Chown, T., Bound, J., Jiang, S. and P. O'Hanlon, "Guidelines for IP version independence in GGF specifications", Global Grid Forum(GGF) Documentation, work in Progress, September 2003.
[IP-GGF]Chown,T.,Bound,J.,Jiang,S.和P.O'Hanlon,“GGF规范中的IP版本独立性指南”,全球网格论坛(GGF)文件,正在进行的工作,2003年9月。
[Embed-RP] Savola, P. and B. Haberman, "Embedding the Rendezvous Point (RP) Address in an IPv6 Multicast Address", RFC 3956, November 2004.
[Embedded RP]Savola,P.和B.Haberman,“将集合点(RP)地址嵌入IPv6多播地址”,RFC 3956,2004年11月。
[RFC3306] Haberman, B. and D. Thaler, "Unicast-Prefix-based IPv6 Multicast Addresses", RFC 3306, August 2002.
[RFC3306]Haberman,B.和D.Thaler,“基于单播前缀的IPv6多播地址”,RFC3306,2002年8月。
[RFC3678] Thaler, D., Fenner, B., and B. Quinn, "Socket Interface Extensions for Multicast Source Filters, RFC 3678, January 2004.
[RFC3678]Thaler,D.,Fenner,B.,和B.Quinn,“多播源过滤器的套接字接口扩展”,RFC 3678,2004年1月。
[MUL-GW] Venaas, S., "An IPv4 - IPv6 multicast gateway", Work in Progress, February 2003.
[MUL-GW]Venaas,S.,“IPv4-IPv6多播网关”,正在进行的工作,2003年2月。
[PRT] Castro, E. M., "Programming guidelines on transition to IPv6 LONG project", Work in Progress, January 2003.
[PRT]Castro,E.M.,“过渡到IPv6长期项目的规划指南”,进展中的工作,2003年1月。
Appendix A. Other Binary/Presentation Format Conversions
附录A.其他二进制/表示格式转换
Section 6.2.3 describes the preferred way to perform binary/presentation format conversions; these can also be done by using inet_pton() and inet_ntop() and by writing protocol-dependent code. This approach is not recommended, but it is provided here for reference and comparison.
第6.2.3节描述了执行二进制/表示格式转换的首选方式;也可以通过使用inet_pton()和inet_ntop()以及编写依赖于协议的代码来完成这些操作。不推荐使用这种方法,但此处提供此方法以供参考和比较。
Note that inet_ntop()/inet_pton() lose the scope identifier (if used, e.g., with link-local addresses) in the conversions, contrary to the getaddrinfo()/getnameinfo() functions.
请注意,inet_ntop()/inet_pton()在转换过程中会丢失作用域标识符(如果与链接本地地址一起使用),这与getaddrinfo()/getnameinfo()函数相反。
Conversions from network address structure to presentation format can be written as follows:
从网络地址结构到表示格式的转换可以编写如下:
struct sockaddr_storage ss; char addrStr[INET6_ADDRSTRLEN];
struct sockaddr_storage ss; char addrStr[INET6_ADDRSTRLEN];
/* fill ss structure */
/* fill ss structure */
switch (ss.ss_family) {
开关(ss.ss_系列){
case AF_INET: inet_ntop(ss.ss_family, &((struct sockaddr_in *)&ss)->sin_addr, addrStr, sizeof(addrStr)); break;
case AF_INET: inet_ntop(ss.ss_family, &((struct sockaddr_in *)&ss)->sin_addr, addrStr, sizeof(addrStr)); break;
case AF_INET6: inet_ntop(ss.ss_family, &((struct sockaddr_in6 *)&ss)->sin6_addr, addrStr, sizeof(addrStr));
case AF_INET6: inet_ntop(ss.ss_family, &((struct sockaddr_in6 *)&ss)->sin6_addr, addrStr, sizeof(addrStr));
break;
打破
default: /* handle unknown family */ }
default: /* handle unknown family */ }
Note that, the destination buffer addrStr should be long enough to contain the presentation address format: INET_ADDRSTRLEN for IPv4 and INET6_ADDRSTRLEN for IPv6. As INET6_ADDRSTRLEN is longer than INET_ADDRSTRLEN, the first one is used as the destination buffer length.
请注意,目标缓冲区addrStr的长度应足以包含表示地址格式:IPv4的INET_ADDRSTRLEN和IPv6的INET6_ADDRSTRLEN。由于INET6_ADDRSTRLEN比INET_ADDRSTRLEN长,第一个用作目标缓冲区长度。
Conversions from presentation format to network address structure can be written as follows:
从表示格式到网络地址结构的转换可以编写如下:
struct sockaddr_storage ss; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; char addrStr[INET6_ADDRSTRLEN];
struct sockaddr_storage ss; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; char addrStr[INET6_ADDRSTRLEN];
/* fill addrStr buffer and ss.ss_family */
/* fill addrStr buffer and ss.ss_family */
switch (ss.ss_family) { case AF_INET: sin = (struct sockaddr_in *)&ss; inet_pton(ss.ss_family, addrStr, (sockaddr *)&sin->sin_addr)); break;
switch (ss.ss_family) { case AF_INET: sin = (struct sockaddr_in *)&ss; inet_pton(ss.ss_family, addrStr, (sockaddr *)&sin->sin_addr)); break;
case AF_INET6: sin6 = (struct sockaddr_in6 *)&ss; inet_pton(ss.ss_family, addrStr, (sockaddr *)&sin6->sin6_addr); break;
case AF_INET6: sin6 = (struct sockaddr_in6 *)&ss; inet_pton(ss.ss_family, addrStr, (sockaddr *)&sin6->sin6_addr); break;
default: /* handle unknown family */ }
default: /* handle unknown family */ }
Note that, the address family of the presentation format must be known.
请注意,表示格式的地址族必须是已知的。
Authors' Addresses
作者地址
Myung-Ki Shin ETRI/NIST 820 West Diamond Avenue Gaithersburg, MD 20899, USA
Myung Ki Shin ETRI/NIST美国马里兰州盖瑟斯堡西钻石大道820号,邮编20899
Phone: +1 301 975-3613 Fax: +1 301 590-0932 EMail: mshin@nist.gov
Phone: +1 301 975-3613 Fax: +1 301 590-0932 EMail: mshin@nist.gov
Yong-Guen Hong ETRI PEC 161 Gajeong-Dong, Yuseong-Gu, Daejeon 305-350, Korea
Yong Guen Hong ETRI PEC 161韩国大田裕成谷Gajeong Dong,邮编305-350
Phone: +82 42 860 6447 Fax: +82 42 861 5404 EMail: yghong@pec.etri.re.kr
Phone: +82 42 860 6447 Fax: +82 42 861 5404 EMail: yghong@pec.etri.re.kr
Jun-ichiro itojun HAGINO Research Laboratory, Internet Initiative Japan Inc. Takebashi Yasuda Bldg., 3-13 Kanda Nishiki-cho, Chiyoda-ku,Tokyo 101-0054, JAPAN
Jun ichiro itojun HAGINO研究实验室,互联网倡议日本公司,日本东京千代田区神田西池町3-13号竹桥安田大厦,101-0054
Phone: +81-3-5259-6350 Fax: +81-3-5259-6351 EMail: itojun@iijlab.net
Phone: +81-3-5259-6350 Fax: +81-3-5259-6351 EMail: itojun@iijlab.net
Pekka Savola CSC/FUNET Espoo, Finland
佩卡·萨沃拉CSC/FUNET Espoo,芬兰
EMail: psavola@funet.fi
EMail: psavola@funet.fi
Eva M. Castro Rey Juan Carlos University (URJC) Departamento de Informatica, Estadistica y Telematica C/Tulipan s/n 28933 Madrid - SPAIN
伊娃·M·卡斯特罗·雷伊·胡安·卡洛斯大学(URJC)信息学系,Estadistica and Telematica C/Tulipan s/n 28933马德里-西班牙
EMail: eva@gsyc.escet.urjc.es
EMail: eva@gsyc.escet.urjc.es
Full Copyright Statement
完整版权声明
Copyright (C) The Internet Society (2005).
版权所有(C)互联网协会(2005年)。
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
本文件受BCP 78中包含的权利、许可和限制的约束,除其中规定外,作者保留其所有权利。
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
本文件及其包含的信息是按“原样”提供的,贡献者、他/她所代表或赞助的组织(如有)、互联网协会和互联网工程任务组不承担任何明示或暗示的担保,包括但不限于任何保证,即使用本文中的信息不会侵犯任何权利,或对适销性或特定用途适用性的任何默示保证。
Intellectual Property
知识产权
The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.
IETF对可能声称与本文件所述技术的实施或使用有关的任何知识产权或其他权利的有效性或范围,或此类权利下的任何许可可能或可能不可用的程度,不采取任何立场;它也不表示它已作出任何独立努力来确定任何此类权利。有关RFC文件中权利的程序信息,请参见BCP 78和BCP 79。
Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.
向IETF秘书处披露的知识产权副本和任何许可证保证,或本规范实施者或用户试图获得使用此类专有权利的一般许可证或许可的结果,可从IETF在线知识产权存储库获取,网址为http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.
IETF邀请任何相关方提请其注意任何版权、专利或专利申请,或其他可能涵盖实施本标准所需技术的专有权利。请将信息发送至IETF的IETF-ipr@ietf.org.
Acknowledgement
确认
Funding for the RFC Editor function is currently provided by the Internet Society.
RFC编辑功能的资金目前由互联网协会提供。