📄 rfc2133.txt
字号:
Gilligan, et. al. Informational [Page 6]RFC 2133 IPv6 Socket Interface Extensions April 1997 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. The sin6_flowinfo field is a 32-bit field that contains two pieces of information: the 24-bit IPv6 flow label and the 4-bit priority field. The contents and interpretation of this member is unspecified at this time. 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. The ordering of elements in this structure is specifically designed so that the sin6_addr field will be aligned on a 64-bit boundary. This is done for optimum performance on 64-bit architectures. 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.3.4. Socket Address Structure for 4.4BSD-Based Systems 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: #include <netinet/in.h> #define SIN6_LEN struct sockaddr_in6 { u_char sin6_len; /* length of this struct */ u_char sin6_family; /* AF_INET6 */ u_int16m_t sin6_port; /* transport layer port # */ u_int32m_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ };Gilligan, et. al. Informational [Page 7]RFC 2133 IPv6 Socket Interface Extensions April 1997 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. 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.3.5. The Socket Functions 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: s = socket(PF_INET, SOCK_STREAM, 0); To create an IPv4/UDP socket, applications make the call: s = socket(PF_INET, SOCK_DGRAM, 0); Applications may create IPv6/TCP and IPv6/UDP sockets by simply using the constant PF_INET6 instead of PF_INET in the first argument. For example, to create an IPv6/TCP socket, applications make the call: s = socket(PF_INET6, SOCK_STREAM, 0); To create an IPv6/UDP socket, applications make the call: s = socket(PF_INET6, SOCK_DGRAM, 0); Once the application has created a PF_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: bind() connect() sendmsg() sendto()Gilligan, et. al. Informational [Page 8]RFC 2133 IPv6 Socket Interface Extensions April 1997 The system will use the sockaddr_in6 address structure to return addresses to applications that are using PF_INET6 sockets. The functions that return an address from the system to an application are: 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.3.6. Compatibility with IPv4 Applications 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 PF_INET sockets and the sockaddr_in address structure. Applications must be able to create IPv4/TCP and IPv4/UDP sockets using the PF_INET constant in the socket() function, as 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. 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.3.7. Compatibility with IPv4 Nodes 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: ::FFFF:<IPv4-address> These addresses are often generated automatically by the gethostbyname() function when the specified host has only IPv4 addresses (as described in Section 6.1).Gilligan, et. al. Informational [Page 9]RFC 2133 IPv6 Socket Interface Extensions April 1997 Applications may use PF_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 PF_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. 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.6, is provided.3.8. IPv6 Wildcard Address 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. 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. 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>: extern const struct in6_addr in6addr_any;Gilligan, et. al. Informational [Page 10]RFC 2133 IPv6 Socket Interface Extensions April 1997 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: 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: struct in6_addr anyaddr = IN6ADDR_ANY_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: /* 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.3.9. IPv6 Loopback Address 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. 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.Gilligan, et. al. Informational [Page 11]RFC 2133 IPv6 Socket Interface Extensions April 1997 The global variable is an in6_addr structure named "in6addr_loopback." The extern declaration for this variable is defined in <netinet/in.h>: extern const struct in6_addr in6addr_loopback; 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: 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: struct in6_addr loopbackaddr = IN6ADDR_LOOPBACK_INIT; Like IN6ADDR_ANY_INIT, this constant cannot be used in an assignment to a previously declared IPv6 address variable.4. Interface Identification This API uses an interface index (a small positive integer) to identify the local interface on which a multicast group is joined (Section 5.3). Additionally, the advanced API [5] 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. 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -