ip6 - Internet Protocol version 6 (IPv6)
#include <sys/socket.h>
#include <netinet/in.h>
int
socket(AF_INET6, SOCK_RAW, proto);
IPv6 is the network layer protocol used by the Internet protocol version
6 family (AF_INET6). Options may be set at the IPv6 level
when using
higher-level protocols that are based on IPv6 (such as TCP
and UDP). It
may also be accessed through a ``raw socket'' when developing new protocols,
or special-purpose applications.
There are several IPv6-level setsockopt(2)/getsockopt(2) options. They
are separated into the basic IPv6 sockets API (defined in
RFC 2553), and
the advanced API (defined in RFC 2292). The basic API looks
very similar
to the API presented in ip(4). Advanced API uses ancillary
data and can
handle more complex cases.
To specify some socket options, a certain level of privilege
(i.e. root
privilege) is required.
Basic IPv6 sockets API [Toc] [Back]
IPV6_UNICAST_HOPS may be used to set the hoplimit field in
the IPv6 header.
As the symbol name suggests, the option controls the
hoplimit field
on unicast packets. If -1 is specified, the kernel will use
a default
value. If a value of 0 to 255 is specified, the packet will
have the
specified value as hoplimit. Other values are considered
invalid, and
EINVAL will be returned. For example:
int hlim = 60; /* max = 255 */
setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hlim,
sizeof(hlim));
IPv6 multicasting is supported only on AF_INET6 sockets of
type
SOCK_DGRAM and SOCK_RAW, and only on networks where the interface driver
supports multicasting.
The IPV6_MULTICAST_HOPS option changes the hoplimit for outgoing multicast
datagrams in order to control the scope of the multicasts:
unsigned int hlim; /* range: 0 to 255, default =
1 */
setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
&hlim, sizeof(hlim));
Datagrams with a hoplimit of 1 are not forwarded beyond the
local network.
Multicast datagrams with a hoplimit of 0 will not be
transmitted
on any network, but may be delivered locally if the sending
host belongs
to the destination group and if multicast loopback has not
been disabled
on the sending socket (see below). Multicast datagrams with
a hoplimit
greater than 1 may be forwarded to other networks if a multicast router
is attached to the local network.
For hosts with multiple interfaces, each multicast transmission is sent
from the primary network interface. The IPV6_MULTICAST_IF
option overrides
the default for subsequent transmissions from a given
socket:
unsigned int outif;
outif = if_nametoindex("ne0");
setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &outif,
sizeof(outif));
where "outif" is an interface index of the desired interface, or 0 to
specify the default interface.
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, by
default, looped back by the IPv6 layer for local delivery.
The
IPV6_MULTICAST_LOOP option gives the sender explicit control
over whether
or not subsequent datagrams are looped back:
u_char loop; /* 0 = disable, 1 = enable (default)
*/
setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&loop, sizeof(loop));
This option improves performance for applications that may
have no more
than one instance on a single host (such as a router daemon), by eliminating
the overhead of receiving their own transmissions.
It should generally
not be used by applications for which there may be
more than one
instance on a single host (such as a conferencing program)
or for which
the sender does not belong to the destination group (such as
a time
querying program).
A multicast datagram sent with an initial hoplimit greater
than 1 may be
delivered to the sending host on a different interface from
that on which
it was sent, if the host belongs to the destination group on
that other
interface. The loopback control option has no effect on
such delivery.
A host must become a member of a multicast group before it
can receive
datagrams sent to the group. To join a multicast group, use
the
IPV6_JOIN_GROUP option:
struct ipv6_mreq mreq6;
setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
sizeof(mreq6));
where mreq6 is the following structure:
struct ipv6_mreq {
struct in6_addr ipv6mr_multiaddr;
unsigned int ipv6mr_interface;
};
ipv6mr_interface should be 0 to choose the default multicast
interface,
or the interface index of a particular multicast-capable interface if the
host is multihomed. Membership is associated with a single
interface;
programs running on multihomed hosts may need to join the
same group on
more than one interface.
To drop a membership, use:
struct ipv6_mreq mreq6;
setsockopt(s, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq6,
sizeof(mreq6));
where mreq6 contains the same values as used to add the membership. Memberships
are dropped when the socket is closed or the process exits.
IPV6_PORTRANGE controls how ephemeral ports are allocated
for SOCK_STREAM
and SOCK_DGRAM sockets. For example,
int range = IPV6_PORTRANGE_LOW; /* see
<netinet/in.h> */
setsockopt(s, IPPROTO_IPV6, IPV6_PORTRANGE, &range,
sizeof(range));
Advanced IPv6 sockets API [Toc] [Back]
The advanced IPv6 sockets API lets userland programs specify
or obtain
details about the IPv6 header and the IPv6 extension headers
on packets.
The advanced API uses ancillary data for passing data
from/to the kernel.
There are setsockopt(2)/getsockopt(2) options to get optional information
on incoming packets. They are IPV6_PKTINFO, IPV6_HOPLIMIT,
IPV6_HOPOPTS,
IPV6_DSTOPTS, and IPV6_RTHDR.
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(2), as one or more ancillary data objects.
If IPV6_PKTINFO is enabled, the destination IPv6 address and
the arriving
interface index will be available via struct in6_pktinfo on
ancillary data
stream. You can pick the structure by checking for an
ancillary data
item with cmsg_level equal to IPPROTO_IPV6, and cmsg_type
equal to
IPV6_PKTINFO.
If IPV6_HOPLIMIT is enabled, the hoplimit value on the packet will be
made available to the userland program. The ancillary data
stream will
contain an integer data item with cmsg_level equal to IPPROTO_IPV6, and
cmsg_type equal to IPV6_HOPLIMIT.
inet6_option_space(3) and friends help parse ancillary data
items for
IPV6_HOPOPTS and IPV6_DSTOPTS. Similarly, inet6_rthdr_space(3) and
friends help parse ancillary data items for IPV6_RTHDR.
IPV6_HOPOPTS and IPV6_DSTOPTS may appear multiple times on
an ancillary
data stream (note that the behavior is slightly different
than the specification).
Other ancillary data items can appear no more
than once.
For outgoing direction, ancillary data items with normal
payload data can
be passed using sendmsg(2). Ancillary data items will be
parsed by the
kernel, and used to construct the IPv6 header and extension
headers. For
the 5 cmsg_level values listed above, the ancillary data
format is the
same as the inbound case. Additionally, the IPV6_NEXTHOP
data object can
also be specified. The IPV6_NEXTHOP ancillary data object
specifies the
next hop for the datagram as a socket address structure. In
the cmsghdr
structure containing this ancillary data, the cmsg_level
member will be
IPPROTO_IPV6, the cmsg_type member will be IPV6_NEXTHOP, and
the first
byte of cmsg_data[] will be the first byte of the socket address structure.
If the socket address structure contains an IPv6 address
(i.e., the
sin6_family member is AF_INET6 ), then the node identified
by that address
must be a neighbor of the sending host. If that address equals the
destination IPv6 address of the datagram, then this is
equivalent to the
existing SO_DONTROUTE socket option.
For applications that do not, or are unable to use
sendmsg(2) or
recvmsg(2), the IPV6_PKTOPTIONS socket option is defined.
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(2) as control information.
The options set by calling setsockopt(2) for IPV6_PKTOPTIONS
are called
"sticky" options because once set they apply to all packets
sent on that
socket. The application can call setsockopt(2) again to
change all the
sticky options, or it can call setsockopt(2) 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(2) as control information.
Advanced API and TCP sockets [Toc] [Back]
When using getsockopt(2) 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. The application is not allowed to specify ancillary
data in a call
to sendmsg(2) on a TCP socket, and none of the ancillary data that we described
above is ever returned as control information by
recvmsg(2) on a
TCP socket.
Conflict resolution [Toc] [Back]
In some cases, there are multiple APIs defined for manipulating a IPv6
header field. A good example is the outgoing interface for
multicast
datagrams: it can be manipulated by IPV6_MULTICAST_IF in basic API,
IPV6_PKTINFO in advanced API, and the sin6_scope_id field of
the socket
address passed to sendto(2).
When conflicting options are given to the kernel, the kernel
will get the
value in the following order of preference: (1) options
specified by using
ancillary data, (2) options specified by a sticky option
of the advanced
API, (3) options specified by using the basic API,
and lastly (4)
options specified by a socket address. Note that the conflict resolution
is undefined in the API specification and implementation dependent.
Raw IPv6 Sockets [Toc] [Back]
Raw IPv6 sockets are connectionless, and are normally used
with the
sendto(2) and recvfrom(2) calls, though the connect(2) call
may also be
used to fix the destination for future packets (in which
case the read(2)
or recv(2) and write(2) or send(2) system calls may be
used).
If proto is 0, the default protocol IPPROTO_RAW is used for
outgoing
packets, and only incoming packets destined for that protocol are received.
If proto is non-zero, that protocol number will be
used on outgoing
packets and to filter incoming packets.
Outgoing packets automatically have an IPv6 header prepended
to them
(based on the destination address and the protocol number
the socket is
created with). Incoming packets are received without an
IPv6 header or
extension headers.
All data sent via raw sockets MUST be in network byte order
and all data
received via raw sockets will be in network byte order.
This differs
from the IPv4 raw sockets, which did not specify a byte ordering and typically
used the host's byte order.
Another difference from IPv4 raw sockets is that complete
packets (that
is, IPv6 packets with extension headers) cannot be read or
written using
the IPv6 raw sockets API. Instead, ancillary data objects
are used to
transfer the extension headers, as described above. Should
an application
need access to the complete IPv6 packet, some other
technique, such
as the datalink interfaces, such as bpf(4), must be used.
All fields in the IPv6 header that an application might want
to change
(i.e., everything other than the version number) can be modified using
ancillary data and/or socket options by the application for
output. All
fields in a received IPv6 header (other than the version
number and Next
Header fields) and all extension headers are also made
available to the
application as ancillary data on input. Hence there is no
need for a
socket option similar to the IPv4 IP_HDRINCL socket option.
When writing to a raw socket the kernel will automatically
fragment the
packet if its size exceeds the path MTU, inserting the required fragmentation
headers. On input the kernel reassembles received
fragments, so
the reader of a raw socket never sees any fragment headers.
Most IPv4 implementations give special treatment to a raw
socket created
with a third argument to socket(2) of IPPROTO_RAW, whose
value is normally
255. We note that this value has no special meaning to
an IPv6 raw
socket (and the IANA currently reserves the value of 255
when used as a
next-header field).
For ICMPv6 raw sockets, the kernel will calculate and insert
the ICMPv6
checksum since this checksum is mandatory.
For other raw IPv6 sockets (that is, for raw IPv6 sockets
created with a
third argument other than IPPROTO_ICMPV6), the application
must set the
new IPV6_CHECKSUM socket option to have the kernel (1) compute and store
a pseudo-header checksum for output, and (2) verify the received pseudoheader
checksum on input, discarding the packet if the
checksum is in error.
This option prevents applications from having to perform source address
selection on the packets they send. The checksum will
incorporate
the IPv6 pseudo-header, defined in Section 8.1 of RFC 2460.
This new
socket option also specifies an integer offset into the user
data of
where the checksum is located.
int offset = 2;
setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset,
sizeof(offset));
By default, this socket option is disabled. Setting the
offset to -1 also
disables the option. By disabled we mean (1) the kernel
will not calculate
and store a checksum for outgoing packets, and (2)
the kernel will
not verify a checksum for received packets.
Note: Since the checksum is always calculated by the kernel
for an ICMPv6
socket, applications are not able to generate ICMPv6 packets
with incorrect
checksums (presumably for testing purposes) using this
API.
A socket operation may fail with one of the following errors
returned:
[EISCONN] when trying to establish a connection on a
socket which
already has one, or when trying to send a
datagram with
the destination address specified and the
socket is already
connected.
[ENOTCONN] when trying to send a datagram, but no destination address
is specified, and the socket hasn't
been connected.
[ENOBUFS] when the system runs out of memory for an
internal data
structure.
[EADDRNOTAVAIL] when an attempt is made to create a socket
with a network
address for which no network interface
exists.
[EACCES] when an attempt is made to create a raw
IPv6 socket by a
non-privileged process.
The following errors specific to IPv6 may occur:
[EINVAL] An unknown socket option name was given.
[EINVAL] The ancillary data items were improperly
formed, or option
name was unknown.
getsockopt(2), recv(2), send(2), setsockopt(2), inet6_option_space(3),
inet6_rthdr_space(3), icmp6(4), inet6(4)
W. Stevens and M. Thomas, Advanced Sockets API for IPv6, RFC
2292,
February 1998.
S. Deering and R. Hinden, Internet Protocol, Version 6
(IPv6)
Specification, RFC 2460, December 1998.
R. Gilligan, S. Thomson, J. Bound, and W. Stevens, Basic
Socket Interface
Extensions for IPv6, RFC 2553, March 1999.
Most of the socket options are defined in RFC 2292 and/or
RFC 2553.
IPV6_PORTRANGE and conflict resolution rule is not defined
in the RFCs
and should be considered implementation dependent.
The implementation is based on KAME stack (which is a descendant of WIDE
hydrangea IPv6 stack kit).
Part of the document was shamelessly copied from RFC 2553
and RFC 2292.
The IPV6_NEXTHOP object/option is not fully implemented as
of writing
this.
OpenBSD 3.6 December 17, 1999
[ Back ] |