Network Working Group                                        R. Gilligan
Request for Comments: 3493                                Intransa, Inc.
Obsoletes: 2553                                               S. Thomson
Category: Informational                                            Cisco
                                                                J. Bound
                                                               J. McCann
                                                         Hewlett-Packard
                                                              W. Stevens
                                                           February 2003
        
Network Working Group                                        R. Gilligan
Request for Comments: 3493                                Intransa, Inc.
Obsoletes: 2553                                               S. Thomson
Category: Informational                                            Cisco
                                                                J. Bound
                                                               J. McCann
                                                         Hewlett-Packard
                                                              W. Stevens
                                                           February 2003
        

Basic Socket Interface Extensions for IPv6

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 (2003). All Rights Reserved.

版权所有(C)互联网协会(2003年)。版权所有。

Abstract

摘要

The de facto standard Application Program Interface (API) for TCP/IP applications is the "sockets" interface. Although this API was developed for Unix in the early 1980s it has also been implemented on a wide variety of non-Unix systems. TCP/IP applications written using the sockets API have in the past enjoyed a high degree of portability and we would like the same portability with IPv6 applications. But changes are required to the sockets API to support IPv6 and this memo describes these changes. These include a new socket address structure to carry IPv6 addresses, new address conversion functions, and some new socket options. These extensions are designed to provide access to the basic IPv6 features required by TCP and UDP applications, including multicasting, while introducing a minimum of change into the system and providing complete compatibility for existing IPv4 applications. Additional extensions for advanced IPv6 features (raw sockets and access to the IPv6 extension headers) are defined in another document.

TCP/IP应用程序的实际标准应用程序接口(API)是“套接字”接口。尽管此API是在20世纪80年代早期为Unix开发的,但它也已在各种非Unix系统上实现。使用sockets API编写的TCP/IP应用程序在过去具有高度的可移植性,我们希望IPv6应用程序具有同样的可移植性。但是需要对套接字API进行更改以支持IPv6,本备忘录描述了这些更改。其中包括用于承载IPv6地址的新套接字地址结构、新的地址转换函数和一些新的套接字选项。这些扩展旨在提供对TCP和UDP应用程序所需的基本IPv6功能(包括多播)的访问,同时将对系统的更改降至最低,并为现有IPv4应用程序提供完全的兼容性。高级IPv6功能的其他扩展(原始套接字和对IPv6扩展头的访问)在另一个文档中定义。

Table of Contents

目录

   1.  Introduction................................................3
   2.  Design Considerations.......................................4
       2.1  What Needs to be Changed...............................4
       2.2  Data Types.............................................6
       2.3  Headers................................................6
       2.4  Structures.............................................6
   3.  Socket Interface............................................6
       3.1  IPv6 Address Family and Protocol Family................6
       3.2  IPv6 Address Structure.................................7
       3.3  Socket Address Structure for 4.3BSD-Based Systems......7
       3.4  Socket Address Structure for 4.4BSD-Based Systems......9
       3.5  The Socket Functions...................................9
       3.6  Compatibility with IPv4 Applications..................10
       3.7  Compatibility with IPv4 Nodes.........................11
       3.8  IPv6 Wildcard Address.................................11
       3.9  IPv6 Loopback Address.................................13
       3.10 Portability Additions.................................14
   4.  Interface Identification...................................16
       4.1  Name-to-Index.........................................17
       4.2  Index-to-Name.........................................17
       4.3  Return All Interface Names and Indexes................18
       4.4  Free Memory...........................................18
   5.  Socket Options.............................................18
       5.1  Unicast Hop Limit.....................................19
       5.2  Sending and Receiving Multicast Packets...............19
       5.3  IPV6_V6ONLY option for AF_INET6 Sockets...............22
   6.  Library Functions..........................................22
       6.1  Protocol-Independent Nodename and
            Service Name Translation..............................23
       6.2  Socket Address Structure to Node Name
            and Service Name......................................28
       6.3  Address Conversion Functions..........................31
       6.4  Address Testing Macros................................33
   7.  Summary of New Definitions.................................33
   8.  Security Considerations....................................35
   9.  Changes from RFC 2553......................................35
   10. Acknowledgments............................................36
   11. References.................................................37
   12. Authors' Addresses.........................................38
   13. Full Copyright Statement...................................39
        
   1.  Introduction................................................3
   2.  Design Considerations.......................................4
       2.1  What Needs to be Changed...............................4
       2.2  Data Types.............................................6
       2.3  Headers................................................6
       2.4  Structures.............................................6
   3.  Socket Interface............................................6
       3.1  IPv6 Address Family and Protocol Family................6
       3.2  IPv6 Address Structure.................................7
       3.3  Socket Address Structure for 4.3BSD-Based Systems......7
       3.4  Socket Address Structure for 4.4BSD-Based Systems......9
       3.5  The Socket Functions...................................9
       3.6  Compatibility with IPv4 Applications..................10
       3.7  Compatibility with IPv4 Nodes.........................11
       3.8  IPv6 Wildcard Address.................................11
       3.9  IPv6 Loopback Address.................................13
       3.10 Portability Additions.................................14
   4.  Interface Identification...................................16
       4.1  Name-to-Index.........................................17
       4.2  Index-to-Name.........................................17
       4.3  Return All Interface Names and Indexes................18
       4.4  Free Memory...........................................18
   5.  Socket Options.............................................18
       5.1  Unicast Hop Limit.....................................19
       5.2  Sending and Receiving Multicast Packets...............19
       5.3  IPV6_V6ONLY option for AF_INET6 Sockets...............22
   6.  Library Functions..........................................22
       6.1  Protocol-Independent Nodename and
            Service Name Translation..............................23
       6.2  Socket Address Structure to Node Name
            and Service Name......................................28
       6.3  Address Conversion Functions..........................31
       6.4  Address Testing Macros................................33
   7.  Summary of New Definitions.................................33
   8.  Security Considerations....................................35
   9.  Changes from RFC 2553......................................35
   10. Acknowledgments............................................36
   11. References.................................................37
   12. Authors' Addresses.........................................38
   13. Full Copyright Statement...................................39
        
1. Introduction
1. 介绍

While IPv4 addresses are 32 bits long, IPv6 addresses are 128 bits long. The socket interface makes the size of an IP address quite visible to an application; virtually all TCP/IP applications for BSD-based systems have knowledge of the size of an IP address. Those parts of the API that expose the addresses must be changed to accommodate the larger IPv6 address size. IPv6 also introduces new features, some of which must be made visible to applications via the API. This memo defines a set of extensions to the socket interface to support the larger address size and new features of IPv6. It defines "basic" extensions that are of use to a broad range of applications. A companion document, the "advanced" API [4], covers extensions that are of use to more specialized applications, examples of which include routing daemons, and the "ping" and "traceroute" utilities.

IPv4地址的长度为32位,IPv6地址的长度为128位。套接字接口使IP地址的大小对应用程序非常可见;几乎所有基于BSD系统的TCP/IP应用程序都知道IP地址的大小。必须更改API中暴露地址的部分,以适应更大的IPv6地址大小。IPv6还引入了一些新功能,其中一些功能必须通过API对应用程序可见。此备忘录定义了套接字接口的一组扩展,以支持更大的地址大小和IPv6的新功能。它定义了可用于广泛应用程序的“基本”扩展。附带文档“advanced”API[4]介绍了用于更专业应用程序的扩展,例如路由守护进程、“ping”和“traceroute”实用程序。

The development of this API was started in 1994 in the IETF IPng working group. The API has evolved over the years, published first in RFC 2133, then again in RFC 2553, and reaching its final form in this document.

该API的开发始于1994年的IETF IPng工作组。API经过多年的发展,首先在RFC 2133中发布,然后在RFC 2553中再次发布,并在本文档中达到最终形式。

As the API matured and stabilized, it was incorporated into the Open Group's Networking Services (XNS) specification, issue 5.2, which was subsequently incorporated into a joint Open Group/IEEE/ISO standard [3].

随着API的成熟和稳定,它被纳入了开放集团的网络服务(XNS)规范第5.2版,随后被纳入了开放集团/IEEE/ISO联合标准[3]。

Effort has been made to ensure that this document and [3] contain the same information with regard to the API definitions. However, the reader should note that this document is for informational purposes only, and that the official standard specification of the sockets API is [3].

已努力确保本文件和[3]包含与API定义相关的相同信息。但是,读者应注意,本文档仅供参考,sockets API的官方标准规范为[3]。

It is expected that any future standardization work on this API would be done by the Open Group Base Working Group [6].

预计该API的任何未来标准化工作都将由开放组基础工作组完成[6]。

It should also be noted that this document describes only those portions of the API needed for IPv4 and IPv6 communications. Other potential uses of the API, for example the use of getaddrinfo() and getnameinfo() with the AF_UNIX address family, are beyond the scope of this document.

还应注意,本文档仅描述IPv4和IPv6通信所需的API部分。API的其他潜在用途,例如在AF_UNIX地址系列中使用getaddrinfo()和getnameinfo(),超出了本文档的范围。

2. Design Considerations
2. 设计考虑

There are a number of important considerations in designing changes to this well-worn API:

在设计对这一老旧API的更改时,有许多重要的考虑因素:

- The API changes should provide both source and binary compatibility for programs written to the original API. That is, existing program binaries should continue to operate when run on a system supporting the new API. In addition, existing applications that are re-compiled and run on a system supporting the new API should continue to operate. Simply put, the API changes for IPv6 should not break existing programs. An additional mechanism for implementations to verify this is to verify the new symbols are protected by Feature Test Macros as described in [3]. (Such Feature Test Macros are not defined by this RFC.)

- API更改应为写入原始API的程序提供源代码和二进制兼容性。也就是说,当在支持新API的系统上运行时,现有的程序二进制文件应该继续运行。此外,在支持新API的系统上重新编译和运行的现有应用程序应继续运行。简言之,IPv6的API更改不应破坏现有程序。实现验证这一点的另一个机制是验证新符号是否受到[3]中所述的功能测试宏的保护。(此RFC未定义此类功能测试宏。)

- The changes to the API should be as small as possible in order to simplify the task of converting existing IPv4 applications to IPv6.

- 为了简化将现有IPv4应用程序转换为IPv6的任务,对API的更改应该尽可能小。

- Where possible, applications should be able to use this API to interoperate with both IPv6 and IPv4 hosts. Applications should not need to know which type of host they are communicating with.

- 在可能的情况下,应用程序应该能够使用此API与IPv6和IPv4主机进行互操作。应用程序不需要知道它们正在与哪种类型的主机通信。

- IPv6 addresses carried in data structures should be 64-bit aligned. This is necessary in order to obtain optimum performance on 64-bit machine architectures.

- 数据结构中携带的IPv6地址应为64位对齐。为了在64位机器体系结构上获得最佳性能,这是必需的。

Because of the importance of providing IPv4 compatibility in the API, these extensions are explicitly designed to operate on machines that provide complete support for both IPv4 and IPv6. A subset of this API could probably be designed for operation on systems that support only IPv6. However, this is not addressed in this memo.

由于在API中提供IPv4兼容性的重要性,这些扩展被明确设计为在同时提供IPv4和IPv6完全支持的计算机上运行。此API的一个子集可能设计用于仅支持IPv6的系统上的操作。然而,本备忘录并未提及这一点。

2.1 What Needs to be Changed
2.1 需要改变什么

The socket interface API consists of a few distinct components:

套接字接口API由几个不同的组件组成:

- Core socket functions.

- 核心套接字功能。

- Address data structures.

- 地址数据结构。

- Name-to-address translation functions.

- 名称地址转换功能。

- Address conversion functions.

- 地址转换函数。

The core socket functions -- those functions that deal with such things as setting up and tearing down TCP connections, and sending and receiving UDP packets -- were designed to be transport independent. Where protocol addresses are passed as function arguments, they are carried via opaque pointers. A protocol-specific address data structure is defined for each protocol that the socket functions support. Applications must cast pointers to these protocol-specific address structures into pointers to the generic "sockaddr" address structure when using the socket functions. These functions need not change for IPv6, but a new IPv6-specific address data structure is needed.

核心套接字函数——这些函数处理诸如设置和断开TCP连接以及发送和接收UDP数据包之类的事情——被设计为独立于传输。当协议地址作为函数参数传递时,它们通过不透明指针携带。为套接字函数支持的每个协议定义了特定于协议的地址数据结构。当使用套接字函数时,应用程序必须将指向这些特定于协议的地址结构的指针强制转换为指向通用“sockaddr”地址结构的指针。IPv6不需要更改这些功能,但需要新的IPv6特定地址数据结构。

The "sockaddr_in" structure is the protocol-specific data structure for IPv4. This data structure actually includes 8-octets of unused space, and it is tempting to try to use this space to adapt the sockaddr_in structure to IPv6. Unfortunately, the sockaddr_in structure is not large enough to hold the 16-octet IPv6 address as well as the other information (address family and port number) that is needed. So a new address data structure must be defined for IPv6.

“sockaddr_in”结构是IPv4的特定于协议的数据结构。这个数据结构实际上包含8个八位字节的未使用空间,尝试使用这个空间来将sockaddr_in结构调整到IPv6是很有诱惑力的。不幸的是,sockaddr_in结构不够大,无法容纳16个八位组的IPv6地址以及所需的其他信息(地址系列和端口号)。因此,必须为IPv6定义新的地址数据结构。

IPv6 addresses are scoped [2] so they could be link-local, site, organization, global, or other scopes at this time undefined. To support applications that want to be able to identify a set of interfaces for a specific scope, the IPv6 sockaddr_in structure must support a field that can be used by an implementation to identify a set of interfaces identifying the scope for an IPv6 address.

IPv6地址的作用域为[2],因此此时它们可能是链接本地、站点、组织、全局或其他未定义的作用域。为了支持希望能够识别特定作用域的一组接口的应用程序,IPv6 SockAddru in结构必须支持一个字段,实现可以使用该字段来识别识别IPv6地址作用域的一组接口。

The IPv4 name-to-address translation functions in the socket interface are gethostbyname() and gethostbyaddr(). These are left as is, and new functions are defined which support both IPv4 and IPv6.

套接字接口中的IPv4名称到地址转换函数是gethostbyname()和gethostbyaddr()。这些功能保持不变,并定义了支持IPv4和IPv6的新功能。

The IPv4 address conversion functions -- inet_ntoa() and inet_addr() -- convert IPv4 addresses between binary and printable form. These functions are quite specific to 32-bit IPv4 addresses. We have designed two analogous functions that convert both IPv4 and IPv6 addresses, and carry an address type parameter so that they can be extended to other protocol families as well.

IPv4地址转换函数inet_ntoa()和inet_addr()在二进制和可打印形式之间转换IPv4地址。这些函数非常特定于32位IPv4地址。我们设计了两个类似的函数,它们转换IPv4和IPv6地址,并带有地址类型参数,以便它们也可以扩展到其他协议系列。

Finally, a few miscellaneous features are needed to support IPv6. A new interface is needed to support the IPv6 hop limit header field. New socket options are needed to control the sending and receiving of IPv6 multicast packets.

最后,需要一些其他特性来支持IPv6。需要一个新接口来支持IPv6跃点限制标头字段。需要新的套接字选项来控制IPv6多播数据包的发送和接收。

The socket interface will be enhanced in the future to provide access to other IPv6 features. Some of these extensions are described in [4].

套接字接口将在将来得到增强,以提供对其他IPv6功能的访问。[4]中描述了其中一些扩展。

2.2 Data Types
2.2 数据类型

The data types of the structure elements given in this memo are intended to track the relevant standards. uintN_t means an unsigned integer of exactly N bits (e.g., uint16_t). The sa_family_t and in_port_t types are defined in [3].

本备忘录中给出的结构元素数据类型旨在跟踪相关标准。uintN_t表示正好为N位的无符号整数(例如uint16_t)。[3]中定义了sa_系列和in_端口类型。

2.3 Headers
2.3 标题

When function prototypes and structures are shown we show the headers that must be #included to cause that item to be defined.

当显示函数原型和结构时,我们会显示必须包含的标题,以便定义该项。

2.4 Structures
2.4 结构

When structures are described the members shown are the ones that must appear in an implementation. Additional, nonstandard members may also be defined by an implementation. As an additional precaution nonstandard members could be verified by Feature Test Macros as described in [3]. (Such Feature Test Macros are not defined by this RFC.)

当描述结构时,显示的成员是必须出现在实现中的成员。其他非标准成员也可以由实现定义。作为额外的预防措施,可以通过[3]中描述的特性测试宏来验证非标准成员。(此RFC未定义此类功能测试宏。)

The ordering shown for the members of a structure is the recommended ordering, given alignment considerations of multibyte members, but an implementation may order the members differently.

考虑到多字节成员的对齐注意事项,结构成员的顺序是推荐的顺序,但是实现可能会以不同的顺序排列成员。

3. Socket Interface
3. 套接字接口

This section specifies the socket interface changes for IPv6.

本节指定IPv6的套接字接口更改。

3.1 IPv6 Address Family and Protocol Family
3.1 IPv6地址族和协议族

A new address family name, AF_INET6, is defined in <sys/socket.h>. The AF_INET6 definition distinguishes between the original sockaddr_in address data structure, and the new sockaddr_in6 data structure.

在<sys/socket.h>中定义了一个新的地址族名称AF_INET6。AF_INET6定义区分了原始地址数据结构中的sockaddr_和新地址数据结构中的sockaddr_。

A new protocol family name, PF_INET6, is defined in <sys/socket.h>. Like most of the other protocol family names, this will usually be defined to have the same value as the corresponding address family name:

<sys/socket.h>中定义了一个新的协议族名称PF_INET6。与大多数其他协议族名称一样,这通常被定义为与相应的地址族名称具有相同的值:

#define PF_INET6 AF_INET6

#定义PF_INET6 AF_INET6

The AF_INET6 is used in the first argument to the socket() function to indicate that an IPv6 socket is being created.

函数socket()的第一个参数中使用了AF_INET6,以指示正在创建IPv6套接字。

3.2 IPv6 Address Structure
3.2 IPv6地址结构

A new in6_addr structure holds a single IPv6 address and is defined as a result of including <netinet/in.h>:

一个新的in6_addr结构包含一个IPv6地址,并定义为包含<netinet/in.h>的结果:

      struct in6_addr {
          uint8_t  s6_addr[16];      /* IPv6 address */
      };
        
      struct in6_addr {
          uint8_t  s6_addr[16];      /* IPv6 address */
      };
        

This data structure contains an array of sixteen 8-bit elements, which make up one 128-bit IPv6 address. The IPv6 address is stored in network byte order.

此数据结构包含16个8位元素的数组,这些元素构成一个128位IPv6地址。IPv6地址以网络字节顺序存储。

The structure in6_addr above is usually implemented with an embedded union with extra fields that force the desired alignment level in a manner similar to BSD implementations of "struct in_addr". Those additional implementation details are omitted here for simplicity.

上面6_addr中的结构通常是通过一个带有额外字段的嵌入式联合来实现的,这些字段以类似于“struct in_addr”的BSD实现的方式强制实现所需的对齐级别。为了简单起见,这里省略了这些附加的实现细节。

An example is as follows:

例如:

   struct in6_addr {
        union {
            uint8_t  _S6_u8[16];
            uint32_t _S6_u32[4];
            uint64_t _S6_u64[2];
        } _S6_un;
   };
   #define s6_addr _S6_un._S6_u8
        
   struct in6_addr {
        union {
            uint8_t  _S6_u8[16];
            uint32_t _S6_u32[4];
            uint64_t _S6_u64[2];
        } _S6_un;
   };
   #define s6_addr _S6_un._S6_u8
        
3.3 Socket Address Structure for 4.3BSD-Based Systems
3.3 基于4.3BSD系统的套接字地址结构

In the socket interface, a different protocol-specific data structure is defined to carry the addresses for each protocol suite. Each protocol-specific data structure is designed so it can be cast into a protocol-independent data structure -- the "sockaddr" structure. Each has a "family" field that overlays the "sa_family" of the sockaddr data structure. This field identifies the type of the data structure.

在套接字接口中,定义了不同的协议特定数据结构,以承载每个协议套件的地址。每个特定于协议的数据结构都经过了设计,因此可以将其转换为独立于协议的数据结构——“sockaddr”结构。每个都有一个“族”字段,覆盖sockaddr数据结构的“sa_族”。此字段标识数据结构的类型。

The sockaddr_in structure is the protocol-specific address data structure for IPv4. It is used to pass addresses between applications and the system in the socket functions. The following sockaddr_in6 structure holds IPv6 addresses and is defined as a result of including the <netinet/in.h> header:

sockaddr_in结构是IPv4的特定于协议的地址数据结构。它用于在套接字函数中在应用程序和系统之间传递地址。以下sockaddr_in6结构保存IPv6地址,并定义为包含<netinet/in.h>头的结果:

struct sockaddr_in6 {
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 flow information */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};
        
struct sockaddr_in6 {
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 flow information */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};
        

This structure is designed to be compatible with the sockaddr data structure used in the 4.3BSD release.

此结构设计为与4.3BSD版本中使用的sockaddr数据结构兼容。

The sin6_family field identifies this as a sockaddr_in6 structure. This field overlays the sa_family field when the buffer is cast to a sockaddr data structure. The value of this field must be AF_INET6.

sin6_family字段将其标识为sockaddr_in6结构。当缓冲区转换为sockaddr数据结构时,此字段覆盖sa_族字段。此字段的值必须为AF_INET6。

The sin6_port field contains the 16-bit UDP or TCP port number. This field is used in the same way as the sin_port field of the sockaddr_in structure. The port number is stored in network byte order.

sin6_端口字段包含16位UDP或TCP端口号。此字段的使用方式与结构中sockaddr_的sin_port字段相同。端口号以网络字节顺序存储。

The sin6_flowinfo field is a 32-bit field intended to contain flow-related information. The exact way this field is mapped to or from a packet is not currently specified. Until such time as its use is specified, applications should set this field to zero when constructing a sockaddr_in6, and ignore this field in a sockaddr_in6 structure constructed by the system.

sin6_flowinfo字段是一个32位字段,用于包含流量相关信息。当前未指定此字段映射到数据包或从数据包映射到数据包的确切方式。在指定其用途之前,应用程序在构造sockaddr_in6时应将此字段设置为零,并在系统构造的sockaddr_in6结构中忽略此字段。

The sin6_addr field is a single in6_addr structure (defined in the previous section). This field holds one 128-bit IPv6 address. The address is stored in network byte order.

sin6_addr字段是单个in6_addr结构(在上一节中定义)。此字段包含一个128位IPv6地址。地址以网络字节顺序存储。

The ordering of elements in this structure is specifically designed so that when sin6_addr field is aligned on a 64-bit boundary, the start of the structure will also be aligned on a 64-bit boundary. This is done for optimum performance on 64-bit architectures.

此结构中元素的顺序是专门设计的,因此当sin6_addr字段在64位边界上对齐时,结构的起点也将在64位边界上对齐。这样做是为了在64位体系结构上获得最佳性能。

The sin6_scope_id field is a 32-bit integer that identifies a set of interfaces as appropriate for the scope [2] of the address carried in the sin6_addr field. The mapping of sin6_scope_id to an interface or set of interfaces is left to implementation and future specifications on the subject of scoped addresses.

sin6_scope_id字段是一个32位整数,它根据sin6_addr字段中地址的作用域[2]来标识一组接口。sin6_scope_id到一个接口或一组接口的映射留待实现和关于作用域地址主题的未来规范处理。

Notice that the sockaddr_in6 structure will normally be larger than the generic sockaddr structure. On many existing implementations the sizeof(struct sockaddr_in) equals sizeof(struct sockaddr), with both being 16 bytes. Any existing code that makes this assumption needs to be examined carefully when converting to IPv6.

请注意,sockaddr_in6结构通常比一般的sockaddr结构大。在许多现有的实现中,sizeof(struct sockaddr_in)等于sizeof(struct sockaddr),两者都是16字节。在转换到IPv6时,需要仔细检查任何做出此假设的现有代码。

3.4 Socket Address Structure for 4.4BSD-Based Systems
3.4 基于4.4BSD系统的套接字地址结构

The 4.4BSD release includes a small, but incompatible change to the socket interface. The "sa_family" field of the sockaddr data structure was changed from a 16-bit value to an 8-bit value, and the space saved used to hold a length field, named "sa_len". The sockaddr_in6 data structure given in the previous section cannot be correctly cast into the newer sockaddr data structure. For this reason, the following alternative IPv6 address data structure is provided to be used on systems based on 4.4BSD. It is defined as a result of including the <netinet/in.h> header.

4.4BSD版本包括对套接字接口的一个小的但不兼容的更改。sockaddr数据结构的“sa_族”字段已从16位值更改为8位值,保存的空间用于保存名为“sa_len”的长度字段。上一节中给出的sockaddr_in6数据结构无法正确转换为较新的sockaddr数据结构。因此,提供了以下替代IPv6地址数据结构,以便在基于4.4BSD的系统上使用。它被定义为包含<netinet/in.h>标题的结果。

struct sockaddr_in6 {
    uint8_t         sin6_len;       /* length of this struct */
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 flow information */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};
        
struct sockaddr_in6 {
    uint8_t         sin6_len;       /* length of this struct */
    sa_family_t     sin6_family;    /* AF_INET6 */
    in_port_t       sin6_port;      /* transport layer port # */
    uint32_t        sin6_flowinfo;  /* IPv6 flow information */
    struct in6_addr sin6_addr;      /* IPv6 address */
    uint32_t        sin6_scope_id;  /* set of interfaces for a scope */
};
        

The only differences between this data structure and the 4.3BSD variant are the inclusion of the length field, and the change of the family field to a 8-bit data type. The definitions of all the other fields are identical to the structure defined in the previous section.

此数据结构与4.3BSD变体之间的唯一区别是包含长度字段,以及将族字段更改为8位数据类型。所有其他字段的定义与上一节中定义的结构相同。

Systems that provide this version of the sockaddr_in6 data structure must also declare SIN6_LEN as a result of including the <netinet/in.h> header. This macro allows applications to determine whether they are being built on a system that supports the 4.3BSD or 4.4BSD variants of the data structure.

由于包含<netinet/in.h>头,提供此版本sockaddr_in6数据结构的系统还必须声明SIN6_LEN。此宏允许应用程序确定它们是否构建在支持数据结构的4.3BSD或4.4BSD变体的系统上。

3.5 The Socket Functions
3.5 套接字功能

Applications call the socket() function to create a socket descriptor that represents a communication endpoint. The arguments to the socket() function tell the system which protocol to use, and what format address structure will be used in subsequent functions. For example, to create an IPv4/TCP socket, applications make the call:

应用程序调用socket()函数来创建表示通信端点的套接字描述符。socket()函数的参数告诉系统要使用哪种协议,以及后续函数将使用哪种格式的地址结构。例如,要创建IPv4/TCP套接字,应用程序进行调用:

      s = socket(AF_INET, SOCK_STREAM, 0);
        
      s = socket(AF_INET, SOCK_STREAM, 0);
        

To create an IPv4/UDP socket, applications make the call:

要创建IPv4/UDP套接字,应用程序将调用:

      s = socket(AF_INET, SOCK_DGRAM, 0);
        
      s = socket(AF_INET, SOCK_DGRAM, 0);
        

Applications may create IPv6/TCP and IPv6/UDP sockets (which may also handle IPv4 communication as described in section 3.7) by simply using the constant AF_INET6 instead of AF_INET in the first argument. For example, to create an IPv6/TCP socket, applications make the call:

应用程序只需在第一个参数中使用常量AF_INET6而不是AF_INET,就可以创建IPv6/TCP和IPv6/UDP套接字(也可以按照第3.7节所述处理IPv4通信)。例如,要创建IPv6/TCP套接字,应用程序进行调用:

      s = socket(AF_INET6, SOCK_STREAM, 0);
        
      s = socket(AF_INET6, SOCK_STREAM, 0);
        

To create an IPv6/UDP socket, applications make the call:

要创建IPv6/UDP套接字,应用程序将调用:

      s = socket(AF_INET6, SOCK_DGRAM, 0);
        
      s = socket(AF_INET6, SOCK_DGRAM, 0);
        

Once the application has created a AF_INET6 socket, it must use the sockaddr_in6 address structure when passing addresses in to the system. The functions that the application uses to pass addresses into the system are:

一旦应用程序创建了AF_INET6套接字,它在向系统传递地址时必须使用sockaddr_in6地址结构。应用程序用于将地址传递到系统的功能包括:

bind() connect() sendmsg() sendto()

绑定()连接()发送消息()发送到()

The system will use the sockaddr_in6 address structure to return addresses to applications that are using AF_INET6 sockets. The functions that return an address from the system to an application are:

系统将使用sockaddr_in6地址结构将地址返回给使用AF_INET6套接字的应用程序。从系统向应用程序返回地址的功能有:

accept() recvfrom() recvmsg() getpeername() getsockname()

accept()recvfrom()recvmsg()getpeername()getsockname()

No changes to the syntax of the socket functions are needed to support IPv6, since all of the "address carrying" functions use an opaque address pointer, and carry an address length as a function argument.

支持IPv6不需要更改套接字函数的语法,因为所有“地址承载”函数都使用不透明的地址指针,并将地址长度作为函数参数。

3.6 Compatibility with IPv4 Applications
3.6 与IPv4应用程序的兼容性

In order to support the large base of applications using the original API, system implementations must provide complete source and binary compatibility with the original API. This means that systems must continue to support AF_INET sockets and the sockaddr_in address structure. Applications must be able to create IPv4/TCP and IPv4/UDP sockets using the AF_INET constant in the socket() function, as

为了支持大量使用原始API的应用程序,系统实现必须与原始API提供完整的源代码和二进制兼容性。这意味着系统必须继续支持AF_INET套接字和sockaddr_in地址结构。应用程序必须能够使用socket()函数中的AF_INET常量创建IPv4/TCP和IPv4/UDP套接字,如下所示

described in the previous section. Applications should be able to hold a combination of IPv4/TCP, IPv4/UDP, IPv6/TCP and IPv6/UDP sockets simultaneously within the same process.

如前一节所述。应用程序应该能够在同一进程中同时持有IPv4/TCP、IPv4/UDP、IPv6/TCP和IPv6/UDP套接字的组合。

Applications using the original API should continue to operate as they did on systems supporting only IPv4. That is, they should continue to interoperate with IPv4 nodes.

使用原始API的应用程序应继续在仅支持IPv4的系统上运行。也就是说,它们应该继续与IPv4节点进行互操作。

3.7 Compatibility with IPv4 Nodes
3.7 与IPv4节点的兼容性

The API also provides a different type of compatibility: the ability for IPv6 applications to interoperate with IPv4 applications. This feature uses the IPv4-mapped IPv6 address format defined in the IPv6 addressing architecture specification [2]. This address format allows the IPv4 address of an IPv4 node to be represented as an IPv6 address. The IPv4 address is encoded into the low-order 32 bits of the IPv6 address, and the high-order 96 bits hold the fixed prefix 0:0:0:0:0:FFFF. IPv4-mapped addresses are written as follows:

API还提供了一种不同类型的兼容性:IPv6应用程序能够与IPv4应用程序进行互操作。此功能使用IPv6寻址体系结构规范[2]中定义的IPv4映射IPv6地址格式。此地址格式允许将IPv4节点的IPv4地址表示为IPv6地址。IPv4地址被编码到IPv6地址的低阶32位,高阶96位保留固定前缀0:0:0:0:FFFF。IPv4映射地址的写入方式如下:

      ::FFFF:<IPv4-address>
        
      ::FFFF:<IPv4-address>
        

These addresses can be generated automatically by the getaddrinfo() function, as described in Section 6.1.

如第6.1节所述,这些地址可以由getaddrinfo()函数自动生成。

Applications may use AF_INET6 sockets to open TCP connections to IPv4 nodes, or send UDP packets to IPv4 nodes, by simply encoding the destination's IPv4 address as an IPv4-mapped IPv6 address, and passing that address, within a sockaddr_in6 structure, in the connect() or sendto() call. When applications use AF_INET6 sockets to accept TCP connections from IPv4 nodes, or receive UDP packets from IPv4 nodes, the system returns the peer's address to the application in the accept(), recvfrom(), or getpeername() call using a sockaddr_in6 structure encoded this way.

应用程序可以使用AF_INET6套接字打开到IPv4节点的TCP连接,或向IPv4节点发送UDP数据包,方法是将目标的IPv4地址编码为IPv4映射的IPv6地址,并在connect()或sendto()调用中在sockaddr_in6结构中传递该地址。当应用程序使用AF_INET6套接字接受来自IPv4节点的TCP连接,或从IPv4节点接收UDP数据包时,系统使用以这种方式编码的sockaddr_in6结构在accept()、recvfrom()或getpeername()调用中将对等方的地址返回给应用程序。

Few applications will likely need to know which type of node they are interoperating with. However, for those applications that do need to know, the IN6_IS_ADDR_V4MAPPED() macro, defined in Section 6.4, is provided.

很少有应用程序需要知道它们正在与哪种类型的节点进行互操作。但是,对于那些确实需要知道的应用程序,提供了第6.4节中定义的IN6_IS_ADDR_V4MAPPED()宏。

3.8 IPv6 Wildcard Address
3.8 IPv6通配符地址

While the bind() function allows applications to select the source IP address of UDP packets and TCP connections, applications often want the system to select the source address for them. With IPv4, one specifies the address as the symbolic constant INADDR_ANY (called the "wildcard" address) in the bind() call, or simply omits the bind() entirely.

虽然bind()函数允许应用程序选择UDP数据包和TCP连接的源IP地址,但应用程序通常希望系统为它们选择源地址。对于IPv4,可以在bind()调用中将地址指定为符号常量INADDR_ANY(称为“通配符”地址),或者干脆完全忽略bind()。

Since the IPv6 address type is a structure (struct in6_addr), a symbolic constant can be used to initialize an IPv6 address variable, but cannot be used in an assignment. Therefore systems provide the IPv6 wildcard address in two forms.

由于IPv6地址类型是一种结构(struct in6_addr),符号常量可用于初始化IPv6地址变量,但不能用于赋值。因此,系统以两种形式提供IPv6通配符地址。

The first version is a global variable named "in6addr_any" that is an in6_addr structure. The extern declaration for this variable is defined in <netinet/in.h>:

第一个版本是名为“in6addr_any”的全局变量,它是一个in6_addr结构。此变量的外部声明在<netinet/in.h>中定义:

extern const struct in6_addr in6addr_any;

6地址中的外部常量结构6地址中的任何地址;

Applications use in6addr_any similarly to the way they use INADDR_ANY in IPv4. For example, to bind a socket to port number 23, but let the system select the source address, an application could use the following code:

应用程序使用in6addr\u any的方式与IPv4中使用INADR\u any的方式类似。例如,要将套接字绑定到端口号23,但让系统选择源地址,应用程序可以使用以下代码:

      struct sockaddr_in6 sin6;
       . . .
      sin6.sin6_family = AF_INET6;
      sin6.sin6_flowinfo = 0;
      sin6.sin6_port = htons(23);
      sin6.sin6_addr = in6addr_any;  /* structure assignment */
       . . .
      if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
              . . .
        
      struct sockaddr_in6 sin6;
       . . .
      sin6.sin6_family = AF_INET6;
      sin6.sin6_flowinfo = 0;
      sin6.sin6_port = htons(23);
      sin6.sin6_addr = in6addr_any;  /* structure assignment */
       . . .
      if (bind(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
              . . .
        

The other version is a symbolic constant named IN6ADDR_ANY_INIT and is defined in <netinet/in.h>. This constant can be used to initialize an in6_addr structure:

另一个版本是名为IN6ADDR\u ANY\u INIT的符号常量,在<netinet/in.h>中定义。此常量可用于初始化in6_addr结构:

struct in6_addr anyaddr = IN6ADDR_ANY_INIT;

结构in6\u addr anyaddr=IN6ADDR\u ANY\u INIT;

Note that this constant can be used ONLY at declaration time. It can not be used to assign a previously declared in6_addr structure. For example, the following code will not work:

请注意,此常量只能在声明时使用。它不能用于分配以前在6_addr结构中声明的。例如,以下代码将不起作用:

      /* This is the WRONG way to assign an unspecified address */
      struct sockaddr_in6 sin6;
       . . .
      sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */
        
      /* This is the WRONG way to assign an unspecified address */
      struct sockaddr_in6 sin6;
       . . .
      sin6.sin6_addr = IN6ADDR_ANY_INIT; /* will NOT compile */
        

Be aware that the IPv4 INADDR_xxx constants are all defined in host byte order but the IPv6 IN6ADDR_xxx constants and the IPv6 in6addr_xxx externals are defined in network byte order.

请注意,IPv4 INADDR_xxx常量都是按主机字节顺序定义的,但IPv6 IN6ADDR_xxx常量和IPv6 IN6ADDR_xxx外部是按网络字节顺序定义的。

3.9 IPv6 Loopback Address
3.9 IPv6环回地址

Applications may need to send UDP packets to, or originate TCP connections to, services residing on the local node. In IPv4, they can do this by using the constant IPv4 address INADDR_LOOPBACK in their connect(), sendto(), or sendmsg() call.

应用程序可能需要向驻留在本地节点上的服务发送UDP数据包或发起TCP连接。在IPv4中,他们可以通过在connect()、sendto()或sendmsg()调用中使用常量IPv4地址INADDR_环回来实现这一点。

IPv6 also provides a loopback address to contact local TCP and UDP services. Like the unspecified address, the IPv6 loopback address is provided in two forms -- a global variable and a symbolic constant.

IPv6还提供一个环回地址来联系本地TCP和UDP服务。与未指定的地址一样,IPv6环回地址以两种形式提供——全局变量和符号常量。

The global variable is an in6_addr structure named "in6addr_loopback." The extern declaration for this variable is defined in <netinet/in.h>:

全局变量是名为“in6addr\u loopback”的in6\u addr结构。此变量的外部声明在<netinet/in.h>中定义:

extern const struct in6_addr in6addr_loopback;

6地址6地址环回中的外部常量结构;

Applications use in6addr_loopback as they would use INADDR_LOOPBACK in IPv4 applications (but beware of the byte ordering difference mentioned at the end of the previous section). For example, to open a TCP connection to the local telnet server, an application could use the following code:

应用程序使用in6addr_环回,就像在IPv4应用程序中使用INADDR_环回一样(但请注意上一节末尾提到的字节顺序差异)。例如,要打开到本地telnet服务器的TCP连接,应用程序可以使用以下代码:

   struct sockaddr_in6 sin6;
    . . .
   sin6.sin6_family = AF_INET6;
   sin6.sin6_flowinfo = 0;
   sin6.sin6_port = htons(23);
   sin6.sin6_addr = in6addr_loopback;  /* structure assignment */
    . . .
   if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
           . . .
        
   struct sockaddr_in6 sin6;
    . . .
   sin6.sin6_family = AF_INET6;
   sin6.sin6_flowinfo = 0;
   sin6.sin6_port = htons(23);
   sin6.sin6_addr = in6addr_loopback;  /* structure assignment */
    . . .
   if (connect(s, (struct sockaddr *) &sin6, sizeof(sin6)) == -1)
           . . .
        

The symbolic constant is named IN6ADDR_LOOPBACK_INIT and is defined in <netinet/in.h>. It can be used at declaration time ONLY; for example:

符号常量在6addr\u LOOPBACK\u INIT中命名,并在<netinet/in.h>中定义。只能在申报时使用;例如:

struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT;

结构in6\u addr loopbackaddr=IN6ADDR\u LOOPBACK\u INIT;

Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment to a previously declared IPv6 address variable.

与IN6ADDR_ANY_INIT一样,该常量不能用于对先前声明的IPv6地址变量的赋值。

3.10 Portability Additions
3.10 可移植性增加

One simple addition to the sockets API that can help application writers is the "struct sockaddr_storage". This data structure can simplify writing code that is portable across multiple address families and platforms. This data structure is designed with the following goals.

sockets API的一个简单新增功能是“struct sockaddr_storage”,它可以帮助应用程序编写者。这种数据结构可以简化编写跨多个地址族和平台可移植的代码。此数据结构的设计目标如下。

- Large enough to accommodate all supported protocol-specific address structures.

- 足够大,可以容纳所有受支持的特定于协议的地址结构。

- Aligned at an appropriate boundary so that pointers to it can be cast as pointers to protocol specific address structures and used to access the fields of those structures without alignment problems.

- 在适当的边界对齐,以便指向它的指针可以转换为指向特定于协议的地址结构的指针,并用于访问这些结构的字段,而不会出现对齐问题。

The sockaddr_storage structure contains field ss_family which is of type sa_family_t. When a sockaddr_storage structure is cast to a sockaddr structure, the ss_family field of the sockaddr_storage structure maps onto the sa_family field of the sockaddr structure. When a sockaddr_storage structure is cast as a protocol specific address structure, the ss_family field maps onto a field of that structure that is of type sa_family_t and that identifies the protocol's address family.

sockaddr_存储结构包含类型为sa_family_t的字段ss_family。将sockaddr_存储结构强制转换为sockaddr结构时,sockaddr_存储结构的ss_族字段映射到sockaddr结构的sa_族字段。当sockaddr_存储结构强制转换为协议特定的地址结构时,ss_族字段映射到该结构的类型为sa_族并标识协议地址族的字段上。

An example implementation design of such a data structure would be as follows.

这种数据结构的示例实现设计如下所示。

/*
 * Desired design of maximum size and alignment
 */
#define _SS_MAXSIZE    128  /* Implementation specific max size */
#define _SS_ALIGNSIZE  (sizeof (int64_t))
                         /* Implementation specific desired alignment */
/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE   (_SS_ALIGNSIZE - sizeof (sa_family_t))
#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (sa_family_t) +
                              _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char      __ss_pad1[_SS_PAD1SIZE];
              /* 6 byte pad, this is to make implementation
              /* specific pad up to alignment field that */
              /* follows explicit in the data structure */
    int64_t   __ss_align;     /* field to force desired structure */
               /* storage alignment */
    char      __ss_pad2[_SS_PAD2SIZE];
              /* 112 byte pad to achieve desired size, */
              /* _SS_MAXSIZE value minus size of ss_family */
              /* __ss_pad1, __ss_align fields is 112 */
};
        
/*
 * Desired design of maximum size and alignment
 */
#define _SS_MAXSIZE    128  /* Implementation specific max size */
#define _SS_ALIGNSIZE  (sizeof (int64_t))
                         /* Implementation specific desired alignment */
/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE   (_SS_ALIGNSIZE - sizeof (sa_family_t))
#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (sa_family_t) +
                              _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char      __ss_pad1[_SS_PAD1SIZE];
              /* 6 byte pad, this is to make implementation
              /* specific pad up to alignment field that */
              /* follows explicit in the data structure */
    int64_t   __ss_align;     /* field to force desired structure */
               /* storage alignment */
    char      __ss_pad2[_SS_PAD2SIZE];
              /* 112 byte pad to achieve desired size, */
              /* _SS_MAXSIZE value minus size of ss_family */
              /* __ss_pad1, __ss_align fields is 112 */
};
        
   The above example implementation illustrates a data structure which
   will align on a 64-bit boundary.  An implementation-specific field
   "__ss_align" along with "__ss_pad1" is used to force a 64-bit
   alignment which covers proper alignment good enough for the needs of
   sockaddr_in6 (IPv6), sockaddr_in (IPv4) address data structures.  The
   size of padding field __ss_pad1 depends on the chosen alignment
   boundary.  The size of padding field __ss_pad2 depends on the value
   of overall size chosen for the total size of the structure.  This
   size and alignment are represented in the above example by
   implementation specific (not required) constants _SS_MAXSIZE (chosen
   value 128) and _SS_ALIGNSIZE (with chosen value 8).  Constants
   _SS_PAD1SIZE (derived value 6) and _SS_PAD2SIZE (derived value 112)
   are also for illustration and not required.  The derived values
   assume sa_family_t is 2 bytes.  The implementation specific
   definitions and structure field names above start with an underscore
   to denote implementation private namespace.  Portable code is not
   expected to access or reference those fields or constants.
        
   The above example implementation illustrates a data structure which
   will align on a 64-bit boundary.  An implementation-specific field
   "__ss_align" along with "__ss_pad1" is used to force a 64-bit
   alignment which covers proper alignment good enough for the needs of
   sockaddr_in6 (IPv6), sockaddr_in (IPv4) address data structures.  The
   size of padding field __ss_pad1 depends on the chosen alignment
   boundary.  The size of padding field __ss_pad2 depends on the value
   of overall size chosen for the total size of the structure.  This
   size and alignment are represented in the above example by
   implementation specific (not required) constants _SS_MAXSIZE (chosen
   value 128) and _SS_ALIGNSIZE (with chosen value 8).  Constants
   _SS_PAD1SIZE (derived value 6) and _SS_PAD2SIZE (derived value 112)
   are also for illustration and not required.  The derived values
   assume sa_family_t is 2 bytes.  The implementation specific
   definitions and structure field names above start with an underscore
   to denote implementation private namespace.  Portable code is not
   expected to access or reference those fields or constants.
        

On implementations where the sockaddr data structure includes a "sa_len" field this data structure would look like this:

在sockaddr数据结构包含“sau len”字段的实现中,此数据结构如下所示:

/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE (_SS_ALIGNSIZE -
                            (sizeof (uint8_t) + sizeof (sa_family_t))
#define _SS_PAD2SIZE (_SS_MAXSIZE -
                            (sizeof (uint8_t) + sizeof (sa_family_t) +
                             _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    uint8_t      ss_len;        /* address length */
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char         __ss_pad1[_SS_PAD1SIZE];
                  /* 6 byte pad, this is to make implementation
                  /* specific pad up to alignment field that */
                  /* follows explicit in the data structure */
    int64_t      __ss_align;  /* field to force desired structure */
                  /* storage alignment */
    char         __ss_pad2[_SS_PAD2SIZE];
                  /* 112 byte pad to achieve desired size, */
                  /* _SS_MAXSIZE value minus size of ss_len, */
                  /* __ss_family, __ss_pad1, __ss_align fields is 112 */
};
        
/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE (_SS_ALIGNSIZE -
                            (sizeof (uint8_t) + sizeof (sa_family_t))
#define _SS_PAD2SIZE (_SS_MAXSIZE -
                            (sizeof (uint8_t) + sizeof (sa_family_t) +
                             _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    uint8_t      ss_len;        /* address length */
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char         __ss_pad1[_SS_PAD1SIZE];
                  /* 6 byte pad, this is to make implementation
                  /* specific pad up to alignment field that */
                  /* follows explicit in the data structure */
    int64_t      __ss_align;  /* field to force desired structure */
                  /* storage alignment */
    char         __ss_pad2[_SS_PAD2SIZE];
                  /* 112 byte pad to achieve desired size, */
                  /* _SS_MAXSIZE value minus size of ss_len, */
                  /* __ss_family, __ss_pad1, __ss_align fields is 112 */
};
        
4. Interface Identification
4. 接口标识

This API uses an interface index (a small positive integer) to identify the local interface on which a multicast group is joined (Section 5.2). Additionally, the advanced API [4] uses these same interface indexes to identify the interface on which a datagram is received, or to specify the interface on which a datagram is to be sent.

此API使用接口索引(一个小的正整数)来标识加入多播组的本地接口(第5.2节)。此外,高级API[4]使用这些相同的接口索引来标识接收数据报的接口,或指定发送数据报的接口。

Interfaces are normally known by names such as "le0", "sl1", "ppp2", and the like. On Berkeley-derived implementations, when an interface is made known to the system, the kernel assigns a unique positive integer value (called the interface index) to that interface. These are small positive integers that start at 1. (Note that 0 is never used for an interface index.) There may be gaps so that there is no current interface for a particular positive interface index.

接口通常以诸如“le0”、“sl1”、“ppp2”等名称为人所知。在Berkeley派生的实现中,当系统知道某个接口时,内核会为该接口分配一个唯一的正整数值(称为接口索引)。这些是从1开始的小正整数。(请注意,0从未用于接口索引。)可能存在间隙,因此对于特定的正接口索引,没有当前接口。

This API defines two functions that map between an interface name and index, a third function that returns all the interface names and indexes, and a fourth function to return the dynamic memory allocated by the previous function. How these functions are implemented is

此API定义了两个在接口名称和索引之间映射的函数,第三个函数返回所有接口名称和索引,第四个函数返回前一个函数分配的动态内存。这些功能是如何实现的

left up to the implementation. 4.4BSD implementations can implement these functions using the existing sysctl() function with the NET_RT_IFLIST command. Other implementations may wish to use ioctl() for this purpose.

留待实施。4.4BSD实现可以使用现有的sysctl()函数和NET\u RT\u IFLIST命令来实现这些函数。其他实现可能希望为此使用ioctl()。

4.1 Name-to-Index
4.1 要索引的名称

The first function maps an interface name into its corresponding index.

第一个函数将接口名称映射到其相应的索引中。

      #include <net/if.h>
        
      #include <net/if.h>
        
      unsigned int  if_nametoindex(const char *ifname);
        
      unsigned int  if_nametoindex(const char *ifname);
        

If ifname is the name of an interface, the if_nametoindex() function shall return the interface index corresponding to name ifname; otherwise, it shall return zero. No errors are defined.

如果ifname是接口的名称,则If_nametoindex()函数应返回名称ifname对应的接口索引;否则,它将返回零。未定义任何错误。

4.2 Index-to-Name
4.2 名称索引

The second function maps an interface index into its corresponding name.

第二个函数将接口索引映射到其相应的名称中。

      #include <net/if.h>
        
      #include <net/if.h>
        
      char  *if_indextoname(unsigned int ifindex, char *ifname);
        
      char  *if_indextoname(unsigned int ifindex, char *ifname);
        

When this function is called, the ifname argument shall point to a buffer of at least IF_NAMESIZE bytes. The function shall place in this buffer the name of the interface with index ifindex. (IF_NAMESIZE is also defined in <net/if.h> and its value includes a terminating null byte at the end of the interface name.) If ifindex is an interface index, then the function shall return the value supplied in ifname, which points to a buffer now containing the interface name. Otherwise, the function shall return a NULL pointer and set errno to indicate the error. If there is no interface corresponding to the specified index, errno is set to ENXIO. If there was a system error (such as running out of memory), errno would be set to the proper value (e.g., ENOMEM).

调用此函数时,ifname参数应指向至少为IF_NAMESIZE字节的缓冲区。该函数应将带有索引ifindex的接口名称放入该缓冲区。(如果在<net/IF.h>中也定义了_NAMESIZE,并且其值在接口名称的末尾包含一个终止的空字节。)如果ifindex是接口索引,则函数应返回ifname中提供的值,该值指向现在包含接口名称的缓冲区。否则,函数应返回空指针并设置errno以指示错误。如果指定的索引没有对应的接口,则errno设置为ENXIO。如果出现系统错误(例如内存不足),errno将设置为正确的值(例如ENOMEM)。

4.3 Return All Interface Names and Indexes
4.3 返回所有接口名称和索引

The if_nameindex structure holds the information about a single interface and is defined as a result of including the <net/if.h> header.

if_nameindex结构保存关于单个接口的信息,并定义为包含<net/if.h>头的结果。

   struct if_nameindex {
     unsigned int   if_index;  /* 1, 2, ... */
     char          *if_name;   /* null terminated name: "le0", ... */
   };
        
   struct if_nameindex {
     unsigned int   if_index;  /* 1, 2, ... */
     char          *if_name;   /* null terminated name: "le0", ... */
   };
        

The final function returns an array of if_nameindex structures, one structure per interface.

最后一个函数返回一个if_nameindex结构数组,每个接口一个结构。

      #include <net/if.h>
        
      #include <net/if.h>
        
      struct if_nameindex  *if_nameindex(void);
        
      struct if_nameindex  *if_nameindex(void);
        

The end of the array of structures is indicated by a structure with an if_index of 0 and an if_name of NULL. The function returns a NULL pointer upon an error, and would set errno to the appropriate value.

结构数组的结尾由一个if_索引为0、if_名称为NULL的结构表示。函数在发生错误时返回空指针,并将errno设置为适当的值。

The memory used for this array of structures along with the interface names pointed to by the if_name members is obtained dynamically. This memory is freed by the next function.

用于此结构数组的内存以及if_name成员指向的接口名称是动态获取的。此内存由下一个函数释放。

4.4 Free Memory
4.4 空闲内存

The following function frees the dynamic memory that was allocated by if_nameindex().

以下函数释放由if_nameindex()分配的动态内存。

      #include <net/if.h>
        
      #include <net/if.h>
        
      void  if_freenameindex(struct if_nameindex *ptr);
        
      void  if_freenameindex(struct if_nameindex *ptr);
        

The ptr argument shall be a pointer that was returned by if_nameindex(). After if_freenameindex() has been called, the application shall not use the array of which ptr is the address.

ptr参数应该是if_nameindex()返回的指针。调用if_freenameindex()后,应用程序不得使用ptr为地址的数组。

5. Socket Options
5. 插座选项

A number of new socket options are defined for IPv6. All of these new options are at the IPPROTO_IPV6 level. That is, the "level" parameter in the getsockopt() and setsockopt() calls is IPPROTO_IPV6 when using these options. The constant name prefix IPV6_ is used in all of the new socket options. This serves to clearly identify these options as applying to IPv6.

为IPv6定义了许多新的套接字选项。所有这些新选项都是IPPROTO_IPV6级别的。也就是说,当使用这些选项时,getsockopt()和setsockopt()调用中的“level”参数是IPPROTO_IPV6。所有新套接字选项中都使用了常量名称前缀IPV6_u。这有助于清楚地确定这些选项是否适用于IPv6。

The declaration for IPPROTO_IPV6, the new IPv6 socket options, and related constants defined in this section are obtained by including the header <netinet/in.h>.

本节中定义的IPPROTO_IPV6声明、新的IPV6套接字选项和相关常量可通过包含标题<netinet/in.h>获得。

5.1 Unicast Hop Limit
5.1 单播跳限制

A new setsockopt() option controls the hop limit used in outgoing unicast IPv6 packets. The name of this option is IPV6_UNICAST_HOPS, and it is used at the IPPROTO_IPV6 layer. The following example illustrates how it is used:

新的setsockopt()选项控制传出单播IPv6数据包中使用的跃点限制。此选项的名称为IPV6_单播_跳,用于IPPROTO_IPV6层。以下示例说明了如何使用它:

int hoplimit = 10;

int-hopflimit=10;

   if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
                  (char *) &hoplimit, sizeof(hoplimit)) == -1)
       perror("setsockopt IPV6_UNICAST_HOPS");
        
   if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
                  (char *) &hoplimit, sizeof(hoplimit)) == -1)
       perror("setsockopt IPV6_UNICAST_HOPS");
        

When the IPV6_UNICAST_HOPS option is set with setsockopt(), the option value given is used as the hop limit for all subsequent unicast packets sent via that socket. If the option is not set, the system selects a default value. The integer hop limit value (called x) is interpreted as follows:

使用setsockopt()设置IPV6_UNICAST_HOPS选项时,给定的选项值将用作通过该套接字发送的所有后续单播数据包的跳数限制。如果未设置该选项,系统将选择默认值。整数跃点限制值(称为x)解释如下:

      x < -1:        return an error of EINVAL
      x == -1:       use kernel default
      0 <= x <= 255: use x
      x >= 256:      return an error of EINVAL
        
      x < -1:        return an error of EINVAL
      x == -1:       use kernel default
      0 <= x <= 255: use x
      x >= 256:      return an error of EINVAL
        

The IPV6_UNICAST_HOPS option may be used with getsockopt() to determine the hop limit value that the system will use for subsequent unicast packets sent via that socket. For example:

IPV6_UNICAST_HOPS选项可与getsockopt()一起使用,以确定系统将用于通过该套接字发送的后续单播数据包的跃点限制值。例如:

      int  hoplimit;
      socklen_t  len = sizeof(hoplimit);
        
      int  hoplimit;
      socklen_t  len = sizeof(hoplimit);
        
      if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
                     (char *) &hoplimit, &len) == -1)
          perror("getsockopt IPV6_UNICAST_HOPS");
      else
          printf("Using %d for hop limit.\n", hoplimit);
        
      if (getsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
                     (char *) &hoplimit, &len) == -1)
          perror("getsockopt IPV6_UNICAST_HOPS");
      else
          printf("Using %d for hop limit.\n", hoplimit);
        
5.2 Sending and Receiving Multicast Packets
5.2 发送和接收多播数据包

IPv6 applications may send multicast packets by simply specifying an IPv6 multicast address as the destination address, for example in the destination address argument of the sendto() function.

IPv6应用程序可以通过简单地指定IPv6多播地址作为目标地址来发送多播数据包,例如在sendto()函数的destination address参数中。

Three socket options at the IPPROTO_IPV6 layer control some of the parameters for sending multicast packets. Setting these options is not required: applications may send multicast packets without using these options. The setsockopt() options for controlling the sending of multicast packets are summarized below. These three options can also be used with getsockopt().

IPPROTO_IPV6层的三个套接字选项控制发送多播数据包的一些参数。不需要设置这些选项:应用程序可以在不使用这些选项的情况下发送多播数据包。下面总结了用于控制多播数据包发送的setsockopt()选项。这三个选项也可以与getsockopt()一起使用。

IPV6_MULTICAST_IF

IPV6\u多播\u如果

Set the interface to use for outgoing multicast packets. The argument is the index of the interface to use. If the interface index is specified as zero, the system selects the interface (for example, by looking up the address in a routing table and using the resulting interface).

设置用于传出多播数据包的接口。参数是要使用的接口的索引。如果接口索引指定为零,系统将选择接口(例如,通过在路由表中查找地址并使用结果接口)。

Argument type: unsigned int

参数类型:unsigned int

IPV6_MULTICAST_HOPS

IPV6\多播\跳

Set the hop limit to use for outgoing multicast packets. (Note a separate option - IPV6_UNICAST_HOPS - is provided to set the hop limit to use for outgoing unicast packets.)

设置用于传出多播数据包的跃点限制。(注意:提供了一个单独的选项—IPV6_单播_跳数—来设置用于传出单播数据包的跳数限制。)

The interpretation of the argument is the same as for the IPV6_UNICAST_HOPS option:

此参数的解释与IPV6_单播_跃点选项的解释相同:

            x < -1:        return an error of EINVAL
            x == -1:       use kernel default
            0 <= x <= 255: use x
            x >= 256:      return an error of EINVAL
        
            x < -1:        return an error of EINVAL
            x == -1:       use kernel default
            0 <= x <= 255: use x
            x >= 256:      return an error of EINVAL
        

If IPV6_MULTICAST_HOPS is not set, the default is 1 (same as IPv4 today)

如果未设置IPV6\多播\跃点,则默认值为1(与今天的IPv4相同)

Argument type: int

参数类型:int

IPV6_MULTICAST_LOOP

IPV6_多播_循环

If a multicast datagram is sent to a group to which the sending host itself belongs (on the outgoing interface), a copy of the datagram is looped back by the IP layer for local delivery if this option is set to 1. If this option is set to 0 a copy is not looped back. Other option values return an error of EINVAL.

如果将多播数据报发送到发送主机本身所属的组(在传出接口上),则如果此选项设置为1,则IP层会将数据报的副本循环回本地传递。如果此选项设置为0,则不会循环回副本。其他选项值返回EINVAL错误。

If IPV6_MULTICAST_LOOP is not set, the default is 1 (loopback; same as IPv4 today).

如果未设置IPV6_多播_循环,则默认值为1(环回;与今天的IPv4相同)。

Argument type: unsigned int

参数类型:unsigned int

The reception of multicast packets is controlled by the two setsockopt() options summarized below. An error of EOPNOTSUPP is returned if these two options are used with getsockopt().

多播数据包的接收由下面总结的两个setsockopt()选项控制。如果这两个选项与getsockopt()一起使用,则返回EOPNOTSUPP错误。

IPV6_JOIN_GROUP

IPV6\u加入\u组

Join a multicast group on a specified local interface. If the interface index is specified as 0, the kernel chooses the local interface. For example, some kernels look up the multicast group in the normal IPv6 routing table and use the resulting interface.

在指定的本地接口上加入多播组。如果接口索引指定为0,内核将选择本地接口。例如,一些内核在普通IPv6路由表中查找多播组,并使用生成的接口。

Argument type: struct ipv6_mreq

参数类型:结构ipv6\u mreq

IPV6_LEAVE_GROUP

IPV6_离开_组

Leave a multicast group on a specified interface. If the interface index is specified as 0, the system may choose a multicast group membership to drop by matching the multicast address only.

将多播组保留在指定接口上。如果接口索引指定为0,则系统可以通过仅匹配多播地址来选择要删除的多播组成员资格。

Argument type: struct ipv6_mreq

参数类型:结构ipv6\u mreq

The argument type of both of these options is the ipv6_mreq structure, defined as a result of including the <netinet/in.h> header;

这两个选项的参数类型都是ipv6_mreq结构,定义为包含<netinet/in.h>头的结果;

   struct ipv6_mreq {
       struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
       unsigned int    ipv6mr_interface; /* interface index */
   };
        
   struct ipv6_mreq {
       struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast addr */
       unsigned int    ipv6mr_interface; /* interface index */
   };
        

Note that to receive multicast datagrams a process must join the multicast group to which datagrams will be sent. UDP applications must also bind the UDP port to which datagrams will be sent. Some processes also bind the multicast group address to the socket, in addition to the port, to prevent other datagrams destined to that same port from being delivered to the socket.

请注意,要接收多播数据报,进程必须加入将向其发送数据报的多播组。UDP应用程序还必须绑定将向其发送数据报的UDP端口。除端口外,一些进程还将多播组地址绑定到套接字,以防止发送到同一端口的其他数据报发送到套接字。

5.3 IPV6_V6ONLY option for AF_INET6 Sockets
5.3 仅适用于AF_INET6套接字的IPV6_v6选项

This socket option restricts AF_INET6 sockets to IPv6 communications only. As stated in section <3.7 Compatibility with IPv4 Nodes>, AF_INET6 sockets may be used for both IPv4 and IPv6 communications. Some applications may want to restrict their use of an AF_INET6 socket to IPv6 communications only. For these applications the IPV6_V6ONLY socket option is defined. When this option is turned on, the socket can be used to send and receive IPv6 packets only. This is an IPPROTO_IPV6 level option. This option takes an int value. This is a boolean option. By default this option is turned off.

此套接字选项仅将AF_INET6套接字限制为IPv6通信。如第<3.7节“与IPv4节点的兼容性”所述,AF_INET6套接字可用于IPv4和IPv6通信。某些应用程序可能希望将AF_INET6套接字的使用限制为仅使用IPv6通信。对于这些应用程序,定义了IPV6_V6ONLY套接字选项。启用此选项后,套接字只能用于发送和接收IPv6数据包。这是IPPROTO_IPV6级别选项。此选项采用int值。这是一个布尔选项。默认情况下,此选项处于禁用状态。

Here is an example of setting this option:

以下是设置此选项的示例:

int on = 1;

int on=1;

      if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
                     (char *)&on, sizeof(on)) == -1)
          perror("setsockopt IPV6_V6ONLY");
      else
          printf("IPV6_V6ONLY set\n");
        
      if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
                     (char *)&on, sizeof(on)) == -1)
          perror("setsockopt IPV6_V6ONLY");
      else
          printf("IPV6_V6ONLY set\n");
        

Note - This option has no effect on the use of IPv4 Mapped addresses which enter a node as a valid IPv6 addresses for IPv6 communications as defined by Stateless IP/ICMP Translation Algorithm (SIIT) [5].

注意-此选项对IPv4映射地址的使用没有影响,IPv4映射地址输入节点作为无状态IP/ICMP转换算法(SIIT)定义的IPv6通信的有效IPv6地址[5]。

An example use of this option is to allow two versions of the same server process to run on the same port, one providing service over IPv6, the other providing the same service over IPv4.

此选项的一个示例用途是允许同一服务器进程的两个版本在同一端口上运行,一个通过IPv6提供服务,另一个通过IPv4提供相同的服务。

6. Library Functions
6. 图书馆职能

New library functions are needed to perform a variety of operations with IPv6 addresses. Functions are needed to lookup IPv6 addresses in the Domain Name System (DNS). Both forward lookup (nodename-to-address translation) and reverse lookup (address-to-nodename translation) need to be supported. Functions are also needed to convert IPv6 addresses between their binary and textual form.

使用IPv6地址执行各种操作需要新的库函数。在域名系统(DNS)中查找IPv6地址需要函数。需要支持正向查找(节点名到地址转换)和反向查找(地址到节点名转换)。还需要函数在二进制和文本形式之间转换IPv6地址。

We note that the two existing functions, gethostbyname() and gethostbyaddr(), are left as-is. New functions are defined to handle both IPv4 and IPv6 addresses.

我们注意到现有的两个函数gethostbyname()和gethostbyaddr()保持原样。定义了新函数来处理IPv4和IPv6地址。

The commonly used function gethostbyname() is inadequate for many applications, first because it provides no way for the caller to specify anything about the types of addresses desired (IPv4 only, IPv6 only, IPv4-mapped IPv6 are OK, etc.), and second because many implementations of this function are not thread safe. RFC 2133

常用的函数gethostbyname()对于许多应用程序来说是不够的,首先是因为它无法让调用者指定任何有关所需地址类型的内容(仅IPv4、仅IPv6、IPv4映射的IPv6都可以,等等),其次是因为此函数的许多实现都不是线程安全的。RFC 2133

defined a function named gethostbyname2() but this function was also inadequate, first because its use required setting a global option (RES_USE_INET6) when IPv6 addresses were required, and second because a flag argument is needed to provide the caller with additional control over the types of addresses required. The gethostbyname2() function was deprecated in RFC 2553 and is no longer part of the basic API.

定义了一个名为gethostbyname2()的函数,但该函数也不充分,首先是因为它的使用需要在需要IPv6地址时设置一个全局选项(RES_use_INET6),其次是因为需要一个标志参数来为调用方提供对所需地址类型的额外控制。gethostbyname2()函数在RFC2553中已被弃用,不再是基本API的一部分。

6.1 Protocol-Independent Nodename and Service Name Translation
6.1 协议无关的节点名和服务名转换

Nodename-to-address translation is done in a protocol-independent fashion using the getaddrinfo() function.

节点名到地址的转换是使用getaddrinfo()函数以独立于协议的方式完成的。

#include <sys/socket.h>
#include <netdb.h>
        
#include <sys/socket.h>
#include <netdb.h>
        
int getaddrinfo(const char *nodename, const char *servname,
                const struct addrinfo *hints, struct addrinfo **res);
        
int getaddrinfo(const char *nodename, const char *servname,
                const struct addrinfo *hints, struct addrinfo **res);
        
void freeaddrinfo(struct addrinfo *ai);
        
void freeaddrinfo(struct addrinfo *ai);
        
struct addrinfo {
  int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME,
                           AI_NUMERICHOST, .. */
  int     ai_family;    /* AF_xxx */
  int     ai_socktype;  /* SOCK_xxx */
  int     ai_protocol;  /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
  socklen_t  ai_addrlen;   /* length of ai_addr */
  char   *ai_canonname; /* canonical name for nodename */
  struct sockaddr  *ai_addr; /* binary address */
  struct addrinfo  *ai_next; /* next structure in linked list */
};
        
struct addrinfo {
  int     ai_flags;     /* AI_PASSIVE, AI_CANONNAME,
                           AI_NUMERICHOST, .. */
  int     ai_family;    /* AF_xxx */
  int     ai_socktype;  /* SOCK_xxx */
  int     ai_protocol;  /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
  socklen_t  ai_addrlen;   /* length of ai_addr */
  char   *ai_canonname; /* canonical name for nodename */
  struct sockaddr  *ai_addr; /* binary address */
  struct addrinfo  *ai_next; /* next structure in linked list */
};
        

The getaddrinfo() function translates the name of a service location (for example, a host name) and/or a service name and returns a set of socket addresses and associated information to be used in creating a socket with which to address the specified service.

函数的作用是:转换服务位置的名称(例如,主机名)和/或服务名称,并返回一组套接字地址和相关信息,用于创建一个套接字来寻址指定的服务。

The nodename and servname arguments are either null pointers or pointers to null-terminated strings. One or both of these two arguments must be a non-null pointer.

nodename和servname参数是空指针或指向以空结尾的字符串的指针。这两个参数中的一个或两个必须是非空指针。

The format of a valid name depends on the address family or families. If a specific family is not given and the name could be interpreted as valid within multiple supported families, the implementation will attempt to resolve the name in all supported families and, in absence of errors, one or more results shall be returned.

有效名称的格式取决于地址族。如果未给出特定族,且名称可能在多个受支持族中被解释为有效,则实现将尝试解析所有受支持族中的名称,如果没有错误,则应返回一个或多个结果。

If the nodename argument is not null, it can be a descriptive name or can be an address string. If the specified address family is AF_INET, AF_INET6, or AF_UNSPEC, valid descriptive names include host names. If the specified address family is AF_INET or AF_UNSPEC, address strings using Internet standard dot notation as specified in inet_addr() are valid. If the specified address family is AF_INET6 or AF_UNSPEC, standard IPv6 text forms described in inet_pton() are valid.

如果nodename参数不为null,则它可以是描述性名称,也可以是地址字符串。如果指定的地址族是AF_INET、AF_INET6或AF_unsec,则有效的描述性名称包括主机名。如果指定的地址族是AF_INET或AF_unsec,则使用INET_addr()中指定的Internet标准点表示法的地址字符串有效。如果指定的地址族是AF_INET6或AF_unsec,则inet_pton()中描述的标准IPv6文本格式有效。

If nodename is not null, the requested service location is named by nodename; otherwise, the requested service location is local to the caller.

如果nodename不为null,则请求的服务位置由nodename命名;否则,请求的服务位置对于调用方来说是本地的。

If servname is null, the call shall return network-level addresses for the specified nodename. If servname is not null, it is a null-terminated character string identifying the requested service. This can be either a descriptive name or a numeric representation suitable for use with the address family or families. If the specified address family is AF_INET, AF_INET6 or AF_UNSPEC, the service can be specified as a string specifying a decimal port number.

如果servname为null,则调用将返回指定节点名的网络级地址。如果servname不为null,则它是一个以null结尾的字符串,用于标识请求的服务。这可以是描述性名称,也可以是适用于地址族的数字表示形式。如果指定的地址族是AF_INET、AF_INET6或AF_unsec,则可以将服务指定为指定十进制端口号的字符串。

If the argument hints is not null, it refers to a structure containing input values that may direct the operation by providing options and by limiting the returned information to a specific socket type, address family and/or protocol. In this hints structure every member other than ai_flags, ai_family, ai_socktype and ai_protocol shall be set to zero or a null pointer. A value of AF_UNSPEC for ai_family means that the caller shall accept any address family. A value of zero for ai_socktype means that the caller shall accept any socket type. A value of zero for ai_protocol means that the caller shall accept any protocol. If hints is a null pointer, the behavior shall be as if it referred to a structure containing the value zero for the ai_flags, ai_socktype and ai_protocol fields, and AF_UNSPEC for the ai_family field.

如果参数提示不为null,则它引用一个包含输入值的结构,该输入值可以通过提供选项并将返回的信息限制为特定的套接字类型、地址族和/或协议来指导操作。在此提示结构中,除ai_标志、ai_系列、ai_socktype和ai_协议之外的每个成员都应设置为零或空指针。对于ai_族,AF_unsec的值表示呼叫者应接受任何地址族。ai_socktype的值为零表示调用方应接受任何套接字类型。ai_协议的值为零表示调用方应接受任何协议。如果提示是空指针,则该行为应与它引用的结构相同,该结构包含ai_标志、ai_socktype和ai_协议字段的值0,以及ai_族字段的值AF_unsec。

Note:

注:

1. If the caller handles only TCP and not UDP, for example, then the ai_protocol member of the hints structure should be set to IPPROTO_TCP when getaddrinfo() is called.

1. 例如,如果调用方只处理TCP而不处理UDP,那么当调用getaddrinfo()时,提示结构的ai_协议成员应设置为IPPROTO_TCP。

2. If the caller handles only IPv4 and not IPv6, then the ai_family member of the hints structure should be set to AF_INET when getaddrinfo() is called.

2. 如果调用方只处理IPv4而不处理IPv6,则在调用getaddrinfo()时,提示结构的ai_族成员应设置为AF_INET。

The ai_flags field to which hints parameter points shall be set to zero or be the bitwise-inclusive OR of one or more of the values AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST, AI_NUMERICSERV, AI_V4MAPPED, AI_ALL, and AI_ADDRCONFIG.

提示参数点应设置为零的ai_标志字段,或按位包含或包含ai_被动、ai_CANONNAME、ai_NUMERICHOST、ai_NUMERICSERV、ai_V4MAPPED、ai_ALL和ai_ADDRCONFIG中的一个或多个值。

If the AI_PASSIVE flag is specified, the returned address information shall be suitable for use in binding a socket for accepting incoming connections for the specified service (i.e., a call to bind()). In this case, if the nodename argument is null, then the IP address portion of the socket address structure shall be set to INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 address. If the AI_PASSIVE flag is not specified, the returned address information shall be suitable for a call to connect() (for a connection-mode protocol) or for a call to connect(), sendto() or sendmsg() (for a connectionless protocol). In this case, if the nodename argument is null, then the IP address portion of the socket address structure shall be set to the loopback address. This flag is ignored if the nodename argument is not null.

如果指定了AI_被动标志,则返回的地址信息应适用于绑定套接字以接受指定服务的传入连接(即,对bind()的调用)。在这种情况下,如果nodename参数为null,则套接字地址结构的IP地址部分对于IPv4地址应设置为INADDR_ANY,对于IPv6地址应设置为IN6ADDR_ANY_INIT。如果未指定AI_被动标志,则返回的地址信息应适用于调用connect()(对于连接模式协议)或调用connect()、sendto()或sendmsg()(对于无连接协议)。在这种情况下,如果nodename参数为null,则套接字地址结构的IP地址部分应设置为环回地址。如果nodename参数不为null,则忽略此标志。

If the AI_CANONNAME flag is specified and the nodename argument is not null, the function shall attempt to determine the canonical name corresponding to nodename (for example, if nodename is an alias or shorthand notation for a complete name).

如果指定了AI_CANONNAME标志且nodename参数不为null,则函数应尝试确定与nodename对应的规范名称(例如,如果nodename是全名的别名或简写符号)。

If the AI_NUMERICHOST flag is specified, then a non-null nodename string supplied shall be a numeric host address string. Otherwise, an [EAI_NONAME] error is returned. This flag shall prevent any type of name resolution service (for example, the DNS) from being invoked.

如果指定了AI_NumeriHost标志,则提供的非空节点名称字符串应为数字主机地址字符串。否则,将返回[EAI_NONAME]错误。此标志应防止调用任何类型的名称解析服务(例如,DNS)。

If the AI_NUMERICSERV flag is specified, then a non-null servname string supplied shall be a numeric port string. Otherwise, an [EAI_NONAME] error shall be returned. This flag shall prevent any type of name resolution service (for example, NIS+) from being invoked.

如果指定了AI_NUMERICSERV标志,则提供的非空servname字符串应为数字端口字符串。否则,将返回[EAI_NONAME]错误。此标志应防止调用任何类型的名称解析服务(例如,NIS+)。

If the AI_V4MAPPED flag is specified along with an ai_family of AF_INET6, then getaddrinfo() shall return IPv4-mapped IPv6 addresses on finding no matching IPv6 addresses (ai_addrlen shall be 16).

如果AI_V4MAPPED标志与AF_INET6的AI_系列一起指定,则getaddrinfo()应在未找到匹配的IPv6地址时返回IPv4映射的IPv6地址(AI_addrlen应为16)。

For example, when using the DNS, if no AAAA records are found then a query is made for A records and any found are returned as IPv4- mapped IPv6 addresses.

例如,在使用DNS时,如果未找到AAAA记录,则会对记录进行查询,找到的任何记录都将作为IPv4映射的IPv6地址返回。

The AI_V4MAPPED flag shall be ignored unless ai_family equals AF_INET6.

除非AI_族等于AF_INET6,否则应忽略AI_V4MAPPED标志。

If the AI_ALL flag is used with the AI_V4MAPPED flag, then getaddrinfo() shall return all matching IPv6 and IPv4 addresses.

如果AI_ALL标志与AI_V4MAPPED标志一起使用,则getaddrinfo()将返回所有匹配的IPv6和IPv4地址。

For example, when using the DNS, queries are made for both AAAA records and A records, and getaddrinfo() returns the combined results of both queries. Any IPv4 addresses found are returned as IPv4-mapped IPv6 addresses.

例如,使用DNS时,对AAAA记录和A记录进行查询,getaddrinfo()返回两个查询的组合结果。找到的任何IPv4地址都将作为IPv4映射的IPv6地址返回。

The AI_ALL flag without the AI_V4MAPPED flag is ignored.

忽略不带AI_V4MAPPED标志的AI_ALL标志。

Note:

注:

When ai_family is not specified (AF_UNSPEC), AI_V4MAPPED and AI_ALL flags will only be used if AF_INET6 is supported.

如果未指定ai_系列(AF_UNSPEC),则仅当支持AF_INET6时,才会使用ai_V4MAPPED和ai_ALL标志。

If the AI_ADDRCONFIG flag is specified, IPv4 addresses shall be returned only if an IPv4 address is configured on the local system, and IPv6 addresses shall be returned only if an IPv6 address is configured on the local system. The loopback address is not considered for this case as valid as a configured address.

如果指定了AI_ADDRCONFIG标志,则只有在本地系统上配置了IPv4地址时,才会返回IPv4地址,而只有在本地系统上配置了IPv6地址时,才会返回IPv6地址。在这种情况下,环回地址没有配置的地址有效。

For example, when using the DNS, a query for AAAA records should occur only if the node has at least one IPv6 address configured (other than IPv6 loopback) and a query for A records should occur only if the node has at least one IPv4 address configured (other than the IPv4 loopback).

例如,在使用DNS时,仅当节点至少配置了一个IPv6地址(IPv6环回除外)时,才应查询AAAA记录;仅当节点至少配置了一个IPv4地址(IPv4环回除外)时,才应查询记录。

The ai_socktype field to which argument hints points specifies the socket type for the service, as defined for socket(). If a specific socket type is not given (for example, a value of zero) and the service name could be interpreted as valid with multiple supported socket types, the implementation shall attempt to resolve the service name for all supported socket types and, in the absence of errors, all possible results shall be returned. A non-zero socket type value shall limit the returned information to values with the specified socket type.

参数提示指向的ai_socktype字段指定服务的套接字类型,如为socket()定义的。如果未给出特定的套接字类型(例如,值为零),并且服务名称可以解释为对多个支持的套接字类型有效,则实现应尝试解析所有支持的套接字类型的服务名称,并且在没有错误的情况下,应返回所有可能的结果。非零套接字类型值应将返回的信息限制为具有指定套接字类型的值。

If the ai_family field to which hints points has the value AF_UNSPEC, addresses shall be returned for use with any address family that can be used with the specified nodename and/or servname. Otherwise, addresses shall be returned for use only with the specified address family. If ai_family is not AF_UNSPEC and ai_protocol is not zero, then addresses are returned for use only with the specified address family and protocol; the value of ai_protocol shall be interpreted as in a call to the socket() function with the corresponding values of ai_family and ai_protocol.

如果提示指向的ai_族字段的值为AF_unsec,则应返回地址,以便与可与指定节点名和/或服务名一起使用的任何地址族一起使用。否则,地址只能返回用于指定的地址系列。如果ai_族不是AF_unsec,并且ai_协议不是零,则返回的地址仅用于指定的地址族和协议;ai_协议的值应解释为在调用socket()函数时使用ai_家族和ai_协议的相应值。

The freeaddrinfo() function frees one or more addrinfo structures returned by getaddrinfo(), along with any additional storage associated with those structures (for example, storage pointed to by the ai_canonname and ai_addr fields; an application must not

函数的作用是:释放getaddrinfo()返回的一个或多个addrinfo结构,以及与这些结构相关联的任何附加存储(例如,ai_canonname和ai_addr字段指向的存储;应用程序不能

reference this storage after the associated addrinfo structure has been freed). If the ai_next field of the structure is not null, the entire list of structures is freed. The freeaddrinfo() function must support the freeing of arbitrary sublists of an addrinfo list originally returned by getaddrinfo().

释放关联的addrinfo结构后引用此存储)。如果结构的ai_next字段不为null,则释放整个结构列表。函数必须支持释放最初由getaddrinfo()返回的addrinfo列表的任意子列表。

Functions getaddrinfo() and freeaddrinfo() must be thread-safe.

函数getaddrinfo()和freeaddrinfo()必须是线程安全的。

A zero return value for getaddrinfo() indicates successful completion; a non-zero return value indicates failure. The possible values for the failures are listed below under Error Return Values.

getaddrinfo()的返回值为零表示成功完成;非零返回值表示失败。错误返回值下面列出了故障的可能值。

Upon successful return of getaddrinfo(), the location to which res points shall refer to a linked list of addrinfo structures, each of which shall specify a socket address and information for use in creating a socket with which to use that socket address. The list shall include at least one addrinfo structure. The ai_next field of each structure contains a pointer to the next structure on the list, or a null pointer if it is the last structure on the list. Each structure on the list shall include values for use with a call to the socket() function, and a socket address for use with the connect() function or, if the AI_PASSIVE flag was specified, for use with the bind() function. The fields ai_family, ai_socktype, and ai_protocol shall be usable as the arguments to the socket() function to create a socket suitable for use with the returned address. The fields ai_addr and ai_addrlen are usable as the arguments to the connect() or bind() functions with such a socket, according to the AI_PASSIVE flag.

成功返回getaddrinfo()后,res指向的位置应参考addrinfo结构的链接列表,每个结构都应指定套接字地址和信息,用于创建使用该套接字地址的套接字。清单应至少包括一个addrinfo结构。每个结构的ai_next字段包含指向列表上下一个结构的指针,如果是列表上的最后一个结构,则包含空指针。列表中的每个结构应包括用于调用socket()函数的值,以及用于connect()函数的套接字地址,或者,如果指定了AI_被动标志,则用于bind()函数。字段ai_family、ai_socktype和ai_protocol应可用作socket()函数的参数,以创建适合与返回地址一起使用的套接字。根据ai_被动标志,字段ai_addr和ai_addrlen可用作带有此类套接字的connect()或bind()函数的参数。

If nodename is not null, and if requested by the AI_CANONNAME flag, the ai_canonname field of the first returned addrinfo structure shall point to a null-terminated string containing the canonical name corresponding to the input nodename; if the canonical name is not available, then ai_canonname shall refer to the nodename argument or a string with the same contents. The contents of the ai_flags field of the returned structures are undefined.

如果节点名不为null,并且如果AI_CANONNAME标志请求,则第一个返回的addrinfo结构的AI_CANONNAME字段应指向一个以null结尾的字符串,该字符串包含与输入节点名对应的规范名;如果规范名称不可用,则ai_canonname应引用nodename参数或具有相同内容的字符串。返回结构的ai_标志字段的内容未定义。

All fields in socket address structures returned by getaddrinfo() that are not filled in through an explicit argument (for example, sin6_flowinfo) shall be set to zero.

getaddrinfo()返回的套接字地址结构中所有未通过显式参数(例如,sin6_flowinfo)填充的字段应设置为零。

Note: This makes it easier to compare socket address structures.

注意:这使得比较套接字地址结构更加容易。

Error Return Values:

错误返回值:

The getaddrinfo() function shall fail and return the corresponding value if:

如果出现以下情况,getaddrinfo()函数将失败并返回相应的值:

[EAI_AGAIN] The name could not be resolved at this time. Future attempts may succeed.

[EAI_再次]此时无法解析名称。未来的尝试可能会成功。

[EAI_BADFLAGS] The flags parameter had an invalid value.

[EAI_BADFLAGS]flags参数的值无效。

[EAI_FAIL] A non-recoverable error occurred when attempting to resolve the name.

[EAI_FAIL]尝试解析名称时发生不可恢复的错误。

[EAI_FAMILY] The address family was not recognized.

[EAI_FAMILY]无法识别地址族。

[EAI_MEMORY] There was a memory allocation failure when trying to allocate storage for the return value.

[EAI_MEMORY]尝试为返回值分配存储时内存分配失败。

[EAI_NONAME] The name does not resolve for the supplied parameters. Neither nodename nor servname were supplied. At least one of these must be supplied.

[EAI_NONAME]未解析提供的参数的名称。未提供nodename或servname。必须至少提供其中一个。

[EAI_SERVICE] The service passed was not recognized for the specified socket type.

[EAI_服务]无法识别指定套接字类型所传递的服务。

[EAI_SOCKTYPE] The intended socket type was not recognized.

[EAI_SOCKTYPE]无法识别预期的套接字类型。

[EAI_SYSTEM] A system error occurred; the error code can be found in errno.

[EAI_系统]发生系统错误;错误代码可以在errno中找到。

The gai_strerror() function provides a descriptive text string corresponding to an EAI_xxx error value.

函数的作用是:提供与EAI_xxx错误值相对应的描述性文本字符串。

      #include <netdb.h>
        
      #include <netdb.h>
        
      const char *gai_strerror(int ecode);
        
      const char *gai_strerror(int ecode);
        

The argument is one of the EAI_xxx values defined for the getaddrinfo() and getnameinfo() functions. The return value points to a string describing the error. If the argument is not one of the EAI_xxx values, the function still returns a pointer to a string whose contents indicate an unknown error.

该参数是为getaddrinfo()和getnameinfo()函数定义的EAI_xxx值之一。返回值指向描述错误的字符串。如果参数不是EAI_xxx值之一,则函数仍然返回指向字符串的指针,该字符串的内容指示未知错误。

6.2 Socket Address Structure to Node Name and Service Name
6.2 节点名和服务名的套接字地址结构

The getnameinfo() function is used to translate the contents of a socket address structure to a node name and/or service name.

函数用于将套接字地址结构的内容转换为节点名和/或服务名。

   #include <sys/socket.h>
   #include <netdb.h>
        
   #include <sys/socket.h>
   #include <netdb.h>
        

int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *node, socklen_t nodelen, char *service, socklen_t servicelen, int flags);

int getnameinfo(const struct sockaddr*sa、socklen\u t salen、char*node、socklen\u t nodelen、char*service、socklen\u t servicelen、int标志);

The getnameinfo() function shall translate a socket address to a node name and service location, all of which are defined as in getaddrinfo().

getnameinfo()函数应将套接字地址转换为节点名和服务位置,所有这些都在getaddrinfo()中定义。

The sa argument points to a socket address structure to be translated.

sa参数指向要转换的套接字地址结构。

The salen argument holds the size of the socket address structure pointed to by sa.

salen参数保存sa指向的套接字地址结构的大小。

If the socket address structure contains an IPv4-mapped IPv6 address or an IPv4-compatible IPv6 address, the implementation shall extract the embedded IPv4 address and lookup the node name for that IPv4 address.

如果套接字地址结构包含IPv4映射的IPv6地址或IPv4兼容的IPv6地址,则实现应提取嵌入的IPv4地址并查找该IPv4地址的节点名称。

Note: The IPv6 unspecified address ("::") and the IPv6 loopback address ("::1") are not IPv4-compatible addresses. If the address is the IPv6 unspecified address ("::"), a lookup is not performed, and the [EAI_NONAME] error is returned.

注意:IPv6未指定的地址(“::”)和IPv6环回地址(“::1”)不是IPv4兼容的地址。如果地址是IPv6未指定的地址(“::”),则不执行查找,并返回[EAI_NONAME]错误。

If the node argument is non-NULL and the nodelen argument is nonzero, then the node argument points to a buffer able to contain up to nodelen characters that receives the node name as a null-terminated string. If the node argument is NULL or the nodelen argument is zero, the node name shall not be returned. If the node's name cannot be located, the numeric form of the node's address is returned instead of its name.

如果node参数为非NULL且nodelen参数为非零,则node参数将指向一个缓冲区,该缓冲区最多可包含nodelen字符,该缓冲区将节点名称作为以NULL结尾的字符串接收。如果node参数为NULL或nodelen参数为零,则不应返回节点名称。如果无法找到节点的名称,则返回节点地址的数字形式,而不是其名称。

If the service argument is non-NULL and the servicelen argument is non-zero, then the service argument points to a buffer able to contain up to servicelen bytes that receives the service name as a null-terminated string. If the service argument is NULL or the servicelen argument is zero, the service name shall not be returned. If the service's name cannot be located, the numeric form of the service address (for example, its port number) shall be returned instead of its name.

如果服务参数为非NULL且servicelen参数为非零,则服务参数将指向一个缓冲区,该缓冲区最多可包含servicelen字节,该缓冲区将服务名称作为以NULL结尾的字符串接收。如果服务参数为NULL或servicelen参数为零,则不应返回服务名称。如果找不到服务名称,则应返回服务地址的数字形式(例如,其端口号),而不是其名称。

The arguments node and service cannot both be NULL.

参数节点和服务不能同时为NULL。

The flags argument is a flag that changes the default actions of the function. By default the fully-qualified domain name (FQDN) for the host shall be returned, but:

flags参数是更改函数默认操作的标志。默认情况下,应返回主机的完全限定域名(FQDN),但:

- If the flag bit NI_NOFQDN is set, only the node name portion of the FQDN shall be returned for local hosts.

- 如果设置了标志位NI_NOFQDN,则对于本地主机,只应返回FQDN的节点名称部分。

- If the flag bit NI_NUMERICHOST is set, the numeric form of the host's address shall be returned instead of its name, under all circumstances.

- 如果设置了标志位NI_NumeriHost,则在任何情况下都应返回主机地址的数字形式,而不是其名称。

- If the flag bit NI_NAMEREQD is set, an error shall be returned if the host's name cannot be located.

- 如果设置了标志位NI_NAMEREQD,如果找不到主机名,则应返回错误。

- If the flag bit NI_NUMERICSERV is set, the numeric form of the service address shall be returned (for example, its port number) instead of its name, under all circumstances.

- 如果设置了标志位NI_NUMERICSERV,则在任何情况下都应返回服务地址的数字形式(例如,其端口号),而不是其名称。

- If the flag bit NI_DGRAM is set, this indicates that the service is a datagram service (SOCK_DGRAM). The default behavior shall assume that the service is a stream service (SOCK_STREAM).

- 如果设置了标志位NI_DGRAM,则表示该服务是数据报服务(SOCK_DGRAM)。默认行为应假定服务是流服务(SOCK_stream)。

Note:

注:

1. The NI_NUMERICxxx flags are required to support the "-n" flags that many commands provide.

1. NI_NUMERICxxx标志是支持许多命令提供的“-n”标志所必需的。

2. The NI_DGRAM flag is required for the few AF_INET and AF_INET6 port numbers (for example, [512,514]) that represent different services for UDP and TCP.

2. 对于表示UDP和TCP不同服务的几个AF_INET和AF_INET6端口号(例如,[512514]),需要NI_DGRAM标志。

The getnameinfo() function shall be thread safe.

getnameinfo()函数应该是线程安全的。

A zero return value for getnameinfo() indicates successful completion; a non-zero return value indicates failure.

getnameinfo()的返回值为零表示成功完成;非零返回值表示失败。

Upon successful completion, getnameinfo() shall return the node and service names, if requested, in the buffers provided. The returned names are always null-terminated strings.

成功完成后,getnameinfo()应在提供的缓冲区中返回节点和服务名称(如果请求)。返回的名称始终是以null结尾的字符串。

Error Return Values:

错误返回值:

The getnameinfo() function shall fail and return the corresponding value if:

如果出现以下情况,则getnameinfo()函数将失败并返回相应的值:

[EAI_AGAIN] The name could not be resolved at this time. Future attempts may succeed.

[EAI_再次]此时无法解析名称。未来的尝试可能会成功。

[EAI_BADFLAGS] The flags had an invalid value.

[EAI_BADFLAGS]这些标志的值无效。

[EAI_FAIL] A non-recoverable error occurred.

[EAI_FAIL]发生不可恢复的错误。

[EAI_FAMILY] The address family was not recognized or the address length was invalid for the specified family.

[EAI_FAMILY]无法识别地址系列,或者指定系列的地址长度无效。

[EAI_MEMORY] There was a memory allocation failure.

[EAI_MEMORY]内存分配失败。

[EAI_NONAME] The name does not resolve for the supplied parameters. NI_NAMEREQD is set and the host's name cannot be located, or both nodename and servname were null.

[EAI_NONAME]未解析提供的参数的名称。设置了NI_NAMEREQD,但找不到主机名,或者nodename和servname都为空。

[EAI_OVERFLOW] An argument buffer overflowed.

[EAI_溢出]参数缓冲区溢出。

[EAI_SYSTEM] A system error occurred. The error code can be found in errno.

[EAI_系统]发生系统错误。错误代码可以在errno中找到。

6.3 Address Conversion Functions
6.3 地址转换函数

The two IPv4 functions inet_addr() and inet_ntoa() convert an IPv4 address between binary and text form. IPv6 applications need similar functions. The following two functions convert both IPv6 and IPv4 addresses:

两个IPv4函数inet_addr()和inet_ntoa()在二进制和文本形式之间转换IPv4地址。IPv6应用程序需要类似的功能。以下两个函数用于转换IPv6和IPv4地址:

   #include <arpa/inet.h>
        
   #include <arpa/inet.h>
        
   int inet_pton(int af, const char *src, void *dst);
        
   int inet_pton(int af, const char *src, void *dst);
        
   const char *inet_ntop(int af, const void *src,
                            char *dst, socklen_t size);
        
   const char *inet_ntop(int af, const void *src,
                            char *dst, socklen_t size);
        

The inet_pton() function shall convert an address in its standard text presentation form into its numeric binary form. The af argument shall specify the family of the address. The AF_INET and AF_INET6 address families shall be supported. The src argument points to the string being passed in. The dst argument points to a buffer into which the function stores the numeric address; this shall be large enough to hold the numeric address (32 bits for AF_INET, 128 bits for AF_INET6). The inet_pton() function shall return 1 if the conversion

inet_pton()函数应将标准文本表示形式中的地址转换为数字二进制形式。af参数应指定地址族。应支持AF_INET和AF_INET6地址系列。src参数指向传入的字符串。dst参数指向函数存储数字地址的缓冲区;其大小应足以容纳数字地址(32位用于AF_INET,128位用于AF_INET6)。如果转换失败,inet_pton()函数将返回1

succeeds, with the address pointed to by dst in network byte order. It shall return 0 if the input is not a valid IPv4 dotted-decimal string or a valid IPv6 address string, or -1 with errno set to EAFNOSUPPORT if the af argument is unknown.

成功,dst以网络字节顺序指向的地址。如果输入不是有效的IPv4虚线十进制字符串或有效的IPv6地址字符串,则返回0;如果af参数未知,则返回-1,并将errno设置为EAFNOSUPPORT。

If the af argument of inet_pton() is AF_INET, the src string shall be in the standard IPv4 dotted-decimal form:

如果inet_pton()的af参数是af_inet,则src字符串应为标准十进制形式:

ddd.ddd.ddd.ddd

ddd.ddd.ddd.ddd

where "ddd" is a one to three digit decimal number between 0 and 255. The inet_pton() function does not accept other formats (such as the octal numbers, hexadecimal numbers, and fewer than four numbers that inet_addr() accepts).

其中,“ddd”是介于0和255之间的一到三位十进制数。inet_pton()函数不接受其他格式(如八进制数、十六进制数以及inet_addr()接受的少于四个数)。

If the af argument of inet_pton() is AF_INET6, the src string shall be in one of the standard IPv6 text forms defined in Section 2.2 of the addressing architecture specification [2].

如果inet_pton()的af参数为af_INET6,则src字符串应采用寻址体系结构规范[2]第2.2节中定义的标准IPv6文本格式之一。

The inet_ntop() function shall convert a numeric address into a text string suitable for presentation. The af argument shall specify the family of the address. This can be AF_INET or AF_INET6. The src argument points to a buffer holding an IPv4 address if the af argument is AF_INET, or an IPv6 address if the af argument is AF_INET6; the address must be in network byte order. The dst argument points to a buffer where the function stores the resulting text string; it shall not be NULL. The size argument specifies the size of this buffer, which shall be large enough to hold the text string (INET_ADDRSTRLEN characters for IPv4, INET6_ADDRSTRLEN characters for IPv6).

inet_ntop()函数应将数字地址转换为适合显示的文本字符串。af参数应指定地址族。这可以是AF_INET或AF_INET6。如果af参数为af_INET,则src参数指向保存IPv4地址的缓冲区;如果af参数为af_INET6,则指向保存IPv6地址的缓冲区;地址必须按网络字节顺序排列。dst参数指向一个缓冲区,函数在其中存储生成的文本字符串;它不应为空。size参数指定此缓冲区的大小,该缓冲区应足够大以容纳文本字符串(IPv4为INET_ADDRSTRLEN字符,IPv6为INET6_ADDRSTRLEN字符)。

In order to allow applications to easily declare buffers of the proper size to store IPv4 and IPv6 addresses in string form, the following two constants are defined in <netinet/in.h>:

为了使应用程序能够轻松声明适当大小的缓冲区,以字符串形式存储IPv4和IPv6地址,在<netinet/In.h>中定义了以下两个常量:

#define INET_ADDRSTRLEN 16 #define INET6_ADDRSTRLEN 46

#定义INET_ADDRSTRLEN 16#定义INET6_ADDRSTRLEN 46

The inet_ntop() function shall return a pointer to the buffer containing the text string if the conversion succeeds, and NULL otherwise. Upon failure, errno is set to EAFNOSUPPORT if the af argument is invalid or ENOSPC if the size of the result buffer is inadequate.

如果转换成功,inet_ntop()函数将返回一个指向包含文本字符串的缓冲区的指针,否则返回NULL。失败时,如果af参数无效,errno设置为EAFNOSUPPORT;如果结果缓冲区的大小不足,errno设置为ENOSPC。

6.4 Address Testing Macros
6.4 地址测试宏

The following macros can be used to test for special IPv6 addresses.

以下宏可用于测试特殊IPv6地址。

   #include <netinet/in.h>
        
   #include <netinet/in.h>
        
   int  IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *);
   int  IN6_IS_ADDR_LOOPBACK    (const struct in6_addr *);
   int  IN6_IS_ADDR_MULTICAST   (const struct in6_addr *);
   int  IN6_IS_ADDR_LINKLOCAL   (const struct in6_addr *);
   int  IN6_IS_ADDR_SITELOCAL   (const struct in6_addr *);
   int  IN6_IS_ADDR_V4MAPPED    (const struct in6_addr *);
   int  IN6_IS_ADDR_V4COMPAT    (const struct in6_addr *);
        
   int  IN6_IS_ADDR_UNSPECIFIED (const struct in6_addr *);
   int  IN6_IS_ADDR_LOOPBACK    (const struct in6_addr *);
   int  IN6_IS_ADDR_MULTICAST   (const struct in6_addr *);
   int  IN6_IS_ADDR_LINKLOCAL   (const struct in6_addr *);
   int  IN6_IS_ADDR_SITELOCAL   (const struct in6_addr *);
   int  IN6_IS_ADDR_V4MAPPED    (const struct in6_addr *);
   int  IN6_IS_ADDR_V4COMPAT    (const struct in6_addr *);
        
   int  IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *);
   int  IN6_IS_ADDR_MC_GLOBAL   (const struct in6_addr *);
        
   int  IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
   int  IN6_IS_ADDR_MC_ORGLOCAL (const struct in6_addr *);
   int  IN6_IS_ADDR_MC_GLOBAL   (const struct in6_addr *);
        

The first seven macros return true if the address is of the specified type, or false otherwise. The last five test the scope of a multicast address and return true if the address is a multicast address of the specified scope or false if the address is either not a multicast address or not of the specified scope.

如果地址为指定类型,则前七个宏返回true,否则返回false。最后五个测试多播地址的范围,如果地址是指定范围的多播地址,则返回true;如果地址不是多播地址或不属于指定范围,则返回false。

Note that IN6_IS_ADDR_LINKLOCAL and IN6_IS_ADDR_SITELOCAL return true only for the two types of local-use IPv6 unicast addresses (Link-Local and Site-Local) defined in [2], and that by this definition, the IN6_IS_ADDR_LINKLOCAL macro returns false for the IPv6 loopback address (::1). These two macros do not return true for IPv6 multicast addresses of either link-local scope or site-local scope.

请注意,IN6_IS_ADDR_LINKLOCAL和IN6_IS_ADDR_SITELOCAL仅对[2]中定义的两种类型的本地使用IPv6单播地址(链路本地和站点本地)返回true,并且根据此定义,IN6_IS_ADDR_LINKLOCAL宏对IPv6环回地址(::1)返回false。对于链路本地作用域或站点本地作用域的IPv6多播地址,这两个宏都不会返回true。

7. Summary of New Definitions
7. 新定义摘要

The following list summarizes the constants, structure, and extern definitions discussed in this memo, sorted by header.

以下列表总结了本备忘录中讨论的常量、结构和外部定义,并按标题排序。

<net/if.h>      IF_NAMESIZE
<net/if.h>      struct if_nameindex{};
        
<net/if.h>      IF_NAMESIZE
<net/if.h>      struct if_nameindex{};
        
<netdb.h>       AI_ADDRCONFIG
<netdb.h>       AI_ALL
<netdb.h>       AI_CANONNAME
<netdb.h>       AI_NUMERICHOST
<netdb.h>       AI_NUMERICSERV
<netdb.h>       AI_PASSIVE
<netdb.h>       AI_V4MAPPED
        
<netdb.h>       AI_ADDRCONFIG
<netdb.h>       AI_ALL
<netdb.h>       AI_CANONNAME
<netdb.h>       AI_NUMERICHOST
<netdb.h>       AI_NUMERICSERV
<netdb.h>       AI_PASSIVE
<netdb.h>       AI_V4MAPPED
        
<netdb.h>       EAI_AGAIN
<netdb.h>       EAI_BADFLAGS
<netdb.h>       EAI_FAIL
<netdb.h>       EAI_FAMILY
<netdb.h>       EAI_MEMORY
<netdb.h>       EAI_NONAME
<netdb.h>       EAI_OVERFLOW
<netdb.h>       EAI_SERVICE
<netdb.h>       EAI_SOCKTYPE
<netdb.h>       EAI_SYSTEM
<netdb.h>       NI_DGRAM
<netdb.h>       NI_NAMEREQD
<netdb.h>       NI_NOFQDN
<netdb.h>       NI_NUMERICHOST
<netdb.h>       NI_NUMERICSERV
<netdb.h>       struct addrinfo{};
        
<netdb.h>       EAI_AGAIN
<netdb.h>       EAI_BADFLAGS
<netdb.h>       EAI_FAIL
<netdb.h>       EAI_FAMILY
<netdb.h>       EAI_MEMORY
<netdb.h>       EAI_NONAME
<netdb.h>       EAI_OVERFLOW
<netdb.h>       EAI_SERVICE
<netdb.h>       EAI_SOCKTYPE
<netdb.h>       EAI_SYSTEM
<netdb.h>       NI_DGRAM
<netdb.h>       NI_NAMEREQD
<netdb.h>       NI_NOFQDN
<netdb.h>       NI_NUMERICHOST
<netdb.h>       NI_NUMERICSERV
<netdb.h>       struct addrinfo{};
        
<netinet/in.h>  IN6ADDR_ANY_INIT
<netinet/in.h>  IN6ADDR_LOOPBACK_INIT
<netinet/in.h>  INET6_ADDRSTRLEN
<netinet/in.h>  INET_ADDRSTRLEN
<netinet/in.h>  IPPROTO_IPV6
<netinet/in.h>  IPV6_JOIN_GROUP
<netinet/in.h>  IPV6_LEAVE_GROUP
<netinet/in.h>  IPV6_MULTICAST_HOPS
<netinet/in.h>  IPV6_MULTICAST_IF
<netinet/in.h>  IPV6_MULTICAST_LOOP
<netinet/in.h>  IPV6_UNICAST_HOPS
<netinet/in.h>  IPV6_V6ONLY
<netinet/in.h>  SIN6_LEN
<netinet/in.h>  extern const struct in6_addr in6addr_any;
<netinet/in.h>  extern const struct in6_addr in6addr_loopback;
<netinet/in.h>  struct in6_addr{};
<netinet/in.h>  struct ipv6_mreq{};
<netinet/in.h>  struct sockaddr_in6{};
        
<netinet/in.h>  IN6ADDR_ANY_INIT
<netinet/in.h>  IN6ADDR_LOOPBACK_INIT
<netinet/in.h>  INET6_ADDRSTRLEN
<netinet/in.h>  INET_ADDRSTRLEN
<netinet/in.h>  IPPROTO_IPV6
<netinet/in.h>  IPV6_JOIN_GROUP
<netinet/in.h>  IPV6_LEAVE_GROUP
<netinet/in.h>  IPV6_MULTICAST_HOPS
<netinet/in.h>  IPV6_MULTICAST_IF
<netinet/in.h>  IPV6_MULTICAST_LOOP
<netinet/in.h>  IPV6_UNICAST_HOPS
<netinet/in.h>  IPV6_V6ONLY
<netinet/in.h>  SIN6_LEN
<netinet/in.h>  extern const struct in6_addr in6addr_any;
<netinet/in.h>  extern const struct in6_addr in6addr_loopback;
<netinet/in.h>  struct in6_addr{};
<netinet/in.h>  struct ipv6_mreq{};
<netinet/in.h>  struct sockaddr_in6{};
        
<sys/socket.h>  AF_INET6
<sys/socket.h>  PF_INET6
<sys/socket.h>  struct sockaddr_storage;
        
<sys/socket.h>  AF_INET6
<sys/socket.h>  PF_INET6
<sys/socket.h>  struct sockaddr_storage;
        

The following list summarizes the function and macro prototypes discussed in this memo, sorted by header.

下表总结了本备忘录中讨论的功能和宏原型,按标题排序。

<arpa/inet.h>   int inet_pton(int, const char *, void *);
<arpa/inet.h>   const char *inet_ntop(int, const void *,
                               char *, socklen_t);
        
<arpa/inet.h>   int inet_pton(int, const char *, void *);
<arpa/inet.h>   const char *inet_ntop(int, const void *,
                               char *, socklen_t);
        
<net/if.h>      char *if_indextoname(unsigned int, char *);
<net/if.h>      unsigned int if_nametoindex(const char *);
<net/if.h>      void if_freenameindex(struct if_nameindex *);
<net/if.h>      struct if_nameindex *if_nameindex(void);
        
<net/if.h>      char *if_indextoname(unsigned int, char *);
<net/if.h>      unsigned int if_nametoindex(const char *);
<net/if.h>      void if_freenameindex(struct if_nameindex *);
<net/if.h>      struct if_nameindex *if_nameindex(void);
        
<netdb.h>       int getaddrinfo(const char *, const char *,
                                const struct addrinfo *,
                                struct addrinfo **);
<netdb.h>       int getnameinfo(const struct sockaddr *, socklen_t,
                  char *, socklen_t, char *, socklen_t, int);
<netdb.h>       void freeaddrinfo(struct addrinfo *);
<netdb.h>       const char *gai_strerror(int);
        
<netdb.h>       int getaddrinfo(const char *, const char *,
                                const struct addrinfo *,
                                struct addrinfo **);
<netdb.h>       int getnameinfo(const struct sockaddr *, socklen_t,
                  char *, socklen_t, char *, socklen_t, int);
<netdb.h>       void freeaddrinfo(struct addrinfo *);
<netdb.h>       const char *gai_strerror(int);
        
<netinet/in.h>  int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);
        
<netinet/in.h>  int IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_LOOPBACK(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_GLOBAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_LINKLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_NODELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_ORGLOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MC_SITELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_MULTICAST(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_SITELOCAL(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_UNSPECIFIED(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_V4COMPAT(const struct in6_addr *);
<netinet/in.h>  int IN6_IS_ADDR_V4MAPPED(const struct in6_addr *);
        
8. Security Considerations
8. 安全考虑

IPv6 provides a number of new security mechanisms, many of which need to be accessible to applications. Companion memos detailing the extensions to the socket interfaces to support IPv6 security are being written.

IPv6提供了许多新的安全机制,其中许多机制需要应用程序可以访问。正在编写配套备忘录,详细说明支持IPv6安全的套接字接口扩展。

9. Changes from RFC 2553
9. RFC 2553的变更

1. Add brief description of the history of this API and its relation to the Open Group/IEEE/ISO standards.

1. 添加此API历史的简要说明及其与开放组/IEEE/ISO标准的关系。

2. Alignments with [3].

2. 与[3]对齐。

3. Removed all references to getipnodebyname() and getipnodebyaddr(), which are deprecated in favor of getaddrinfo() and getnameinfo().

3. 删除了对getipnodebyname()和getipnodebyaddr()的所有引用,这些引用已被弃用,取而代之的是getaddrinfo()和getnameinfo()。

4. Added IPV6_V6ONLY IP level socket option to permit nodes to not process IPv4 packets as IPv4 Mapped addresses in implementations.

4. 添加了IPV6_V6ONLY IP级别套接字选项,以允许节点在实现中不将IPv4数据包作为IPv4映射地址进行处理。

5. Added SIIT to references and added new contributors.

5. 将SIIT添加到引用并添加新的贡献者。

6. In previous versions of this specification, the sin6_flowinfo field was associated with the IPv6 traffic class and flow label, but its usage was not completely specified. The complete definition of the sin6_flowinfo field, including its association with the traffic class or flow label, is now deferred to a future specification.

6. 在本规范的早期版本中,sin6_flowinfo字段与IPv6流量类别和流量标签相关联,但未完全指定其用法。sin6_flowinfo字段的完整定义,包括其与流量类别或流量标签的关联,现在推迟到将来的规范。

10. Acknowledgments
10. 致谢

This specification's evolution and completeness were significantly influenced by the efforts of Richard Stevens, who has passed on. Richard's wisdom and talent made the specification what it is today. The co-authors will long think of Richard with great respect.

本规范的发展和完整性受到了Richard Stevens的努力的重大影响,他已经去世。理查德的智慧和才能造就了今天的规格。两位合著者长期以来都会非常尊重理查德。

Thanks to the many people who made suggestions and provided feedback to this document, including:

感谢为本文件提供建议和反馈的许多人,包括:

Werner Almesberger, Ran Atkinson, Fred Baker, Dave Borman, Andrew Cherenson, Alex Conta, Alan Cox, Steve Deering, Richard Draves, Francis Dupont, Robert Elz, Brian Haberman, Jun-ichiro itojun Hagino, Marc Hasson, Tom Herbert, Bob Hinden, Wan-Yen Hsu, Christian Huitema, Koji Imada, Markus Jork, Ron Lee, Alan Lloyd, Charles Lynn, Dan McDonald, Dave Mitton, Finnbarr Murphy, Thomas Narten, Josh Osborne, Craig Partridge, Jean-Luc Richier, Bill Sommerfield, Erik Scoredos, Keith Sklower, JINMEI Tatuya, Dave Thaler, Matt Thomas, Harvey Thompson, Dean D. Throop, Karen Tracey, Glenn Trewitt, Paul Vixie, David Waitzman, Carl Williams, Kazu Yamamoto, Vlad Yasevich, Stig Venaas, and Brian Zill.

沃纳·阿尔梅斯伯格、冉·阿特金森、弗雷德·贝克、戴夫·鲍曼、安德鲁·切伦森、亚历克斯·孔塔、艾伦·考克斯、史蒂夫·迪林、理查德·德拉维斯、弗朗西斯·杜邦、罗伯特·埃尔兹、布莱恩·哈伯曼、伊藤俊哈吉诺、马克·哈森、汤姆·赫伯特、鲍勃·欣登、万延旭、克里斯蒂安·惠特玛、伊玛达、马库斯·乔克、罗恩·李、艾伦·劳埃德、查尔斯·林恩、丹·麦克唐纳、,戴夫·米顿、芬巴尔·墨菲、托马斯·纳滕、乔什·奥斯本、克雷格·帕特里奇、让·吕克·里奇、比尔·索默菲尔德、埃里克·斯科多斯、基思·斯克罗、金美·塔图亚、戴夫·泰勒、马特·托马斯、哈维·汤普森、迪安·D·斯洛普、卡伦·特雷西、格伦·特雷维特、保罗·维克西、大卫·维茨曼、卡尔·威廉姆斯、山本卡祖、弗拉德·亚舍维奇、斯蒂格·维纳斯和布赖恩·齐尔。

The getaddrinfo() and getnameinfo() functions are taken from an earlier document by Keith Sklower. As noted in that document, William Durst, Steven Wise, Michael Karels, and Eric Allman provided many useful discussions on the subject of protocol-independent name-to-address translation, and reviewed early versions of Keith Sklower's original proposal. Eric Allman implemented the first prototype of getaddrinfo(). The observation that specifying the pair of name and service would suffice for connecting to a service independent of protocol details was made by Marshall Rose in a proposal to X/Open for a "Uniform Network Interface".

getaddrinfo()和getnameinfo()函数取自Keith Sklower之前的文档。如该文件所述,William Durst、Steven Wise、Michael Karels和Eric Allman就协议独立名称翻译问题进行了许多有益的讨论,并审查了Keith Sklower最初提案的早期版本。Eric Allman实现了getaddrinfo()的第一个原型。Marshall Rose在向X/Open提交的“统一网络接口”提案中指出,指定名称和服务对就足以连接到独立于协议细节的服务。

Craig Metz, Jack McCann, Erik Nordmark, Tim Hartrick, and Mukesh Kacker made many contributions to this document. Ramesh Govindan made a number of contributions and co-authored an earlier version of this memo.

Craig Metz、Jack McCann、Erik Nordmark、Tim Hartrick和Mukesh Kacker对本文件做出了许多贡献。拉梅什·戈文丹(Ramesh Govindan)做出了许多贡献,并与他人共同撰写了这份备忘录的早期版本。

11. References
11. 工具书类

[1] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, December 1998.

[1] Deering,S.和R.Hinden,“互联网协议,第6版(IPv6)规范”,RFC 2460,1998年12月。

[2] Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 2373, July 1998.

[2] Hinden,R.和S.Deering,“IP版本6寻址体系结构”,RFC 23731998年7月。

   [3]  IEEE Std. 1003.1-2001 Standard for Information Technology --
        Portable Operating System Interface (POSIX). Open Group
        Technical Standard: Base Specifications, Issue 6, December 2001.
        ISO/IEC 9945:2002.  http://www.opengroup.org/austin
        
   [3]  IEEE Std. 1003.1-2001 Standard for Information Technology --
        Portable Operating System Interface (POSIX). Open Group
        Technical Standard: Base Specifications, Issue 6, December 2001.
        ISO/IEC 9945:2002.  http://www.opengroup.org/austin
        

[4] Stevens, W. and M. Thomas, "Advanced Sockets API for IPv6", RFC 2292, February 1998.

[4] Stevens,W.和M.Thomas,“IPv6的高级套接字API”,RFC 2292,1998年2月。

[5] Nordmark, E., "Stateless IP/ICMP Translation Algorithm (SIIT)", RFC 2765, February 2000.

[5] Nordmark,E.,“无状态IP/ICMP转换算法(SIIT)”,RFC 27652000年2月。

   [6]  The Open Group Base Working Group
        http://www.opengroup.org/platform/base.html
        
   [6]  The Open Group Base Working Group
        http://www.opengroup.org/platform/base.html
        
12. Authors' Addresses
12. 作者地址

Bob Gilligan Intransa, Inc. 2870 Zanker Rd. San Jose, CA 95134

Bob Gilligan Intransa,Inc.加利福尼亚州圣何塞市赞克路2870号,邮编95134

Phone: 408-678-8647 EMail: gilligan@intransa.com

电话:408-678-8647电子邮件:gilligan@intransa.com

Susan Thomson Cisco Systems 499 Thornall Street, 8th floor Edison, NJ 08837

Susan Thomson Cisco Systems新泽西州爱迪生市索纳尔街499号8楼08837

Phone: 732-635-3086 EMail: sethomso@cisco.com

电话:732-635-3086电子邮件:sethomso@cisco.com

Jim Bound Hewlett-Packard Company 110 Spitbrook Road ZKO3-3/W20 Nashua, NH 03062

Jim Bound Hewlett-Packard Company美国新罕布什尔州纳舒亚市斯皮布鲁克路110号ZKO3-3/W20邮编03062

Phone: 603-884-0062 EMail: Jim.Bound@hp.com

电话:603-884-0062电子邮件:吉姆。Bound@hp.com

Jack McCann Hewlett-Packard Company 110 Spitbrook Road ZKO3-3/W20 Nashua, NH 03062

Jack McCann Hewlett-Packard公司地址:新罕布什尔州纳舒亚市斯皮布鲁克路110号ZKO3-3/W20邮编:03062

Phone: 603-884-2608 EMail: Jack.McCann@hp.com

电话:603-884-2608电子邮件:杰克。McCann@hp.com

13. Full Copyright Statement
13. 完整版权声明

Copyright (C) The Internet Society (2003). All Rights Reserved.

版权所有(C)互联网协会(2003年)。版权所有。

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

本文件及其译本可复制并提供给他人,对其进行评论或解释或协助其实施的衍生作品可全部或部分编制、复制、出版和分发,不受任何限制,前提是上述版权声明和本段包含在所有此类副本和衍生作品中。但是,不得以任何方式修改本文件本身,例如删除版权通知或对互联网协会或其他互联网组织的引用,除非出于制定互联网标准的需要,在这种情况下,必须遵循互联网标准过程中定义的版权程序,或根据需要将其翻译成英语以外的其他语言。

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

上述授予的有限许可是永久性的,互联网协会或其继承人或受让人不会撤销。

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS 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.

本文件和其中包含的信息是按“原样”提供的,互联网协会和互联网工程任务组否认所有明示或暗示的保证,包括但不限于任何保证,即使用本文中的信息不会侵犯任何权利,或对适销性或特定用途适用性的任何默示保证。

Acknowledgement

确认

Funding for the RFC Editor function is currently provided by the Internet Society.

RFC编辑功能的资金目前由互联网协会提供。