📄 rfc2292.txt
字号:
Note the difference between CMSG_SPACE() and CMSG_LEN(), shown also
in the figure in Section 4.2: the former accounts for any required
padding at the end of the ancillary data object and the latter is the
actual length to store in the cmsg_len member of the ancillary data
object.
4.4. Summary of Options Described Using Ancillary Data
There are six types of optional information described in this
document that are passed between the application and the kernel using
ancillary data:
1. the send/receive interface and source/destination address,
2. the hop limit,
3. next hop address,
4. Hop-by-Hop options,
5. Destination options, and
6. Routing header.
First, to receive any of this optional information (other than the
next hop address, which can only be set), the application must call
setsockopt() to turn on the corresponding flag:
int on = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
setsockopt(fd, IPPROTO_IPV6, IPV6_HOPOPTS, &on, sizeof(on));
setsockopt(fd, IPPROTO_IPV6, IPV6_DSTOPTS, &on, sizeof(on));
setsockopt(fd, IPPROTO_IPV6, IPV6_RTHDR, &on, sizeof(on));
When any of these options are enabled, the corresponding data is
returned as control information by recvmsg(), as one or more
ancillary data objects.
Nothing special need be done to send any of this optional
information; the application just calls sendmsg() and specifies one
or more ancillary data objects as control information.
We also summarize the three cmsghdr fields that describe the
ancillary data objects:
cmsg_level cmsg_type cmsg_data[] #times
------------ ------------ ------------------------ ------
IPPROTO_IPV6 IPV6_PKTINFO in6_pktinfo structure once
IPPROTO_IPV6 IPV6_HOPLIMIT int once
IPPROTO_IPV6 IPV6_NEXTHOP socket address structure once
IPPROTO_IPV6 IPV6_HOPOPTS implementation dependent mult.
Stevens & Thomas Informational [Page 23]
RFC 2292 Advanced Sockets API for IPv6 February 1998
IPPROTO_IPV6 IPV6_DSTOPTS implementation dependent mult.
IPPROTO_IPV6 IPV6_RTHDR implementation dependent once
The final column indicates how many times an ancillary data object of
that type can appear as control information. The Hop-by-Hop and
Destination options can appear multiple times, while all the others
can appear only one time.
All these options are described in detail in following sections. All
the constants beginning with IPV6_ are defined as a result of
including the <netinet/in.h> header.
(Note: We intentionally use the same constant for the cmsg_level
member as is used as the second argument to getsockopt() and
setsockopt() (what is called the "level"), and the same constant for
the cmsg_type member as is used as the third argument to getsockopt()
and setsockopt() (what is called the "option name"). This is
consistent with the existing use of ancillary data in 4.4BSD:
returning the destination address of an IPv4 datagram.)
(Note: It is up to the implementation what it passes as ancillary
data for the Hop-by-Hop option, Destination option, and Routing
header option, since the API to these features is through a set of
inet6_option_XXX() and inet6_rthdr_XXX() functions that we define
later. These functions serve two purposes: to simplify the interface
to these features (instead of requiring the application to know the
intimate details of the extension header formats), and to hide the
actual implementation from the application. Nevertheless, we show
some examples of these features that store the actual extension
header as the ancillary data. Implementations need not use this
technique.)
4.5. IPV6_PKTOPTIONS Socket Option
The summary in the previous section assumes a UDP socket. Sending
and receiving ancillary data is easy with UDP: the application calls
sendmsg() and recvmsg() instead of sendto() and recvfrom().
But there might be cases where a TCP application wants to send or
receive this optional information. For example, a TCP client might
want to specify a Routing header and this needs to be done before
calling connect(). Similarly a TCP server might want to know the
received interface after accept() returns along with any Destination
options.
Stevens & Thomas Informational [Page 24]
RFC 2292 Advanced Sockets API for IPv6 February 1998
A new socket option is defined that provides access to the optional
information described in the previous section, but without using
recvmsg() and sendmsg(). Setting the socket option specifies any of
the optional output fields:
setsockopt(fd, IPPROTO_IPV6, IPV6_PKTOPTIONS, &buf, len);
The fourth argument points to a buffer containing one or more
ancillary data objects, and the fifth argument is the total length of
all these objects. The application fills in this buffer exactly as
if the buffer were being passed to sendmsg() as control information.
The options set by calling setsockopt() for IPV6_PKTOPTIONS are
called "sticky" options because once set they apply to all packets
sent on that socket. The application can call setsockopt() again to
change all the sticky options, or it can call setsockopt() with a
length of 0 to remove all the sticky options for the socket.
The corresponding receive option
getsockopt(fd, IPPROTO_IPV6, IPV6_PKTOPTIONS, &buf, &len);
returns a buffer with one or more ancillary data objects for all the
optional receive information that the application has previously
specified that it wants to receive. The fourth argument points to
the buffer that is filled in by the call. The fifth argument is a
pointer to a value-result integer: when the function is called the
integer specifies the size of the buffer pointed to by the fourth
argument, and on return this integer contains the actual number of
bytes that were returned. The application processes this buffer
exactly as if the buffer were returned by recvmsg() as control
information.
To simplify this document, in the remaining sections when we say "can
be specified as ancillary data to sendmsg()" we mean "can be
specified as ancillary data to sendmsg() or specified as a sticky
option using setsockopt() and the IPV6_PKTOPTIONS socket option".
Similarly when we say "can be returned as ancillary data by
recvmsg()" we mean "can be returned as ancillary data by recvmsg() or
returned by getsockopt() with the IPV6_PKTOPTIONS socket option".
4.5.1. TCP Sticky Options
When using getsockopt() with the IPV6_PKTOPTIONS option and a TCP
socket, only the options from the most recently received segment are
retained and returned to the caller, and only after the socket option
has been set. That is, TCP need not start saving a copy of the
options until the application says to do so.
Stevens & Thomas Informational [Page 25]
RFC 2292 Advanced Sockets API for IPv6 February 1998
The application is not allowed to specify ancillary data in a call to
sendmsg() on a TCP socket, and none of the ancillary data that we
describe in this document is ever returned as control information by
recvmsg() on a TCP socket.
4.5.2. UDP and Raw Socket Sticky Options
The IPV6_PKTOPTIONS socket option can also be used with a UDP socket
or with a raw IPv6 socket, normally to set some of the options once,
instead of with each call to sendmsg().
Unlike the TCP case, the sticky options can be overridden on a per-
packet basis with ancillary data specified in a call to sendmsg() on
a UDP or raw IPv6 socket. If any ancillary data is specified in a
call to sendmsg(), none of the sticky options are sent with that
datagram.
5. Packet Information
There are four pieces of information that an application can specify
for an outgoing packet using ancillary data:
1. the source IPv6 address,
2. the outgoing interface index,
3. the outgoing hop limit, and
4. the next hop address.
Three similar pieces of information can be returned for a received
packet as ancillary data:
1. the destination IPv6 address,
2. the arriving interface index, and
3. the arriving hop limit.
The first two pieces of information are contained in an in6_pktinfo
structure that is sent as ancillary data with sendmsg() and received
as ancillary data with recvmsg(). This structure is defined as a
result of including the <netinet/in.h> header.
struct in6_pktinfo {
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
In the cmsghdr structure containing this ancillary data, the
cmsg_level member will be IPPROTO_IPV6, the cmsg_type member will be
IPV6_PKTINFO, and the first byte of cmsg_data[] will be the first
byte of the in6_pktinfo structure.
Stevens & Thomas Informational [Page 26]
RFC 2292 Advanced Sockets API for IPv6 February 1998
This information is returned as ancillary data by recvmsg() only if
the application has enabled the IPV6_PKTINFO socket option:
int on = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));
Nothing special need be done to send this information: just specify
the control information as ancillary data for sendmsg().
(Note: The hop limit is not contained in the in6_pktinfo structure
for the following reason. Some UDP servers want to respond to client
requests by sending their reply out the same interface on which the
request was received and with the source IPv6 address of the reply
equal to the destination IPv6 address of the request. To do this the
application can enable just the IPV6_PKTINFO socket option and then
use the received control information from recvmsg() as the outgoing
control information for sendmsg(). The application need not examine
or modify the in6_pktinfo structure at all. But if the hop limit
were contained in this structure, the application would have to parse
the received control information and change the hop limit member,
since the received hop limit is not the desired value for an outgoing
packet.)
5.1. Specifying/Receiving the Interface
Interfaces on an IPv6 node are identified by a small positive
integer, as described in Section 4 of [RFC-2133]. That document also
describes a function to map an interface name to its interface index,
a function to map an interface index to its interface name, and a
function to return all the interface names and indexes. Notice from
this document that no interface is ever assigned an index of 0.
When specifying the outgoing interface, if the ipi6_ifindex value is
0, the kernel will choose the outgoing interface. If the application
specifies an outgoing interface for a multicast packet, the interface
specified by the ancillary data overrides any interface specified by
the IPV6_MULTICAST_IF socket option (described in [RFC-2133]), for
that call to sendmsg() only.
When the IPV6_PKTINFO socket option is enabled, the received
interface index is always returned as the ipi6_ifindex member of the
in6_pktinfo structure.
5.2. Specifying/Receiving Source/Destination Address
The source IPv6 address can be specified by calling bind() before
each output operation, but supplying the source address together with
the data requires less overhead (i.e., fewer system calls) and
Stevens & Thomas Informational [Page 27]
RFC 2292 Advanced Sockets API for IPv6 February 1998
requires less state to be stored and protected in a multithreaded
application.
When specifying the source IPv6 address as ancillary data, if the
ipi6_addr member of the in6_pktinfo structure is the unspecified
address (IN6ADDR_ANY_INIT), then (a) if an address is currently bound
to the socket, it is used as the source address, or (b) if no address
is currently bound to the socket, the kernel will choose the source
address. If the ipi6_addr member is not the unspecified address, but
the socket has already bound a source address, then the ipi6_addr
value overrides the already-bound source address for this output
operation only.
The kernel must verify that the requested source address is indeed a
unicast address assigned to the node.
When the in6_pktinfo structure is returned as ancillary data by
recvmsg(), the ipi6_addr member contains the destination IPv6 address
from the received packet.
5.3. Specifying/Receiving the Hop Limit
The outgoing hop limit is normally specified with either the
IPV6_UNICAST_HOPS socket option or the IPV6_MULTICAST_HOPS socket
option, both of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -