📄 rfc2133.txt
字号:
Gilligan, et. al. Informational [Page 18]RFC 2133 IPv6 Socket Interface Extensions April 19976. Library Functions 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 (hostname-to- address translation) and reverse lookup (address-to-hostname translation) need to be supported. Functions are also needed to convert IPv6 addresses between their binary and textual form.6.1. Hostname-to-Address Translation The commonly used function gethostbyname() remains unchanged as does the hostent structure to which it returns a pointer. Existing applications that call this function continue to receive only IPv4 addresses that are the result of a query in the DNS for A records. (We assume the DNS is being used; some environments may be using a hosts file or some other name resolution system, either of which may impede renumbering. We also assume that the RES_USE_INET6 resolver option is not set, which we describe in more detail shortly.) Two new changes are made to support IPv6 addresses. First, the following function is new: #include <sys/socket.h> #include <netdb.h> struct hostent *gethostbyname2(const char *name, int af); The af argument specifies the address family. The default operation of this function is simple: - If the af argument is AF_INET, then a query is made for A records. If successful, IPv4 addresses are returned and the h_length member of the hostent structure will be 4, else the function returns a NULL pointer. - If the af argument is AF_INET6, then a query is made for AAAA records. If successful, IPv6 addresses are returned and the h_length member of the hostent structure will be 16, else the function returns a NULL pointer.Gilligan, et. al. Informational [Page 19]RFC 2133 IPv6 Socket Interface Extensions April 1997 The second change, that provides additional functionality, is a new resolver option RES_USE_INET6, which is defined as a result of including the <resolv.h> header. (This option is provided starting with the BIND 4.9.4 release.) There are three ways to set this option. - The first way is res_init(); _res.options |= RES_USE_INET6; and then call either gethostbyname() or gethostbyname2(). This option then affects only the process that is calling the resolver. - The second way to set this option is to set the environment variable RES_OPTIONS, as in RES_OPTIONS=inet6. (This example is for the Bourne and Korn shells.) This method affects any processes that see this environment variable. - The third way is to set this option in the resolver configuration file (normally /etc/resolv.conf) and the option then affects all applications on the host. This final method should not be done until all applications on the host are capable of dealing with IPv6 addresses. There is no priority among these three methods. When the RES_USE_INET6 option is set, two changes occur: - gethostbyname(host) first calls gethostbyname2(host, AF_INET6) looking for AAAA records, and if this fails it then calls gethostbyname2(host, AF_INET) looking for A records. - gethostbyname2(host, AF_INET) always returns IPv4-mapped IPv6 addresses with the h_length member of the hostent structure set to 16. An application must not enable the RES_USE_INET6 option until it is prepared to deal with 16-byte addresses in the returned hostent structure.Gilligan, et. al. Informational [Page 20]RFC 2133 IPv6 Socket Interface Extensions April 1997 The following table summarizes the operation of the existing gethostbyname() function, the new function gethostbyname2(), along with the new resolver option RES_USE_INET6.+------------------+---------------------------------------------------+| | RES_USE_INET6 option || +-------------------------+-------------------------+| | off | on |+------------------+-------------------------+-------------------------+| |Search for A records. |Search for AAAA records. || gethostbyname | If found, return IPv4 | If found, return IPv6 || (host) | addresses (h_length=4). | addresses (h_length=16).|| | Else error. | Else search for A || | | records. If found, || |Provides backward | return IPv4-mapped IPv6 || | compatibility with all | addresses (h_length=16).|| | existing IPv4 appls. | Else error. |+------------------+-------------------------+-------------------------+| |Search for A records. |Search for A records. || gethostbyname2 | If found, return IPv4 | If found, return || (host, AF_INET) | addresses (h_length=4). | IPv4-mapped IPv6 || | Else error. | addresses (h_length=16).|| | | Else error. |+------------------+-------------------------+-------------------------+| |Search for AAAA records. |Search for AAAA records. || gethostbyname2 | If found, return IPv6 | If found, return IPv6 || (host, AF_INET6) | addresses (h_length=16).| addresses (h_length=16).|| | Else error. | Else error. |+------------------+-------------------------+-------------------------+ It is expected that when a typical naive application that calls gethostbyname() today is modified to use IPv6, it simply changes the program to use IPv6 sockets and then enables the RES_USE_INET6 resolver option before calling gethostbyname(). This application will then work with either IPv4 or IPv6 peers. Note that gethostbyname() and gethostbyname2() are not thread-safe, since both return a pointer to a static hostent structure. But several vendors have defined a thread-safe gethostbyname_r() function that requires four additional arguments. We expect these vendors to also define a gethostbyname2_r() function.Gilligan, et. al. Informational [Page 21]RFC 2133 IPv6 Socket Interface Extensions April 19976.2. Address To Hostname Translation The existing gethostbyaddr() function already requires an address family argument and can therefore work with IPv6 addresses: #include <sys/socket.h> #include <netdb.h> struct hostent *gethostbyaddr(const char *src, int len, int af); One possible source of confusion is the handling of IPv4-mapped IPv6 addresses and IPv4-compatible IPv6 addresses. This is addressed in [6] and involves the following logic: 1. If af is AF_INET6, and if len equals 16, and if the IPv6 address is an IPv4-mapped IPv6 address or an IPv4-compatible IPv6 address, then skip over the first 12 bytes of the IPv6 address, set af to AF_INET, and set len to 4. 2. If af is AF_INET, then query for a PTR record in the in- addr.arpa domain. 3. If af is AF_INET6, then query for a PTR record in the ip6.int domain. 4. If the function is returning success, and if af equals AF_INET, and if the RES_USE_INET6 option was set, then the single address that is returned in the hostent structure (a copy of the first argument to the function) is returned as an IPv4-mapped IPv6 address and the h_length member is set to 16. All four steps listed are performed, in order. The same caveats regarding a thread-safe version of gethostbyname() that were made at the end of the previous section apply here as well.6.3. Protocol-Independent Hostname and Service Name Translation Hostname-to-address translation is done in a protocol-independent fashion using the getaddrinfo() function that is taken from the Institute of Electrical and Electronic Engineers (IEEE) POSIX 1003.1g (Protocol Independent Interfaces) work in progress specification [4]. The official specification for this function will be the final POSIX standard. We are providing this independent description of the function because POSIX standards are not freely available (as are IETF documents). Should there be any discrepancies between this description and the POSIX description, the POSIX description takes precedence.Gilligan, et. al. Informational [Page 22]RFC 2133 IPv6 Socket Interface Extensions April 1997 #include <sys/socket.h> #include <netdb.h> int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hints, struct addrinfo **res); The addrinfo structure is defined as: #include <sys/socket.h> #include <netdb.h> struct addrinfo { int ai_flags; /* AI_PASSIVE, AI_CANONNAME */ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ size_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for hostname */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ }; The return value from the function is 0 upon success or a nonzero error code. The following names are the nonzero error codes from getaddrinfo(), and are defined in <netdb.h>: EAI_ADDRFAMILY address family for hostname not supported EAI_AGAIN temporary failure in name resolution EAI_BADFLAGS invalid value for ai_flags EAI_FAIL non-recoverable failure in name resolution EAI_FAMILY ai_family not supported EAI_MEMORY memory allocation failure EAI_NODATA no address associated with hostname EAI_NONAME hostname nor servname provided, or not known EAI_SERVICE servname not supported for ai_socktype EAI_SOCKTYPE ai_socktype not supported EAI_SYSTEM system error returned in errno The hostname and servname arguments are pointers to null-terminated strings or NULL. One or both of these two arguments must be a non- NULL pointer. In the normal client scenario, both the hostname and servname are specified. In the normal server scenario, only the servname is specified. A non-NULL hostname string can be either a host name or a numeric host address string (i.e., a dotted-decimal IPv4 address or an IPv6 hex address). A non-NULL servname string can be either a service name or a decimal port number.Gilligan, et. al. Informational [Page 23]RFC 2133 IPv6 Socket Interface Extensions April 1997 The caller can optionally pass an addrinfo structure, pointed to by the third argument, to provide hints concerning the type of socket that the caller supports. In this hints structure all members other than ai_flags, ai_family, ai_socktype, and ai_protocol must be zero or a NULL pointer. A value of PF_UNSPEC for ai_family means the caller will accept any protocol family. A value of 0 for ai_socktype means the caller will accept any socket type. A value of 0 for ai_protocol means the caller will accept any protocol. For example, if the caller handles only TCP and not UDP, then the ai_socktype member of the hints structure should be set to SOCK_STREAM when getaddrinfo() is called. If the caller handles only IPv4 and not IPv6, then the ai_family member of the hints structure should be set to PF_INET when getaddrinfo() is called. If the third argument to getaddrinfo() is a NULL pointer, this is the same as if the caller had filled in an addrinfo structure initialized to zero with ai_family set to PF_UNSPEC. Upon successful return a pointer to a linked list of one or more addrinfo structures is returned through the final argument. The caller can process each addrinfo structure in this list by following the ai_next pointer, until a NULL pointer is encountered. In each returned addrinfo structure the three members ai_family, ai_socktype, and ai_protocol are the corresponding arguments for a call to the socket() function. In each addrinfo structure the ai_addr member points to a filled-in socket address structure whose length is specified by the ai_addrlen member. If the AI_PASSIVE bit is set in the ai_flags member of the hints structure, then the caller plans to use the returned socket address structure in a call to bind(). In this case, if the hostname argument is a NULL pointer, then the IP address portion of the socket address structure will be set to INADDR_ANY for an IPv4 address or IN6ADDR_ANY_INIT for an IPv6 address. If the AI_PASSIVE bit is not set in the ai_flags member of the hints structure, then the returned socket address structure will be ready for a call to connect() (for a connection-oriented protocol) or either connect(), sendto(), or sendmsg() (for a connectionless protocol). In this case, if the hostname argument is a NULL pointer, then the IP address portion of the socket address structure will be set to the loopback address.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -