diff --git a/doc/draft/draft-ietf-ipngwg-rfc2292bis-01.txt b/doc/draft/draft-ietf-ipngwg-rfc2292bis-01.txt new file mode 100644 index 0000000000..017ef839fa --- /dev/null +++ b/doc/draft/draft-ietf-ipngwg-rfc2292bis-01.txt @@ -0,0 +1,4044 @@ +INTERNET-DRAFT W. Richard Stevens (Consultant) +Expires: December 24, 1999 Matt Thomas (Consultant) +Obsoletes RFC 2292 Erik Nordmark (Sun) + Oct 22, 1999 + + + Advanced Sockets API for IPv6 + + + + +Abstract + + A separate specification [RFC-2553] contain changes to the sockets + API to support IP version 6. Those 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-2553]: The Routing header (source + routing), Hop-by-Hop options, and Destination options. This document + provides API access to these features too. + +Status of this Memo + + This document is an Internet-Draft and is in full conformance with + all provisions of Section 10 of RFC2026. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 1] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + This Internet Draft expires April 22, 2000. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 2] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + +Table of Contents + + 1. Introduction .................................................... 6 + + 2. Common Structures and Definitions ............................... 7 + 2.1. The ip6_hdr Structure ...................................... 8 + 2.1.1. IPv6 Next Header Values ............................. 8 + 2.1.2. IPv6 Extension Headers .............................. 9 + 2.1.3. IPv6 Options ........................................ 10 + 2.2. The icmp6_hdr Structure .................................... 12 + 2.2.1. ICMPv6 Type and Code Values ......................... 13 + 2.2.2. ICMPv6 Neighbor Discovery Type and Code Values ...... 14 + 2.2.3. Multicast Listener Discovery Type and Code Values ... 16 + 2.2.4. ICMPv6 Router Renumbering Type and Code Values ...... 17 + 2.3. Address Testing Macros ..................................... 19 + 2.4. Protocols File ............................................. 19 + + 3. IPv6 Raw Sockets ................................................ 20 + 3.1. Checksums .................................................. 21 + 3.2. ICMPv6 Type Filtering ...................................... 21 + + 4. Access to IPv6 and Extension Headers ............................ 24 + 4.1. TCP Implications ........................................... 26 + 4.2. UDP and Raw Socket Implications ............................ 27 + + 5. Extensions to Socket Ancillary Data ............................. 27 + + 6. Packet Information .............................................. 28 + 6.1. Specifying/Receiving the Interface ......................... 29 + 6.2. Specifying/Receiving Source/Destination Address ............ 29 + 6.3. Specifying/Receiving the Hop Limit ......................... 30 + 6.4. Specifying the Next Hop Address ............................ 31 + 6.5. Additional Errors with sendmsg() and setsockopt() .......... 31 + + 7. Routing Header Option ........................................... 32 + 7.1. inet6_rth_space ............................................ 33 + 7.2. inet6_rth_init ............................................. 33 + 7.3. inet6_rth_add .............................................. 34 + 7.4. inet6_rth_reverse .......................................... 34 + 7.5. inet6_rth_segments ......................................... 35 + 7.6. inet6_rth_getaddr .......................................... 35 + + 8. Hop-By-Hop Options .............................................. 35 + 8.1. Receiving Hop-by-Hop Options ............................... 36 + 8.2. Sending Hop-by-Hop Options ................................. 37 + + 9. Destination Options ............................................. 37 + 9.1. Receiving Destination Options .............................. 37 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 3] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 9.2. Sending Destination Options ................................ 38 + + 10. Hop-by-Hop and Destination Options Processing ................... 39 + 10.1. inet6_opt_init ............................................ 39 + 10.2. inet6_opt_append .......................................... 39 + 10.3. inet6_opt_finish .......................................... 40 + 10.4. inet6_opt_set_val ......................................... 41 + 10.5. inet6_opt_next ............................................ 41 + 10.6. inet6_opt_find ............................................ 41 + 10.7. inet6_opt_get_val ......................................... 42 + + 11. Additional Advanced API Functions ............................... 42 + 11.1. Sending with the Minimum MTU .............................. 42 + 11.2. Path MTU Discovery and UDP ................................ 43 + 11.3. Neighbor Reachability and UDP ............................. 43 + + 12. Ordering of Ancillary Data and IPv6 Extension Headers ........... 44 + + 13. IPv6-Specific Options with IPv4-Mapped IPv6 Addresses ........... 44 + + 14. Extended interfaces for rresvport, rcmd and rexec ............... 45 + 14.1. rresvport_af .............................................. 45 + 14.2. rcmd_af ................................................... 45 + 14.3. rexec_af .................................................. 46 + + 15. Summary of New Definitions ...................................... 46 + + 16. Security Considerations ......................................... 49 + + 17. Change History .................................................. 49 + + 18. TODO and Open Issues ............................................ 52 + + 19. References ...................................................... 52 + + 20. Acknowledgments ................................................. 53 + + 21. Authors' Addresses .............................................. 53 + + 22. Appendix A: Ancillary Data Overview ............................. 54 + 22.1. The msghdr Structure ...................................... 54 + 22.2. The cmsghdr Structure ..................................... 55 + 22.3. Ancillary Data Object Macros .............................. 57 + 22.3.1. CMSG_FIRSTHDR ...................................... 57 + 22.3.2. CMSG_NXTHDR ........................................ 58 + 22.3.3. CMSG_DATA .......................................... 59 + 22.3.4. CMSG_SPACE ......................................... 60 + 22.3.5. CMSG_LEN ........................................... 60 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 4] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 23. Appendix B: Examples using the inet6_rth_XXX() functions ........ 61 + 23.1. Sending a Routing Header .................................. 61 + 23.2. Receiving Routing Headers ................................. 66 + + 24. Appendix C: Examples using the inet6_opt_XXX() functions ........ 68 + 24.1. Building options .......................................... 68 + 24.2. Parsing received options .................................. 70 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 5] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + +1. Introduction + + A separate specification [RFC-2553] contain changes to the sockets + API to support IP version 6. Those changes are for TCP and UDP-based + applications. This 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 header files. 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. + + There are also features from the basic IPv6 specification that are + not addressed in [RFC-2553]: sending and receiving Routing headers, + Hop-by-Hop options, and Destination options, 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 Routing header, Hop-by-Hop, and + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 6] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + Destination extension headers. + + 5. Additional features required for improved IPv6 application + portability. + + The packet information along with access to the extension headers + (Routing header, Hop-by-Hop options, and Destination options) 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 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. + + 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 protocol headers are required, along with + common constant definitions for the structure members. + + 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(). + + Two new header files are defined: and + . + + When an include file is specified, that include file is allowed to + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 7] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 + . Note that this is a new header. + + struct ip6_hdr { + union { + struct ip6_hdrctl { + uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, 24 bits 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, top 4 bits tclass */ + } 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 + #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 + . + + #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. + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 8] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 + . + + /* Hop-by-Hop options header */ + 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 */ + 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 { + 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 */ + uint32_t ip6r0_reserved; /* reserved field */ + /* followed by up to 127 struct in6_addr */ + }; + + /* Fragment header */ + struct ip6_frag { + uint8_t ip6f_nxt; /* next header */ + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 9] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 + + + +2.1.3. IPv6 Options + + Eleven options are defined for IPv6 at the time of writing this + document. We define structures for all except the unspecified EID + option. The following structures are defined as a result of + including . + + /* IPv6 options */ + structip6_opt { + uint8_tip6o_type; + uint8_tip6o_len; + }; + + /* + * The high-order 3 bits of the option type define the behavior + * when processing an unknown option and whether or not the option + * content changes in flight. + */ + #defineIP6OPT_TYPE(o)((o) & 0xc0) + #defineIP6OPT_TYPE_SKIP0x00 + #defineIP6OPT_TYPE_DISCARD0x40 + #defineIP6OPT_TYPE_FORCEICMP0x80 + #defineIP6OPT_TYPE_ICMP0xc0 + #defineIP6OPT_MUTABLE0x20 + + #defineIP6OPT_PAD10x00/* 00 0 00000 */ + #defineIP6OPT_PADN0x01/* 00 0 00001 */ + #defineIP6OPT_JUMBO0xc2/* 11 0 00010 = 194 */ + #defineIP6OPT_NSAP_ADDR0xc3/* 11 0 00011 */ + #defineIP6OPT_TUNNEL_LIMIT0x04/* 00 0 00100 */ + #defineIP6OPT_ROUTER_ALERT0x05/* 00 0 00101 */ + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 10] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + #defineIP6OPT_BINDING_UPDATE0xc6/* 11 0 00110 */ + #defineIP6OPT_BINDING_ACK0x07/* 00 0 00111 */ + #defineIP6OPT_BINDING_REQ0x08/* 00 0 01000 */ + #defineIP6OPT_HOME_ADDRESS0xc9/* 11 0 01001 */ + #defineIP6OPT_EID0x8a/* 10 0 01010 */ + + /* Jumbo Payload Option */ + structip6_opt_jumbo { + uint8_tip6oj_type; + uint8_tip6oj_len; + uint8_t ip6oj_jumbo_len[4]; + }; + #defineIP6OPT_JUMBO_LEN6 + + /* NSAP Address Option */ + structip6_opt_nsap { + uint8_tip6on_type; + uint8_tip6on_len; + uint8_t ip6on_src_nsap_len; + uint8_t ip6on_dst_nsap_len; + /* followed by source NSAP */ + /* followed by destination NSAP */ + }; + + /* Tunnel Limit Option */ + structip6_opt_tunnel { + uint8_tip6ot_type; + uint8_tip6ot_len; + uint8_t ip6ot_encap_limit; + }; + + /* Router Alert Option */ + structip6_opt_router { + uint8_tip6or_type; + uint8_tip6or_len; + uint8_t ip6or_value[2]; + }; + + /* Router alert values (in network byte order) */ + #ifdef _BIG_ENDIAN + #defineIP6_ALERT_MLD0x0000 + #defineIP6_ALERT_RSVP0x0001 + #defineIP6_ALERT_AN0x0002 + #else + #defineIP6_ALERT_MLD0x0000 + #defineIP6_ALERT_RSVP0x0100 + #defineIP6_ALERT_AN0x0200 + #endif + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 11] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + /* Binding Update Option */ + structip6_opt_binding_update { + uint8_tip6ou_type; + uint8_tip6ou_len; + uint8_t ip6ou_flags; + uint8_t ip6ou_prefixlen; + uint8_t ip6ou_seqno[2]; + uint8_t ip6ou_lifetime[4]; + uint8_t ip6ou_coa[16];/* Optional based on flags */ + /* followed by sub-options */ + }; + + /* Binding Update Flags */ + #defineIP6_BUF_ACK0x80/* Request a binding ack */ + #defineIP6_BUF_HOME0x40/* Home Registration */ + #defineIP6_BUF_COA0x20/* Care-of-address present in option */ + #defineIP6_BUF_ROUTER0x10/* Sending mobile node is a router */ + + /* Binding Ack Option */ + structip6_opt_binding_ack { + uint8_tip6oa_type; + uint8_tip6oa_len; + uint8_t ip6oa_status; + uint8_t ip6oa_seqno[2]; + uint8_t ip6oa_lifetime[4]; + uint8_t ip6oa_refresh[4]; + /* followed by sub-options */ + }; + + /* Binding Request Option */ + structip6_opt_binding_request { + uint8_tip6or_type; + uint8_tip6or_len; + /* followed by sub-options */ + }; + + /* Home Address Option */ + structip6_opt_home_address { + uint8_tip6oh_type; + uint8_tip6oh_len; + uint8_t ip6oh_addr[16];/* Home Address */ + /* followed by sub-options */ + }; + + + +2.2. The icmp6_hdr Structure + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 12] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 + . 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 + . + + #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 + #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 */ + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 13] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + #define ICMP6_DST_UNREACH_ADMIN 1 /* communication with */ + /* destination */ + /* admin. prohibited */ + #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ + #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 . + + #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 */ + /* could be followed by options */ + }; + + #define nd_ra_type nd_ra_hdr.icmp6_type + #define nd_ra_code nd_ra_hdr.icmp6_code + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 14] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + #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 */ + }; + + #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 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 15] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + #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; + }; + + We note that the nd_na_flags_reserved flags have the same byte + ordering problems as we discussed with ip6f_offlg. + + +2.2.3. Multicast Listener Discovery Type and Code Values + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 16] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + The following structures and definitions are defined as a result of + including . + + struct mld_hdr { + struct icmp6_hdr mld_hdr; + struct in6_addr mld_addr; /* multicast address */ + }; + #define mld_type mld_hdr.icmp6_type + #define mld_code mld_hdr.icmp6_code + #define mld_cksum mld_hdr.icmp6_cksum + #define mld_maxdelay mld_hdr.icmp6_data16[0] + #define mld_reserved mld_hdr.icmp6_data16[1] + + + +2.2.4. ICMPv6 Router Renumbering Type and Code Values + + The following structures and definitions are defined as a result of + including . + + struct icmp6_router_renum { /* router renumbering header */ + struct icmp6_hdr rr_hdr; + u_int8_t rr_segnum; + u_int8_t rr_flags; + u_int16_t rr_maxdelay; + u_int32_t rr_reserved; + }; + #define rr_type rr_hdr.icmp6_type + #define rr_code rr_hdr.icmp6_code + #define rr_cksum rr_hdr.icmp6_cksum + #define rr_seqnum rr_hdr.icmp6_data32[0] + + /* Router renumbering flags */ + #define ICMP6_RR_FLAGS_TEST 0x80 + #define ICMP6_RR_FLAGS_REQRESULT 0x40 + #define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 + #define ICMP6_RR_FLAGS_SPECSITE 0x10 + #define ICMP6_RR_FLAGS_PREVDONE 0x08 + + + struct rr_pco_match { /* match prefix part */ + u_int8_t rpm_code; + u_int8_t rpm_len; + u_int8_t rpm_ordinal; + u_int8_t rpm_matchlen; + u_int8_t rpm_minlen; + u_int8_t rpm_maxlen; + u_int16_t rpm_reserved; + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 17] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + struct in6_addr rpm_prefix; + }; + + /* PCI code values */ + #define RPM_PCO_ADD 1 + #define RPM_PCO_CHANGE 2 + #define RPM_PCO_SETGLOBAL 3 + + struct rr_pco_use { /* use prefix part */ + u_int8_t rpu_uselen; + u_int8_t rpu_keeplen; + u_int8_t rpu_ramask; + u_int8_t rpu_raflags; + u_int32_t rpu_vltime; + u_int32_t rpu_pltime; + u_int32_t rpu_flags; + struct in6_addr rpu_prefix; + }; + #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20 + #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10 + + #if BYTE_ORDER == BIG_ENDIAN + #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000 + #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000 + #elif BYTE_ORDER == LITTLE_ENDIAN + #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80 + #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40 + #endif + + struct rr_result { /* router renumbering result message */ + u_int16_t rrr_flags; + u_int8_t rrr_ordinal; + u_int8_t rrr_matchedlen; + u_int32_t rrr_ifid; + struct in6_addr rrr_prefix; + }; + + #if BYTE_ORDER == BIG_ENDIAN + #define ICMP6_RR_RESULT_FLAGS_OOB 0x0002 + #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001 + #elif BYTE_ORDER == LITTLE_ENDIAN + #define ICMP6_RR_RESULT_FLAGS_OOB 0x0200 + #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100 + #endif + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 18] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + +2.3. Address Testing Macros + + The basic API ([RFC-2553]) 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 . + + int IN6_ARE_ADDR_EQUAL(const struct in6_addr *, + const struct in6_addr *); + + This macro returns non-zero if the addresses are equal; otherwise it + returns zero. + + +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(PF_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 + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 19] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + +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 used the host's byte order for certain IP header fields. + + Another difference from IPv4 raw sockets is that complete packets + (that is, IPv6 packets with extension headers) cannot be sent or + received using the IPv6 raw sockets API. Instead, ancillary data + objects are used to transfer the extension headers and hoplimit + information, as described in Section 6. 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 and on receipt the application will + only receive the payload i.e. the data after the IPv6 header and all + the extension headers. + + 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 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 20] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + is normally 255, to have it mean that the application will send down + complete packets including the IPv4 header. (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.) We note that this value has no + special meaning to an IPv6 raw socket (and the IANA currently + reserves the value of 255 when used as a next-header field). + + +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-2460]. This new socket option also specifies an integer offset + into the user data of where the checksum is located. + + int offset = 2; + setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)); + + By default, this socket option is disabled. Setting the offset to -1 + also disables the option. By disabled we mean (1) the kernel will + not calculate and store a checksum for outgoing packets, and (2) the + kernel will not verify a checksum for received packets. + + An attempt to set IPV6_CHECKSUM for an ICMPv6 socket will fail. + + (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 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 21] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 multicast listener discovery messages. + + 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 + . + + 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 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 22] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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. + + 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. + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 23] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + 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)) + + (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 header for the memset() function.) + + +4. Access to IPv6 and Extension Headers + + Applications need to be able to control IPv6 header and extension + header content when sending as well as being able to receive the + content of these headers. This is done by defining socket option + types which can be used both with setsockopt and with ancillary data. + Ancillary data is discussed in Appendix A. The following optional + information can be exchanged between the application and the kernel: + + 1. The send/receive interface and source/destination address, + 2. The hop limit, + 3. Next hop address, + 4. Routing header. + 5. Hop-by-Hop options, and + 6. Destination options (both before and after a 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: + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 24] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + int on = 1; + + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &on, sizeof(on)); + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, + &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. + + Two different mechanisms exist for sending this optional information: + + 1. Using setsockopt to specify the option content for a socket. + These are known an "sticky" options since they affect all + transmitted packets on the socket until either the a new + setsockopt is done or the options are overridden using ancillary + data. + + 2. Using ancillary data to specify the option content for a single + datagram. This only applies to datagram and raw sockets; not to + TCP sockets. + + + The three socket option parameters and the three cmsghdr fields that + describe the options/ancillary data objects are summarized as: + + opt level/ optname/ optval/ + cmsg_level cmsg_type cmsg_data[] + ------------ ------------ ------------------------ + IPPROTO_IPV6 IPV6_PKTINFO in6_pktinfo structure + IPPROTO_IPV6 IPV6_HOPLIMIT int + IPPROTO_IPV6 IPV6_NEXTHOP socket address structure + IPPROTO_IPV6 IPV6_RTHDR ip6_rthdr structure + IPPROTO_IPV6 IPV6_HOPOPTS ip6_hbh structure + IPPROTO_IPV6 IPV6_DSTOPTS ip6_dest structure + IPPROTO_IPV6 IPV6_RTHDRDSTOPTS ip6_dest structure + + + All these options are described in detail in Section 6, 7, 8 and 9. + All the constants beginning with IPV6_ are defined as a result of + including the . + + Issuing getsockopt() for the above options will return the sticky + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 25] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + option value i.e. the value set with setsockopt(). + + 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"). + + The application does not explicitly need to access the data + structures for the Routing header option, Hop-by-Hop option, and + Destination options, since the API to these features is through a set + of inet6_rth_XXX() and inet6_opt_XXX() functions that we define in + Section 8 and Section 10. Those functions simplify the interface to + these features instead of requiring the application to know the + intimate details of the extension header formats. + + +4.1. TCP Implications + + It is not possible to use ancillary data to transmit the above + options for TCP since there is not a one-to-one mapping between send + operations and the TCP segments being transmitted. Instead an + application can use setsockopt to specify them as sticky options. + When the application uses setsockopt to specify the above options it + is expected that TCP will start using the new information when + sending segments. However, TCP may or may not use the new + information when retransmitting segments that were originally sent + when the old sticky options were in effect. + + Applications using TCP can use ancillary data (after enabling the + desired IPV6_RECVxxx options) to receive the IPv6 and extension + header information. However, since there is not a one-to-one mapping + between received TCP segments and recv operations seen by the + application, when different TCP segments have different IPv6 and + extension headers the application might not be able to observe all + received headers. For efficiency reasons it is recommended that a + TCP implementation not send ancillary data items with every received + segment but instead try to detect the points in the data stream when + the requested IPv6 and extension header content changes and only send + a single ancillary data item at the time of the change. Also, TCP + should send ancillary data items at the start of the connection and + when the application enables a new IPV6_RECVxxx option. + + For example, assume an application has enabled IPV6_RECVHOPLIMIT + before a connection is established. Then the first recvmsg() would + have an IPV6_HOPLIMIT item indicating the hop limit in the first data + segment. Should the hoplimit in the received data segment change a + subsequent recvmsg() will also have an IPV6_HOPLIMIT item. However, + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 26] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + the application must be prepared to handle ancillary data items even + though the hop limit did not change. Note that should the hop limit + in received ACK-only segments be different than the hop limit in data + segments the application might only be able to observe the hop limit + in the received data segments. + + The above example was for hop limit but the application should be + prepared to handle the corresponding behavior for the other option + information. + + The above recvmsg() behavior allows the application to detect changes + in the received IPv6 and extension headers without resorting to + periodic getsockopt() calls. + + +4.2. UDP and Raw Socket Implications + + The receive behavior for UDP and raw sockets is quite + straightforward. After the application has enabled an IPV6_RECVxxx + socket option it will receive ancillary data items for every + recvmsg() call containing the requested information. However, if the + information is not present in the packet the ancillary data item will + not be included. For example, if the application enables + IPV6_RECVRTHDR and a received datagram does not contain a Routing + header there will not be an IPV6_RTHDR ancillary data item. Note + that due to buffering in the socket implementation there might be + some packets queued when an IPV6_RECVxxx option is enabled and they + might not have the ancillary data information. + + For sending the application has the choice between using sticky + options and ancillary data. The application can also use both having + the sticky options specify the "default" and using ancillary data to + override the default options. Note that if any ancillary data is + specified in a call to sendmsg(), all of the sticky options are + overridden for that datagram. For example, if the application has + set IPV6_RTHDR using a sticky option and later passes IPV6_HOPLIMIT + as ancillary data this will override the IPV6_RTHDR sticky option and + no Routing header will be sent with that datagram. + + +5. Extensions to Socket Ancillary Data + + This specification uses ancillary data as defined in Posix.1g which + the following compatible extensions: + + - CMSG_NEXTHDR has been extended to handle a NULL 2nd argument to + mean "get the first header". See Section 22.3.2. + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 27] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + - A new CMSG_SPACE macro is defined. It is used to determine how + much space need to be allocated for an ancillary data item. See + Section 22.3.4. + + - A new CMSG_LEN macro is defined. It returns the value to store + in the cmsg_len member of the cmsghdr structure, taking into + account any padding needed to satisfy alignment requirements. + See Section 22.3.5. + + +6. 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 set with setsockopt() or sent as ancillary data + with sendmsg() and received as ancillary data with recvmsg(). This + structure is defined as a result of including the . + + struct in6_pktinfo { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ + }; + + In the socket option and cmsghdr level will be IPPROTO_IPV6, the type + will be IPV6_PKTINFO, and the first byte of the option value and + cmsg_data[] will be the first byte of the in6_pktinfo structure. An + application can clear any sticky IPV6_PKTINFO option by either doing + a setsockopt for option with optlen being zero, or by doing a + "regular" setsockopt with ipi6_addr being in6addr_any and + ipi6_ifindex being zero. + + This information is returned as ancillary data by recvmsg() only if + the application has enabled the IPV6_RECVPKTINFO socket option: + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 28] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); + + + (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_RECVPKTINFO 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.) + + +6.1. Specifying/Receiving the Interface + + Interfaces on an IPv6 node are identified by a small positive + integer, as described in Section 4 of [RFC-2553]. 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-2553]), 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. + + +6.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 + requires less state to be stored and protected in a multithreaded + application. + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 29] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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 or in6addr_any), 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. + + +6.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-2553]. 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_RECVHOPLIMIT socket + option: + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &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() or + using setsockopt(). As specified in [RFC-2553], the interpretation + of the integer hop limit value is + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 30] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + x < -1: return an error of EINVAL + x == -1: use kernel default + 0 <= x <= 255: use x + x >= 256: return an error of EINVAL + + + +6.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. + + +6.5. Additional Errors with sendmsg() and setsockopt() + + 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() or setsockopt(). Note that some + implementations might only be able to return this type of errors for + setsockopt(). 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. + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 31] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + EHOSTUNREACH No route to the destination exists over the interface + specified by ifi6_ifindex. + + +7. 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-2460]. This type supports up to 127 intermediate nodes (limited + by the length field in the extension header). With this maximum + number of intermediate nodes, a source, and a destination, there are + 128 hops. + + 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, and the ability to use sticky options or ancillary data to + communicate this information between the application and the kernel + using the IPV6_RTHDR option. + + Three functions build a Routing header: + + inet6_rth_space() - return #bytes required for Routing header + inet6_rth_init() - initialize buffer data for Routing header + inet6_rth_add() - add one IPv6 address to the Routing header + + Three functions deal with a returned Routing header: + + inet6_rth_reverse() - reverse a Routing header + inet6_rth_segments() - return #segments in a Routing header + inet6_rth_getaddr() - fetch one address from a Routing header + + The function prototypes for these functions are defined as a result + of including the . + + To receive a Routing header the application must enable the + IPV6_RECVRTHDR socket option: + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDR, &on, sizeof(on)); + + To send a Routing header the application specifies it either as + ancillary data in a call to sendmsg() or using setsockopt(). + + The application can remove any sticky Routing header by calling + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 32] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + setsockopt() for IPV6_RTHDR with a zero option length. + + When using ancillary data a Routing header is passed between the + application and the kernel as follows: 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 six functions that we are about to + describe. + + The following constant is defined as a result of including the + : + + #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. + + +7.1. inet6_rth_space + + + size_t inet6_rth_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 + segments (addresses). For an IPv6 Type 0 Routing header, the number + of segments must be between 0 and 127, inclusive. The return value + is just the space for the Routing header. When the application uses + ancillary data it must pass the returned length to CMSG_LEN() to + determine how much memory is needed for the ancillary data object + (including the cmsghdr structure). + + 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.) + + +7.2. inet6_rth_init + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 33] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + void *inet6_rth_init(void *bp, int bp_len, int type, int segments); + + This function initializes the buffer pointed to by bp to contain a + Routing header of the specified type and sets ip6r0_len based on the + segments parameter. bp_len is only used to verify that the buffer is + large enough. The ip6r0_segleft field is set to zero; + inet6_rth_add() will increment it. + + When the application uses ancillary data the application must + initialize any cmsghdr fields. + + The caller must allocate the buffer and its size can be determined by + calling inet6_rth_space(). + + Upon success the return value is the pointer to the buffer (bp), and + this is then used as the first argument to the next two functions. + Upon an error the return value is NULL. + + +7.3. inet6_rth_add + + + int inet6_rth_add(void *bp, const struct in6_addr *addr); + + This function adds the IPv6 address pointed to by addr to the end of + the Routing header being constructed. + + If successful, the segleft member of the Routing Header 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. + + +7.4. inet6_rth_reverse + + + int inet6_rth_reverse(const void *in, void *out) + + This function takes a Routing header extension header (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 + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 34] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + error. + + +7.5. inet6_rth_segments + + + int inet6_rth_segments(const void *bp); + + This function returns the number of segments (addresses) contained in + the Routing header described by bp. On success the return value is + zero or greater. The return value of the function is -1 upon an + error. + + +7.6. inet6_rth_getaddr + + + struct in6_addr *inet6_rth_getaddr(const void *bp, int index); + + This function returns a pointer to the IPv6 address specified by + index (which must have a value between 0 and one less than the value + returned by inet6_rth_segments()) in the Routing header described by + bp. An application should first call inet6_rth_segments() to obtain + the number of segments in the Routing header. + + Upon an error the return value of the function is NULL. + + +8. 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 four Hop-by-Hop options are defined for IPv6 [RFC-2460]: + Jumbo Payload, Pad1, PadN, and router-alert. The two pad options are + for alignment purposes and are automatically inserted by the + inet6_opt_XXX() routines and ignored by the inet6_opt_XXX() routines + on the receive side. + + This section of the API is therefore defined for future Hop-by-Hop + options (as well as destination options) that an application may need + to specify and receive. This IPv6 API defines seven functions that + the application calls to build and examine a Hop-by_Hop options + header, and the ability to use sticky options or ancillary data to + communicate this information between the application and the kernel. + This uses the IPV6_HOPOPTS for hob-by-hop options. + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 35] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + Four functions build a options header: + + inet6_opt_init() - initialize buffer data for options header + inet6_opt_append() - add one TLV option to the options header + inet6_opt_finish() - finish adding TLV options to the options header + inet6_opt_set_val() - add one component of the option content to the option + + Three functions deal with a returned options header: + + inet6_opt_next() - extract the next option from the options header + inet6_opt_find() - extract an option of a specified type from the header + inet6_opt_get_val() - retrieve one component of the option content + + + Individual Hop-by-Hop options (and Destination options, which are + described in Section 9 and are very 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 B of [RFC-2460]. The alignment + of first byte 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. The + functions below need to know the alignment of the end of the option + (which is always in the form "xn," where x can have the values 1, 2, + 4, or 8) and the total size of the data portion of the option. These + are passed as the "align" and "len" arguments to inet6_opt_append(). + + Multiple Hop-by-Hop options must be specified by the application by + placing them in a single extension header. + + Finally, we note that use of some Hop-by-Hop options or 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. + + +8.1. Receiving Hop-by-Hop Options + + To receive Hop-by-Hop options the application must enable the + IPV6_RECVHOPOPTS socket option: + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 36] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &on, sizeof(on)); + + When using ancillary data a Hop-by-hop options is passed between the + application and the kernel as follows: 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_opt_next(), + inet6_opt_find(), and inet6_opt_get_val() functions, described in + Section 10.6. + + +8.2. Sending Hop-by-Hop Options + + To send a Hop-by-Hop options header, the application specifies the + header either as ancillary data in a call to sendmsg() or using + setsockopt(). + + The application can remove any sticky Hop-by-Hop extension header by + calling setsockopt() for IPV6_HOPOPTS with a zero option length. + + All the Hop-by-Hop options must specified by a single ancillary data + object. 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_opt_init(), inet6_opt_append(), + inet6_opt_finish(), and inet6_set_val() functions, described in + Section 10. + + Additional errors may be possible from sendmsg() and setsockopt() if + the specified option is in error. + + +9. Destination Options + + A variable number of Destination options can appear in one or more + Destination option headers. As defined in [RFC-2460], 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-2460], + although proposals exist to use Destination options with Mobile IPv6. + + +9.1. Receiving Destination Options + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 37] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + To receive Destination options appearing after a Routing header (or + in a packet without a Routing header) the application must enable the + IPV6_RECVDSTOPTS socket option: + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &on, sizeof(on)); + + To receive Destination options appearing before a Routing header the + application must enable the IPV6_RECVRTHDRDSTOPTS socket option: + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, + &on, sizeof(on)); + + All the Destination options appearing before a Routing header are + returned as one ancillary data object described by a cmsghdr + structure (with cmsg_type set to IPV6_RTHDRDSTOPTS) and all the + Destination options appearing after a Routing header (or in a packet + without a Routing header) are returned as another ancillary data + object described by a cmsghdr structure (with cmsg_type set to + IPV6_DSTOPTS). For all these ancillary data objects, the cmsg_level + member will be IPPROTO_IPV6. + + These options are then processed by calling the inet6_opt_next(), + inet6_opt_find(), and inet6_opt_get_value() functions. + + +9.2. Sending Destination Options + + To send a Destination options header, the application specifies it + either as ancillary data in a call to sendmsg() or using + setsockopt(). + + The application can remove any sticky Destination extension header by + calling setsockopt() for IPV6_RTHDRDSTOPTS/IPV6_DSTOPTS with a zero + option length. + + As described in Section 6 one set of Destination options can appear + before a Routing header, and one set can appear after a Routing + header (or in a packet with no Routing header). Each set can consist + of one or more options but each set is a single extension header. + + When using ancillary data a Destination options header is passed + between the application and the kernel as follows: The set preceding + a Routing header are specified with the cmsg_level member is set to + IPPROTO_IPV6 and the cmsg_type member is set to IPV6_RTHDRDSTOPTS. + Any setsockopt or ancillary data for IPV6_RTHDRDSTOPTS is silently + ignore when sending packets unless a Routing header is also + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 38] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + specified. + + The set of Destination options after a Routing header, which are also + used when no Routing header is present, are specified with the + cmsg_level member is set to IPPROTO_IPV6 and the cmsg_type member is + set to IPV6_DSTOPTS. + + The Destination options are normally constructed using the + inet6_opt_init(), inet6_opt_append(), inet6_opt_finish(), and + inet6_set_val() functions, described in Section 10. + + Additional errors may be possible from sendmsg() and setsockopt() if + the specified option is in error. + + +10. 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. These functions assume the + formatting rules specified in Appendix B in [RFC-2460] i.e. that the + largest field is placed last in the option. + + The function prototypes for these functions are defined as a result + of including the . + + The first 3 functions (init, append, and finish) are used both to + calculate the needed buffer size for the options, and to actually + encode the options once the application has allocated a buffer for + the header. In order to only calculate the size the application must + pass a NULL extbuf and a zero extlen to those functions. + + +10.1. inet6_opt_init + + + int inet6_opt_init(void *extbuf, size_t extlen); + + This function returns the number of bytes needed for the empty + extension header i.e. without any options. If extbuf is not NULL it + also initializes the extension header to have the correct length + field. If the extlen value is not a positive (i.e., non-zero) + multiple of 8 the function fails and returns -1. + + +10.2. inet6_opt_append + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 39] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + int inet6_opt_append(void *extbuf, size_t extlen, int prevlen, + uint8_t type, size_t len, uint_t align, + void **databufp); + + Prevlen should be the length returned by inet6_opt_init() or a + previous inet6_opt_append(). This function returns the updated total + length taking into account adding an option with length 'len' and + alignment 'align'. If extbuf is not NULL then, in addition to + returning the length, the function inserts any needed pad option, + initializes the option (setting the type and length fields) and + returns a pointer to the location for the option content in databufp. + If the option does not fit in the extension header buffer the + function returns -1. + + type is the 8-bit option type. len is the length of the option data + (i.e. excluding the option type and option length fields). + + Once inet6_opt_append() has been called the application can use the + databuf directly, or use inet6_opt_set_val() to specify the content + of the option. + + 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. + + The align parameter must have a value of 1, 2, 4, or 8. The align + value can not exceed the value of len. + + +10.3. inet6_opt_finish + + + int inet6_opt_finish(void *extbuf, size_t extlen, int prevlen); + + Prevlen should be the length returned by inet6_opt_init() or + inet6_opt_append(). This function returns the updated total length + taking into account the final padding of the extension header to make + it a multiple of 8 bytes. If extbuf is not NULL the function also + initializes the option by inserting a Pad1 or PadN option of the + proper length. + + If the necessary pad does not fit in the extension header buffer the + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 40] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + function returns -1. + + +10.4. inet6_opt_set_val + + + int inet6_opt_set_val(void *databuf, size_t offset, void *val, + int vallen); + + Databuf should be a pointer returned by inet6_opt_append(). This + function inserts data items of various sizes (1, 2, 4, or 8 bytes) in + the data portion of the option. val should point to the data to be + inserted. Offset specifies where in the data portion of the option + the value should be inserted; the first byte after the option type + and length is accessed by specifying an offset of zero. + + The function returns the offset for the next field (i.e., offset + + vallen) which can be used when composing option content with multiple + fields. + + +10.5. inet6_opt_next + + + int inet6_opt_next(void *extbuf, size_t extlen, int prevlen, + uint8_t *typep, size_t *lenp, + void **databufp); + + This function parses received extension headers returning the next + option. Extbuf and extlen specifies the extension header. Prevlen + should either be zero (for the first option) or the length returned + by a previous call to inet6_opt_next() or inet6_opt_find(). It + specifies the position where to continue scanning the extension + buffer. The next option is returned by updating typep, lenp, and + databufp. This function returns the updated "previous" length + computed by advancing past the option that was returned. This + returned "previous" length can then be passed to subsequent calls to + inet6_opt_next(). This function does not return any PAD1 or PADN + options. When there are no more options the return value is -1. + + +10.6. inet6_opt_find + + + int inet6_opt_find(void *extbuf, size_t extlen, int prevlen, + uint8_t type, size_t *lenp, + void **databufp); + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 41] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + This function is similar to the previously described inet6_opt_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 extension header. + + If an option of the specified type is located, the function returns + the updated "previous" total length computed by advancing past the + option that was returned and past any options that didn't match the + type. This returned "previous" length can then be passed to + subsequent calls to inet6_opt_find() for finding the next occurance + of the same option type. + + If an option of the specified type is not located, the return value + is -1. If an error occurs, the return value is -1. + + +10.7. inet6_opt_get_val + + + int inet6_opt_get_val(void *databuf, size_t offset, void *val, + int vallen); + + Databuf should be a pointer returned by inet6_opt_next() or + inet6_opt_find(). This function extracts data items of various sizes + (1, 2, 4, or 8 bytes) in the data portion of the option. val should + point to the destination for the extracted data. Offset specifies + from where in the data portion of the option the value should be + extracted; the first byte after the option type and length is + accessed by specifying an offset of zero. + + The function returns the offset for the next field (i.e., offset + + vallen) which can be used when extracting option content with + multiple fields. XXX Perhaps we should add a note to point out that + robust receivers should verify alignment before calling + inet6_opt_get_val(). XXX Or check alignment and fail by returning + -1? + + +11. Additional Advanced API Functions + + + +11.1. Sending with the Minimum MTU + + Some applications might not want to incur the overhead of path MTU + discovery, especially if the applications only send a single datagram + to a destination. A potential example is a DNS server. + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 42] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + This specification defines a mechanism to avoid fragmentation by + sending at the minimum IPv6 MTU (1280 bytes). This can be enabled + using the IPV6_USE_MIN_MTU socket option. + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &on, sizeof(on)); + + By default, this socket option is disabled. Setting the value to 0 + also disables the option. This option can also be sent as ancillary + data. + + +11.2. Path MTU Discovery and UDP + + UDP and raw socket applications need to be able to determine the + "maximum send transport-message size" (Section 5.1 of [RFC-1981]) to + a given destination so that those applications can participate in + path MTU discovery. This lets those applications send smaller + datagrams to the destination, avoiding fragmentation. + + This is accomplished using a new ancillary data item (IPV6_PATHMTU) + which is delivered to recvmsg() without any actual data. The + application enable the receipt of IPV6_PATHMTU ancillary data items + by enabing IPV6_RECVPATHMTU. + + int on = 1; + setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPATHMTU, &on, sizeof(on)); + + By default, this socket option is disabled. Setting the value to 0 + also disables the option. + + When the application is sending packets too big for the path MTU + recvmsg will return zero (indicating no data) but there will be a + cmsghdr with cmsg_type set to IPV6_PATHMTU, and cmsg_len will + indicate that cmsg_data is 4 bytes long. CMSG_DATA will point to an + integer carrying the path MTU to use. + + +11.3. Neighbor Reachability and UDP + + UDP and raw socket application might know that communication is + making forward progress i.e. that the path from the node to the next + hop is working. In such a case the applications, similarly to TCP as + specified in [RFC-2461], has the option indicate to the internet + layer that the neighbor is reachable. See section 7.3.1 of + [RFC-2461]. This could save unneeded neighbor solicitation and + neighbor advertisement messages. + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 43] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + This is done by including an ancilary data item with cmsg_type being + IPV6_REACHCONF and with no attached CMSG_DATA. + + +12. 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(): the Routing header, Hop-by-Hop options, and Destination + options. When multiple ancillary data objects are transferred via + 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 for using these ancillary data objects with + sendmsg(). + + All Hop-by-Hop options must be specified in a single ancillary data + object. Should multiple hop-by-hop ancillary data objects be + specified the implementation might choose an arbitrary one or drop + the packet. + + All Destination options that precede a Routing header must be + specified in a single ancillary data object. If there is no Routing + header ancillary data object the IPV6_RTHDRDSTOPTS object will be + silently ignored. + + All Destination options that follow a Routing header (or are used + without a Routing header) must be specified in a single ancillary + data object. + + 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. + + +13. 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 + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 44] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + 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. + + +14. Extended interfaces for rresvport, rcmd and rexec + + TBD + + +14.1. 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 + + int rresvport_af(int *port, int family); + + This function behaves the same as the existing rresvport() function, + but instead of creating an AF_INET TCP socket, it can also create an + AF_INET6 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 + , others in , and others don't define the function + prototypes at all.) + + +14.2. rcmd_af + + The existing rcmd() function can not transparently use AF_INET6 + sockets since the an application would not be prepared to handle + AF_INET6 addresses returned by e.g. getpeername on the file + descriptor created by rcmd. Thus a new function is needed. + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 45] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + int rcmd_af(char **ahost, unsigned short rport, const char *locuser, + const char *remuser, const char *cmd, int *fd2p, int af) + + This function behaves the same as the existing rcmd() function, but + instead of creating an AF_INET TCP socket, it can also create an + AF_INET6 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. + + +14.3. rexec_af + + The existing rexec() function can not transparently use AF_INET6 + sockets since the an application would not be prepared to handle + AF_INET6 addresses returned by e.g. getpeername on the file + descriptor created by rexec. Thus a new function is needed. + + int rexec_af(char **ahost, unsigned short rport, const char *name, + const char *pass, const char *cmd, int *fd2p, int af) + + This function behaves the same as the existing rexec() function, but + instead of creating an AF_INET TCP socket, it can also create an + AF_INET6 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. + + +15. Summary of New Definitions + + The following list summarizes the constants and structure, + definitions discussed in this memo, sorted by header. + + ICMP6_DST_UNREACH + ICMP6_DST_UNREACH_ADDR + ICMP6_DST_UNREACH_ADMIN + ICMP6_DST_UNREACH_NOPORT + ICMP6_DST_UNREACH_NOROUTE + ICMP6_DST_UNREACH_BEYONDSCOPE + ICMP6_ECHO_REPLY + ICMP6_ECHO_REQUEST + ICMP6_INFOMSG_MASK + ICMP6_MEMBERSHIP_QUERY + ICMP6_MEMBERSHIP_REDUCTION + ICMP6_MEMBERSHIP_REPORT + ICMP6_PACKET_TOO_BIG + ICMP6_PARAMPROB_HEADER + ICMP6_PARAMPROB_NEXTHEADER + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 46] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + ICMP6_PARAMPROB_OPTION + ICMP6_PARAM_PROB + ICMP6_TIME_EXCEEDED + ICMP6_TIME_EXCEED_REASSEMBLY + ICMP6_TIME_EXCEED_TRANSIT + ND_NA_FLAG_OVERRIDE + ND_NA_FLAG_ROUTER + ND_NA_FLAG_SOLICITED + ND_NEIGHBOR_ADVERT + ND_NEIGHBOR_SOLICIT + ND_OPT_MTU + ND_OPT_PI_FLAG_AUTO + ND_OPT_PI_FLAG_ONLINK + ND_OPT_PREFIX_INFORMATION + ND_OPT_REDIRECTED_HEADER + ND_OPT_SOURCE_LINKADDR + ND_OPT_TARGET_LINKADDR + ND_RA_FLAG_MANAGED + ND_RA_FLAG_OTHER + ND_REDIRECT + ND_ROUTER_ADVERT + ND_ROUTER_SOLICIT + + struct icmp6_filter{}; + struct icmp6_hdr{}; + struct nd_neighbor_advert{}; + struct nd_neighbor_solicit{}; + struct nd_opt_hdr{}; + struct nd_opt_mtu{}; + struct nd_opt_prefix_info{}; + struct nd_opt_rd_hdr{}; + struct nd_redirect{}; + struct nd_router_advert{}; + struct nd_router_solicit{}; + + IPPROTO_AH + IPPROTO_DSTOPTS + IPPROTO_ESP + IPPROTO_FRAGMENT + IPPROTO_HOPOPTS + IPPROTO_ICMPV6 + IPPROTO_IPV6 + IPPROTO_NONE + IPPROTO_ROUTING + IPV6_RECVDSTOPTS + IPV6_RECVHOPLIMIT + IPV6_RECVHOPOPTS + IPV6_RECVPKTINFO + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 47] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + IPV6_RECVRTHDR + IPV6_RECVRTHDRDSTOPTS + IPV6_DSTOPTS + IPV6_HOPLIMIT + IPV6_HOPOPTS + IPV6_NEXTHOP + IPV6_PKTINFO + IPV6_RTHDR + IPV6_RTHDRDSTOPTS + IPV6_RTHDR_TYPE_0 + IPV6_USE_MIN_MTU + IPV6_RECVPATHMTU + IPV6_PATHMTU + IPV6_REACHCONF + struct in6_pktinfo{}; + + IP6F_OFF_MASK + IP6F_RESERVED_MASK + IP6F_MORE_FRAG + struct ip6_dest{}; + struct ip6_frag{}; + struct ip6_hbh{}; + struct ip6_hdr{}; + struct ip6_rthdr{}; + struct ip6_rthdr0{}; + + struct cmsghdr{}; + struct msghdr{}; + + + The following list summarizes the function and macro prototypes + discussed in this memo, sorted by header. + + void ICMP6_FILTER_SETBLOCK(int, struct icmp6_filter *); + void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *); + void ICMP6_FILTER_SETPASS(int, struct icmp6_filter *); + void ICMP6_FILTER_SETPASSALL(struct icmp6_filter *); + int ICMP6_FILTER_WILLBLOCK(int, + const struct icmp6_filter *); + int ICMP6_FILTER_WILLPASS(int, + const struct icmp6_filter *); + + int IN6_ARE_ADDR_EQUAL(const struct in6_addr *, + const struct in6_addr *); + + int inet6_opt_append(void *, size_t, int, + uint8_t, size_t, uint_8, void **); + int inet6_opt_get_val(void *, size_t, void *, int); + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 48] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + int inet6_opt_find(void *, size_t, int, uint8_t , + size_t *, void **); + int inet6_opt_finish(void *, size_t, int); + int inet6_opt_init(void *, size_t); + int inet6_opt_next(void *, size_t, int, uint8_t *, + size_t *, void **); + int inet6_opt_set_val(void *, size_t, void *, int); + + int inet6_rth_add(void *, + const struct in6_addr *); + struct in6_addr inet6_rth_getaddr(const void *, + int); + void *inet6_rth_init(void *, int, int, int); + int inet6_rth_reverse(const void *, void *); + int inet6_rth_segments(const void *); + size_t inet6_rth_space(int, int); + + unsigned char *CMSG_DATA(const struct cmsghdr *); + struct cmsghdr *CMSG_FIRSTHDR(const struct msghdr *); + unsigned int CMSG_LEN(unsigned int); + struct cmsghdr *CMSG_NXTHDR(const struct msghdr *mhdr, + const struct cmsghdr *); + unsigned int CMSG_SPACE(unsigned int); + + int rresvport_af(int *, int); + int rcmd_af(char **, unsigned short, const char *, + const char *, const char *, int *, int); + int rexec_af(char **, unsigned short , const char *, + const char *, const char *, int *, int); + + + +16. 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. + + The ability to specify an arbitrary source address using IPV6_PKTINFO + must be prevented; at least for non-privileged processes. + + +17. Change History + + Changes from RFC 2292: + + - Removed the IPV6_PKTOPTIONS socket option by allowing sticky + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 49] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + options to be set with individual setsockopt calls. This + simplifies the protocol stack implementation by not having to + handle options within options and also clarifies the failure + semantics when some option is incorrectly formatted. + + - Added the IPV6_RTHDRDSTOPTS for a Destination header before the + Routing header. This is necessary to allow setting these + Destination headers without IPV6_PKTOPTIONS. + + - Removed the ability to be able to specify Hop-by-Hop and + Destination options using multiple ancillary data items. The + application, using the inet6_option_*() routines, is responsible + for formatting the whole extension header. This removes the need + for the protocol stack to somehow guess the alignment + restrictions on options when concatenating them together. + + - Added separate IPV6_RECVxxx options to enable the receipt of the + corresponding ancillary data items. This makes the API cleaner + since it allows the application to retrieve with getsockopt the + sticky options it has set with setsockopt. + + - Clarified how sticky options are turned off. + + - Clarified how and when TCP returns ancillary data. + + - Removed the support for the loose/strict Routing header since + that has been removed from the IPv6 specification. + + - Modified the inet6_rthdr_XXX() functions to not assume a cmsghdr + structure in order to work with both sticky options and ancillary + data. Renamed the functions to inet6_rth_XXX() to allow + implementations to provide both the old and new functions. + + - Modified the inet6_option_XXX() functions to not assume a cmsghdr + structure in order to work with both sticky options and ancillary + data. Renamed the functions to inet6_opt_XXX() to allow + implementations to provide both the old and new functions. + + - The new inet6_opt_XXX() functions were made different that the + old as to not require structure declarations but instead use + functions to add the individual fields to the option. + + - Changed inet6_rthdr_getaddr() to operate on index O through N-1 + (used to be 1 through N). + + - Changed the comments in the struct ip6_hdr from "priority" to + "traffic class". + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 50] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + - Clarified the alignment issues involving ancillary data to allow + for separate alignment of cmsghdr structures and the data. Made + CMSG_SPACE() return an upper bound on the needed space. + + - Added rcmd_af() and rexec_af(). + + Changes since -00: + + - Changed ICMP unreachable code 2 name to be "beyond scope of + source address". + + - Added motivation for rcmd_af() and rexec_af(). + + - Added option definitions (IP6OPT_PAD1 etc) to ip6.h. + + - Added MLD and router renumbering definitions to icmp6.h + + - Removed ip6r0_addr field - replaced by a comment. + + - Made the content of IPV6_RTHDR, IPV6_HOPOPTS etc be specified as + the extension header format (struct ip6_rthdr etc) instead of the + previous "implementation dependent". + + - Removed attempt at RFC 2292 compatibility. + + - Excluded pad options from inet6_opt_next(). + + - Added IPV6_USE_MIN_MTU socket option for applications to avoid + fragmentation by sending at the minimum IPv6 MTU. + + - Added MTU notification so that UDP and raw socket applications + can participate in path MTU discovery. + + - Added Reachability confirmation for UDP and raw socket + applications. + + - Clarified that if the application asks for e.g., IPV6_RTHDR and a + received datagram does not contain a Routing header an + implementation will exclude the IPV6_RTHDR ancillary data item. + + - Removed the constraints for jumbo option. + + - Moved the new CMSG macros and changes from the appendix. + + - Add text about inet6_opt_ depending on 2260 appendix B formatting + rules i.e. largest field last in the option. + + - Specified that getsockopt() of a sticky option returns what was + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 51] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + set with setsockopt(). + + +18. TODO and Open Issues + + Items left to do: + + - Add credits for UDP MTU stuff + + - Move information about mapping from inet6_opt to setsockopt and + cmsg. + + - Clarify IPV6_RTHDRDSTOPTS's interaction with IPV6_RTHDR. + + - Make the new inet6_opt_set_val() and inet6_opt_get_val() check + the length of the data item. + + Open issues: + + - Anything special for mobility options? Restrict setting at API? + Filter out on receipt? If received what does the home address + option contain? + + - Specify "change" for TCP especially when there are multiple HBH + option headers etc. + + - Specify binding to scope-id => implies filtering of addresses + with that scope if the address you are bound to is link-local + etc. What about conflicts with bound scope-id and sendto/connect + scope-id? + + - Specify order for ifindex selection. Put in separate section. + Different cases for sending to link-local (scope_id including + nexthop scope_id) and global. Is multicast different? + + - bind() and sin6_scope_id. Should have been in Basic API. Error + checks when bind/sendto sin6_scope_id does not match? + + - Specify notion of default multicast interface? In Basic API? + + - What about site names and site ids? Need for interfaces to map? + Requires that site-prefixes pass name - does name need to use DNS + format to handle character sets? + + +19. References + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 52] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + [RFC-2460] Deering, S., Hinden, R., "Internet Protocol, Version 6 + (IPv6), Specification", RFC 2460, Dec. 1998. + + [RFC-2553] Gilligan, R. E., Thomson, S., Bound, J., Stevens, W., + "Basic Socket Interface Extensions for IPv6", RFC 2553, + March 1999. + + [RFC-1981] McCann, J., Deering, S., Mogul, J, "Path MTU Discovery + for IP version 6", RFC 1981, Aug. 1996. + + [RFC-2461] Narten, T., Nordmark, E., Simpson, W., "Neighbor + Discovery for IP Version 6 (IPv6)", RFC 2461, Dec. 1998. + + +20. 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, Jim Bound, + Don Coolidge, Matt Crawford, Sam T. Denton, Richard Draves, Francis + Dupont, Bob Gilligan, Jun-ichiro Hagino, Gerri Harter, Tim Hartrick, + Bob Halley, Masaki Hirabaru, Yoshinobu Inoue, Mukesh Kacker, A. N. + Kuznetsov, Sam Manthorpe, Pedro Marques, Jack McCann, der Mouse, John + Moy, Thomas Narten, Steve Parker, Charles Perkins, Ken Powell, Tom + Pusateri, Pedro Roque, Sameer Shah, Peter Sjodin, Stephen P. + Spackman, Jinmei Tatuya, Karen Tracey, Sowmini Varadhan, Quaizar + Vohra, Carl Williams, Steve Wise, Eric Wong, Farrell Woods, Kazu + Yamamoto, and Vlad Yasevich. + + +21. Authors' Addresses + + W. Richard Stevens + 1202 E. Paseo del Zorro + Tucson, AZ 85718 + Email: rstevens@kohala.com + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 53] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + Matt Thomas + 3am Software Foundry + 8053 Park Villa Circle + Cupertino, CA 95014 + Email: matt@3am-software.com + + + Erik Nordmark + Sun Microsystems, Inc. + 901 San Antonio Road + Palo Alto, CA 94303, USA + Email: erik.nordmark@eng.sun.com + + + +22. Appendix A: Ancillary Data Overview + + 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. + + + +22.1. The msghdr Structure + + The msghdr structure is used by the recvmsg() and sendmsg() + functions. Its Posix.1g definition is: + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 54] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + 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 . + + (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.) + + (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.) + + 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 Routing header is 2048 bytes.) + + +22.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[]; */ + }; + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 55] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + This structure is declared as a result of including . + + 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 in Section 22.3. Nevertheless, it is + common to refer to the cmsg_data[] member. + + 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 -------------------------->| + | OR | + |<--------------------------- msg_controllen ----------------------->| + | | + |<----- ancillary data object ----->|<----- ancillary data object ----->| + |<------ min CMSG_SPACE() --------->|<------ min 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. While sending an + application may or may not include padding at the end of last + ancillary data in msg_controllen and implementations must accept both + as valid. On receiving a portable application must provide space for + padding at the end of the last ancillary data as implementations may + copy out the padding at the end of the control message buffer and + include it in the received msg_controllen. When recvmsg() is called + if msg_controllen is too small for all the ancillary data items + including any trailing padding after the last item an implementation + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 56] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + may set MSG_CTRUNC. + + +22.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; + + /* 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 . + + +22.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 by the 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 + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 57] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + #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.) + + +22.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: + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 58] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + 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_H((cmsg)->cmsg_len) \ + + ALIGN_D(sizeof(struct cmsghdr)) > \ + (u_char *)((mhdr)->msg_control) + (mhdr)->msg_controllen) ? \ + (struct cmsghdr *)NULL : \ + (struct cmsghdr *)((u_char *)(cmsg) + ALIGN_H((cmsg)->cmsg_len)))) + + The macros ALIGN_H() and ALIGN_D(), which are implementation + dependent, round their arguments up to the next even multiple of + whatever alignment is required for the start of the cmsghdr structure + and the data, respectively. (This is probably a multiple of 4 or 8 + bytes.) They are often the same macro in implementations platforms + where alignment requirement for header and data is chosen to be + identical. + + +22.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: + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 59] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + #define CMSG_DATA(cmsg) ( (u_char *)(cmsg) + \ + ALIGN_D(sizeof(struct cmsghdr)) ) + + + +22.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 an upper bound on 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, when allocating 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_D(sizeof(struct cmsghdr)) + \ + ALIGN_H(length) ) + + + +22.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_D(sizeof(struct cmsghdr)) + length ) + + 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 + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 60] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + object. + + +23. Appendix B: Examples using the inet6_rth_XXX() functions + + Here we show an example for both sending Routing headers and + processing and reversing a received Routing header. + + +23.1. Sending a Routing Header + + As an example of these Routing header functions defined in this + document, we go through the function calls for the example on p. 17 + of [RFC-2460]. The source is S, the destination is D, and the three + intermediate nodes are I1, I2, and I3. + + 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 + + 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. + + The six values in the column beneath node S are the values in the + Routing header specified by the sending application using sendmsg() + of setsockopt(). The function calls by the sender would look like: + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 61] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + void *extptr; + int extlen; + struct msghdr msg; + struct cmsghdr *cmsgptr; + int cmsglen; + struct sockaddr_in6 I1, I2, I3, D; + + extlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, 3); + cmsglen = CMSG_SPACE(extlen); + cmsgptr = malloc(cmsglen); + cmsgptr->cmsg_len = CMSG_LEN(extlen); + cmsgptr->cmsg_level = IPPROTO_IPV6; + cmsgptr->cmsg_type = IPV6_RTHDR; + + optptr = CMSG_DATA(cmsgptr); + optptr = inet6_rth_init(optptr, optlen, IPV6_RTHDR_TYPE_0, 3); + + inet6_rth_add(optptr, &I1.sin6_addr); + inet6_rth_add(optptr, &I2.sin6_addr); + inet6_rth_add(optptr, &I3.sin6_addr); + + msg.msg_control = cmsgptr; + msg.msg_controllen = cmsglen; + + /* 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]. + + 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_RECVPKTINFO and IPV6_RECVRTHDR 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). The number of segments in + the Routing header is known from the Hdr Ext Len field in the Routing + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 62] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + header (a value of 6, indicating 3 addresses). + + The return value from inet6_rth_segments() will be 3 and + inet6_rth_getaddr(0) will return I1, inet6_rth_getaddr(1) will return + I2, and inet6_rth_getaddr(2) will return I3, + + If the receiving application then calls inet6_rth_reverse(), the + order of the three addresses will become I3, I2, and I1. + + 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_rth_space(3) returns 68: 12 bytes for the + cmsghdr structure and 56 bytes for the Routing header (8 + 3*16). + + The call to inet6_rth_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=6 | Routing Type=0| Seg Left=0 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The first call to inet6_rth_add() adds I1 to the list. + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 63] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_len = 36 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_level = IPPROTO_IPV6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_type = IPV6_RTHDR | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len=6 | Routing Type=0| Seg Left=1 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[1] = I1 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + cmsg_len is incremented by 16, and the Segments Left field is + incremented by 1. + + The next call to inet6_rth_add() adds I2 to the list. + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 64] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_len = 52 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_level = IPPROTO_IPV6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_type = IPV6_RTHDR | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len=6 | Routing Type=0| Seg Left=2 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[1] = I1 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[2] = I2 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + cmsg_len is incremented by 16, and the Segments Left field is + incremented by 1. + + The last call to inet6_rth_add() adds I3 to the list. + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 65] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_len = 68 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_level = IPPROTO_IPV6 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | cmsg_type = IPV6_RTHDR | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Next Header | Hdr Ext Len=6 | Routing Type=0| Seg Left=3 | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Reserved | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[1] = I1 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[2] = I2 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + + + + | | + + Address[3] = I3 + + | | + + + + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + cmsg_len is incremented by 16, and the Segments Left field is + incremented by 1. + + +23.2. Receiving Routing Headers + + This example assumes that the application has enabled IPV6_RECVRTHDR + socket option. The application prints and reverses a source route + and uses that to echo the received data. + + struct sockaddr_in6 addr; + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 66] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsgptr; + size_t cmsgspace; + void *optptr; + int optlen; + + int segments; + int i; + char databuf[8192]; + + segments = 100; /* Enough */ + optlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, segments); + cmsgspace = CMSG_SPACE(optlen); + cmsgptr = malloc(cmsgspace); + if (cmsgptr == NULL) { + perror("malloc"); + exit(1); + } + optptr = CMSG_DATA(cmsgptr); + + msg.msg_control = (char *)cmsgptr; + msg.msg_controllen = cmsgspace; + msg.msg_name = (struct sockaddr *)&addr; + msg.msg_namelen = sizeof (addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + iov.iov_base = databuf; + iov.iov_len = sizeof (databuf); + msg.msg_flags = 0; + if (recvmsg(s, &msg, 0) == -1) { + perror("recvmsg"); + return; + } + if (msg.msg_controllen != 0 && + cmsgptr->cmsg_level == IPPROTO_IPV6 && + cmsgptr->cmsg_type == IPV6_RTHDR) { + struct in6_addr *in6; + char asciiname[INET6_ADDRSTRLEN]; + struct ip6_rthdr0 *rthdr; + + rthdr = (struct ip6_rthdr0 *)optptr; + segments = inet6_rth_segments(optptr); + printf("route (%d segments, %d left): ", + segments, rthdr->ip6r0_segleft); + for (i = 0; i < segments; i++) { + in6 = inet6_rth_getaddr(optptr, i); + if (in6 == NULL) + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 67] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + printf(" "); + else + printf("%s ", inet_ntop(AF_INET6, + (void *)in6->s6_addr, + asciiname, INET6_ADDRSTRLEN)); + } + if (inet6_rth_reverse(optptr, optptr) == -1) { + printf("reverse failed"); + return; + } + } + iov.iov_base = databuf; + iov.iov_len = strlen(databuf); + if (sendmsg(s, &msg, 0) == -1) + perror("sendmsg"); + if (cmsgptr != NULL) + free(cmsgptr); + + Note: The above example is a simple illustration. It skips some + error checks involving the MSG_TRUNC and MSG_CTRUNC flags. + + +24. Appendix C: Examples using the inet6_opt_XXX() functions + + This shows how Hop-by-Hop and Destination options can be both built + as well as parsed using the inet6_opt_XXX() functions. This examples + assume that there are defined values for OPT_X and OPT_Y. + + +24.1. Building options + + We now provide an example that builds two Hop-by-Hop options using + the example in Appendix B of [RFC-2460]. + + void *extbuf; + size_t extlen; + int currentlen; + void *databuf; + size_t offset; + uint8_t value1; + uint16_t value2; + uint32_t value4; + uint64_t value8; + + /* Estimate the length */ + currentlen = inet6_opt_init(NULL, 0); + if (currentlen == -1) + return (-1); + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 68] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + currentlen = inet6_opt_append(NULL, 0, currentlen, OPT_X, 12, 8, NULL); + if (currentlen == -1) + return (-1); + currentlen = inet6_opt_append(NULL, 0, currentlen, OPT_Y, 7, 4, NULL); + if (currentlen == -1) + return (-1); + currentlen = inet6_opt_finish(NULL, 0, currentlen); + if (currentlen == -1) + return (-1); + extlen = currentlen; + + extbuf = malloc(extlen); + if (extbuf == NULL) { + perror("malloc"); + return (-1); + } + currentlen = inet6_opt_init(extbuf, extlen); + if (currentlen == -1) + return (-1); + + currentlen = inet6_opt_append(extbuf, extlen, currentlen, + OPT_X, 12, 8, &databuf); + if (currentlen == -1) + return (-1); + /* Insert value 0x12345678 for 4-octet field */ + offset = 0; + value4 = 0x12345678; + offset = inet6_opt_set_val(databuf, offset, &value4, sizeof (value4)); + /* Insert value 0x0102030405060708 for 8-octet field */ + value8 = 0x0102030405060708; + offset = inet6_opt_set_val(databuf, offset, &value8, sizeof (value8)); + + currentlen = inet6_opt_append(extbuf, extlen, currentlen, + OPT_Y, 7, 4, &databuf); + if (currentlen == -1) + return (-1); + /* Insert value 0x01 for 1-octet field */ + offset = 0; + value1 = 0x01; + offset = inet6_opt_set_val(databuf, offset, &value1, sizeof (value1)); + /* Insert value 0x1331 for 2-octet field */ + value2 = 0x1331; + offset = inet6_opt_set_val(databuf, offset, &value2, sizeof (value2)); + /* Insert value 0x01020304 for 4-octet field */ + value4 = 0x01020304; + offset = inet6_opt_set_val(databuf, offset, &value4, sizeof (value4)); + + currentlen = inet6_opt_finish(extbuf, extlen, currentlen); + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 69] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + if (currentlen == -1) + return (-1); + /* extbuf and extlen are now completely formatted */ + + + +24.2. Parsing received options + + This example parses and prints the content of the two options in the + previous example. + + int + print_opt(void *extbuf, size_t extlen) + { + ip6_dest_t *ext; + int currentlen; + uint8_t type; + size_t len; + void *databuf; + size_t offset; + uint8_t value1; + uint16_t value2; + uint32_t value4; + uint64_t value8; + + ext = (ip6_dest_t *)extbuf; + printf("nxt %u, len %u (bytes %d)\n", ext->ip6d_nxt, + ext->ip6d_len, (ext->ip6d_len + 1) * 8); + + currentlen = 0; + while (1) { + currentlen = inet6_opt_next(extbuf, extlen, currentlen, + &type, &len, &databuf); + if (currentlen == -1) + break; + printf("Received opt %u len %u\n", + type, len); + switch (type) { + case OPT_X: + offset = 0; + offset = inet6_opt_get_val(databuf, offset, + &value4, sizeof (value4)); + printf("X 4-byte field %x\n", value4); + offset = inet6_opt_get_val(databuf, offset, + &value8, sizeof (value8)); + printf("X 8-byte field %llx\n", value8); + break; + case OPT_Y: + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 70] + + +INTERNET-DRAFT Advanced Sockets API for IPv6 Oct 22, 1999 + + + offset = 0; + offset = inet6_opt_get_val(databuf, offset, + &value1, sizeof (value1)); + printf("Y 1-byte field %x\n", value1); + offset = inet6_opt_get_val(databuf, offset, + &value2, sizeof (value2)); + printf("Y 2-byte field %x\n", value2); + offset = inet6_opt_get_val(databuf, offset, + &value4, sizeof (value4)); + printf("Y 4-byte field %x\n", value4); + break; + default: + printf("Unknown option %u\n", type); + break; + } + } + return (0); + } + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +draft-ietf-ipngwg-2292bis-01.txt [Page 71] + +