summaryrefslogtreecommitdiff
path: root/doc/rfc/rfc2292.txt
diff options
context:
space:
mode:
Diffstat (limited to 'doc/rfc/rfc2292.txt')
-rw-r--r--doc/rfc/rfc2292.txt3755
1 files changed, 3755 insertions, 0 deletions
diff --git a/doc/rfc/rfc2292.txt b/doc/rfc/rfc2292.txt
new file mode 100644
index 0000000..4b7e111
--- /dev/null
+++ b/doc/rfc/rfc2292.txt
@@ -0,0 +1,3755 @@
+
+
+
+
+
+
+Network Working Group W. Stevens
+Request for Comments: 2292 Consultant
+Category: Informational M. Thomas
+ AltaVista
+ February 1998
+
+
+
+ Advanced Sockets API for IPv6
+
+
+Status of this Memo
+
+ This memo provides information for the Internet community. It does
+ not specify an Internet standard of any kind. Distribution of this
+ memo is unlimited.
+
+Copyright Notice
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+Abstract
+
+ Specifications are in progress for changes to the sockets API to
+ support IP version 6 [RFC-2133]. These changes are for TCP and UDP-
+ based applications and will support most end-user applications in use
+ today: Telnet and FTP clients and servers, HTTP clients and servers,
+ and the like.
+
+ But another class of applications exists that will also be run under
+ IPv6. We call these "advanced" applications and today this includes
+ programs such as Ping, Traceroute, routing daemons, multicast routing
+ daemons, router discovery daemons, and the like. The API feature
+ typically used by these programs that make them "advanced" is a raw
+ socket to access ICMPv4, IGMPv4, or IPv4, along with some knowledge
+ of the packet header formats used by these protocols. To provide
+ portability for applications that use raw sockets under IPv6, some
+ standardization is needed for the advanced API features.
+
+ There are other features of IPv6 that some applications will need to
+ access: interface identification (specifying the outgoing interface
+ and determining the incoming interface) and IPv6 extension headers
+ that are not addressed in [RFC-2133]: Hop-by-Hop options, Destination
+ options, and the Routing header (source routing). This document
+ provides API access to these features too.
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 1]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+Table of Contents
+
+ 1. Introduction ................................................3
+ 2. Common Structures and Definitions ...........................5
+ 2.1. The ip6_hdr Structure ..................................5
+ 2.1.1. IPv6 Next Header Values .........................6
+ 2.1.2. IPv6 Extension Headers ..........................6
+ 2.2. The icmp6_hdr Structure ................................8
+ 2.2.1. ICMPv6 Type and Code Values .....................8
+ 2.2.2. ICMPv6 Neighbor Discovery Type and Code Values ..9
+ 2.3. Address Testing Macros .................................12
+ 2.4. Protocols File .........................................12
+ 3. IPv6 Raw Sockets ............................................13
+ 3.1. Checksums ..............................................14
+ 3.2. ICMPv6 Type Filtering ..................................14
+ 4. Ancillary Data ..............................................17
+ 4.1. The msghdr Structure ...................................18
+ 4.2. The cmsghdr Structure ..................................18
+ 4.3. Ancillary Data Object Macros ...........................19
+ 4.3.1. CMSG_FIRSTHDR ...................................20
+ 4.3.2. CMSG_NXTHDR .....................................22
+ 4.3.3. CMSG_DATA .......................................22
+ 4.3.4. CMSG_SPACE ......................................22
+ 4.3.5. CMSG_LEN ........................................22
+ 4.4. Summary of Options Described Using Ancillary Data ......23
+ 4.5. IPV6_PKTOPTIONS Socket Option ..........................24
+ 4.5.1. TCP Sticky Options ..............................25
+ 4.5.2. UDP and Raw Socket Sticky Options ...............26
+ 5. Packet Information ..........................................26
+ 5.1. Specifying/Receiving the Interface .....................27
+ 5.2. Specifying/Receiving Source/Destination Address ........27
+ 5.3. Specifying/Receiving the Hop Limit .....................28
+ 5.4. Specifying the Next Hop Address ........................29
+ 5.5. Additional Errors with sendmsg() .......................29
+ 6. Hop-By-Hop Options ..........................................30
+ 6.1. Receiving Hop-by-Hop Options ...........................31
+ 6.2. Sending Hop-by-Hop Options .............................31
+ 6.3. Hop-by-Hop and Destination Options Processing ..........32
+ 6.3.1. inet6_option_space ..............................32
+ 6.3.2. inet6_option_init ...............................32
+ 6.3.3. inet6_option_append .............................33
+ 6.3.4. inet6_option_alloc ..............................33
+ 6.3.5. inet6_option_next ...............................34
+ 6.3.6. inet6_option_find ...............................35
+ 6.3.7. Options Examples ................................35
+ 7. Destination Options .........................................42
+ 7.1. Receiving Destination Options ..........................42
+ 7.2. Sending Destination Options ............................43
+
+
+
+Stevens & Thomas Informational [Page 2]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ 8. Routing Header Option .......................................43
+ 8.1. inet6_rthdr_space ......................................44
+ 8.2. inet6_rthdr_init .......................................45
+ 8.3. inet6_rthdr_add ........................................45
+ 8.4. inet6_rthdr_lasthop ....................................46
+ 8.5. inet6_rthdr_reverse ....................................46
+ 8.6. inet6_rthdr_segments ...................................46
+ 8.7. inet6_rthdr_getaddr ....................................46
+ 8.8. inet6_rthdr_getflags ...................................47
+ 8.9. Routing Header Example .................................47
+ 9. Ordering of Ancillary Data and IPv6 Extension Headers .......53
+ 10. IPv6-Specific Options with IPv4-Mapped IPv6 Addresses .......54
+ 11. rresvport_af ................................................55
+ 12. Future Items ................................................55
+ 12.1. Flow Labels ...........................................55
+ 12.2. Path MTU Discovery and UDP ............................56
+ 12.3. Neighbor Reachability and UDP .........................56
+ 13. Summary of New Definitions ..................................56
+ 14. Security Considerations .....................................59
+ 15. Change History ..............................................59
+ 16. References ..................................................65
+ 17. Acknowledgments .............................................65
+ 18. Authors' Addresses ..........................................66
+ 19. Full Copyright Statement ....................................67
+
+1. Introduction
+
+ Specifications are in progress for changes to the sockets API to
+ support IP version 6 [RFC-2133]. These changes are for TCP and UDP-
+ based applications. The current document defines some the "advanced"
+ features of the sockets API that are required for applications to
+ take advantage of additional features of IPv6.
+
+ Today, the portability of applications using IPv4 raw sockets is
+ quite high, but this is mainly because most IPv4 implementations
+ started from a common base (the Berkeley source code) or at least
+ started with the Berkeley headers. This allows programs such as Ping
+ and Traceroute, for example, to compile with minimal effort on many
+ hosts that support the sockets API. With IPv6, however, there is no
+ common source code base that implementors are starting from, and the
+ possibility for divergence at this level between different
+ implementations is high. To avoid a complete lack of portability
+ amongst applications that use raw IPv6 sockets, some standardization
+ is necessary.
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 3]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ There are also features from the basic IPv6 specification that are
+ not addressed in [RFC-2133]: sending and receiving Hop-by-Hop
+ options, Destination options, and Routing headers, specifying the
+ outgoing interface, and being told of the receiving interface.
+
+ This document can be divided into the following main sections.
+
+ 1. Definitions of the basic constants and structures required for
+ applications to use raw IPv6 sockets. This includes structure
+ definitions for the IPv6 and ICMPv6 headers and all associated
+ constants (e.g., values for the Next Header field).
+
+ 2. Some basic semantic definitions for IPv6 raw sockets. For
+ example, a raw ICMPv4 socket requires the application to
+ calculate and store the ICMPv4 header checksum. But with IPv6
+ this would require the application to choose the source IPv6
+ address because the source address is part of the pseudo header
+ that ICMPv6 now uses for its checksum computation. It should be
+ defined that with a raw ICMPv6 socket the kernel always
+ calculates and stores the ICMPv6 header checksum.
+
+ 3. Packet information: how applications can obtain the received
+ interface, destination address, and received hop limit, along
+ with specifying these values on a per-packet basis. There are a
+ class of applications that need this capability and the technique
+ should be portable.
+
+ 4. Access to the optional Hop-by-Hop, Destination, and Routing
+ headers.
+
+ 5. Additional features required for IPv6 application portability.
+
+ The packet information along with access to the extension headers
+ (Hop-by-Hop options, Destination options, and Routing header) are
+ specified using the "ancillary data" fields that were added to the
+ 4.3BSD Reno sockets API in 1990. The reason is that these ancillary
+ data fields are part of the Posix.1g standard (which should be
+ approved in 1997) and should therefore be adopted by most vendors.
+
+ This document does not address application access to either the
+ authentication header or the encapsulating security payload header.
+
+ All examples in this document omit error checking in favor of brevity
+ and clarity.
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 4]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ We note that many of the functions and socket options defined in this
+ document may have error returns that are not defined in this
+ document. Many of these possible error returns will be recognized
+ only as implementations proceed.
+
+ Datatypes in this document follow the Posix.1g format: intN_t means a
+ signed integer of exactly N bits (e.g., int16_t) and uintN_t means an
+ unsigned integer of exactly N bits (e.g., uint32_t).
+
+ Note that we use the (unofficial) terminology ICMPv4, IGMPv4, and
+ ARPv4 to avoid any confusion with the newer ICMPv6 protocol.
+
+2. Common Structures and Definitions
+
+ Many advanced applications examine fields in the IPv6 header and set
+ and examine fields in the various ICMPv6 headers. Common structure
+ definitions for these headers are required, along with common
+ constant definitions for the structure members.
+
+ Two new headers are defined: <netinet/ip6.h> and <netinet/icmp6.h>.
+
+ When an include file is specified, that include file is allowed to
+ include other files that do the actual declaration or definition.
+
+2.1. The ip6_hdr Structure
+
+ The following structure is defined as a result of including
+ <netinet/ip6.h>. Note that this is a new header.
+
+ struct ip6_hdr {
+ union {
+ struct ip6_hdrctl {
+ uint32_t ip6_un1_flow; /* 24 bits of flow-ID */
+ uint16_t ip6_un1_plen; /* payload length */
+ uint8_t ip6_un1_nxt; /* next header */
+ uint8_t ip6_un1_hlim; /* hop limit */
+ } ip6_un1;
+ uint8_t ip6_un2_vfc; /* 4 bits version, 4 bits priority */
+ } ip6_ctlun;
+ struct in6_addr ip6_src; /* source address */
+ struct in6_addr ip6_dst; /* destination address */
+ };
+
+ #define ip6_vfc ip6_ctlun.ip6_un2_vfc
+ #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow
+ #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen
+ #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt
+ #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+
+
+Stevens & Thomas Informational [Page 5]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+2.1.1. IPv6 Next Header Values
+
+ IPv6 defines many new values for the Next Header field. The
+ following constants are defined as a result of including
+ <netinet/in.h>.
+
+ #define IPPROTO_HOPOPTS 0 /* IPv6 Hop-by-Hop options */
+ #define IPPROTO_IPV6 41 /* IPv6 header */
+ #define IPPROTO_ROUTING 43 /* IPv6 Routing header */
+ #define IPPROTO_FRAGMENT 44 /* IPv6 fragmentation header */
+ #define IPPROTO_ESP 50 /* encapsulating security payload */
+ #define IPPROTO_AH 51 /* authentication header */
+ #define IPPROTO_ICMPV6 58 /* ICMPv6 */
+ #define IPPROTO_NONE 59 /* IPv6 no next header */
+ #define IPPROTO_DSTOPTS 60 /* IPv6 Destination options */
+
+ Berkeley-derived IPv4 implementations also define IPPROTO_IP to be 0.
+ This should not be a problem since IPPROTO_IP is used only with IPv4
+ sockets and IPPROTO_HOPOPTS only with IPv6 sockets.
+
+2.1.2. IPv6 Extension Headers
+
+ Six extension headers are defined for IPv6. We define structures for
+ all except the Authentication header and Encapsulating Security
+ Payload header, both of which are beyond the scope of this document.
+ The following structures are defined as a result of including
+ <netinet/ip6.h>.
+
+ /* Hop-by-Hop options header */
+ /* XXX should we pad it to force alignment on an 8-byte boundary? */
+ struct ip6_hbh {
+ uint8_t ip6h_nxt; /* next header */
+ uint8_t ip6h_len; /* length in units of 8 octets */
+ /* followed by options */
+ };
+
+ /* Destination options header */
+ /* XXX should we pad it to force alignment on an 8-byte boundary? */
+ struct ip6_dest {
+ uint8_t ip6d_nxt; /* next header */
+ uint8_t ip6d_len; /* length in units of 8 octets */
+ /* followed by options */
+ };
+
+ /* Routing header */
+ struct ip6_rthdr {
+
+
+
+Stevens & Thomas Informational [Page 6]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ uint8_t ip6r_nxt; /* next header */
+ uint8_t ip6r_len; /* length in units of 8 octets */
+ uint8_t ip6r_type; /* routing type */
+ uint8_t ip6r_segleft; /* segments left */
+ /* followed by routing type specific data */
+ };
+
+ /* Type 0 Routing header */
+ struct ip6_rthdr0 {
+ uint8_t ip6r0_nxt; /* next header */
+ uint8_t ip6r0_len; /* length in units of 8 octets */
+ uint8_t ip6r0_type; /* always zero */
+ uint8_t ip6r0_segleft; /* segments left */
+ uint8_t ip6r0_reserved; /* reserved field */
+ uint8_t ip6r0_slmap[3]; /* strict/loose bit map */
+ struct in6_addr ip6r0_addr[1]; /* up to 23 addresses */
+ };
+
+ /* Fragment header */
+ struct ip6_frag {
+ uint8_t ip6f_nxt; /* next header */
+ uint8_t ip6f_reserved; /* reserved field */
+ uint16_t ip6f_offlg; /* offset, reserved, and flag */
+ uint32_t ip6f_ident; /* identification */
+ };
+
+ #if BYTE_ORDER == BIG_ENDIAN
+ #define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */
+ #define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */
+ #define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */
+ #else /* BYTE_ORDER == LITTLE_ENDIAN */
+ #define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */
+ #define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */
+ #define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */
+ #endif
+
+ Defined constants for fields larger than 1 byte depend on the byte
+ ordering that is used. This API assumes that the fields in the
+ protocol headers are left in the network byte order, which is big-
+ endian for the Internet protocols. If not, then either these
+ constants or the fields being tested must be converted at run-time,
+ using something like htons() or htonl().
+
+ (Note: We show an implementation that supports both big-endian and
+ little-endian byte ordering, assuming a hypothetical compile-time #if
+ test to determine the byte ordering. The constant that we show,
+
+
+
+
+
+Stevens & Thomas Informational [Page 7]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ BYTE_ORDER, with values of BIG_ENDIAN and LITTLE_ENDIAN, are for
+ example purposes only. If an implementation runs on only one type of
+ hardware it need only define the set of constants for that hardware's
+ byte ordering.)
+
+2.2. The icmp6_hdr Structure
+
+ The ICMPv6 header is needed by numerous IPv6 applications including
+ Ping, Traceroute, router discovery daemons, and neighbor discovery
+ daemons. The following structure is defined as a result of including
+ <netinet/icmp6.h>. Note that this is a new header.
+
+ struct icmp6_hdr {
+ uint8_t icmp6_type; /* type field */
+ uint8_t icmp6_code; /* code field */
+ uint16_t icmp6_cksum; /* checksum field */
+ union {
+ uint32_t icmp6_un_data32[1]; /* type-specific field */
+ uint16_t icmp6_un_data16[2]; /* type-specific field */
+ uint8_t icmp6_un_data8[4]; /* type-specific field */
+ } icmp6_dataun;
+ };
+
+ #define icmp6_data32 icmp6_dataun.icmp6_un_data32
+ #define icmp6_data16 icmp6_dataun.icmp6_un_data16
+ #define icmp6_data8 icmp6_dataun.icmp6_un_data8
+ #define icmp6_pptr icmp6_data32[0] /* parameter prob */
+ #define icmp6_mtu icmp6_data32[0] /* packet too big */
+ #define icmp6_id icmp6_data16[0] /* echo request/reply */
+ #define icmp6_seq icmp6_data16[1] /* echo request/reply */
+ #define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */
+
+2.2.1. ICMPv6 Type and Code Values
+
+ In addition to a common structure for the ICMPv6 header, common
+ definitions are required for the ICMPv6 type and code fields. The
+ following constants are also defined as a result of including
+ <netinet/icmp6.h>.
+
+#define ICMP6_DST_UNREACH 1
+#define ICMP6_PACKET_TOO_BIG 2
+#define ICMP6_TIME_EXCEEDED 3
+#define ICMP6_PARAM_PROB 4
+
+#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */
+
+#define ICMP6_ECHO_REQUEST 128
+#define ICMP6_ECHO_REPLY 129
+
+
+
+Stevens & Thomas Informational [Page 8]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+#define ICMP6_MEMBERSHIP_QUERY 130
+#define ICMP6_MEMBERSHIP_REPORT 131
+#define ICMP6_MEMBERSHIP_REDUCTION 132
+
+#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with */
+ /* destination */
+ /* administratively */
+ /* prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor */
+#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
+
+#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
+#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
+
+ The five ICMP message types defined by IPv6 neighbor discovery (133-
+ 137) are defined in the next section.
+
+2.2.2. ICMPv6 Neighbor Discovery Type and Code Values
+
+ The following structures and definitions are defined as a result of
+ including <netinet/icmp6.h>.
+
+ #define ND_ROUTER_SOLICIT 133
+ #define ND_ROUTER_ADVERT 134
+ #define ND_NEIGHBOR_SOLICIT 135
+ #define ND_NEIGHBOR_ADVERT 136
+ #define ND_REDIRECT 137
+
+ struct nd_router_solicit { /* router solicitation */
+ struct icmp6_hdr nd_rs_hdr;
+ /* could be followed by options */
+ };
+
+ #define nd_rs_type nd_rs_hdr.icmp6_type
+ #define nd_rs_code nd_rs_hdr.icmp6_code
+ #define nd_rs_cksum nd_rs_hdr.icmp6_cksum
+ #define nd_rs_reserved nd_rs_hdr.icmp6_data32[0]
+
+ struct nd_router_advert { /* router advertisement */
+ struct icmp6_hdr nd_ra_hdr;
+ uint32_t nd_ra_reachable; /* reachable time */
+ uint32_t nd_ra_retransmit; /* retransmit timer */
+
+
+
+Stevens & Thomas Informational [Page 9]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ /* could be followed by options */
+ };
+
+ #define nd_ra_type nd_ra_hdr.icmp6_type
+ #define nd_ra_code nd_ra_hdr.icmp6_code
+ #define nd_ra_cksum nd_ra_hdr.icmp6_cksum
+ #define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0]
+ #define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1]
+ #define ND_RA_FLAG_MANAGED 0x80
+ #define ND_RA_FLAG_OTHER 0x40
+ #define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1]
+
+ struct nd_neighbor_solicit { /* neighbor solicitation */
+ struct icmp6_hdr nd_ns_hdr;
+ struct in6_addr nd_ns_target; /* target address */
+ /* could be followed by options */
+ };
+
+ #define nd_ns_type nd_ns_hdr.icmp6_type
+ #define nd_ns_code nd_ns_hdr.icmp6_code
+ #define nd_ns_cksum nd_ns_hdr.icmp6_cksum
+ #define nd_ns_reserved nd_ns_hdr.icmp6_data32[0]
+
+ struct nd_neighbor_advert { /* neighbor advertisement */
+ struct icmp6_hdr nd_na_hdr;
+ struct in6_addr nd_na_target; /* target address */
+ /* could be followed by options */
+ };
+
+ #define nd_na_type nd_na_hdr.icmp6_type
+ #define nd_na_code nd_na_hdr.icmp6_code
+ #define nd_na_cksum nd_na_hdr.icmp6_cksum
+ #define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0]
+ #if BYTE_ORDER == BIG_ENDIAN
+ #define ND_NA_FLAG_ROUTER 0x80000000
+ #define ND_NA_FLAG_SOLICITED 0x40000000
+ #define ND_NA_FLAG_OVERRIDE 0x20000000
+ #else /* BYTE_ORDER == LITTLE_ENDIAN */
+ #define ND_NA_FLAG_ROUTER 0x00000080
+ #define ND_NA_FLAG_SOLICITED 0x00000040
+ #define ND_NA_FLAG_OVERRIDE 0x00000020
+ #endif
+
+ struct nd_redirect { /* redirect */
+ struct icmp6_hdr nd_rd_hdr;
+ struct in6_addr nd_rd_target; /* target address */
+ struct in6_addr nd_rd_dst; /* destination address */
+ /* could be followed by options */
+
+
+
+Stevens & Thomas Informational [Page 10]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ };
+
+ #define nd_rd_type nd_rd_hdr.icmp6_type
+ #define nd_rd_code nd_rd_hdr.icmp6_code
+ #define nd_rd_cksum nd_rd_hdr.icmp6_cksum
+ #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0]
+
+ struct nd_opt_hdr { /* Neighbor discovery option header */
+ uint8_t nd_opt_type;
+ uint8_t nd_opt_len; /* in units of 8 octets */
+ /* followed by option specific data */
+ };
+
+ #define ND_OPT_SOURCE_LINKADDR 1
+ #define ND_OPT_TARGET_LINKADDR 2
+ #define ND_OPT_PREFIX_INFORMATION 3
+ #define ND_OPT_REDIRECTED_HEADER 4
+ #define ND_OPT_MTU 5
+
+ struct nd_opt_prefix_info { /* prefix information */
+ uint8_t nd_opt_pi_type;
+ uint8_t nd_opt_pi_len;
+ uint8_t nd_opt_pi_prefix_len;
+ uint8_t nd_opt_pi_flags_reserved;
+ uint32_t nd_opt_pi_valid_time;
+ uint32_t nd_opt_pi_preferred_time;
+ uint32_t nd_opt_pi_reserved2;
+ struct in6_addr nd_opt_pi_prefix;
+ };
+
+ #define ND_OPT_PI_FLAG_ONLINK 0x80
+ #define ND_OPT_PI_FLAG_AUTO 0x40
+
+ struct nd_opt_rd_hdr { /* redirected header */
+ uint8_t nd_opt_rh_type;
+ uint8_t nd_opt_rh_len;
+ uint16_t nd_opt_rh_reserved1;
+ uint32_t nd_opt_rh_reserved2;
+ /* followed by IP header and data */
+ };
+
+ struct nd_opt_mtu { /* MTU option */
+ uint8_t nd_opt_mtu_type;
+ uint8_t nd_opt_mtu_len;
+ uint16_t nd_opt_mtu_reserved;
+ uint32_t nd_opt_mtu_mtu;
+ };
+
+
+
+
+Stevens & Thomas Informational [Page 11]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ We note that the nd_na_flags_reserved flags have the same byte
+ ordering problems as we discussed with ip6f_offlg.
+
+2.3. Address Testing Macros
+
+ The basic API ([RFC-2133]) defines some macros for testing an IPv6
+ address for certain properties. This API extends those definitions
+ with additional address testing macros, defined as a result of
+ including <netinet/in.h>.
+
+ int IN6_ARE_ADDR_EQUAL(const struct in6_addr *,
+ const struct in6_addr *);
+
+2.4. Protocols File
+
+ Many hosts provide the file /etc/protocols that contains the names of
+ the various IP protocols and their protocol number (e.g., the value
+ of the protocol field in the IPv4 header for that protocol, such as 1
+ for ICMP). Some programs then call the function getprotobyname() to
+ obtain the protocol value that is then specified as the third
+ argument to the socket() function. For example, the Ping program
+ contains code of the form
+
+ struct protoent *proto;
+
+ proto = getprotobyname("icmp");
+
+ s = socket(AF_INET, SOCK_RAW, proto->p_proto);
+
+ Common names are required for the new IPv6 protocols in this file, to
+ provide portability of applications that call the getprotoXXX()
+ functions.
+
+ We define the following protocol names with the values shown. These
+ are taken from ftp://ftp.isi.edu/in-notes/iana/assignments/protocol-
+ numbers.
+
+ hopopt 0 # hop-by-hop options for ipv6
+ ipv6 41 # ipv6
+ ipv6-route 43 # routing header for ipv6
+ ipv6-frag 44 # fragment header for ipv6
+ esp 50 # encapsulating security payload for ipv6
+ ah 51 # authentication header for ipv6
+ ipv6-icmp 58 # icmp for ipv6
+ ipv6-nonxt 59 # no next header for ipv6
+ ipv6-opts 60 # destination options for ipv6
+
+
+
+
+
+Stevens & Thomas Informational [Page 12]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+3. IPv6 Raw Sockets
+
+ Raw sockets bypass the transport layer (TCP or UDP). With IPv4, raw
+ sockets are used to access ICMPv4, IGMPv4, and to read and write IPv4
+ datagrams containing a protocol field that the kernel does not
+ process. An example of the latter is a routing daemon for OSPF,
+ since it uses IPv4 protocol field 89. With IPv6 raw sockets will be
+ used for ICMPv6 and to read and write IPv6 datagrams containing a
+ Next Header field that the kernel does not process. Examples of the
+ latter are a routing daemon for OSPF for IPv6 and RSVP (protocol
+ field 46).
+
+ 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
+ later in this document. Should an application need access to the
+ complete IPv6 packet, some other technique, such as the datalink
+ interfaces BPF or DLPI, 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.
+
+ When we say "an ICMPv6 raw socket" we mean a socket created by
+ calling the socket function with the three arguments PF_INET6,
+ SOCK_RAW, and IPPROTO_ICMPV6.
+
+ Most IPv4 implementations give special treatment to a raw socket
+ created with a third argument to socket() 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
+
+
+
+Stevens & Thomas Informational [Page 13]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ when used as a next-header field). (Note: This feature was added to
+ IPv4 in 1988 by Van Jacobson to support traceroute, allowing a
+ complete IP header to be passed by the application, before the
+ IP_HDRINCL socket option was added.)
+
+3.1. Checksums
+
+ The kernel will calculate and insert the ICMPv6 checksum for ICMPv6
+ raw sockets, 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 checksum for output, and (2) verify the received
+ 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-
+ 1883]. 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.)
+
+3.2. ICMPv6 Type Filtering
+
+ ICMPv4 raw sockets receive most ICMPv4 messages received by the
+ kernel. (We say "most" and not "all" because Berkeley-derived
+ kernels never pass echo requests, timestamp requests, or address mask
+ requests to a raw socket. Instead these three messages are processed
+ entirely by the kernel.) But ICMPv6 is a superset of ICMPv4, also
+ including the functionality of IGMPv4 and ARPv4. This means that an
+ ICMPv6 raw socket can potentially receive many more messages than
+ would be received with an ICMPv4 raw socket: ICMP messages similar to
+ ICMPv4, along with neighbor solicitations, neighbor advertisements,
+ and the three group membership messages.
+
+
+
+
+
+Stevens & Thomas Informational [Page 14]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ Most applications using an ICMPv6 raw socket care about only a small
+ subset of the ICMPv6 message types. To transfer extraneous ICMPv6
+ messages from the kernel to user can incur a significant overhead.
+ Therefore this API includes a method of filtering ICMPv6 messages by
+ the ICMPv6 type field.
+
+ Each ICMPv6 raw socket has an associated filter whose datatype is
+ defined as
+
+ struct icmp6_filter;
+
+ This structure, along with the macros and constants defined later in
+ this section, are defined as a result of including the
+ <netinet/icmp6.h> header.
+
+ The current filter is fetched and stored using getsockopt() and
+ setsockopt() with a level of IPPROTO_ICMPV6 and an option name of
+ ICMP6_FILTER.
+
+ Six macros operate on an icmp6_filter structure:
+
+ void ICMP6_FILTER_SETPASSALL (struct icmp6_filter *);
+ void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *);
+
+ void ICMP6_FILTER_SETPASS ( int, struct icmp6_filter *);
+ void ICMP6_FILTER_SETBLOCK( int, struct icmp6_filter *);
+
+ int ICMP6_FILTER_WILLPASS (int, const struct icmp6_filter *);
+ int ICMP6_FILTER_WILLBLOCK(int, const struct icmp6_filter *);
+
+ The first argument to the last four macros (an integer) is an ICMPv6
+ message type, between 0 and 255. The pointer argument to all six
+ macros is a pointer to a filter that is modified by the first four
+ macros examined by the last two macros.
+
+ The first two macros, SETPASSALL and SETBLOCKALL, let us specify that
+ all ICMPv6 messages are passed to the application or that all ICMPv6
+ messages are blocked from being passed to the application.
+
+ The next two macros, SETPASS and SETBLOCK, let us specify that
+ messages of a given ICMPv6 type should be passed to the application
+ or not passed to the application (blocked).
+
+ The final two macros, WILLPASS and WILLBLOCK, return true or false
+ depending whether the specified message type is passed to the
+ application or blocked from being passed to the application by the
+ filter pointed to by the second argument.
+
+
+
+
+Stevens & Thomas Informational [Page 15]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ When an ICMPv6 raw socket is created, it will by default pass all
+ ICMPv6 message types to the application.
+
+ As an example, a program that wants to receive only router
+ advertisements could execute the following:
+
+struct icmp6_filter myfilt;
+
+fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+
+ICMP6_FILTER_SETBLOCKALL(&myfilt);
+ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &myfilt);
+setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &myfilt, sizeof(myfilt));
+
+ The filter structure is declared and then initialized to block all
+ messages types. The filter structure is then changed to allow router
+ advertisement messages to be passed to the application and the filter
+ is installed using setsockopt().
+
+ The icmp6_filter structure is similar to the fd_set datatype used
+ with the select() function in the sockets API. The icmp6_filter
+ structure is an opaque datatype and the application should not care
+ how it is implemented. All the application does with this datatype
+ is allocate a variable of this type, pass a pointer to a variable of
+ this type to getsockopt() and setsockopt(), and operate on a variable
+ of this type using the six macros that we just defined.
+
+ Nevertheless, it is worth showing a simple implementation of this
+ datatype and the six macros.
+
+struct icmp6_filter {
+ uint32_t icmp6_filt[8]; /* 8*32 = 256 bits */
+};
+
+#define ICMP6_FILTER_WILLPASS(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+#define ICMP6_FILTER_WILLBLOCK(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+#define ICMP6_FILTER_SETPASS(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))))
+#define ICMP6_FILTER_SETBLOCK(type, filterp) \
+ ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))))
+#define ICMP6_FILTER_SETPASSALL(filterp) \
+ memset((filterp), 0xFF, sizeof(struct icmp6_filter))
+#define ICMP6_FILTER_SETBLOCKALL(filterp) \
+ memset((filterp), 0, sizeof(struct icmp6_filter))
+
+
+
+
+
+Stevens & Thomas Informational [Page 16]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ (Note: These sample definitions have two limitations that an
+ implementation may want to change. The first four macros evaluate
+ their first argument two times. The second two macros require the
+ inclusion of the <string.h> header for the memset() function.)
+
+4. Ancillary Data
+
+ 4.2BSD allowed file descriptors to be transferred between separate
+ processes across a UNIX domain socket using the sendmsg() and
+ recvmsg() functions. Two members of the msghdr structure,
+ msg_accrights and msg_accrightslen, were used to send and receive the
+ descriptors. When the OSI protocols were added to 4.3BSD Reno in
+ 1990 the names of these two fields in the msghdr structure were
+ changed to msg_control and msg_controllen, because they were used by
+ the OSI protocols for "control information", although the comments in
+ the source code call this "ancillary data".
+
+ Other than the OSI protocols, the use of ancillary data has been
+ rare. In 4.4BSD, for example, the only use of ancillary data with
+ IPv4 is to return the destination address of a received UDP datagram
+ if the IP_RECVDSTADDR socket option is set. With Unix domain sockets
+ ancillary data is still used to send and receive descriptors.
+
+ Nevertheless the ancillary data fields of the msghdr structure
+ provide a clean way to pass information in addition to the data that
+ is being read or written. The inclusion of the msg_control and
+ msg_controllen members of the msghdr structure along with the cmsghdr
+ structure that is pointed to by the msg_control member is required by
+ the Posix.1g sockets API standard (which should be completed during
+ 1997).
+
+ In this document ancillary data is used to exchange the following
+ optional information between the application and the kernel:
+
+ 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.
+
+ Before describing these uses in detail, we review the definition of
+ the msghdr structure itself, the cmsghdr structure that defines an
+ ancillary data object, and some functions that operate on the
+ ancillary data objects.
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 17]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+4.1. The msghdr Structure
+
+ The msghdr structure is used by the recvmsg() and sendmsg()
+ functions. Its Posix.1g definition is:
+
+ struct msghdr {
+ void *msg_name; /* ptr to socket address structure */
+ socklen_t msg_namelen; /* size of socket address structure */
+ struct iovec *msg_iov; /* scatter/gather array */
+ size_t msg_iovlen; /* # elements in msg_iov */
+ void *msg_control; /* ancillary data */
+ socklen_t msg_controllen; /* ancillary data buffer length */
+ int msg_flags; /* flags on received message */
+ };
+
+ The structure is declared as a result of including <sys/socket.h>.
+
+ (Note: Before Posix.1g the two "void *" pointers were typically "char
+ *", and the two socklen_t members and the size_t member were
+ typically integers. Earlier drafts of Posix.1g had the two socklen_t
+ members as size_t, but Draft 6.6 of Posix.1g, apparently the final
+ draft, changed these to socklen_t to simplify binary portability for
+ 64-bit implementations and to align Posix.1g with X/Open's Networking
+ Services, Issue 5. The change in msg_control to a "void *" pointer
+ affects any code that increments this pointer.)
+
+ Most Berkeley-derived implementations limit the amount of ancillary
+ data in a call to sendmsg() to no more than 108 bytes (an mbuf).
+ This API requires a minimum of 10240 bytes of ancillary data, but it
+ is recommended that the amount be limited only by the buffer space
+ reserved by the socket (which can be modified by the SO_SNDBUF socket
+ option). (Note: This magic number 10240 was picked as a value that
+ should always be large enough. 108 bytes is clearly too small as the
+ maximum size of a Type 0 Routing header is 376 bytes.)
+
+4.2. The cmsghdr Structure
+
+ The cmsghdr structure describes ancillary data objects transferred by
+ recvmsg() and sendmsg(). Its Posix.1g definition is:
+
+ struct cmsghdr {
+ socklen_t cmsg_len; /* #bytes, including this header */
+ int cmsg_level; /* originating protocol */
+ int cmsg_type; /* protocol-specific type */
+ /* followed by unsigned char cmsg_data[]; */
+ };
+
+ This structure is declared as a result of including <sys/socket.h>.
+
+
+
+Stevens & Thomas Informational [Page 18]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ As shown in this definition, normally there is no member with the
+ name cmsg_data[]. Instead, the data portion is accessed using the
+ CMSG_xxx() macros, as described shortly. Nevertheless, it is common
+ to refer to the cmsg_data[] member.
+
+ (Note: Before Posix.1g the cmsg_len member was an integer, and not a
+ socklen_t. See the Note in the previous section for why socklen_t is
+ used here.)
+
+ When ancillary data is sent or received, any number of ancillary data
+ objects can be specified by the msg_control and msg_controllen
+ members of the msghdr structure, because each object is preceded by a
+ cmsghdr structure defining the object's length (the cmsg_len member).
+ Historically Berkeley-derived implementations have passed only one
+ object at a time, but this API allows multiple objects to be passed
+ in a single call to sendmsg() or recvmsg(). The following example
+ shows two ancillary data objects in a control buffer.
+
+|<--------------------------- msg_controllen -------------------------->|
+| |
+|<----- ancillary data object ----->|<----- ancillary data object ----->|
+|<---------- CMSG_SPACE() --------->|<---------- CMSG_SPACE() --------->|
+| | |
+|<---------- cmsg_len ---------->| |<--------- cmsg_len ----------->| |
+|<--------- CMSG_LEN() --------->| |<-------- CMSG_LEN() ---------->| |
+| | | | |
++-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+
+|cmsg_|cmsg_|cmsg_|XX| |XX|cmsg_|cmsg_|cmsg_|XX| |XX|
+|len |level|type |XX|cmsg_data[]|XX|len |level|type |XX|cmsg_data[]|XX|
++-----+-----+-----+--+-----------+--+-----+-----+-----+--+-----------+--+
+ ^
+ |
+msg_control
+points here
+
+ The fields shown as "XX" are possible padding, between the cmsghdr
+ structure and the data, and between the data and the next cmsghdr
+ structure, if required by the implementation.
+
+4.3. Ancillary Data Object Macros
+
+ To aid in the manipulation of ancillary data objects, three macros
+ from 4.4BSD are defined by Posix.1g: CMSG_DATA(), CMSG_NXTHDR(), and
+ CMSG_FIRSTHDR(). Before describing these macros, we show the
+ following example of how they might be used with a call to recvmsg().
+
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+
+
+
+Stevens & Thomas Informational [Page 19]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ /* fill in msg */
+
+ /* call recvmsg() */
+
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+ if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) {
+ u_char *ptr;
+
+ ptr = CMSG_DATA(cmsgptr);
+ /* process data pointed to by ptr */
+ }
+ }
+
+ We now describe the three Posix.1g macros, followed by two more that
+ are new with this API: CMSG_SPACE() and CMSG_LEN(). All these macros
+ are defined as a result of including <sys/socket.h>.
+
+4.3.1. CMSG_FIRSTHDR
+
+ struct cmsghdr *CMSG_FIRSTHDR(const struct msghdr *mhdr);
+
+ CMSG_FIRSTHDR() returns a pointer to the first cmsghdr structure in
+ the msghdr structure pointed to by mhdr. The macro returns NULL if
+ there is no ancillary data pointed to the by msghdr structure (that
+ is, if either msg_control is NULL or if msg_controllen is less than
+ the size of a cmsghdr structure).
+
+ One possible implementation could be
+
+ #define CMSG_FIRSTHDR(mhdr) \
+ ( (mhdr)->msg_controllen >= sizeof(struct cmsghdr) ? \
+ (struct cmsghdr *)(mhdr)->msg_control : \
+ (struct cmsghdr *)NULL )
+
+ (Note: Most existing implementations do not test the value of
+ msg_controllen, and just return the value of msg_control. The value
+ of msg_controllen must be tested, because if the application asks
+ recvmsg() to return ancillary data, by setting msg_control to point
+ to the application's buffer and setting msg_controllen to the length
+ of this buffer, the kernel indicates that no ancillary data is
+ available by setting msg_controllen to 0 on return. It is also
+ easier to put this test into this macro, than making the application
+ perform the test.)
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 20]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+4.3.2. CMSG_NXTHDR
+
+ struct cmsghdr *CMSG_NXTHDR(const struct msghdr *mhdr,
+ const struct cmsghdr *cmsg);
+
+ CMSG_NXTHDR() returns a pointer to the cmsghdr structure describing
+ the next ancillary data object. mhdr is a pointer to a msghdr
+ structure and cmsg is a pointer to a cmsghdr structure. If there is
+ not another ancillary data object, the return value is NULL.
+
+ The following behavior of this macro is new to this API: if the value
+ of the cmsg pointer is NULL, a pointer to the cmsghdr structure
+ describing the first ancillary data object is returned. That is,
+ CMSG_NXTHDR(mhdr, NULL) is equivalent to CMSG_FIRSTHDR(mhdr). If
+ there are no ancillary data objects, the return value is NULL. This
+ provides an alternative way of coding the processing loop shown
+ earlier:
+
+struct msghdr msg;
+struct cmsghdr *cmsgptr = NULL;
+
+/* fill in msg */
+
+/* call recvmsg() */
+
+while ((cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) != NULL) {
+ if (cmsgptr->cmsg_level == ... && cmsgptr->cmsg_type == ... ) {
+ u_char *ptr;
+
+ ptr = CMSG_DATA(cmsgptr);
+ /* process data pointed to by ptr */
+ }
+}
+
+ One possible implementation could be:
+
+ #define CMSG_NXTHDR(mhdr, cmsg) \
+ ( ((cmsg) == NULL) ? CMSG_FIRSTHDR(mhdr) : \
+ (((u_char *)(cmsg) + ALIGN((cmsg)->cmsg_len) \
+ + ALIGN(sizeof(struct cmsghdr)) > \
+ (u_char *)((mhdr)->msg_control) + (mhdr)->msg_controllen) ? \
+ (struct cmsghdr *)NULL : \
+ (struct cmsghdr *)((u_char *)(cmsg) + ALIGN((cmsg)->cmsg_len))) )
+
+ The macro ALIGN(), which is implementation dependent, rounds its
+ argument up to the next even multiple of whatever alignment is
+ required (probably a multiple of 4 or 8 bytes).
+
+
+
+
+Stevens & Thomas Informational [Page 21]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+4.3.3. CMSG_DATA
+
+ unsigned char *CMSG_DATA(const struct cmsghdr *cmsg);
+
+ CMSG_DATA() returns a pointer to the data (what is called the
+ cmsg_data[] member, even though such a member is not defined in the
+ structure) following a cmsghdr structure.
+
+ One possible implementation could be:
+
+ #define CMSG_DATA(cmsg) ( (u_char *)(cmsg) + \
+ ALIGN(sizeof(struct cmsghdr)) )
+
+4.3.4. CMSG_SPACE
+
+ unsigned int CMSG_SPACE(unsigned int length);
+
+ This macro is new with this API. Given the length of an ancillary
+ data object, CMSG_SPACE() returns the space required by the object
+ and its cmsghdr structure, including any padding needed to satisfy
+ alignment requirements. This macro can be used, for example, to
+ allocate space dynamically for the ancillary data. This macro should
+ not be used to initialize the cmsg_len member of a cmsghdr structure;
+ instead use the CMSG_LEN() macro.
+
+ One possible implementation could be:
+
+ #define CMSG_SPACE(length) ( ALIGN(sizeof(struct cmsghdr)) + \
+ ALIGN(length) )
+
+4.3.5. CMSG_LEN
+
+ unsigned int CMSG_LEN(unsigned int length);
+
+ This macro is new with this API. Given the length of an ancillary
+ data object, CMSG_LEN() returns the value to store in the cmsg_len
+ member of the cmsghdr structure, taking into account any padding
+ needed to satisfy alignment requirements.
+
+ One possible implementation could be:
+
+ #define CMSG_LEN(length) ( ALIGN(sizeof(struct cmsghdr)) + length
+ )
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 22]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ 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 which are described in [RFC-2133]. Specifying the
+ hop limit as ancillary data lets the application override either the
+ kernel's default or a previously specified value, for either a
+ unicast destination or a multicast destination, for a single output
+ operation. Returning the received hop limit is useful for programs
+ such as Traceroute and for IPv6 applications that need to verify that
+ the received hop limit is 255 (e.g., that the packet has not been
+ forwarded).
+
+ The received hop limit is returned as ancillary data by recvmsg()
+ only if the application has enabled the IPV6_HOPLIMIT socket option:
+
+ int on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &on, sizeof(on));
+
+ In the cmsghdr structure containing this ancillary data, the
+ cmsg_level member will be IPPROTO_IPV6, the cmsg_type member will be
+ IPV6_HOPLIMIT, and the first byte of cmsg_data[] will be the first
+ byte of the integer hop limit.
+
+ Nothing special need be done to specify the outgoing hop limit: just
+ specify the control information as ancillary data for sendmsg(). As
+ specified in [RFC-2133], the interpretation of the integer hop limit
+ value is
+
+
+
+Stevens & Thomas Informational [Page 28]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ x < -1: return an error of EINVAL
+ x == -1: use kernel default
+ 0 <= x <= 255: use x
+ x >= 256: return an error of EINVAL
+
+5.4. Specifying the Next Hop Address
+
+ 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.
+
+ This is a privileged option. (Note: It is implementation defined and
+ beyond the scope of this document to define what "privileged" means.
+ Unix systems use this term to mean the process must have an effective
+ user ID of 0.)
+
+ If the socket address structure contains an IPv6 address (e.g., 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.
+
+5.5. Additional Errors with sendmsg()
+
+ With the IPV6_PKTINFO socket option there are no additional errors
+ possible with the call to recvmsg(). But when specifying the
+ outgoing interface or the source address, additional errors are
+ possible from sendmsg(). The following are examples, but some of
+ these may not be provided by some implementations, and some
+ implementations may define additional errors:
+
+ ENXIO The interface specified by ipi6_ifindex does not exist.
+
+ ENETDOWN The interface specified by ipi6_ifindex is not enabled
+ for IPv6 use.
+
+ EADDRNOTAVAIL ipi6_ifindex specifies an interface but the address
+ ipi6_addr is not available for use on that interface.
+
+ EHOSTUNREACH No route to the destination exists over the interface
+ specified by ifi6_ifindex.
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 29]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+6. Hop-By-Hop Options
+
+ A variable number of Hop-by-Hop options can appear in a single Hop-
+ by-Hop options header. Each option in the header is TLV-encoded with
+ a type, length, and value.
+
+ Today only three Hop-by-Hop options are defined for IPv6 [RFC-1883]:
+ Jumbo Payload, Pad1, and PadN, although a proposal exists for a
+ router-alert Hop-by-Hop option. The Jumbo Payload option should not
+ be passed back to an application and an application should receive an
+ error if it attempts to set it. This option is processed entirely by
+ the kernel. It is indirectly specified by datagram-based
+ applications as the size of the datagram to send and indirectly
+ passed back to these applications as the length of the received
+ datagram. The two pad options are for alignment purposes and are
+ automatically inserted by a sending kernel when needed and ignored by
+
+ the receiving kernel. This section of the API is therefore defined
+ for future Hop-by-Hop options that an application may need to specify
+ and receive.
+
+ Individual Hop-by-Hop options (and Destination options, which are
+ described shortly, and which are similar to the Hop-by-Hop options)
+ may have specific alignment requirements. For example, the 4-byte
+ Jumbo Payload length should appear on a 4-byte boundary, and IPv6
+ addresses are normally aligned on an 8-byte boundary. These
+ requirements and the terminology used with these options are
+ discussed in Section 4.2 and Appendix A of [RFC-1883]. The alignment
+ of each option is specified by two values, called x and y, written as
+ "xn + y". This states that the option must appear at an integer
+ multiple of x bytes from the beginning of the options header (x can
+ have the values 1, 2, 4, or 8), plus y bytes (y can have a value
+ between 0 and 7, inclusive). The Pad1 and PadN options are inserted
+ as needed to maintain the required alignment. Whatever code builds
+ either a Hop-by-Hop options header or a Destination options header
+ must know the values of x and y for each option.
+
+ Multiple Hop-by-Hop options can be specified by the application.
+ Normally one ancillary data object describes all the Hop-by-Hop
+ options (since each option is itself TLV-encoded) but the application
+ can specify multiple ancillary data objects for the Hop-by-Hop
+ options, each object specifying one or more options. Care must be
+ taken designing the API for these options since
+
+ 1. it may be possible for some future Hop-by-Hop options to be
+ generated by the application and processed entirely by the
+ application (e.g., the kernel may not know the alignment
+ restrictions for the option),
+
+
+
+Stevens & Thomas Informational [Page 30]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ 2. it must be possible for the kernel to insert its own Hop-by-Hop
+ options in an outgoing packet (e.g., the Jumbo Payload option),
+
+ 3. the application can place one or more Hop-by-Hop options into a
+ single ancillary data object,
+
+ 4. if the application specifies multiple ancillary data objects,
+ each containing one or more Hop-by-Hop options, the kernel must
+ combine these a single Hop-by-Hop options header, and
+
+ 5. it must be possible for the kernel to remove some Hop-by-Hop
+ options from a received packet before returning the remaining
+ Hop-by-Hop options to the application. (This removal might
+ consist of the kernel converting the option into a pad option of
+ the same length.)
+
+ Finally, we note that access to some Hop-by-Hop options or to some
+ Destination options, might require special privilege. That is,
+ normal applications (without special privilege) might be forbidden
+ from setting certain options in outgoing packets, and might never see
+ certain options in received packets.
+
+6.1. Receiving Hop-by-Hop Options
+
+ To receive Hop-by-Hop options the application must enable the
+ IPV6_HOPOPTS socket option:
+
+ int on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_HOPOPTS, &on, sizeof(on));
+
+ All the Hop-by-Hop options are returned as one ancillary data object
+ described by a cmsghdr structure. The cmsg_level member will be
+ IPPROTO_IPV6 and the cmsg_type member will be IPV6_HOPOPTS. These
+ options are then processed by calling the inet6_option_next() and
+ inet6_option_find() functions, described shortly.
+
+6.2. Sending Hop-by-Hop Options
+
+ To send one or more Hop-by-Hop options, the application just
+ specifies them as ancillary data in a call to sendmsg(). No socket
+ option need be set.
+
+ Normally all the Hop-by-Hop options are specified by a single
+ ancillary data object. Multiple ancillary data objects, each
+ containing one or more Hop-by-Hop options, can also be specified, in
+ which case the kernel will combine all the Hop-by-Hop options into a
+ single Hop-by-Hop extension header. But it should be more efficient
+ to use a single ancillary data object to describe all the Hop-by-Hop
+
+
+
+Stevens & Thomas Informational [Page 31]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ options. The cmsg_level member is set to IPPROTO_IPV6 and the
+ cmsg_type member is set to IPV6_HOPOPTS. The option is normally
+ constructed using the inet6_option_init(), inet6_option_append(), and
+ inet6_option_alloc() functions, described shortly.
+
+ Additional errors may be possible from sendmsg() if the specified
+ option is in error.
+
+6.3. Hop-by-Hop and Destination Options Processing
+
+ Building and parsing the Hop-by-Hop and Destination options is
+ complicated for the reasons given earlier. We therefore define a set
+ of functions to help the application. The function prototypes for
+ these functions are all in the <netinet/in.h> header.
+
+6.3.1. inet6_option_space
+
+ int inet6_option_space(int nbytes);
+
+ This function returns the number of bytes required to hold an option
+ when it is stored as ancillary data, including the cmsghdr structure
+ at the beginning, and any padding at the end (to make its size a
+ multiple of 8 bytes). The argument is the size of the structure
+ defining the option, which must include any pad bytes at the
+ beginning (the value y in the alignment term "xn + y"), the type
+ byte, the length byte, and the option data.
+
+ (Note: If multiple options are stored in a single ancillary data
+ object, which is the recommended technique, this function
+ overestimates the amount of space required by the size of N-1 cmsghdr
+ structures, where N is the number of options to be stored in the
+ object. This is of little consequence, since it is assumed that most
+ Hop-by-Hop option headers and Destination option headers carry only
+ one option (p. 33 of [RFC-1883]).)
+
+6.3.2. inet6_option_init
+
+ int inet6_option_init(void *bp, struct cmsghdr **cmsgp, int
+ type);
+
+ This function is called once per ancillary data object that will
+ contain either Hop-by-Hop or Destination options. It returns 0 on
+ success or -1 on an error.
+
+ bp is a pointer to previously allocated space that will contain the
+ ancillary data object. It must be large enough to contain all the
+ individual options to be added by later calls to
+ inet6_option_append() and inet6_option_alloc().
+
+
+
+Stevens & Thomas Informational [Page 32]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ cmsgp is a pointer to a pointer to a cmsghdr structure. *cmsgp is
+ initialized by this function to point to the cmsghdr structure
+ constructed by this function in the buffer pointed to by bp.
+
+ type is either IPV6_HOPOPTS or IPV6_DSTOPTS. This type is stored in
+ the cmsg_type member of the cmsghdr structure pointed to by *cmsgp.
+
+6.3.3. inet6_option_append
+
+
+ int inet6_option_append(struct cmsghdr *cmsg, const uint8_t *typep,
+ int multx, int plusy);
+
+ This function appends a Hop-by-Hop option or a Destination option
+ into an ancillary data object that has been initialized by
+ inet6_option_init(). This function returns 0 if it succeeds or -1 on
+ an error.
+
+ cmsg is a pointer to the cmsghdr structure that must have been
+ initialized by inet6_option_init().
+
+ typep is a pointer to the 8-bit option type. It is assumed that this
+ field is immediately followed by the 8-bit option data length field,
+ which is then followed immediately by the option data. The caller
+ initializes these three fields (the type-length-value, or TLV) before
+ calling this function.
+
+ The option type must have a value from 2 to 255, inclusive. (0 and 1
+ are reserved for the Pad1 and PadN options, respectively.)
+
+ The option data length must have a value between 0 and 255,
+ inclusive, and is the length of the option data that follows.
+
+ multx is the value x in the alignment term "xn + y" described
+ earlier. It must have a value of 1, 2, 4, or 8.
+
+ plusy is the value y in the alignment term "xn + y" described
+ earlier. It must have a value between 0 and 7, inclusive.
+
+6.3.4. inet6_option_alloc
+
+ uint8_t *inet6_option_alloc(struct cmsghdr *cmsg, int datalen,
+ int multx, int plusy);
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 33]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ This function appends a Hop-by-Hop option or a Destination option
+ into an ancillary data object that has been initialized by
+ inet6_option_init(). This function returns a pointer to the 8-bit
+ option type field that starts the option on success, or NULL on an
+ error.
+
+ The difference between this function and inet6_option_append() is
+ that the latter copies the contents of a previously built option into
+ the ancillary data object while the current function returns a
+ pointer to the space in the data object where the option's TLV must
+ then be built by the caller.
+
+ cmsg is a pointer to the cmsghdr structure that must have been
+ initialized by inet6_option_init().
+
+ datalen is the value of the option data length byte for this option.
+ This value is required as an argument to allow the function to
+ determine if padding must be appended at the end of the option. (The
+ inet6_option_append() function does not need a data length argument
+ since the option data length must already be stored by the caller.)
+
+ multx is the value x in the alignment term "xn + y" described
+ earlier. It must have a value of 1, 2, 4, or 8.
+
+ plusy is the value y in the alignment term "xn + y" described
+ earlier. It must have a value between 0 and 7, inclusive.
+
+6.3.5. inet6_option_next
+
+ int inet6_option_next(const struct cmsghdr *cmsg, uint8_t
+ **tptrp);
+
+ This function processes the next Hop-by-Hop option or Destination
+ option in an ancillary data object. If another option remains to be
+ processed, the return value of the function is 0 and *tptrp points to
+ the 8-bit option type field (which is followed by the 8-bit option
+ data length, followed by the option data). If no more options remain
+ to be processed, the return value is -1 and *tptrp is NULL. If an
+ error occurs, the return value is -1 and *tptrp is not NULL.
+
+ cmsg is a pointer to cmsghdr structure of which cmsg_level equals
+ IPPROTO_IPV6 and cmsg_type equals either IPV6_HOPOPTS or
+ IPV6_DSTOPTS.
+
+ tptrp is a pointer to a pointer to an 8-bit byte and *tptrp is used
+ by the function to remember its place in the ancillary data object
+ each time the function is called. The first time this function is
+ called for a given ancillary data object, *tptrp must be set to NULL.
+
+
+
+Stevens & Thomas Informational [Page 34]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ Each time this function returns success, *tptrp points to the 8-bit
+ option type field for the next option to be processed.
+
+6.3.6. inet6_option_find
+
+ int inet6_option_find(const struct cmsghdr *cmsg, uint8_t *tptrp,
+ int type);
+
+ This function is similar to the previously described
+ inet6_option_next() function, except this function lets the caller
+ specify the option type to be searched for, instead of always
+ returning the next option in the ancillary data object. cmsg is a
+ pointer to cmsghdr structure of which cmsg_level equals IPPROTO_IPV6
+ and cmsg_type equals either IPV6_HOPOPTS or IPV6_DSTOPTS.
+
+ tptrp is a pointer to a pointer to an 8-bit byte and *tptrp is used
+ by the function to remember its place in the ancillary data object
+ each time the function is called. The first time this function is
+ called for a given ancillary data object, *tptrp must be set to NULL.
+
+ This function starts searching for an option of the specified type
+ beginning after the value of *tptrp. If an option of the specified
+ type is located, this function returns 0 and *tptrp points to the 8-
+ bit option type field for the option of the specified type. If an
+ option of the specified type is not located, the return value is -1
+ and *tptrp is NULL. If an error occurs, the return value is -1 and
+ *tptrp is not NULL.
+
+6.3.7. Options Examples
+
+ We now provide an example that builds two Hop-by-Hop options. First
+ we define two options, called X and Y, taken from the example in
+ Appendix A of [RFC-1883]. We assume that all options will have
+ structure definitions similar to what is shown below.
+
+ /* option X and option Y are defined in [RFC-1883], pp. 33-34 */
+#define IP6_X_OPT_TYPE X /* replace X with assigned value */
+#define IP6_X_OPT_LEN 12
+#define IP6_X_OPT_MULTX 8 /* 8n + 2 alignment */
+#define IP6_X_OPT_OFFSETY 2
+
+struct ip6_X_opt {
+ uint8_t ip6_X_opt_pad[IP6_X_OPT_OFFSETY];
+ uint8_t ip6_X_opt_type;
+ uint8_t ip6_X_opt_len;
+ uint32_t ip6_X_opt_val1;
+ uint64_t ip6_X_opt_val2;
+};
+
+
+
+Stevens & Thomas Informational [Page 35]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+#define IP6_Y_OPT_TYPE Y /* replace Y with assigned value */
+#define IP6_Y_OPT_LEN 7
+#define IP6_Y_OPT_MULTX 4 /* 4n + 3 alignment */
+#define IP6_Y_OPT_OFFSETY 3
+
+struct ip6_Y_opt {
+ uint8_t ip6_Y_opt_pad[IP6_Y_OPT_OFFSETY];
+ uint8_t ip6_Y_opt_type;
+ uint8_t ip6_Y_opt_len;
+ uint8_t ip6_Y_opt_val1;
+ uint16_t ip6_Y_opt_val2;
+ uint32_t ip6_Y_opt_val3;
+};
+
+ We now show the code fragment to build one ancillary data object
+ containing both options.
+
+struct msghdr msg;
+struct cmsghdr *cmsgptr;
+struct ip6_X_opt optX;
+struct ip6_Y_opt optY;
+
+msg.msg_control = malloc(inet6_option_space(sizeof(optX) +
+ sizeof(optY)));
+
+inet6_option_init(msg.msg_control, &cmsgptr, IPV6_HOPOPTS);
+
+optX.ip6_X_opt_type = IP6_X_OPT_TYPE;
+optX.ip6_X_opt_len = IP6_X_OPT_LEN;
+optX.ip6_X_opt_val1 = <32-bit value>;
+optX.ip6_X_opt_val2 = <64-bit value>;
+inet6_option_append(cmsgptr, &optX.ip6_X_opt_type,
+ IP6_X_OPT_MULTX, IP6_X_OPT_OFFSETY);
+
+optY.ip6_Y_opt_type = IP6_Y_OPT_TYPE;
+optY.ip6_Y_opt_len = IP6_Y_OPT_LEN;
+optY.ip6_Y_opt_val1 = <8-bit value>;
+optY.ip6_Y_opt_val2 = <16-bit value>;
+optY.ip6_Y_opt_val3 = <32-bit value>;
+inet6_option_append(cmsgptr, &optY.ip6_Y_opt_type,
+ IP6_Y_OPT_MULTX, IP6_Y_OPT_OFFSETY);
+
+msg.msg_controllen = cmsgptr->cmsg_len;
+
+ The call to inet6_option_init() builds the cmsghdr structure in the
+ control buffer.
+
+
+
+
+
+Stevens & Thomas Informational [Page 36]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = CMSG_LEN(0) = 12 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_HOPOPTS |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Here we assume a 32-bit architecture where sizeof(struct cmsghdr)
+ equals 12, with a desired alignment of 4-byte boundaries (that is,
+ the ALIGN() macro shown in the sample implementations of the
+ CMSG_xxx() macros rounds up to a multiple of 4).
+
+ The first call to inet6_option_append() appends the X option. Since
+ this is the first option in the ancillary data object, 2 bytes are
+ allocated for the Next Header byte and for the Hdr Ext Len byte. The
+ former will be set by the kernel, depending on the type of header
+ that follows this header, and the latter byte is set to 1. These 2
+ bytes form the 2 bytes of padding (IP6_X_OPT_OFFSETY) required at the
+ beginning of this option.
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 28 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_HOPOPTS |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=1 | Option Type=X |Opt Data Len=12|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 4-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + 8-octet field +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The cmsg_len member of the cmsghdr structure is incremented by 16,
+ the size of the option.
+
+ The next call to inet6_option_append() appends the Y option to the
+ ancillary data object.
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 37]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 44 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_HOPOPTS |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=3 | Option Type=X |Opt Data Len=12|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 4-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + 8-octet field +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | PadN Option=1 |Opt Data Len=1 | 0 | Option Type=Y |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Opt Data Len=7 | 1-octet field | 2-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 4-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | PadN Option=1 |Opt Data Len=2 | 0 | 0 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ 16 bytes are appended by this function, so cmsg_len becomes 44. The
+ inet6_option_append() function notices that the appended data
+ requires 4 bytes of padding at the end, to make the size of the
+ ancillary data object a multiple of 8, and appends the PadN option
+ before returning. The Hdr Ext Len byte is incremented by 2 to become
+ 3.
+
+ Alternately, the application could build two ancillary data objects,
+ one per option, although this will probably be less efficient than
+ combining the two options into a single ancillary data object (as
+ just shown). The kernel must combine these into a single Hop-by-Hop
+ extension header in the final IPv6 packet.
+
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ struct ip6_X_opt optX;
+ struct ip6_Y_opt optY;
+
+ msg.msg_control = malloc(inet6_option_space(sizeof(optX)) +
+ inet6_option_space(sizeof(optY)));
+
+ inet6_option_init(msg.msg_control, &cmsgptr, IPPROTO_HOPOPTS);
+
+ optX.ip6_X_opt_type = IP6_X_OPT_TYPE;
+
+
+
+Stevens & Thomas Informational [Page 38]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ optX.ip6_X_opt_len = IP6_X_OPT_LEN;
+ optX.ip6_X_opt_val1 = <32-bit value>;
+ optX.ip6_X_opt_val2 = <64-bit value>;
+ inet6_option_append(cmsgptr, &optX.ip6_X_opt_type,
+ IP6_X_OPT_MULTX, IP6_X_OPT_OFFSETY);
+ msg.msg_controllen = CMSG_SPACE(sizeof(optX));
+
+ inet6_option_init((u_char *)msg.msg_control + msg.msg_controllen,
+ &cmsgptr, IPPROTO_HOPOPTS);
+
+ optY.ip6_Y_opt_type = IP6_Y_OPT_TYPE;
+ optY.ip6_Y_opt_len = IP6_Y_OPT_LEN;
+ optY.ip6_Y_opt_val1 = <8-bit value>;
+ optY.ip6_Y_opt_val2 = <16-bit value>;
+ optY.ip6_Y_opt_val3 = <32-bit value>;
+ inet6_option_append(cmsgptr, &optY.ip6_Y_opt_type,
+ IP6_Y_OPT_MULTX, IP6_Y_OPT_OFFSETY);
+ msg.msg_controllen += cmsgptr->cmsg_len;
+
+ Each call to inet6_option_init() builds a new cmsghdr structure, and
+ the final result looks like the following:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 39]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 28 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_HOPOPTS |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=1 | Option Type=X |Opt Data Len=12|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 4-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + 8-octet field +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 28 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_HOPOPTS |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=1 | Pad1 Option=0 | Option Type=Y |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ |Opt Data Len=7 | 1-octet field | 2-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 4-octet field |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | PadN Option=1 |Opt Data Len=2 | 0 | 0 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ When the kernel combines these two options into a single Hop-by-Hop
+ extension header, the first 3 bytes of the second ancillary data
+ object (the Next Header byte, the Hdr Ext Len byte, and the Pad1
+ option) will be combined into a PadN option occupying 3 bytes.
+
+ The following code fragment is a redo of the first example shown
+ (building two options in a single ancillary data object) but this
+ time we use inet6_option_alloc().
+
+uint8_t *typep;
+struct msghdr msg;
+struct cmsghdr *cmsgptr;
+struct ip6_X_opt *optXp; /* now a pointer, not a struct */
+struct ip6_Y_opt *optYp; /* now a pointer, not a struct */
+
+msg.msg_control = malloc(inet6_option_space(sizeof(*optXp) +
+ sizeof(*optYp)));
+
+
+
+
+Stevens & Thomas Informational [Page 40]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+inet6_option_init(msg.msg_control, &cmsgptr, IPV6_HOPOPTS);
+
+typep = inet6_option_alloc(cmsgptr, IP6_X_OPT_LEN,
+ IP6_X_OPT_MULTX, IP6_X_OPT_OFFSETY);
+optXp = (struct ip6_X_opt *) (typep - IP6_X_OPT_OFFSETY);
+optXp->ip6_X_opt_type = IP6_X_OPT_TYPE;
+optXp->ip6_X_opt_len = IP6_X_OPT_LEN;
+optXp->ip6_X_opt_val1 = <32-bit value>;
+optXp->ip6_X_opt_val2 = <64-bit value>;
+
+typep = inet6_option_alloc(cmsgptr, IP6_Y_OPT_LEN,
+ IP6_Y_OPT_MULTX, IP6_Y_OPT_OFFSETY);
+optYp = (struct ip6_Y_opt *) (typep - IP6_Y_OPT_OFFSETY);
+optYp->ip6_Y_opt_type = IP6_Y_OPT_TYPE;
+optYp->ip6_Y_opt_len = IP6_Y_OPT_LEN;
+optYp->ip6_Y_opt_val1 = <8-bit value>;
+optYp->ip6_Y_opt_val2 = <16-bit value>;
+optYp->ip6_Y_opt_val3 = <32-bit value>;
+
+msg.msg_controllen = cmsgptr->cmsg_len;
+
+ Notice that inet6_option_alloc() returns a pointer to the 8-bit
+ option type field. If the program wants a pointer to an option
+ structure that includes the padding at the front (as shown in our
+ definitions of the ip6_X_opt and ip6_Y_opt structures), the y-offset
+ at the beginning of the structure must be subtracted from the
+ returned pointer.
+
+ The following code fragment shows the processing of Hop-by-Hop
+ options using the inet6_option_next() function.
+
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+
+ /* fill in msg */
+
+ /* call recvmsg() */
+
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+ if (cmsgptr->cmsg_level == IPPROTO_IPV6 &&
+ cmsgptr->cmsg_type == IPV6_HOPOPTS) {
+
+ uint8_t *tptr = NULL;
+
+ while (inet6_option_next(cmsgptr, &tptr) == 0) {
+ if (*tptr == IP6_X_OPT_TYPE) {
+ struct ip6_X_opt *optXp;
+
+
+
+Stevens & Thomas Informational [Page 41]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ optXp = (struct ip6_X_opt *) (tptr - IP6_X_OPT_OFFSETY);
+ <do whatever with> optXp->ip6_X_opt_val1;
+ <do whatever with> optXp->ip6_X_opt_val2;
+
+ } else if (*tptr == IP6_Y_OPT_TYPE) {
+ struct ip6_Y_opt *optYp;
+
+ optYp = (struct ip6_Y_opt *) (tptr - IP6_Y_OPT_OFFSETY);
+ <do whatever with> optYp->ip6_Y_opt_val1;
+ <do whatever with> optYp->ip6_Y_opt_val2;
+ <do whatever with> optYp->ip6_Y_opt_val3;
+ }
+ }
+ if (tptr != NULL)
+ <error encountered by inet6_option_next()>;
+ }
+ }
+
+7. Destination Options
+
+ A variable number of Destination options can appear in one or more
+ Destination option headers. As defined in [RFC-1883], a Destination
+ options header appearing before a Routing header is processed by the
+ first destination plus any subsequent destinations specified in the
+ Routing header, while a Destination options header appearing after a
+ Routing header is processed only by the final destination. As with
+ the Hop-by-Hop options, each option in a Destination options header
+ is TLV-encoded with a type, length, and value.
+
+ Today no Destination options are defined for IPv6 [RFC-1883],
+ although proposals exist to use Destination options with mobility and
+ anycasting.
+
+7.1. Receiving Destination Options
+
+ To receive Destination options the application must enable the
+ IPV6_DSTOPTS socket option:
+
+ int on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_DSTOPTS, &on, sizeof(on));
+
+ All the Destination options appearing before a Routing header are
+ returned as one ancillary data object described by a cmsghdr
+ structure and all the Destination options appearing after a Routing
+ header are returned as another ancillary data object described by a
+ cmsghdr structure. For these ancillary data objects, the cmsg_level
+
+
+
+
+
+Stevens & Thomas Informational [Page 42]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ member will be IPPROTO_IPV6 and the cmsg_type member will be
+ IPV6_HOPOPTS. These options are then processed by calling the
+ inet6_option_next() and inet6_option_find() functions.
+
+7.2. Sending Destination Options
+
+ To send one or more Destination options, the application just
+ specifies them as ancillary data in a call to sendmsg(). No socket
+ option need be set.
+
+ As described earlier, one set of Destination options can appear
+ before a Routing header, and one set can appear after a Routing
+ header. Each set can consist of one or more options.
+
+ Normally all the Destination options in a set are specified by a
+ single ancillary data object, since each option is itself TLV-
+ encoded. Multiple ancillary data objects, each containing one or
+ more Destination options, can also be specified, in which case the
+ kernel will combine all the Destination options in the set into a
+ single Destination extension header. But it should be more efficient
+ to use a single ancillary data object to describe all the Destination
+ options in a set. The cmsg_level member is set to IPPROTO_IPV6 and
+ the cmsg_type member is set to IPV6_DSTOPTS. The option is normally
+ constructed using the inet6_option_init(), inet6_option_append(), and
+ inet6_option_alloc() functions.
+
+ Additional errors may be possible from sendmsg() if the specified
+ option is in error.
+
+8. Routing Header Option
+
+ Source routing in IPv6 is accomplished by specifying a Routing header
+ as an extension header. There can be different types of Routing
+ headers, but IPv6 currently defines only the Type 0 Routing header
+ [RFC-1883]. This type supports up to 23 intermediate nodes. With
+ this maximum number of intermediate nodes, a source, and a
+ destination, there are 24 hops, each of which is defined as a strict
+ or loose hop.
+
+ Source routing with IPv4 sockets API (the IP_OPTIONS socket option)
+ requires the application to build the source route in the format that
+ appears as the IPv4 header option, requiring intimate knowledge of
+ the IPv4 options format. This IPv6 API, however, defines eight
+ functions that the application calls to build and examine a Routing
+ header. Four functions build a Routing header:
+
+ inet6_rthdr_space() - return #bytes required for ancillary data
+ inet6_rthdr_init() - initialize ancillary data for Routing header
+
+
+
+Stevens & Thomas Informational [Page 43]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ inet6_rthdr_add() - add IPv6 address & flags to Routing header
+ inet6_rthdr_lasthop() - specify the flags for the final hop
+
+ Four functions deal with a returned Routing header:
+
+ inet6_rthdr_reverse() - reverse a Routing header
+ inet6_rthdr_segments() - return #segments in a Routing header
+ inet6_rthdr_getaddr() - fetch one address from a Routing header
+ inet6_rthdr_getflags() - fetch one flag from a Routing header
+
+ The function prototypes for these functions are all in the
+ <netinet/in.h> header.
+
+ To receive a Routing header the application must enable the
+ IPV6_RTHDR socket option:
+
+ int on = 1;
+ setsockopt(fd, IPPROTO_IPV6, IPV6_RTHDR, &on, sizeof(on));
+
+ To send a Routing header the application just specifies it as
+ ancillary data in a call to sendmsg().
+
+ A Routing header is passed between the application and the kernel as
+ an ancillary data object. The cmsg_level member has a value of
+ IPPROTO_IPV6 and the cmsg_type member has a value of IPV6_RTHDR. The
+ contents of the cmsg_data[] member is implementation dependent and
+ should not be accessed directly by the application, but should be
+ accessed using the eight functions that we are about to describe.
+
+ The following constants are defined in the <netinet/in.h> header:
+
+ #define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor */
+ #define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor */
+
+ #define IPV6_RTHDR_TYPE_0 0 /* IPv6 Routing header type 0 */
+
+ When a Routing header is specified, the destination address specified
+ for connect(), sendto(), or sendmsg() is the final destination
+ address of the datagram. The Routing header then contains the
+ addresses of all the intermediate nodes.
+
+8.1. inet6_rthdr_space
+
+ size_t inet6_rthdr_space(int type, int segments);
+
+ This function returns the number of bytes required to hold a Routing
+ header of the specified type containing the specified number of
+
+
+
+
+Stevens & Thomas Informational [Page 44]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ segments (addresses). For an IPv6 Type 0 Routing header, the number
+ of segments must be between 1 and 23, inclusive. The return value
+ includes the size of the cmsghdr structure that precedes the Routing
+ header, and any required padding.
+
+ If the return value is 0, then either the type of the Routing header
+ is not supported by this implementation or the number of segments is
+ invalid for this type of Routing header.
+
+ (Note: This function returns the size but does not allocate the space
+ required for the ancillary data. This allows an application to
+ allocate a larger buffer, if other ancillary data objects are
+ desired, since all the ancillary data objects must be specified to
+ sendmsg() as a single msg_control buffer.)
+
+8.2. inet6_rthdr_init
+
+ struct cmsghdr *inet6_rthdr_init(void *bp, int type);
+
+ This function initializes the buffer pointed to by bp to contain a
+ cmsghdr structure followed by a Routing header of the specified type.
+ The cmsg_len member of the cmsghdr structure is initialized to the
+ size of the structure plus the amount of space required by the
+ Routing header. The cmsg_level and cmsg_type members are also
+ initialized as required.
+
+ The caller must allocate the buffer and its size can be determined by
+ calling inet6_rthdr_space().
+
+ Upon success the return value is the pointer to the cmsghdr
+ structure, and this is then used as the first argument to the next
+ two functions. Upon an error the return value is NULL.
+
+8.3. inet6_rthdr_add
+
+ int inet6_rthdr_add(struct cmsghdr *cmsg,
+ const struct in6_addr *addr, unsigned int flags);
+
+ This function adds the address pointed to by addr to the end of the
+ Routing header being constructed and sets the type of this hop to the
+ value of flags. For an IPv6 Type 0 Routing header, flags must be
+ either IPV6_RTHDR_LOOSE or IPV6_RTHDR_STRICT.
+
+ If successful, the cmsg_len member of the cmsghdr structure is
+ updated to account for the new address in the Routing header and the
+ return value of the function is 0. Upon an error the return value of
+ the function is -1.
+
+
+
+
+Stevens & Thomas Informational [Page 45]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+8.4. inet6_rthdr_lasthop
+
+ int inet6_rthdr_lasthop(struct cmsghdr *cmsg,
+ unsigned int flags);
+
+ This function specifies the Strict/Loose flag for the final hop of a
+ Routing header. For an IPv6 Type 0 Routing header, flags must be
+ either IPV6_RTHDR_LOOSE or IPV6_RTHDR_STRICT.
+
+ The return value of the function is 0 upon success, or -1 upon an
+ error.
+
+ Notice that a Routing header specifying N intermediate nodes requires
+ N+1 Strict/Loose flags. This requires N calls to inet6_rthdr_add()
+ followed by one call to inet6_rthdr_lasthop().
+
+8.5. inet6_rthdr_reverse
+
+ int inet6_rthdr_reverse(const struct cmsghdr *in, struct cmsghdr *out);
+
+ This function takes a Routing header that was received as ancillary
+ data (pointed to by the first argument) and writes a new Routing
+ header that sends datagrams along the reverse of that route. Both
+ arguments are allowed to point to the same buffer (that is, the
+ reversal can occur in place).
+
+ The return value of the function is 0 on success, or -1 upon an
+ error.
+
+8.6. inet6_rthdr_segments
+
+ int inet6_rthdr_segments(const struct cmsghdr *cmsg);
+
+ This function returns the number of segments (addresses) contained in
+ the Routing header described by cmsg. On success the return value is
+ between 1 and 23, inclusive. The return value of the function is -1
+ upon an error.
+
+8.7. inet6_rthdr_getaddr
+
+ struct in6_addr *inet6_rthdr_getaddr(struct cmsghdr *cmsg, int
+ index);
+
+ This function returns a pointer to the IPv6 address specified by
+ index (which must have a value between 1 and the value returned by
+ inet6_rthdr_segments()) in the Routing header described by cmsg. An
+ application should first call inet6_rthdr_segments() to obtain the
+ number of segments in the Routing header.
+
+
+
+Stevens & Thomas Informational [Page 46]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ Upon an error the return value of the function is NULL.
+
+8.8. inet6_rthdr_getflags
+
+ int inet6_rthdr_getflags(const struct cmsghdr *cmsg, int index);
+
+ This function returns the flags value specified by index (which must
+ have a value between 0 and the value returned by
+ inet6_rthdr_segments()) in the Routing header described by cmsg. For
+ an IPv6 Type 0 Routing header the return value will be either
+ IPV6_RTHDR_LOOSE or IPV6_RTHDR_STRICT.
+
+ Upon an error the return value of the function is -1.
+
+ (Note: Addresses are indexed starting at 1, and flags starting at 0,
+ to maintain consistency with the terminology and figures in [RFC-
+ 1883].)
+
+8.9. Routing Header Example
+
+ As an example of these Routing header functions, we go through the
+ function calls for the example on p. 18 of [RFC-1883]. The source is
+ S, the destination is D, and the three intermediate nodes are I1, I2,
+ and I3. f0, f1, f2, and f3 are the Strict/Loose flags for each hop.
+
+ f0 f1 f2 f3
+ S -----> I1 -----> I2 -----> I3 -----> D
+
+ src: * S S S S S
+ dst: D I1 I2 I3 D D
+ A[1]: I1 I2 I1 I1 I1 I1
+ A[2]: I2 I3 I3 I2 I2 I2
+ A[3]: I3 D D D I3 I3
+ #seg: 3 3 2 1 0 3
+
+ check: f0 f1 f2 f3
+
+ src and dst are the source and destination IPv6 addresses in the IPv6
+ header. A[1], A[2], and A[3] are the three addresses in the Routing
+ header. #seg is the Segments Left field in the Routing header.
+ check indicates which bit of the Strict/Loose Bit Map (0 through 3,
+ specified as f0 through f3) that node checks.
+
+ The six values in the column beneath node S are the values in the
+ Routing header specified by the application using sendmsg(). The
+ function calls by the sender would look like:
+
+
+
+
+
+Stevens & Thomas Informational [Page 47]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ void *ptr;
+ struct msghdr msg;
+ struct cmsghdr *cmsgptr;
+ struct sockaddr_in6 I1, I2, I3, D;
+ unsigned int f0, f1, f2, f3;
+
+ ptr = malloc(inet6_rthdr_space(IPV6_RTHDR_TYPE_0, 3));
+ cmsgptr = inet6_rthdr_init(ptr, IPV6_RTHDR_TYPE_0);
+
+ inet6_rthdr_add(cmsgptr, &I1.sin6_addr, f0);
+ inet6_rthdr_add(cmsgptr, &I2.sin6_addr, f1);
+ inet6_rthdr_add(cmsgptr, &I3.sin6_addr, f2);
+ inet6_rthdr_lasthop(cmsgptr, f3);
+
+ msg.msg_control = ptr;
+ msg.msg_controllen = cmsgptr->cmsg_len;
+
+ /* finish filling in msg{}, msg_name = D */
+ /* call sendmsg() */
+
+ We also assume that the source address for the socket is not
+ specified (i.e., the asterisk in the figure).
+
+ The four columns of six values that are then shown between the five
+ nodes are the values of the fields in the packet while the packet is
+ in transit between the two nodes. Notice that before the packet is
+ sent by the source node S, the source address is chosen (replacing
+ the asterisk), I1 becomes the destination address of the datagram,
+ the two addresses A[2] and A[3] are "shifted up", and D is moved to
+ A[3]. If f0 is IPV6_RTHDR_STRICT, then I1 must be a neighbor of S.
+
+ The columns of values that are shown beneath the destination node are
+ the values returned by recvmsg(), assuming the application has
+ enabled both the IPV6_PKTINFO and IPV6_RTHDR socket options. The
+ source address is S (contained in the sockaddr_in6 structure pointed
+ to by the msg_name member), the destination address is D (returned as
+ an ancillary data object in an in6_pktinfo structure), and the
+ ancillary data object specifying the Routing header will contain
+ three addresses (I1, I2, and I3) and four flags (f0, f1, f2, and f3).
+ The number of segments in the Routing header is known from the Hdr
+ Ext Len field in the Routing header (a value of 6, indicating 3
+ addresses).
+
+ The return value from inet6_rthdr_segments() will be 3 and
+ inet6_rthdr_getaddr(1) will return I1, inet6_rthdr_getaddr(2) will
+ return I2, and inet6_rthdr_getaddr(3) will return I3, The return
+
+
+
+
+
+Stevens & Thomas Informational [Page 48]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ value from inet6_rthdr_flags(0) will be f0, inet6_rthdr_flags(1) will
+ return f1, inet6_rthdr_flags(2) will return f2, and
+ inet6_rthdr_flags(3) will return f3.
+
+ If the receiving application then calls inet6_rthdr_reverse(), the
+ order of the three addresses will become I3, I2, and I1, and the
+ order of the four Strict/Loose flags will become f3, f2, f1, and f0.
+
+ We can also show what an implementation might store in the ancillary
+ data object as the Routing header is being built by the sending
+ process. If we assume a 32-bit architecture where sizeof(struct
+ cmsghdr) equals 12, with a desired alignment of 4-byte boundaries,
+ then the call to inet6_rthdr_space(3) returns 68: 12 bytes for the
+ cmsghdr structure and 56 bytes for the Routing header (8 + 3*16).
+
+ The call to inet6_rthdr_init() initializes the ancillary data object
+ to contain a Type 0 Routing header:
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 20 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_RTHDR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=0 | Routing Type=0| Seg Left=0 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved | Strict/Loose Bit Map |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The first call to inet6_rthdr_add() adds I1 to the list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 49]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 36 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_RTHDR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=2 | Routing Type=0| Seg Left=1 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |X| Strict/Loose Bit Map |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[1] = I1 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ Bit 0 of the Strict/Loose Bit Map contains the value f0, which we
+ just mark as X. cmsg_len is incremented by 16, the Hdr Ext Len field
+ is incremented by 2, and the Segments Left field is incremented by 1.
+
+ The next call to inet6_rthdr_add() adds I2 to the list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 50]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 52 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_RTHDR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=4 | Routing Type=0| Seg Left=2 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |X|X| Strict/Loose Bit Map |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[1] = I1 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[2] = I2 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The next bit of the Strict/Loose Bit Map contains the value f1.
+ cmsg_len is incremented by 16, the Hdr Ext Len field is incremented
+ by 2, and the Segments Left field is incremented by 1.
+
+ The last call to inet6_rthdr_add() adds I3 to the list.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 51]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_len = 68 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_level = IPPROTO_IPV6 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | cmsg_type = IPV6_RTHDR |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Next Header | Hdr Ext Len=6 | Routing Type=0| Seg Left=3 |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Reserved |X|X|X| Strict/Loose Bit Map |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[1] = I1 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[2] = I2 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | |
+ + +
+ | |
+ + Address[3] = I3 +
+ | |
+ + +
+ | |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+ The next bit of the Strict/Loose Bit Map contains the value f2.
+ cmsg_len is incremented by 16, the Hdr Ext Len field is incremented
+ by 2, and the Segments Left field is incremented by 1.
+
+ Finally, the call to inet6_rthdr_lasthop() sets the next bit of the
+ Strict/Loose Bit Map to the value specified by f3. All the lengths
+ remain unchanged.
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 52]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+9. Ordering of Ancillary Data and IPv6 Extension Headers
+
+ Three IPv6 extension headers can be specified by the application and
+ returned to the application using ancillary data with sendmsg() and
+ recvmsg(): Hop-by-Hop options, Destination options, and the Routing
+ header. When multiple ancillary data objects are transferred via
+ sendmsg() or recvmsg() and these objects represent any of these three
+ extension headers, their placement in the control buffer is directly
+ tied to their location in the corresponding IPv6 datagram. This API
+ imposes some ordering constraints when using multiple ancillary data
+ objects with sendmsg().
+
+ When multiple IPv6 Hop-by-Hop options having the same option type are
+ specified, these options will be inserted into the Hop-by-Hop options
+ header in the same order as they appear in the control buffer. But
+ when multiple Hop-by-Hop options having different option types are
+ specified, these options may be reordered by the kernel to reduce
+ padding in the Hop-by-Hop options header. Hop-by-Hop options may
+ appear anywhere in the control buffer and will always be collected by
+ the kernel and placed into a single Hop-by-Hop options header that
+ immediately follows the IPv6 header.
+
+ Similar rules apply to the Destination options: (1) those of the same
+ type will appear in the same order as they are specified, and (2)
+ those of differing types may be reordered. But the kernel will build
+ up to two Destination options headers: one to precede the Routing
+ header and one to follow the Routing header. If the application
+ specifies a Routing header then all Destination options that appear
+ in the control buffer before the Routing header will appear in a
+ Destination options header before the Routing header and these
+ options might be reordered, subject to the two rules that we just
+ stated. Similarly all Destination options that appear in the control
+ buffer after the Routing header will appear in a Destination options
+ header after the Routing header, and these options might be
+ reordered, subject to the two rules that we just stated.
+
+ As an example, assume that an application specifies control
+ information to sendmsg() containing six ancillary data objects: the
+ first containing two Hop-by-Hop options, the second containing one
+ Destination option, the third containing two Destination options, the
+ fourth containing a Routing header, the fifth containing a Hop-by-Hop
+ option, and the sixth containing two Destination options. We also
+ assume that all the Hop-by-Hop options are of different types, as are
+ all the Destination options. We number these options 1-9,
+ corresponding to their order in the control buffer, and show them on
+ the left below.
+
+
+
+
+
+Stevens & Thomas Informational [Page 53]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ In the middle we show the final arrangement of the options in the
+ extension headers built by the kernel. On the right we show the four
+ ancillary data objects returned to the receiving application.
+
+ Sender's Receiver's
+ Ancillary Data --> IPv6 Extension --> Ancillary Data
+ Objects Headers Objects
+ ------------------ --------------- --------------
+ HOPOPT-1,2 (first) HOPHDR(J,7,1,2) HOPOPT-7,1,2
+ DSTOPT-3 DSTHDR(4,5,3) DSTOPT-4,5,3
+ DSTOPT-4,5 RTHDR(6) RTHDR-6
+ RTHDR-6 DSTHDR(8,9) DSTOPT-8,9
+ HOPOPT-7
+ DSTOPT-8,9 (last)
+
+ The sender's two Hop-by-Hop ancillary data objects are reordered, as
+ are the first two Destination ancillary data objects. We also show a
+ Jumbo Payload option (denoted as J) inserted by the kernel before the
+ sender's three Hop-by-Hop options. The first three Destination
+ options must appear in a Destination header before the Routing
+ header, and the final two Destination options must appear in a
+ Destination header after the Routing header.
+
+ If Destination options are specified in the control buffer after a
+ Routing header, or if Destination options are specified without a
+ Routing header, the kernel will place those Destination options after
+ an authentication header and/or an encapsulating security payload
+ header, if present.
+
+10. IPv6-Specific Options with IPv4-Mapped IPv6 Addresses
+
+ The various socket options and ancillary data specifications defined
+ in this document apply only to true IPv6 sockets. It is possible to
+ create an IPv6 socket that actually sends and receives IPv4 packets,
+ using IPv4-mapped IPv6 addresses, but the mapping of the options
+ defined in this document to an IPv4 datagram is beyond the scope of
+ this document.
+
+ In general, attempting to specify an IPv6-only option, such as the
+ Hop-by-Hop options, Destination options, or Routing header on an IPv6
+ socket that is using IPv4-mapped IPv6 addresses, will probably result
+ in an error. Some implementations, however, may provide access to
+ the packet information (source/destination address, send/receive
+ interface, and hop limit) on an IPv6 socket that is using IPv4-mapped
+ IPv6 addresses.
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 54]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+11. rresvport_af
+
+ The rresvport() function is used by the rcmd() function, and this
+ function is in turn called by many of the "r" commands such as
+ rlogin. While new applications are not being written to use the
+ rcmd() function, legacy applications such as rlogin will continue to
+ use it and these will be ported to IPv6.
+
+ rresvport() creates an IPv4/TCP socket and binds a "reserved port" to
+ the socket. Instead of defining an IPv6 version of this function we
+ define a new function that takes an address family as its argument.
+
+ #include <unistd.h>
+
+ int rresvport_af(int *port, int family);
+
+ This function behaves the same as the existing rresvport() function,
+ but instead of creating an IPv4/TCP socket, it can also create an
+ IPv6/TCP socket. The family argument is either AF_INET or AF_INET6,
+ and a new error return is EAFNOSUPPORT if the address family is not
+ supported.
+
+ (Note: There is little consensus on which header defines the
+ rresvport() and rcmd() function prototypes. 4.4BSD defines it in
+ <unistd.h>, others in <netdb.h>, and others don't define the function
+ prototypes at all.)
+
+ (Note: We define this function only, and do not define something like
+ rcmd_af() or rcmd6(). The reason is that rcmd() calls
+ gethostbyname(), which returns the type of address: AF_INET or
+ AF_INET6. It should therefore be possible to modify rcmd() to
+ support either IPv4 or IPv6, based on the address family returned by
+ gethostbyname().)
+
+12. Future Items
+
+ Some additional items may require standardization, but no concrete
+ proposals have been made for the API to perform these tasks. These
+ may be addressed in a later document.
+
+12.1. Flow Labels
+
+ Earlier revisions of this document specified a set of
+ inet6_flow_XXX() functions to assign, share, and free IPv6 flow
+ labels. Consensus, however, indicated that it was premature to
+ specify this part of the API.
+
+
+
+
+
+Stevens & Thomas Informational [Page 55]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+12.2. Path MTU Discovery and UDP
+
+ A standard method may be desirable for a UDP application to determine
+ the "maximum send transport-message size" (Section 5.1 of [RFC-1981])
+ to a given destination. This would let the UDP application send
+ smaller datagrams to the destination, avoiding fragmentation.
+
+12.3. Neighbor Reachability and UDP
+
+ A standard method may be desirable for a UDP application to tell the
+ kernel that it is making forward progress with a given peer (Section
+ 7.3.1 of [RFC-1970]). This could save unneeded neighbor
+ solicitations and neighbor advertisements.
+
+13. Summary of New Definitions
+
+ The following list summarizes the constants and structure,
+ definitions discussed in this memo, sorted by header.
+
+ <netinet/icmp6.h> ICMP6_DST_UNREACH
+ <netinet/icmp6.h> ICMP6_DST_UNREACH_ADDR
+ <netinet/icmp6.h> ICMP6_DST_UNREACH_ADMIN
+ <netinet/icmp6.h> ICMP6_DST_UNREACH_NOPORT
+ <netinet/icmp6.h> ICMP6_DST_UNREACH_NOROUTE
+ <netinet/icmp6.h> ICMP6_DST_UNREACH_NOTNEIGHBOR
+ <netinet/icmp6.h> ICMP6_ECHO_REPLY
+ <netinet/icmp6.h> ICMP6_ECHO_REQUEST
+ <netinet/icmp6.h> ICMP6_INFOMSG_MASK
+ <netinet/icmp6.h> ICMP6_MEMBERSHIP_QUERY
+ <netinet/icmp6.h> ICMP6_MEMBERSHIP_REDUCTION
+ <netinet/icmp6.h> ICMP6_MEMBERSHIP_REPORT
+ <netinet/icmp6.h> ICMP6_PACKET_TOO_BIG
+ <netinet/icmp6.h> ICMP6_PARAMPROB_HEADER
+ <netinet/icmp6.h> ICMP6_PARAMPROB_NEXTHEADER
+ <netinet/icmp6.h> ICMP6_PARAMPROB_OPTION
+ <netinet/icmp6.h> ICMP6_PARAM_PROB
+ <netinet/icmp6.h> ICMP6_TIME_EXCEEDED
+ <netinet/icmp6.h> ICMP6_TIME_EXCEED_REASSEMBLY
+ <netinet/icmp6.h> ICMP6_TIME_EXCEED_TRANSIT
+ <netinet/icmp6.h> ND_NA_FLAG_OVERRIDE
+ <netinet/icmp6.h> ND_NA_FLAG_ROUTER
+ <netinet/icmp6.h> ND_NA_FLAG_SOLICITED
+ <netinet/icmp6.h> ND_NEIGHBOR_ADVERT
+ <netinet/icmp6.h> ND_NEIGHBOR_SOLICIT
+ <netinet/icmp6.h> ND_OPT_MTU
+ <netinet/icmp6.h> ND_OPT_PI_FLAG_AUTO
+ <netinet/icmp6.h> ND_OPT_PI_FLAG_ONLINK
+ <netinet/icmp6.h> ND_OPT_PREFIX_INFORMATION
+
+
+
+Stevens & Thomas Informational [Page 56]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ <netinet/icmp6.h> ND_OPT_REDIRECTED_HEADER
+ <netinet/icmp6.h> ND_OPT_SOURCE_LINKADDR
+ <netinet/icmp6.h> ND_OPT_TARGET_LINKADDR
+ <netinet/icmp6.h> ND_RA_FLAG_MANAGED
+ <netinet/icmp6.h> ND_RA_FLAG_OTHER
+ <netinet/icmp6.h> ND_REDIRECT
+ <netinet/icmp6.h> ND_ROUTER_ADVERT
+ <netinet/icmp6.h> ND_ROUTER_SOLICIT
+
+ <netinet/icmp6.h> struct icmp6_filter{};
+ <netinet/icmp6.h> struct icmp6_hdr{};
+ <netinet/icmp6.h> struct nd_neighbor_advert{};
+ <netinet/icmp6.h> struct nd_neighbor_solicit{};
+ <netinet/icmp6.h> struct nd_opt_hdr{};
+ <netinet/icmp6.h> struct nd_opt_mtu{};
+ <netinet/icmp6.h> struct nd_opt_prefix_info{};
+ <netinet/icmp6.h> struct nd_opt_rd_hdr{};
+ <netinet/icmp6.h> struct nd_redirect{};
+ <netinet/icmp6.h> struct nd_router_advert{};
+ <netinet/icmp6.h> struct nd_router_solicit{};
+
+ <netinet/in.h> IPPROTO_AH
+ <netinet/in.h> IPPROTO_DSTOPTS
+ <netinet/in.h> IPPROTO_ESP
+ <netinet/in.h> IPPROTO_FRAGMENT
+ <netinet/in.h> IPPROTO_HOPOPTS
+ <netinet/in.h> IPPROTO_ICMPV6
+ <netinet/in.h> IPPROTO_IPV6
+ <netinet/in.h> IPPROTO_NONE
+ <netinet/in.h> IPPROTO_ROUTING
+ <netinet/in.h> IPV6_DSTOPTS
+ <netinet/in.h> IPV6_HOPLIMIT
+ <netinet/in.h> IPV6_HOPOPTS
+ <netinet/in.h> IPV6_NEXTHOP
+ <netinet/in.h> IPV6_PKTINFO
+ <netinet/in.h> IPV6_PKTOPTIONS
+ <netinet/in.h> IPV6_RTHDR
+ <netinet/in.h> IPV6_RTHDR_LOOSE
+ <netinet/in.h> IPV6_RTHDR_STRICT
+ <netinet/in.h> IPV6_RTHDR_TYPE_0
+ <netinet/in.h> struct in6_pktinfo{};
+
+ <netinet/ip6.h> IP6F_OFF_MASK
+ <netinet/ip6.h> IP6F_RESERVED_MASK
+ <netinet/ip6.h> IP6F_MORE_FRAG
+ <netinet/ip6.h> struct ip6_dest{};
+ <netinet/ip6.h> struct ip6_frag{};
+ <netinet/ip6.h> struct ip6_hbh{};
+
+
+
+Stevens & Thomas Informational [Page 57]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ <netinet/ip6.h> struct ip6_hdr{};
+ <netinet/ip6.h> struct ip6_rthdr{};
+ <netinet/ip6.h> struct ip6_rthdr0{};
+
+ <sys/socket.h> struct cmsghdr{};
+ <sys/socket.h> struct msghdr{};
+
+ The following list summarizes the function and macro prototypes
+ discussed in this memo, sorted by header.
+
+<netinet/icmp6.h> void ICMP6_FILTER_SETBLOCK(int,
+ struct icmp6_filter *);
+<netinet/icmp6.h> void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *);
+<netinet/icmp6.h> void ICMP6_FILTER_SETPASS(int, struct icmp6_filter *);
+<netinet/icmp6.h> void ICMP6_FILTER_SETPASSALL(struct icmp6_filter *);
+<netinet/icmp6.h> int ICMP6_FILTER_WILLBLOCK(int,
+ const struct icmp6_filter *);
+<netinet/icmp6.h> int ICMP6_FILTER_WILLPASS(int,
+ const struct icmp6_filter *);
+
+<netinet/in.h> int IN6_ARE_ADDR_EQUAL(const struct in6_addr *,
+ const struct in6_addr *);
+
+<netinet/in.h> uint8_t *inet6_option_alloc(struct cmsghdr *,
+ int, int, int);
+<netinet/in.h> int inet6_option_append(struct cmsghdr *,
+ const uint8_t *, int, int);
+<netinet/in.h> int inet6_option_find(const struct cmsghdr *,
+ uint8_t *, int);
+<netinet/in.h> int inet6_option_init(void *, struct cmsghdr **, int);
+<netinet/in.h> int inet6_option_next(const struct cmsghdr *,
+ uint8_t **);
+<netinet/in.h> int inet6_option_space(int);
+
+<netinet/in.h> int inet6_rthdr_add(struct cmsghdr *,
+ const struct in6_addr *,
+ unsigned int);
+<netinet/in.h> struct in6_addr inet6_rthdr_getaddr(struct cmsghdr *,
+ int);
+<netinet/in.h> int inet6_rthdr_getflags(const struct cmsghdr *, int);
+<netinet/in.h> struct cmsghdr *inet6_rthdr_init(void *, int);
+<netinet/in.h> int inet6_rthdr_lasthop(struct cmsghdr *,
+ unsigned int);
+<netinet/in.h> int inet6_rthdr_reverse(const struct cmsghdr *,
+ struct cmsghdr *);
+<netinet/in.h> int inet6_rthdr_segments(const struct cmsghdr *);
+<netinet/in.h> size_t inet6_rthdr_space(int, int);
+
+
+
+
+Stevens & Thomas Informational [Page 58]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+<sys/socket.h> unsigned char *CMSG_DATA(const struct cmsghdr *);
+<sys/socket.h> struct cmsghdr *CMSG_FIRSTHDR(const struct msghdr *);
+<sys/socket.h> unsigned int CMSG_LEN(unsigned int);
+<sys/socket.h> struct cmsghdr *CMSG_NXTHDR(const struct msghdr *mhdr,
+ const struct cmsghdr *);
+<sys/socket.h> unsigned int CMSG_SPACE(unsigned int);
+
+<unistd.h> int rresvport_af(int *, int);
+
+14. Security Considerations
+
+ The setting of certain Hop-by-Hop options and Destination options may
+ be restricted to privileged processes. Similarly some Hop-by-Hop
+ options and Destination options may not be returned to nonprivileged
+ applications.
+
+15. Change History
+
+ Changes from the June 1997 Edition (-03 draft)
+
+ - Added a note that defined constants for multibyte fields are in
+ network byte order. This affects the ip6f_offlg member of the
+ Fragment header (Section 2.1.2) and the nd_na_flags_reserved
+ member of the nd_neighbor_advert structure (Section 2.2.2).
+
+ - Section 5: the ipi6_ifindex member of the in6_pktinfo structure
+ should be "unsigned int" instead of "int", for consistency with
+ the interface indexes in [RFC-2133].
+
+ - Section 6.3.7: the three calls to inet6_option_space() in the
+ examples needed to be arguments to malloc(). The final one of
+ these was missing the "6" in the name "inet6_option_space".
+
+ - Section 8.6: the function prototype for inet6_rthdr_segments()
+ was missing the ending semicolon.
+
+ Changes from the March 1997 Edition (-02 draft)
+
+ - In May 1997 Draft 6.6 of Posix 1003.1g (called Posix.1g herein)
+ passed ballot and will be forwarded to the IEEE Standards Board
+ later in 1997 for final approval. Some changes made for this
+ final Posix draft are incorporated into this Internet Draft,
+ specifically the datatypes mentioned in Section 1 (and used
+ throughout the text), and the socklen_t datatype used in Section
+ 4.1 and 4.2.
+
+ - Section 1: Added the intN_t signed datatypes, changed the
+ datatype u_intN_t to uintN_t (no underscore after the "u"), and
+
+
+
+Stevens & Thomas Informational [Page 59]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ removed the datatype u_intNm_t, as per Draft 6.6 of Posix.1g.
+
+ - Name space issues for structure and constant names in Section 2:
+ Many of the structure member names and constant names were
+ changed so that the prefixes are the same. The following
+ prefixes are used for structure members: "ip6_", "icmp6_", and
+ "nd_". All constants have the prefixes "ICMP6_" and "ND_".
+
+ - New definitions: Section 2.1.2: contains definitions for the IPv6
+ extension headers, other than AH and ESP. Section 2.2.2:
+ contains additional structures and constants for the neighbor
+ discovery option header and redirected header.
+
+ - Section 2.2.2: the enum for the neighbor discovery option field
+ was changed to be a set of #define constants.
+
+ - Changed the word "function" to "macro" for references to all the
+ uppercase names in Sections 2.3 (IN6_ARE_ADDR_EQUAL), 3.2
+ (ICMPV6_FILTER_xxx), and 4.3 (CMSG_xxx).
+
+ - Added more protocols to the /etc/protocols file (Section 2.4) and
+ changed the name of "icmpv6" to "ipv6-icmp".
+
+ - Section 3: Made it more explicit that an application cannot read
+ or write entire IPv6 packets, that all extension headers are
+ passed as ancillary data. Added a sentence that the kernel
+ fragments packets written to an IPv6 raw socket when necessary.
+ Added a note that IPPROTO_RAW raw IPv6 sockets are not special.
+
+ - Section 3.1: Explicitly stated that the checksum option applies
+ to both outgoing packets and received packets.
+
+ - Section 3.2: Changed the array name within the icmp6_filter
+ structure from "data" to "icmp6_filt". Changes the prefix for
+ the filter macros from "ICMPV6_" to "ICMP6_", for consistency
+ with the names in Section 2.2. Changed the example from a ping
+ program to a program that wants to receive only router
+ advertisements.
+
+ - Section 4.1: Changed msg_namelen and msg_controllen from size_t
+ to the Posix.1g socklen_t datatype. Updated the Note that
+ follows.
+
+ - Section 4.2: Changed cmsg_len from size_t to the Posix.1g
+ socklen_t datatype. Updated the Note that follows.
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 60]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ - Section 4.4: Added a Note that the second and third arguments to
+ getsockopt() and setsockopt() are intentionally the same as the
+ cmsg_level and cmsg_type members.
+
+ - Section 4.5: Reorganized the section into a description of the
+ option, followed by the TCP semantics, and the UDP and raw socket
+ semantics. Added a sentence on how to clear all the sticky
+ options. Added a note that TCP need not save the options from
+ the most recently received segment until the application says to
+ do so. Added the statement that ancillary data is never passed
+ with sendmsg() or recvmsg() on a TCP socket. Simplified the
+ interaction of the sticky options with ancillary data for UDP or
+ raw IP: none of the sticky options are sent if ancillary data is
+ specified.
+
+ - Final paragraph of Section 5.1: ipi6_index should be
+ ipi6_ifindex.
+
+ - Section 5.4: Added a note on the term "privileged".
+
+ - Section 5.5: Noted that the errors listed are examples, and the
+ actual errors depend on the implementation.
+
+ - Removed Section 6 ("Flow Labels") as the consensus is that it is
+ premature to try and specify an API for this feature. Access to
+ the flow label field in the IPv6 header is still provided through
+ the sin6_flowinfo member of the IPv6 socket address structure in
+ [RFC-2133]. Added a subsection to Section 13 that this is a
+ future item.
+
+ All remaining changes are identified by their section number in
+ the previous draft. With the removal of Section 6, the section
+ numbers are decremented by one.
+
+ - Section 7.3.7: the calls to malloc() in all three examples should
+ be calls to inet6_option_space() instead. The two calls to
+ inet6_option_append() in the third example should be calls to
+ inet6_option_alloc(). The two calls to CMSG_SPACE() in the first
+ and third examples should be calls to CMSG_LEN(). The second
+ call to CMSG_SPACE() in the second example should be a call to
+ CMSG_LEN().
+
+ - Section 7.3.7: All the opt_X_ and opt_Y_ structure member names
+ were changed to be ip6_X_opt_ and ip6_Y_opt_. The two structure
+ names ipv6_opt_X and ipv6_opt_Y were changed to ip6_X_opt and
+ ip6_Y_opt. The constants beginning with IPV6_OPT_X_ and
+ IPV6_OPT_Y_ were changed to begin with IP6_X_OPT_ and IP6_Y_OPT_.
+
+
+
+
+Stevens & Thomas Informational [Page 61]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ - Use the term "Routing header" throughout the draft, instead of
+ "source routing". Changed the names of the eight
+ inet6_srcrt_XXX() functions in Section 9 to inet6_rthdr_XXX().
+ Changed the name of the socket option from IPV6_SRCRT to
+ IPV6_RTHDR, and the names of the three IPV6_SRCRT_xxx constants
+ in Section 9 to IPV6_RTHDR_xxx.
+
+ - Added a paragraph to Section 9 on how to receive and send a
+ Routing header.
+
+ - Changed inet6_rthdr_add() and inet6_rthdr_reverse() so that they
+ return -1 upon an error, instead of an Exxx errno value.
+
+ - In the description of inet6_rthdr_space() in Section 9.1, added
+ the qualifier "For an IPv6 Type 0 Routing header" to the
+ restriction of between 1 and 23 segments.
+
+ - Refer to final function argument in Sections 9.7 and 9.8 as
+ index, not offset.
+
+ - Updated Section 14 with new names from Section 2.
+
+ - Changed the References from "[n]" to "[RFC-abcd]".
+
+ Changes from the February 1997 Edition (-01 draft)
+
+ - Changed the name of the ip6hdr structure to ip6_hdr (Section 2.1)
+ for consistency with the icmp6hdr structure. Also changed the
+ name of the ip6hdrctl structure contained within the ip6_hdr
+ structure to ip6_hdrctl (Section 2.1). Finally, changed the name
+ of the icmp6hdr structure to icmp6_hdr (Section 2.2). All other
+ occurrences of this structure name, within the Neighbor Discovery
+ structures in Section 2.2.1, already contained the underscore.
+
+ - The "struct nd_router_solicit" and "struct nd_router_advert"
+ should both begin with "nd6_". (Section 2.2.2).
+
+ - Changed the name of in6_are_addr_equal to IN6_ARE_ADDR_EQUAL
+ (Section 2.3) for consistency with basic API address testing
+ functions. The header defining this macro is <netinet/in.h>.
+
+ - getprotobyname("ipv6") now returns 41, not 0 (Section 2.4).
+
+ - The first occurrence of "struct icmpv6_filter" in Section 3.2
+ should be "struct icmp6_filter".
+
+ - Changed the name of the CMSG_LENGTH() macro to CMSG_LEN()
+ (Section 4.3.5), since LEN is used throughout the <netinet/*.h>
+
+
+
+Stevens & Thomas Informational [Page 62]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ headers.
+
+ - Corrected the argument name for the sample implementations of the
+ CMSG_SPACE() and CMSG_LEN() macros to be "length" (Sections 4.3.4
+ and 4.3.5).
+
+ - Corrected the socket option mentioned in Section 5.1 to specify
+ the interface for multicasting from IPV6_ADD_MEMBERSHIP to
+ IPV6_MULTICAST_IF.
+
+ - There were numerous errors in the previous draft that specified
+ <netinet/ip6.h> that should have been <netinet/in.h>. These have
+ all been corrected and the locations of all definitions is now
+ summarized in the new Section 14 ("Summary of New Definitions").
+
+ Changes from the October 1996 Edition (-00 draft)
+
+ - Numerous rationale added using the format (Note: ...).
+
+ - Added note that not all errors may be defined.
+
+ - Added note about ICMPv4, IGMPv4, and ARPv4 terminology.
+
+ - Changed the name of <netinet/ip6_icmp.h> to <netinet/icmp6.h>.
+
+ - Changed some names in Section 2.2.1: ICMPV6_PKT_TOOBIG to
+ ICMPV6_PACKET_TOOBIG, ICMPV6_TIME_EXCEED to ICMPV6_TIME_EXCEEDED,
+ ICMPV6_ECHORQST to ICMPV6_ECHOREQUEST, ICMPV6_ECHORPLY to
+ ICMPV6_ECHOREPLY, ICMPV6_PARAMPROB_HDR to
+ ICMPV6_PARAMPROB_HEADER, ICMPV6_PARAMPROB_NXT_HDR to
+ ICMPV6_PARAMPROB_NEXTHEADER, and ICMPV6_PARAMPROB_OPTS to
+ ICMPV6_PARAMPROB_OPTION.
+
+ - Prepend the prefix "icmp6_" to the three members of the
+ icmp6_dataun union of the icmp6hdr structure (Section 2.2).
+
+ - Moved the neighbor discovery definitions into the
+ <netinet/icmp6.h> header, instead of being in their own header
+ (Section 2.2.1).
+
+ - Changed Section 2.3 ("Address Testing"). The basic macros are
+ now in the basic API.
+
+ - Added the new Section 2.4 on "Protocols File".
+
+ - Added note to raw sockets description that something like BPF or
+ DLPI must be used to read or write entire IPv6 packets.
+
+
+
+
+Stevens & Thomas Informational [Page 63]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ - Corrected example of IPV6_CHECKSUM socket option (Section 3.1).
+ Also defined value of -1 to disable.
+
+ - Noted that <netinet/icmp6.h> defines all the ICMPv6 filtering
+ constants, macros, and structures (Section 3.2).
+
+ - Added note on magic number 10240 for amount of ancillary data
+ (Section 4.1).
+
+ - Added possible padding to picture of ancillary data (Section
+ 4.2).
+
+ - Defined <sys/socket.h> header for CMSG_xxx() functions (Section
+ 4.2).
+
+ - Note that the data returned by getsockopt(IPV6_PKTOPTIONS) for a
+ TCP socket is just from the optional headers, if present, of the
+ most recently received segment. Also note that control
+ information is never returned by recvmsg() for a TCP socket.
+
+ - Changed header for struct in6_pktinfo from <netinet.in.h> to
+ <netinet/ip6.h> (Section 5).
+
+ - Removed the old Sections 5.1 and 5.2, because the interface
+ identification functions went into the basic API.
+
+ - Redid Section 5 to support the hop limit field.
+
+ - New Section 5.4 ("Next Hop Address").
+
+ - New Section 6 ("Flow Labels").
+
+ - Changed all of Sections 7 and 8 dealing with Hop-by-Hop and
+ Destination options. We now define a set of inet6_option_XXX()
+ functions.
+
+ - Changed header for IPV6_SRCRT_xxx constants from <netinet.in.h>
+ to <netinet/ip6.h> (Section 9).
+
+ - Add inet6_rthdr_lasthop() function, and fix errors in description
+ of Routing header (Section 9).
+
+ - Reworded some of the Routing header descriptions to conform to
+ the terminology in [RFC-1883].
+
+ - Added the example from [RFC-1883] for the Routing header (Section
+ 9.9).
+
+
+
+
+Stevens & Thomas Informational [Page 64]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+ - Expanded the example in Section 10 to show multiple options per
+ ancillary data object, and to show the receiver's ancillary data
+ objects.
+
+ - New Section 11 ("IPv6-Specific Options with IPv4-Mapped IPv6
+ Addresses").
+
+ - New Section 12 ("rresvport_af").
+
+ - Redid old Section 10 ("Additional Items") into new Section 13
+ ("Future Items").
+
+16. References
+
+ [RFC-1883] Deering, S., and R. Hinden, "Internet Protocol, Version 6
+ (IPv6), Specification", RFC 1883, December 1995.
+
+ [RFC-2133] Gilligan, R., Thomson, S., Bound, J., and W. Stevens,
+ "Basic Socket Interface Extensions for IPv6", RFC 2133,
+ April 1997.
+
+ [RFC-1981] McCann, J., Deering, S., and J. Mogul, "Path MTU
+ Discovery
+ for IP version 6", RFC 1981, August 1996.
+
+ [RFC-1970] Narten, T., Nordmark, E., and W. Simpson, "Neighbor
+ Discovery for IP Version 6 (IPv6)", RFC 1970, August
+ 1996.
+
+17. Acknowledgments
+
+ Matt Thomas and Jim Bound have been working on the technical details
+ in this draft for over a year. Keith Sklower is the original
+ implementor of ancillary data in the BSD networking code. Craig Metz
+ provided lots of feedback, suggestions, and comments based on his
+ implementing many of these features as the document was being
+ written.
+
+ The following provided comments on earlier drafts: Pascal Anelli,
+ Hamid Asayesh, Ran Atkinson, Karl Auerbach, Hamid Asayesh, Matt
+ Crawford, Sam T. Denton, Richard Draves, Francis Dupont, Bob
+ Gilligan, Tim Hartrick, Masaki Hirabaru, Yoshinobu Inoue, Mukesh
+ Kacker, A. N. Kuznetsov, Pedro Marques, Jack McCann, der Mouse, John
+ Moy, Thomas Narten, Erik Nordmark, Steve Parker, Charles Perkins, Tom
+ Pusateri, Pedro Roque, Sameer Shah, Peter Sjodin, Stephen P.
+ Spackman, Jinmei Tatuya, Karen Tracey, Quaizar Vohra, Carl Williams,
+ Steve Wise, and Kazu Yamamoto.
+
+
+
+
+Stevens & Thomas Informational [Page 65]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+18. Authors' Addresses
+
+ W. Richard Stevens
+ 1202 E. Paseo del Zorro
+ Tucson, AZ 85718
+
+ EMail: rstevens@kohala.com
+
+
+ Matt Thomas
+ AltaVista Internet Software
+ LJO2-1/J8
+ 30 Porter Rd
+ Littleton, MA 01460
+ EMail: matt.thomas@altavista-software.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 66]
+
+RFC 2292 Advanced Sockets API for IPv6 February 1998
+
+
+19. Full Copyright Statement
+
+ Copyright (C) The Internet Society (1998). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Stevens & Thomas Informational [Page 67]
+