📄 rfc2553.txt
字号:
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.
An example is as follows:
Gilligan, et. al. Informational [Page 6]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
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
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.
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:
struct sockaddr_in6 {
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* transport layer port # */
uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
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.
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.
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.
Gilligan, et. al. Informational [Page 7]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
The sin6_flowinfo field is a 32-bit field that contains two pieces of
information: the traffic class and the flow label. The contents and
interpretation of this member is specified in [1]. The sin6_flowinfo
field SHOULD be set to zero by an implementation prior to using the
sockaddr_in6 structure by an application on receive operations.
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 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.
The sin6_scope_id field is a 32-bit integer that identifies a set of
interfaces as appropriate for the scope of the address carried in the
sin6_addr field. For a link scope sin6_addr sin6_scope_id would be
an interface index. For a site scope sin6_addr, sin6_scope_id would
be a site identifier. The mapping of sin6_scope_id to an interface
or set of interfaces is left to implementation and future
specifications on the subject of site identifiers.
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. It is defined as a
result of including the <netinet/in.h> header.
Gilligan, et. al. Informational [Page 8]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
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.
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);
Gilligan, et. al. Informational [Page 9]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
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()
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
Gilligan, et. al. Informational [Page 10]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
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 can be generated automatically by the
getipnodebyname() function when the specified host has only IPv4
addresses (as described in Section 6.1).
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.7, 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 11]
RFC 2553 Basic Socket Interface Extensions for IPv6 March 1999
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -