home *** CD-ROM | disk | FTP | other *** search
Text File | 2003-06-11 | 148.5 KB | 3,756 lines |
-
-
-
-
-
-
- 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]
-
-